diff options
author | glen@chromium.org <glen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-14 00:21:58 +0000 |
---|---|---|
committer | glen@chromium.org <glen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-14 00:21:58 +0000 |
commit | 0078ffb91ddeea8c35cdd75ffe161623030d8dbf (patch) | |
tree | 96089176d6afd0030fa4eb77a8b6ca7bcbb4ec59 /chrome/browser/dom_ui | |
parent | 849a62a1aa77e5d7887bc310233d86cf33ebf393 (diff) | |
download | chromium_src-0078ffb91ddeea8c35cdd75ffe161623030d8dbf.zip chromium_src-0078ffb91ddeea8c35cdd75ffe161623030d8dbf.tar.gz chromium_src-0078ffb91ddeea8c35cdd75ffe161623030d8dbf.tar.bz2 |
Allow the new tab page to be themed (you may want to review DOMUIThemeSource as a whole and not just these changes).
Change global std::strings to chars* in browser theme provider.
Add ability for ReplaceStringPlaceHolder to take up to 9 replacements.
BUG=11235,11685
Review URL: http://codereview.chromium.org/115172
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16020 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/dom_ui')
-rw-r--r-- | chrome/browser/dom_ui/dom_ui_theme_source.cc | 125 | ||||
-rw-r--r-- | chrome/browser/dom_ui/dom_ui_theme_source.h | 14 | ||||
-rw-r--r-- | chrome/browser/dom_ui/dom_ui_theme_source_unittest.cc | 84 | ||||
-rw-r--r-- | chrome/browser/dom_ui/new_tab_ui.cc | 16 | ||||
-rw-r--r-- | chrome/browser/dom_ui/new_tab_ui.h | 8 |
5 files changed, 226 insertions, 21 deletions
diff --git a/chrome/browser/dom_ui/dom_ui_theme_source.cc b/chrome/browser/dom_ui/dom_ui_theme_source.cc index 31ff1f8..1ff0492 100644 --- a/chrome/browser/dom_ui/dom_ui_theme_source.cc +++ b/chrome/browser/dom_ui/dom_ui_theme_source.cc @@ -4,34 +4,129 @@ #include "chrome/browser/dom_ui/dom_ui_theme_source.h" +#include "app/l10n_util.h" #include "app/resource_bundle.h" #include "app/theme_provider.h" #include "base/gfx/png_encoder.h" #include "base/message_loop.h" +#include "base/string_util.h" +#include "base/time.h" +#include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/profile.h" #include "chrome/browser/theme_resources_util.h" #include "chrome/common/url_constants.h" +#include "googleurl/src/gurl.h" +#include "grit/browser_resources.h" +#include "grit/generated_resources.h" #include "grit/theme_resources.h" +// Path for the New Tab CSS. When we get more than a few of these, we should +// use a resource map rather than hard-coded strings. +static const char* kNewTabCSSPath = "css/newtab.css"; + +static string16 SkColorToRGBAString(SkColor color) { + return WideToUTF16(l10n_util::GetStringF(IDS_RGBA_CSS_FORMAT_STRING, + IntToWString(SkColorGetR(color)), + IntToWString(SkColorGetG(color)), + IntToWString(SkColorGetB(color)), + DoubleToWString(SkColorGetA(color) / 255.0))); +} + +static std::string StripQueryParams(const std::string& path) { + GURL path_url = GURL(std::string(chrome::kChromeUIScheme) + "://" + + std::string(chrome::kChromeUIThemePath) + "/" + path); + return path_url.path().substr(1); // path() always includes a leading '/'. +} + +//////////////////////////////////////////////////////////////////////////////// +// DOMUIThemeSource, public: + DOMUIThemeSource::DOMUIThemeSource(Profile* profile) - : DataSource(chrome::kChromeUIThemePath, MessageLoop::current()), - profile_(profile) { + : DataSource(chrome::kChromeUIThemePath, MessageLoop::current()), + profile_(profile) { } void DOMUIThemeSource::StartDataRequest(const std::string& path, - int request_id) { - ThemeProvider* tp = profile_->GetThemeProvider(); - if (tp) { - int id = ThemeResourcesUtil::GetId(path); - if (id != -1) { - SkBitmap* image = tp->GetBitmapNamed(id); - if (image) { - std::vector<unsigned char> png_bytes; - PNGEncoder::EncodeBGRASkBitmap(*image, false, &png_bytes); - - scoped_refptr<RefCountedBytes> image_data = new RefCountedBytes(png_bytes); - SendResponse(request_id, image_data); - } + int request_id) { + // Our path may include cachebuster arguments, so trim them off. + std::string uncached_path = StripQueryParams(path); + + if (strcmp(uncached_path.c_str(), kNewTabCSSPath) == 0) { + SendNewTabCSS(request_id); + return; + } else { + int resource_id = ThemeResourcesUtil::GetId(uncached_path); + if (resource_id != -1) { + SendThemeBitmap(request_id, resource_id); + return; } } + // We don't have any data to send back. + SendResponse(request_id, NULL); +} + +std::string DOMUIThemeSource::GetMimeType(const std::string& path) const { + std::string uncached_path = StripQueryParams(path); + + if (strcmp(uncached_path.c_str(), kNewTabCSSPath) == 0) + return "text/css"; + return "image/png"; +} + +//////////////////////////////////////////////////////////////////////////////// +// DOMUIThemeSource, private: + +void DOMUIThemeSource::SendNewTabCSS(int request_id) { + ThemeProvider* tp = profile_->GetThemeProvider(); + DCHECK(tp); + + // Get our theme colors + SkColor color_text = tp->GetColor(BrowserThemeProvider::COLOR_NTP_TEXT); + SkColor color_link = tp->GetColor(BrowserThemeProvider::COLOR_NTP_LINK); + SkColor color_section = + tp->GetColor(BrowserThemeProvider::COLOR_NTP_SECTION); + + // Generate the replacements. + std::vector<const string16> subst; + + // Cache-buster for background. + subst.push_back(UTF8ToUTF16(IntToString(static_cast<int>( + base::Time::Now().ToDoubleT())))); + + // Colors. + subst.push_back(SkColorToRGBAString(color_text)); + subst.push_back(SkColorToRGBAString(color_link)); + subst.push_back(SkColorToRGBAString(color_section)); + + // Get our template. + static const StringPiece new_tab_theme_css( + ResourceBundle::GetSharedInstance().GetRawDataResource( + IDR_NEW_TAB_THEME_CSS)); + + // Create the string from our template and the replacements. + string16 format_string = ASCIIToUTF16(new_tab_theme_css.as_string()); + const std::string css_string = UTF16ToASCII(ReplaceStringPlaceholders( + format_string, subst, NULL)); + + // Convert to a format appropriate for sending. + scoped_refptr<RefCountedBytes> css_bytes(new RefCountedBytes); + css_bytes->data.resize(css_string.size()); + std::copy(css_string.begin(), css_string.end(), css_bytes->data.begin()); + + // Send. + SendResponse(request_id, css_bytes); +} + +void DOMUIThemeSource::SendThemeBitmap(int request_id, int resource_id) { + ThemeProvider* tp = profile_->GetThemeProvider(); + DCHECK(tp); + + SkBitmap* image = tp->GetBitmapNamed(resource_id); + DCHECK(image); + std::vector<unsigned char> png_bytes; + PNGEncoder::EncodeBGRASkBitmap(*image, false, &png_bytes); + + scoped_refptr<RefCountedBytes> image_data = + new RefCountedBytes(png_bytes); + SendResponse(request_id, image_data); } diff --git a/chrome/browser/dom_ui/dom_ui_theme_source.h b/chrome/browser/dom_ui/dom_ui_theme_source.h index 279042d..4dc9bc1 100644 --- a/chrome/browser/dom_ui/dom_ui_theme_source.h +++ b/chrome/browser/dom_ui/dom_ui_theme_source.h @@ -12,17 +12,21 @@ class Profile; // ThumbnailSource is the gateway between network-level chrome: // requests for thumbnails and the history backend that serves these. class DOMUIThemeSource : public ChromeURLDataManager::DataSource { -public: + public: explicit DOMUIThemeSource(Profile* profile); // Called when the network layer has requested a resource underneath // the path we registered. virtual void StartDataRequest(const std::string& path, int request_id); - virtual std::string GetMimeType(const std::string& path) const { - return "image/png"; - } + virtual std::string GetMimeType(const std::string& path) const; + + private: + // Generate and send the CSS for the new tab. + void SendNewTabCSS(int request_id); + + // Fetch and send the theme bitmap. + void SendThemeBitmap(int request_id, int resource_id); -private: Profile* profile_; DISALLOW_COPY_AND_ASSIGN(DOMUIThemeSource); }; diff --git a/chrome/browser/dom_ui/dom_ui_theme_source_unittest.cc b/chrome/browser/dom_ui/dom_ui_theme_source_unittest.cc new file mode 100644 index 0000000..7eae052 --- /dev/null +++ b/chrome/browser/dom_ui/dom_ui_theme_source_unittest.cc @@ -0,0 +1,84 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/gfx/png_encoder.h" +#include "chrome/browser/browser_theme_provider.h" +#include "chrome/browser/dom_ui/dom_ui_theme_source.h" +#include "chrome/browser/profile.h" +#include "chrome/common/url_constants.h" +#include "chrome/test/testing_profile.h" +#include "grit/theme_resources.h" +#include "testing/gtest/include/gtest/gtest.h" + +// A mock ThemeSource (so we can override SendResponse to get at its data). +class MockThemeSource : public DOMUIThemeSource { + public: + explicit MockThemeSource(Profile* profile) : DOMUIThemeSource(profile) { } + + void SendResponse(int request_id, RefCountedBytes* data) { + result_data_ = data ? data : new RefCountedBytes(); + result_request_id_ = request_id; + } + + int result_request_id_; + RefCountedBytes* result_data_; +}; + +// A mock profile +class MockProfile : public TestingProfile { + public: + ThemeProvider* GetThemeProvider() { return new BrowserThemeProvider(); } +}; + + +TEST(DOMUISources, ThemeSourceMimeTypes) { + MockProfile* profile = new MockProfile(); + DOMUIThemeSource* theme_source = new DOMUIThemeSource(profile); + + EXPECT_EQ(theme_source->GetMimeType("css/newtab.css"), "text/css"); + EXPECT_EQ(theme_source->GetMimeType("css/newtab.css?foo"), "text/css"); + EXPECT_EQ(theme_source->GetMimeType("WRONGURL"), "image/png"); +} + +TEST(DOMUISources, ThemeSourceImages) { + MockProfile* profile = new MockProfile(); + MockThemeSource* theme_source = new MockThemeSource(profile); + + // Our test data. + ThemeProvider* tp = profile->GetThemeProvider(); + SkBitmap* image = tp->GetBitmapNamed(IDR_THEME_FRAME); + std::vector<unsigned char> png_bytes; + PNGEncoder::EncodeBGRASkBitmap(*image, false, &png_bytes); + RefCountedBytes* image_data = new RefCountedBytes(png_bytes); + + theme_source->StartDataRequest("theme_frame", 1); + EXPECT_EQ(theme_source->result_request_id_, 1); + EXPECT_EQ(theme_source->result_data_, image_data); + + theme_source->StartDataRequest("theme_toolbar", 2); + EXPECT_EQ(theme_source->result_request_id_, 2); + EXPECT_NE(theme_source->result_data_, image_data); +} + +TEST(DOMUISources, ThemeSourceCSS) { + MockProfile* profile = new MockProfile(); + MockThemeSource* theme_source = new MockThemeSource(profile); + + // Generating the test data for the NTP CSS would just involve copying the + // method, or being super brittle and hard-coding the result (requiring + // an update to the unittest every time the CSS template changes), so we + // just check for a successful request. + theme_source->StartDataRequest("css/newtab.css", 1); + EXPECT_EQ(theme_source->result_request_id_, 1); + EXPECT_NE(theme_source->result_data_, new RefCountedBytes()); + + theme_source->StartDataRequest("css/newtab.css?pipe", 3); + EXPECT_EQ(theme_source->result_request_id_, 3); + EXPECT_NE(theme_source->result_data_, new RefCountedBytes()); + + // Check that we send NULL back when we can't find what we're looking for. + theme_source->StartDataRequest("css/WRONGURL", 7); + EXPECT_EQ(theme_source->result_request_id_, 7); + EXPECT_EQ(theme_source->result_data_, new RefCountedBytes()); +} diff --git a/chrome/browser/dom_ui/new_tab_ui.cc b/chrome/browser/dom_ui/new_tab_ui.cc index f76c711..f64d0ff 100644 --- a/chrome/browser/dom_ui/new_tab_ui.cc +++ b/chrome/browser/dom_ui/new_tab_ui.cc @@ -1172,11 +1172,27 @@ NewTabUI::NewTabUI(TabContents* contents) html_source)); } } + + // Listen for theme installation. + NotificationService::current()->AddObserver(this, + NotificationType::THEME_INSTALLED, NotificationService::AllSources()); } NewTabUI::~NewTabUI() { + // Remove theme observer. + NotificationService::current()->RemoveObserver(this, + NotificationType::THEME_INSTALLED, NotificationService::AllSources()); +} + +void NewTabUI::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + if (NotificationType::THEME_INSTALLED == type) { + CallJavascriptFunction(L"themeChanged"); + } } + // static void NewTabUI::RegisterUserPrefs(PrefService* prefs) { MostVisitedHandler::RegisterUserPrefs(prefs); diff --git a/chrome/browser/dom_ui/new_tab_ui.h b/chrome/browser/dom_ui/new_tab_ui.h index 8e3b560..f233b0f 100644 --- a/chrome/browser/dom_ui/new_tab_ui.h +++ b/chrome/browser/dom_ui/new_tab_ui.h @@ -6,13 +6,15 @@ #define CHROME_BROWSER_DOM_UI_NEW_TAB_UI_H_ #include "chrome/browser/dom_ui/dom_ui.h" +#include "chrome/common/notification_observer.h" class GURL; class PrefService; class Profile; // The TabContents used for the New Tab page. -class NewTabUI : public DOMUI { +class NewTabUI : public DOMUI, + public NotificationObserver { public: explicit NewTabUI(TabContents* manager); ~NewTabUI(); @@ -20,6 +22,10 @@ class NewTabUI : public DOMUI { static void RegisterUserPrefs(PrefService* prefs); private: + void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + // The message id that should be displayed in this NewTabUIContents // instance's motd area. int motd_message_id_; |