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

Unified Diff: chrome/browser/extensions/api/developer_private/extension_info_generator.cc

Issue 1092953004: [Extensions] Update developerPrivate API to use base-64 data urls for icons (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Latest master Created 5 years, 8 months 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/api/developer_private/extension_info_generator.cc
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
index 9ac1c437bb94dda7831f2e83e532ffccd3081125..fd91759ec21c43cfb965ff5b1b490047d011d50b 100644
--- a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
+++ b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/extensions/api/developer_private/extension_info_generator.h"
+#include "base/base64.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/api/developer_private/inspectable_views_finder.h"
#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
@@ -22,17 +23,25 @@
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
+#include "extensions/browser/image_loader.h"
#include "extensions/browser/warning_service.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/feature_switch.h"
#include "extensions/common/install_warning.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_handlers/background_info.h"
+#include "extensions/common/manifest_handlers/icons_handler.h"
#include "extensions/common/manifest_handlers/offline_enabled_info.h"
#include "extensions/common/manifest_handlers/options_page_info.h"
#include "extensions/common/manifest_url_handlers.h"
#include "extensions/common/permissions/permissions_data.h"
+#include "extensions/grit/extensions_browser_resources.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/image/image.h"
+#include "ui/gfx/skbitmap_operations.h"
namespace extensions {
@@ -142,15 +151,83 @@ ExtensionInfoGenerator::ExtensionInfoGenerator(
extension_prefs_(ExtensionPrefs::Get(browser_context)),
extension_action_api_(ExtensionActionAPI::Get(browser_context)),
warning_service_(WarningService::Get(browser_context)),
- error_console_(ErrorConsole::Get(browser_context)) {
+ error_console_(ErrorConsole::Get(browser_context)),
+ image_loader_(ImageLoader::Get(browser_context)),
+ pending_image_loads_(0u),
+ weak_factory_(this) {
}
ExtensionInfoGenerator::~ExtensionInfoGenerator() {
}
-scoped_ptr<developer::ExtensionInfo>
-ExtensionInfoGenerator::CreateExtensionInfo(const Extension& extension,
- developer::ExtensionState state) {
+void ExtensionInfoGenerator::CreateExtensionInfo(
+ const std::string& id,
+ const ExtensionInfosCallback& callback) {
+ DCHECK(callback_.is_null() && list_.empty()) <<
+ "Only a single generation can be running at a time!";
+ ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
+
+ developer::ExtensionState state = developer::EXTENSION_STATE_NONE;
+ const Extension* ext = nullptr;
+ if ((ext = registry->enabled_extensions().GetByID(id)) != nullptr)
+ state = developer::EXTENSION_STATE_ENABLED;
+ else if ((ext = registry->disabled_extensions().GetByID(id)) != nullptr)
+ state = developer::EXTENSION_STATE_DISABLED;
+ else if ((ext = registry->terminated_extensions().GetByID(id)) != nullptr)
+ state = developer::EXTENSION_STATE_TERMINATED;
+
+ if (ext && ui_util::ShouldDisplayInExtensionSettings(ext, browser_context_))
+ CreateExtensionInfoHelper(*ext, state);
+
+ if (pending_image_loads_ == 0) {
+ // Don't call the callback re-entrantly.
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(callback, list_));
+ list_.clear();
+ } else {
+ callback_ = callback;
+ }
+}
+
+void ExtensionInfoGenerator::CreateExtensionsInfo(
+ bool include_disabled,
+ bool include_terminated,
+ const ExtensionInfosCallback& callback) {
+ auto add_to_list = [this](const ExtensionSet& extensions,
+ developer::ExtensionState state) {
+ for (const scoped_refptr<const Extension>& extension : extensions) {
+ if (ui_util::ShouldDisplayInExtensionSettings(extension.get(),
+ browser_context_)) {
+ CreateExtensionInfoHelper(*extension, state);
+ }
+ }
+ };
+
+ ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
+ add_to_list(registry->enabled_extensions(),
+ developer::EXTENSION_STATE_ENABLED);
+ if (include_disabled) {
+ add_to_list(registry->disabled_extensions(),
+ developer::EXTENSION_STATE_DISABLED);
+ }
+ if (include_terminated) {
+ add_to_list(registry->terminated_extensions(),
+ developer::EXTENSION_STATE_TERMINATED);
+ }
+
+ if (pending_image_loads_ == 0) {
+ // Don't call the callback re-entrantly.
+ base::MessageLoop::current()->PostTask(FROM_HERE,
+ base::Bind(callback, list_));
+ list_.clear();
+ } else {
+ callback_ = callback;
+ }
+}
+
+void ExtensionInfoGenerator::CreateExtensionInfoHelper(
+ const Extension& extension,
+ developer::ExtensionState state) {
scoped_ptr<developer::ExtensionInfo> info(new developer::ExtensionInfo());
// Don't consider the button hidden with the redesign, because "hidden"
@@ -217,17 +294,6 @@ ExtensionInfoGenerator::CreateExtensionInfo(const Extension& extension,
info->home_page.url = ManifestURL::GetHomepageURL(&extension).spec();
info->home_page.specified = ManifestURL::SpecifiedHomepageURL(&extension);
- bool is_enabled = state == developer::EXTENSION_STATE_ENABLED;
-
- // TODO(devlin): This won't work with apps (CORS). We should convert to data
- // urls.
- info->icon_url =
- ExtensionIconSource::GetIconURL(&extension,
- extension_misc::EXTENSION_ICON_MEDIUM,
- ExtensionIconSet::MATCH_BIGGER,
- !is_enabled,
- nullptr).spec();
-
info->id = extension.id();
// Incognito access.
@@ -357,68 +423,98 @@ ExtensionInfoGenerator::CreateExtensionInfo(const Extension& extension,
info->version = extension.GetVersionForDisplay();
+ bool is_enabled = state == developer::EXTENSION_STATE_ENABLED;
if (state != developer::EXTENSION_STATE_TERMINATED) {
info->views = InspectableViewsFinder(profile).
GetViewsForExtension(extension, is_enabled);
}
- return info.Pass();
-}
-scoped_ptr<api::developer_private::ExtensionInfo>
-ExtensionInfoGenerator::CreateExtensionInfo(const std::string& id) {
- ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
-
- const Extension* enabled = registry->enabled_extensions().GetByID(id);
- if (enabled &&
- ui_util::ShouldDisplayInExtensionSettings(enabled, browser_context_)) {
- return CreateExtensionInfo(*enabled, developer::EXTENSION_STATE_ENABLED);
+ // The icon.
+ ExtensionResource icon =
+ IconsInfo::GetIconResource(&extension,
+ extension_misc::EXTENSION_ICON_MEDIUM,
+ ExtensionIconSet::MATCH_BIGGER);
+ if (icon.empty()) {
+ info->icon_url = GetDefaultIconUrl(extension.is_app(), !is_enabled);
+ list_.push_back(make_linked_ptr(info.release()));
+ } else {
+ ++pending_image_loads_;
+ // Max size of 128x128 is a random guess at a nice balance between being
+ // overly eager to resize and sending across gigantic data urls. (The icon
+ // used by the url is 48x48).
+ gfx::Size max_size(128, 128);
+ image_loader_->LoadImageAsync(
+ &extension,
+ icon,
+ max_size,
+ base::Bind(&ExtensionInfoGenerator::OnImageLoaded,
+ weak_factory_.GetWeakPtr(),
+ base::Passed(info.Pass())));
}
+}
- const Extension* disabled = registry->disabled_extensions().GetByID(id);
- if (disabled &&
- ui_util::ShouldDisplayInExtensionSettings(disabled, browser_context_)) {
- return CreateExtensionInfo(*disabled, developer::EXTENSION_STATE_DISABLED);
+const std::string& ExtensionInfoGenerator::GetDefaultIconUrl(
+ bool is_app,
+ bool is_greyscale) {
+ std::string* str;
+ if (is_app) {
+ str = is_greyscale ? &default_disabled_app_icon_url_ :
+ &default_app_icon_url_;
+ } else {
+ str = is_greyscale ? &default_disabled_extension_icon_url_ :
+ &default_extension_icon_url_;
}
- const Extension* terminated = registry->terminated_extensions().GetByID(id);
- if (terminated &&
- ui_util::ShouldDisplayInExtensionSettings(terminated, browser_context_)) {
- return CreateExtensionInfo(*terminated,
- developer::EXTENSION_STATE_TERMINATED);
+ if (str->empty()) {
+ *str = GetIconUrlFromImage(
+ ui::ResourceBundle::GetSharedInstance().GetImageNamed(
+ is_app ? IDR_APP_DEFAULT_ICON : IDR_EXTENSION_DEFAULT_ICON),
+ is_greyscale);
}
- return scoped_ptr<api::developer_private::ExtensionInfo>();
+ return *str;
}
-ExtensionInfoGenerator::ExtensionInfoList
-ExtensionInfoGenerator::CreateExtensionsInfo(bool include_disabled,
- bool include_terminated) {
- std::vector<linked_ptr<developer::ExtensionInfo>> list;
- auto add_to_list = [this, &list](const ExtensionSet& extensions,
- developer::ExtensionState state) {
- for (const scoped_refptr<const Extension>& extension : extensions) {
- if (ui_util::ShouldDisplayInExtensionSettings(extension.get(),
- browser_context_)) {
- scoped_ptr<developer::ExtensionInfo> info =
- CreateExtensionInfo(*extension, state);
- list.push_back(make_linked_ptr(info.release()));
- }
- }
- };
-
- ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
- add_to_list(registry->enabled_extensions(),
- developer::EXTENSION_STATE_ENABLED);
- if (include_disabled) {
- add_to_list(registry->disabled_extensions(),
- developer::EXTENSION_STATE_DISABLED);
- }
- if (include_terminated) {
- add_to_list(registry->terminated_extensions(),
- developer::EXTENSION_STATE_TERMINATED);
+std::string ExtensionInfoGenerator::GetIconUrlFromImage(
+ const gfx::Image& image,
+ bool should_greyscale) {
+ scoped_refptr<base::RefCountedMemory> data;
+ if (should_greyscale) {
+ color_utils::HSL shift = {-1, 0, 0.6};
+ SkBitmap bitmap =
+ SkBitmapOperations::CreateHSLShiftedBitmap(*image.ToSkBitmap(), shift);
+ scoped_refptr<base::RefCountedBytes> image_bytes(
+ new base::RefCountedBytes());
+ gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &image_bytes->data());
+ data = image_bytes;
+ } else {
+ data = image.As1xPNGBytes();
}
- return list;
+ std::string base_64;
+ base::Base64Encode(std::string(data->front_as<char>(), data->size()),
+ &base_64);
+ const char kDataUrlPrefix[] = "data:image/png;base64,";
+ return GURL(kDataUrlPrefix + base_64).spec();
+}
+
+void ExtensionInfoGenerator::OnImageLoaded(
+ scoped_ptr<developer::ExtensionInfo> info,
+ const gfx::Image& icon) {
+ info->icon_url = GetIconUrlFromImage(
+ icon, info->state != developer::EXTENSION_STATE_ENABLED);
+ list_.push_back(make_linked_ptr(info.release()));
+
+ --pending_image_loads_;
+
+ if (pending_image_loads_ == 0) { // All done!
+ // We assign to a temporary and Reset() so that at the end of the method,
+ // any stored refs are destroyed.
+ ExtensionInfosCallback callback = callback_;
+ callback_.Reset();
+ callback.Run(list_);
+ list_.clear();
+ }
}
} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698