 Chromium Code Reviews
 Chromium Code Reviews Issue 989813002:
  [Extensions] Make a chrome.developerPrivate.getExtensionsInfo function  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 989813002:
  [Extensions] Make a chrome.developerPrivate.getExtensionsInfo function  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| Index: chrome/browser/extensions/api/developer_private/developer_private_api.cc | 
| diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc | 
| index b618c1d3f99aa513280dcdab105e3abd6542e017..f55160331b5f4775d4ccec4ee4736cc570c683c8 100644 | 
| --- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc | 
| +++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc | 
| @@ -9,32 +9,30 @@ | 
| #include "base/base64.h" | 
| #include "base/bind.h" | 
| #include "base/command_line.h" | 
| -#include "base/files/file_enumerator.h" | 
| #include "base/files/file_util.h" | 
| -#include "base/i18n/file_util_icu.h" | 
| #include "base/lazy_instance.h" | 
| #include "base/strings/string_number_conversions.h" | 
| #include "base/strings/stringprintf.h" | 
| #include "base/strings/utf_string_conversions.h" | 
| #include "base/values.h" | 
| #include "chrome/browser/devtools/devtools_window.h" | 
| +#include "chrome/browser/extensions/api/developer_private/developer_private_mangle.h" | 
| #include "chrome/browser/extensions/api/developer_private/entry_picker.h" | 
| +#include "chrome/browser/extensions/api/developer_private/inspectable_views_finder.h" | 
| #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" | 
| #include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h" | 
| #include "chrome/browser/extensions/chrome_requirements_checker.h" | 
| #include "chrome/browser/extensions/devtools_util.h" | 
| -#include "chrome/browser/extensions/extension_disabled_ui.h" | 
| -#include "chrome/browser/extensions/extension_error_reporter.h" | 
| #include "chrome/browser/extensions/extension_service.h" | 
| #include "chrome/browser/extensions/extension_ui_util.h" | 
| #include "chrome/browser/extensions/extension_util.h" | 
| +#include "chrome/browser/extensions/path_util.h" | 
| +#include "chrome/browser/extensions/shared_module_service.h" | 
| #include "chrome/browser/extensions/unpacked_installer.h" | 
| #include "chrome/browser/extensions/updater/extension_updater.h" | 
| #include "chrome/browser/platform_util.h" | 
| #include "chrome/browser/profiles/profile.h" | 
| -#include "chrome/browser/sync_file_system/syncable_file_system_util.h" | 
| #include "chrome/browser/ui/browser_finder.h" | 
| -#include "chrome/browser/ui/chrome_select_file_policy.h" | 
| #include "chrome/browser/ui/tabs/tab_strip_model.h" | 
| #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" | 
| #include "chrome/common/extensions/api/developer_private.h" | 
| @@ -58,10 +56,11 @@ | 
| #include "extensions/browser/file_highlighter.h" | 
| #include "extensions/browser/management_policy.h" | 
| #include "extensions/browser/notification_types.h" | 
| -#include "extensions/browser/view_type_utils.h" | 
| +#include "extensions/browser/warning_service.h" | 
| #include "extensions/common/constants.h" | 
| #include "extensions/common/extension_resource.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" | 
| @@ -74,7 +73,6 @@ | 
| #include "extensions/common/switches.h" | 
| #include "extensions/grit/extensions_browser_resources.h" | 
| #include "net/base/net_util.h" | 
| -#include "storage/browser/blob/shareable_file_reference.h" | 
| #include "storage/browser/fileapi/external_mount_points.h" | 
| #include "storage/browser/fileapi/file_system_context.h" | 
| #include "storage/browser/fileapi/file_system_operation.h" | 
| @@ -84,8 +82,6 @@ | 
| #include "ui/base/resource/resource_bundle.h" | 
| #include "ui/base/webui/web_ui_util.h" | 
| -using content::RenderViewHost; | 
| - | 
| namespace extensions { | 
| namespace developer_private = api::developer_private; | 
| @@ -157,7 +153,7 @@ GURL ToDataURL(const base::FilePath& path, developer_private::ItemType type) { | 
| return GetImageURLFromData(contents); | 
| } | 
| -std::string GetExtensionID(const RenderViewHost* render_view_host) { | 
| +std::string GetExtensionID(const content::RenderViewHost* render_view_host) { | 
| if (!render_view_host->GetSiteInstance()) | 
| return std::string(); | 
| @@ -184,6 +180,345 @@ std::string ReadFileToString(const base::FilePath& path) { | 
| return data; | 
| } | 
| +// Populates the common fields of an extension error. | 
| +void PopulateErrorBase(const ExtensionError& error, | 
| + developer::ErrorBase* base) { | 
| + base->type = error.type() == ExtensionError::MANIFEST_ERROR ? | 
| + developer::ERROR_TYPE_MANIFEST : developer::ERROR_TYPE_RUNTIME; | 
| + base->extension_id = error.extension_id(); | 
| + base->from_incognito = error.from_incognito(); | 
| + base->source = base::UTF16ToUTF8(error.source()); | 
| + base->message = base::UTF16ToUTF8(error.message()); | 
| +} | 
| + | 
| +// Given a ManifestError object, converts it into its developer_private | 
| +// counterpart. | 
| +linked_ptr<developer::ManifestError> ConstructManifestError( | 
| + const ManifestError& error) { | 
| + linked_ptr<developer::ManifestError> result(new developer::ManifestError()); | 
| + PopulateErrorBase(error, &result->base); | 
| + result->manifest_key = base::UTF16ToUTF8(error.manifest_key()); | 
| + if (!error.manifest_specific().empty()) { | 
| + result->manifest_specific.reset( | 
| + new std::string(base::UTF16ToUTF8(error.manifest_specific()))); | 
| + } | 
| + return result; | 
| +} | 
| + | 
| +// Given a RuntimeError object, converts it into its developer_private | 
| +// counterpart. | 
| +linked_ptr<developer::RuntimeError> ConstructRuntimeError( | 
| + const RuntimeError& error) { | 
| + linked_ptr<developer::RuntimeError> result(new developer::RuntimeError()); | 
| + PopulateErrorBase(error, &result->base); | 
| + switch (error.level()) { | 
| + case logging::LOG_INFO: | 
| + result->severity = developer::ERROR_SEVERITY_LOG; | 
| + break; | 
| + case logging::LOG_WARNING: | 
| + result->severity = developer::ERROR_SEVERITY_WARN; | 
| + break; | 
| + case logging::LOG_ERROR: | 
| + result->severity = developer::ERROR_SEVERITY_ERROR; | 
| + break; | 
| + default: | 
| + NOTREACHED(); | 
| + } | 
| + result->occurrences = error.occurrences(); | 
| + result->render_view_id = error.render_view_id(); | 
| + result->render_process_id = error.render_process_id(); | 
| + result->can_inspect = | 
| + content::RenderViewHost::FromID(error.render_process_id(), | 
| + error.render_view_id()) != nullptr; | 
| + for (const StackFrame& f : error.stack_trace()) { | 
| + linked_ptr<developer::StackFrame> frame(new developer::StackFrame()); | 
| + frame->line_number = f.line_number; | 
| + frame->column_number = f.column_number; | 
| + frame->source = base::UTF16ToUTF8(f.source); | 
| + frame->function = base::UTF16ToUTF8(f.function); | 
| + result->stack_trace.push_back(frame); | 
| + } | 
| + return result; | 
| +} | 
| + | 
| +// Given a Manifest::Type, converts it into its developer_private | 
| +// counterpart. | 
| +developer::ExtensionType GetExtensionType(Manifest::Type manifest_type) { | 
| + developer::ExtensionType type = developer::EXTENSION_TYPE_EXTENSION; | 
| + switch (manifest_type) { | 
| + case Manifest::TYPE_EXTENSION: | 
| + type = developer::EXTENSION_TYPE_EXTENSION; | 
| + break; | 
| + case Manifest::TYPE_THEME: | 
| + type = developer::EXTENSION_TYPE_THEME; | 
| + break; | 
| + case Manifest::TYPE_HOSTED_APP: | 
| + type = developer::EXTENSION_TYPE_HOSTED_APP; | 
| + break; | 
| + case Manifest::TYPE_LEGACY_PACKAGED_APP: | 
| + type = developer::EXTENSION_TYPE_LEGACY_PACKAGED_APP; | 
| + break; | 
| + case Manifest::TYPE_PLATFORM_APP: | 
| + type = developer::EXTENSION_TYPE_PLATFORM_APP; | 
| + break; | 
| + case Manifest::TYPE_SHARED_MODULE: | 
| + type = developer::EXTENSION_TYPE_SHARED_MODULE; | 
| + break; | 
| + default: | 
| + NOTREACHED(); | 
| + } | 
| + return type; | 
| +} | 
| + | 
| +// Constructs information about a given |extension|. | 
| +scoped_ptr<developer::ExtensionInfo> CreateExtensionInfo( | 
| + const Extension& extension, | 
| + developer::ExtensionState state, | 
| + content::BrowserContext* browser_context) { | 
| + scoped_ptr<developer::ExtensionInfo> info(new developer::ExtensionInfo()); | 
| + | 
| + ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context); | 
| + // Don't consider the button hidden with the redesign, because "hidden" | 
| + // buttons are now just hidden in the wrench menu. | 
| + info->action_button_hidden = | 
| + !ExtensionActionAPI::GetBrowserActionVisibility(prefs, extension.id()) && | 
| + !FeatureSwitch::extension_action_redesign()->IsEnabled(); | 
| + | 
| + // Blacklist text. | 
| + int blacklist_text = -1; | 
| + switch (prefs->GetExtensionBlacklistState(extension.id())) { | 
| + case BLACKLISTED_SECURITY_VULNERABILITY: | 
| + blacklist_text = IDS_OPTIONS_BLACKLISTED_SECURITY_VULNERABILITY; | 
| + break; | 
| + case BLACKLISTED_CWS_POLICY_VIOLATION: | 
| + blacklist_text = IDS_OPTIONS_BLACKLISTED_CWS_POLICY_VIOLATION; | 
| + break; | 
| + case BLACKLISTED_POTENTIALLY_UNWANTED: | 
| + blacklist_text = IDS_OPTIONS_BLACKLISTED_POTENTIALLY_UNWANTED; | 
| + break; | 
| + default: | 
| + break; | 
| + } | 
| + if (blacklist_text != -1) { | 
| + info->blacklist_text.reset( | 
| + new std::string(l10n_util::GetStringUTF8(blacklist_text))); | 
| + } | 
| + | 
| + // Dependent extensions. | 
| + if (extension.is_shared_module()) { | 
| + scoped_ptr<ExtensionSet> dependent_extensions = | 
| + ExtensionSystem::Get(browser_context)->extension_service()-> | 
| + shared_module_service()->GetDependentExtensions(&extension); | 
| + for (const scoped_refptr<const Extension>& dependent : | 
| + *dependent_extensions) | 
| + info->dependent_extensions.push_back(dependent->id()); | 
| + } | 
| + | 
| + info->description = extension.description(); | 
| + | 
| + // Disable reasons. | 
| + int disable_reasons = prefs->GetDisableReasons(extension.id()); | 
| + info->disable_reasons.suspicious_install = | 
| + (disable_reasons & Extension::DISABLE_NOT_VERIFIED) != 0; | 
| + info->disable_reasons.corrupt_install = | 
| + (disable_reasons & Extension::DISABLE_CORRUPTED) != 0; | 
| + info->disable_reasons.update_required = | 
| + (disable_reasons & Extension::DISABLE_UPDATE_REQUIRED_BY_POLICY) != 0; | 
| + | 
| + // Error collection. | 
| + Profile* profile = Profile::FromBrowserContext(browser_context); | 
| + ErrorConsole* error_console = ErrorConsole::Get(profile); | 
| + bool error_console_enabled = | 
| + error_console->IsEnabledForChromeExtensionsPage(); | 
| + info->error_collection.is_enabled = error_console_enabled; | 
| + info->error_collection.is_active = | 
| + error_console_enabled && | 
| + error_console->IsReportingEnabledForExtension(extension.id()); | 
| + | 
| + // File access. | 
| + info->file_access.is_enabled = extension.wants_file_access(); | 
| + info->file_access.is_active = | 
| + util::AllowFileAccess(extension.id(), browser_context); | 
| + | 
| + // Home page. | 
| + 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). | 
| 
not at google - send to devlin
2015/03/11 17:43:05
We should convert to data URLs.
 
Devlin
2015/03/11 21:45:53
Yep, I know. Updated the TODO to be more specific.
 | 
| + info->icon_url = | 
| + ExtensionIconSource::GetIconURL(&extension, | 
| + extension_misc::EXTENSION_ICON_MEDIUM, | 
| + ExtensionIconSet::MATCH_BIGGER, | 
| + !is_enabled, | 
| + nullptr).spec(); | 
| + | 
| + info->id = extension.id(); | 
| + | 
| + // Incognito access. | 
| + info->incognito_access.is_enabled = extension.can_be_incognito_enabled(); | 
| + info->incognito_access.is_active = | 
| + util::IsIncognitoEnabled(extension.id(), browser_context); | 
| + | 
| + info->installed_by_custodian = | 
| + util::IsExtensionSupervised(&extension, profile); | 
| + | 
| + // Install warnings (only if unpacked and no error console). | 
| + if (!error_console_enabled && | 
| + Manifest::IsUnpackedLocation(extension.location())) { | 
| + const std::vector<InstallWarning>& install_warnings = | 
| + extension.install_warnings(); | 
| + for (const InstallWarning& warning : install_warnings) | 
| + info->install_warnings.push_back(warning.message); | 
| + } | 
| + | 
| + // Launch url. | 
| + if (extension.is_app()) { | 
| + info->launch_url.reset( | 
| + new std::string(AppLaunchInfo::GetFullLaunchURL(&extension).spec())); | 
| + } | 
| + | 
| + // Location. | 
| + if (extension.location() == Manifest::INTERNAL && | 
| + ManifestURL::UpdatesFromGallery(&extension)) { | 
| + info->location = developer::LOCATION_FROM_STORE; | 
| + } else if (Manifest::IsUnpackedLocation(extension.location())) { | 
| + info->location = developer::LOCATION_UNPACKED; | 
| + } else { | 
| + info->location = developer::LOCATION_UNKNOWN; | 
| + } | 
| + | 
| + // Location text. | 
| + int location_text = -1; | 
| + if (info->location == developer::LOCATION_UNKNOWN) | 
| + location_text = IDS_OPTIONS_INSTALL_LOCATION_UNKNOWN; | 
| + else if (extension.location() == Manifest::EXTERNAL_REGISTRY) | 
| + location_text = IDS_OPTIONS_INSTALL_LOCATION_3RD_PARTY; | 
| + else if (extension.is_shared_module()) | 
| + location_text = IDS_OPTIONS_INSTALL_LOCATION_SHARED_MODULE; | 
| + if (location_text != -1) { | 
| + info->location_text.reset( | 
| + new std::string(l10n_util::GetStringUTF8(location_text))); | 
| + } | 
| + | 
| + // Runtime/Manifest errors. | 
| + if (error_console_enabled) { | 
| + const ErrorList& errors = | 
| + error_console->GetErrorsForExtension(extension.id()); | 
| + for (const ExtensionError* error : errors) { | 
| + switch (error->type()) { | 
| + case ExtensionError::MANIFEST_ERROR: | 
| + info->manifest_errors.push_back(ConstructManifestError( | 
| + static_cast<const ManifestError&>(*error))); | 
| + break; | 
| + case ExtensionError::RUNTIME_ERROR: | 
| + info->runtime_errors.push_back(ConstructRuntimeError( | 
| + static_cast<const RuntimeError&>(*error))); | 
| + break; | 
| + case ExtensionError::NUM_ERROR_TYPES: | 
| + NOTREACHED(); | 
| + break; | 
| + } | 
| + } | 
| + } | 
| + | 
| + ManagementPolicy* management_policy = | 
| + ExtensionSystem::Get(browser_context)->management_policy(); | 
| + info->must_remain_installed = | 
| + management_policy->MustRemainInstalled(&extension, nullptr); | 
| + | 
| + info->name = extension.name(); | 
| + info->offline_enabled = OfflineEnabledInfo::IsOfflineEnabled(&extension); | 
| + | 
| + // Options page. | 
| + if (OptionsPageInfo::HasOptionsPage(&extension)) { | 
| + info->options_page.reset(new developer::OptionsPage()); | 
| + info->options_page->open_in_tab = | 
| + OptionsPageInfo::ShouldOpenInTab(&extension); | 
| + info->options_page->url = | 
| + OptionsPageInfo::GetOptionsPage(&extension).spec(); | 
| + } | 
| + | 
| + // Path. | 
| + if (Manifest::IsUnpackedLocation(extension.location())) { | 
| + info->path.reset(new std::string(extension.path().AsUTF8Unsafe())); | 
| + info->prettified_path.reset(new std::string( | 
| + extensions::path_util::PrettifyPath(extension.path()).AsUTF8Unsafe())); | 
| + } | 
| + | 
| + if (Manifest::IsPolicyLocation(extension.location())) { | 
| + info->policy_text.reset(new std::string( | 
| + l10n_util::GetStringUTF8(IDS_OPTIONS_INSTALL_LOCATION_ENTERPRISE))); | 
| + } | 
| + | 
| + // Runs on all urls. | 
| + info->run_on_all_urls.is_enabled = | 
| + (FeatureSwitch::scripts_require_action()->IsEnabled() && | 
| + PermissionsData::ScriptsMayRequireActionForExtension( | 
| + &extension, | 
| + extension.permissions_data()->active_permissions().get())) || | 
| + extension.permissions_data()->HasWithheldImpliedAllHosts() || | 
| + util::HasSetAllowedScriptingOnAllUrls(extension.id(), browser_context); | 
| + info->run_on_all_urls.is_active = | 
| + util::AllowedScriptingOnAllUrls(extension.id(), browser_context); | 
| + | 
| + // Runtime warnings. | 
| + WarningService* warning_service = WarningService::Get(profile); | 
| + std::vector<std::string> warnings = | 
| + warning_service->GetWarningMessagesForExtension(extension.id()); | 
| + for (const std::string& warning : warnings) | 
| + info->runtime_warnings.push_back(warning); | 
| + | 
| + info->state = state; | 
| + | 
| + info->type = GetExtensionType(extension.manifest()->type()); | 
| + | 
| + info->update_url = ManifestURL::GetUpdateURL(&extension).spec(); | 
| + | 
| + info->user_may_modify = | 
| + management_policy->UserMayModifySettings(&extension, nullptr); | 
| + | 
| + info->version = extension.GetVersionForDisplay(); | 
| + | 
| + if (state != developer::EXTENSION_STATE_TERMINATED) { | 
| + info->views = InspectableViewsFinder(profile, nullptr). | 
| + GetViewsForExtension(extension, is_enabled); | 
| + } | 
| + return info.Pass(); | 
| +} | 
| + | 
| +std::vector<linked_ptr<developer::ExtensionInfo>> GetExtensionsInfo( | 
| + content::BrowserContext* context, | 
| + bool include_disabled, | 
| + bool include_terminated) { | 
| + std::vector<linked_ptr<developer::ExtensionInfo>> list; | 
| + auto add_to_list = [&list, context](const ExtensionSet& extensions, | 
| + developer::ExtensionState state) { | 
| + for (const scoped_refptr<const Extension>& extension : extensions) { | 
| + if (ui_util::ShouldDisplayInExtensionSettings(extension.get(), context)) { | 
| + scoped_ptr<developer::ExtensionInfo> info = | 
| + CreateExtensionInfo(*extension, state, context); | 
| + list.push_back(make_linked_ptr(info.release())); | 
| + } | 
| + } | 
| + }; | 
| + | 
| + ExtensionRegistry* registry = ExtensionRegistry::Get(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); | 
| + } | 
| + | 
| + return list; | 
| +} | 
| + | 
| } // namespace | 
| namespace AllowFileAccess = api::developer_private::AllowFileAccess; | 
| @@ -256,13 +591,13 @@ void DeveloperPrivateEventRouter::Observe( | 
| case extensions::NOTIFICATION_EXTENSION_VIEW_UNREGISTERED: { | 
| event_data.event_type = developer::EVENT_TYPE_VIEW_UNREGISTERED; | 
| event_data.item_id = GetExtensionID( | 
| - content::Details<const RenderViewHost>(details).ptr()); | 
| + content::Details<const content::RenderViewHost>(details).ptr()); | 
| break; | 
| } | 
| case extensions::NOTIFICATION_EXTENSION_VIEW_REGISTERED: { | 
| event_data.event_type = developer::EVENT_TYPE_VIEW_REGISTERED; | 
| event_data.item_id = GetExtensionID( | 
| - content::Details<const RenderViewHost>(details).ptr()); | 
| + content::Details<const content::RenderViewHost>(details).ptr()); | 
| break; | 
| } | 
| default: | 
| @@ -375,333 +710,129 @@ bool DeveloperPrivateAutoUpdateFunction::RunSync() { | 
| DeveloperPrivateAutoUpdateFunction::~DeveloperPrivateAutoUpdateFunction() {} | 
| -scoped_ptr<developer::ItemInfo> | 
| -DeveloperPrivateGetItemsInfoFunction::CreateItemInfo(const Extension& item, | 
| - bool item_is_enabled) { | 
| - scoped_ptr<developer::ItemInfo> info(new developer::ItemInfo()); | 
| - | 
| - ExtensionSystem* system = ExtensionSystem::Get(GetProfile()); | 
| - ExtensionService* service = system->extension_service(); | 
| - ExtensionRegistry* registry = ExtensionRegistry::Get(GetProfile()); | 
| - | 
| - info->id = item.id(); | 
| - info->name = item.name(); | 
| - info->enabled = service->IsExtensionEnabled(info->id); | 
| - info->offline_enabled = OfflineEnabledInfo::IsOfflineEnabled(&item); | 
| - info->version = item.VersionString(); | 
| - info->description = item.description(); | 
| - | 
| - if (item.is_app()) { | 
| - if (item.is_legacy_packaged_app()) | 
| - info->type = developer::ITEM_TYPE_LEGACY_PACKAGED_APP; | 
| - else if (item.is_hosted_app()) | 
| - info->type = developer::ITEM_TYPE_HOSTED_APP; | 
| - else if (item.is_platform_app()) | 
| - info->type = developer::ITEM_TYPE_PACKAGED_APP; | 
| - else | 
| - NOTREACHED(); | 
| - } else if (item.is_theme()) { | 
| - info->type = developer::ITEM_TYPE_THEME; | 
| - } else if (item.is_extension()) { | 
| - info->type = developer::ITEM_TYPE_EXTENSION; | 
| - } else { | 
| - NOTREACHED(); | 
| - } | 
| - | 
| - if (Manifest::IsUnpackedLocation(item.location())) { | 
| - info->path.reset( | 
| - new std::string(base::UTF16ToUTF8(item.path().LossyDisplayName()))); | 
| - // If the ErrorConsole is enabled and the extension is unpacked, use the | 
| - // more detailed errors from the ErrorConsole. Otherwise, use the install | 
| - // warnings (using both is redundant). | 
| - ErrorConsole* error_console = ErrorConsole::Get(GetProfile()); | 
| - if (error_console->IsEnabledForAppsDeveloperTools() && | 
| - item.location() == Manifest::UNPACKED) { | 
| - const ErrorList& errors = error_console->GetErrorsForExtension(item.id()); | 
| - if (!errors.empty()) { | 
| - for (ErrorList::const_iterator iter = errors.begin(); | 
| - iter != errors.end(); | 
| - ++iter) { | 
| - switch ((*iter)->type()) { | 
| - case ExtensionError::MANIFEST_ERROR: | 
| - info->manifest_errors.push_back( | 
| - make_linked_ptr((*iter)->ToValue().release())); | 
| - break; | 
| - case ExtensionError::RUNTIME_ERROR: { | 
| - const RuntimeError* error = | 
| - static_cast<const RuntimeError*>(*iter); | 
| - scoped_ptr<base::DictionaryValue> value = error->ToValue(); | 
| - bool can_inspect = content::RenderViewHost::FromID( | 
| - error->render_process_id(), | 
| - error->render_view_id()) != NULL; | 
| - value->SetBoolean("canInspect", can_inspect); | 
| - info->runtime_errors.push_back(make_linked_ptr(value.release())); | 
| - break; | 
| - } | 
| - case ExtensionError::NUM_ERROR_TYPES: | 
| - NOTREACHED(); | 
| - break; | 
| - } | 
| - } | 
| - } | 
| - } else { | 
| - for (std::vector<InstallWarning>::const_iterator it = | 
| - item.install_warnings().begin(); | 
| - it != item.install_warnings().end(); | 
| - ++it) { | 
| - scoped_ptr<developer::InstallWarning> warning( | 
| - new developer::InstallWarning); | 
| - warning->message = it->message; | 
| - info->install_warnings.push_back(make_linked_ptr(warning.release())); | 
| - } | 
| - } | 
| - } | 
| - | 
| - info->incognito_enabled = util::IsIncognitoEnabled(item.id(), GetProfile()); | 
| - info->wants_file_access = item.wants_file_access(); | 
| - info->allow_file_access = util::AllowFileAccess(item.id(), GetProfile()); | 
| - info->allow_reload = Manifest::IsUnpackedLocation(item.location()); | 
| - info->is_unpacked = Manifest::IsUnpackedLocation(item.location()); | 
| - info->terminated = registry->terminated_extensions().Contains(item.id()); | 
| - info->allow_incognito = item.can_be_incognito_enabled(); | 
| - | 
| - info->homepage_url.reset(new std::string( | 
| - ManifestURL::GetHomepageURL(&item).spec())); | 
| - if (!OptionsPageInfo::GetOptionsPage(&item).is_empty()) { | 
| - info->options_url.reset( | 
| - new std::string(OptionsPageInfo::GetOptionsPage(&item).spec())); | 
| - } | 
| - | 
| - if (!ManifestURL::GetUpdateURL(&item).is_empty()) { | 
| - info->update_url.reset( | 
| - new std::string(ManifestURL::GetUpdateURL(&item).spec())); | 
| - } | 
| - | 
| - if (item.is_app()) { | 
| - info->app_launch_url.reset( | 
| - new std::string(AppLaunchInfo::GetFullLaunchURL(&item).spec())); | 
| - } | 
| - | 
| - info->may_disable = system->management_policy()-> | 
| - UserMayModifySettings(&item, NULL); | 
| - info->is_app = item.is_app(); | 
| - info->views = GetInspectablePagesForExtension(&item, item_is_enabled); | 
| - | 
| - return info.Pass(); | 
| +DeveloperPrivateGetExtensionsInfoFunction:: | 
| +~DeveloperPrivateGetExtensionsInfoFunction() { | 
| } | 
| -void DeveloperPrivateGetItemsInfoFunction::GetIconsOnFileThread( | 
| - ItemInfoList item_list, | 
| - const std::map<std::string, ExtensionResource> idToIcon) { | 
| - for (ItemInfoList::iterator iter = item_list.begin(); | 
| - iter != item_list.end(); ++iter) { | 
| - developer_private::ItemInfo* info = iter->get(); | 
| - std::map<std::string, ExtensionResource>::const_iterator resource_ptr | 
| - = idToIcon.find(info->id); | 
| - if (resource_ptr != idToIcon.end()) { | 
| - info->icon_url = | 
| - ToDataURL(resource_ptr->second.GetFilePath(), info->type).spec(); | 
| - } | 
| +ExtensionFunction::ResponseAction | 
| +DeveloperPrivateGetExtensionsInfoFunction::Run() { | 
| + scoped_ptr<developer::GetExtensionsInfo::Params> params( | 
| + developer::GetExtensionsInfo::Params::Create(*args_)); | 
| + EXTENSION_FUNCTION_VALIDATE(params); | 
| + | 
| + bool include_disabled = true; | 
| + bool include_terminated = true; | 
| + if (params->options) { | 
| + if (params->options->include_disabled) | 
| + include_disabled = *params->options->include_disabled; | 
| + if (params->options->include_terminated) | 
| + include_terminated = *params->options->include_terminated; | 
| } | 
| - results_ = developer::GetItemsInfo::Results::Create(item_list); | 
| - content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 
| - base::Bind(&DeveloperPrivateGetItemsInfoFunction::SendResponse, | 
| - this, | 
| - true)); | 
| -} | 
| - | 
| -void DeveloperPrivateGetItemsInfoFunction:: | 
| - GetInspectablePagesForExtensionProcess( | 
| - const Extension* extension, | 
| - const std::set<content::RenderViewHost*>& views, | 
| - ItemInspectViewList* result) { | 
| - bool has_generated_background_page = | 
| - BackgroundInfo::HasGeneratedBackgroundPage(extension); | 
| - for (std::set<content::RenderViewHost*>::const_iterator iter = views.begin(); | 
| - iter != views.end(); ++iter) { | 
| - content::RenderViewHost* host = *iter; | 
| - content::WebContents* web_contents = | 
| - content::WebContents::FromRenderViewHost(host); | 
| - ViewType host_type = GetViewType(web_contents); | 
| - if (VIEW_TYPE_EXTENSION_POPUP == host_type || | 
| - VIEW_TYPE_EXTENSION_DIALOG == host_type) | 
| - continue; | 
| + std::vector<linked_ptr<developer::ExtensionInfo>> list = | 
| + GetExtensionsInfo(browser_context(), | 
| + include_disabled, | 
| + include_terminated); | 
| - content::RenderProcessHost* process = host->GetProcess(); | 
| - bool is_background_page = | 
| - (web_contents->GetURL() == BackgroundInfo::GetBackgroundURL(extension)); | 
| - result->push_back(constructInspectView( | 
| - web_contents->GetURL(), | 
| - process->GetID(), | 
| - host->GetRoutingID(), | 
| - process->GetBrowserContext()->IsOffTheRecord(), | 
| - is_background_page && has_generated_background_page)); | 
| - } | 
| + return RespondNow(ArgumentList( | 
| + developer::GetExtensionsInfo::Results::Create(list))); | 
| } | 
| -void DeveloperPrivateGetItemsInfoFunction::GetAppWindowPagesForExtensionProfile( | 
| - const Extension* extension, | 
| - ItemInspectViewList* result) { | 
| - AppWindowRegistry* registry = AppWindowRegistry::Get(GetProfile()); | 
| - if (!registry) return; | 
| - | 
| - const AppWindowRegistry::AppWindowList windows = | 
| - registry->GetAppWindowsForApp(extension->id()); | 
| - | 
| - bool has_generated_background_page = | 
| - BackgroundInfo::HasGeneratedBackgroundPage(extension); | 
| - for (AppWindowRegistry::const_iterator it = windows.begin(); | 
| - it != windows.end(); | 
| - ++it) { | 
| - content::WebContents* web_contents = (*it)->web_contents(); | 
| - RenderViewHost* host = web_contents->GetRenderViewHost(); | 
| - content::RenderProcessHost* process = host->GetProcess(); | 
| - bool is_background_page = | 
| - (web_contents->GetURL() == BackgroundInfo::GetBackgroundURL(extension)); | 
| - result->push_back(constructInspectView( | 
| - web_contents->GetURL(), | 
| - process->GetID(), | 
| - host->GetRoutingID(), | 
| - process->GetBrowserContext()->IsOffTheRecord(), | 
| - is_background_page && has_generated_background_page)); | 
| - } | 
| +DeveloperPrivateGetExtensionInfoFunction:: | 
| +~DeveloperPrivateGetExtensionInfoFunction() { | 
| } | 
| -linked_ptr<developer::ItemInspectView> DeveloperPrivateGetItemsInfoFunction:: | 
| - constructInspectView( | 
| - const GURL& url, | 
| - int render_process_id, | 
| - int render_view_id, | 
| - bool incognito, | 
| - bool generated_background_page) { | 
| - linked_ptr<developer::ItemInspectView> view(new developer::ItemInspectView()); | 
| +ExtensionFunction::ResponseAction | 
| +DeveloperPrivateGetExtensionInfoFunction::Run() { | 
| + scoped_ptr<developer::GetExtensionInfo::Params> params( | 
| + developer::GetExtensionInfo::Params::Create(*args_)); | 
| + EXTENSION_FUNCTION_VALIDATE(params); | 
| - if (url.scheme() == kExtensionScheme) { | 
| - // No leading slash. | 
| - view->path = url.path().substr(1); | 
| + ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context()); | 
| + developer::ExtensionState state = developer::EXTENSION_STATE_ENABLED; | 
| + const Extension* extension = | 
| + registry->enabled_extensions().GetByID(params->id); | 
| + if (!extension && | 
| + (extension = registry->disabled_extensions().GetByID(params->id))) { | 
| + state = developer::EXTENSION_STATE_DISABLED; | 
| + } else if (!extension && | 
| + (extension = | 
| + registry->terminated_extensions().GetByID(params->id))) { | 
| + state = developer::EXTENSION_STATE_TERMINATED; | 
| } else { | 
| - // For live pages, use the full URL. | 
| - view->path = url.spec(); | 
| - } | 
| - | 
| - view->render_process_id = render_process_id; | 
| - view->render_view_id = render_view_id; | 
| - view->incognito = incognito; | 
| - view->generated_background_page = generated_background_page; | 
| - return view; | 
| -} | 
| - | 
| -ItemInspectViewList DeveloperPrivateGetItemsInfoFunction:: | 
| - GetInspectablePagesForExtension( | 
| - const Extension* extension, | 
| - bool extension_is_enabled) { | 
| - ItemInspectViewList result; | 
| - // Get the extension process's active views. | 
| - ProcessManager* process_manager = ProcessManager::Get(GetProfile()); | 
| - GetInspectablePagesForExtensionProcess( | 
| - extension, | 
| - process_manager->GetRenderViewHostsForExtension(extension->id()), | 
| - &result); | 
| - | 
| - // Get app window views. | 
| - GetAppWindowPagesForExtensionProfile(extension, &result); | 
| - | 
| - // Include a link to start the lazy background page, if applicable. | 
| - if (BackgroundInfo::HasLazyBackgroundPage(extension) && | 
| - extension_is_enabled && | 
| - !process_manager->GetBackgroundHostForExtension(extension->id())) { | 
| - result.push_back(constructInspectView( | 
| - BackgroundInfo::GetBackgroundURL(extension), | 
| - -1, | 
| - -1, | 
| - false, | 
| - BackgroundInfo::HasGeneratedBackgroundPage(extension))); | 
| - } | 
| - | 
| - ExtensionService* service = GetExtensionService(GetProfile()); | 
| - // Repeat for the incognito process, if applicable. Don't try to get | 
| - // app windows for incognito process. | 
| - if (service->profile()->HasOffTheRecordProfile() && | 
| - IncognitoInfo::IsSplitMode(extension)) { | 
| - process_manager = | 
| - ProcessManager::Get(service->profile()->GetOffTheRecordProfile()); | 
| - GetInspectablePagesForExtensionProcess( | 
| - extension, | 
| - process_manager->GetRenderViewHostsForExtension(extension->id()), | 
| - &result); | 
| - | 
| - if (BackgroundInfo::HasLazyBackgroundPage(extension) && | 
| - extension_is_enabled && | 
| - !process_manager->GetBackgroundHostForExtension(extension->id())) { | 
| - result.push_back(constructInspectView( | 
| - BackgroundInfo::GetBackgroundURL(extension), | 
| - -1, | 
| - -1, | 
| - false, | 
| - BackgroundInfo::HasGeneratedBackgroundPage(extension))); | 
| - } | 
| + return RespondNow(Error(kNoSuchExtensionError)); | 
| } | 
| - return result; | 
| + return RespondNow(OneArgument(CreateExtensionInfo( | 
| + *extension, state, browser_context())->ToValue().release())); | 
| } | 
| -bool DeveloperPrivateGetItemsInfoFunction::RunAsync() { | 
| +DeveloperPrivateGetItemsInfoFunction::DeveloperPrivateGetItemsInfoFunction() {} | 
| +DeveloperPrivateGetItemsInfoFunction::~DeveloperPrivateGetItemsInfoFunction() {} | 
| + | 
| +ExtensionFunction::ResponseAction DeveloperPrivateGetItemsInfoFunction::Run() { | 
| scoped_ptr<developer::GetItemsInfo::Params> params( | 
| developer::GetItemsInfo::Params::Create(*args_)); | 
| - EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); | 
| - | 
| - bool include_disabled = params->include_disabled; | 
| - bool include_terminated = params->include_terminated; | 
| + EXTENSION_FUNCTION_VALIDATE(params); | 
| ExtensionSet items; | 
| - | 
| - ExtensionRegistry* registry = ExtensionRegistry::Get(GetProfile()); | 
| - | 
| + ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context()); | 
| items.InsertAll(registry->enabled_extensions()); | 
| - if (include_disabled) { | 
| + if (params->include_disabled) | 
| items.InsertAll(registry->disabled_extensions()); | 
| - } | 
| - | 
| - if (include_terminated) { | 
| + if (params->include_terminated) | 
| items.InsertAll(registry->terminated_extensions()); | 
| + | 
| + std::map<std::string, ExtensionResource> resource_map; | 
| + for (const scoped_refptr<const Extension>& item : items) { | 
| + // Don't show component extensions and invisible apps. | 
| + if (ui_util::ShouldDisplayInExtensionSettings(item.get(), | 
| + browser_context())) { | 
| + resource_map[item->id()] = | 
| + IconsInfo::GetIconResource(item.get(), | 
| + extension_misc::EXTENSION_ICON_MEDIUM, | 
| + ExtensionIconSet::MATCH_BIGGER); | 
| 
not at google - send to devlin
2015/03/11 17:43:05
All of this data population is... incredibly hard
 
Devlin
2015/03/11 21:45:53
Yeah, I had the same dilemma when writing it.
 | 
| + } | 
| } | 
| - ExtensionService* service = | 
| - ExtensionSystem::Get(GetProfile())->extension_service(); | 
| - std::map<std::string, ExtensionResource> id_to_icon; | 
| - ItemInfoList item_list; | 
| + std::vector<linked_ptr<developer::ExtensionInfo>> list = | 
| + GetExtensionsInfo(browser_context(), | 
| + params->include_disabled, | 
| + params->include_terminated); | 
| - for (ExtensionSet::const_iterator iter = items.begin(); iter != items.end(); | 
| - ++iter) { | 
| - const Extension& item = *iter->get(); | 
| + for (const linked_ptr<developer::ExtensionInfo>& info : list) | 
| + item_list_.push_back(developer_private_mangle::MangleExtensionInfo(*info)); | 
| - ExtensionResource item_resource = | 
| - IconsInfo::GetIconResource(&item, | 
| - extension_misc::EXTENSION_ICON_MEDIUM, | 
| - ExtensionIconSet::MATCH_BIGGER); | 
| - id_to_icon[item.id()] = item_resource; | 
| + content::BrowserThread::PostTask( | 
| + content::BrowserThread::FILE, | 
| + FROM_HERE, | 
| + base::Bind(&DeveloperPrivateGetItemsInfoFunction::GetIconsOnFileThread, | 
| + this, | 
| + resource_map)); | 
| - // Don't show component extensions and invisible apps. | 
| - if (ui_util::ShouldNotBeVisible(&item, GetProfile())) | 
| - continue; | 
| + return RespondLater(); | 
| +} | 
| - item_list.push_back(make_linked_ptr<developer::ItemInfo>( | 
| - CreateItemInfo( | 
| - item, service->IsExtensionEnabled(item.id())).release())); | 
| +void DeveloperPrivateGetItemsInfoFunction::GetIconsOnFileThread( | 
| + const std::map<std::string, ExtensionResource> resource_map) { | 
| + for (const linked_ptr<developer::ItemInfo>& item : item_list_) { | 
| + auto resource = resource_map.find(item->id); | 
| + if (resource != resource_map.end()) { | 
| + item->icon_url = ToDataURL(resource->second.GetFilePath(), | 
| + item->type).spec(); | 
| + } | 
| } | 
| - content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE, | 
| - base::Bind(&DeveloperPrivateGetItemsInfoFunction::GetIconsOnFileThread, | 
| - this, | 
| - item_list, | 
| - id_to_icon)); | 
| - | 
| - return true; | 
| + content::BrowserThread::PostTask( | 
| + content::BrowserThread::UI, | 
| + FROM_HERE, | 
| + base::Bind(&DeveloperPrivateGetItemsInfoFunction::Finish, this)); | 
| } | 
| -DeveloperPrivateGetItemsInfoFunction::~DeveloperPrivateGetItemsInfoFunction() {} | 
| +void DeveloperPrivateGetItemsInfoFunction::Finish() { | 
| + Respond(ArgumentList(developer::GetItemsInfo::Results::Create(item_list_))); | 
| +} | 
| ExtensionFunction::ResponseAction | 
| DeveloperPrivateAllowFileAccessFunction::Run() { |