Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/api/developer_private/extension_info_generat or.h" | 5 #include "chrome/browser/extensions/api/developer_private/extension_info_generat or.h" |
| 6 | 6 |
| 7 #include "base/base64.h" | |
| 7 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
| 8 #include "chrome/browser/extensions/api/developer_private/inspectable_views_find er.h" | 9 #include "chrome/browser/extensions/api/developer_private/inspectable_views_find er.h" |
| 9 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" | 10 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" |
| 10 #include "chrome/browser/extensions/error_console/error_console.h" | 11 #include "chrome/browser/extensions/error_console/error_console.h" |
| 11 #include "chrome/browser/extensions/extension_service.h" | 12 #include "chrome/browser/extensions/extension_service.h" |
| 12 #include "chrome/browser/extensions/extension_ui_util.h" | 13 #include "chrome/browser/extensions/extension_ui_util.h" |
| 13 #include "chrome/browser/extensions/extension_util.h" | 14 #include "chrome/browser/extensions/extension_util.h" |
| 14 #include "chrome/browser/extensions/path_util.h" | 15 #include "chrome/browser/extensions/path_util.h" |
| 15 #include "chrome/browser/extensions/shared_module_service.h" | 16 #include "chrome/browser/extensions/shared_module_service.h" |
| 16 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
| 17 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" | 18 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" |
| 18 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" | 19 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" |
| 19 #include "chrome/grit/generated_resources.h" | 20 #include "chrome/grit/generated_resources.h" |
| 20 #include "content/public/browser/render_view_host.h" | 21 #include "content/public/browser/render_view_host.h" |
| 21 #include "extensions/browser/extension_error.h" | 22 #include "extensions/browser/extension_error.h" |
| 22 #include "extensions/browser/extension_prefs.h" | 23 #include "extensions/browser/extension_prefs.h" |
| 23 #include "extensions/browser/extension_registry.h" | 24 #include "extensions/browser/extension_registry.h" |
| 24 #include "extensions/browser/extension_system.h" | 25 #include "extensions/browser/extension_system.h" |
| 26 #include "extensions/browser/image_loader.h" | |
| 25 #include "extensions/browser/warning_service.h" | 27 #include "extensions/browser/warning_service.h" |
| 26 #include "extensions/common/extension_set.h" | 28 #include "extensions/common/extension_set.h" |
| 27 #include "extensions/common/feature_switch.h" | 29 #include "extensions/common/feature_switch.h" |
| 28 #include "extensions/common/install_warning.h" | 30 #include "extensions/common/install_warning.h" |
| 29 #include "extensions/common/manifest.h" | 31 #include "extensions/common/manifest.h" |
| 30 #include "extensions/common/manifest_handlers/background_info.h" | 32 #include "extensions/common/manifest_handlers/background_info.h" |
| 33 #include "extensions/common/manifest_handlers/icons_handler.h" | |
| 31 #include "extensions/common/manifest_handlers/offline_enabled_info.h" | 34 #include "extensions/common/manifest_handlers/offline_enabled_info.h" |
| 32 #include "extensions/common/manifest_handlers/options_page_info.h" | 35 #include "extensions/common/manifest_handlers/options_page_info.h" |
| 33 #include "extensions/common/manifest_url_handlers.h" | 36 #include "extensions/common/manifest_url_handlers.h" |
| 34 #include "extensions/common/permissions/permissions_data.h" | 37 #include "extensions/common/permissions/permissions_data.h" |
| 38 #include "extensions/grit/extensions_browser_resources.h" | |
| 35 #include "ui/base/l10n/l10n_util.h" | 39 #include "ui/base/l10n/l10n_util.h" |
| 40 #include "ui/base/resource/resource_bundle.h" | |
| 41 #include "ui/gfx/codec/png_codec.h" | |
| 42 #include "ui/gfx/color_utils.h" | |
| 43 #include "ui/gfx/image/image.h" | |
| 44 #include "ui/gfx/skbitmap_operations.h" | |
| 36 | 45 |
| 37 namespace extensions { | 46 namespace extensions { |
| 38 | 47 |
| 39 namespace developer = api::developer_private; | 48 namespace developer = api::developer_private; |
| 40 | 49 |
| 41 namespace { | 50 namespace { |
| 42 | 51 |
| 43 // Given a Manifest::Type, converts it into its developer_private | 52 // Given a Manifest::Type, converts it into its developer_private |
| 44 // counterpart. | 53 // counterpart. |
| 45 developer::ExtensionType GetExtensionType(Manifest::Type manifest_type) { | 54 developer::ExtensionType GetExtensionType(Manifest::Type manifest_type) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 135 | 144 |
| 136 } // namespace | 145 } // namespace |
| 137 | 146 |
| 138 ExtensionInfoGenerator::ExtensionInfoGenerator( | 147 ExtensionInfoGenerator::ExtensionInfoGenerator( |
| 139 content::BrowserContext* browser_context) | 148 content::BrowserContext* browser_context) |
| 140 : browser_context_(browser_context), | 149 : browser_context_(browser_context), |
| 141 extension_system_(ExtensionSystem::Get(browser_context)), | 150 extension_system_(ExtensionSystem::Get(browser_context)), |
| 142 extension_prefs_(ExtensionPrefs::Get(browser_context)), | 151 extension_prefs_(ExtensionPrefs::Get(browser_context)), |
| 143 extension_action_api_(ExtensionActionAPI::Get(browser_context)), | 152 extension_action_api_(ExtensionActionAPI::Get(browser_context)), |
| 144 warning_service_(WarningService::Get(browser_context)), | 153 warning_service_(WarningService::Get(browser_context)), |
| 145 error_console_(ErrorConsole::Get(browser_context)) { | 154 error_console_(ErrorConsole::Get(browser_context)), |
| 155 image_loader_(ImageLoader::Get(browser_context)), | |
| 156 pending_image_loads_(0u), | |
| 157 weak_factory_(this) { | |
| 146 } | 158 } |
| 147 | 159 |
| 148 ExtensionInfoGenerator::~ExtensionInfoGenerator() { | 160 ExtensionInfoGenerator::~ExtensionInfoGenerator() { |
| 149 } | 161 } |
| 150 | 162 |
| 151 scoped_ptr<developer::ExtensionInfo> | 163 void ExtensionInfoGenerator::CreateExtensionInfo( |
| 152 ExtensionInfoGenerator::CreateExtensionInfo(const Extension& extension, | 164 const std::string& id, |
| 153 developer::ExtensionState state) { | 165 const ExtensionInfosCallback& callback) { |
| 166 callback_ = callback; | |
| 167 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_); | |
| 168 | |
| 169 developer::ExtensionState state = developer::EXTENSION_STATE_NONE; | |
| 170 const Extension* ext = nullptr; | |
| 171 if ((ext = registry->enabled_extensions().GetByID(id)) != nullptr) | |
| 172 state = developer::EXTENSION_STATE_ENABLED; | |
| 173 else if ((ext = registry->disabled_extensions().GetByID(id)) != nullptr) | |
| 174 state = developer::EXTENSION_STATE_DISABLED; | |
| 175 else if ((ext = registry->terminated_extensions().GetByID(id)) != nullptr) | |
| 176 state = developer::EXTENSION_STATE_TERMINATED; | |
| 177 | |
| 178 if (ext && ui_util::ShouldDisplayInExtensionSettings(ext, browser_context_)) | |
| 179 CreateExtensionInfoHelper(*ext, state); | |
| 180 | |
| 181 if (pending_image_loads_ == 0) { | |
| 182 // Don't call the callback re-entrantly. | |
| 183 base::MessageLoop::current()->PostTask(FROM_HERE, | |
| 184 base::Bind(callback, list_)); | |
| 185 } else { | |
| 186 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.
| |
| 187 } | |
| 188 } | |
| 189 | |
| 190 void ExtensionInfoGenerator::CreateExtensionsInfo( | |
| 191 bool include_disabled, | |
| 192 bool include_terminated, | |
| 193 const ExtensionInfosCallback& callback) { | |
| 194 callback_ = callback; | |
| 195 auto add_to_list = [this](const ExtensionSet& extensions, | |
| 196 developer::ExtensionState state) { | |
| 197 for (const scoped_refptr<const Extension>& extension : extensions) { | |
| 198 if (ui_util::ShouldDisplayInExtensionSettings(extension.get(), | |
| 199 browser_context_)) { | |
| 200 CreateExtensionInfoHelper(*extension, state); | |
| 201 } | |
| 202 } | |
| 203 }; | |
| 204 | |
| 205 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_); | |
| 206 add_to_list(registry->enabled_extensions(), | |
| 207 developer::EXTENSION_STATE_ENABLED); | |
| 208 if (include_disabled) { | |
| 209 add_to_list(registry->disabled_extensions(), | |
| 210 developer::EXTENSION_STATE_DISABLED); | |
| 211 } | |
| 212 if (include_terminated) { | |
| 213 add_to_list(registry->terminated_extensions(), | |
| 214 developer::EXTENSION_STATE_TERMINATED); | |
| 215 } | |
| 216 | |
| 217 if (pending_image_loads_ == 0) { | |
| 218 // Don't call the callback re-entrantly. | |
| 219 base::MessageLoop::current()->PostTask(FROM_HERE, | |
| 220 base::Bind(callback, list_)); | |
| 221 } else { | |
| 222 callback_ = callback; | |
|
not at google - send to devlin
2015/04/22 21:38:37
(ditto)
Devlin
2015/04/23 19:17:21
Done.
| |
| 223 } | |
| 224 } | |
| 225 | |
| 226 void ExtensionInfoGenerator::CreateExtensionInfoHelper( | |
| 227 const Extension& extension, | |
| 228 developer::ExtensionState state) { | |
| 154 scoped_ptr<developer::ExtensionInfo> info(new developer::ExtensionInfo()); | 229 scoped_ptr<developer::ExtensionInfo> info(new developer::ExtensionInfo()); |
| 155 | 230 |
| 156 // Don't consider the button hidden with the redesign, because "hidden" | 231 // Don't consider the button hidden with the redesign, because "hidden" |
| 157 // buttons are now just hidden in the wrench menu. | 232 // buttons are now just hidden in the wrench menu. |
| 158 info->action_button_hidden = | 233 info->action_button_hidden = |
| 159 !extension_action_api_->GetBrowserActionVisibility(extension.id()) && | 234 !extension_action_api_->GetBrowserActionVisibility(extension.id()) && |
| 160 !FeatureSwitch::extension_action_redesign()->IsEnabled(); | 235 !FeatureSwitch::extension_action_redesign()->IsEnabled(); |
| 161 | 236 |
| 162 // Blacklist text. | 237 // Blacklist text. |
| 163 int blacklist_text = -1; | 238 int blacklist_text = -1; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 210 | 285 |
| 211 // File access. | 286 // File access. |
| 212 info->file_access.is_enabled = extension.wants_file_access(); | 287 info->file_access.is_enabled = extension.wants_file_access(); |
| 213 info->file_access.is_active = | 288 info->file_access.is_active = |
| 214 util::AllowFileAccess(extension.id(), browser_context_); | 289 util::AllowFileAccess(extension.id(), browser_context_); |
| 215 | 290 |
| 216 // Home page. | 291 // Home page. |
| 217 info->home_page.url = ManifestURL::GetHomepageURL(&extension).spec(); | 292 info->home_page.url = ManifestURL::GetHomepageURL(&extension).spec(); |
| 218 info->home_page.specified = ManifestURL::SpecifiedHomepageURL(&extension); | 293 info->home_page.specified = ManifestURL::SpecifiedHomepageURL(&extension); |
| 219 | 294 |
| 220 bool is_enabled = state == developer::EXTENSION_STATE_ENABLED; | |
| 221 | |
| 222 // TODO(devlin): This won't work with apps (CORS). We should convert to data | |
| 223 // urls. | |
| 224 info->icon_url = | |
| 225 ExtensionIconSource::GetIconURL(&extension, | |
| 226 extension_misc::EXTENSION_ICON_MEDIUM, | |
| 227 ExtensionIconSet::MATCH_BIGGER, | |
| 228 !is_enabled, | |
| 229 nullptr).spec(); | |
| 230 | |
| 231 info->id = extension.id(); | 295 info->id = extension.id(); |
| 232 | 296 |
| 233 // Incognito access. | 297 // Incognito access. |
| 234 info->incognito_access.is_enabled = extension.can_be_incognito_enabled(); | 298 info->incognito_access.is_enabled = extension.can_be_incognito_enabled(); |
| 235 info->incognito_access.is_active = | 299 info->incognito_access.is_active = |
| 236 util::IsIncognitoEnabled(extension.id(), browser_context_); | 300 util::IsIncognitoEnabled(extension.id(), browser_context_); |
| 237 | 301 |
| 238 Profile* profile = Profile::FromBrowserContext(browser_context_); | 302 Profile* profile = Profile::FromBrowserContext(browser_context_); |
| 239 info->installed_by_custodian = | 303 info->installed_by_custodian = |
| 240 util::IsExtensionSupervised(&extension, profile); | 304 util::IsExtensionSupervised(&extension, profile); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 350 | 414 |
| 351 info->type = GetExtensionType(extension.manifest()->type()); | 415 info->type = GetExtensionType(extension.manifest()->type()); |
| 352 | 416 |
| 353 info->update_url = ManifestURL::GetUpdateURL(&extension).spec(); | 417 info->update_url = ManifestURL::GetUpdateURL(&extension).spec(); |
| 354 | 418 |
| 355 info->user_may_modify = | 419 info->user_may_modify = |
| 356 management_policy->UserMayModifySettings(&extension, nullptr); | 420 management_policy->UserMayModifySettings(&extension, nullptr); |
| 357 | 421 |
| 358 info->version = extension.GetVersionForDisplay(); | 422 info->version = extension.GetVersionForDisplay(); |
| 359 | 423 |
| 424 bool is_enabled = state == developer::EXTENSION_STATE_ENABLED; | |
| 360 if (state != developer::EXTENSION_STATE_TERMINATED) { | 425 if (state != developer::EXTENSION_STATE_TERMINATED) { |
| 361 info->views = InspectableViewsFinder(profile). | 426 info->views = InspectableViewsFinder(profile). |
| 362 GetViewsForExtension(extension, is_enabled); | 427 GetViewsForExtension(extension, is_enabled); |
| 363 } | 428 } |
| 364 return info.Pass(); | 429 |
| 430 // The icon. | |
| 431 ExtensionResource icon = | |
| 432 IconsInfo::GetIconResource(&extension, | |
| 433 extension_misc::EXTENSION_ICON_MEDIUM, | |
| 434 ExtensionIconSet::MATCH_BIGGER); | |
| 435 if (icon.empty()) { | |
| 436 info->icon_url = GetDefaultIconUrl(extension.is_app(), !is_enabled); | |
| 437 list_.push_back(make_linked_ptr(info.release())); | |
| 438 } else { | |
| 439 ++pending_image_loads_; | |
| 440 image_loader_->LoadImageAsync( | |
| 441 &extension, | |
| 442 icon, | |
| 443 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.
| |
| 444 base::Bind(&ExtensionInfoGenerator::OnImageLoaded, | |
| 445 weak_factory_.GetWeakPtr(), | |
| 446 base::Passed(info.Pass()))); | |
| 447 } | |
| 365 } | 448 } |
| 366 | 449 |
| 367 scoped_ptr<api::developer_private::ExtensionInfo> | 450 const std::string& ExtensionInfoGenerator::GetDefaultIconUrl( |
| 368 ExtensionInfoGenerator::CreateExtensionInfo(const std::string& id) { | 451 bool is_app, |
| 369 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_); | 452 bool is_greyscale) { |
| 370 | 453 std::string* str; |
| 371 const Extension* enabled = registry->enabled_extensions().GetByID(id); | 454 if (is_app) { |
| 372 if (enabled && | 455 str = is_greyscale ? &default_disabled_app_icon_url_ : |
| 373 ui_util::ShouldDisplayInExtensionSettings(enabled, browser_context_)) { | 456 &default_app_icon_url_; |
| 374 return CreateExtensionInfo(*enabled, developer::EXTENSION_STATE_ENABLED); | 457 } else { |
| 458 str = is_greyscale ? &default_disabled_extension_icon_url_ : | |
| 459 &default_extension_icon_url_; | |
| 375 } | 460 } |
| 376 | 461 |
| 377 const Extension* disabled = registry->disabled_extensions().GetByID(id); | 462 if (str->empty()) { |
| 378 if (disabled && | 463 *str = GetIconUrlFromImage( |
| 379 ui_util::ShouldDisplayInExtensionSettings(disabled, browser_context_)) { | 464 ui::ResourceBundle::GetSharedInstance().GetImageNamed( |
| 380 return CreateExtensionInfo(*disabled, developer::EXTENSION_STATE_DISABLED); | 465 is_app ? IDR_APP_DEFAULT_ICON : IDR_EXTENSION_DEFAULT_ICON), |
| 466 is_greyscale); | |
| 381 } | 467 } |
| 382 | 468 |
| 383 const Extension* terminated = registry->terminated_extensions().GetByID(id); | 469 return *str; |
| 384 if (terminated && | 470 } |
| 385 ui_util::ShouldDisplayInExtensionSettings(terminated, browser_context_)) { | 471 |
| 386 return CreateExtensionInfo(*terminated, | 472 std::string ExtensionInfoGenerator::GetIconUrlFromImage( |
| 387 developer::EXTENSION_STATE_TERMINATED); | 473 const gfx::Image& image, |
| 474 bool should_greyscale) { | |
| 475 scoped_refptr<base::RefCountedMemory> data; | |
| 476 if (should_greyscale) { | |
| 477 color_utils::HSL shift = {-1, 0, 0.6}; | |
| 478 SkBitmap bitmap = | |
| 479 SkBitmapOperations::CreateHSLShiftedBitmap(*image.ToSkBitmap(), shift); | |
| 480 scoped_refptr<base::RefCountedBytes> image_bytes( | |
| 481 new base::RefCountedBytes()); | |
| 482 gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &image_bytes->data()); | |
| 483 data = image_bytes; | |
| 484 } else { | |
| 485 data = image.As1xPNGBytes(); | |
| 388 } | 486 } |
| 389 | 487 |
| 390 return scoped_ptr<api::developer_private::ExtensionInfo>(); | 488 std::string base_64; |
| 489 base::Base64Encode(std::string(data->front_as<char>(), data->size()), | |
| 490 &base_64); | |
| 491 const char kDataUrlPrefix[] = "data:image/png;base64,"; | |
| 492 return GURL(kDataUrlPrefix + base_64).spec(); | |
| 391 } | 493 } |
| 392 | 494 |
| 393 ExtensionInfoGenerator::ExtensionInfoList | 495 void ExtensionInfoGenerator::OnImageLoaded( |
| 394 ExtensionInfoGenerator::CreateExtensionsInfo(bool include_disabled, | 496 scoped_ptr<developer::ExtensionInfo> info, |
| 395 bool include_terminated) { | 497 const gfx::Image& icon) { |
| 396 std::vector<linked_ptr<developer::ExtensionInfo>> list; | 498 info->icon_url = GetIconUrlFromImage( |
| 397 auto add_to_list = [this, &list](const ExtensionSet& extensions, | 499 icon, info->state != developer::EXTENSION_STATE_ENABLED); |
| 398 developer::ExtensionState state) { | 500 list_.push_back(make_linked_ptr(info.release())); |
| 399 for (const scoped_refptr<const Extension>& extension : extensions) { | |
| 400 if (ui_util::ShouldDisplayInExtensionSettings(extension.get(), | |
| 401 browser_context_)) { | |
| 402 scoped_ptr<developer::ExtensionInfo> info = | |
| 403 CreateExtensionInfo(*extension, state); | |
| 404 list.push_back(make_linked_ptr(info.release())); | |
| 405 } | |
| 406 } | |
| 407 }; | |
| 408 | 501 |
| 409 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_); | 502 --pending_image_loads_; |
| 410 add_to_list(registry->enabled_extensions(), | 503 |
| 411 developer::EXTENSION_STATE_ENABLED); | 504 if (pending_image_loads_ == 0) { // All done! |
| 412 if (include_disabled) { | 505 // We assign to a temporary and Reset() so that at the end of the method, |
| 413 add_to_list(registry->disabled_extensions(), | 506 // any stored refs are destroyed. |
| 414 developer::EXTENSION_STATE_DISABLED); | 507 ExtensionInfosCallback callback = callback_; |
| 508 callback_.Reset(); | |
| 509 callback.Run(list_); | |
| 415 } | 510 } |
| 416 if (include_terminated) { | |
| 417 add_to_list(registry->terminated_extensions(), | |
| 418 developer::EXTENSION_STATE_TERMINATED); | |
| 419 } | |
| 420 | |
| 421 return list; | |
| 422 } | 511 } |
| 423 | 512 |
| 424 } // namespace extensions | 513 } // namespace extensions |
| OLD | NEW |