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