summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-24 23:06:19 +0000
committermirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-24 23:06:19 +0000
commit7624dc623e076ad374d3fe259d98ad1525de0a0d (patch)
tree9863983099cb48145aa319787d7a9928aca1e3c6
parenta7a702c1b5283d4fad6ca02bcbcfaf13009b978e (diff)
downloadchromium_src-7624dc623e076ad374d3fe259d98ad1525de0a0d.zip
chromium_src-7624dc623e076ad374d3fe259d98ad1525de0a0d.tar.gz
chromium_src-7624dc623e076ad374d3fe259d98ad1525de0a0d.tar.bz2
Cache images on theme install so startup does no image processing.
BUG= http://crbug.com/18768 TEST= none Review URL: http://codereview.chromium.org/174085 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@24170 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/browser_theme_provider.cc219
-rw-r--r--chrome/browser/browser_theme_provider.h24
-rw-r--r--chrome/common/chrome_constants.cc1
-rw-r--r--chrome/common/chrome_constants.h1
-rw-r--r--chrome/test/data/profiles/complex_theme/Default/PreferencesTemplate13
5 files changed, 200 insertions, 58 deletions
diff --git a/chrome/browser/browser_theme_provider.cc b/chrome/browser/browser_theme_provider.cc
index f9aa52b..6021712 100644
--- a/chrome/browser/browser_theme_provider.cc
+++ b/chrome/browser/browser_theme_provider.cc
@@ -4,7 +4,9 @@
#include "chrome/browser/browser_theme_provider.h"
+#include "base/file_util.h"
#include "base/gfx/png_decoder.h"
+#include "base/gfx/png_encoder.h"
#include "base/string_util.h"
#include "base/values.h"
#include "chrome/browser/browser_list.h"
@@ -12,6 +14,7 @@
#include "chrome/browser/metrics/user_metrics.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/theme_resources_util.h"
+#include "chrome/common/chrome_constants.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
@@ -185,6 +188,35 @@ static std::map<const int, bool> themeable_images_;
// A map of frame image IDs to the tints for those ids.
static std::map<const int, int> frame_tints_;
+void BrowserThemeProvider::WriteImagesToDisk() {
+ // TODO(mirandac): move this to a different thread.
+ BrowserThemeProvider::ImageSaveCache::iterator iter;
+ for (iter = image_save_cache_.begin(); iter != image_save_cache_.end();
+ iter++) {
+ FilePath image_path = (*iter).first;
+ if ((*iter).second != NULL) {
+ SkBitmap* bitmap = (*iter).second;
+
+ std::vector<unsigned char> image_data;
+ if (!PNGEncoder::EncodeBGRASkBitmap(*bitmap, false, &image_data)) {
+ NOTREACHED() << "Image file could not be encoded.";
+ return;
+ }
+
+ const char* image_data_ptr =
+ reinterpret_cast<const char*>(&image_data[0]);
+ if (!file_util::WriteFile(image_path,
+ image_data_ptr, image_data.size())) {
+ NOTREACHED() << "Image file could not be written to disk.";
+ return;
+ }
+ } else {
+ NOTREACHED();
+ return;
+ }
+ }
+}
+
BrowserThemeProvider::BrowserThemeProvider()
: rb_(ResourceBundle::GetSharedInstance()) {
static bool initialized = false;
@@ -202,6 +234,15 @@ BrowserThemeProvider::BrowserThemeProvider()
frame_tints_[IDR_THEME_FRAME_INCOGNITO] = TINT_FRAME_INCOGNITO;
frame_tints_[IDR_THEME_FRAME_INCOGNITO_INACTIVE] =
TINT_FRAME_INCOGNITO_INACTIVE;
+
+ resource_names_[IDR_THEME_FRAME] = "theme_frame";
+ resource_names_[IDR_THEME_FRAME_INACTIVE] = "theme_frame_inactive";
+ resource_names_[IDR_THEME_FRAME_OVERLAY] = "theme_frame_overlay";
+ resource_names_[IDR_THEME_FRAME_OVERLAY_INACTIVE] =
+ "theme_frame_overlay_inactive";
+ resource_names_[IDR_THEME_FRAME_INCOGNITO] = "theme_frame_incognito";
+ resource_names_[IDR_THEME_FRAME_INCOGNITO_INACTIVE] =
+ "theme_frame_incognito_inactive";
}
}
@@ -212,6 +253,12 @@ BrowserThemeProvider::~BrowserThemeProvider() {
void BrowserThemeProvider::Init(Profile* profile) {
DCHECK(CalledOnValidThread());
profile_ = profile;
+
+ image_dir_ = profile_->GetPath().AppendASCII(
+ WideToASCII(chrome::kThemeImagesDirname));
+ if (!file_util::PathExists(image_dir_))
+ file_util::CreateDirectory(image_dir_);
+
LoadThemePrefs();
}
@@ -234,11 +281,6 @@ SkBitmap* BrowserThemeProvider::GetBitmapNamed(int id) {
// Try to load the image from the extension.
result.reset(LoadThemeBitmap(id));
- // If the extension doesn't provide the requested image, but has provided
- // a custom frame, then we may be able to generate the image required.
- if (!result.get())
- result.reset(GenerateBitmap(id));
-
// If we still don't have an image, load it from resourcebundle.
if (!result.get())
result.reset(new SkBitmap(*rb_.GetBitmapNamed(id)));
@@ -450,9 +492,13 @@ void BrowserThemeProvider::SetTheme(Extension* extension) {
SaveDisplayPropertyData();
SaveThemeID(extension->id());
+ // Process all images when we first set theme.
+ process_images_ = true;
+
GenerateFrameColors();
GenerateFrameImages();
GenerateTabImages();
+ WriteImagesToDisk();
NotifyThemeChanged();
UserMetrics::RecordAction(L"Themes_Installed", profile_);
@@ -529,6 +575,30 @@ SkBitmap* BrowserThemeProvider::LoadThemeBitmap(int id) {
}
}
+void BrowserThemeProvider::SaveThemeBitmap(
+ const std::string resource_name, int id) {
+ DCHECK(CalledOnValidThread());
+ if (!image_cache_[id]) {
+ NOTREACHED();
+ return;
+ }
+
+#if defined(OS_WIN)
+ FilePath image_path = image_dir_.Append(FilePath(UTF8ToWide(resource_name)));
+#elif defined(OS_POSIX)
+ FilePath image_path = image_dir_.Append(FilePath(resource_name));
+#endif
+
+ DictionaryValue* pref_images =
+ profile_->GetPrefs()->GetMutableDictionary(prefs::kCurrentThemeImages);
+ // TODO(mirandac): remove ToWStringHack from this class.
+ pref_images->SetString(UTF8ToWide(resource_name),
+ WideToUTF8(image_path.ToWStringHack()));
+ image_save_cache_[image_path] = image_cache_[id];
+}
+
+
+
const std::string BrowserThemeProvider::GetTintKey(int id) {
switch (id) {
case TINT_FRAME:
@@ -599,6 +669,7 @@ void BrowserThemeProvider::SetImageData(DictionaryValue* images_value,
if (!images_path.empty()) {
images_[id] = WideToUTF8(images_path.AppendASCII(val)
.ToWStringHack());
+ resource_names_[id] = WideToASCII(*iter);
} else {
images_[id] = val;
}
@@ -813,35 +884,57 @@ void BrowserThemeProvider::GenerateFrameImages() {
// the default provided frame. If that's not provided, skip this whole
// thing and just use the default images.
int base_id;
- if (id == IDR_THEME_FRAME_INCOGNITO_INACTIVE)
- base_id = (HasCustomImage(IDR_THEME_FRAME_INCOGNITO)) ?
- IDR_THEME_FRAME_INCOGNITO :
- IDR_THEME_FRAME;
- else if (id == IDR_THEME_FRAME_OVERLAY_INACTIVE)
- base_id = IDR_THEME_FRAME_OVERLAY;
- else if (id == IDR_THEME_FRAME_INACTIVE)
- base_id = IDR_THEME_FRAME;
- else if (id == IDR_THEME_FRAME_INCOGNITO &&
- !HasCustomImage(IDR_THEME_FRAME_INCOGNITO))
- base_id = IDR_THEME_FRAME;
- else
- base_id = id;
-
- if (HasCustomImage(id)) {
+ std::string resource_name;
+
+ // If we've already processed the images for this theme, they're all
+ // waiting on disk -- just load them in.
+ if (!process_images_) {
frame.reset(LoadThemeBitmap(id));
- } else if (base_id != id && HasCustomImage(base_id)) {
- frame.reset(LoadThemeBitmap(base_id));
+ if (frame.get())
+ image_cache_[id] = new SkBitmap(*frame.get());
} else {
- // If the theme doesn't specify an image, then apply the tint to
- // the default frame. Note that the default theme provides default
- // bitmaps for all frame types, so this isn't strictly necessary
- // in the case where no tint is provided either.
- frame.reset(new SkBitmap(*rb_.GetBitmapNamed(IDR_THEME_FRAME)));
- }
+ if (id == IDR_THEME_FRAME_INCOGNITO_INACTIVE) {
+ resource_name = "theme_frame_incognito_inactive";
+ base_id = HasCustomImage(IDR_THEME_FRAME_INCOGNITO) ?
+ IDR_THEME_FRAME_INCOGNITO : IDR_THEME_FRAME;
+ } else if (id == IDR_THEME_FRAME_OVERLAY_INACTIVE) {
+ base_id = IDR_THEME_FRAME_OVERLAY;
+ resource_name = "theme_frame_overlay_inactive";
+ } else if (id == IDR_THEME_FRAME_INACTIVE) {
+ base_id = IDR_THEME_FRAME;
+ resource_name = "theme_frame_inactive";
+ } else if (id == IDR_THEME_FRAME_INCOGNITO &&
+ !HasCustomImage(IDR_THEME_FRAME_INCOGNITO)) {
+ base_id = IDR_THEME_FRAME;
+ resource_name = "theme_frame_incognito";
+ } else {
+ base_id = id;
+ resource_name = resource_names_[id];
+ }
+
+ if (HasCustomImage(id)) {
+ frame.reset(LoadThemeBitmap(id));
+ } else if (base_id != id && HasCustomImage(base_id)) {
+ frame.reset(LoadThemeBitmap(base_id));
+ } else if (base_id == IDR_THEME_FRAME_OVERLAY &&
+ HasCustomImage(IDR_THEME_FRAME)) {
+ // If there is no theme overlay, don't tint the default frame,
+ // because it will overwrite the custom frame image when we cache and
+ // reload from disk.
+ frame.reset(NULL);
+ } else {
+ // If the theme doesn't specify an image, then apply the tint to
+ // the default frame. Note that the default theme provides default
+ // bitmaps for all frame types, so this isn't strictly necessary
+ // in the case where no tint is provided either.
+ frame.reset(new SkBitmap(*rb_.GetBitmapNamed(IDR_THEME_FRAME)));
+ }
- if (frame.get()) {
- SkBitmap* tinted = new SkBitmap(TintBitmap(*frame, iter->second));
- image_cache_[id] = tinted;
+ if (frame.get()) {
+ SkBitmap* tinted = new SkBitmap(TintBitmap(*frame, iter->second));
+ image_cache_[id] = tinted;
+ SaveThemeBitmap(resource_name, id);
+ }
}
++iter;
}
@@ -876,32 +969,46 @@ SkBitmap* BrowserThemeProvider::GenerateBitmap(int id) {
// tab against. As themes don't use the glass frame, we don't have to
// worry about compositing them together, as our default theme provides
// the necessary bitmaps.
- int base_id = (id == IDR_THEME_TAB_BACKGROUND) ?
- IDR_THEME_FRAME : IDR_THEME_FRAME_INCOGNITO;
-
- std::map<int, SkBitmap*>::iterator it = image_cache_.find(base_id);
- if (it != image_cache_.end()) {
- SkBitmap* frame = it->second;
- int blur_amount = (HasCustomImage(id)) ? 1 : 2;
- SkBitmap blurred =
+ if (!process_images_) {
+ scoped_ptr<SkBitmap> frame;
+ frame.reset(LoadThemeBitmap(id));
+ if (frame.get())
+ image_cache_[id] = new SkBitmap(*frame.get());
+ } else {
+ int base_id;
+ std::string resource_name;
+ if (id == IDR_THEME_TAB_BACKGROUND) {
+ base_id = IDR_THEME_FRAME;
+ resource_name = "theme_tab_background";
+ } else {
+ base_id = IDR_THEME_FRAME_INCOGNITO;
+ resource_name = "theme_tab_background_incognito";
+ }
+ std::map<int, SkBitmap*>::iterator it = image_cache_.find(base_id);
+ if (it != image_cache_.end()) {
+ SkBitmap* frame = it->second;
+ int blur_amount = HasCustomImage(id) ? 1 : 2;
+ SkBitmap blurred =
skia::ImageOperations::CreateBlurredBitmap(*frame, blur_amount);
- SkBitmap* bg_tab = new SkBitmap(TintBitmap(blurred, TINT_BACKGROUND_TAB));
-
- // If they've provided a custom image, overlay it.
- if (HasCustomImage(id)) {
- SkBitmap* overlay = LoadThemeBitmap(id);
- if (overlay) {
- SkCanvas canvas(*bg_tab);
- for (int x = 0; x < bg_tab->width(); x += overlay->width())
- canvas.drawBitmap(*overlay, static_cast<SkScalar>(x), 0, NULL);
+ SkBitmap* bg_tab = new SkBitmap(TintBitmap(blurred,
+ TINT_BACKGROUND_TAB));
+
+ // If they've provided a custom image, overlay it.
+ if (HasCustomImage(id)) {
+ SkBitmap* overlay = LoadThemeBitmap(id);
+ if (overlay) {
+ SkCanvas canvas(*bg_tab);
+ for (int x = 0; x < bg_tab->width(); x += overlay->width())
+ canvas.drawBitmap(*overlay, static_cast<SkScalar>(x), 0, NULL);
+ }
}
- }
- image_cache_[id] = bg_tab;
- return bg_tab;
+ image_cache_[id] = bg_tab;
+ SaveThemeBitmap(resource_name, id);
+ return bg_tab;
+ }
}
}
-
return NULL;
}
@@ -1009,6 +1116,9 @@ void BrowserThemeProvider::NotifyThemeChanged() {
}
void BrowserThemeProvider::LoadThemePrefs() {
+ // Images were already processed when theme was set.
+ process_images_ = false;
+
PrefService* prefs = profile_->GetPrefs();
// TODO(glen): Figure out if any custom prefs were loaded, and if so
@@ -1038,6 +1148,11 @@ void BrowserThemeProvider::ClearCaches() {
delete i->second;
}
image_cache_.clear();
+
+ // The SkBitmaps in the image_save_cache_ are a subset of those stored in
+ // the image_cache_, and have therefore all been deleted in the lines above.
+ // TODO(mirandac): make memory management clearer here.
+ image_save_cache_.clear();
}
#if defined(TOOLKIT_VIEWS)
diff --git a/chrome/browser/browser_theme_provider.h b/chrome/browser/browser_theme_provider.h
index 0b4eecb..6d81937 100644
--- a/chrome/browser/browser_theme_provider.h
+++ b/chrome/browser/browser_theme_provider.h
@@ -211,7 +211,8 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>,
void GenerateFrameColors();
// Generate any frame images that weren't specified. The resulting images
- // will be stored in our cache.
+ // will be stored in our cache and written to disk. If images have already
+ // been generated and cached, load them from disk.
void GenerateFrameImages();
// Generate any tab images that weren't specified. The resulting images
@@ -231,6 +232,9 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>,
// otherwise modified, or an application default.
virtual SkBitmap* LoadThemeBitmap(int id);
+ // Save the modified bitmap at image_cache_[id].
+ virtual void SaveThemeBitmap(const std::string resource_name, int id);
+
Profile* profile() { return profile_; }
private:
@@ -239,6 +243,7 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>,
typedef std::map<const std::string, skia::HSL> TintMap;
typedef std::map<const std::string, int> DisplayPropertyMap;
typedef std::map<const int, std::vector<unsigned char> > RawDataMap;
+ typedef std::map<const int, std::string> ResourceNameMap;
// Returns the string key for the given tint |id| TINT_* enum value.
const std::string GetTintKey(int id);
@@ -300,6 +305,9 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>,
// from ClearCaches().
void FreePlatformCaches();
+ // Encode image at image_cache_[id] as PNG and write to disk.
+ void WriteImagesToDisk();
+
#if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS)
// Loads an image and flips it horizontally if |rtl_enabled| is true.
GdkPixbuf* GetPixbufImpl(int id, bool rtl_enabled);
@@ -320,6 +328,11 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>,
NSColorMap nscolor_cache_;
#endif
+ // We save here the images to be written to disk, along with the file paths
+ // where they are to be written.
+ typedef std::map<FilePath, SkBitmap*> ImageSaveCache;
+ ImageSaveCache image_save_cache_;
+
ResourceBundle& rb_;
Profile* profile_;
@@ -329,6 +342,15 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>,
RawDataMap raw_data_;
DisplayPropertyMap display_properties_;
+ // Reverse of theme_resources_map, so we can cache images properly.
+ ResourceNameMap resource_names_;
+
+ // If true, process all images; if false, just load from disk.
+ bool process_images_;
+
+ // Where we will store our generated images.
+ FilePath image_dir_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserThemeProvider);
};
diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc
index 7f11c88..6e578c5 100644
--- a/chrome/common/chrome_constants.cc
+++ b/chrome/common/chrome_constants.cc
@@ -65,6 +65,7 @@ const FilePath::CharType kMediaCacheDirname[] = FPL("Media Cache");
const FilePath::CharType kOffTheRecordMediaCacheDirname[] =
FPL("Incognito Media Cache");
const wchar_t kChromePluginDataDirname[] = L"Plugin Data";
+const wchar_t kThemeImagesDirname[] = L"Cached Theme Images";
const FilePath::CharType kCookieFilename[] = FPL("Cookies");
const FilePath::CharType kExtensionsCookieFilename[] = FPL("Extension Cookies");
const FilePath::CharType kHistoryFilename[] = FPL("History");
diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h
index 516b7c89..9e76426 100644
--- a/chrome/common/chrome_constants.h
+++ b/chrome/common/chrome_constants.h
@@ -31,6 +31,7 @@ extern const FilePath::CharType kCacheDirname[];
extern const FilePath::CharType kMediaCacheDirname[];
extern const FilePath::CharType kOffTheRecordMediaCacheDirname[];
extern const wchar_t kChromePluginDataDirname[];
+extern const wchar_t kThemeImagesDirname[];
extern const FilePath::CharType kCookieFilename[];
extern const FilePath::CharType kExtensionsCookieFilename[];
extern const FilePath::CharType kHistoryFilename[];
diff --git a/chrome/test/data/profiles/complex_theme/Default/PreferencesTemplate b/chrome/test/data/profiles/complex_theme/Default/PreferencesTemplate
index 227f142..0297245 100644
--- a/chrome/test/data/profiles/complex_theme/Default/PreferencesTemplate
+++ b/chrome/test/data/profiles/complex_theme/Default/PreferencesTemplate
@@ -18,9 +18,6 @@
"colors": {
"bookmark_text": [ 0, 0, 0 ],
"frame": [ 57, 137, 194 ],
- "frame_inactive": [ 155, 196, 224 ],
- "frame_incognito": [ 68, 90, 106 ],
- "frame_incognito_inactive": [ 118, 156, 183 ],
"ntp_background": [ 57, 137, 194 ],
"ntp_link": [ 0, 0, 0 ],
"ntp_section": [ 131, 138, 146, 0.8 ],
@@ -34,9 +31,15 @@
"id": "mblmlcbknbnfebdfjnolmcapmdofhmme",
"images": {
"theme_button_background": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/agxjaHJvbWV0aGVtZXNyDAsSBEZpbGUYwsgCDA",
- "theme_frame": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/agxjaHJvbWV0aGVtZXNyDAsSBEZpbGUYw8gCDA",
+ "theme_frame": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/theme_frame",
+ "theme_frame_inactive": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/theme_frame_inactive",
+ "theme_frame_incognito": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/theme_frame_incognito",
+ "theme_frame_incognito_inactive": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/theme_frame_incognito_inactive",
+ "theme_frame_overlay": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/theme_frame_overlay",
+ "theme_frame_overlay_inactive": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/theme_frame_overlay_inactive",
"theme_ntp_background": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/agxjaHJvbWV0aGVtZXNyDAsSBEZpbGUYj9gCDA",
- "theme_tab_background": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/agxjaHJvbWV0aGVtZXNyDAsSBEZpbGUY_c8CDA",
+ "theme_tab_background": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/theme_tab_background",
+ "theme_tab_background_incognito": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/theme_tab_background_incognito",
"theme_toolbar": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/agxjaHJvbWV0aGVtZXNyDAsSBEZpbGUYnMgCDA",
"theme_window_control_background": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/agxjaHJvbWV0aGVtZXNyDAsSBEZpbGUYjNgCDA"
},