Add ENABLE_MEDIA_ROUTER define to builds other than Android and iOS.
[chromium-blink-merge.git] / chrome / browser / extensions / api / developer_private / extension_info_generator.cc
blob0c30fd61bafae3938f0b256afbb77feef18926f5
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
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/developer_private/extension_info_generator.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/extensions/api/developer_private/inspectable_views_finder.h"
9 #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/extension_service.h"
12 #include "chrome/browser/extensions/extension_ui_util.h"
13 #include "chrome/browser/extensions/extension_util.h"
14 #include "chrome/browser/extensions/path_util.h"
15 #include "chrome/browser/extensions/shared_module_service.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
18 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
19 #include "chrome/grit/generated_resources.h"
20 #include "content/public/browser/render_view_host.h"
21 #include "extensions/browser/extension_error.h"
22 #include "extensions/browser/extension_prefs.h"
23 #include "extensions/browser/extension_registry.h"
24 #include "extensions/browser/extension_system.h"
25 #include "extensions/browser/warning_service.h"
26 #include "extensions/common/extension_set.h"
27 #include "extensions/common/feature_switch.h"
28 #include "extensions/common/install_warning.h"
29 #include "extensions/common/manifest.h"
30 #include "extensions/common/manifest_handlers/background_info.h"
31 #include "extensions/common/manifest_handlers/offline_enabled_info.h"
32 #include "extensions/common/manifest_handlers/options_page_info.h"
33 #include "extensions/common/manifest_url_handlers.h"
34 #include "extensions/common/permissions/permissions_data.h"
35 #include "ui/base/l10n/l10n_util.h"
37 namespace extensions {
39 namespace developer = api::developer_private;
41 namespace {
43 // Given a Manifest::Type, converts it into its developer_private
44 // counterpart.
45 developer::ExtensionType GetExtensionType(Manifest::Type manifest_type) {
46 developer::ExtensionType type = developer::EXTENSION_TYPE_EXTENSION;
47 switch (manifest_type) {
48 case Manifest::TYPE_EXTENSION:
49 type = developer::EXTENSION_TYPE_EXTENSION;
50 break;
51 case Manifest::TYPE_THEME:
52 type = developer::EXTENSION_TYPE_THEME;
53 break;
54 case Manifest::TYPE_HOSTED_APP:
55 type = developer::EXTENSION_TYPE_HOSTED_APP;
56 break;
57 case Manifest::TYPE_LEGACY_PACKAGED_APP:
58 type = developer::EXTENSION_TYPE_LEGACY_PACKAGED_APP;
59 break;
60 case Manifest::TYPE_PLATFORM_APP:
61 type = developer::EXTENSION_TYPE_PLATFORM_APP;
62 break;
63 case Manifest::TYPE_SHARED_MODULE:
64 type = developer::EXTENSION_TYPE_SHARED_MODULE;
65 break;
66 default:
67 NOTREACHED();
69 return type;
72 // Populates the common fields of an extension error.
73 template <typename ErrorType>
74 void PopulateErrorBase(const ExtensionError& error, ErrorType* out) {
75 CHECK(out);
76 out->type = error.type() == ExtensionError::MANIFEST_ERROR ?
77 developer::ERROR_TYPE_MANIFEST : developer::ERROR_TYPE_RUNTIME;
78 out->extension_id = error.extension_id();
79 out->from_incognito = error.from_incognito();
80 out->source = base::UTF16ToUTF8(error.source());
81 out->message = base::UTF16ToUTF8(error.message());
84 // Given a ManifestError object, converts it into its developer_private
85 // counterpart.
86 linked_ptr<developer::ManifestError> ConstructManifestError(
87 const ManifestError& error) {
88 linked_ptr<developer::ManifestError> result(new developer::ManifestError());
89 PopulateErrorBase(error, result.get());
90 result->manifest_key = base::UTF16ToUTF8(error.manifest_key());
91 if (!error.manifest_specific().empty()) {
92 result->manifest_specific.reset(
93 new std::string(base::UTF16ToUTF8(error.manifest_specific())));
95 return result;
98 // Given a RuntimeError object, converts it into its developer_private
99 // counterpart.
100 linked_ptr<developer::RuntimeError> ConstructRuntimeError(
101 const RuntimeError& error) {
102 linked_ptr<developer::RuntimeError> result(new developer::RuntimeError());
103 PopulateErrorBase(error, result.get());
104 switch (error.level()) {
105 case logging::LOG_VERBOSE:
106 case logging::LOG_INFO:
107 result->severity = developer::ERROR_LEVEL_LOG;
108 break;
109 case logging::LOG_WARNING:
110 result->severity = developer::ERROR_LEVEL_WARN;
111 break;
112 case logging::LOG_FATAL:
113 case logging::LOG_ERROR:
114 result->severity = developer::ERROR_LEVEL_ERROR;
115 break;
116 default:
117 NOTREACHED();
119 result->occurrences = error.occurrences();
120 result->render_view_id = error.render_view_id();
121 result->render_process_id = error.render_process_id();
122 result->can_inspect =
123 content::RenderViewHost::FromID(error.render_process_id(),
124 error.render_view_id()) != nullptr;
125 for (const StackFrame& f : error.stack_trace()) {
126 linked_ptr<developer::StackFrame> frame(new developer::StackFrame());
127 frame->line_number = f.line_number;
128 frame->column_number = f.column_number;
129 frame->url = base::UTF16ToUTF8(f.source);
130 frame->function_name = base::UTF16ToUTF8(f.function);
131 result->stack_trace.push_back(frame);
133 return result;
136 } // namespace
138 ExtensionInfoGenerator::ExtensionInfoGenerator(
139 content::BrowserContext* browser_context)
140 : browser_context_(browser_context),
141 extension_system_(ExtensionSystem::Get(browser_context)),
142 extension_prefs_(ExtensionPrefs::Get(browser_context)),
143 warning_service_(WarningService::Get(browser_context)),
144 error_console_(ErrorConsole::Get(browser_context)) {
147 ExtensionInfoGenerator::~ExtensionInfoGenerator() {
150 scoped_ptr<developer::ExtensionInfo>
151 ExtensionInfoGenerator::CreateExtensionInfo(const Extension& extension,
152 developer::ExtensionState state) {
153 scoped_ptr<developer::ExtensionInfo> info(new developer::ExtensionInfo());
155 // Don't consider the button hidden with the redesign, because "hidden"
156 // buttons are now just hidden in the wrench menu.
157 info->action_button_hidden =
158 !ExtensionActionAPI::GetBrowserActionVisibility(
159 extension_prefs_, extension.id()) &&
160 !FeatureSwitch::extension_action_redesign()->IsEnabled();
162 // Blacklist text.
163 int blacklist_text = -1;
164 switch (extension_prefs_->GetExtensionBlacklistState(extension.id())) {
165 case BLACKLISTED_SECURITY_VULNERABILITY:
166 blacklist_text = IDS_OPTIONS_BLACKLISTED_SECURITY_VULNERABILITY;
167 break;
168 case BLACKLISTED_CWS_POLICY_VIOLATION:
169 blacklist_text = IDS_OPTIONS_BLACKLISTED_CWS_POLICY_VIOLATION;
170 break;
171 case BLACKLISTED_POTENTIALLY_UNWANTED:
172 blacklist_text = IDS_OPTIONS_BLACKLISTED_POTENTIALLY_UNWANTED;
173 break;
174 default:
175 break;
177 if (blacklist_text != -1) {
178 info->blacklist_text.reset(
179 new std::string(l10n_util::GetStringUTF8(blacklist_text)));
182 // Dependent extensions.
183 if (extension.is_shared_module()) {
184 scoped_ptr<ExtensionSet> dependent_extensions =
185 extension_system_->extension_service()->
186 shared_module_service()->GetDependentExtensions(&extension);
187 for (const scoped_refptr<const Extension>& dependent :
188 *dependent_extensions)
189 info->dependent_extensions.push_back(dependent->id());
192 info->description = extension.description();
194 // Disable reasons.
195 int disable_reasons = extension_prefs_->GetDisableReasons(extension.id());
196 info->disable_reasons.suspicious_install =
197 (disable_reasons & Extension::DISABLE_NOT_VERIFIED) != 0;
198 info->disable_reasons.corrupt_install =
199 (disable_reasons & Extension::DISABLE_CORRUPTED) != 0;
200 info->disable_reasons.update_required =
201 (disable_reasons & Extension::DISABLE_UPDATE_REQUIRED_BY_POLICY) != 0;
203 // Error collection.
204 bool error_console_enabled =
205 error_console_->IsEnabledForChromeExtensionsPage();
206 info->error_collection.is_enabled = error_console_enabled;
207 info->error_collection.is_active =
208 error_console_enabled &&
209 error_console_->IsReportingEnabledForExtension(extension.id());
211 // File access.
212 info->file_access.is_enabled = extension.wants_file_access();
213 info->file_access.is_active =
214 util::AllowFileAccess(extension.id(), browser_context_);
216 // Home page.
217 info->home_page.url = ManifestURL::GetHomepageURL(&extension).spec();
218 info->home_page.specified = ManifestURL::SpecifiedHomepageURL(&extension);
220 bool is_enabled = state == developer::EXTENSION_STATE_ENABLED;
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();
231 info->id = extension.id();
233 // Incognito access.
234 info->incognito_access.is_enabled = extension.can_be_incognito_enabled();
235 info->incognito_access.is_active =
236 util::IsIncognitoEnabled(extension.id(), browser_context_);
238 Profile* profile = Profile::FromBrowserContext(browser_context_);
239 info->installed_by_custodian =
240 util::IsExtensionSupervised(&extension, profile);
242 // Install warnings (only if unpacked and no error console).
243 if (!error_console_enabled &&
244 Manifest::IsUnpackedLocation(extension.location())) {
245 const std::vector<InstallWarning>& install_warnings =
246 extension.install_warnings();
247 for (const InstallWarning& warning : install_warnings)
248 info->install_warnings.push_back(warning.message);
251 // Launch url.
252 if (extension.is_app()) {
253 info->launch_url.reset(
254 new std::string(AppLaunchInfo::GetFullLaunchURL(&extension).spec()));
257 // Location.
258 if (extension.location() == Manifest::INTERNAL &&
259 ManifestURL::UpdatesFromGallery(&extension)) {
260 info->location = developer::LOCATION_FROM_STORE;
261 } else if (Manifest::IsUnpackedLocation(extension.location())) {
262 info->location = developer::LOCATION_UNPACKED;
263 } else if (Manifest::IsExternalLocation(extension.location()) &&
264 ManifestURL::UpdatesFromGallery(&extension)) {
265 info->location = developer::LOCATION_THIRD_PARTY;
266 } else {
267 info->location = developer::LOCATION_UNKNOWN;
270 // Location text.
271 int location_text = -1;
272 if (info->location == developer::LOCATION_UNKNOWN)
273 location_text = IDS_OPTIONS_INSTALL_LOCATION_UNKNOWN;
274 else if (extension.location() == Manifest::EXTERNAL_REGISTRY)
275 location_text = IDS_OPTIONS_INSTALL_LOCATION_3RD_PARTY;
276 else if (extension.is_shared_module())
277 location_text = IDS_OPTIONS_INSTALL_LOCATION_SHARED_MODULE;
278 if (location_text != -1) {
279 info->location_text.reset(
280 new std::string(l10n_util::GetStringUTF8(location_text)));
283 // Runtime/Manifest errors.
284 if (error_console_enabled) {
285 const ErrorList& errors =
286 error_console_->GetErrorsForExtension(extension.id());
287 for (const ExtensionError* error : errors) {
288 switch (error->type()) {
289 case ExtensionError::MANIFEST_ERROR:
290 info->manifest_errors.push_back(ConstructManifestError(
291 static_cast<const ManifestError&>(*error)));
292 break;
293 case ExtensionError::RUNTIME_ERROR:
294 info->runtime_errors.push_back(ConstructRuntimeError(
295 static_cast<const RuntimeError&>(*error)));
296 break;
297 case ExtensionError::NUM_ERROR_TYPES:
298 NOTREACHED();
299 break;
304 ManagementPolicy* management_policy = extension_system_->management_policy();
305 info->must_remain_installed =
306 management_policy->MustRemainInstalled(&extension, nullptr);
308 info->name = extension.name();
309 info->offline_enabled = OfflineEnabledInfo::IsOfflineEnabled(&extension);
311 // Options page.
312 if (OptionsPageInfo::HasOptionsPage(&extension)) {
313 info->options_page.reset(new developer::OptionsPage());
314 info->options_page->open_in_tab =
315 OptionsPageInfo::ShouldOpenInTab(&extension);
316 info->options_page->url =
317 OptionsPageInfo::GetOptionsPage(&extension).spec();
320 // Path.
321 if (Manifest::IsUnpackedLocation(extension.location())) {
322 info->path.reset(new std::string(extension.path().AsUTF8Unsafe()));
323 info->prettified_path.reset(new std::string(
324 extensions::path_util::PrettifyPath(extension.path()).AsUTF8Unsafe()));
327 if (Manifest::IsPolicyLocation(extension.location())) {
328 info->policy_text.reset(new std::string(
329 l10n_util::GetStringUTF8(IDS_OPTIONS_INSTALL_LOCATION_ENTERPRISE)));
332 // Runs on all urls.
333 info->run_on_all_urls.is_enabled =
334 (FeatureSwitch::scripts_require_action()->IsEnabled() &&
335 PermissionsData::ScriptsMayRequireActionForExtension(
336 &extension,
337 extension.permissions_data()->active_permissions().get())) ||
338 extension.permissions_data()->HasWithheldImpliedAllHosts() ||
339 util::HasSetAllowedScriptingOnAllUrls(extension.id(), browser_context_);
340 info->run_on_all_urls.is_active =
341 util::AllowedScriptingOnAllUrls(extension.id(), browser_context_);
343 // Runtime warnings.
344 std::vector<std::string> warnings =
345 warning_service_->GetWarningMessagesForExtension(extension.id());
346 for (const std::string& warning : warnings)
347 info->runtime_warnings.push_back(warning);
349 info->state = state;
351 info->type = GetExtensionType(extension.manifest()->type());
353 info->update_url = ManifestURL::GetUpdateURL(&extension).spec();
355 info->user_may_modify =
356 management_policy->UserMayModifySettings(&extension, nullptr);
358 info->version = extension.GetVersionForDisplay();
360 if (state != developer::EXTENSION_STATE_TERMINATED) {
361 info->views = InspectableViewsFinder(profile, nullptr).
362 GetViewsForExtension(extension, is_enabled);
364 return info.Pass();
367 scoped_ptr<api::developer_private::ExtensionInfo>
368 ExtensionInfoGenerator::CreateExtensionInfo(const std::string& id) {
369 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
371 const Extension* enabled = registry->enabled_extensions().GetByID(id);
372 if (enabled &&
373 ui_util::ShouldDisplayInExtensionSettings(enabled, browser_context_)) {
374 return CreateExtensionInfo(*enabled, developer::EXTENSION_STATE_ENABLED);
377 const Extension* disabled = registry->disabled_extensions().GetByID(id);
378 if (disabled &&
379 ui_util::ShouldDisplayInExtensionSettings(disabled, browser_context_)) {
380 return CreateExtensionInfo(*disabled, developer::EXTENSION_STATE_DISABLED);
383 const Extension* terminated = registry->terminated_extensions().GetByID(id);
384 if (terminated &&
385 ui_util::ShouldDisplayInExtensionSettings(terminated, browser_context_)) {
386 return CreateExtensionInfo(*terminated,
387 developer::EXTENSION_STATE_TERMINATED);
390 return scoped_ptr<api::developer_private::ExtensionInfo>();
393 ExtensionInfoGenerator::ExtensionInfoList
394 ExtensionInfoGenerator::CreateExtensionsInfo(bool include_disabled,
395 bool include_terminated) {
396 std::vector<linked_ptr<developer::ExtensionInfo>> list;
397 auto add_to_list = [this, &list](const ExtensionSet& extensions,
398 developer::ExtensionState state) {
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()));
409 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
410 add_to_list(registry->enabled_extensions(),
411 developer::EXTENSION_STATE_ENABLED);
412 if (include_disabled) {
413 add_to_list(registry->disabled_extensions(),
414 developer::EXTENSION_STATE_DISABLED);
416 if (include_terminated) {
417 add_to_list(registry->terminated_extensions(),
418 developer::EXTENSION_STATE_TERMINATED);
421 return list;
424 } // namespace extensions