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/coalesced_permission_message.h"
41 #include "extensions/common/permissions/permission_set.h"
42 #include "extensions/common/permissions/permissions_data.h"
43 #include "extensions/common/url_pattern.h"
45 using base::IntToString
;
46 using content::BrowserThread
;
48 namespace keys
= extension_management_api_constants
;
50 namespace extensions
{
52 namespace management
= api::management
;
56 typedef std::vector
<linked_ptr
<management::ExtensionInfo
>> ExtensionInfoList
;
57 typedef std::vector
<linked_ptr
<management::IconInfo
>> IconInfoList
;
59 enum AutoConfirmForTest
{ DO_NOT_SKIP
= 0, PROCEED
, ABORT
};
61 AutoConfirmForTest auto_confirm_for_test
= DO_NOT_SKIP
;
63 std::vector
<std::string
> CreateWarningsList(const Extension
* extension
) {
64 std::vector
<std::string
> warnings_list
;
65 for (const CoalescedPermissionMessage
& msg
:
66 extension
->permissions_data()->GetPermissionMessages()) {
67 warnings_list
.push_back(base::UTF16ToUTF8(msg
.message()));
73 std::vector
<management::LaunchType
> GetAvailableLaunchTypes(
74 const Extension
& extension
,
75 const ManagementAPIDelegate
* delegate
) {
76 std::vector
<management::LaunchType
> launch_type_list
;
77 if (extension
.is_platform_app()) {
78 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW
);
79 return launch_type_list
;
82 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB
);
83 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW
);
85 if (!delegate
->IsNewBookmarkAppsEnabled()) {
86 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB
);
87 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_FULL_SCREEN
);
89 return launch_type_list
;
92 scoped_ptr
<management::ExtensionInfo
> CreateExtensionInfo(
93 const Extension
& extension
,
94 content::BrowserContext
* context
) {
95 ExtensionSystem
* system
= ExtensionSystem::Get(context
);
96 ExtensionRegistry
* registry
= ExtensionRegistry::Get(context
);
97 const ManagementAPIDelegate
* delegate
=
98 ManagementAPI::GetFactoryInstance()->Get(context
)->GetDelegate();
99 scoped_ptr
<management::ExtensionInfo
> info(new management::ExtensionInfo());
101 info
->id
= extension
.id();
102 info
->name
= extension
.name();
103 info
->short_name
= extension
.short_name();
104 info
->enabled
= registry
->enabled_extensions().Contains(info
->id
);
105 info
->offline_enabled
= OfflineEnabledInfo::IsOfflineEnabled(&extension
);
106 info
->version
= extension
.VersionString();
107 info
->description
= extension
.description();
108 info
->options_url
= OptionsPageInfo::GetOptionsPage(&extension
).spec();
109 info
->homepage_url
.reset(
110 new std::string(ManifestURL::GetHomepageURL(&extension
).spec()));
112 system
->management_policy()->UserMayModifySettings(&extension
, NULL
);
113 info
->is_app
= extension
.is_app();
115 if (extension
.is_legacy_packaged_app())
116 info
->type
= management::EXTENSION_TYPE_LEGACY_PACKAGED_APP
;
117 else if (extension
.is_hosted_app())
118 info
->type
= management::EXTENSION_TYPE_HOSTED_APP
;
120 info
->type
= management::EXTENSION_TYPE_PACKAGED_APP
;
121 } else if (extension
.is_theme()) {
122 info
->type
= management::EXTENSION_TYPE_THEME
;
124 info
->type
= management::EXTENSION_TYPE_EXTENSION
;
128 info
->disabled_reason
= management::EXTENSION_DISABLED_REASON_NONE
;
130 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(context
);
131 if (prefs
->DidExtensionEscalatePermissions(extension
.id())) {
132 info
->disabled_reason
=
133 management::EXTENSION_DISABLED_REASON_PERMISSIONS_INCREASE
;
135 info
->disabled_reason
=
136 management::EXTENSION_DISABLED_REASON_UNKNOWN
;
140 if (!ManifestURL::GetUpdateURL(&extension
).is_empty()) {
141 info
->update_url
.reset(
142 new std::string(ManifestURL::GetUpdateURL(&extension
).spec()));
145 if (extension
.is_app()) {
146 info
->app_launch_url
.reset(
147 new std::string(delegate
->GetFullLaunchURL(&extension
).spec()));
150 const ExtensionIconSet::IconMap
& icons
=
151 IconsInfo::GetIcons(&extension
).map();
152 if (!icons
.empty()) {
153 info
->icons
.reset(new IconInfoList());
154 ExtensionIconSet::IconMap::const_iterator icon_iter
;
155 for (icon_iter
= icons
.begin(); icon_iter
!= icons
.end(); ++icon_iter
) {
156 management::IconInfo
* icon_info
= new management::IconInfo();
157 icon_info
->size
= icon_iter
->first
;
159 delegate
->GetIconURL(&extension
, icon_info
->size
,
160 ExtensionIconSet::MATCH_EXACTLY
, false, nullptr);
161 icon_info
->url
= url
.spec();
162 info
->icons
->push_back(make_linked_ptr
<management::IconInfo
>(icon_info
));
166 const std::set
<std::string
> perms
=
167 extension
.permissions_data()->active_permissions()->GetAPIsAsStrings();
168 if (!perms
.empty()) {
169 std::set
<std::string
>::const_iterator perms_iter
;
170 for (perms_iter
= perms
.begin(); perms_iter
!= perms
.end(); ++perms_iter
)
171 info
->permissions
.push_back(*perms_iter
);
174 if (!extension
.is_hosted_app()) {
175 // Skip host permissions for hosted apps.
176 const URLPatternSet host_perms
=
177 extension
.permissions_data()->active_permissions()->explicit_hosts();
178 if (!host_perms
.is_empty()) {
179 for (URLPatternSet::const_iterator iter
= host_perms
.begin();
180 iter
!= host_perms
.end(); ++iter
) {
181 info
->host_permissions
.push_back(iter
->GetAsString());
186 switch (extension
.location()) {
187 case Manifest::INTERNAL
:
188 info
->install_type
= management::EXTENSION_INSTALL_TYPE_NORMAL
;
190 case Manifest::UNPACKED
:
191 case Manifest::COMMAND_LINE
:
192 info
->install_type
= management::EXTENSION_INSTALL_TYPE_DEVELOPMENT
;
194 case Manifest::EXTERNAL_PREF
:
195 case Manifest::EXTERNAL_REGISTRY
:
196 case Manifest::EXTERNAL_PREF_DOWNLOAD
:
197 info
->install_type
= management::EXTENSION_INSTALL_TYPE_SIDELOAD
;
199 case Manifest::EXTERNAL_POLICY
:
200 case Manifest::EXTERNAL_POLICY_DOWNLOAD
:
201 info
->install_type
= management::EXTENSION_INSTALL_TYPE_ADMIN
;
203 case Manifest::NUM_LOCATIONS
:
205 case Manifest::INVALID_LOCATION
:
206 case Manifest::COMPONENT
:
207 case Manifest::EXTERNAL_COMPONENT
:
208 info
->install_type
= management::EXTENSION_INSTALL_TYPE_OTHER
;
212 info
->launch_type
= management::LAUNCH_TYPE_NONE
;
213 if (extension
.is_app()) {
214 LaunchType launch_type
;
215 if (extension
.is_platform_app()) {
216 launch_type
= LAUNCH_TYPE_WINDOW
;
219 delegate
->GetLaunchType(ExtensionPrefs::Get(context
), &extension
);
222 switch (launch_type
) {
223 case LAUNCH_TYPE_PINNED
:
224 info
->launch_type
= management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB
;
226 case LAUNCH_TYPE_REGULAR
:
227 info
->launch_type
= management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB
;
229 case LAUNCH_TYPE_FULLSCREEN
:
230 info
->launch_type
= management::LAUNCH_TYPE_OPEN_FULL_SCREEN
;
232 case LAUNCH_TYPE_WINDOW
:
233 info
->launch_type
= management::LAUNCH_TYPE_OPEN_AS_WINDOW
;
235 case LAUNCH_TYPE_INVALID
:
236 case NUM_LAUNCH_TYPES
:
240 info
->available_launch_types
.reset(new std::vector
<management::LaunchType
>(
241 GetAvailableLaunchTypes(extension
, delegate
)));
247 bool ShouldNotBeVisible(const Extension
* extension
,
248 content::BrowserContext
* context
) {
249 return (extension
->ShouldNotBeVisible() ||
250 ExtensionPrefs::Get(context
)->IsEphemeralApp(extension
->id()));
253 void AddExtensionInfo(const ExtensionSet
& extensions
,
254 ExtensionInfoList
* extension_list
,
255 content::BrowserContext
* context
) {
256 for (ExtensionSet::const_iterator iter
= extensions
.begin();
257 iter
!= extensions
.end(); ++iter
) {
258 const Extension
& extension
= *iter
->get();
260 if (ShouldNotBeVisible(&extension
, context
))
261 continue; // Skip built-in extensions/apps.
263 extension_list
->push_back(make_linked_ptr
<management::ExtensionInfo
>(
264 CreateExtensionInfo(extension
, context
).release()));
270 bool ManagementGetAllFunction::RunSync() {
271 ExtensionInfoList extensions
;
272 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser_context());
274 AddExtensionInfo(registry
->enabled_extensions(), &extensions
,
276 AddExtensionInfo(registry
->disabled_extensions(), &extensions
,
278 AddExtensionInfo(registry
->terminated_extensions(), &extensions
,
281 results_
= management::GetAll::Results::Create(extensions
);
285 bool ManagementGetFunction::RunSync() {
286 scoped_ptr
<management::Get::Params
> params(
287 management::Get::Params::Create(*args_
));
288 EXTENSION_FUNCTION_VALIDATE(params
.get());
289 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser_context());
291 const Extension
* extension
=
292 registry
->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
295 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
299 scoped_ptr
<management::ExtensionInfo
> info
=
300 CreateExtensionInfo(*extension
, browser_context());
301 results_
= management::Get::Results::Create(*info
);
306 bool ManagementGetSelfFunction::RunSync() {
307 scoped_ptr
<management::ExtensionInfo
> info
=
308 CreateExtensionInfo(*extension_
, browser_context());
309 results_
= management::Get::Results::Create(*info
);
314 bool ManagementGetPermissionWarningsByIdFunction::RunSync() {
315 scoped_ptr
<management::GetPermissionWarningsById::Params
> params(
316 management::GetPermissionWarningsById::Params::Create(*args_
));
317 EXTENSION_FUNCTION_VALIDATE(params
.get());
319 const Extension
* extension
=
320 ExtensionRegistry::Get(browser_context())
321 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
324 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
328 std::vector
<std::string
> warnings
= CreateWarningsList(extension
);
329 results_
= management::GetPermissionWarningsById::Results::Create(warnings
);
333 bool ManagementGetPermissionWarningsByManifestFunction::RunAsync() {
334 scoped_ptr
<management::GetPermissionWarningsByManifest::Params
> params(
335 management::GetPermissionWarningsByManifest::Params::Create(*args_
));
336 EXTENSION_FUNCTION_VALIDATE(params
.get());
338 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
339 ->Get(browser_context())
343 delegate
->GetPermissionWarningsByManifestFunctionDelegate(
344 this, params
->manifest_str
);
346 // Matched with a Release() in OnParseSuccess/Failure().
349 // Response is sent async in OnParseSuccess/Failure().
352 // TODO(lfg) add error string
358 void ManagementGetPermissionWarningsByManifestFunction::OnParseSuccess(
359 scoped_ptr
<base::Value
> value
) {
360 if (!value
->IsType(base::Value::TYPE_DICTIONARY
)) {
361 OnParseFailure(keys::kManifestParseError
);
364 const base::DictionaryValue
* parsed_manifest
=
365 static_cast<const base::DictionaryValue
*>(value
.get());
367 scoped_refptr
<Extension
> extension
=
368 Extension::Create(base::FilePath(), Manifest::INVALID_LOCATION
,
369 *parsed_manifest
, Extension::NO_FLAGS
, &error_
);
371 OnParseFailure(keys::kExtensionCreateError
);
375 std::vector
<std::string
> warnings
= CreateWarningsList(extension
.get());
377 management::GetPermissionWarningsByManifest::Results::Create(warnings
);
380 // Matched with AddRef() in RunAsync().
384 void ManagementGetPermissionWarningsByManifestFunction::OnParseFailure(
385 const std::string
& error
) {
389 // Matched with AddRef() in RunAsync().
393 bool ManagementLaunchAppFunction::RunSync() {
394 scoped_ptr
<management::LaunchApp::Params
> params(
395 management::LaunchApp::Params::Create(*args_
));
396 EXTENSION_FUNCTION_VALIDATE(params
.get());
397 const Extension
* extension
=
398 ExtensionRegistry::Get(browser_context())
399 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
402 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
405 if (!extension
->is_app()) {
406 error_
= ErrorUtils::FormatErrorMessage(keys::kNotAnAppError
, params
->id
);
410 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
411 ->Get(browser_context())
413 return delegate
->LaunchAppFunctionDelegate(extension
, browser_context());
416 ManagementSetEnabledFunction::ManagementSetEnabledFunction() {
419 ManagementSetEnabledFunction::~ManagementSetEnabledFunction() {
422 ExtensionFunction::ResponseAction
ManagementSetEnabledFunction::Run() {
423 scoped_ptr
<management::SetEnabled::Params
> params(
424 management::SetEnabled::Params::Create(*args_
));
425 EXTENSION_FUNCTION_VALIDATE(params
.get());
426 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser_context());
427 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
428 ->Get(browser_context())
431 extension_id_
= params
->id
;
433 const Extension
* extension
=
434 registry
->GetExtensionById(extension_id_
, ExtensionRegistry::EVERYTHING
);
435 if (!extension
|| ShouldNotBeVisible(extension
, browser_context()))
436 return RespondNow(Error(keys::kNoExtensionError
, extension_id_
));
438 bool enabled
= params
->enabled
;
439 const ManagementPolicy
* policy
=
440 ExtensionSystem::Get(browser_context())->management_policy();
441 if (!policy
->UserMayModifySettings(extension
, nullptr) ||
442 (!enabled
&& policy
->MustRemainEnabled(extension
, nullptr)) ||
443 (enabled
&& policy
->MustRemainDisabled(extension
, nullptr, nullptr))) {
444 return RespondNow(Error(keys::kUserCantModifyError
, extension_id_
));
447 bool currently_enabled
=
448 registry
->enabled_extensions().Contains(extension_id_
) ||
449 registry
->terminated_extensions().Contains(extension_id_
);
451 if (!currently_enabled
&& enabled
) {
452 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(browser_context());
453 if (prefs
->DidExtensionEscalatePermissions(extension_id_
)) {
455 return RespondNow(Error(keys::kGestureNeededForEscalationError
));
457 AddRef(); // Matched in InstallUIProceed/InstallUIAbort
458 install_prompt_
= delegate
->SetEnabledFunctionDelegate(this, extension
);
459 return RespondLater();
461 if (prefs
->GetDisableReasons(extension_id_
) &
462 Extension::DISABLE_UNSUPPORTED_REQUIREMENT
) {
463 // Recheck the requirements.
464 requirements_checker_
= delegate
->CreateRequirementsChecker();
465 requirements_checker_
->Check(
467 base::Bind(&ManagementSetEnabledFunction::OnRequirementsChecked
,
468 this)); // This bind creates a reference.
469 return RespondLater();
471 delegate
->EnableExtension(browser_context(), extension_id_
);
472 } else if (currently_enabled
&& !params
->enabled
) {
473 delegate
->DisableExtension(browser_context(), extension_id_
,
474 Extension::DISABLE_USER_ACTION
);
477 return RespondNow(NoArguments());
480 void ManagementSetEnabledFunction::InstallUIProceed() {
481 ManagementAPI::GetFactoryInstance()
482 ->Get(browser_context())
484 ->EnableExtension(browser_context(), extension_id_
);
485 Respond(OneArgument(new base::FundamentalValue(true)));
489 void ManagementSetEnabledFunction::InstallUIAbort(bool user_initiated
) {
490 Respond(Error(keys::kUserDidNotReEnableError
));
494 void ManagementSetEnabledFunction::OnRequirementsChecked(
495 const std::vector
<std::string
>& requirements_errors
) {
496 if (requirements_errors
.empty()) {
497 ManagementAPI::GetFactoryInstance()->Get(browser_context())->GetDelegate()->
498 EnableExtension(browser_context(), extension_id_
);
499 Respond(NoArguments());
501 // TODO(devlin): Should we really be noisy here all the time?
502 Respond(Error(keys::kMissingRequirementsError
,
503 base::JoinString(requirements_errors
, " ")));
507 ManagementUninstallFunctionBase::ManagementUninstallFunctionBase() {
510 ManagementUninstallFunctionBase::~ManagementUninstallFunctionBase() {
513 ExtensionFunction::ResponseAction
ManagementUninstallFunctionBase::Uninstall(
514 const std::string
& target_extension_id
,
515 bool show_confirm_dialog
) {
516 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
517 ->Get(browser_context())
519 target_extension_id_
= target_extension_id
;
520 const Extension
* target_extension
=
521 extensions::ExtensionRegistry::Get(browser_context())
522 ->GetExtensionById(target_extension_id_
,
523 ExtensionRegistry::EVERYTHING
);
524 if (!target_extension
||
525 ShouldNotBeVisible(target_extension
, browser_context())) {
526 return RespondNow(Error(keys::kNoExtensionError
, target_extension_id_
));
529 ManagementPolicy
* policy
=
530 ExtensionSystem::Get(browser_context())->management_policy();
531 if (!policy
->UserMayModifySettings(target_extension
, nullptr) ||
532 policy
->MustRemainInstalled(target_extension
, nullptr)) {
533 return RespondNow(Error(keys::kUserCantModifyError
, target_extension_id_
));
536 // Note: null extension() means it's WebUI.
537 bool self_uninstall
= extension() && extension_id() == target_extension_id_
;
538 // We need to show a dialog for any extension uninstalling another extension.
539 show_confirm_dialog
|= !self_uninstall
;
541 if (show_confirm_dialog
&& !user_gesture())
542 return RespondNow(Error(keys::kGestureNeededForUninstallError
));
544 if (show_confirm_dialog
) {
545 // We show the programmatic uninstall ui for extensions uninstalling
547 bool show_programmatic_uninstall_ui
= !self_uninstall
&& extension();
548 AddRef(); // Balanced in OnExtensionUninstallDialogClosed.
549 // TODO(devlin): A method called "UninstallFunctionDelegate" does not in
550 // any way imply that this actually creates a dialog and runs it.
551 uninstall_dialog_
= delegate
->UninstallFunctionDelegate(
552 this, target_extension
, show_programmatic_uninstall_ui
);
553 } else { // No confirm dialog.
554 base::MessageLoop::current()->PostTask(
556 base::Bind(&ManagementUninstallFunctionBase::UninstallExtension
, this));
559 return RespondLater();
562 void ManagementUninstallFunctionBase::Finish(bool did_start_uninstall
,
563 const std::string
& error
) {
564 Respond(did_start_uninstall
? NoArguments() : Error(error
));
567 void ManagementUninstallFunctionBase::OnExtensionUninstallDialogClosed(
568 bool did_start_uninstall
,
569 const base::string16
& error
) {
570 Finish(did_start_uninstall
,
571 ErrorUtils::FormatErrorMessage(keys::kUninstallCanceledError
,
572 target_extension_id_
));
573 Release(); // Balanced in Uninstall().
576 void ManagementUninstallFunctionBase::UninstallExtension() {
577 // The extension can be uninstalled in another window while the UI was
578 // showing. Do nothing in that case.
579 const Extension
* target_extension
=
580 extensions::ExtensionRegistry::Get(browser_context())
581 ->GetExtensionById(target_extension_id_
,
582 ExtensionRegistry::EVERYTHING
);
584 bool success
= false;
585 if (target_extension
) {
586 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
587 ->Get(browser_context())
589 base::string16 utf16_error
;
590 success
= delegate
->UninstallExtension(
591 browser_context(), target_extension_id_
,
592 extensions::UNINSTALL_REASON_MANAGEMENT_API
,
593 base::Bind(&base::DoNothing
), &utf16_error
);
594 error
= base::UTF16ToUTF8(utf16_error
);
596 error
= ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
,
597 target_extension_id_
);
599 Finish(success
, error
);
602 ManagementUninstallFunction::ManagementUninstallFunction() {
605 ManagementUninstallFunction::~ManagementUninstallFunction() {
608 ExtensionFunction::ResponseAction
ManagementUninstallFunction::Run() {
609 scoped_ptr
<management::Uninstall::Params
> params(
610 management::Uninstall::Params::Create(*args_
));
611 EXTENSION_FUNCTION_VALIDATE(params
.get());
613 bool show_confirm_dialog
= params
->options
.get() &&
614 params
->options
->show_confirm_dialog
.get() &&
615 *params
->options
->show_confirm_dialog
;
616 return Uninstall(params
->id
, show_confirm_dialog
);
619 ManagementUninstallSelfFunction::ManagementUninstallSelfFunction() {
622 ManagementUninstallSelfFunction::~ManagementUninstallSelfFunction() {
625 ExtensionFunction::ResponseAction
ManagementUninstallSelfFunction::Run() {
626 scoped_ptr
<management::UninstallSelf::Params
> params(
627 management::UninstallSelf::Params::Create(*args_
));
628 EXTENSION_FUNCTION_VALIDATE(params
.get());
629 EXTENSION_FUNCTION_VALIDATE(extension_
.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(extension_
->id(), show_confirm_dialog
);
637 ManagementCreateAppShortcutFunction::ManagementCreateAppShortcutFunction() {
640 ManagementCreateAppShortcutFunction::~ManagementCreateAppShortcutFunction() {
644 void ManagementCreateAppShortcutFunction::SetAutoConfirmForTest(
645 bool should_proceed
) {
646 auto_confirm_for_test
= should_proceed
? PROCEED
: ABORT
;
649 void ManagementCreateAppShortcutFunction::OnCloseShortcutPrompt(bool created
) {
651 error_
= keys::kCreateShortcutCanceledError
;
652 SendResponse(created
);
656 bool ManagementCreateAppShortcutFunction::RunAsync() {
657 if (!user_gesture()) {
658 error_
= keys::kGestureNeededForCreateAppShortcutError
;
662 scoped_ptr
<management::CreateAppShortcut::Params
> params(
663 management::CreateAppShortcut::Params::Create(*args_
));
664 EXTENSION_FUNCTION_VALIDATE(params
.get());
665 const Extension
* extension
=
666 ExtensionRegistry::Get(browser_context())
667 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
670 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
674 if (!extension
->is_app()) {
675 error_
= ErrorUtils::FormatErrorMessage(keys::kNotAnAppError
, params
->id
);
679 #if defined(OS_MACOSX)
680 if (!extension
->is_platform_app()) {
681 error_
= keys::kCreateOnlyPackagedAppShortcutMac
;
686 if (auto_confirm_for_test
!= DO_NOT_SKIP
) {
687 // Matched with a Release() in OnCloseShortcutPrompt().
690 OnCloseShortcutPrompt(auto_confirm_for_test
== PROCEED
);
695 if (ManagementAPI::GetFactoryInstance()
696 ->Get(browser_context())
698 ->CreateAppShortcutFunctionDelegate(this, extension
)) {
699 // Matched with a Release() in OnCloseShortcutPrompt().
703 // Response is sent async in OnCloseShortcutPrompt().
707 bool ManagementSetLaunchTypeFunction::RunSync() {
708 if (!user_gesture()) {
709 error_
= keys::kGestureNeededForSetLaunchTypeError
;
713 scoped_ptr
<management::SetLaunchType::Params
> params(
714 management::SetLaunchType::Params::Create(*args_
));
715 EXTENSION_FUNCTION_VALIDATE(params
.get());
716 const Extension
* extension
=
717 ExtensionRegistry::Get(browser_context())
718 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
719 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
720 ->Get(browser_context())
724 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
728 if (!extension
->is_app()) {
729 error_
= ErrorUtils::FormatErrorMessage(keys::kNotAnAppError
, params
->id
);
733 std::vector
<management::LaunchType
> available_launch_types
=
734 GetAvailableLaunchTypes(*extension
, delegate
);
736 management::LaunchType app_launch_type
= params
->launch_type
;
737 if (std::find(available_launch_types
.begin(), available_launch_types
.end(),
738 app_launch_type
) == available_launch_types
.end()) {
739 error_
= keys::kLaunchTypeNotAvailableError
;
743 LaunchType launch_type
= LAUNCH_TYPE_DEFAULT
;
744 switch (app_launch_type
) {
745 case management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB
:
746 launch_type
= LAUNCH_TYPE_PINNED
;
748 case management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB
:
749 launch_type
= LAUNCH_TYPE_REGULAR
;
751 case management::LAUNCH_TYPE_OPEN_FULL_SCREEN
:
752 launch_type
= LAUNCH_TYPE_FULLSCREEN
;
754 case management::LAUNCH_TYPE_OPEN_AS_WINDOW
:
755 launch_type
= LAUNCH_TYPE_WINDOW
;
757 case management::LAUNCH_TYPE_NONE
:
761 delegate
->SetLaunchType(browser_context(), params
->id
, launch_type
);
766 ManagementGenerateAppForLinkFunction::ManagementGenerateAppForLinkFunction() {
769 ManagementGenerateAppForLinkFunction::~ManagementGenerateAppForLinkFunction() {
772 void ManagementGenerateAppForLinkFunction::FinishCreateBookmarkApp(
773 const Extension
* extension
,
774 const WebApplicationInfo
& web_app_info
) {
776 scoped_ptr
<management::ExtensionInfo
> info
=
777 CreateExtensionInfo(*extension
, browser_context());
778 results_
= management::GenerateAppForLink::Results::Create(*info
);
783 error_
= keys::kGenerateAppForLinkInstallError
;
789 bool ManagementGenerateAppForLinkFunction::RunAsync() {
790 if (!user_gesture()) {
791 error_
= keys::kGestureNeededForGenerateAppForLinkError
;
795 scoped_ptr
<management::GenerateAppForLink::Params
> params(
796 management::GenerateAppForLink::Params::Create(*args_
));
797 EXTENSION_FUNCTION_VALIDATE(params
.get());
799 GURL
launch_url(params
->url
);
800 if (!launch_url
.is_valid() || !launch_url
.SchemeIsHTTPOrHTTPS()) {
802 ErrorUtils::FormatErrorMessage(keys::kInvalidURLError
, params
->url
);
806 if (params
->title
.empty()) {
807 error_
= keys::kEmptyTitleError
;
811 app_for_link_delegate_
=
812 ManagementAPI::GetFactoryInstance()
813 ->Get(browser_context())
815 ->GenerateAppForLinkFunctionDelegate(this, browser_context(),
816 params
->title
, launch_url
);
818 // Matched with a Release() in FinishCreateBookmarkApp().
821 // Response is sent async in FinishCreateBookmarkApp().
825 ManagementEventRouter::ManagementEventRouter(content::BrowserContext
* context
)
826 : browser_context_(context
), extension_registry_observer_(this) {
827 extension_registry_observer_
.Add(ExtensionRegistry::Get(browser_context_
));
830 ManagementEventRouter::~ManagementEventRouter() {
833 void ManagementEventRouter::OnExtensionLoaded(
834 content::BrowserContext
* browser_context
,
835 const Extension
* extension
) {
836 BroadcastEvent(extension
, events::MANAGEMENT_ON_ENABLED
,
837 management::OnEnabled::kEventName
);
840 void ManagementEventRouter::OnExtensionUnloaded(
841 content::BrowserContext
* browser_context
,
842 const Extension
* extension
,
843 UnloadedExtensionInfo::Reason reason
) {
844 BroadcastEvent(extension
, events::MANAGEMENT_ON_DISABLED
,
845 management::OnDisabled::kEventName
);
848 void ManagementEventRouter::OnExtensionInstalled(
849 content::BrowserContext
* browser_context
,
850 const Extension
* extension
,
852 BroadcastEvent(extension
, events::MANAGEMENT_ON_INSTALLED
,
853 management::OnInstalled::kEventName
);
856 void ManagementEventRouter::OnExtensionUninstalled(
857 content::BrowserContext
* browser_context
,
858 const Extension
* extension
,
859 extensions::UninstallReason reason
) {
860 BroadcastEvent(extension
, events::MANAGEMENT_ON_UNINSTALLED
,
861 management::OnUninstalled::kEventName
);
864 void ManagementEventRouter::BroadcastEvent(
865 const Extension
* extension
,
866 events::HistogramValue histogram_value
,
867 const char* event_name
) {
868 if (ShouldNotBeVisible(extension
, browser_context_
))
869 return; // Don't dispatch events for built-in extenions.
870 scoped_ptr
<base::ListValue
> args(new base::ListValue());
871 if (event_name
== management::OnUninstalled::kEventName
) {
872 args
->Append(new base::StringValue(extension
->id()));
874 scoped_ptr
<management::ExtensionInfo
> info
=
875 CreateExtensionInfo(*extension
, browser_context_
);
876 args
->Append(info
->ToValue().release());
879 EventRouter::Get(browser_context_
)
880 ->BroadcastEvent(scoped_ptr
<Event
>(
881 new Event(histogram_value
, event_name
, args
.Pass())));
884 ManagementAPI::ManagementAPI(content::BrowserContext
* context
)
885 : browser_context_(context
),
886 delegate_(ExtensionsAPIClient::Get()->CreateManagementAPIDelegate()) {
887 EventRouter
* event_router
= EventRouter::Get(browser_context_
);
888 event_router
->RegisterObserver(this, management::OnInstalled::kEventName
);
889 event_router
->RegisterObserver(this, management::OnUninstalled::kEventName
);
890 event_router
->RegisterObserver(this, management::OnEnabled::kEventName
);
891 event_router
->RegisterObserver(this, management::OnDisabled::kEventName
);
894 ManagementAPI::~ManagementAPI() {
897 void ManagementAPI::Shutdown() {
898 EventRouter::Get(browser_context_
)->UnregisterObserver(this);
901 static base::LazyInstance
<BrowserContextKeyedAPIFactory
<ManagementAPI
>>
902 g_factory
= LAZY_INSTANCE_INITIALIZER
;
905 BrowserContextKeyedAPIFactory
<ManagementAPI
>*
906 ManagementAPI::GetFactoryInstance() {
907 return g_factory
.Pointer();
910 void ManagementAPI::OnListenerAdded(const EventListenerInfo
& details
) {
911 management_event_router_
.reset(new ManagementEventRouter(browser_context_
));
912 EventRouter::Get(browser_context_
)->UnregisterObserver(this);
915 } // namespace extensions