summaryrefslogtreecommitdiffstats
path: root/chrome/browser/dom_ui
diff options
context:
space:
mode:
authorglen@chromium.org <glen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-14 00:21:58 +0000
committerglen@chromium.org <glen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-14 00:21:58 +0000
commit0078ffb91ddeea8c35cdd75ffe161623030d8dbf (patch)
tree96089176d6afd0030fa4eb77a8b6ca7bcbb4ec59 /chrome/browser/dom_ui
parent849a62a1aa77e5d7887bc310233d86cf33ebf393 (diff)
downloadchromium_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.cc125
-rw-r--r--chrome/browser/dom_ui/dom_ui_theme_source.h14
-rw-r--r--chrome/browser/dom_ui/dom_ui_theme_source_unittest.cc84
-rw-r--r--chrome/browser/dom_ui/new_tab_ui.cc16
-rw-r--r--chrome/browser/dom_ui/new_tab_ui.h8
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_;