Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(795)

Unified Diff: chrome/browser/extensions/extensions_ui.cc

Issue 360039: Fix bug where we were not displaying icons in the management (Closed)
Patch Set: update test data Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/extensions_ui.cc
diff --git a/chrome/browser/extensions/extensions_ui.cc b/chrome/browser/extensions/extensions_ui.cc
index e4ef3cf063682fece61a80a4b9505445d50ad502..0e3dc3286cf0d28f83cd2bb09d72eab191351936 100644
--- a/chrome/browser/extensions/extensions_ui.cc
+++ b/chrome/browser/extensions/extensions_ui.cc
@@ -4,8 +4,12 @@
#include "chrome/browser/extensions/extensions_ui.h"
+#include "app/gfx/codec/png_codec.h"
+#include "app/gfx/color_utils.h"
+#include "app/gfx/skbitmap_operations.h"
#include "app/l10n_util.h"
#include "app/resource_bundle.h"
+#include "base/file_util.h"
#include "base/string_util.h"
#include "base/thread.h"
#include "chrome/browser/browser.h"
@@ -31,11 +35,12 @@
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
#include "chrome/common/url_constants.h"
+#include "net/base/base64.h"
#include "net/base/net_util.h"
-
Finnur 2009/11/05 03:55:08 nit: Did you delete this line on purpose? I think
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
+#include "webkit/glue/image_decoder.h"
////////////////////////////////////////////////////////////////////////////////
//
@@ -115,6 +120,97 @@ void ExtensionsUIHTMLSource::StartDataRequest(const std::string& path,
SendResponse(request_id, html_bytes);
}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// ExtensionsDOMHandler::IconLoader
+//
+///////////////////////////////////////////////////////////////////////////////
Finnur 2009/11/05 03:55:08 nit: Add one more / to complete 80 columns. :)
+
+ExtensionsDOMHandler::IconLoader::IconLoader(ExtensionsDOMHandler* handler)
+ : handler_(handler) {
+}
+
+void ExtensionsDOMHandler::IconLoader::LoadIcons(
+ std::vector<ExtensionResource>* icons, DictionaryValue* json) {
+ ChromeThread::PostTask(
+ ChromeThread::FILE, FROM_HERE,
+ NewRunnableMethod(this,
+ &IconLoader::LoadIconsOnFileThread, icons, json));
+}
+
+void ExtensionsDOMHandler::IconLoader::Cancel() {
+ handler_ = NULL;
+}
+
+void ExtensionsDOMHandler::IconLoader::LoadIconsOnFileThread(
+ std::vector<ExtensionResource>* icons, DictionaryValue* json) {
+ scoped_ptr<std::vector<ExtensionResource> > icons_deleter(icons);
+ scoped_ptr<DictionaryValue> json_deleter(json);
+
+ ListValue* extensions = NULL;
+ CHECK(json->GetList(L"extensions", &extensions));
+
+ for (size_t i = 0; i < icons->size(); ++i) {
+ DictionaryValue* extension = NULL;
+ CHECK(extensions->GetDictionary(static_cast<int>(i), &extension));
+
+ // Read the file.
+ std::string file_contents;
+ if (icons->at(i).relative_path().empty() ||
+ !file_util::ReadFileToString(icons->at(i).GetFilePath(),
+ &file_contents)) {
+ // If there's no icon, default to the puzzle icon. This is safe to do from
+ // the file thread.
+ file_contents = ResourceBundle::GetSharedInstance().GetDataResource(
+ IDR_INFOBAR_PLUGIN_INSTALL);
+ }
+
+ // If the extension is disabled, we desaturate the icon to add to the
+ // disabledness effect.
+ bool enabled = false;
+ CHECK(extension->GetBoolean(L"enabled", &enabled));
Finnur 2009/11/05 03:55:08 nit: Why CHECK here instead of DCHECK?
+ if (!enabled) {
+ const unsigned char* data =
+ reinterpret_cast<const unsigned char*>(file_contents.data());
+ webkit_glue::ImageDecoder decoder;
+ scoped_ptr<SkBitmap> decoded(new SkBitmap());
+ *decoded = decoder.Decode(data, file_contents.length());
+
+ // Desaturate the icon and lighten it a bit.
+ color_utils::HSL shift = {-1, 0, 0.6};
+ *decoded = SkBitmapOperations::CreateHSLShiftedBitmap(*decoded, shift);
+
+ std::vector<unsigned char> output;
+ gfx::PNGCodec::EncodeBGRASkBitmap(*decoded, false, &output);
+
+ // Lame, but we must make a copy of this now, because base64 doesn't take
+ // the same input type.
+ file_contents.assign(reinterpret_cast<char*>(&output.front()),
+ output.size());
+ }
+
+ // Create a data URL (all icons are converted to PNGs during unpacking).
+ std::string base64_encoded;
+ net::Base64Encode(file_contents, &base64_encoded);
+ GURL icon_url("data:image/png;base64," + base64_encoded);
+
+ extension->SetString(L"icon", icon_url.spec());
+ }
+
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ NewRunnableMethod(this, &IconLoader::ReportResultOnUIThread,
+ json_deleter.release()));
+}
+
+void ExtensionsDOMHandler::IconLoader::ReportResultOnUIThread(
+ DictionaryValue* json) {
+ if (handler_)
+ handler_->OnIconsLoaded(json);
+}
+
+
///////////////////////////////////////////////////////////////////////////////
//
// ExtensionsDOMHandler
@@ -151,10 +247,17 @@ void ExtensionsDOMHandler::RegisterMessages() {
}
void ExtensionsDOMHandler::HandleRequestExtensionsData(const Value* value) {
- DictionaryValue results;
+ DictionaryValue* results = new DictionaryValue();
// Add the extensions to the results structure.
ListValue *extensions_list = new ListValue();
+
+ // Stores the icon resource for each of the extensions in extensions_list. We
+ // build up a list of them here, then load them on the file thread in
+ // ::LoadIcons().
+ std::vector<ExtensionResource>* extension_icons =
+ new std::vector<ExtensionResource>();
+
const ExtensionList* extensions = extensions_service_->extensions();
for (ExtensionList::const_iterator extension = extensions->begin();
extension != extensions->end(); ++extension) {
@@ -163,6 +266,7 @@ void ExtensionsDOMHandler::HandleRequestExtensionsData(const Value* value) {
if (!(*extension)->IsTheme()) {
extensions_list->Append(CreateExtensionDetailValue(
*extension, GetActivePagesForExtension((*extension)->id()), true));
+ extension_icons->push_back(PickExtensionIcon(*extension));
}
}
extensions = extensions_service_->disabled_extensions();
@@ -171,15 +275,25 @@ void ExtensionsDOMHandler::HandleRequestExtensionsData(const Value* value) {
if (!(*extension)->IsTheme()) {
extensions_list->Append(CreateExtensionDetailValue(
*extension, GetActivePagesForExtension((*extension)->id()), false));
+ extension_icons->push_back(PickExtensionIcon(*extension));
}
}
- results.Set(L"extensions", extensions_list);
+ results->Set(L"extensions", extensions_list);
bool developer_mode = dom_ui_->GetProfile()->GetPrefs()
->GetBoolean(prefs::kExtensionsUIDeveloperMode);
- results.SetBoolean(L"developerMode", developer_mode);
+ results->SetBoolean(L"developerMode", developer_mode);
- dom_ui_->CallJavascriptFunction(L"returnExtensionsData", results);
+ if (icon_loader_.get())
+ icon_loader_->Cancel();
+
+ icon_loader_ = new IconLoader(this);
+ icon_loader_->LoadIcons(extension_icons, results);
+}
+
+void ExtensionsDOMHandler::OnIconsLoaded(DictionaryValue* json) {
+ dom_ui_->CallJavascriptFunction(L"returnExtensionsData", *json);
+ delete json;
// Register for notifications that we need to reload the page.
registrar_.RemoveAll();
@@ -193,6 +307,20 @@ void ExtensionsDOMHandler::HandleRequestExtensionsData(const Value* value) {
NotificationService::AllSources());
}
+ExtensionResource ExtensionsDOMHandler::PickExtensionIcon(
+ Extension* extension) {
+ // Try to fetch the medium sized icon, then (if missing) go for the large one.
+ const std::map<int, std::string>& icons = extension->icons();
+ std::map<int, std::string>::const_iterator iter =
+ icons.find(Extension::EXTENSION_ICON_MEDIUM);
+ if (iter == icons.end())
+ iter = icons.find(Extension::EXTENSION_ICON_LARGE);
+ if (iter != icons.end())
+ return extension->GetResource(iter->second);
+ else
+ return ExtensionResource();
+}
+
void ExtensionsDOMHandler::HandleToggleDeveloperMode(const Value* value) {
bool developer_mode = dom_ui_->GetProfile()->GetPrefs()
->GetBoolean(prefs::kExtensionsUIDeveloperMode);
@@ -481,17 +609,6 @@ DictionaryValue* ExtensionsDOMHandler::CreateExtensionDetailValue(
if (!extension->options_url().is_empty())
extension_data->SetString(L"options_url", extension->options_url().spec());
- // Try to fetch the medium sized icon, then (if missing) go for the large one.
- const std::map<int, std::string>& icons = extension->icons();
- std::map<int, std::string>::const_iterator iter =
- icons.find(Extension::EXTENSION_ICON_MEDIUM);
- if (iter == icons.end())
- iter = icons.find(Extension::EXTENSION_ICON_LARGE);
- if (iter != icons.end())
- extension_data->SetString(L"icon", iter->second);
- else
- extension_data->SetString(L"icon", "");
-
// Add list of content_script detail DictionaryValues
ListValue *content_script_list = new ListValue();
UserScriptList content_scripts = extension->content_scripts();
@@ -550,6 +667,9 @@ std::vector<ExtensionPage> ExtensionsDOMHandler::GetActivePagesForExtension(
ExtensionsDOMHandler::~ExtensionsDOMHandler() {
if (pack_job_.get())
pack_job_->ClearClient();
+
+ if (icon_loader_.get())
+ icon_loader_->Cancel();
}
// ExtensionsDOMHandler, public: -----------------------------------------------

Powered by Google App Engine
This is Rietveld 408576698