summaryrefslogtreecommitdiffstats
path: root/chrome
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
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')
-rw-r--r--chrome/app/generated_resources.grd4
-rw-r--r--chrome/app/theme/ntp_background.pngbin1885 -> 144 bytes
-rw-r--r--chrome/app/theme/theme_resources.grd7
-rw-r--r--chrome/browser/browser_resources.grd1
-rw-r--r--chrome/browser/browser_theme_provider.cc81
-rw-r--r--chrome/browser/browser_theme_provider.h4
-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
-rw-r--r--chrome/browser/resources/new_tab.html29
-rw-r--r--chrome/browser/resources/new_tab_theme.css11
-rw-r--r--chrome/chrome.gyp1
-rw-r--r--chrome/test/unit/unittests.vcproj4
15 files changed, 324 insertions, 65 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 33bbbf3..ffc5ab6 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -3814,6 +3814,10 @@ each locale. -->
Don't ask again
</message>
+ <message name="IDS_RGBA_CSS_FORMAT_STRING" translateable="false" desc="The format string to use when converting colors to CSS rgba().">
+ rgba($1, $2, $3, $4)
+ </message>
+
</messages>
</release>
</grit>
diff --git a/chrome/app/theme/ntp_background.png b/chrome/app/theme/ntp_background.png
index fb75b9f..490e723 100644
--- a/chrome/app/theme/ntp_background.png
+++ b/chrome/app/theme/ntp_background.png
Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index c89f5db..b0080d5 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -175,6 +175,11 @@
<include name="IDR_NEWTAB_BUTTON" file="newtab.png" type="BINDATA" />
<include name="IDR_NEWTAB_BUTTON_H" file="newtab_h.png" type="BINDATA" />
<include name="IDR_NEWTAB_BUTTON_P" file="newtab_p.png" type="BINDATA" />
+ <include name="IDR_NEWTAB_REMOVE_ICON" file="ntp_x_icon_small.png" type="BINDATA" />
+ <include name="IDR_NEWTAB_REMOVE_THUMBNAIL" file="ntp_x_icon.png" type="BINDATA" />
+ <include name="IDR_NEWTAB_REMOVE_THUMBNAIL_HOVER" file="ntp_x_icon_hover.png" type="BINDATA" />
+ <include name="IDR_NEWTAB_REMOVE_THUMBNAIL_ACTIVE" file="ntp_x_icon_active.png" type="BINDATA" />
+ <include name="IDR_NEWTAB_CLOSED_WINDOW" file="closed_window.png" type="BINDATA" />
<include name="IDR_ARROW_RIGHT" file="arrow_right.png" type="BINDATA" />
<include name="IDR_TEXTBUTTON_TOP_LEFT_H" file="textbutton_tl_h.png" type="BINDATA" />
<include name="IDR_TEXTBUTTON_TOP_H" file="textbutton_t_h.png" type="BINDATA" />
@@ -304,7 +309,7 @@
<include name="IDR_THEME_TAB_BACKGROUND" file="theme_tab_background.png" type="BINDATA" />
<include name="IDR_THEME_TAB_BACKGROUND_INCOGNITO" file="theme_tab_background_incognito.png" type="BINDATA" />
<include name="IDR_THEME_TAB_BACKGROUND_V" file="theme_tab_background_glass.png" type="BINDATA" />
- <include name="IDR_THEME_NEWTAB_BACKGROUND" file="ntp_background.png" type="BINDATA" />
+ <include name="IDR_THEME_NTP_BACKGROUND" file="ntp_background.png" type="BINDATA" />
<if expr="pp_ifdef('_google_chrome')">
<include name="IDR_ABOUT_BACKGROUND" file="google_chrome/about_background.png" type="BINDATA" />
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index f0f36df6..b4eff3d 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -18,6 +18,7 @@ without changes to the corresponding grd file. -->
<include name="IDR_SSL_ROAD_BLOCK_HTML" file="security\resources\ssl_roadblock.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_SSL_ERROR_HTML" file="security\resources\ssl_error.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_NEW_TAB_HTML" file="resources\new_tab.html" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_NEW_TAB_THEME_CSS" file="resources\new_tab_theme.css" flattenhtml="true" type="BINDATA" />
<include name="IDR_SAFE_BROWSING_MALWARE_BLOCK" file="resources\safe_browsing_malware_block.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_SAFE_BROWSING_PHISHING_BLOCK" file="resources\safe_browsing_phishing_block.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_SAFE_BROWSING_MULTIPLE_THREAT_BLOCK" file="resources\safe_browsing_multiple_threat_block.html" flattenhtml="true" type="BINDATA" />
diff --git a/chrome/browser/browser_theme_provider.cc b/chrome/browser/browser_theme_provider.cc
index 5774f36..64124bc 100644
--- a/chrome/browser/browser_theme_provider.cc
+++ b/chrome/browser/browser_theme_provider.cc
@@ -22,29 +22,29 @@
#include "SkBitmap.h"
// Strings used by themes to identify colors for different parts of our UI.
-static const std::string kColorFrame = "frame";
-static const std::string kColorFrameInactive = "frame_inactive";
-static const std::string kColorFrameIncognito = "frame_incognito";
-static const std::string kColorFrameIncognitoInactive =
+static const char* kColorFrame = "frame";
+static const char* kColorFrameInactive = "frame_inactive";
+static const char* kColorFrameIncognito = "frame_incognito";
+static const char* kColorFrameIncognitoInactive =
"frame_incognito_inactive";
-static const std::string kColorToolbar = "toolbar";
-static const std::string kColorTabText = "tab_text";
-static const std::string kColorBackgroundTabText = "background_tab_text";
-static const std::string kColorBookmarkText = "bookmark_text";
-static const std::string kColorNTPText = "ntp_text";
-static const std::string kColorNTPLink = "ntp_link";
-static const std::string kColorNTPSection = "ntp_section";
+static const char* kColorToolbar = "toolbar";
+static const char* kColorTabText = "tab_text";
+static const char* kColorBackgroundTabText = "background_tab_text";
+static const char* kColorBookmarkText = "bookmark_text";
+static const char* kColorNTPText = "ntp_text";
+static const char* kColorNTPLink = "ntp_link";
+static const char* kColorNTPSection = "ntp_section";
// Strings used by themes to identify tints to apply to different parts of
// our UI. The frame tints apply to the frame color and produce the
// COLOR_FRAME* colors.
-static const std::string kTintButtons = "buttons";
-static const std::string kTintFrame = "frame";
-static const std::string kTintFrameInactive = "frame_inactive";
-static const std::string kTintFrameIncognito = "frame_incognito";
-static const std::string kTintFrameIncognitoInactive =
+static const char* kTintButtons = "buttons";
+static const char* kTintFrame = "frame";
+static const char* kTintFrameInactive = "frame_inactive";
+static const char* kTintFrameIncognito = "frame_incognito";
+static const char* kTintFrameIncognitoInactive =
"frame_incognito_inactive";
-static const std::string kTintBackgroundTab = "background_tab";
+static const char* kTintBackgroundTab = "background_tab";
// Default colors.
static const SkColor kDefaultColorFrame = SkColorSetRGB(77, 139, 217);
@@ -55,6 +55,10 @@ static const SkColor kDefaultColorFrameIncognitoInactive =
static const SkColor kDefaultColorToolbar = SkColorSetRGB(210, 225, 246);
static const SkColor kDefaultColorTabText = SkColorSetRGB(0, 0, 0);
static const SkColor kDefaultColorBackgroundTabText = SkColorSetRGB(64, 64, 64);
+static const SkColor kDefaultColorBookmarkText = SkColorSetRGB(64, 64, 64);
+static const SkColor kDefaultColorNTPText = SkColorSetRGB(0, 0, 0);
+static const SkColor kDefaultColorNTPLink = SkColorSetRGB(0, 0, 204);
+static const SkColor kDefaultColorNTPSection = SkColorSetRGB(225, 236, 254);
// Default tints.
static const skia::HSL kDefaultTintButtons = { -1, -1, -1 };
@@ -104,11 +108,14 @@ BrowserThemeProvider::BrowserThemeProvider()
BrowserThemeProvider::~BrowserThemeProvider() { }
void BrowserThemeProvider::Init(Profile* profile) {
+ DCHECK(CalledOnValidThread());
profile_ = profile;
LoadThemePrefs();
}
SkBitmap* BrowserThemeProvider::GetBitmapNamed(int id) {
+ DCHECK(CalledOnValidThread());
+
// Check to see if we already have the Skia image in the cache.
ImageCache::const_iterator found = image_cache_.find(id);
if (found != image_cache_.end())
@@ -128,15 +135,15 @@ SkBitmap* BrowserThemeProvider::GetBitmapNamed(int id) {
if (!result.get())
result.reset(rb_.GetBitmapNamed(id));
- // If the requested image is part of the toolbar button set, and we have
- // a provided tint for that set, tint it appropriately.
- if (button_images_.count(id) && tints_.count(kTintButtons)) {
- SkBitmap* tinted =
- new SkBitmap(TintBitmap(*result.release(), TINT_BUTTONS));
- result.reset(tinted);
- }
-
if (result.get()) {
+ // If the requested image is part of the toolbar button set, and we have
+ // a provided tint for that set, tint it appropriately.
+ if (button_images_.count(id) && tints_.count(kTintButtons)) {
+ SkBitmap* tinted =
+ new SkBitmap(TintBitmap(*result.release(), TINT_BUTTONS));
+ result.reset(tinted);
+ }
+
// We loaded successfully. Cache the bitmap.
image_cache_[id] = result.get();
return result.release();
@@ -147,6 +154,8 @@ SkBitmap* BrowserThemeProvider::GetBitmapNamed(int id) {
}
SkColor BrowserThemeProvider::GetColor(int id) {
+ DCHECK(CalledOnValidThread());
+
// TODO(glen): Figure out if we need to tint these. http://crbug.com/11578
switch (id) {
case COLOR_FRAME:
@@ -172,6 +181,22 @@ SkColor BrowserThemeProvider::GetColor(int id) {
return (colors_.find(kColorBackgroundTabText) != colors_.end()) ?
colors_[kColorBackgroundTabText] :
kDefaultColorBackgroundTabText;
+ case COLOR_BOOKMARK_TEXT:
+ return (colors_.find(kColorBookmarkText) != colors_.end()) ?
+ colors_[kColorBookmarkText] :
+ kDefaultColorBookmarkText;
+ case COLOR_NTP_TEXT:
+ return (colors_.find(kColorNTPText) != colors_.end()) ?
+ colors_[kColorNTPText] :
+ kDefaultColorNTPText;
+ case COLOR_NTP_LINK:
+ return (colors_.find(kColorNTPLink) != colors_.end()) ?
+ colors_[kColorNTPLink] :
+ kDefaultColorNTPLink;
+ case COLOR_NTP_SECTION:
+ return (colors_.find(kColorNTPSection) != colors_.end()) ?
+ colors_[kColorNTPSection] :
+ kDefaultColorNTPSection;
default:
NOTREACHED() << "Unknown color requested";
}
@@ -217,6 +242,7 @@ void BrowserThemeProvider::UseDefaultTheme() {
}
SkBitmap* BrowserThemeProvider::LoadThemeBitmap(int id) {
+ DCHECK(CalledOnValidThread());
// Attempt to find the image in our theme bundle.
std::vector<unsigned char> raw_data, png_data;
if (images_.count(id)) {
@@ -266,6 +292,7 @@ SkBitmap* BrowserThemeProvider::LoadThemeBitmap(int id) {
}
skia::HSL BrowserThemeProvider::GetTint(int id) {
+ DCHECK(CalledOnValidThread());
switch (id) {
case TINT_FRAME:
return (tints_.find(kTintFrame) != tints_.end()) ?
@@ -447,8 +474,8 @@ void BrowserThemeProvider::NotifyThemeChanged() {
// Redraw!
for (BrowserList::const_iterator browser = BrowserList::begin();
- browser != BrowserList::end(); ++browser) {
- (*browser)->window()->UserChangedTheme();
+ browser != BrowserList::end(); ++browser) {
+ (*browser)->window()->UserChangedTheme();
}
}
diff --git a/chrome/browser/browser_theme_provider.h b/chrome/browser/browser_theme_provider.h
index bf16a0d..d9996f0c 100644
--- a/chrome/browser/browser_theme_provider.h
+++ b/chrome/browser/browser_theme_provider.h
@@ -7,6 +7,7 @@
#include "app/resource_bundle.h"
#include "app/theme_provider.h"
+#include "base/non_thread_safe.h"
#include "base/ref_counted.h"
#include "skia/ext/skia_utils.h"
@@ -15,7 +16,8 @@ class Profile;
class DictionaryValue;
class BrowserThemeProvider :
- public base::RefCountedThreadSafe<BrowserThemeProvider>,
+ public base::RefCounted<BrowserThemeProvider>,
+ public NonThreadSafe,
public ThemeProvider {
public:
BrowserThemeProvider();
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_;
diff --git a/chrome/browser/resources/new_tab.html b/chrome/browser/resources/new_tab.html
index 271bc35..455cdb2 100644
--- a/chrome/browser/resources/new_tab.html
+++ b/chrome/browser/resources/new_tab.html
@@ -130,10 +130,12 @@ logEvent('log start');
<meta charset="utf-8">
<title jscontent="title"></title>
<style>
+html {
+ height:100%;
+}
body {
background-color:white;
margin:0px;
- background-image:url(chrome-ui://theme/theme_newtab_background);
background-repeat:repeat-x;
}
html[firstview='true'] #main {
@@ -157,7 +159,6 @@ form {
margin-bottom:30px;
}
.section-title {
- color:#000;
line-height:19pt;
font-size:110%;
font-weight:bold;
@@ -223,7 +224,6 @@ a.thumbnail {
padding:15px;
margin:12px;
}
-
.recent-bookmark {
display:block;
background-repeat:no-repeat;
@@ -298,12 +298,6 @@ html[dir='rtl'] #managesearcheslink {
-webkit-border-radius:5px 5px;
margin-bottom:10px;
}
-#searches {
- background-color:#e1ecfe;
-}
-#recentlyBookmarked {
- background-color:#e1ecfe;
-}
html[dir='rtl'] #recentlyBookmarkedContainer {
text-align:right;
}
@@ -358,6 +352,7 @@ html[dir='rtl'] #searches input {
pointer-events: none; /* Disable clicks */
}
</style>
+<link id="themecss" rel="stylesheet" href="chrome://theme/css/newtab.css" />
</head>
<body onload="logEvent('body onload fired');"
jsvalues=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
@@ -455,7 +450,7 @@ document.addEventListener('DOMContentLoaded', handleDOMContentLoaded);
<div id='searches-entries'></div>
</div>
- <div id="recentlyBookmarked" class="sidebar" style="display:none">
+ <div id="recentlyBookmarked" class="sidebar themed" style="display:none">
<span class="section-title" jscontent="bookmarks"></span>
<div id="recentlyBookmarkedContainer"></div>
</div>
@@ -958,6 +953,10 @@ function restoreThumbnails() {
chrome.send('clearMostVisitedURLsBlacklist');
}
+function themeChanged() {
+ $('themecss').href = 'chrome://theme/css/newtab.css?' + Date.now();
+}
+
function viewLog() {
var lines = [];
var start = log[0][1];
@@ -987,7 +986,7 @@ setTimeout(function(){document.getElementById('main').className = 'visible'},
</script>
<img id="small-cross-image" style="display: none; vertical-align:middle;" alt="X"
- src="../../app/theme/ntp_x_icon_small.png"/>
+ src="chrome://theme/newtab_remove_icon"/>
</body>
<style>
@@ -1001,16 +1000,16 @@ setTimeout(function(){document.getElementById('main').className = 'visible'},
height: 81px;
left: 60px;
top: 47px;
- background: url('../../app/theme/ntp_x_icon.png');
+ background: url(chrome://theme/newtab_remove_thumbnail);
}
.edit-mode div.edit-cross:hover {
- background: url('../../app/theme/ntp_x_icon_hover.png');
+ background: url(chrome://theme/newtab_remove_thumbnail_hover);
}
.edit-mode div.edit-cross:active {
- background: url('../../app/theme/ntp_x_icon_active.png');
+ background: url(chrome://theme/newtab_remove_thumbnail_active);
}
.recent-window-container {
- background: url('../../app/theme/closed_window.png');
+ background: url(chrome://theme/newtab_closed_window);
background-repeat: no-repeat;
}
html[dir='rtl'] .recent-window-container {
diff --git a/chrome/browser/resources/new_tab_theme.css b/chrome/browser/resources/new_tab_theme.css
new file mode 100644
index 0000000..0c28c46
--- /dev/null
+++ b/chrome/browser/resources/new_tab_theme.css
@@ -0,0 +1,11 @@
+body {
+ background-image:url(chrome://theme/theme_ntp_background?$1);
+ background-position:bottom;
+ color: $2;
+}
+a {
+ color: $3;
+}
+.sidebar.themed {
+ background-color: $4;
+} \ No newline at end of file
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 7634269..becaa93 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -2695,6 +2695,7 @@
'browser/cocoa/toolbar_view_unittest.mm',
'browser/command_updater_unittest.cc',
'browser/debugger/devtools_manager_unittest.cc',
+ 'browser/dom_ui/dom_ui_theme_source_unittest.cc',
'browser/dom_ui/dom_ui_unittest.cc',
'browser/download/download_manager_unittest.cc',
'browser/download/download_request_manager_unittest.cc',
diff --git a/chrome/test/unit/unittests.vcproj b/chrome/test/unit/unittests.vcproj
index f18b051..f161020 100644
--- a/chrome/test/unit/unittests.vcproj
+++ b/chrome/test/unit/unittests.vcproj
@@ -496,6 +496,10 @@
>
</File>
<File
+ RelativePath="..\..\browser\dom_ui\dom_ui_theme_source_unittest.cc"
+ >
+ </File>
+ <File
RelativePath="..\..\browser\dom_ui\dom_ui_unittest.cc"
>
</File>