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 for (const extensions::PermissionMessageString
& str
:
65 extension
->permissions_data()->GetPermissionMessageStrings()) {
66 warnings_list
.push_back(base::UTF16ToUTF8(str
.message
));
72 std::vector
<management::LaunchType
> GetAvailableLaunchTypes(
73 const Extension
& extension
,
74 const ManagementAPIDelegate
* delegate
) {
75 std::vector
<management::LaunchType
> launch_type_list
;
76 if (extension
.is_platform_app()) {
77 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW
);
78 return launch_type_list
;
81 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB
);
82 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW
);
84 if (!delegate
->IsNewBookmarkAppsEnabled()) {
85 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB
);
86 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_FULL_SCREEN
);
88 return launch_type_list
;
91 scoped_ptr
<management::ExtensionInfo
> CreateExtensionInfo(
92 const Extension
& extension
,
93 content::BrowserContext
* context
) {
94 ExtensionSystem
* system
= ExtensionSystem::Get(context
);
95 ExtensionRegistry
* registry
= ExtensionRegistry::Get(context
);
96 const ManagementAPIDelegate
* delegate
=
97 ManagementAPI::GetFactoryInstance()->Get(context
)->GetDelegate();
98 scoped_ptr
<management::ExtensionInfo
> info(new management::ExtensionInfo());
100 info
->id
= extension
.id();
101 info
->name
= extension
.name();
102 info
->short_name
= extension
.short_name();
103 info
->enabled
= registry
->enabled_extensions().Contains(info
->id
);
104 info
->offline_enabled
= OfflineEnabledInfo::IsOfflineEnabled(&extension
);
105 info
->version
= extension
.VersionString();
106 info
->description
= extension
.description();
107 info
->options_url
= OptionsPageInfo::GetOptionsPage(&extension
).spec();
108 info
->homepage_url
.reset(
109 new std::string(ManifestURL::GetHomepageURL(&extension
).spec()));
111 system
->management_policy()->UserMayModifySettings(&extension
, NULL
);
112 info
->is_app
= extension
.is_app();
114 if (extension
.is_legacy_packaged_app())
115 info
->type
= management::EXTENSION_TYPE_LEGACY_PACKAGED_APP
;
116 else if (extension
.is_hosted_app())
117 info
->type
= management::EXTENSION_TYPE_HOSTED_APP
;
119 info
->type
= management::EXTENSION_TYPE_PACKAGED_APP
;
120 } else if (extension
.is_theme()) {
121 info
->type
= management::EXTENSION_TYPE_THEME
;
123 info
->type
= management::EXTENSION_TYPE_EXTENSION
;
127 info
->disabled_reason
= management::EXTENSION_DISABLED_REASON_NONE
;
129 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(context
);
130 if (prefs
->DidExtensionEscalatePermissions(extension
.id())) {
131 info
->disabled_reason
=
132 management::EXTENSION_DISABLED_REASON_PERMISSIONS_INCREASE
;
134 info
->disabled_reason
=
135 management::EXTENSION_DISABLED_REASON_UNKNOWN
;
139 if (!ManifestURL::GetUpdateURL(&extension
).is_empty()) {
140 info
->update_url
.reset(
141 new std::string(ManifestURL::GetUpdateURL(&extension
).spec()));
144 if (extension
.is_app()) {
145 info
->app_launch_url
.reset(
146 new std::string(delegate
->GetFullLaunchURL(&extension
).spec()));
149 const ExtensionIconSet::IconMap
& icons
=
150 IconsInfo::GetIcons(&extension
).map();
151 if (!icons
.empty()) {
152 info
->icons
.reset(new IconInfoList());
153 ExtensionIconSet::IconMap::const_iterator icon_iter
;
154 for (icon_iter
= icons
.begin(); icon_iter
!= icons
.end(); ++icon_iter
) {
155 management::IconInfo
* icon_info
= new management::IconInfo();
156 icon_info
->size
= icon_iter
->first
;
158 delegate
->GetIconURL(&extension
, icon_info
->size
,
159 ExtensionIconSet::MATCH_EXACTLY
, false, nullptr);
160 icon_info
->url
= url
.spec();
161 info
->icons
->push_back(make_linked_ptr
<management::IconInfo
>(icon_info
));
165 const std::set
<std::string
> perms
=
166 extension
.permissions_data()->active_permissions()->GetAPIsAsStrings();
167 if (!perms
.empty()) {
168 std::set
<std::string
>::const_iterator perms_iter
;
169 for (perms_iter
= perms
.begin(); perms_iter
!= perms
.end(); ++perms_iter
)
170 info
->permissions
.push_back(*perms_iter
);
173 if (!extension
.is_hosted_app()) {
174 // Skip host permissions for hosted apps.
175 const URLPatternSet host_perms
=
176 extension
.permissions_data()->active_permissions()->explicit_hosts();
177 if (!host_perms
.is_empty()) {
178 for (URLPatternSet::const_iterator iter
= host_perms
.begin();
179 iter
!= host_perms
.end(); ++iter
) {
180 info
->host_permissions
.push_back(iter
->GetAsString());
185 switch (extension
.location()) {
186 case Manifest::INTERNAL
:
187 info
->install_type
= management::EXTENSION_INSTALL_TYPE_NORMAL
;
189 case Manifest::UNPACKED
:
190 case Manifest::COMMAND_LINE
:
191 info
->install_type
= management::EXTENSION_INSTALL_TYPE_DEVELOPMENT
;
193 case Manifest::EXTERNAL_PREF
:
194 case Manifest::EXTERNAL_REGISTRY
:
195 case Manifest::EXTERNAL_PREF_DOWNLOAD
:
196 info
->install_type
= management::EXTENSION_INSTALL_TYPE_SIDELOAD
;
198 case Manifest::EXTERNAL_POLICY
:
199 case Manifest::EXTERNAL_POLICY_DOWNLOAD
:
200 info
->install_type
= management::EXTENSION_INSTALL_TYPE_ADMIN
;
202 case Manifest::NUM_LOCATIONS
:
204 case Manifest::INVALID_LOCATION
:
205 case Manifest::COMPONENT
:
206 case Manifest::EXTERNAL_COMPONENT
:
207 info
->install_type
= management::EXTENSION_INSTALL_TYPE_OTHER
;
211 info
->launch_type
= management::LAUNCH_TYPE_NONE
;
212 if (extension
.is_app()) {
213 LaunchType launch_type
;
214 if (extension
.is_platform_app()) {
215 launch_type
= LAUNCH_TYPE_WINDOW
;
218 delegate
->GetLaunchType(ExtensionPrefs::Get(context
), &extension
);
221 switch (launch_type
) {
222 case LAUNCH_TYPE_PINNED
:
223 info
->launch_type
= management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB
;
225 case LAUNCH_TYPE_REGULAR
:
226 info
->launch_type
= management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB
;
228 case LAUNCH_TYPE_FULLSCREEN
:
229 info
->launch_type
= management::LAUNCH_TYPE_OPEN_FULL_SCREEN
;
231 case LAUNCH_TYPE_WINDOW
:
232 info
->launch_type
= management::LAUNCH_TYPE_OPEN_AS_WINDOW
;
234 case LAUNCH_TYPE_INVALID
:
235 case NUM_LAUNCH_TYPES
:
239 info
->available_launch_types
.reset(new std::vector
<management::LaunchType
>(
240 GetAvailableLaunchTypes(extension
, delegate
)));
246 bool ShouldNotBeVisible(const Extension
* extension
,
247 content::BrowserContext
* context
) {
248 return (extension
->ShouldNotBeVisible() ||
249 ExtensionPrefs::Get(context
)->IsEphemeralApp(extension
->id()));
252 void AddExtensionInfo(const ExtensionSet
& extensions
,
253 ExtensionInfoList
* extension_list
,
254 content::BrowserContext
* context
) {
255 for (ExtensionSet::const_iterator iter
= extensions
.begin();
256 iter
!= extensions
.end(); ++iter
) {
257 const Extension
& extension
= *iter
->get();
259 if (ShouldNotBeVisible(&extension
, context
))
260 continue; // Skip built-in extensions/apps.
262 extension_list
->push_back(make_linked_ptr
<management::ExtensionInfo
>(
263 CreateExtensionInfo(extension
, context
).release()));
269 bool ManagementGetAllFunction::RunSync() {
270 ExtensionInfoList extensions
;
271 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser_context());
273 AddExtensionInfo(registry
->enabled_extensions(), &extensions
,
275 AddExtensionInfo(registry
->disabled_extensions(), &extensions
,
277 AddExtensionInfo(registry
->terminated_extensions(), &extensions
,
280 results_
= management::GetAll::Results::Create(extensions
);
284 bool ManagementGetFunction::RunSync() {
285 scoped_ptr
<management::Get::Params
> params(
286 management::Get::Params::Create(*args_
));
287 EXTENSION_FUNCTION_VALIDATE(params
.get());
288 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser_context());
290 const Extension
* extension
=
291 registry
->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
294 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
298 scoped_ptr
<management::ExtensionInfo
> info
=
299 CreateExtensionInfo(*extension
, browser_context());
300 results_
= management::Get::Results::Create(*info
);
305 bool ManagementGetSelfFunction::RunSync() {
306 scoped_ptr
<management::ExtensionInfo
> info
=
307 CreateExtensionInfo(*extension_
, browser_context());
308 results_
= management::Get::Results::Create(*info
);
313 bool ManagementGetPermissionWarningsByIdFunction::RunSync() {
314 scoped_ptr
<management::GetPermissionWarningsById::Params
> params(
315 management::GetPermissionWarningsById::Params::Create(*args_
));
316 EXTENSION_FUNCTION_VALIDATE(params
.get());
318 const Extension
* extension
=
319 ExtensionRegistry::Get(browser_context())
320 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
323 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
327 std::vector
<std::string
> warnings
= CreateWarningsList(extension
);
328 results_
= management::GetPermissionWarningsById::Results::Create(warnings
);
332 bool ManagementGetPermissionWarningsByManifestFunction::RunAsync() {
333 scoped_ptr
<management::GetPermissionWarningsByManifest::Params
> params(
334 management::GetPermissionWarningsByManifest::Params::Create(*args_
));
335 EXTENSION_FUNCTION_VALIDATE(params
.get());
337 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
338 ->Get(browser_context())
342 delegate
->GetPermissionWarningsByManifestFunctionDelegate(
343 this, params
->manifest_str
);
345 // Matched with a Release() in OnParseSuccess/Failure().
348 // Response is sent async in OnParseSuccess/Failure().
351 // TODO(lfg) add error string
357 void ManagementGetPermissionWarningsByManifestFunction::OnParseSuccess(
358 scoped_ptr
<base::Value
> value
) {
359 if (!value
->IsType(base::Value::TYPE_DICTIONARY
)) {
360 OnParseFailure(keys::kManifestParseError
);
363 const base::DictionaryValue
* parsed_manifest
=
364 static_cast<const base::DictionaryValue
*>(value
.get());
366 scoped_refptr
<Extension
> extension
=
367 Extension::Create(base::FilePath(), Manifest::INVALID_LOCATION
,
368 *parsed_manifest
, Extension::NO_FLAGS
, &error_
);
370 OnParseFailure(keys::kExtensionCreateError
);
374 std::vector
<std::string
> warnings
= CreateWarningsList(extension
.get());
376 management::GetPermissionWarningsByManifest::Results::Create(warnings
);
379 // Matched with AddRef() in RunAsync().
383 void ManagementGetPermissionWarningsByManifestFunction::OnParseFailure(
384 const std::string
& error
) {
388 // Matched with AddRef() in RunAsync().
392 bool ManagementLaunchAppFunction::RunSync() {
393 scoped_ptr
<management::LaunchApp::Params
> params(
394 management::LaunchApp::Params::Create(*args_
));
395 EXTENSION_FUNCTION_VALIDATE(params
.get());
396 const Extension
* extension
=
397 ExtensionRegistry::Get(browser_context())
398 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
401 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
404 if (!extension
->is_app()) {
405 error_
= ErrorUtils::FormatErrorMessage(keys::kNotAnAppError
, params
->id
);
409 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
410 ->Get(browser_context())
412 return delegate
->LaunchAppFunctionDelegate(extension
, browser_context());
415 ManagementSetEnabledFunction::ManagementSetEnabledFunction() {
418 ManagementSetEnabledFunction::~ManagementSetEnabledFunction() {
421 ExtensionFunction::ResponseAction
ManagementSetEnabledFunction::Run() {
422 scoped_ptr
<management::SetEnabled::Params
> params(
423 management::SetEnabled::Params::Create(*args_
));
424 EXTENSION_FUNCTION_VALIDATE(params
.get());
425 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser_context());
426 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
427 ->Get(browser_context())
430 extension_id_
= params
->id
;
432 const Extension
* extension
=
433 registry
->GetExtensionById(extension_id_
, ExtensionRegistry::EVERYTHING
);
434 if (!extension
|| ShouldNotBeVisible(extension
, browser_context()))
435 return RespondNow(Error(keys::kNoExtensionError
, extension_id_
));
437 bool enabled
= params
->enabled
;
438 const ManagementPolicy
* policy
=
439 ExtensionSystem::Get(browser_context())->management_policy();
440 if (!policy
->UserMayModifySettings(extension
, nullptr) ||
441 (!enabled
&& policy
->MustRemainEnabled(extension
, nullptr)) ||
442 (enabled
&& policy
->MustRemainDisabled(extension
, nullptr, nullptr))) {
443 return RespondNow(Error(keys::kUserCantModifyError
, extension_id_
));
446 bool currently_enabled
=
447 registry
->enabled_extensions().Contains(extension_id_
) ||
448 registry
->terminated_extensions().Contains(extension_id_
);
450 if (!currently_enabled
&& enabled
) {
451 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(browser_context());
452 if (prefs
->DidExtensionEscalatePermissions(extension_id_
)) {
454 return RespondNow(Error(keys::kGestureNeededForEscalationError
));
456 AddRef(); // Matched in InstallUIProceed/InstallUIAbort
457 install_prompt_
= delegate
->SetEnabledFunctionDelegate(this, extension
);
458 return RespondLater();
460 if (prefs
->GetDisableReasons(extension_id_
) &
461 Extension::DISABLE_UNSUPPORTED_REQUIREMENT
) {
462 // Recheck the requirements.
463 requirements_checker_
= delegate
->CreateRequirementsChecker();
464 requirements_checker_
->Check(
466 base::Bind(&ManagementSetEnabledFunction::OnRequirementsChecked
,
467 this)); // This bind creates a reference.
468 return RespondLater();
470 delegate
->EnableExtension(browser_context(), extension_id_
);
471 } else if (currently_enabled
&& !params
->enabled
) {
472 delegate
->DisableExtension(browser_context(), extension_id_
,
473 Extension::DISABLE_USER_ACTION
);
476 return RespondNow(NoArguments());
479 void ManagementSetEnabledFunction::InstallUIProceed() {
480 ManagementAPI::GetFactoryInstance()
481 ->Get(browser_context())
483 ->EnableExtension(browser_context(), extension_id_
);
484 Respond(OneArgument(new base::FundamentalValue(true)));
488 void ManagementSetEnabledFunction::InstallUIAbort(bool user_initiated
) {
489 Respond(Error(keys::kUserDidNotReEnableError
));
493 void ManagementSetEnabledFunction::OnRequirementsChecked(
494 const std::vector
<std::string
>& requirements_errors
) {
495 if (requirements_errors
.empty()) {
496 ManagementAPI::GetFactoryInstance()->Get(browser_context())->GetDelegate()->
497 EnableExtension(browser_context(), extension_id_
);
498 Respond(NoArguments());
500 // TODO(devlin): Should we really be noisy here all the time?
501 Respond(Error(keys::kMissingRequirementsError
,
502 JoinString(requirements_errors
, ' ')));
506 ManagementUninstallFunctionBase::ManagementUninstallFunctionBase() {
509 ManagementUninstallFunctionBase::~ManagementUninstallFunctionBase() {
512 ExtensionFunction::ResponseAction
ManagementUninstallFunctionBase::Uninstall(
513 const std::string
& target_extension_id
,
514 bool show_confirm_dialog
) {
515 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
516 ->Get(browser_context())
518 target_extension_id_
= target_extension_id
;
519 const Extension
* target_extension
=
520 extensions::ExtensionRegistry::Get(browser_context())
521 ->GetExtensionById(target_extension_id_
,
522 ExtensionRegistry::EVERYTHING
);
523 if (!target_extension
||
524 ShouldNotBeVisible(target_extension
, browser_context())) {
525 return RespondNow(Error(keys::kNoExtensionError
, target_extension_id_
));
528 ManagementPolicy
* policy
=
529 ExtensionSystem::Get(browser_context())->management_policy();
530 if (!policy
->UserMayModifySettings(target_extension
, nullptr) ||
531 policy
->MustRemainInstalled(target_extension
, nullptr)) {
532 return RespondNow(Error(keys::kUserCantModifyError
, target_extension_id_
));
535 // Note: null extension() means it's WebUI.
536 bool self_uninstall
= extension() && extension_id() == target_extension_id_
;
537 // We need to show a dialog for any extension uninstalling another extension.
538 show_confirm_dialog
|= !self_uninstall
;
540 if (show_confirm_dialog
&& !user_gesture())
541 return RespondNow(Error(keys::kGestureNeededForUninstallError
));
543 if (show_confirm_dialog
) {
544 switch (auto_confirm_for_test
) {
546 // We show the programmatic uninstall ui for extensions uninstalling
548 bool show_programmatic_uninstall_ui
= !self_uninstall
&& extension();
549 AddRef(); // Balanced in OnExtensionUninstallDialogClosed.
550 // TODO(devlin): A method called "UninstallFunctionDelegate" does not in
551 // any way imply that this actually creates a dialog and runs it.
553 delegate
->UninstallFunctionDelegate(
556 show_programmatic_uninstall_ui
);
560 // Skip the confirm dialog for testing.
561 base::MessageLoop::current()->PostTask(
563 base::Bind(&ManagementUninstallFunctionBase::UninstallExtension
,
568 // Fake the user canceling.
569 base::MessageLoop::current()->PostTask(
572 &ManagementUninstallFunctionBase::Finish
, this, false,
573 ErrorUtils::FormatErrorMessage(keys::kUninstallCanceledError
,
574 target_extension_id_
)));
577 } else { // No confirm dialog.
578 base::MessageLoop::current()->PostTask(
580 base::Bind(&ManagementUninstallFunctionBase::UninstallExtension
, this));
583 return RespondLater();
586 void ManagementUninstallFunctionBase::Finish(bool did_start_uninstall
,
587 const std::string
& error
) {
588 Respond(did_start_uninstall
? NoArguments() : Error(error
));
591 void ManagementUninstallFunctionBase::OnExtensionUninstallDialogClosed(
592 bool did_start_uninstall
,
593 const base::string16
& error
) {
594 Finish(did_start_uninstall
, base::UTF16ToUTF8(error
));
595 Release(); // Balanced in Uninstall().
598 void ManagementUninstallFunctionBase::UninstallExtension() {
599 // The extension can be uninstalled in another window while the UI was
600 // showing. Do nothing in that case.
601 const Extension
* target_extension
=
602 extensions::ExtensionRegistry::Get(browser_context())
603 ->GetExtensionById(target_extension_id_
,
604 ExtensionRegistry::EVERYTHING
);
606 bool success
= false;
607 if (target_extension
) {
608 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
609 ->Get(browser_context())
611 base::string16 utf16_error
;
612 success
= delegate
->UninstallExtension(
613 browser_context(), target_extension_id_
,
614 extensions::UNINSTALL_REASON_MANAGEMENT_API
,
615 base::Bind(&base::DoNothing
), &utf16_error
);
616 error
= base::UTF16ToUTF8(utf16_error
);
618 error
= ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
,
619 target_extension_id_
);
621 Finish(success
, error
);
625 void ManagementUninstallFunctionBase::SetAutoConfirmForTest(
626 bool should_proceed
) {
627 auto_confirm_for_test
= should_proceed
? PROCEED
: ABORT
;
630 ManagementUninstallFunction::ManagementUninstallFunction() {
633 ManagementUninstallFunction::~ManagementUninstallFunction() {
636 ExtensionFunction::ResponseAction
ManagementUninstallFunction::Run() {
637 scoped_ptr
<management::Uninstall::Params
> params(
638 management::Uninstall::Params::Create(*args_
));
639 EXTENSION_FUNCTION_VALIDATE(params
.get());
641 bool show_confirm_dialog
= params
->options
.get() &&
642 params
->options
->show_confirm_dialog
.get() &&
643 *params
->options
->show_confirm_dialog
;
644 return Uninstall(params
->id
, show_confirm_dialog
);
647 ManagementUninstallSelfFunction::ManagementUninstallSelfFunction() {
650 ManagementUninstallSelfFunction::~ManagementUninstallSelfFunction() {
653 ExtensionFunction::ResponseAction
ManagementUninstallSelfFunction::Run() {
654 scoped_ptr
<management::UninstallSelf::Params
> params(
655 management::UninstallSelf::Params::Create(*args_
));
656 EXTENSION_FUNCTION_VALIDATE(params
.get());
657 EXTENSION_FUNCTION_VALIDATE(extension_
.get());
659 bool show_confirm_dialog
= params
->options
.get() &&
660 params
->options
->show_confirm_dialog
.get() &&
661 *params
->options
->show_confirm_dialog
;
662 return Uninstall(extension_
->id(), show_confirm_dialog
);
665 ManagementCreateAppShortcutFunction::ManagementCreateAppShortcutFunction() {
668 ManagementCreateAppShortcutFunction::~ManagementCreateAppShortcutFunction() {
672 void ManagementCreateAppShortcutFunction::SetAutoConfirmForTest(
673 bool should_proceed
) {
674 auto_confirm_for_test
= should_proceed
? PROCEED
: ABORT
;
677 void ManagementCreateAppShortcutFunction::OnCloseShortcutPrompt(bool created
) {
679 error_
= keys::kCreateShortcutCanceledError
;
680 SendResponse(created
);
684 bool ManagementCreateAppShortcutFunction::RunAsync() {
685 if (!user_gesture()) {
686 error_
= keys::kGestureNeededForCreateAppShortcutError
;
690 scoped_ptr
<management::CreateAppShortcut::Params
> params(
691 management::CreateAppShortcut::Params::Create(*args_
));
692 EXTENSION_FUNCTION_VALIDATE(params
.get());
693 const Extension
* extension
=
694 ExtensionRegistry::Get(browser_context())
695 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
698 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
702 if (!extension
->is_app()) {
703 error_
= ErrorUtils::FormatErrorMessage(keys::kNotAnAppError
, params
->id
);
707 #if defined(OS_MACOSX)
708 if (!extension
->is_platform_app()) {
709 error_
= keys::kCreateOnlyPackagedAppShortcutMac
;
714 if (auto_confirm_for_test
!= DO_NOT_SKIP
) {
715 // Matched with a Release() in OnCloseShortcutPrompt().
718 OnCloseShortcutPrompt(auto_confirm_for_test
== PROCEED
);
723 if (ManagementAPI::GetFactoryInstance()
724 ->Get(browser_context())
726 ->CreateAppShortcutFunctionDelegate(this, extension
)) {
727 // Matched with a Release() in OnCloseShortcutPrompt().
731 // Response is sent async in OnCloseShortcutPrompt().
735 bool ManagementSetLaunchTypeFunction::RunSync() {
736 if (!user_gesture()) {
737 error_
= keys::kGestureNeededForSetLaunchTypeError
;
741 scoped_ptr
<management::SetLaunchType::Params
> params(
742 management::SetLaunchType::Params::Create(*args_
));
743 EXTENSION_FUNCTION_VALIDATE(params
.get());
744 const Extension
* extension
=
745 ExtensionRegistry::Get(browser_context())
746 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
747 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
748 ->Get(browser_context())
752 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
756 if (!extension
->is_app()) {
757 error_
= ErrorUtils::FormatErrorMessage(keys::kNotAnAppError
, params
->id
);
761 std::vector
<management::LaunchType
> available_launch_types
=
762 GetAvailableLaunchTypes(*extension
, delegate
);
764 management::LaunchType app_launch_type
= params
->launch_type
;
765 if (std::find(available_launch_types
.begin(), available_launch_types
.end(),
766 app_launch_type
) == available_launch_types
.end()) {
767 error_
= keys::kLaunchTypeNotAvailableError
;
771 LaunchType launch_type
= LAUNCH_TYPE_DEFAULT
;
772 switch (app_launch_type
) {
773 case management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB
:
774 launch_type
= LAUNCH_TYPE_PINNED
;
776 case management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB
:
777 launch_type
= LAUNCH_TYPE_REGULAR
;
779 case management::LAUNCH_TYPE_OPEN_FULL_SCREEN
:
780 launch_type
= LAUNCH_TYPE_FULLSCREEN
;
782 case management::LAUNCH_TYPE_OPEN_AS_WINDOW
:
783 launch_type
= LAUNCH_TYPE_WINDOW
;
785 case management::LAUNCH_TYPE_NONE
:
789 delegate
->SetLaunchType(browser_context(), params
->id
, launch_type
);
794 ManagementGenerateAppForLinkFunction::ManagementGenerateAppForLinkFunction() {
797 ManagementGenerateAppForLinkFunction::~ManagementGenerateAppForLinkFunction() {
800 void ManagementGenerateAppForLinkFunction::FinishCreateBookmarkApp(
801 const Extension
* extension
,
802 const WebApplicationInfo
& web_app_info
) {
804 scoped_ptr
<management::ExtensionInfo
> info
=
805 CreateExtensionInfo(*extension
, browser_context());
806 results_
= management::GenerateAppForLink::Results::Create(*info
);
811 error_
= keys::kGenerateAppForLinkInstallError
;
817 bool ManagementGenerateAppForLinkFunction::RunAsync() {
818 if (!user_gesture()) {
819 error_
= keys::kGestureNeededForGenerateAppForLinkError
;
823 scoped_ptr
<management::GenerateAppForLink::Params
> params(
824 management::GenerateAppForLink::Params::Create(*args_
));
825 EXTENSION_FUNCTION_VALIDATE(params
.get());
827 GURL
launch_url(params
->url
);
828 if (!launch_url
.is_valid() || !launch_url
.SchemeIsHTTPOrHTTPS()) {
830 ErrorUtils::FormatErrorMessage(keys::kInvalidURLError
, params
->url
);
834 if (params
->title
.empty()) {
835 error_
= keys::kEmptyTitleError
;
839 app_for_link_delegate_
=
840 ManagementAPI::GetFactoryInstance()
841 ->Get(browser_context())
843 ->GenerateAppForLinkFunctionDelegate(this, browser_context(),
844 params
->title
, launch_url
);
846 // Matched with a Release() in FinishCreateBookmarkApp().
849 // Response is sent async in FinishCreateBookmarkApp().
853 ManagementEventRouter::ManagementEventRouter(content::BrowserContext
* context
)
854 : browser_context_(context
), extension_registry_observer_(this) {
855 extension_registry_observer_
.Add(ExtensionRegistry::Get(browser_context_
));
858 ManagementEventRouter::~ManagementEventRouter() {
861 void ManagementEventRouter::OnExtensionLoaded(
862 content::BrowserContext
* browser_context
,
863 const Extension
* extension
) {
864 BroadcastEvent(extension
, management::OnEnabled::kEventName
);
867 void ManagementEventRouter::OnExtensionUnloaded(
868 content::BrowserContext
* browser_context
,
869 const Extension
* extension
,
870 UnloadedExtensionInfo::Reason reason
) {
871 BroadcastEvent(extension
, management::OnDisabled::kEventName
);
874 void ManagementEventRouter::OnExtensionInstalled(
875 content::BrowserContext
* browser_context
,
876 const Extension
* extension
,
878 BroadcastEvent(extension
, management::OnInstalled::kEventName
);
881 void ManagementEventRouter::OnExtensionUninstalled(
882 content::BrowserContext
* browser_context
,
883 const Extension
* extension
,
884 extensions::UninstallReason reason
) {
885 BroadcastEvent(extension
, management::OnUninstalled::kEventName
);
888 void ManagementEventRouter::BroadcastEvent(const Extension
* extension
,
889 const char* event_name
) {
890 if (ShouldNotBeVisible(extension
, browser_context_
))
891 return; // Don't dispatch events for built-in extenions.
892 scoped_ptr
<base::ListValue
> args(new base::ListValue());
893 if (event_name
== management::OnUninstalled::kEventName
) {
894 args
->Append(new base::StringValue(extension
->id()));
896 scoped_ptr
<management::ExtensionInfo
> info
=
897 CreateExtensionInfo(*extension
, browser_context_
);
898 args
->Append(info
->ToValue().release());
901 EventRouter::Get(browser_context_
)
902 ->BroadcastEvent(scoped_ptr
<Event
>(new Event(event_name
, args
.Pass())));
905 ManagementAPI::ManagementAPI(content::BrowserContext
* context
)
906 : browser_context_(context
),
907 delegate_(ExtensionsAPIClient::Get()->CreateManagementAPIDelegate()) {
908 EventRouter
* event_router
= EventRouter::Get(browser_context_
);
909 event_router
->RegisterObserver(this, management::OnInstalled::kEventName
);
910 event_router
->RegisterObserver(this, management::OnUninstalled::kEventName
);
911 event_router
->RegisterObserver(this, management::OnEnabled::kEventName
);
912 event_router
->RegisterObserver(this, management::OnDisabled::kEventName
);
915 ManagementAPI::~ManagementAPI() {
918 void ManagementAPI::Shutdown() {
919 EventRouter::Get(browser_context_
)->UnregisterObserver(this);
922 static base::LazyInstance
<BrowserContextKeyedAPIFactory
<ManagementAPI
>>
923 g_factory
= LAZY_INSTANCE_INITIALIZER
;
926 BrowserContextKeyedAPIFactory
<ManagementAPI
>*
927 ManagementAPI::GetFactoryInstance() {
928 return g_factory
.Pointer();
931 void ManagementAPI::OnListenerAdded(const EventListenerInfo
& details
) {
932 management_event_router_
.reset(new ManagementEventRouter(browser_context_
));
933 EventRouter::Get(browser_context_
)->UnregisterObserver(this);
936 } // namespace extensions