1 // Copyright (c) 2012 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/ui/webui/extensions/extension_settings_handler.h"
7 #include "apps/app_load_service.h"
8 #include "apps/saved_files_service.h"
9 #include "base/auto_reset.h"
10 #include "base/base64.h"
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/location.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/metrics/histogram.h"
16 #include "base/prefs/pref_service.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/values.h"
21 #include "base/version.h"
22 #include "chrome/browser/background/background_contents.h"
23 #include "chrome/browser/browser_process.h"
24 #include "chrome/browser/chrome_notification_types.h"
25 #include "chrome/browser/devtools/devtools_window.h"
26 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
27 #include "chrome/browser/extensions/component_loader.h"
28 #include "chrome/browser/extensions/crx_installer.h"
29 #include "chrome/browser/extensions/devtools_util.h"
30 #include "chrome/browser/extensions/error_console/error_console.h"
31 #include "chrome/browser/extensions/extension_action_manager.h"
32 #include "chrome/browser/extensions/extension_error_reporter.h"
33 #include "chrome/browser/extensions/extension_management.h"
34 #include "chrome/browser/extensions/extension_service.h"
35 #include "chrome/browser/extensions/extension_tab_util.h"
36 #include "chrome/browser/extensions/extension_ui_util.h"
37 #include "chrome/browser/extensions/extension_util.h"
38 #include "chrome/browser/extensions/install_verifier.h"
39 #include "chrome/browser/extensions/path_util.h"
40 #include "chrome/browser/extensions/shared_module_service.h"
41 #include "chrome/browser/extensions/updater/extension_updater.h"
42 #include "chrome/browser/extensions/webstore_reinstaller.h"
43 #include "chrome/browser/platform_util.h"
44 #include "chrome/browser/prefs/incognito_mode_prefs.h"
45 #include "chrome/browser/profiles/profile.h"
46 #include "chrome/browser/ui/apps/app_info_dialog.h"
47 #include "chrome/browser/ui/browser.h"
48 #include "chrome/browser/ui/browser_finder.h"
49 #include "chrome/browser/ui/browser_window.h"
50 #include "chrome/browser/ui/extensions/app_launch_params.h"
51 #include "chrome/browser/ui/extensions/application_launch.h"
52 #include "chrome/browser/ui/webui/extensions/extension_basic_info.h"
53 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
54 #include "chrome/common/chrome_version_info.h"
55 #include "chrome/common/extensions/features/feature_channel.h"
56 #include "chrome/common/pref_names.h"
57 #include "chrome/common/url_constants.h"
58 #include "chrome/grit/chromium_strings.h"
59 #include "chrome/grit/generated_resources.h"
60 #include "components/google/core/browser/google_util.h"
61 #include "components/pref_registry/pref_registry_syncable.h"
62 #include "content/public/browser/notification_service.h"
63 #include "content/public/browser/notification_source.h"
64 #include "content/public/browser/notification_types.h"
65 #include "content/public/browser/render_process_host.h"
66 #include "content/public/browser/render_view_host.h"
67 #include "content/public/browser/site_instance.h"
68 #include "content/public/browser/web_contents.h"
69 #include "content/public/browser/web_ui.h"
70 #include "content/public/browser/web_ui_data_source.h"
71 #include "extensions/browser/api/device_permissions_manager.h"
72 #include "extensions/browser/app_window/app_window.h"
73 #include "extensions/browser/app_window/app_window_registry.h"
74 #include "extensions/browser/blacklist_state.h"
75 #include "extensions/browser/extension_error.h"
76 #include "extensions/browser/extension_host.h"
77 #include "extensions/browser/extension_registry.h"
78 #include "extensions/browser/extension_system.h"
79 #include "extensions/browser/lazy_background_task_queue.h"
80 #include "extensions/browser/management_policy.h"
81 #include "extensions/browser/pref_names.h"
82 #include "extensions/browser/uninstall_reason.h"
83 #include "extensions/browser/view_type_utils.h"
84 #include "extensions/browser/warning_set.h"
85 #include "extensions/common/constants.h"
86 #include "extensions/common/extension.h"
87 #include "extensions/common/extension_icon_set.h"
88 #include "extensions/common/extension_set.h"
89 #include "extensions/common/extension_urls.h"
90 #include "extensions/common/feature_switch.h"
91 #include "extensions/common/manifest.h"
92 #include "extensions/common/manifest_handlers/background_info.h"
93 #include "extensions/common/manifest_handlers/incognito_info.h"
94 #include "extensions/common/manifest_handlers/options_page_info.h"
95 #include "extensions/common/manifest_url_handlers.h"
96 #include "extensions/common/permissions/permissions_data.h"
97 #include "grit/browser_resources.h"
98 #include "grit/components_strings.h"
99 #include "grit/theme_resources.h"
100 #include "ui/base/l10n/l10n_util.h"
102 using base::DictionaryValue
;
103 using base::ListValue
;
104 using content::RenderViewHost
;
105 using content::WebContents
;
109 const char kAppsDeveloperToolsExtensionId
[] =
110 "ohmmkhmmmpcnpikjeljgnaoabkaalbgc";
114 namespace extensions
{
116 ExtensionPage::ExtensionPage(const GURL
& url
,
117 int render_process_id
,
120 bool generated_background_page
)
122 render_process_id(render_process_id
),
123 render_view_id(render_view_id
),
124 incognito(incognito
),
125 generated_background_page(generated_background_page
) {
128 // The install prompt is not necessarily modal (e.g. Mac, Linux Unity). This
129 // means that the user can navigate while the dialog is up, causing the dialog
130 // handler to outlive the ExtensionSettingsHandler. That's a problem because the
131 // dialog framework will try to contact us back once the dialog is closed, which
132 // causes a crash. This class is designed to broker the message between the two
133 // objects, while managing its own lifetime so that it can outlive the
134 // ExtensionSettingsHandler and (when doing so) gracefully ignore the message
136 class BrokerDelegate
: public ExtensionInstallPrompt::Delegate
{
138 explicit BrokerDelegate(
139 const base::WeakPtr
<ExtensionSettingsHandler
>& delegate
)
140 : delegate_(delegate
) {}
142 // ExtensionInstallPrompt::Delegate implementation.
143 void InstallUIProceed() override
{
145 delegate_
->InstallUIProceed();
149 void InstallUIAbort(bool user_initiated
) override
{
151 delegate_
->InstallUIAbort(user_initiated
);
155 void AppInfoDialogClosed() {
157 delegate_
->AppInfoDialogClosed();
162 base::WeakPtr
<ExtensionSettingsHandler
> delegate_
;
164 DISALLOW_COPY_AND_ASSIGN(BrokerDelegate
);
167 ///////////////////////////////////////////////////////////////////////////////
169 // ExtensionSettingsHandler
171 ///////////////////////////////////////////////////////////////////////////////
173 ExtensionSettingsHandler::ExtensionSettingsHandler()
174 : extension_service_(NULL
),
175 management_policy_(NULL
),
176 ignore_notifications_(false),
178 deleting_rwh_id_(-1),
179 deleting_rph_id_(-1),
180 registered_for_notifications_(false),
181 warning_service_observer_(this),
182 error_console_observer_(this),
183 extension_prefs_observer_(this),
184 extension_registry_observer_(this),
185 extension_management_observer_(this),
186 should_do_verification_check_(false) {
189 ExtensionSettingsHandler::~ExtensionSettingsHandler() {
192 ExtensionSettingsHandler::ExtensionSettingsHandler(ExtensionService
* service
,
193 ManagementPolicy
* policy
)
194 : extension_service_(service
),
195 management_policy_(policy
),
196 ignore_notifications_(false),
198 deleting_rwh_id_(-1),
199 deleting_rph_id_(-1),
200 registered_for_notifications_(false),
201 warning_service_observer_(this),
202 error_console_observer_(this),
203 extension_prefs_observer_(this),
204 extension_registry_observer_(this),
205 extension_management_observer_(this),
206 should_do_verification_check_(false) {
210 void ExtensionSettingsHandler::RegisterProfilePrefs(
211 user_prefs::PrefRegistrySyncable
* registry
) {
212 registry
->RegisterBooleanPref(
213 prefs::kExtensionsUIDeveloperMode
,
215 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF
);
216 registry
->RegisterBooleanPref(
217 prefs::kExtensionsUIDismissedADTPromo
,
219 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF
);
222 base::DictionaryValue
* ExtensionSettingsHandler::CreateExtensionDetailValue(
223 const Extension
* extension
,
224 const std::vector
<ExtensionPage
>& pages
,
225 const WarningService
* warning_service
) {
226 // The items which are to be written into app_dict are also described in
227 // chrome/browser/resources/extensions/extension_list.js in @typedef for
228 // ExtensionData. Please update it whenever you add or remove any keys here.
229 base::DictionaryValue
* extension_data
= new base::DictionaryValue();
230 bool enabled
= extension_service_
->IsExtensionEnabled(extension
->id());
231 GetExtensionBasicInfo(extension
, enabled
, extension_data
);
233 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(extension_service_
->profile());
234 int disable_reasons
= prefs
->GetDisableReasons(extension
->id());
236 bool suspicious_install
=
237 (disable_reasons
& Extension::DISABLE_NOT_VERIFIED
) != 0;
238 extension_data
->SetBoolean("suspiciousInstall", suspicious_install
);
239 if (suspicious_install
)
240 should_do_verification_check_
= true;
242 bool corrupt_install
=
243 (disable_reasons
& Extension::DISABLE_CORRUPTED
) != 0;
244 extension_data
->SetBoolean("corruptInstall", corrupt_install
);
246 bool update_required_by_policy
=
247 (disable_reasons
& Extension::DISABLE_UPDATE_REQUIRED_BY_POLICY
) != 0;
248 extension_data
->SetBoolean("updateRequiredByPolicy",
249 update_required_by_policy
);
251 bool managed_install
=
252 !management_policy_
->UserMayModifySettings(extension
, NULL
);
253 extension_data
->SetBoolean("managedInstall", managed_install
);
255 bool recommended_install
=
257 management_policy_
->MustRemainInstalled(extension
, NULL
);
258 extension_data
->SetBoolean("recommendedInstall", recommended_install
);
260 // Suspicious install should always be mutually exclusive to managed and/or
261 // recommended install.
262 DCHECK(!(managed_install
|| recommended_install
) || !suspicious_install
);
264 // |web_ui()| can be null in unit tests.
265 bool installed_by_custodian
= web_ui() &&
266 util::IsExtensionSupervised(extension
, Profile::FromWebUI(web_ui()));
267 extension_data
->SetBoolean("installedByCustodian", installed_by_custodian
);
270 ExtensionIconSource::GetIconURL(extension
,
271 extension_misc::EXTENSION_ICON_MEDIUM
,
272 ExtensionIconSet::MATCH_BIGGER
,
274 if (Manifest::IsUnpackedLocation(extension
->location())) {
275 extension_data
->SetString("path", extension
->path().value());
276 extension_data
->SetString(
278 extensions::path_util::PrettifyPath(extension
->path()).value());
280 extension_data
->SetString("icon", icon
.spec());
281 extension_data
->SetBoolean("isUnpacked",
282 Manifest::IsUnpackedLocation(extension
->location()));
283 extension_data
->SetBoolean("isFromStore",
284 extension
->location() == Manifest::INTERNAL
&&
285 ManifestURL::UpdatesFromGallery(extension
));
286 ExtensionRegistry
* registry
=
287 ExtensionRegistry::Get(extension_service_
->profile());
288 extension_data
->SetBoolean(
290 registry
->terminated_extensions().Contains(extension
->id()));
291 extension_data
->SetBoolean("enabledIncognito",
292 util::IsIncognitoEnabled(extension
->id(), extension_service_
->profile()));
293 extension_data
->SetBoolean("incognitoCanBeEnabled",
294 extension
->can_be_incognito_enabled());
295 extension_data
->SetBoolean("wantsFileAccess", extension
->wants_file_access());
296 extension_data
->SetBoolean("allowFileAccess",
297 util::AllowFileAccess(extension
->id(), extension_service_
->profile()));
298 extension_data
->SetBoolean("allow_reload",
299 Manifest::IsUnpackedLocation(extension
->location()));
300 extension_data
->SetBoolean("is_hosted_app", extension
->is_hosted_app());
301 extension_data
->SetBoolean("is_platform_app", extension
->is_platform_app());
302 extension_data
->SetBoolean("homepageProvided",
303 ManifestURL::SpecifiedHomepageURL(extension
));
304 extension_data
->SetBoolean("optionsOpenInTab",
305 OptionsPageInfo::ShouldOpenInTab(extension
));
306 extension_data
->SetString("optionsPageHref",
307 OptionsPageInfo::GetOptionsPage(extension
).spec());
308 extension_data
->SetBoolean("enableExtensionInfoDialog",
309 CanShowAppInfoDialog());
311 // Add dependent extensions.
312 base::ListValue
* dependents_list
= new base::ListValue
;
313 if (extension
->is_shared_module()) {
314 scoped_ptr
<ExtensionSet
> dependent_extensions
=
315 extension_service_
->shared_module_service()->GetDependentExtensions(
317 for (ExtensionSet::const_iterator i
= dependent_extensions
->begin();
318 i
!= dependent_extensions
->end();
320 base::DictionaryValue
* dependent_entry
= new base::DictionaryValue
;
321 dependent_entry
->SetString("id", (*i
)->id());
322 dependent_entry
->SetString("name", (*i
)->name());
323 dependents_list
->Append(dependent_entry
);
326 extension_data
->Set("dependentExtensions", dependents_list
);
328 // We show the "all urls" checkbox if:
329 // - The feature is enabled for the given extension, or has been set in the
331 // - The extension has access to enough urls that we can't just let it run
332 // on those specified in the permissions.
333 content::BrowserContext
* context
= extension_service_
->GetBrowserContext();
335 (FeatureSwitch::scripts_require_action()->IsEnabled() &&
336 PermissionsData::ScriptsMayRequireActionForExtension(
338 extension
->permissions_data()->active_permissions().get())) ||
339 extension
->permissions_data()->HasWithheldImpliedAllHosts() ||
340 util::HasSetAllowedScriptingOnAllUrls(extension
->id(), context
);
341 extension_data
->SetBoolean("showAllUrls", show_all_urls
);
342 extension_data
->SetBoolean(
344 util::AllowedScriptingOnAllUrls(extension
->id(), context
));
346 base::string16 location_text
;
347 if (extension
->location() == Manifest::INTERNAL
&&
348 !ManifestURL::UpdatesFromGallery(extension
)) {
349 location_text
= l10n_util::GetStringUTF16(
350 IDS_OPTIONS_INSTALL_LOCATION_UNKNOWN
);
351 } else if (extension
->location() == Manifest::EXTERNAL_REGISTRY
) {
352 location_text
= l10n_util::GetStringUTF16(
353 IDS_OPTIONS_INSTALL_LOCATION_3RD_PARTY
);
354 } else if (extension
->is_shared_module()) {
355 location_text
= l10n_util::GetStringUTF16(
356 IDS_OPTIONS_INSTALL_LOCATION_SHARED_MODULE
);
358 extension_data
->SetString("locationText", location_text
);
360 base::string16 policy_text
;
361 if (Manifest::IsPolicyLocation(extension
->location())) {
362 policy_text
= l10n_util::GetStringUTF16(
363 IDS_OPTIONS_INSTALL_LOCATION_ENTERPRISE
);
365 extension_data
->SetString("policyText", policy_text
);
367 base::string16 blacklist_text
;
368 switch (prefs
->GetExtensionBlacklistState(extension
->id())) {
369 case BLACKLISTED_SECURITY_VULNERABILITY
:
370 blacklist_text
= l10n_util::GetStringUTF16(
371 IDS_OPTIONS_BLACKLISTED_SECURITY_VULNERABILITY
);
374 case BLACKLISTED_CWS_POLICY_VIOLATION
:
375 blacklist_text
= l10n_util::GetStringUTF16(
376 IDS_OPTIONS_BLACKLISTED_CWS_POLICY_VIOLATION
);
379 case BLACKLISTED_POTENTIALLY_UNWANTED
:
380 blacklist_text
= l10n_util::GetStringUTF16(
381 IDS_OPTIONS_BLACKLISTED_POTENTIALLY_UNWANTED
);
387 extension_data
->SetString("blacklistText", blacklist_text
);
389 // Force unpacked extensions to show at the top.
390 if (Manifest::IsUnpackedLocation(extension
->location()))
391 extension_data
->SetInteger("order", 1);
393 extension_data
->SetInteger("order", 2);
395 // Don't show the "show button" for the browser action if the toolbar
396 // redesign is enabled, because "hidden" buttons are now just hidden in the
398 if (!ExtensionActionAPI::GetBrowserActionVisibility(prefs
, extension
->id()) &&
399 !FeatureSwitch::extension_action_redesign()->IsEnabled()) {
400 extension_data
->SetBoolean("enable_show_button", true);
404 base::ListValue
* views
= new base::ListValue
;
405 for (std::vector
<ExtensionPage
>::const_iterator iter
= pages
.begin();
406 iter
!= pages
.end(); ++iter
) {
407 base::DictionaryValue
* view_value
= new base::DictionaryValue
;
408 if (iter
->url
.scheme() == kExtensionScheme
) {
410 view_value
->SetString("path", iter
->url
.path().substr(1));
412 // For live pages, use the full URL.
413 view_value
->SetString("path", iter
->url
.spec());
415 view_value
->SetInteger("renderViewId", iter
->render_view_id
);
416 view_value
->SetInteger("renderProcessId", iter
->render_process_id
);
417 view_value
->SetBoolean("incognito", iter
->incognito
);
418 view_value
->SetBoolean("generatedBackgroundPage",
419 iter
->generated_background_page
);
420 views
->Append(view_value
);
422 extension_data
->Set("views", views
);
423 ExtensionActionManager
* extension_action_manager
=
424 ExtensionActionManager::Get(extension_service_
->profile());
425 extension_data
->SetBoolean(
427 extension_action_manager
->GetBrowserAction(*extension
) ||
428 extension_action_manager
->GetPageAction(*extension
));
431 if (warning_service
) {
432 std::vector
<std::string
> warnings
=
433 warning_service
->GetWarningMessagesForExtension(extension
->id());
435 if (!warnings
.empty()) {
436 base::ListValue
* warnings_list
= new base::ListValue
;
437 for (std::vector
<std::string
>::const_iterator iter
= warnings
.begin();
438 iter
!= warnings
.end(); ++iter
) {
439 warnings_list
->Append(new base::StringValue(*iter
));
441 extension_data
->Set("warnings", warnings_list
);
445 // If the ErrorConsole is enabled and the extension is unpacked, use the more
446 // detailed errors from the ErrorConsole. Otherwise, use the install warnings
447 // (using both is redundant).
448 ErrorConsole
* error_console
=
449 ErrorConsole::Get(extension_service_
->profile());
450 bool error_console_is_enabled
=
451 error_console
->IsEnabledForChromeExtensionsPage();
452 extension_data
->SetBoolean("wantsErrorCollection", error_console_is_enabled
);
453 if (error_console_is_enabled
) {
454 extension_data
->SetBoolean("errorCollectionEnabled",
455 error_console
->IsReportingEnabledForExtension(
457 const ErrorList
& errors
=
458 error_console
->GetErrorsForExtension(extension
->id());
459 if (!errors
.empty()) {
460 scoped_ptr
<base::ListValue
> manifest_errors(new base::ListValue
);
461 scoped_ptr
<base::ListValue
> runtime_errors(new base::ListValue
);
462 for (ErrorList::const_iterator iter
= errors
.begin();
463 iter
!= errors
.end(); ++iter
) {
464 if ((*iter
)->type() == ExtensionError::MANIFEST_ERROR
) {
465 manifest_errors
->Append((*iter
)->ToValue().release());
466 } else { // Handle runtime error.
467 const RuntimeError
* error
= static_cast<const RuntimeError
*>(*iter
);
468 scoped_ptr
<base::DictionaryValue
> value
= error
->ToValue();
470 !(deleting_rwh_id_
== error
->render_view_id() &&
471 deleting_rph_id_
== error
->render_process_id()) &&
472 RenderViewHost::FromID(error
->render_process_id(),
473 error
->render_view_id()) != NULL
;
474 value
->SetBoolean("canInspect", can_inspect
);
475 runtime_errors
->Append(value
.release());
478 if (!manifest_errors
->empty())
479 extension_data
->Set("manifestErrors", manifest_errors
.release());
480 if (!runtime_errors
->empty())
481 extension_data
->Set("runtimeErrors", runtime_errors
.release());
483 } else if (Manifest::IsUnpackedLocation(extension
->location())) {
484 const std::vector
<InstallWarning
>& install_warnings
=
485 extension
->install_warnings();
486 if (!install_warnings
.empty()) {
487 scoped_ptr
<base::ListValue
> list(new base::ListValue());
488 for (std::vector
<InstallWarning
>::const_iterator it
=
489 install_warnings
.begin(); it
!= install_warnings
.end(); ++it
) {
490 base::DictionaryValue
* item
= new base::DictionaryValue();
491 item
->SetString("message", it
->message
);
494 extension_data
->Set("installWarnings", list
.release());
498 return extension_data
;
501 void ExtensionSettingsHandler::GetLocalizedValues(
502 content::WebUIDataSource
* source
) {
503 source
->AddString("extensionSettings",
504 l10n_util::GetStringUTF16(IDS_MANAGE_EXTENSIONS_SETTING_WINDOWS_TITLE
));
506 source
->AddString("extensionSettingsDeveloperMode",
507 l10n_util::GetStringUTF16(IDS_EXTENSIONS_DEVELOPER_MODE_LINK
));
508 source
->AddString("extensionSettingsNoExtensions",
509 l10n_util::GetStringUTF16(IDS_EXTENSIONS_NONE_INSTALLED
));
511 "extensionSettingsSuggestGallery",
512 l10n_util::GetStringFUTF16(
513 IDS_EXTENSIONS_NONE_INSTALLED_SUGGEST_GALLERY
,
515 google_util::AppendGoogleLocaleParam(
516 GURL(extension_urls::GetWebstoreExtensionsCategoryURL()),
517 g_browser_process
->GetApplicationLocale()).spec())));
518 source
->AddString("extensionSettingsGetMoreExtensions",
519 l10n_util::GetStringUTF16(IDS_GET_MORE_EXTENSIONS
));
521 "extensionSettingsGetMoreExtensionsUrl",
523 google_util::AppendGoogleLocaleParam(
524 GURL(extension_urls::GetWebstoreExtensionsCategoryURL()),
525 g_browser_process
->GetApplicationLocale()).spec()));
526 source
->AddString("extensionSettingsExtensionId",
527 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ID
));
528 source
->AddString("extensionSettingsExtensionPath",
529 l10n_util::GetStringUTF16(IDS_EXTENSIONS_PATH
));
530 source
->AddString("extensionSettingsInspectViews",
531 l10n_util::GetStringUTF16(IDS_EXTENSIONS_INSPECT_VIEWS
));
532 source
->AddString("extensionSettingsInstallWarnings",
533 l10n_util::GetStringUTF16(IDS_EXTENSIONS_INSTALL_WARNINGS
));
534 source
->AddString("viewIncognito",
535 l10n_util::GetStringUTF16(IDS_EXTENSIONS_VIEW_INCOGNITO
));
536 source
->AddString("viewInactive",
537 l10n_util::GetStringUTF16(IDS_EXTENSIONS_VIEW_INACTIVE
));
538 source
->AddString("backgroundPage",
539 l10n_util::GetStringUTF16(IDS_EXTENSIONS_BACKGROUND_PAGE
));
540 source
->AddString("extensionSettingsEnable",
541 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ENABLE
));
542 source
->AddString("extensionSettingsEnabled",
543 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ENABLED
));
544 source
->AddString("extensionSettingsRemove",
545 l10n_util::GetStringUTF16(IDS_EXTENSIONS_REMOVE
));
546 source
->AddString("extensionSettingsEnableIncognito",
547 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ENABLE_INCOGNITO
));
548 source
->AddString("extensionSettingsEnableErrorCollection",
549 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ENABLE_ERROR_COLLECTION
));
550 source
->AddString("extensionSettingsAllowFileAccess",
551 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ALLOW_FILE_ACCESS
));
552 source
->AddString("extensionSettingsAllowOnAllUrls",
553 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ALLOW_ON_ALL_URLS
));
554 source
->AddString("extensionSettingsIncognitoWarning",
555 l10n_util::GetStringUTF16(IDS_EXTENSIONS_INCOGNITO_WARNING
));
556 source
->AddString("extensionSettingsReloadTerminated",
557 l10n_util::GetStringUTF16(IDS_EXTENSIONS_RELOAD_TERMINATED
));
558 source
->AddString("extensionSettingsRepairCorrupted",
559 l10n_util::GetStringUTF16(IDS_EXTENSIONS_REPAIR_CORRUPTED
));
560 source
->AddString("extensionSettingsLaunch",
561 l10n_util::GetStringUTF16(IDS_EXTENSIONS_LAUNCH
));
562 source
->AddString("extensionSettingsReloadUnpacked",
563 l10n_util::GetStringUTF16(IDS_EXTENSIONS_RELOAD_UNPACKED
));
564 source
->AddString("extensionSettingsOptions",
565 l10n_util::GetStringUTF16(IDS_EXTENSIONS_OPTIONS_LINK
));
566 if (CanShowAppInfoDialog()) {
567 source
->AddString("extensionSettingsPermissions",
568 l10n_util::GetStringUTF16(IDS_EXTENSIONS_INFO_LINK
));
571 "extensionSettingsPermissions",
572 l10n_util::GetStringUTF16(IDS_EXTENSIONS_PERMISSIONS_LINK
));
574 source
->AddString("extensionSettingsVisitWebsite",
575 l10n_util::GetStringUTF16(IDS_EXTENSIONS_VISIT_WEBSITE
));
576 source
->AddString("extensionSettingsVisitWebStore",
577 l10n_util::GetStringUTF16(IDS_EXTENSIONS_VISIT_WEBSTORE
));
578 source
->AddString("extensionSettingsPolicyControlled",
579 l10n_util::GetStringUTF16(IDS_EXTENSIONS_POLICY_CONTROLLED
));
580 source
->AddString("extensionSettingsPolicyRecommeneded",
581 l10n_util::GetStringUTF16(IDS_EXTENSIONS_POLICY_RECOMMENDED
));
582 source
->AddString("extensionSettingsDependentExtensions",
583 l10n_util::GetStringUTF16(IDS_EXTENSIONS_DEPENDENT_EXTENSIONS
));
584 source
->AddString("extensionSettingsSupervisedUser",
585 l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOCKED_SUPERVISED_USER
));
586 source
->AddString("extensionSettingsCorruptInstall",
587 l10n_util::GetStringUTF16(
588 IDS_EXTENSIONS_CORRUPTED_EXTENSION
));
589 source
->AddString("extensionSettingsSuspiciousInstall",
590 l10n_util::GetStringFUTF16(
591 IDS_EXTENSIONS_ADDED_WITHOUT_KNOWLEDGE
,
592 l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE
)));
593 source
->AddString("extensionSettingsLearnMore",
594 l10n_util::GetStringUTF16(IDS_LEARN_MORE
));
595 source
->AddString("extensionSettingsSuspiciousInstallHelpUrl",
597 google_util::AppendGoogleLocaleParam(
598 GURL(chrome::kRemoveNonCWSExtensionURL
),
599 g_browser_process
->GetApplicationLocale()).spec()));
600 source
->AddString("extensionSettingsShowButton",
601 l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_BUTTON
));
602 source
->AddString("extensionSettingsLoadUnpackedButton",
603 l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOAD_UNPACKED_BUTTON
));
604 source
->AddString("extensionSettingsPackButton",
605 l10n_util::GetStringUTF16(IDS_EXTENSIONS_PACK_BUTTON
));
606 source
->AddString("extensionSettingsCommandsLink",
607 l10n_util::GetStringUTF16(IDS_EXTENSIONS_COMMANDS_CONFIGURE
));
608 source
->AddString("extensionSettingsUpdateButton",
609 l10n_util::GetStringUTF16(IDS_EXTENSIONS_UPDATE_BUTTON
));
611 "extensionSettingsAppsDevToolsPromoHTML",
612 l10n_util::GetStringFUTF16(
613 IDS_EXTENSIONS_APPS_DEV_TOOLS_PROMO_HTML
,
615 google_util::AppendGoogleLocaleParam(
616 GURL(extension_urls::GetWebstoreItemDetailURLPrefix() +
617 kAppsDeveloperToolsExtensionId
),
618 g_browser_process
->GetApplicationLocale()).spec())));
620 "extensionSettingsAppDevToolsPromoClose",
621 l10n_util::GetStringUTF16(IDS_CLOSE
));
622 source
->AddString("extensionSettingsCrashMessage",
623 l10n_util::GetStringUTF16(IDS_EXTENSIONS_CRASHED_EXTENSION
));
624 source
->AddString("extensionSettingsInDevelopment",
625 l10n_util::GetStringUTF16(IDS_EXTENSIONS_IN_DEVELOPMENT
));
626 source
->AddString("extensionSettingsWarningsTitle",
627 l10n_util::GetStringUTF16(IDS_EXTENSION_WARNINGS_TITLE
));
628 source
->AddString("extensionSettingsShowDetails",
629 l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_DETAILS
));
630 source
->AddString("extensionSettingsHideDetails",
631 l10n_util::GetStringUTF16(IDS_EXTENSIONS_HIDE_DETAILS
));
632 source
->AddString("extensionSettingsUpdateRequiredBePolicy",
633 l10n_util::GetStringUTF16(
634 IDS_EXTENSIONS_DISABLED_UPDATE_REQUIRED_BY_POLICY
));
636 // TODO(estade): comb through the above strings to find ones no longer used in
638 source
->AddString("extensionUninstall",
639 l10n_util::GetStringUTF16(IDS_EXTENSIONS_UNINSTALL
));
642 void ExtensionSettingsHandler::RenderViewDeleted(
643 RenderViewHost
* render_view_host
) {
644 deleting_rvh_
= render_view_host
;
645 Profile
* source_profile
= Profile::FromBrowserContext(
646 render_view_host
->GetSiteInstance()->GetBrowserContext());
647 if (!Profile::FromWebUI(web_ui())->IsSameProfile(source_profile
))
649 MaybeUpdateAfterNotification();
652 void ExtensionSettingsHandler::DidStartNavigationToPendingEntry(
654 content::NavigationController::ReloadType reload_type
) {
655 if (reload_type
!= content::NavigationController::NO_RELOAD
)
656 ReloadUnpackedExtensions();
659 void ExtensionSettingsHandler::RegisterMessages() {
660 // Don't override an |extension_service_| or |management_policy_| injected
662 if (!extension_service_
) {
663 Profile
* profile
= Profile::FromWebUI(web_ui())->GetOriginalProfile();
665 extensions::ExtensionSystem::Get(profile
)->extension_service();
667 if (!management_policy_
) {
668 management_policy_
= ExtensionSystem::Get(
669 extension_service_
->profile())->management_policy();
672 web_ui()->RegisterMessageCallback("extensionSettingsRequestExtensionsData",
673 base::Bind(&ExtensionSettingsHandler::HandleRequestExtensionsData
,
675 web_ui()->RegisterMessageCallback("extensionSettingsToggleDeveloperMode",
676 base::Bind(&ExtensionSettingsHandler::HandleToggleDeveloperMode
,
678 web_ui()->RegisterMessageCallback("extensionSettingsInspect",
679 base::Bind(&ExtensionSettingsHandler::HandleInspectMessage
,
681 web_ui()->RegisterMessageCallback("extensionSettingsLaunch",
682 base::Bind(&ExtensionSettingsHandler::HandleLaunchMessage
,
684 web_ui()->RegisterMessageCallback("extensionSettingsReload",
685 base::Bind(&ExtensionSettingsHandler::HandleReloadMessage
,
687 web_ui()->RegisterMessageCallback("extensionSettingsRepair",
688 base::Bind(&ExtensionSettingsHandler::HandleRepairMessage
,
690 web_ui()->RegisterMessageCallback("extensionSettingsEnableIncognito",
691 base::Bind(&ExtensionSettingsHandler::HandleEnableIncognitoMessage
,
693 web_ui()->RegisterMessageCallback("extensionSettingsEnableErrorCollection",
694 base::Bind(&ExtensionSettingsHandler::HandleEnableErrorCollectionMessage
,
696 web_ui()->RegisterMessageCallback("extensionSettingsAllowFileAccess",
697 base::Bind(&ExtensionSettingsHandler::HandleAllowFileAccessMessage
,
699 web_ui()->RegisterMessageCallback("extensionSettingsAllowOnAllUrls",
700 base::Bind(&ExtensionSettingsHandler::HandleAllowOnAllUrlsMessage
,
702 web_ui()->RegisterMessageCallback("extensionSettingsUninstall",
703 base::Bind(&ExtensionSettingsHandler::HandleUninstallMessage
,
705 web_ui()->RegisterMessageCallback("extensionSettingsOptions",
706 base::Bind(&ExtensionSettingsHandler::HandleOptionsMessage
,
708 web_ui()->RegisterMessageCallback("extensionSettingsPermissions",
709 base::Bind(&ExtensionSettingsHandler::HandlePermissionsMessage
,
711 web_ui()->RegisterMessageCallback("extensionSettingsShowButton",
712 base::Bind(&ExtensionSettingsHandler::HandleShowButtonMessage
,
714 web_ui()->RegisterMessageCallback("extensionSettingsAutoupdate",
715 base::Bind(&ExtensionSettingsHandler::HandleAutoUpdateMessage
,
717 web_ui()->RegisterMessageCallback("extensionSettingsDismissADTPromo",
718 base::Bind(&ExtensionSettingsHandler::HandleDismissADTPromoMessage
,
720 web_ui()->RegisterMessageCallback("extensionSettingsShowPath",
721 base::Bind(&ExtensionSettingsHandler::HandleShowPath
,
725 void ExtensionSettingsHandler::OnErrorAdded(const ExtensionError
* error
) {
726 MaybeUpdateAfterNotification();
729 void ExtensionSettingsHandler::Observe(
731 const content::NotificationSource
& source
,
732 const content::NotificationDetails
& details
) {
733 Profile
* profile
= Profile::FromWebUI(web_ui());
734 Profile
* source_profile
= NULL
;
736 // We listen for notifications that will result in the page being
737 // repopulated with data twice for the same event in certain cases.
738 // For instance, EXTENSION_LOADED & EXTENSION_HOST_CREATED because
739 // we don't know about the views for an extension at EXTENSION_LOADED, but
740 // if we only listen to EXTENSION_HOST_CREATED, we'll miss extensions
741 // that don't have a process at startup.
743 // Doing it this way gets everything but causes the page to be rendered
744 // more than we need. It doesn't seem to result in any noticeable flicker.
745 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED
:
746 deleting_rvh_
= content::Details
<BackgroundContents
>(details
)->
747 web_contents()->GetRenderViewHost();
749 case chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED
:
750 case extensions::NOTIFICATION_EXTENSION_HOST_CREATED
:
751 source_profile
= content::Source
<Profile
>(source
).ptr();
752 if (!profile
->IsSameProfile(source_profile
))
754 MaybeUpdateAfterNotification();
756 case content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED
: {
757 content::RenderWidgetHost
* rwh
=
758 content::Source
<content::RenderWidgetHost
>(source
).ptr();
759 deleting_rwh_id_
= rwh
->GetRoutingID();
760 deleting_rph_id_
= rwh
->GetProcess()->GetID();
761 MaybeUpdateAfterNotification();
764 case extensions::NOTIFICATION_EXTENSION_UPDATE_DISABLED
:
765 case extensions::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED
:
766 MaybeUpdateAfterNotification();
768 case extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED
:
769 // This notification is sent when the extension host destruction begins,
770 // not when it finishes. We use PostTask to delay the update until after
771 // the destruction finishes.
772 base::MessageLoop::current()->PostTask(
774 base::Bind(&ExtensionSettingsHandler::MaybeUpdateAfterNotification
,
782 void ExtensionSettingsHandler::OnExtensionLoaded(
783 content::BrowserContext
* browser_context
,
784 const Extension
* extension
) {
785 MaybeUpdateAfterNotification();
788 void ExtensionSettingsHandler::OnExtensionUnloaded(
789 content::BrowserContext
* browser_context
,
790 const Extension
* extension
,
791 UnloadedExtensionInfo::Reason reason
) {
792 MaybeUpdateAfterNotification();
795 void ExtensionSettingsHandler::OnExtensionUninstalled(
796 content::BrowserContext
* browser_context
,
797 const Extension
* extension
,
798 extensions::UninstallReason reason
) {
799 MaybeUpdateAfterNotification();
802 void ExtensionSettingsHandler::OnExtensionDisableReasonsChanged(
803 const std::string
& extension_id
, int disable_reasons
) {
804 MaybeUpdateAfterNotification();
807 void ExtensionSettingsHandler::OnExtensionManagementSettingsChanged() {
808 MaybeUpdateAfterNotification();
811 void ExtensionSettingsHandler::ExtensionUninstallAccepted() {
812 DCHECK(!extension_id_prompting_
.empty());
814 bool was_terminated
= false;
816 // The extension can be uninstalled in another window while the UI was
817 // showing. Do nothing in that case.
818 const Extension
* extension
=
819 extension_service_
->GetExtensionById(extension_id_prompting_
, true);
822 ExtensionRegistry::Get(Profile::FromWebUI(web_ui()))->GetExtensionById(
823 extension_id_prompting_
, ExtensionRegistry::TERMINATED
);
824 was_terminated
= true;
829 extension_service_
->UninstallExtension(
830 extension_id_prompting_
,
831 extensions::UNINSTALL_REASON_USER_INITIATED
,
832 base::Bind(&base::DoNothing
),
834 extension_id_prompting_
= "";
836 // There will be no EXTENSION_UNLOADED notification for terminated
837 // extensions as they were already unloaded.
839 HandleRequestExtensionsData(NULL
);
842 void ExtensionSettingsHandler::ExtensionUninstallCanceled() {
843 extension_id_prompting_
= "";
846 void ExtensionSettingsHandler::ExtensionWarningsChanged() {
847 MaybeUpdateAfterNotification();
850 // This is called when the user clicks "Revoke File/Device Access."
851 void ExtensionSettingsHandler::InstallUIProceed() {
852 Profile
* profile
= Profile::FromWebUI(web_ui());
853 extensions::DevicePermissionsManager::Get(profile
)
854 ->Clear(extension_id_prompting_
);
855 apps::SavedFilesService::Get(profile
)->ClearQueue(
856 extension_service_
->GetExtensionById(extension_id_prompting_
, true));
857 apps::AppLoadService::Get(profile
)
858 ->RestartApplicationIfRunning(extension_id_prompting_
);
859 extension_id_prompting_
.clear();
862 void ExtensionSettingsHandler::InstallUIAbort(bool user_initiated
) {
863 extension_id_prompting_
.clear();
866 void ExtensionSettingsHandler::AppInfoDialogClosed() {
867 extension_id_prompting_
.clear();
870 void ExtensionSettingsHandler::ReloadUnpackedExtensions() {
871 ExtensionRegistry
* registry
=
872 ExtensionRegistry::Get(extension_service_
->profile());
873 std::vector
<const Extension
*> unpacked_extensions
;
874 for (const scoped_refptr
<const extensions::Extension
>& extension
:
875 registry
->enabled_extensions()) {
876 if (Manifest::IsUnpackedLocation(extension
->location()))
877 unpacked_extensions
.push_back(extension
.get());
880 for (std::vector
<const Extension
*>::iterator iter
=
881 unpacked_extensions
.begin(); iter
!= unpacked_extensions
.end(); ++iter
) {
882 extension_service_
->ReloadExtensionWithQuietFailure((*iter
)->id());
886 void ExtensionSettingsHandler::HandleRequestExtensionsData(
887 const base::ListValue
* args
) {
888 // The items which are to be written into results are also described in
889 // chrome/browser/resources/extensions/extensions.js in @typedef for
890 // ExtensionDataResponse. Please update it whenever you add or remove any keys
892 base::DictionaryValue results
;
894 Profile
* profile
= Profile::FromWebUI(web_ui());
896 // Add the extensions to the results structure.
897 base::ListValue
* extensions_list
= new base::ListValue();
899 WarningService
* warnings
= WarningService::Get(profile
);
901 ExtensionRegistry
* registry
= ExtensionRegistry::Get(profile
);
902 const ExtensionSet
& enabled_set
= registry
->enabled_extensions();
903 for (ExtensionSet::const_iterator extension
= enabled_set
.begin();
904 extension
!= enabled_set
.end(); ++extension
) {
905 if (ui_util::ShouldDisplayInExtensionSettings(extension
->get(), profile
)) {
906 extensions_list
->Append(CreateExtensionDetailValue(
908 GetInspectablePagesForExtension(extension
->get(), true),
912 const ExtensionSet
& disabled_set
= registry
->disabled_extensions();
913 for (ExtensionSet::const_iterator extension
= disabled_set
.begin();
914 extension
!= disabled_set
.end(); ++extension
) {
915 if (ui_util::ShouldDisplayInExtensionSettings(extension
->get(), profile
)) {
916 extensions_list
->Append(CreateExtensionDetailValue(
918 GetInspectablePagesForExtension(extension
->get(), false),
922 const ExtensionSet
& terminated_set
= registry
->terminated_extensions();
923 std::vector
<ExtensionPage
> empty_pages
;
924 for (ExtensionSet::const_iterator extension
= terminated_set
.begin();
925 extension
!= terminated_set
.end(); ++extension
) {
926 if (ui_util::ShouldDisplayInExtensionSettings(extension
->get(), profile
)) {
927 extensions_list
->Append(CreateExtensionDetailValue(
929 empty_pages
, // Terminated process has no active pages.
933 results
.Set("extensions", extensions_list
);
935 bool is_supervised
= profile
->IsSupervised();
936 bool incognito_available
=
937 IncognitoModePrefs::GetAvailability(profile
->GetPrefs()) !=
938 IncognitoModePrefs::DISABLED
;
939 bool developer_mode
=
941 profile
->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode
);
942 results
.SetBoolean("profileIsSupervised", is_supervised
);
943 results
.SetBoolean("incognitoAvailable", incognito_available
);
944 results
.SetBoolean("developerMode", developer_mode
);
946 // Promote the Chrome Apps & Extensions Developer Tools if they are not
947 // installed and the user has not previously dismissed the warning.
948 bool promote_apps_dev_tools
= false;
949 if (!ExtensionRegistry::Get(Profile::FromWebUI(web_ui()))->
950 GetExtensionById(kAppsDeveloperToolsExtensionId
,
951 ExtensionRegistry::EVERYTHING
) &&
952 !profile
->GetPrefs()->GetBoolean(prefs::kExtensionsUIDismissedADTPromo
)) {
953 promote_apps_dev_tools
= true;
955 results
.SetBoolean("promoteAppsDevTools", promote_apps_dev_tools
);
957 const bool load_unpacked_disabled
=
958 ExtensionManagementFactory::GetForBrowserContext(profile
)
959 ->BlacklistedByDefault();
960 results
.SetBoolean("loadUnpackedDisabled", load_unpacked_disabled
);
962 web_ui()->CallJavascriptFunction(
963 "extensions.ExtensionSettings.returnExtensionsData", results
);
965 MaybeRegisterForNotifications();
966 UMA_HISTOGRAM_BOOLEAN("ExtensionSettings.ShouldDoVerificationCheck",
967 should_do_verification_check_
);
968 if (should_do_verification_check_
) {
969 should_do_verification_check_
= false;
970 ExtensionSystem::Get(Profile::FromWebUI(web_ui()))
972 ->VerifyAllExtensions();
976 void ExtensionSettingsHandler::HandleToggleDeveloperMode(
977 const base::ListValue
* args
) {
978 Profile
* profile
= Profile::FromWebUI(web_ui());
979 if (profile
->IsSupervised())
982 bool developer_mode_on
;
983 CHECK(args
->GetBoolean(0, &developer_mode_on
));
984 profile
->GetPrefs()->SetBoolean(prefs::kExtensionsUIDeveloperMode
,
988 void ExtensionSettingsHandler::HandleInspectMessage(
989 const base::ListValue
* args
) {
990 std::string extension_id
;
991 std::string render_process_id_str
;
992 std::string render_view_id_str
;
993 int render_process_id
;
996 CHECK_EQ(4U, args
->GetSize());
997 CHECK(args
->GetString(0, &extension_id
));
998 CHECK(args
->GetString(1, &render_process_id_str
));
999 CHECK(args
->GetString(2, &render_view_id_str
));
1000 CHECK(args
->GetBoolean(3, &incognito
));
1001 CHECK(base::StringToInt(render_process_id_str
, &render_process_id
));
1002 CHECK(base::StringToInt(render_view_id_str
, &render_view_id
));
1004 if (render_process_id
== -1) {
1005 // This message is for a lazy background page. Start the page if necessary.
1006 Profile
* profile
= Profile::FromWebUI(web_ui());
1007 const Extension
* extension
=
1008 ExtensionRegistry::Get(profile
)->enabled_extensions().GetByID(
1012 profile
= profile
->GetOffTheRecordProfile();
1013 devtools_util::InspectBackgroundPage(extension
, profile
);
1017 RenderViewHost
* host
= RenderViewHost::FromID(render_process_id
,
1019 if (!host
|| !WebContents::FromRenderViewHost(host
)) {
1020 // This can happen if the host has gone away since the page was displayed.
1024 DevToolsWindow::OpenDevToolsWindow(WebContents::FromRenderViewHost(host
));
1027 void ExtensionSettingsHandler::HandleLaunchMessage(
1028 const base::ListValue
* args
) {
1029 CHECK_EQ(1U, args
->GetSize());
1030 std::string extension_id
;
1031 CHECK(args
->GetString(0, &extension_id
));
1032 const Extension
* extension
=
1033 extension_service_
->GetExtensionById(extension_id
, false);
1034 OpenApplication(AppLaunchParams(extension_service_
->profile(), extension
,
1035 extensions::LAUNCH_CONTAINER_WINDOW
,
1037 extensions::SOURCE_EXTENSIONS_PAGE
));
1040 void ExtensionSettingsHandler::HandleReloadMessage(
1041 const base::ListValue
* args
) {
1042 std::string extension_id
= base::UTF16ToUTF8(ExtractStringValue(args
));
1043 CHECK(!extension_id
.empty());
1044 extension_service_
->ReloadExtensionWithQuietFailure(extension_id
);
1047 void ExtensionSettingsHandler::HandleRepairMessage(
1048 const base::ListValue
* args
) {
1049 std::string extension_id
= base::UTF16ToUTF8(ExtractStringValue(args
));
1050 CHECK(!extension_id
.empty());
1051 scoped_refptr
<WebstoreReinstaller
> reinstaller(new WebstoreReinstaller(
1054 base::Bind(&ExtensionSettingsHandler::OnReinstallComplete
,
1056 reinstaller
->BeginReinstall();
1059 void ExtensionSettingsHandler::HandleEnableIncognitoMessage(
1060 const base::ListValue
* args
) {
1061 CHECK_EQ(2U, args
->GetSize());
1062 std::string extension_id
, enable_str
;
1063 CHECK(args
->GetString(0, &extension_id
));
1064 CHECK(args
->GetString(1, &enable_str
));
1065 const Extension
* extension
=
1066 extension_service_
->GetInstalledExtension(extension_id
);
1070 // Flipping the incognito bit will generate unload/load notifications for the
1071 // extension, but we don't want to reload the page, because a) we've already
1072 // updated the UI to reflect the change, and b) we want the yellow warning
1073 // text to stay until the user has left the page.
1075 // TODO(aa): This creates crappiness in some cases. For example, in a main
1076 // window, when toggling this, the browser action will flicker because it gets
1077 // unloaded, then reloaded. It would be better to have a dedicated
1078 // notification for this case.
1080 // Bug: http://crbug.com/41384
1081 base::AutoReset
<bool> auto_reset_ignore_notifications(
1082 &ignore_notifications_
, true);
1083 util::SetIsIncognitoEnabled(extension
->id(),
1084 extension_service_
->profile(),
1085 enable_str
== "true");
1088 void ExtensionSettingsHandler::HandleEnableErrorCollectionMessage(
1089 const base::ListValue
* args
) {
1090 CHECK_EQ(2u, args
->GetSize());
1091 std::string extension_id
;
1092 std::string enable_str
;
1093 CHECK(args
->GetString(0, &extension_id
));
1094 CHECK(args
->GetString(1, &enable_str
));
1095 bool enabled
= enable_str
== "true";
1096 ErrorConsole::Get(Profile::FromWebUI(web_ui()))
1097 ->SetReportingAllForExtension(extension_id
, enabled
);
1100 void ExtensionSettingsHandler::HandleAllowFileAccessMessage(
1101 const base::ListValue
* args
) {
1102 CHECK_EQ(2U, args
->GetSize());
1103 std::string extension_id
, allow_str
;
1104 CHECK(args
->GetString(0, &extension_id
));
1105 CHECK(args
->GetString(1, &allow_str
));
1106 const Extension
* extension
=
1107 extension_service_
->GetInstalledExtension(extension_id
);
1111 if (util::IsExtensionSupervised(extension
, Profile::FromWebUI(web_ui())))
1114 if (!management_policy_
->UserMayModifySettings(extension
, NULL
)) {
1115 LOG(ERROR
) << "An attempt was made to change allow file access of an"
1116 << " extension that is non-usermanagable. Extension id : "
1121 util::SetAllowFileAccess(
1122 extension_id
, extension_service_
->profile(), allow_str
== "true");
1125 void ExtensionSettingsHandler::HandleAllowOnAllUrlsMessage(
1126 const base::ListValue
* args
) {
1127 DCHECK(FeatureSwitch::scripts_require_action()->IsEnabled());
1128 CHECK_EQ(2u, args
->GetSize());
1129 std::string extension_id
;
1130 std::string allow_str
;
1131 CHECK(args
->GetString(0, &extension_id
));
1132 CHECK(args
->GetString(1, &allow_str
));
1133 util::SetAllowedScriptingOnAllUrls(extension_id
,
1134 extension_service_
->GetBrowserContext(),
1135 allow_str
== "true");
1138 void ExtensionSettingsHandler::HandleUninstallMessage(
1139 const base::ListValue
* args
) {
1140 CHECK_EQ(1U, args
->GetSize());
1141 std::string extension_id
;
1142 CHECK(args
->GetString(0, &extension_id
));
1143 const Extension
* extension
=
1144 extension_service_
->GetInstalledExtension(extension_id
);
1148 if (!management_policy_
->UserMayModifySettings(extension
, NULL
) ||
1149 management_policy_
->MustRemainInstalled(extension
, NULL
)) {
1150 LOG(ERROR
) << "An attempt was made to uninstall an extension that is "
1151 << "non-usermanagable. Extension id : " << extension
->id();
1155 if (!extension_id_prompting_
.empty())
1156 return; // Only one prompt at a time.
1158 extension_id_prompting_
= extension_id
;
1160 GetExtensionUninstallDialog()->ConfirmUninstall(extension
);
1163 void ExtensionSettingsHandler::HandleOptionsMessage(
1164 const base::ListValue
* args
) {
1165 const Extension
* extension
= GetActiveExtension(args
);
1166 if (!extension
|| OptionsPageInfo::GetOptionsPage(extension
).is_empty())
1168 ExtensionTabUtil::OpenOptionsPage(extension
,
1169 chrome::FindBrowserWithWebContents(web_ui()->GetWebContents()));
1172 void ExtensionSettingsHandler::HandlePermissionsMessage(
1173 const base::ListValue
* args
) {
1174 std::string
extension_id(base::UTF16ToUTF8(ExtractStringValue(args
)));
1175 CHECK(!extension_id
.empty());
1176 const Extension
* extension
=
1177 ExtensionRegistry::Get(Profile::FromWebUI(web_ui()))
1178 ->GetExtensionById(extension_id
, ExtensionRegistry::EVERYTHING
);
1182 if (!extension_id_prompting_
.empty())
1183 return; // Only one prompt at a time.
1184 extension_id_prompting_
= extension
->id();
1186 // The BrokerDelegate manages its own lifetime.
1187 BrokerDelegate
* broker_delegate
= new BrokerDelegate(AsWeakPtr());
1189 // Show the new-style extensions dialog when it is available. It is currently
1190 // unavailable by default on Mac.
1191 if (CanShowAppInfoDialog()) {
1192 UMA_HISTOGRAM_ENUMERATION("Apps.AppInfoDialog.Launches",
1193 AppInfoLaunchSource::FROM_EXTENSIONS_PAGE
,
1194 AppInfoLaunchSource::NUM_LAUNCH_SOURCES
);
1196 // Display the dialog at a size similar to the app list.
1197 ShowAppInfoInNativeDialog(
1198 web_contents()->GetTopLevelNativeWindow(),
1199 GetAppInfoNativeDialogSize(),
1200 Profile::FromWebUI(web_ui()), extension
,
1201 base::Bind(&BrokerDelegate::AppInfoDialogClosed
,
1202 base::Unretained(broker_delegate
)));
1204 prompt_
.reset(new ExtensionInstallPrompt(web_contents()));
1205 std::vector
<base::FilePath
> retained_file_paths
;
1206 if (extension
->permissions_data()->HasAPIPermission(
1207 APIPermission::kFileSystem
)) {
1208 std::vector
<apps::SavedFileEntry
> retained_file_entries
=
1209 apps::SavedFilesService::Get(Profile::FromWebUI(web_ui()))
1210 ->GetAllFileEntries(extension_id_prompting_
);
1211 for (size_t i
= 0; i
< retained_file_entries
.size(); ++i
) {
1212 retained_file_paths
.push_back(retained_file_entries
[i
].path
);
1215 std::vector
<base::string16
> retained_device_messages
;
1216 if (extension
->permissions_data()->HasAPIPermission(APIPermission::kUsb
)) {
1217 retained_device_messages
=
1218 extensions::DevicePermissionsManager::Get(
1219 Profile::FromWebUI(web_ui()))
1220 ->GetPermissionMessageStrings(extension_id_prompting_
);
1223 prompt_
->ReviewPermissions(broker_delegate
, extension
, retained_file_paths
,
1224 retained_device_messages
);
1228 void ExtensionSettingsHandler::HandleShowButtonMessage(
1229 const base::ListValue
* args
) {
1230 const Extension
* extension
= GetActiveExtension(args
);
1233 ExtensionActionAPI::SetBrowserActionVisibility(
1234 ExtensionPrefs::Get(extension_service_
->profile()),
1239 void ExtensionSettingsHandler::HandleAutoUpdateMessage(
1240 const base::ListValue
* args
) {
1241 ExtensionUpdater
* updater
= extension_service_
->updater();
1243 ExtensionUpdater::CheckParams params
;
1244 params
.install_immediately
= true;
1245 updater
->CheckNow(params
);
1249 void ExtensionSettingsHandler::HandleDismissADTPromoMessage(
1250 const base::ListValue
* args
) {
1251 DCHECK(args
->empty());
1252 Profile::FromWebUI(web_ui())->GetPrefs()->SetBoolean(
1253 prefs::kExtensionsUIDismissedADTPromo
, true);
1256 void ExtensionSettingsHandler::HandleShowPath(const base::ListValue
* args
) {
1257 DCHECK(!args
->empty());
1258 std::string extension_id
= base::UTF16ToUTF8(ExtractStringValue(args
));
1260 Profile
* profile
= Profile::FromWebUI(web_ui());
1261 ExtensionRegistry
* registry
= ExtensionRegistry::Get(profile
);
1262 const Extension
* extension
= registry
->GetExtensionById(
1264 ExtensionRegistry::EVERYTHING
);
1266 // We explicitly show manifest.json in order to work around an issue in OSX
1267 // where opening the directory doesn't focus the Finder.
1268 platform_util::ShowItemInFolder(profile
,
1269 extension
->path().Append(kManifestFilename
));
1272 void ExtensionSettingsHandler::ShowAlert(const std::string
& message
) {
1273 base::ListValue arguments
;
1274 arguments
.Append(new base::StringValue(message
));
1275 web_ui()->CallJavascriptFunction("alert", arguments
);
1278 const Extension
* ExtensionSettingsHandler::GetActiveExtension(
1279 const base::ListValue
* args
) {
1280 std::string extension_id
= base::UTF16ToUTF8(ExtractStringValue(args
));
1281 CHECK(!extension_id
.empty());
1282 return extension_service_
->GetExtensionById(extension_id
, false);
1285 void ExtensionSettingsHandler::MaybeUpdateAfterNotification() {
1286 WebContents
* contents
= web_ui()->GetWebContents();
1287 if (!ignore_notifications_
&& contents
&& contents
->GetRenderViewHost())
1288 HandleRequestExtensionsData(NULL
);
1289 deleting_rvh_
= NULL
;
1292 void ExtensionSettingsHandler::MaybeRegisterForNotifications() {
1293 if (registered_for_notifications_
)
1296 registered_for_notifications_
= true;
1297 Profile
* profile
= Profile::FromWebUI(web_ui());
1299 // Register for notifications that we need to reload the page.
1300 registrar_
.Add(this,
1301 extensions::NOTIFICATION_EXTENSION_UPDATE_DISABLED
,
1302 content::Source
<Profile
>(profile
));
1303 registrar_
.Add(this,
1304 extensions::NOTIFICATION_EXTENSION_HOST_CREATED
,
1305 content::NotificationService::AllBrowserContextsAndSources());
1306 registrar_
.Add(this,
1307 chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED
,
1308 content::NotificationService::AllBrowserContextsAndSources());
1309 registrar_
.Add(this,
1310 chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED
,
1311 content::NotificationService::AllBrowserContextsAndSources());
1314 extensions::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED
,
1315 content::Source
<ExtensionPrefs
>(ExtensionPrefs::Get(profile
)));
1316 registrar_
.Add(this,
1317 extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED
,
1318 content::NotificationService::AllBrowserContextsAndSources());
1319 registrar_
.Add(this,
1320 content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED
,
1321 content::NotificationService::AllBrowserContextsAndSources());
1323 extension_registry_observer_
.Add(ExtensionRegistry::Get(profile
));
1325 content::WebContentsObserver::Observe(web_ui()->GetWebContents());
1327 warning_service_observer_
.Add(WarningService::Get(profile
));
1329 error_console_observer_
.Add(ErrorConsole::Get(profile
));
1331 extension_management_observer_
.Add(
1332 ExtensionManagementFactory::GetForBrowserContext(profile
));
1335 std::vector
<ExtensionPage
>
1336 ExtensionSettingsHandler::GetInspectablePagesForExtension(
1337 const Extension
* extension
, bool extension_is_enabled
) {
1338 std::vector
<ExtensionPage
> result
;
1340 // Get the extension process's active views.
1341 extensions::ProcessManager
* process_manager
=
1342 ProcessManager::Get(extension_service_
->profile());
1343 GetInspectablePagesForExtensionProcess(
1345 process_manager
->GetRenderViewHostsForExtension(extension
->id()),
1348 // Get app window views
1349 GetAppWindowPagesForExtensionProfile(
1350 extension
, extension_service_
->profile(), &result
);
1352 // Include a link to start the lazy background page, if applicable.
1353 if (BackgroundInfo::HasLazyBackgroundPage(extension
) &&
1354 extension_is_enabled
&&
1355 !process_manager
->GetBackgroundHostForExtension(extension
->id())) {
1356 result
.push_back(ExtensionPage(
1357 BackgroundInfo::GetBackgroundURL(extension
),
1361 BackgroundInfo::HasGeneratedBackgroundPage(extension
)));
1364 // Repeat for the incognito process, if applicable. Don't try to get
1365 // app windows for incognito processes.
1366 if (extension_service_
->profile()->HasOffTheRecordProfile() &&
1367 IncognitoInfo::IsSplitMode(extension
) &&
1368 util::IsIncognitoEnabled(extension
->id(),
1369 extension_service_
->profile())) {
1370 extensions::ProcessManager
* process_manager
= ProcessManager::Get(
1371 extension_service_
->profile()->GetOffTheRecordProfile());
1372 GetInspectablePagesForExtensionProcess(
1374 process_manager
->GetRenderViewHostsForExtension(extension
->id()),
1377 if (BackgroundInfo::HasLazyBackgroundPage(extension
) &&
1378 extension_is_enabled
&&
1379 !process_manager
->GetBackgroundHostForExtension(extension
->id())) {
1380 result
.push_back(ExtensionPage(
1381 BackgroundInfo::GetBackgroundURL(extension
),
1385 BackgroundInfo::HasGeneratedBackgroundPage(extension
)));
1392 void ExtensionSettingsHandler::GetInspectablePagesForExtensionProcess(
1393 const Extension
* extension
,
1394 const std::set
<RenderViewHost
*>& views
,
1395 std::vector
<ExtensionPage
>* result
) {
1396 bool has_generated_background_page
=
1397 BackgroundInfo::HasGeneratedBackgroundPage(extension
);
1398 for (std::set
<RenderViewHost
*>::const_iterator iter
= views
.begin();
1399 iter
!= views
.end(); ++iter
) {
1400 RenderViewHost
* host
= *iter
;
1401 WebContents
* web_contents
= WebContents::FromRenderViewHost(host
);
1402 ViewType host_type
= GetViewType(web_contents
);
1403 if (host
== deleting_rvh_
||
1404 VIEW_TYPE_EXTENSION_POPUP
== host_type
||
1405 VIEW_TYPE_EXTENSION_DIALOG
== host_type
)
1408 GURL url
= web_contents
->GetURL();
1409 content::RenderProcessHost
* process
= host
->GetProcess();
1410 bool is_background_page
=
1411 (url
== BackgroundInfo::GetBackgroundURL(extension
));
1415 host
->GetRoutingID(),
1416 process
->GetBrowserContext()->IsOffTheRecord(),
1417 is_background_page
&& has_generated_background_page
));
1421 void ExtensionSettingsHandler::GetAppWindowPagesForExtensionProfile(
1422 const Extension
* extension
,
1424 std::vector
<ExtensionPage
>* result
) {
1425 AppWindowRegistry
* registry
= AppWindowRegistry::Get(profile
);
1426 if (!registry
) return;
1428 const AppWindowRegistry::AppWindowList windows
=
1429 registry
->GetAppWindowsForApp(extension
->id());
1431 bool has_generated_background_page
=
1432 BackgroundInfo::HasGeneratedBackgroundPage(extension
);
1433 for (AppWindowRegistry::const_iterator it
= windows
.begin();
1434 it
!= windows
.end();
1436 WebContents
* web_contents
= (*it
)->web_contents();
1437 RenderViewHost
* host
= web_contents
->GetRenderViewHost();
1438 content::RenderProcessHost
* process
= host
->GetProcess();
1440 bool is_background_page
=
1441 (web_contents
->GetURL() == BackgroundInfo::GetBackgroundURL(extension
));
1443 ExtensionPage(web_contents
->GetURL(),
1445 host
->GetRoutingID(),
1446 process
->GetBrowserContext()->IsOffTheRecord(),
1447 is_background_page
&& has_generated_background_page
));
1451 ExtensionUninstallDialog
*
1452 ExtensionSettingsHandler::GetExtensionUninstallDialog() {
1453 if (!extension_uninstall_dialog_
.get()) {
1454 Browser
* browser
= chrome::FindBrowserWithWebContents(
1455 web_ui()->GetWebContents());
1456 extension_uninstall_dialog_
.reset(
1457 ExtensionUninstallDialog::Create(extension_service_
->profile(),
1458 browser
->window()->GetNativeWindow(),
1461 return extension_uninstall_dialog_
.get();
1464 void ExtensionSettingsHandler::OnReinstallComplete(
1466 const std::string
& error
,
1467 webstore_install::Result result
) {
1468 MaybeUpdateAfterNotification();
1471 } // namespace extensions