1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/webui/ntp/ntp_resource_cache.h"
6
7#include <string>
8#include <vector>
9
10#include "base/command_line.h"
11#include "base/memory/ref_counted_memory.h"
12#include "base/prefs/pref_service.h"
13#include "base/strings/string16.h"
14#include "base/strings/string_number_conversions.h"
15#include "base/strings/stringprintf.h"
16#include "base/strings/utf_string_conversions.h"
17#include "base/values.h"
18#include "chrome/browser/browser_process.h"
19#include "chrome/browser/chrome_notification_types.h"
20#include "chrome/browser/extensions/extension_util.h"
21#include "chrome/browser/first_run/first_run.h"
22#include "chrome/browser/profiles/profile.h"
23#include "chrome/browser/search/search.h"
24#include "chrome/browser/sync/profile_sync_service.h"
25#include "chrome/browser/sync/profile_sync_service_factory.h"
26#include "chrome/browser/themes/theme_properties.h"
27#include "chrome/browser/themes/theme_service.h"
28#include "chrome/browser/themes/theme_service_factory.h"
29#include "chrome/browser/ui/app_list/app_list_util.h"
30#include "chrome/browser/ui/bookmarks/bookmark_bar_constants.h"
31#include "chrome/browser/ui/sync/sync_promo_ui.h"
32#include "chrome/browser/ui/webui/ntp/new_tab_page_handler.h"
33#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
34#include "chrome/browser/ui/webui/ntp/ntp_login_handler.h"
35#include "chrome/browser/ui/webui/sync_setup_handler.h"
36#include "chrome/browser/web_resource/notification_promo.h"
37#include "chrome/common/chrome_switches.h"
38#include "chrome/common/pref_names.h"
39#include "chrome/common/url_constants.h"
40#include "chrome/grit/chromium_strings.h"
41#include "chrome/grit/generated_resources.h"
42#include "chrome/grit/locale_settings.h"
43#include "components/google/core/browser/google_util.h"
44#include "content/public/browser/browser_thread.h"
45#include "content/public/browser/notification_service.h"
46#include "content/public/browser/render_process_host.h"
47#include "extensions/common/extension.h"
48#include "extensions/common/extension_urls.h"
49#include "grit/browser_resources.h"
50#include "grit/components_strings.h"
51#include "grit/theme_resources.h"
52#include "ui/base/l10n/l10n_util.h"
53#include "ui/base/resource/resource_bundle.h"
54#include "ui/base/theme_provider.h"
55#include "ui/base/webui/jstemplate_builder.h"
56#include "ui/base/webui/web_ui_util.h"
57#include "ui/gfx/animation/animation.h"
58#include "ui/gfx/color_utils.h"
59#include "ui/gfx/sys_color_change_listener.h"
60
61#if defined(OS_CHROMEOS)
62#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
63#include "chromeos/chromeos_switches.h"
64#endif
65
66#if defined(OS_MACOSX)
67#include "chrome/browser/platform_util.h"
68#endif
69
70using content::BrowserThread;
71
72namespace {
73
74// The URL for the the Learn More page shown on incognito new tab.
75const char kLearnMoreIncognitoUrl[] =
76#if defined(OS_CHROMEOS)
77    "https://www.google.com/support/chromeos/bin/answer.py?answer=95464";
78#else
79    "https://www.google.com/support/chrome/bin/answer.py?answer=95464";
80#endif
81
82// The URL for the Learn More page shown on guest session new tab.
83const char kLearnMoreGuestSessionUrl[] =
84    "https://www.google.com/support/chromeos/bin/answer.py?answer=1057090";
85
86std::string SkColorToRGBAString(SkColor color) {
87  // We convert the alpha using DoubleToString because StringPrintf will use
88  // locale specific formatters (e.g., use , instead of . in German).
89  return base::StringPrintf(
90      "rgba(%d,%d,%d,%s)",
91      SkColorGetR(color),
92      SkColorGetG(color),
93      SkColorGetB(color),
94      base::DoubleToString(SkColorGetA(color) / 255.0).c_str());
95}
96
97// Creates an rgb string for an SkColor, but leaves the alpha blank so that the
98// css can fill it in.
99std::string SkColorToRGBComponents(SkColor color) {
100  return base::StringPrintf(
101      "%d,%d,%d",
102      SkColorGetR(color),
103      SkColorGetG(color),
104      SkColorGetB(color));
105}
106
107SkColor GetThemeColor(ui::ThemeProvider* tp, int id) {
108  SkColor color = tp->GetColor(id);
109  // If web contents are being inverted because the system is in high-contrast
110  // mode, any system theme colors we use must be inverted too to cancel out.
111  return gfx::IsInvertedColorScheme() ?
112      color_utils::InvertColor(color) : color;
113}
114
115// Get the CSS string for the background position on the new tab page for the
116// states when the bar is attached or detached.
117std::string GetNewTabBackgroundCSS(const ui::ThemeProvider* theme_provider,
118                                   bool bar_attached) {
119  // TODO(glen): This is a quick workaround to hide the notused.png image when
120  // no image is provided - we don't have time right now to figure out why
121  // this is painting as white.
122  // http://crbug.com/17593
123  if (!theme_provider->HasCustomImage(IDR_THEME_NTP_BACKGROUND)) {
124    return "-64px";
125  }
126
127  int alignment = theme_provider->GetDisplayProperty(
128      ThemeProperties::NTP_BACKGROUND_ALIGNMENT);
129
130  if (bar_attached)
131    return ThemeProperties::AlignmentToString(alignment);
132
133  if (alignment & ThemeProperties::ALIGN_TOP) {
134    // The bar is detached, so we must offset the background by the bar size
135    // if it's a top-aligned bar.
136    int offset = chrome::kNTPBookmarkBarHeight;
137
138    if (alignment & ThemeProperties::ALIGN_LEFT)
139      return "left " + base::IntToString(-offset) + "px";
140    else if (alignment & ThemeProperties::ALIGN_RIGHT)
141      return "right " + base::IntToString(-offset) + "px";
142    return "center " + base::IntToString(-offset) + "px";
143  }
144
145  return ThemeProperties::AlignmentToString(alignment);
146}
147
148// How the background image on the new tab page should be tiled (see tiling
149// masks in theme_service.h).
150std::string GetNewTabBackgroundTilingCSS(
151    const ui::ThemeProvider* theme_provider) {
152  int repeat_mode = theme_provider->GetDisplayProperty(
153      ThemeProperties::NTP_BACKGROUND_TILING);
154  return ThemeProperties::TilingToString(repeat_mode);
155}
156
157}  // namespace
158
159NTPResourceCache::NTPResourceCache(Profile* profile)
160    : profile_(profile), is_swipe_tracking_from_scroll_events_enabled_(false),
161      should_show_apps_page_(NewTabUI::ShouldShowApps()),
162      should_show_most_visited_page_(true),
163      should_show_other_devices_menu_(true),
164      should_show_recently_closed_menu_(true) {
165  registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
166                 content::Source<ThemeService>(
167                     ThemeServiceFactory::GetForProfile(profile)));
168  registrar_.Add(this, chrome::NOTIFICATION_PROMO_RESOURCE_STATE_CHANGED,
169                 content::NotificationService::AllSources());
170
171  base::Closure callback = base::Bind(&NTPResourceCache::OnPreferenceChanged,
172                                      base::Unretained(this));
173
174  // Watch for pref changes that cause us to need to invalidate the HTML cache.
175  profile_pref_change_registrar_.Init(profile_->GetPrefs());
176  profile_pref_change_registrar_.Add(bookmarks::prefs::kShowBookmarkBar,
177                                     callback);
178  profile_pref_change_registrar_.Add(prefs::kNtpShownPage, callback);
179  profile_pref_change_registrar_.Add(prefs::kSignInPromoShowNTPBubble,
180                                     callback);
181  profile_pref_change_registrar_.Add(prefs::kHideWebStoreIcon, callback);
182
183  // Some tests don't have a local state.
184#if defined(ENABLE_APP_LIST)
185  if (g_browser_process->local_state()) {
186    local_state_pref_change_registrar_.Init(g_browser_process->local_state());
187    local_state_pref_change_registrar_.Add(prefs::kShowAppLauncherPromo,
188                                           callback);
189    local_state_pref_change_registrar_.Add(
190        prefs::kAppLauncherHasBeenEnabled, callback);
191  }
192#endif
193}
194
195NTPResourceCache::~NTPResourceCache() {}
196
197bool NTPResourceCache::NewTabCacheNeedsRefresh() {
198#if defined(OS_MACOSX)
199  // Invalidate if the current value is different from the cached value.
200  bool is_enabled = platform_util::IsSwipeTrackingFromScrollEventsEnabled();
201  if (is_enabled != is_swipe_tracking_from_scroll_events_enabled_) {
202    is_swipe_tracking_from_scroll_events_enabled_ = is_enabled;
203    return true;
204  }
205#endif
206  bool should_show_apps_page = NewTabUI::ShouldShowApps();
207  if (should_show_apps_page != should_show_apps_page_) {
208    should_show_apps_page_ = should_show_apps_page;
209    return true;
210  }
211  return false;
212}
213
214NTPResourceCache::WindowType NTPResourceCache::GetWindowType(
215    Profile* profile, content::RenderProcessHost* render_host) {
216  if (profile->IsGuestSession()) {
217    return NTPResourceCache::GUEST;
218  } else if (render_host) {
219    // Sometimes the |profile| is the parent (non-incognito) version of the user
220    // so we check the |render_host| if it is provided.
221    if (render_host->GetBrowserContext()->IsOffTheRecord())
222      return NTPResourceCache::INCOGNITO;
223  } else if (profile->IsOffTheRecord()) {
224    return NTPResourceCache::INCOGNITO;
225  }
226  return NTPResourceCache::NORMAL;
227}
228
229base::RefCountedMemory* NTPResourceCache::GetNewTabHTML(WindowType win_type) {
230  DCHECK_CURRENTLY_ON(BrowserThread::UI);
231  if (win_type == GUEST) {
232    if (!new_tab_guest_html_.get())
233      CreateNewTabGuestHTML();
234    return new_tab_guest_html_.get();
235  } else if (win_type == INCOGNITO) {
236    if (!new_tab_incognito_html_.get())
237      CreateNewTabIncognitoHTML();
238    return new_tab_incognito_html_.get();
239  } else {
240    // Refresh the cached HTML if necessary.
241    // NOTE: NewTabCacheNeedsRefresh() must be called every time the new tab
242    // HTML is fetched, because it needs to initialize cached values.
243    if (NewTabCacheNeedsRefresh() || !new_tab_html_.get())
244      CreateNewTabHTML();
245    return new_tab_html_.get();
246  }
247}
248
249base::RefCountedMemory* NTPResourceCache::GetNewTabCSS(WindowType win_type) {
250  DCHECK_CURRENTLY_ON(BrowserThread::UI);
251  if (win_type == GUEST) {
252    if (!new_tab_guest_css_.get())
253      CreateNewTabGuestCSS();
254    return new_tab_guest_css_.get();
255  } else if (win_type == INCOGNITO) {
256    if (!new_tab_incognito_css_.get())
257      CreateNewTabIncognitoCSS();
258    return new_tab_incognito_css_.get();
259  } else {
260    if (!new_tab_css_.get())
261      CreateNewTabCSS();
262    return new_tab_css_.get();
263  }
264}
265
266void NTPResourceCache::Observe(int type,
267                               const content::NotificationSource& source,
268                               const content::NotificationDetails& details) {
269  // Invalidate the cache.
270  if (chrome::NOTIFICATION_BROWSER_THEME_CHANGED == type ||
271      chrome::NOTIFICATION_PROMO_RESOURCE_STATE_CHANGED == type) {
272    new_tab_incognito_html_ = NULL;
273    new_tab_html_ = NULL;
274    new_tab_incognito_css_ = NULL;
275    new_tab_css_ = NULL;
276  } else {
277    NOTREACHED();
278  }
279}
280
281void NTPResourceCache::OnPreferenceChanged() {
282  // A change occurred to one of the preferences we care about, so flush the
283  // cache.
284  new_tab_incognito_html_ = NULL;
285  new_tab_html_ = NULL;
286  new_tab_css_ = NULL;
287}
288
289void NTPResourceCache::CreateNewTabIncognitoHTML() {
290  base::DictionaryValue localized_strings;
291  localized_strings.SetString("title",
292      l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE));
293  int new_tab_description_ids = IDS_NEW_TAB_OTR_DESCRIPTION;
294  int new_tab_heading_ids = IDS_NEW_TAB_OTR_HEADING;
295  int new_tab_link_ids = IDS_NEW_TAB_OTR_LEARN_MORE_LINK;
296  int new_tab_warning_ids = IDS_NEW_TAB_OTR_MESSAGE_WARNING;
297  int new_tab_html_idr = IDR_INCOGNITO_TAB_HTML;
298  const char* new_tab_link = kLearnMoreIncognitoUrl;
299
300  if (profile_->IsGuestSession()) {
301    localized_strings.SetString("guestTabDescription",
302        l10n_util::GetStringUTF16(new_tab_description_ids));
303    localized_strings.SetString("guestTabHeading",
304        l10n_util::GetStringUTF16(new_tab_heading_ids));
305  } else {
306    localized_strings.SetString("incognitoTabDescription",
307        l10n_util::GetStringUTF16(new_tab_description_ids));
308    localized_strings.SetString("incognitoTabHeading",
309        l10n_util::GetStringUTF16(new_tab_heading_ids));
310    localized_strings.SetString("incognitoTabWarning",
311        l10n_util::GetStringUTF16(new_tab_warning_ids));
312  }
313
314  localized_strings.SetString("learnMore",
315      l10n_util::GetStringUTF16(new_tab_link_ids));
316  localized_strings.SetString("learnMoreLink", new_tab_link);
317
318  bool bookmark_bar_attached =
319      profile_->GetPrefs()->GetBoolean(bookmarks::prefs::kShowBookmarkBar);
320  localized_strings.SetBoolean("bookmarkbarattached", bookmark_bar_attached);
321
322  webui::SetFontAndTextDirection(&localized_strings);
323
324  static const base::StringPiece incognito_tab_html(
325      ResourceBundle::GetSharedInstance().GetRawDataResource(
326          new_tab_html_idr));
327
328  std::string full_html = webui::GetI18nTemplateHtml(
329      incognito_tab_html, &localized_strings);
330
331  new_tab_incognito_html_ = base::RefCountedString::TakeString(&full_html);
332}
333
334void NTPResourceCache::CreateNewTabGuestHTML() {
335  base::DictionaryValue localized_strings;
336  localized_strings.SetString("title",
337      l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE));
338  const char* guest_tab_link = kLearnMoreGuestSessionUrl;
339  int guest_tab_ids = IDR_GUEST_TAB_HTML;
340  int guest_tab_description_ids = IDS_NEW_TAB_GUEST_SESSION_DESCRIPTION;
341  int guest_tab_heading_ids = IDS_NEW_TAB_GUEST_SESSION_HEADING;
342  int guest_tab_link_ids = IDS_NEW_TAB_GUEST_SESSION_LEARN_MORE_LINK;
343
344#if defined(OS_CHROMEOS)
345  guest_tab_ids = IDR_GUEST_SESSION_TAB_HTML;
346  guest_tab_link = kLearnMoreGuestSessionUrl;
347
348  policy::BrowserPolicyConnectorChromeOS* connector =
349      g_browser_process->platform_part()->browser_policy_connector_chromeos();
350  std::string enterprise_domain = connector->GetEnterpriseDomain();
351
352  if (!enterprise_domain.empty()) {
353    // Device is enterprise enrolled.
354    localized_strings.SetString("enterpriseInfoVisible", "true");
355    base::string16 enterprise_info = l10n_util::GetStringFUTF16(
356        IDS_DEVICE_OWNED_BY_NOTICE,
357        base::UTF8ToUTF16(enterprise_domain));
358    localized_strings.SetString("enterpriseInfoMessage", enterprise_info);
359    localized_strings.SetString("enterpriseLearnMore",
360        l10n_util::GetStringUTF16(IDS_LEARN_MORE));
361    localized_strings.SetString("enterpriseInfoHintLink",
362                                chrome::kLearnMoreEnterpriseURL);
363  } else {
364    localized_strings.SetString("enterpriseInfoVisible", "false");
365  }
366#endif
367
368  localized_strings.SetString("guestTabDescription",
369      l10n_util::GetStringUTF16(guest_tab_description_ids));
370  localized_strings.SetString("guestTabHeading",
371      l10n_util::GetStringUTF16(guest_tab_heading_ids));
372  localized_strings.SetString("learnMore",
373      l10n_util::GetStringUTF16(guest_tab_link_ids));
374  localized_strings.SetString("learnMoreLink", guest_tab_link);
375
376  webui::SetFontAndTextDirection(&localized_strings);
377
378  static const base::StringPiece guest_tab_html(
379      ResourceBundle::GetSharedInstance().GetRawDataResource(guest_tab_ids));
380
381  std::string full_html = webui::GetI18nTemplateHtml(
382      guest_tab_html, &localized_strings);
383
384  new_tab_guest_html_ = base::RefCountedString::TakeString(&full_html);
385}
386
387void NTPResourceCache::CreateNewTabHTML() {
388  // TODO(estade): these strings should be defined in their relevant handlers
389  // (in GetLocalizedValues) and should have more legible names.
390  // Show the profile name in the title and most visited labels if the current
391  // profile is not the default.
392  PrefService* prefs = profile_->GetPrefs();
393  base::DictionaryValue load_time_data;
394  load_time_data.SetBoolean("bookmarkbarattached",
395      prefs->GetBoolean(bookmarks::prefs::kShowBookmarkBar));
396  load_time_data.SetBoolean("hasattribution",
397      ThemeServiceFactory::GetForProfile(profile_)->HasCustomImage(
398          IDR_THEME_NTP_ATTRIBUTION));
399  load_time_data.SetBoolean("showMostvisited", should_show_most_visited_page_);
400  load_time_data.SetBoolean("showAppLauncherPromo",
401      ShouldShowAppLauncherPromo());
402  load_time_data.SetBoolean("showRecentlyClosed",
403      should_show_recently_closed_menu_);
404  load_time_data.SetString("title",
405      l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE));
406  load_time_data.SetString("mostvisited",
407      l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED));
408  load_time_data.SetString("suggestions",
409      l10n_util::GetStringUTF16(IDS_NEW_TAB_SUGGESTIONS));
410  load_time_data.SetString("restoreThumbnailsShort",
411      l10n_util::GetStringUTF16(IDS_NEW_TAB_RESTORE_THUMBNAILS_SHORT_LINK));
412  load_time_data.SetString("recentlyclosed",
413      l10n_util::GetStringUTF16(IDS_NEW_TAB_RECENTLY_CLOSED));
414  load_time_data.SetString("webStoreTitle",
415      l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE));
416  load_time_data.SetString("webStoreTitleShort",
417      l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE_SHORT));
418  load_time_data.SetString("closedwindowsingle",
419      l10n_util::GetStringUTF16(IDS_NEW_TAB_RECENTLY_CLOSED_WINDOW_SINGLE));
420  load_time_data.SetString("closedwindowmultiple",
421      l10n_util::GetStringUTF16(IDS_NEW_TAB_RECENTLY_CLOSED_WINDOW_MULTIPLE));
422  load_time_data.SetString("attributionintro",
423      l10n_util::GetStringUTF16(IDS_NEW_TAB_ATTRIBUTION_INTRO));
424  load_time_data.SetString("thumbnailremovednotification",
425      l10n_util::GetStringUTF16(IDS_NEW_TAB_THUMBNAIL_REMOVED_NOTIFICATION));
426  load_time_data.SetString("undothumbnailremove",
427      l10n_util::GetStringUTF16(IDS_NEW_TAB_UNDO_THUMBNAIL_REMOVE));
428  load_time_data.SetString("removethumbnailtooltip",
429      l10n_util::GetStringUTF16(IDS_NEW_TAB_REMOVE_THUMBNAIL_TOOLTIP));
430  load_time_data.SetString("appuninstall",
431      l10n_util::GetStringUTF16(IDS_EXTENSIONS_UNINSTALL));
432  load_time_data.SetString("appoptions",
433      l10n_util::GetStringUTF16(IDS_NEW_TAB_APP_OPTIONS));
434  load_time_data.SetString("appdetails",
435      l10n_util::GetStringUTF16(IDS_NEW_TAB_APP_DETAILS));
436  load_time_data.SetString("appcreateshortcut",
437      l10n_util::GetStringUTF16(IDS_NEW_TAB_APP_CREATE_SHORTCUT));
438  load_time_data.SetString("appDefaultPageName",
439      l10n_util::GetStringUTF16(IDS_APP_DEFAULT_PAGE_NAME));
440  load_time_data.SetString("applaunchtypepinned",
441      l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_PINNED));
442  load_time_data.SetString("applaunchtyperegular",
443      l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_REGULAR));
444  load_time_data.SetString("applaunchtypewindow",
445      l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_WINDOW));
446  load_time_data.SetString("applaunchtypefullscreen",
447      l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_FULLSCREEN));
448  load_time_data.SetString("syncpromotext",
449      l10n_util::GetStringUTF16(IDS_SYNC_START_SYNC_BUTTON_LABEL));
450  load_time_data.SetString("syncLinkText",
451      l10n_util::GetStringUTF16(IDS_SYNC_ADVANCED_OPTIONS));
452  load_time_data.SetBoolean("shouldShowSyncLogin",
453                            NTPLoginHandler::ShouldShow(profile_));
454  load_time_data.SetString("otherSessions",
455      l10n_util::GetStringUTF16(IDS_NEW_TAB_OTHER_SESSIONS_LABEL));
456  load_time_data.SetString("otherSessionsEmpty",
457      l10n_util::GetStringUTF16(IDS_NEW_TAB_OTHER_SESSIONS_EMPTY));
458  load_time_data.SetString("otherSessionsLearnMoreUrl",
459      l10n_util::GetStringUTF16(IDS_NEW_TAB_OTHER_SESSIONS_LEARN_MORE_URL));
460  load_time_data.SetString("learnMore",
461      l10n_util::GetStringUTF16(IDS_LEARN_MORE));
462  load_time_data.SetString("webStoreLink",
463      google_util::AppendGoogleLocaleParam(
464          GURL(extension_urls::GetWebstoreLaunchURL()),
465          g_browser_process->GetApplicationLocale()).spec());
466  load_time_data.SetString("appInstallHintText",
467      l10n_util::GetStringUTF16(IDS_NEW_TAB_APP_INSTALL_HINT_LABEL));
468  load_time_data.SetBoolean("isDiscoveryInNTPEnabled",
469      NewTabUI::IsDiscoveryInNTPEnabled());
470  load_time_data.SetString("collapseSessionMenuItemText",
471      l10n_util::GetStringUTF16(IDS_NEW_TAB_OTHER_SESSIONS_COLLAPSE_SESSION));
472  load_time_data.SetString("expandSessionMenuItemText",
473      l10n_util::GetStringUTF16(IDS_NEW_TAB_OTHER_SESSIONS_EXPAND_SESSION));
474  load_time_data.SetString("restoreSessionMenuItemText",
475      l10n_util::GetStringUTF16(IDS_NEW_TAB_OTHER_SESSIONS_OPEN_ALL));
476  load_time_data.SetString("learn_more",
477      l10n_util::GetStringUTF16(IDS_LEARN_MORE));
478  load_time_data.SetString("tile_grid_screenreader_accessible_description",
479      l10n_util::GetStringUTF16(IDS_NEW_TAB_TILE_GRID_ACCESSIBLE_DESCRIPTION));
480  load_time_data.SetString("page_switcher_change_title",
481      l10n_util::GetStringUTF16(IDS_NEW_TAB_PAGE_SWITCHER_CHANGE_TITLE));
482  load_time_data.SetString("page_switcher_same_title",
483      l10n_util::GetStringUTF16(IDS_NEW_TAB_PAGE_SWITCHER_SAME_TITLE));
484  load_time_data.SetString("appsPromoTitle",
485      l10n_util::GetStringUTF16(IDS_NEW_TAB_PAGE_APPS_PROMO_TITLE));
486  // On Mac OS X 10.7+, horizontal scrolling can be treated as a back or
487  // forward gesture. Pass through a flag that indicates whether or not that
488  // feature is enabled.
489  load_time_data.SetBoolean("isSwipeTrackingFromScrollEventsEnabled",
490                            is_swipe_tracking_from_scroll_events_enabled_);
491
492  load_time_data.SetBoolean("showApps", should_show_apps_page_);
493  load_time_data.SetBoolean("showWebStoreIcon",
494                            !prefs->GetBoolean(prefs::kHideWebStoreIcon));
495
496  bool streamlined_hosted_apps =
497      extensions::util::IsStreamlinedHostedAppsEnabled();
498  load_time_data.SetBoolean("enableStreamlinedHostedApps",
499                            streamlined_hosted_apps);
500  // Use a different string for launching as a regular tab for streamlined
501  // hosted apps.
502  if (streamlined_hosted_apps) {
503    load_time_data.SetString("applaunchtypetab",
504        l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_TAB));
505  }
506
507#if defined(OS_CHROMEOS)
508  load_time_data.SetString("expandMenu",
509      l10n_util::GetStringUTF16(IDS_NEW_TAB_CLOSE_MENU_EXPAND));
510#endif
511
512  NewTabPageHandler::GetLocalizedValues(profile_, &load_time_data);
513  NTPLoginHandler::GetLocalizedValues(profile_, &load_time_data);
514
515  webui::SetFontAndTextDirection(&load_time_data);
516
517  // Control fade and resize animations.
518  load_time_data.SetBoolean("anim",
519                            gfx::Animation::ShouldRenderRichAnimation());
520
521  ui::ThemeProvider* tp = ThemeServiceFactory::GetForProfile(profile_);
522  int alignment = tp->GetDisplayProperty(
523      ThemeProperties::NTP_BACKGROUND_ALIGNMENT);
524  load_time_data.SetString("themegravity",
525      (alignment & ThemeProperties::ALIGN_RIGHT) ? "right" : "");
526
527  // Disable the promo if this is the first run, otherwise set the promo string
528  // for display if there is a valid outstanding promo.
529  if (first_run::IsChromeFirstRun()) {
530    NotificationPromo::HandleClosed(NotificationPromo::NTP_NOTIFICATION_PROMO);
531  } else {
532    NotificationPromo notification_promo;
533    notification_promo.InitFromPrefs(NotificationPromo::NTP_NOTIFICATION_PROMO);
534    if (notification_promo.CanShow()) {
535      load_time_data.SetString("notificationPromoText",
536                               notification_promo.promo_text());
537      DVLOG(1) << "Notification promo:" << notification_promo.promo_text();
538    }
539
540    NotificationPromo bubble_promo;
541    bubble_promo.InitFromPrefs(NotificationPromo::NTP_BUBBLE_PROMO);
542    if (bubble_promo.CanShow()) {
543      load_time_data.SetString("bubblePromoText",
544                               bubble_promo.promo_text());
545      DVLOG(1) << "Bubble promo:" << bubble_promo.promo_text();
546    }
547  }
548
549  // Determine whether to show the menu for accessing tabs on other devices.
550  bool show_other_sessions_menu = should_show_other_devices_menu_ &&
551      !CommandLine::ForCurrentProcess()->HasSwitch(
552          switches::kDisableNTPOtherSessionsMenu);
553  load_time_data.SetBoolean("showOtherSessionsMenu", show_other_sessions_menu);
554  load_time_data.SetBoolean("isUserSignedIn",
555      !prefs->GetString(prefs::kGoogleServicesUsername).empty());
556
557  // Load the new tab page appropriate for this build.
558  base::StringPiece new_tab_html(ResourceBundle::GetSharedInstance().
559      GetRawDataResource(IDR_NEW_TAB_4_HTML));
560  webui::UseVersion2 version2;
561  std::string full_html =
562      webui::GetI18nTemplateHtml(new_tab_html, &load_time_data);
563  new_tab_html_ = base::RefCountedString::TakeString(&full_html);
564}
565
566void NTPResourceCache::CreateNewTabIncognitoCSS() {
567  ui::ThemeProvider* tp = ThemeServiceFactory::GetForProfile(profile_);
568  DCHECK(tp);
569
570  // Get our theme colors
571  SkColor color_background =
572      GetThemeColor(tp, ThemeProperties::COLOR_NTP_BACKGROUND);
573
574  // Generate the replacements.
575  std::vector<std::string> subst;
576
577  // Cache-buster for background.
578  subst.push_back(
579      profile_->GetPrefs()->GetString(prefs::kCurrentThemeID));  // $1
580
581  // Colors.
582  subst.push_back(SkColorToRGBAString(color_background));  // $2
583  subst.push_back(GetNewTabBackgroundCSS(tp, false));  // $3
584  subst.push_back(GetNewTabBackgroundCSS(tp, true));  // $4
585  subst.push_back(GetNewTabBackgroundTilingCSS(tp));  // $5
586
587  // Get our template.
588  static const base::StringPiece new_tab_theme_css(
589      ResourceBundle::GetSharedInstance().GetRawDataResource(
590          IDR_NEW_INCOGNITO_TAB_THEME_CSS));
591
592  // Create the string from our template and the replacements.
593  std::string full_css = ReplaceStringPlaceholders(
594      new_tab_theme_css, subst, NULL);
595
596  new_tab_incognito_css_ = base::RefCountedString::TakeString(&full_css);
597}
598
599void NTPResourceCache::CreateNewTabGuestCSS() {
600  ui::ThemeProvider* tp = ThemeServiceFactory::GetForProfile(profile_);
601  DCHECK(tp);
602
603  // Get our theme colors
604  SkColor color_background =
605      GetThemeColor(tp, ThemeProperties::COLOR_NTP_BACKGROUND);
606
607  // Generate the replacements.
608  std::vector<std::string> subst;
609
610  // Cache-buster for background.
611  subst.push_back(
612      profile_->GetPrefs()->GetString(prefs::kCurrentThemeID));  // $1
613
614  // Colors.
615  subst.push_back(SkColorToRGBAString(color_background));  // $2
616  subst.push_back(GetNewTabBackgroundCSS(tp, false));  // $3
617  subst.push_back(GetNewTabBackgroundCSS(tp, true));  // $4
618  subst.push_back(GetNewTabBackgroundTilingCSS(tp));  // $5
619
620  // Get our template.
621  static const base::StringPiece new_tab_theme_css(
622      ResourceBundle::GetSharedInstance().GetRawDataResource(
623          IDR_NEW_GUEST_TAB_THEME_CSS));
624
625  // Create the string from our template and the replacements.
626  std::string full_css = ReplaceStringPlaceholders(
627      new_tab_theme_css, subst, NULL);
628
629  new_tab_guest_css_ = base::RefCountedString::TakeString(&full_css);
630}
631
632void NTPResourceCache::CreateNewTabCSS() {
633  ui::ThemeProvider* tp = ThemeServiceFactory::GetForProfile(profile_);
634  DCHECK(tp);
635
636  // Get our theme colors
637  SkColor color_background =
638      GetThemeColor(tp, ThemeProperties::COLOR_NTP_BACKGROUND);
639  SkColor color_text = GetThemeColor(tp, ThemeProperties::COLOR_NTP_TEXT);
640  SkColor color_link = GetThemeColor(tp, ThemeProperties::COLOR_NTP_LINK);
641  SkColor color_link_underline =
642      GetThemeColor(tp, ThemeProperties::COLOR_NTP_LINK_UNDERLINE);
643
644  SkColor color_section =
645      GetThemeColor(tp, ThemeProperties::COLOR_NTP_SECTION);
646  SkColor color_section_text =
647      GetThemeColor(tp, ThemeProperties::COLOR_NTP_SECTION_TEXT);
648  SkColor color_section_link =
649      GetThemeColor(tp, ThemeProperties::COLOR_NTP_SECTION_LINK);
650  SkColor color_section_link_underline =
651      GetThemeColor(tp, ThemeProperties::COLOR_NTP_SECTION_LINK_UNDERLINE);
652  SkColor color_section_header_text =
653      GetThemeColor(tp, ThemeProperties::COLOR_NTP_SECTION_HEADER_TEXT);
654  SkColor color_section_header_text_hover =
655      GetThemeColor(tp, ThemeProperties::COLOR_NTP_SECTION_HEADER_TEXT_HOVER);
656  SkColor color_section_header_rule =
657      GetThemeColor(tp, ThemeProperties::COLOR_NTP_SECTION_HEADER_RULE);
658  SkColor color_section_header_rule_light =
659      GetThemeColor(tp, ThemeProperties::COLOR_NTP_SECTION_HEADER_RULE_LIGHT);
660  SkColor color_text_light =
661      GetThemeColor(tp, ThemeProperties::COLOR_NTP_TEXT_LIGHT);
662
663  SkColor color_header =
664      GetThemeColor(tp, ThemeProperties::COLOR_NTP_HEADER);
665  // Generate a lighter color for the header gradients.
666  color_utils::HSL header_lighter;
667  color_utils::SkColorToHSL(color_header, &header_lighter);
668  header_lighter.l += (1 - header_lighter.l) * 0.33;
669  SkColor color_header_gradient_light =
670      color_utils::HSLToSkColor(header_lighter, SkColorGetA(color_header));
671
672  // Generate section border color from the header color. See
673  // BookmarkBarView::Paint for how we do this for the bookmark bar
674  // borders.
675  SkColor color_section_border =
676      SkColorSetARGB(80,
677                     SkColorGetR(color_header),
678                     SkColorGetG(color_header),
679                     SkColorGetB(color_header));
680
681  // Generate the replacements.
682  std::vector<std::string> subst;
683
684  // Cache-buster for background.
685  subst.push_back(
686      profile_->GetPrefs()->GetString(prefs::kCurrentThemeID));  // $1
687
688  // Colors.
689  subst.push_back(SkColorToRGBAString(color_background));  // $2
690  subst.push_back(GetNewTabBackgroundCSS(tp, false));  // $3
691  subst.push_back(GetNewTabBackgroundCSS(tp, true));  // $4
692  subst.push_back(GetNewTabBackgroundTilingCSS(tp));  // $5
693  subst.push_back(SkColorToRGBAString(color_header));  // $6
694  subst.push_back(SkColorToRGBAString(color_header_gradient_light));  // $7
695  subst.push_back(SkColorToRGBAString(color_text));  // $8
696  subst.push_back(SkColorToRGBAString(color_link));  // $9
697  subst.push_back(SkColorToRGBAString(color_section));  // $10
698  subst.push_back(SkColorToRGBAString(color_section_border));  // $11
699  subst.push_back(SkColorToRGBAString(color_section_text));  // $12
700  subst.push_back(SkColorToRGBAString(color_section_link));  // $13
701  subst.push_back(SkColorToRGBAString(color_link_underline));  // $14
702  subst.push_back(SkColorToRGBAString(color_section_link_underline));  // $15
703  subst.push_back(SkColorToRGBAString(color_section_header_text));  // $16
704  subst.push_back(SkColorToRGBAString(
705      color_section_header_text_hover));  // $17
706  subst.push_back(SkColorToRGBAString(color_section_header_rule));  // $18
707  subst.push_back(SkColorToRGBAString(
708      color_section_header_rule_light));  // $19
709  subst.push_back(SkColorToRGBAString(
710      SkColorSetA(color_section_header_rule, 0)));  // $20
711  subst.push_back(SkColorToRGBAString(color_text_light));  // $21
712  subst.push_back(SkColorToRGBComponents(color_section_border));  // $22
713  subst.push_back(SkColorToRGBComponents(color_text));  // $23
714
715  // Get our template.
716  static const base::StringPiece new_tab_theme_css(
717      ResourceBundle::GetSharedInstance().GetRawDataResource(
718          IDR_NEW_TAB_4_THEME_CSS));
719
720  // Create the string from our template and the replacements.
721  std::string css_string;
722  css_string = ReplaceStringPlaceholders(new_tab_theme_css, subst, NULL);
723  new_tab_css_ = base::RefCountedString::TakeString(&css_string);
724}
725