Chromium Code Reviews| 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..c16f10e60c61253e0e80a158788d755730e695f0 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,81 @@ 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) { |
| + callback_ = callback; |
| + 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_)); |
| + } else { |
| + callback_ = callback; |
|
not at google - send to devlin
2015/04/22 21:38:37
You already assigned on line 166?
Devlin
2015/04/23 19:17:21
Whoops! I don't want to.
|
| + } |
| +} |
| + |
| +void ExtensionInfoGenerator::CreateExtensionsInfo( |
| + bool include_disabled, |
| + bool include_terminated, |
| + const ExtensionInfosCallback& callback) { |
| + callback_ = 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_)); |
| + } else { |
| + callback_ = callback; |
|
not at google - send to devlin
2015/04/22 21:38:37
(ditto)
Devlin
2015/04/23 19:17:21
Done.
|
| + } |
| +} |
| + |
| +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 +292,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 +421,93 @@ 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_; |
| + image_loader_->LoadImageAsync( |
| + &extension, |
| + icon, |
| + gfx::Size(128, 128), |
|
not at google - send to devlin
2015/04/22 21:38:37
Where does 128/128 come from?
Devlin
2015/04/23 19:17:21
Added a comment.
not at google - send to devlin
2015/04/23 22:25:21
I presume you meant to use max_size here.
Devlin
2015/04/27 17:06:30
Done.
|
| + 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_); |
| + } |
| } |
| } // namespace extensions |