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 "extensions/browser/api/management/management_api.h"
10 #include "base/basictypes.h"
11 #include "base/bind.h"
12 #include "base/json/json_writer.h"
13 #include "base/lazy_instance.h"
14 #include "base/logging.h"
15 #include "base/memory/linked_ptr.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/metrics/histogram.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "content/public/browser/browser_context.h"
22 #include "extensions/browser/api/extensions_api_client.h"
23 #include "extensions/browser/api/management/management_api_constants.h"
24 #include "extensions/browser/event_router.h"
25 #include "extensions/browser/extension_prefs.h"
26 #include "extensions/browser/extension_registry.h"
27 #include "extensions/browser/extension_system.h"
28 #include "extensions/browser/management_policy.h"
29 #include "extensions/browser/requirements_checker.h"
30 #include "extensions/browser/uninstall_reason.h"
31 #include "extensions/common/api/management.h"
32 #include "extensions/common/constants.h"
33 #include "extensions/common/error_utils.h"
34 #include "extensions/common/extension.h"
35 #include "extensions/common/extension_icon_set.h"
36 #include "extensions/common/manifest_handlers/icons_handler.h"
37 #include "extensions/common/manifest_handlers/offline_enabled_info.h"
38 #include "extensions/common/manifest_handlers/options_page_info.h"
39 #include "extensions/common/manifest_url_handlers.h"
40 #include "extensions/common/permissions/permission_set.h"
41 #include "extensions/common/permissions/permissions_data.h"
42 #include "extensions/common/url_pattern.h"
44 using base::IntToString
;
45 using content::BrowserThread
;
47 namespace keys
= extension_management_api_constants
;
49 namespace extensions
{
51 namespace management
= core_api::management
;
55 typedef std::vector
<linked_ptr
<management::ExtensionInfo
>> ExtensionInfoList
;
56 typedef std::vector
<linked_ptr
<management::IconInfo
>> IconInfoList
;
58 enum AutoConfirmForTest
{ DO_NOT_SKIP
= 0, PROCEED
, ABORT
};
60 AutoConfirmForTest auto_confirm_for_test
= DO_NOT_SKIP
;
62 std::vector
<std::string
> CreateWarningsList(const Extension
* extension
) {
63 std::vector
<std::string
> warnings_list
;
64 PermissionMessages warnings
=
65 extension
->permissions_data()->GetPermissionMessages();
66 for (PermissionMessages::const_iterator iter
= warnings
.begin();
67 iter
!= warnings
.end(); ++iter
) {
68 warnings_list
.push_back(base::UTF16ToUTF8(iter
->message()));
74 std::vector
<management::LaunchType
> GetAvailableLaunchTypes(
75 const Extension
& extension
,
76 const ManagementAPIDelegate
* delegate
) {
77 std::vector
<management::LaunchType
> launch_type_list
;
78 if (extension
.is_platform_app()) {
79 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW
);
80 return launch_type_list
;
83 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB
);
84 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW
);
86 if (!delegate
->IsNewBookmarkAppsEnabled()) {
87 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB
);
88 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_FULL_SCREEN
);
90 return launch_type_list
;
93 scoped_ptr
<management::ExtensionInfo
> CreateExtensionInfo(
94 const Extension
& extension
,
95 content::BrowserContext
* context
) {
96 ExtensionSystem
* system
= ExtensionSystem::Get(context
);
97 ExtensionRegistry
* registry
= ExtensionRegistry::Get(context
);
98 const ManagementAPIDelegate
* delegate
=
99 ManagementAPI::GetFactoryInstance()->Get(context
)->GetDelegate();
100 scoped_ptr
<management::ExtensionInfo
> info(new management::ExtensionInfo());
102 info
->id
= extension
.id();
103 info
->name
= extension
.name();
104 info
->short_name
= extension
.short_name();
105 info
->enabled
= registry
->enabled_extensions().Contains(info
->id
);
106 info
->offline_enabled
= OfflineEnabledInfo::IsOfflineEnabled(&extension
);
107 info
->version
= extension
.VersionString();
108 info
->description
= extension
.description();
109 info
->options_url
= OptionsPageInfo::GetOptionsPage(&extension
).spec();
110 info
->homepage_url
.reset(
111 new std::string(ManifestURL::GetHomepageURL(&extension
).spec()));
113 system
->management_policy()->UserMayModifySettings(&extension
, NULL
);
114 info
->is_app
= extension
.is_app();
116 if (extension
.is_legacy_packaged_app())
117 info
->type
= management::ExtensionInfo::TYPE_LEGACY_PACKAGED_APP
;
118 else if (extension
.is_hosted_app())
119 info
->type
= management::ExtensionInfo::TYPE_HOSTED_APP
;
121 info
->type
= management::ExtensionInfo::TYPE_PACKAGED_APP
;
122 } else if (extension
.is_theme()) {
123 info
->type
= management::ExtensionInfo::TYPE_THEME
;
125 info
->type
= management::ExtensionInfo::TYPE_EXTENSION
;
129 info
->disabled_reason
= management::ExtensionInfo::DISABLED_REASON_NONE
;
131 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(context
);
132 if (prefs
->DidExtensionEscalatePermissions(extension
.id())) {
133 info
->disabled_reason
=
134 management::ExtensionInfo::DISABLED_REASON_PERMISSIONS_INCREASE
;
136 info
->disabled_reason
=
137 management::ExtensionInfo::DISABLED_REASON_UNKNOWN
;
141 if (!ManifestURL::GetUpdateURL(&extension
).is_empty()) {
142 info
->update_url
.reset(
143 new std::string(ManifestURL::GetUpdateURL(&extension
).spec()));
146 if (extension
.is_app()) {
147 info
->app_launch_url
.reset(
148 new std::string(delegate
->GetFullLaunchURL(&extension
).spec()));
151 const ExtensionIconSet::IconMap
& icons
=
152 IconsInfo::GetIcons(&extension
).map();
153 if (!icons
.empty()) {
154 info
->icons
.reset(new IconInfoList());
155 ExtensionIconSet::IconMap::const_iterator icon_iter
;
156 for (icon_iter
= icons
.begin(); icon_iter
!= icons
.end(); ++icon_iter
) {
157 management::IconInfo
* icon_info
= new management::IconInfo();
158 icon_info
->size
= icon_iter
->first
;
160 delegate
->GetIconURL(&extension
, icon_info
->size
,
161 ExtensionIconSet::MATCH_EXACTLY
, false, nullptr);
162 icon_info
->url
= url
.spec();
163 info
->icons
->push_back(make_linked_ptr
<management::IconInfo
>(icon_info
));
167 const std::set
<std::string
> perms
=
168 extension
.permissions_data()->active_permissions()->GetAPIsAsStrings();
169 if (!perms
.empty()) {
170 std::set
<std::string
>::const_iterator perms_iter
;
171 for (perms_iter
= perms
.begin(); perms_iter
!= perms
.end(); ++perms_iter
)
172 info
->permissions
.push_back(*perms_iter
);
175 if (!extension
.is_hosted_app()) {
176 // Skip host permissions for hosted apps.
177 const URLPatternSet host_perms
=
178 extension
.permissions_data()->active_permissions()->explicit_hosts();
179 if (!host_perms
.is_empty()) {
180 for (URLPatternSet::const_iterator iter
= host_perms
.begin();
181 iter
!= host_perms
.end(); ++iter
) {
182 info
->host_permissions
.push_back(iter
->GetAsString());
187 switch (extension
.location()) {
188 case Manifest::INTERNAL
:
189 info
->install_type
= management::ExtensionInfo::INSTALL_TYPE_NORMAL
;
191 case Manifest::UNPACKED
:
192 case Manifest::COMMAND_LINE
:
193 info
->install_type
= management::ExtensionInfo::INSTALL_TYPE_DEVELOPMENT
;
195 case Manifest::EXTERNAL_PREF
:
196 case Manifest::EXTERNAL_REGISTRY
:
197 case Manifest::EXTERNAL_PREF_DOWNLOAD
:
198 info
->install_type
= management::ExtensionInfo::INSTALL_TYPE_SIDELOAD
;
200 case Manifest::EXTERNAL_POLICY
:
201 case Manifest::EXTERNAL_POLICY_DOWNLOAD
:
202 info
->install_type
= management::ExtensionInfo::INSTALL_TYPE_ADMIN
;
204 case Manifest::NUM_LOCATIONS
:
206 case Manifest::INVALID_LOCATION
:
207 case Manifest::COMPONENT
:
208 case Manifest::EXTERNAL_COMPONENT
:
209 info
->install_type
= management::ExtensionInfo::INSTALL_TYPE_OTHER
;
213 info
->launch_type
= management::LAUNCH_TYPE_NONE
;
214 if (extension
.is_app()) {
215 LaunchType launch_type
;
216 if (extension
.is_platform_app()) {
217 launch_type
= LAUNCH_TYPE_WINDOW
;
220 delegate
->GetLaunchType(ExtensionPrefs::Get(context
), &extension
);
223 switch (launch_type
) {
224 case LAUNCH_TYPE_PINNED
:
225 info
->launch_type
= management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB
;
227 case LAUNCH_TYPE_REGULAR
:
228 info
->launch_type
= management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB
;
230 case LAUNCH_TYPE_FULLSCREEN
:
231 info
->launch_type
= management::LAUNCH_TYPE_OPEN_FULL_SCREEN
;
233 case LAUNCH_TYPE_WINDOW
:
234 info
->launch_type
= management::LAUNCH_TYPE_OPEN_AS_WINDOW
;
236 case LAUNCH_TYPE_INVALID
:
237 case NUM_LAUNCH_TYPES
:
241 info
->available_launch_types
.reset(new std::vector
<management::LaunchType
>(
242 GetAvailableLaunchTypes(extension
, delegate
)));
248 bool ShouldNotBeVisible(const Extension
* extension
,
249 content::BrowserContext
* context
) {
250 return (extension
->ShouldNotBeVisible() ||
251 ExtensionPrefs::Get(context
)->IsEphemeralApp(extension
->id()));
254 void AddExtensionInfo(const ExtensionSet
& extensions
,
255 ExtensionInfoList
* extension_list
,
256 content::BrowserContext
* context
) {
257 for (ExtensionSet::const_iterator iter
= extensions
.begin();
258 iter
!= extensions
.end(); ++iter
) {
259 const Extension
& extension
= *iter
->get();
261 if (ShouldNotBeVisible(&extension
, context
))
262 continue; // Skip built-in extensions/apps.
264 extension_list
->push_back(make_linked_ptr
<management::ExtensionInfo
>(
265 CreateExtensionInfo(extension
, context
).release()));
271 bool ManagementGetAllFunction::RunSync() {
272 ExtensionInfoList extensions
;
273 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser_context());
275 AddExtensionInfo(registry
->enabled_extensions(), &extensions
,
277 AddExtensionInfo(registry
->disabled_extensions(), &extensions
,
279 AddExtensionInfo(registry
->terminated_extensions(), &extensions
,
282 results_
= management::GetAll::Results::Create(extensions
);
286 bool ManagementGetFunction::RunSync() {
287 scoped_ptr
<management::Get::Params
> params(
288 management::Get::Params::Create(*args_
));
289 EXTENSION_FUNCTION_VALIDATE(params
.get());
290 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser_context());
292 const Extension
* extension
=
293 registry
->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
296 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
300 scoped_ptr
<management::ExtensionInfo
> info
=
301 CreateExtensionInfo(*extension
, browser_context());
302 results_
= management::Get::Results::Create(*info
);
307 bool ManagementGetSelfFunction::RunSync() {
308 scoped_ptr
<management::ExtensionInfo
> info
=
309 CreateExtensionInfo(*extension_
, browser_context());
310 results_
= management::Get::Results::Create(*info
);
315 bool ManagementGetPermissionWarningsByIdFunction::RunSync() {
316 scoped_ptr
<management::GetPermissionWarningsById::Params
> params(
317 management::GetPermissionWarningsById::Params::Create(*args_
));
318 EXTENSION_FUNCTION_VALIDATE(params
.get());
320 const Extension
* extension
=
321 ExtensionRegistry::Get(browser_context())
322 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
325 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
329 std::vector
<std::string
> warnings
= CreateWarningsList(extension
);
330 results_
= management::GetPermissionWarningsById::Results::Create(warnings
);
334 bool ManagementGetPermissionWarningsByManifestFunction::RunAsync() {
335 scoped_ptr
<management::GetPermissionWarningsByManifest::Params
> params(
336 management::GetPermissionWarningsByManifest::Params::Create(*args_
));
337 EXTENSION_FUNCTION_VALIDATE(params
.get());
339 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
340 ->Get(browser_context())
344 delegate
->GetPermissionWarningsByManifestFunctionDelegate(
345 this, params
->manifest_str
);
347 // Matched with a Release() in OnParseSuccess/Failure().
350 // Response is sent async in OnParseSuccess/Failure().
353 // TODO(lfg) add error string
359 void ManagementGetPermissionWarningsByManifestFunction::OnParseSuccess(
360 scoped_ptr
<base::Value
> value
) {
361 if (!value
->IsType(base::Value::TYPE_DICTIONARY
)) {
362 OnParseFailure(keys::kManifestParseError
);
365 const base::DictionaryValue
* parsed_manifest
=
366 static_cast<const base::DictionaryValue
*>(value
.get());
368 scoped_refptr
<Extension
> extension
=
369 Extension::Create(base::FilePath(), Manifest::INVALID_LOCATION
,
370 *parsed_manifest
, Extension::NO_FLAGS
, &error_
);
372 OnParseFailure(keys::kExtensionCreateError
);
376 std::vector
<std::string
> warnings
= CreateWarningsList(extension
.get());
378 management::GetPermissionWarningsByManifest::Results::Create(warnings
);
381 // Matched with AddRef() in RunAsync().
385 void ManagementGetPermissionWarningsByManifestFunction::OnParseFailure(
386 const std::string
& error
) {
390 // Matched with AddRef() in RunAsync().
394 bool ManagementLaunchAppFunction::RunSync() {
395 scoped_ptr
<management::LaunchApp::Params
> params(
396 management::LaunchApp::Params::Create(*args_
));
397 EXTENSION_FUNCTION_VALIDATE(params
.get());
398 const Extension
* extension
=
399 ExtensionRegistry::Get(browser_context())
400 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
403 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
406 if (!extension
->is_app()) {
407 error_
= ErrorUtils::FormatErrorMessage(keys::kNotAnAppError
, params
->id
);
411 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
412 ->Get(browser_context())
414 return delegate
->LaunchAppFunctionDelegate(extension
, browser_context());
417 ManagementSetEnabledFunction::ManagementSetEnabledFunction() {
420 ManagementSetEnabledFunction::~ManagementSetEnabledFunction() {
423 ExtensionFunction::ResponseAction
ManagementSetEnabledFunction::Run() {
424 scoped_ptr
<management::SetEnabled::Params
> params(
425 management::SetEnabled::Params::Create(*args_
));
426 EXTENSION_FUNCTION_VALIDATE(params
.get());
427 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser_context());
428 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
429 ->Get(browser_context())
432 extension_id_
= params
->id
;
434 const Extension
* extension
=
435 registry
->GetExtensionById(extension_id_
, ExtensionRegistry::EVERYTHING
);
436 if (!extension
|| ShouldNotBeVisible(extension
, browser_context()))
437 return RespondNow(Error(keys::kNoExtensionError
, extension_id_
));
439 bool enabled
= params
->enabled
;
440 const ManagementPolicy
* policy
=
441 ExtensionSystem::Get(browser_context())->management_policy();
442 if (!policy
->UserMayModifySettings(extension
, nullptr) ||
443 (!enabled
&& policy
->MustRemainEnabled(extension
, nullptr)) ||
444 (enabled
&& policy
->MustRemainDisabled(extension
, nullptr, nullptr))) {
445 return RespondNow(Error(keys::kUserCantModifyError
, extension_id_
));
448 bool currently_enabled
=
449 registry
->enabled_extensions().Contains(extension_id_
) ||
450 registry
->terminated_extensions().Contains(extension_id_
);
452 if (!currently_enabled
&& enabled
) {
453 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(browser_context());
454 if (prefs
->DidExtensionEscalatePermissions(extension_id_
)) {
456 return RespondNow(Error(keys::kGestureNeededForEscalationError
));
458 AddRef(); // Matched in InstallUIProceed/InstallUIAbort
459 install_prompt_
= delegate
->SetEnabledFunctionDelegate(this, extension
);
460 return RespondLater();
462 if (prefs
->GetDisableReasons(extension_id_
) &
463 Extension::DISABLE_UNSUPPORTED_REQUIREMENT
) {
464 // Recheck the requirements.
465 requirements_checker_
= delegate
->CreateRequirementsChecker();
466 requirements_checker_
->Check(
468 base::Bind(&ManagementSetEnabledFunction::OnRequirementsChecked
,
469 this)); // This bind creates a reference.
470 return RespondLater();
472 delegate
->EnableExtension(browser_context(), extension_id_
);
473 } else if (currently_enabled
&& !params
->enabled
) {
474 delegate
->DisableExtension(browser_context(), extension_id_
,
475 Extension::DISABLE_USER_ACTION
);
478 return RespondNow(NoArguments());
481 void ManagementSetEnabledFunction::InstallUIProceed() {
482 ManagementAPI::GetFactoryInstance()
483 ->Get(browser_context())
485 ->EnableExtension(browser_context(), extension_id_
);
486 Respond(OneArgument(new base::FundamentalValue(true)));
490 void ManagementSetEnabledFunction::InstallUIAbort(bool user_initiated
) {
491 Respond(Error(keys::kUserDidNotReEnableError
));
495 void ManagementSetEnabledFunction::OnRequirementsChecked(
496 const std::vector
<std::string
>& requirements_errors
) {
497 if (requirements_errors
.empty()) {
498 ManagementAPI::GetFactoryInstance()->Get(browser_context())->GetDelegate()->
499 EnableExtension(browser_context(), extension_id_
);
500 Respond(NoArguments());
502 // TODO(devlin): Should we really be noisy here all the time?
503 Respond(Error(keys::kMissingRequirementsError
,
504 JoinString(requirements_errors
, ' ')));
508 ManagementUninstallFunctionBase::ManagementUninstallFunctionBase() {
511 ManagementUninstallFunctionBase::~ManagementUninstallFunctionBase() {
514 ExtensionFunction::ResponseAction
ManagementUninstallFunctionBase::Uninstall(
515 const std::string
& target_extension_id
,
516 bool show_confirm_dialog
) {
517 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
518 ->Get(browser_context())
520 target_extension_id_
= target_extension_id
;
521 const Extension
* target_extension
=
522 extensions::ExtensionRegistry::Get(browser_context())
523 ->GetExtensionById(target_extension_id_
,
524 ExtensionRegistry::EVERYTHING
);
525 if (!target_extension
||
526 ShouldNotBeVisible(target_extension
, browser_context())) {
527 return RespondNow(Error(keys::kNoExtensionError
, target_extension_id_
));
530 ManagementPolicy
* policy
=
531 ExtensionSystem::Get(browser_context())->management_policy();
532 if (!policy
->UserMayModifySettings(target_extension
, nullptr) ||
533 policy
->MustRemainInstalled(target_extension
, nullptr)) {
534 return RespondNow(Error(keys::kUserCantModifyError
, target_extension_id_
));
537 // Note: null extension() means it's WebUI.
538 bool self_uninstall
= extension() && extension_id() == target_extension_id_
;
539 // We need to show a dialog for any extension uninstalling another extension.
540 show_confirm_dialog
|= !self_uninstall
;
542 if (show_confirm_dialog
&& !user_gesture())
543 return RespondNow(Error(keys::kGestureNeededForUninstallError
));
545 if (show_confirm_dialog
) {
546 if (auto_confirm_for_test
== DO_NOT_SKIP
) {
547 // We show the programmatic uninstall ui for extensions uninstalling
549 bool show_programmatic_uninstall_ui
= !self_uninstall
&& extension();
550 AddRef(); // Balanced in ExtensionUninstallAccepted/Canceled
551 // TODO(devlin): A method called "UninstallFunctionDelegate" does not in
552 // any way imply that this actually creates a dialog and runs it.
554 delegate
->UninstallFunctionDelegate(
557 show_programmatic_uninstall_ui
);
559 // Skip the confirm dialog for testing.
560 base::MessageLoop::current()->PostTask(
562 base::Bind(&ManagementUninstallFunctionBase::Finish
,
564 auto_confirm_for_test
== PROCEED
));
566 } else { // No confirm dialog.
567 base::MessageLoop::current()->PostTask(
569 base::Bind(&ManagementUninstallFunctionBase::Finish
, this, true));
572 return RespondLater();
576 void ManagementUninstallFunctionBase::SetAutoConfirmForTest(
577 bool should_proceed
) {
578 auto_confirm_for_test
= should_proceed
? PROCEED
: ABORT
;
581 void ManagementUninstallFunctionBase::Finish(bool should_uninstall
) {
582 if (!should_uninstall
) {
583 Respond(Error(keys::kUninstallCanceledError
, target_extension_id_
));
587 // The extension can be uninstalled in another window while the UI was
588 // showing. Do nothing in that case.
589 const Extension
* target_extension
=
590 extensions::ExtensionRegistry::Get(browser_context())
591 ->GetExtensionById(target_extension_id_
,
592 ExtensionRegistry::EVERYTHING
);
593 if (!target_extension
) {
594 Respond(Error(keys::kNoExtensionError
, target_extension_id_
));
598 const ManagementAPIDelegate
* delegate
=
599 ManagementAPI::GetFactoryInstance()
600 ->Get(browser_context())
602 base::string16 error
;
603 bool success
= delegate
->UninstallExtension(
604 browser_context(), target_extension_id_
,
605 extensions::UNINSTALL_REASON_MANAGEMENT_API
,
606 base::Bind(&base::DoNothing
), &error
);
607 Respond(success
? NoArguments() : Error(base::UTF16ToUTF8(error
)));
610 void ManagementUninstallFunctionBase::ExtensionUninstallAccepted() {
615 void ManagementUninstallFunctionBase::ExtensionUninstallCanceled() {
620 ManagementUninstallFunction::ManagementUninstallFunction() {
623 ManagementUninstallFunction::~ManagementUninstallFunction() {
626 ExtensionFunction::ResponseAction
ManagementUninstallFunction::Run() {
627 scoped_ptr
<management::Uninstall::Params
> params(
628 management::Uninstall::Params::Create(*args_
));
629 EXTENSION_FUNCTION_VALIDATE(params
.get());
631 bool show_confirm_dialog
= params
->options
.get() &&
632 params
->options
->show_confirm_dialog
.get() &&
633 *params
->options
->show_confirm_dialog
;
634 return Uninstall(params
->id
, show_confirm_dialog
);
637 ManagementUninstallSelfFunction::ManagementUninstallSelfFunction() {
640 ManagementUninstallSelfFunction::~ManagementUninstallSelfFunction() {
643 ExtensionFunction::ResponseAction
ManagementUninstallSelfFunction::Run() {
644 scoped_ptr
<management::UninstallSelf::Params
> params(
645 management::UninstallSelf::Params::Create(*args_
));
646 EXTENSION_FUNCTION_VALIDATE(params
.get());
647 EXTENSION_FUNCTION_VALIDATE(extension_
.get());
649 bool show_confirm_dialog
= params
->options
.get() &&
650 params
->options
->show_confirm_dialog
.get() &&
651 *params
->options
->show_confirm_dialog
;
652 return Uninstall(extension_
->id(), show_confirm_dialog
);
655 ManagementCreateAppShortcutFunction::ManagementCreateAppShortcutFunction() {
658 ManagementCreateAppShortcutFunction::~ManagementCreateAppShortcutFunction() {
662 void ManagementCreateAppShortcutFunction::SetAutoConfirmForTest(
663 bool should_proceed
) {
664 auto_confirm_for_test
= should_proceed
? PROCEED
: ABORT
;
667 void ManagementCreateAppShortcutFunction::OnCloseShortcutPrompt(bool created
) {
669 error_
= keys::kCreateShortcutCanceledError
;
670 SendResponse(created
);
674 bool ManagementCreateAppShortcutFunction::RunAsync() {
675 if (!user_gesture()) {
676 error_
= keys::kGestureNeededForCreateAppShortcutError
;
680 scoped_ptr
<management::CreateAppShortcut::Params
> params(
681 management::CreateAppShortcut::Params::Create(*args_
));
682 EXTENSION_FUNCTION_VALIDATE(params
.get());
683 const Extension
* extension
=
684 ExtensionRegistry::Get(browser_context())
685 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
688 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
692 if (!extension
->is_app()) {
693 error_
= ErrorUtils::FormatErrorMessage(keys::kNotAnAppError
, params
->id
);
697 #if defined(OS_MACOSX)
698 if (!extension
->is_platform_app()) {
699 error_
= keys::kCreateOnlyPackagedAppShortcutMac
;
704 if (auto_confirm_for_test
!= DO_NOT_SKIP
) {
705 // Matched with a Release() in OnCloseShortcutPrompt().
708 OnCloseShortcutPrompt(auto_confirm_for_test
== PROCEED
);
713 if (ManagementAPI::GetFactoryInstance()
714 ->Get(browser_context())
716 ->CreateAppShortcutFunctionDelegate(this, extension
)) {
717 // Matched with a Release() in OnCloseShortcutPrompt().
721 // Response is sent async in OnCloseShortcutPrompt().
725 bool ManagementSetLaunchTypeFunction::RunSync() {
726 if (!user_gesture()) {
727 error_
= keys::kGestureNeededForSetLaunchTypeError
;
731 scoped_ptr
<management::SetLaunchType::Params
> params(
732 management::SetLaunchType::Params::Create(*args_
));
733 EXTENSION_FUNCTION_VALIDATE(params
.get());
734 const Extension
* extension
=
735 ExtensionRegistry::Get(browser_context())
736 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
737 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
738 ->Get(browser_context())
742 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
746 if (!extension
->is_app()) {
747 error_
= ErrorUtils::FormatErrorMessage(keys::kNotAnAppError
, params
->id
);
751 std::vector
<management::LaunchType
> available_launch_types
=
752 GetAvailableLaunchTypes(*extension
, delegate
);
754 management::LaunchType app_launch_type
= params
->launch_type
;
755 if (std::find(available_launch_types
.begin(), available_launch_types
.end(),
756 app_launch_type
) == available_launch_types
.end()) {
757 error_
= keys::kLaunchTypeNotAvailableError
;
761 LaunchType launch_type
= LAUNCH_TYPE_DEFAULT
;
762 switch (app_launch_type
) {
763 case management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB
:
764 launch_type
= LAUNCH_TYPE_PINNED
;
766 case management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB
:
767 launch_type
= LAUNCH_TYPE_REGULAR
;
769 case management::LAUNCH_TYPE_OPEN_FULL_SCREEN
:
770 launch_type
= LAUNCH_TYPE_FULLSCREEN
;
772 case management::LAUNCH_TYPE_OPEN_AS_WINDOW
:
773 launch_type
= LAUNCH_TYPE_WINDOW
;
775 case management::LAUNCH_TYPE_NONE
:
779 delegate
->SetLaunchType(browser_context(), params
->id
, launch_type
);
784 ManagementGenerateAppForLinkFunction::ManagementGenerateAppForLinkFunction() {
787 ManagementGenerateAppForLinkFunction::~ManagementGenerateAppForLinkFunction() {
790 void ManagementGenerateAppForLinkFunction::FinishCreateBookmarkApp(
791 const Extension
* extension
,
792 const WebApplicationInfo
& web_app_info
) {
794 scoped_ptr
<management::ExtensionInfo
> info
=
795 CreateExtensionInfo(*extension
, browser_context());
796 results_
= management::GenerateAppForLink::Results::Create(*info
);
801 error_
= keys::kGenerateAppForLinkInstallError
;
807 bool ManagementGenerateAppForLinkFunction::RunAsync() {
808 if (!user_gesture()) {
809 error_
= keys::kGestureNeededForGenerateAppForLinkError
;
813 scoped_ptr
<management::GenerateAppForLink::Params
> params(
814 management::GenerateAppForLink::Params::Create(*args_
));
815 EXTENSION_FUNCTION_VALIDATE(params
.get());
817 GURL
launch_url(params
->url
);
818 if (!launch_url
.is_valid() || !launch_url
.SchemeIsHTTPOrHTTPS()) {
820 ErrorUtils::FormatErrorMessage(keys::kInvalidURLError
, params
->url
);
824 if (params
->title
.empty()) {
825 error_
= keys::kEmptyTitleError
;
829 app_for_link_delegate_
=
830 ManagementAPI::GetFactoryInstance()
831 ->Get(browser_context())
833 ->GenerateAppForLinkFunctionDelegate(this, browser_context(),
834 params
->title
, launch_url
);
836 // Matched with a Release() in FinishCreateBookmarkApp().
839 // Response is sent async in FinishCreateBookmarkApp().
843 ManagementEventRouter::ManagementEventRouter(content::BrowserContext
* context
)
844 : browser_context_(context
), extension_registry_observer_(this) {
845 extension_registry_observer_
.Add(ExtensionRegistry::Get(browser_context_
));
848 ManagementEventRouter::~ManagementEventRouter() {
851 void ManagementEventRouter::OnExtensionLoaded(
852 content::BrowserContext
* browser_context
,
853 const Extension
* extension
) {
854 BroadcastEvent(extension
, management::OnEnabled::kEventName
);
857 void ManagementEventRouter::OnExtensionUnloaded(
858 content::BrowserContext
* browser_context
,
859 const Extension
* extension
,
860 UnloadedExtensionInfo::Reason reason
) {
861 BroadcastEvent(extension
, management::OnDisabled::kEventName
);
864 void ManagementEventRouter::OnExtensionInstalled(
865 content::BrowserContext
* browser_context
,
866 const Extension
* extension
,
868 BroadcastEvent(extension
, management::OnInstalled::kEventName
);
871 void ManagementEventRouter::OnExtensionUninstalled(
872 content::BrowserContext
* browser_context
,
873 const Extension
* extension
,
874 extensions::UninstallReason reason
) {
875 BroadcastEvent(extension
, management::OnUninstalled::kEventName
);
878 void ManagementEventRouter::BroadcastEvent(const Extension
* extension
,
879 const char* event_name
) {
880 if (ShouldNotBeVisible(extension
, browser_context_
))
881 return; // Don't dispatch events for built-in extenions.
882 scoped_ptr
<base::ListValue
> args(new base::ListValue());
883 if (event_name
== management::OnUninstalled::kEventName
) {
884 args
->Append(new base::StringValue(extension
->id()));
886 scoped_ptr
<management::ExtensionInfo
> info
=
887 CreateExtensionInfo(*extension
, browser_context_
);
888 args
->Append(info
->ToValue().release());
891 EventRouter::Get(browser_context_
)
892 ->BroadcastEvent(scoped_ptr
<Event
>(new Event(event_name
, args
.Pass())));
895 ManagementAPI::ManagementAPI(content::BrowserContext
* context
)
896 : browser_context_(context
),
897 delegate_(ExtensionsAPIClient::Get()->CreateManagementAPIDelegate()) {
898 EventRouter
* event_router
= EventRouter::Get(browser_context_
);
899 event_router
->RegisterObserver(this, management::OnInstalled::kEventName
);
900 event_router
->RegisterObserver(this, management::OnUninstalled::kEventName
);
901 event_router
->RegisterObserver(this, management::OnEnabled::kEventName
);
902 event_router
->RegisterObserver(this, management::OnDisabled::kEventName
);
905 ManagementAPI::~ManagementAPI() {
908 void ManagementAPI::Shutdown() {
909 EventRouter::Get(browser_context_
)->UnregisterObserver(this);
912 static base::LazyInstance
<BrowserContextKeyedAPIFactory
<ManagementAPI
>>
913 g_factory
= LAZY_INSTANCE_INITIALIZER
;
916 BrowserContextKeyedAPIFactory
<ManagementAPI
>*
917 ManagementAPI::GetFactoryInstance() {
918 return g_factory
.Pointer();
921 void ManagementAPI::OnListenerAdded(const EventListenerInfo
& details
) {
922 management_event_router_
.reset(new ManagementEventRouter(browser_context_
));
923 EventRouter::Get(browser_context_
)->UnregisterObserver(this);
926 } // namespace extensions