Home | History | Annotate | Download | only in webui
      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 
     79 string16 GetUrlWithLang(const GURL& url) {
     80   return ASCIIToUTF16(google_util::AppendGoogleLocaleParam(url).spec());
     81 }
     82 
     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.
     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).
    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?
    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 
    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 
    164 NTPResourceCache::~NTPResourceCache() {}
    165 
    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 
    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 
    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 
    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 
    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 
    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 
    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