• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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_resource_cache.h"
6 
7 #include <algorithm>
8 #include <vector>
9 
10 #include "base/command_line.h"
11 #include "base/file_util.h"
12 #include "base/memory/ref_counted_memory.h"
13 #include "base/string16.h"
14 #include "base/string_number_conversions.h"
15 #include "base/time.h"
16 #include "base/utf_string_conversions.h"
17 #include "base/values.h"
18 #include "chrome/browser/google/google_util.h"
19 #include "chrome/browser/metrics/user_metrics.h"
20 #include "chrome/browser/prefs/pref_service.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/themes/theme_service.h"
23 #include "chrome/browser/themes/theme_service_factory.h"
24 #include "chrome/browser/ui/webui/chrome_url_data_manager.h"
25 #include "chrome/browser/ui/webui/shown_sections_handler.h"
26 #include "chrome/browser/web_resource/promo_resource_service.h"
27 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/extensions/extension.h"
29 #include "chrome/common/extensions/extension_constants.h"
30 #include "chrome/common/jstemplate_builder.h"
31 #include "chrome/common/pref_names.h"
32 #include "chrome/common/url_constants.h"
33 #include "content/browser/browser_thread.h"
34 #include "content/common/notification_service.h"
35 #include "content/common/notification_type.h"
36 #include "grit/browser_resources.h"
37 #include "grit/chromium_strings.h"
38 #include "grit/generated_resources.h"
39 #include "grit/locale_settings.h"
40 #include "grit/theme_resources.h"
41 #include "ui/base/animation/animation.h"
42 #include "ui/base/l10n/l10n_util.h"
43 #include "ui/base/resource/resource_bundle.h"
44 #include "ui/base/theme_provider.h"
45 #include "ui/gfx/color_utils.h"
46 
47 #if defined(OS_WIN) || defined(TOOLKIT_VIEWS)
48 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
49 #elif defined(OS_MACOSX)
50 #include "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h"
51 #elif defined(OS_POSIX)
52 #include "chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.h"
53 #endif
54 
55 using base::Time;
56 
57 namespace {
58 
59 // The URL for the the Learn More page shown on incognito new tab.
60 const char kLearnMoreIncognitoUrl[] =
61 #if defined(OS_CHROMEOS)
62     "https://www.google.com/support/chromeos/bin/answer.py?answer=95464";
63 #else
64     "https://www.google.com/support/chrome/bin/answer.py?answer=95464";
65 #endif
66 
67 // The URL for the Learn More page shown on guest session new tab.
68 const char kLearnMoreGuestSessionUrl[] =
69     "https://www.google.com/support/chromeos/bin/answer.py?answer=1057090";
70 
71 // The URL for bookmark sync service help.
72 const char kSyncServiceHelpUrl[] =
73     "https://www.google.com/support/chrome/bin/answer.py?answer=165139";
74 
75 // The URL to be loaded to display Help.
76 const char kHelpContentUrl[] =
77     "https://www.google.com/support/chrome/";
78 
GetUrlWithLang(const GURL & url)79 string16 GetUrlWithLang(const GURL& url) {
80   return ASCIIToUTF16(google_util::AppendGoogleLocaleParam(url).spec());
81 }
82 
SkColorToRGBAString(SkColor color)83 std::string SkColorToRGBAString(SkColor color) {
84   // We convert the alpha using DoubleToString because StringPrintf will use
85   // locale specific formatters (e.g., use , instead of . in German).
86   return StringPrintf("rgba(%d,%d,%d,%s)", SkColorGetR(color),
87       SkColorGetG(color), SkColorGetB(color),
88       base::DoubleToString(SkColorGetA(color) / 255.0).c_str());
89 }
90 
91 // Get the CSS string for the background position on the new tab page for the
92 // states when the bar is attached or detached.
GetNewTabBackgroundCSS(const ui::ThemeProvider * theme_provider,bool bar_attached)93 std::string GetNewTabBackgroundCSS(const ui::ThemeProvider* theme_provider,
94                                    bool bar_attached) {
95   int alignment;
96   theme_provider->GetDisplayProperty(
97       ThemeService::NTP_BACKGROUND_ALIGNMENT, &alignment);
98 
99   // TODO(glen): This is a quick workaround to hide the notused.png image when
100   // no image is provided - we don't have time right now to figure out why
101   // this is painting as white.
102   // http://crbug.com/17593
103   if (!theme_provider->HasCustomImage(IDR_THEME_NTP_BACKGROUND)) {
104     return "-64px";
105   }
106 
107   if (bar_attached)
108     return ThemeService::AlignmentToString(alignment);
109 
110   // The bar is detached, so we must offset the background by the bar size
111   // if it's a top-aligned bar.
112 #if defined(OS_WIN) || defined(TOOLKIT_VIEWS)
113   int offset = BookmarkBarView::kNewtabBarHeight;
114 #elif defined(OS_MACOSX)
115   int offset = bookmarks::kNTPBookmarkBarHeight;
116 #elif defined(OS_POSIX)
117   int offset = BookmarkBarGtk::kBookmarkBarNTPHeight;
118 #else
119   int offset = 0;
120 #endif
121 
122   if (alignment & ThemeService::ALIGN_TOP) {
123     if (alignment & ThemeService::ALIGN_LEFT)
124       return "0% " + base::IntToString(-offset) + "px";
125     else if (alignment & ThemeService::ALIGN_RIGHT)
126       return "100% " + base::IntToString(-offset) + "px";
127     return "center " + base::IntToString(-offset) + "px";
128   }
129   return ThemeService::AlignmentToString(alignment);
130 }
131 
132 // How the background image on the new tab page should be tiled (see tiling
133 // masks in theme_service.h).
GetNewTabBackgroundTilingCSS(const ui::ThemeProvider * theme_provider)134 std::string GetNewTabBackgroundTilingCSS(
135     const ui::ThemeProvider* theme_provider) {
136   int repeat_mode;
137   theme_provider->GetDisplayProperty(
138       ThemeService::NTP_BACKGROUND_TILING, &repeat_mode);
139   return ThemeService::TilingToString(repeat_mode);
140 }
141 
142 // Is the current time within a given date range?
InDateRange(double begin,double end)143 bool InDateRange(double begin, double end) {
144   Time start_time = Time::FromDoubleT(begin);
145   Time end_time = Time::FromDoubleT(end);
146   return start_time < Time::Now() && end_time > Time::Now();
147 }
148 
149 }  // namespace
150 
NTPResourceCache(Profile * profile)151 NTPResourceCache::NTPResourceCache(Profile* profile) : profile_(profile) {
152   registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
153                  NotificationService::AllSources());
154   registrar_.Add(this, NotificationType::PROMO_RESOURCE_STATE_CHANGED,
155                  NotificationService::AllSources());
156 
157   // Watch for pref changes that cause us to need to invalidate the HTML cache.
158   pref_change_registrar_.Init(profile_->GetPrefs());
159   pref_change_registrar_.Add(prefs::kShowBookmarkBar, this);
160   pref_change_registrar_.Add(prefs::kEnableBookmarkBar, this);
161   pref_change_registrar_.Add(prefs::kNTPShownSections, this);
162 }
163 
~NTPResourceCache()164 NTPResourceCache::~NTPResourceCache() {}
165 
GetNewTabHTML(bool is_incognito)166 RefCountedBytes* NTPResourceCache::GetNewTabHTML(bool is_incognito) {
167   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
168   if (is_incognito) {
169     if (!new_tab_incognito_html_.get())
170       CreateNewTabIncognitoHTML();
171   } else {
172     if (!new_tab_html_.get())
173       CreateNewTabHTML();
174   }
175   return is_incognito ? new_tab_incognito_html_.get()
176                       : new_tab_html_.get();
177 }
178 
GetNewTabCSS(bool is_incognito)179 RefCountedBytes* NTPResourceCache::GetNewTabCSS(bool is_incognito) {
180   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
181   if (is_incognito) {
182     if (!new_tab_incognito_css_.get())
183       CreateNewTabIncognitoCSS();
184   } else {
185     if (!new_tab_css_.get())
186       CreateNewTabCSS();
187   }
188   return is_incognito ? new_tab_incognito_css_.get()
189                       : new_tab_css_.get();
190 }
191 
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)192 void NTPResourceCache::Observe(NotificationType type,
193     const NotificationSource& source, const NotificationDetails& details) {
194   // Invalidate the cache.
195   if (NotificationType::BROWSER_THEME_CHANGED == type ||
196       NotificationType::PROMO_RESOURCE_STATE_CHANGED == type) {
197     new_tab_incognito_html_ = NULL;
198     new_tab_html_ = NULL;
199     new_tab_incognito_css_ = NULL;
200     new_tab_css_ = NULL;
201   } else if (NotificationType::PREF_CHANGED == type) {
202     std::string* pref_name = Details<std::string>(details).ptr();
203     if (*pref_name == prefs::kShowBookmarkBar ||
204         *pref_name == prefs::kEnableBookmarkBar ||
205         *pref_name == prefs::kHomePageIsNewTabPage ||
206         *pref_name == prefs::kNTPShownSections) {
207       new_tab_incognito_html_ = NULL;
208       new_tab_html_ = NULL;
209     } else {
210       NOTREACHED();
211     }
212   } else {
213     NOTREACHED();
214   }
215 }
216 
CreateNewTabIncognitoHTML()217 void NTPResourceCache::CreateNewTabIncognitoHTML() {
218   DictionaryValue localized_strings;
219   localized_strings.SetString("title",
220       l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE));
221   int new_tab_message_ids = IDS_NEW_TAB_OTR_MESSAGE;
222   int new_tab_html_idr = IDR_INCOGNITO_TAB_HTML;
223   const char* new_tab_link = kLearnMoreIncognitoUrl;
224   // TODO(altimofeev): consider implementation without 'if def' usage.
225 #if defined(OS_CHROMEOS)
226   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kGuestSession)) {
227     new_tab_message_ids = IDS_NEW_TAB_GUEST_SESSION_MESSAGE;
228     new_tab_html_idr = IDR_GUEST_SESSION_TAB_HTML;
229     new_tab_link = kLearnMoreGuestSessionUrl;
230   }
231 #endif
232   localized_strings.SetString("content",
233       l10n_util::GetStringFUTF16(new_tab_message_ids,
234                                  GetUrlWithLang(GURL(new_tab_link))));
235   localized_strings.SetString("extensionsmessage",
236       l10n_util::GetStringFUTF16(IDS_NEW_TAB_OTR_EXTENSIONS_MESSAGE,
237                                  l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
238                                  ASCIIToUTF16(chrome::kChromeUIExtensionsURL)));
239   bool bookmark_bar_attached = profile_->GetPrefs()->GetBoolean(
240       prefs::kShowBookmarkBar);
241   localized_strings.SetString("bookmarkbarattached",
242       bookmark_bar_attached ? "true" : "false");
243 
244   ChromeURLDataManager::DataSource::SetFontAndTextDirection(&localized_strings);
245 
246   static const base::StringPiece incognito_tab_html(
247       ResourceBundle::GetSharedInstance().GetRawDataResource(
248           new_tab_html_idr));
249 
250   std::string full_html = jstemplate_builder::GetI18nTemplateHtml(
251       incognito_tab_html, &localized_strings);
252 
253   new_tab_incognito_html_ = new RefCountedBytes;
254   new_tab_incognito_html_->data.resize(full_html.size());
255   std::copy(full_html.begin(), full_html.end(),
256             new_tab_incognito_html_->data.begin());
257 }
258 
CreateNewTabHTML()259 void NTPResourceCache::CreateNewTabHTML() {
260   // Show the profile name in the title and most visited labels if the current
261   // profile is not the default.
262   string16 apps = l10n_util::GetStringUTF16(IDS_NEW_TAB_APPS);
263   string16 title = l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE);
264   string16 most_visited = l10n_util::GetStringUTF16(IDS_NEW_TAB_MOST_VISITED);
265   DictionaryValue localized_strings;
266   localized_strings.SetString("bookmarkbarattached",
267       profile_->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar) ?
268       "true" : "false");
269   localized_strings.SetString("hasattribution",
270       ThemeServiceFactory::GetForProfile(profile_)->HasCustomImage(
271           IDR_THEME_NTP_ATTRIBUTION) ?
272       "true" : "false");
273   localized_strings.SetString("apps", apps);
274   localized_strings.SetString("title", title);
275   localized_strings.SetString("mostvisited", most_visited);
276   localized_strings.SetString("restorethumbnails",
277       l10n_util::GetStringUTF16(IDS_NEW_TAB_RESTORE_THUMBNAILS_LINK));
278   localized_strings.SetString("recentlyclosed",
279       l10n_util::GetStringUTF16(IDS_NEW_TAB_RECENTLY_CLOSED));
280   localized_strings.SetString("closedwindowsingle",
281       l10n_util::GetStringUTF16(IDS_NEW_TAB_RECENTLY_CLOSED_WINDOW_SINGLE));
282   localized_strings.SetString("foreignsessions",
283       l10n_util::GetStringUTF16(IDS_SYNC_DATATYPE_SESSIONS));
284   localized_strings.SetString("closedwindowmultiple",
285       l10n_util::GetStringUTF16(IDS_NEW_TAB_RECENTLY_CLOSED_WINDOW_MULTIPLE));
286   localized_strings.SetString("attributionintro",
287       l10n_util::GetStringUTF16(IDS_NEW_TAB_ATTRIBUTION_INTRO));
288   localized_strings.SetString("thumbnailremovednotification",
289       l10n_util::GetStringUTF16(IDS_NEW_TAB_THUMBNAIL_REMOVED_NOTIFICATION));
290   localized_strings.SetString("undothumbnailremove",
291       l10n_util::GetStringUTF16(IDS_NEW_TAB_UNDO_THUMBNAIL_REMOVE));
292   localized_strings.SetString("removethumbnailtooltip",
293       l10n_util::GetStringUTF16(IDS_NEW_TAB_REMOVE_THUMBNAIL_TOOLTIP));
294   localized_strings.SetString("pinthumbnailtooltip",
295       l10n_util::GetStringUTF16(IDS_NEW_TAB_PIN_THUMBNAIL_TOOLTIP));
296   localized_strings.SetString("unpinthumbnailtooltip",
297       l10n_util::GetStringUTF16(IDS_NEW_TAB_UNPIN_THUMBNAIL_TOOLTIP));
298   localized_strings.SetString("showhidethumbnailtooltip",
299       l10n_util::GetStringUTF16(IDS_NEW_TAB_SHOW_HIDE_THUMBNAIL_TOOLTIP));
300   localized_strings.SetString("showhidelisttooltip",
301       l10n_util::GetStringUTF16(IDS_NEW_TAB_SHOW_HIDE_LIST_TOOLTIP));
302   localized_strings.SetString("pagedisplaytooltip",
303       l10n_util::GetStringUTF16(IDS_NEW_TAB_PAGE_DISPLAY_TOOLTIP));
304   localized_strings.SetString("closefirstrunnotification",
305       l10n_util::GetStringUTF16(IDS_NEW_TAB_CLOSE_FIRST_RUN_NOTIFICATION));
306   localized_strings.SetString("close", l10n_util::GetStringUTF16(IDS_CLOSE));
307   localized_strings.SetString("history",
308       l10n_util::GetStringUTF16(IDS_NEW_TAB_HISTORY));
309   localized_strings.SetString("downloads",
310       l10n_util::GetStringUTF16(IDS_NEW_TAB_DOWNLOADS));
311   localized_strings.SetString("help",
312       l10n_util::GetStringUTF16(IDS_NEW_TAB_HELP));
313   localized_strings.SetString("helpurl",
314       GetUrlWithLang(GURL(kHelpContentUrl)));
315   localized_strings.SetString("appsettings",
316       l10n_util::GetStringUTF16(IDS_NEW_TAB_APP_SETTINGS));
317   localized_strings.SetString("appuninstall",
318       l10n_util::GetStringUTF16(IDS_NEW_TAB_APP_UNINSTALL));
319   localized_strings.SetString("appoptions",
320       l10n_util::GetStringUTF16(IDS_NEW_TAB_APP_OPTIONS));
321   localized_strings.SetString("appcreateshortcut",
322       l10n_util::GetStringUTF16(IDS_NEW_TAB_APP_CREATE_SHORTCUT));
323   localized_strings.SetString("applaunchtypepinned",
324       l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_PINNED));
325   localized_strings.SetString("applaunchtyperegular",
326       l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_REGULAR));
327   localized_strings.SetString("applaunchtypewindow",
328       l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_WINDOW));
329   localized_strings.SetString("applaunchtypefullscreen",
330       l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_FULLSCREEN));
331   localized_strings.SetString("web_store_title",
332       l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE));
333   localized_strings.SetString("web_store_url",
334       GetUrlWithLang(GURL(Extension::ChromeStoreLaunchURL())));
335   localized_strings.SetString("syncpromotext",
336       l10n_util::GetStringUTF16(IDS_SYNC_START_SYNC_BUTTON_LABEL));
337 #if defined(OS_CHROMEOS)
338   localized_strings.SetString("expandMenu",
339       l10n_util::GetStringUTF16(IDS_NEW_TAB_CLOSE_MENU_EXPAND));
340 #endif
341 
342   // Don't initiate the sync related message passing with the page if the sync
343   // code is not present.
344   if (profile_->GetProfileSyncService())
345     localized_strings.SetString("syncispresent", "true");
346   else
347     localized_strings.SetString("syncispresent", "false");
348 
349   ChromeURLDataManager::DataSource::SetFontAndTextDirection(&localized_strings);
350 
351   // Control fade and resize animations.
352   std::string anim =
353       ui::Animation::ShouldRenderRichAnimation() ? "true" : "false";
354   localized_strings.SetString("anim", anim);
355 
356   // Pass the shown_sections pref early so that we can prevent flicker.
357   const int shown_sections = ShownSectionsHandler::GetShownSections(
358       profile_->GetPrefs());
359   localized_strings.SetInteger("shown_sections", shown_sections);
360 
361   // If the user has preferences for a start and end time for a custom logo,
362   // and the time now is between these two times, show the custom logo.
363   if (profile_->GetPrefs()->FindPreference(prefs::kNTPCustomLogoStart) &&
364       profile_->GetPrefs()->FindPreference(prefs::kNTPCustomLogoEnd)) {
365     localized_strings.SetString("customlogo",
366         InDateRange(profile_->GetPrefs()->GetDouble(prefs::kNTPCustomLogoStart),
367                     profile_->GetPrefs()->GetDouble(prefs::kNTPCustomLogoEnd)) ?
368         "true" : "false");
369   } else {
370     localized_strings.SetString("customlogo", "false");
371   }
372 
373   // If the user has preferences for a start and end time for a promo from
374   // the server, and this promo string exists, set the localized string.
375   if (profile_->GetPrefs()->FindPreference(prefs::kNTPPromoStart) &&
376       profile_->GetPrefs()->FindPreference(prefs::kNTPPromoEnd) &&
377       profile_->GetPrefs()->FindPreference(prefs::kNTPPromoLine) &&
378       PromoResourceServiceUtil::CanShowPromo(profile_)) {
379     localized_strings.SetString("serverpromo",
380         InDateRange(profile_->GetPrefs()->GetDouble(prefs::kNTPPromoStart),
381                     profile_->GetPrefs()->GetDouble(prefs::kNTPPromoEnd)) ?
382                     profile_->GetPrefs()->GetString(prefs::kNTPPromoLine) :
383                                                     std::string());
384     UserMetrics::RecordAction(UserMetricsAction("NTPPromoShown"));
385   }
386 
387   // Load the new tab page appropriate for this build
388   // Note that some builds (eg. TOUCHUI) don't make use of everything we
389   // do here (all of the template data, etc.), but we keep the back end
390   // consistent across builds, supporting the union of all NTP front-ends
391   // for simplicity.
392   std::string full_html;
393   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kNewTabPage4)) {
394     base::StringPiece new_tab_html(ResourceBundle::GetSharedInstance().
395         GetRawDataResource(IDR_NEW_TAB_4_HTML));
396     full_html = jstemplate_builder::GetI18nTemplateHtml(new_tab_html,
397                                                         &localized_strings);
398   } else {
399     base::StringPiece new_tab_html(ResourceBundle::GetSharedInstance().
400         GetRawDataResource(IDR_NEW_TAB_HTML));
401 
402     // Inject the template data into the HTML so that it is available before any
403     // layout is needed.
404     std::string json_html;
405     jstemplate_builder::AppendJsonHtml(&localized_strings, &json_html);
406 
407     static const base::StringPiece template_data_placeholder(
408         "<!-- template data placeholder -->");
409     size_t pos = new_tab_html.find(template_data_placeholder);
410 
411     if (pos != base::StringPiece::npos) {
412       full_html.assign(new_tab_html.data(), pos);
413       full_html.append(json_html);
414       size_t after_offset = pos + template_data_placeholder.size();
415       full_html.append(new_tab_html.data() + after_offset,
416                        new_tab_html.size() - after_offset);
417     } else {
418       NOTREACHED();
419       full_html.assign(new_tab_html.data(), new_tab_html.size());
420     }
421   }
422 
423   new_tab_html_ = new RefCountedBytes;
424   new_tab_html_->data.resize(full_html.size());
425   std::copy(full_html.begin(), full_html.end(), new_tab_html_->data.begin());
426 }
427 
CreateNewTabIncognitoCSS()428 void NTPResourceCache::CreateNewTabIncognitoCSS() {
429   ui::ThemeProvider* tp = ThemeServiceFactory::GetForProfile(profile_);
430   DCHECK(tp);
431 
432   // Get our theme colors
433   SkColor color_background =
434       tp->GetColor(ThemeService::COLOR_NTP_BACKGROUND);
435 
436   // Generate the replacements.
437   std::vector<std::string> subst;
438 
439   // Cache-buster for background.
440   subst.push_back(
441       profile_->GetPrefs()->GetString(prefs::kCurrentThemeID));  // $1
442 
443   // Colors.
444   subst.push_back(SkColorToRGBAString(color_background));  // $2
445   subst.push_back(GetNewTabBackgroundCSS(tp, false));  // $3
446   subst.push_back(GetNewTabBackgroundCSS(tp, true));  // $4
447   subst.push_back(GetNewTabBackgroundTilingCSS(tp));  // $5
448 
449   // Get our template.
450   static const base::StringPiece new_tab_theme_css(
451       ResourceBundle::GetSharedInstance().GetRawDataResource(
452       IDR_NEW_INCOGNITO_TAB_THEME_CSS));
453 
454   // Create the string from our template and the replacements.
455   std::string full_css = ReplaceStringPlaceholders(
456       new_tab_theme_css, subst, NULL);
457 
458   new_tab_incognito_css_ = new RefCountedBytes;
459   new_tab_incognito_css_->data.resize(full_css.size());
460   std::copy(full_css.begin(), full_css.end(),
461             new_tab_incognito_css_->data.begin());
462 }
463 
CreateNewTabCSS()464 void NTPResourceCache::CreateNewTabCSS() {
465   ui::ThemeProvider* tp = ThemeServiceFactory::GetForProfile(profile_);
466   DCHECK(tp);
467 
468   // Get our theme colors
469   SkColor color_background =
470       tp->GetColor(ThemeService::COLOR_NTP_BACKGROUND);
471   SkColor color_text = tp->GetColor(ThemeService::COLOR_NTP_TEXT);
472   SkColor color_link = tp->GetColor(ThemeService::COLOR_NTP_LINK);
473   SkColor color_link_underline =
474       tp->GetColor(ThemeService::COLOR_NTP_LINK_UNDERLINE);
475 
476   SkColor color_section =
477       tp->GetColor(ThemeService::COLOR_NTP_SECTION);
478   SkColor color_section_text =
479       tp->GetColor(ThemeService::COLOR_NTP_SECTION_TEXT);
480   SkColor color_section_link =
481       tp->GetColor(ThemeService::COLOR_NTP_SECTION_LINK);
482   SkColor color_section_link_underline =
483       tp->GetColor(ThemeService::COLOR_NTP_SECTION_LINK_UNDERLINE);
484   SkColor color_section_header_text =
485       tp->GetColor(ThemeService::COLOR_NTP_SECTION_HEADER_TEXT);
486   SkColor color_section_header_text_hover =
487       tp->GetColor(ThemeService::COLOR_NTP_SECTION_HEADER_TEXT_HOVER);
488   SkColor color_section_header_rule =
489       tp->GetColor(ThemeService::COLOR_NTP_SECTION_HEADER_RULE);
490   SkColor color_section_header_rule_light =
491       tp->GetColor(ThemeService::COLOR_NTP_SECTION_HEADER_RULE_LIGHT);
492   SkColor color_text_light =
493       tp->GetColor(ThemeService::COLOR_NTP_TEXT_LIGHT);
494 
495   SkColor color_header =
496       tp->GetColor(ThemeService::COLOR_NTP_HEADER);
497   // Generate a lighter color for the header gradients.
498   color_utils::HSL header_lighter;
499   color_utils::SkColorToHSL(color_header, &header_lighter);
500   header_lighter.l += (1 - header_lighter.l) * 0.33;
501   SkColor color_header_gradient_light =
502       color_utils::HSLToSkColor(header_lighter, SkColorGetA(color_header));
503 
504   // Generate section border color from the header color. See
505   // BookmarkBarView::Paint for how we do this for the bookmark bar
506   // borders.
507   SkColor color_section_border =
508       SkColorSetARGB(80,
509                      SkColorGetR(color_header),
510                      SkColorGetG(color_header),
511                      SkColorGetB(color_header));
512 
513   // Generate the replacements.
514   std::vector<std::string> subst;
515   // A second list of replacements, each of which must be in $$x format,
516   // where x is a digit from 1-9.
517   std::vector<std::string> subst2;
518   std::vector<std::string> subst3;
519 
520   // Cache-buster for background.
521   subst.push_back(
522       profile_->GetPrefs()->GetString(prefs::kCurrentThemeID));  // $1
523 
524   // Colors.
525   subst.push_back(SkColorToRGBAString(color_background));  // $2
526   subst.push_back(GetNewTabBackgroundCSS(tp, false));  // $3
527   subst.push_back(GetNewTabBackgroundCSS(tp, true));  // $4
528   subst.push_back(GetNewTabBackgroundTilingCSS(tp));  // $5
529   subst.push_back(SkColorToRGBAString(color_header));  // $6
530   subst.push_back(SkColorToRGBAString(color_header_gradient_light));  // $7
531   subst.push_back(SkColorToRGBAString(color_text));  // $8
532   subst.push_back(SkColorToRGBAString(color_link));  // $9
533 
534   subst2.push_back(SkColorToRGBAString(color_section));  // $$1
535   subst2.push_back(SkColorToRGBAString(color_section_border));  // $$2
536   subst2.push_back(SkColorToRGBAString(color_section_text));  // $$3
537   subst2.push_back(SkColorToRGBAString(color_section_link));  // $$4
538   subst2.push_back(SkColorToRGBAString(color_link_underline));  // $$5
539   subst2.push_back(SkColorToRGBAString(color_section_link_underline));  // $$6
540   subst2.push_back(SkColorToRGBAString(color_section_header_text)); // $$7
541   subst2.push_back(SkColorToRGBAString(
542       color_section_header_text_hover)); // $$8
543   subst2.push_back(SkColorToRGBAString(color_section_header_rule));  // $$9
544 
545   subst3.push_back(SkColorToRGBAString(
546       color_section_header_rule_light));  // $$$1
547   subst3.push_back(SkColorToRGBAString(
548       SkColorSetA(color_section_header_rule, 0)));  // $$$2
549   subst3.push_back(SkColorToRGBAString(color_text_light));  // $$$3
550 
551   // Get our template.
552   int ntp_css_resource_id =
553       CommandLine::ForCurrentProcess()->HasSwitch(switches::kNewTabPage4) ?
554           IDR_NEW_TAB_4_THEME_CSS : IDR_NEW_TAB_THEME_CSS;
555   static const base::StringPiece new_tab_theme_css(
556       ResourceBundle::GetSharedInstance().GetRawDataResource(
557           ntp_css_resource_id));
558 
559   // Create the string from our template and the replacements.
560   std::string css_string;
561   css_string = ReplaceStringPlaceholders(new_tab_theme_css, subst, NULL);
562   css_string = ReplaceStringPlaceholders(css_string, subst2, NULL);
563   css_string = ReplaceStringPlaceholders(css_string, subst3, NULL);
564 
565   new_tab_css_ = new RefCountedBytes;
566   new_tab_css_->data.resize(css_string.size());
567   std::copy(css_string.begin(), css_string.end(),
568             new_tab_css_->data.begin());
569 }
570