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
);
84 // TODO(dominickn): remove check when hosted apps can open in windows on Mac.
85 if (delegate
->CanHostedAppsOpenInWindows())
86 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW
);
88 if (!delegate
->IsNewBookmarkAppsEnabled()) {
89 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB
);
90 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_FULL_SCREEN
);
92 return launch_type_list
;
95 scoped_ptr
<management::ExtensionInfo
> CreateExtensionInfo(
96 const Extension
& extension
,
97 content::BrowserContext
* context
) {
98 ExtensionSystem
* system
= ExtensionSystem::Get(context
);
99 ExtensionRegistry
* registry
= ExtensionRegistry::Get(context
);
100 const ManagementAPIDelegate
* delegate
=
101 ManagementAPI::GetFactoryInstance()->Get(context
)->GetDelegate();
102 scoped_ptr
<management::ExtensionInfo
> info(new management::ExtensionInfo());
104 info
->id
= extension
.id();
105 info
->name
= extension
.name();
106 info
->short_name
= extension
.short_name();
107 info
->enabled
= registry
->enabled_extensions().Contains(info
->id
);
108 info
->offline_enabled
= OfflineEnabledInfo::IsOfflineEnabled(&extension
);
109 info
->version
= extension
.VersionString();
110 info
->description
= extension
.description();
111 info
->options_url
= OptionsPageInfo::GetOptionsPage(&extension
).spec();
112 info
->homepage_url
.reset(
113 new std::string(ManifestURL::GetHomepageURL(&extension
).spec()));
115 system
->management_policy()->UserMayModifySettings(&extension
, NULL
);
116 info
->is_app
= extension
.is_app();
118 if (extension
.is_legacy_packaged_app())
119 info
->type
= management::EXTENSION_TYPE_LEGACY_PACKAGED_APP
;
120 else if (extension
.is_hosted_app())
121 info
->type
= management::EXTENSION_TYPE_HOSTED_APP
;
123 info
->type
= management::EXTENSION_TYPE_PACKAGED_APP
;
124 } else if (extension
.is_theme()) {
125 info
->type
= management::EXTENSION_TYPE_THEME
;
127 info
->type
= management::EXTENSION_TYPE_EXTENSION
;
131 info
->disabled_reason
= management::EXTENSION_DISABLED_REASON_NONE
;
133 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(context
);
134 if (prefs
->DidExtensionEscalatePermissions(extension
.id())) {
135 info
->disabled_reason
=
136 management::EXTENSION_DISABLED_REASON_PERMISSIONS_INCREASE
;
138 info
->disabled_reason
=
139 management::EXTENSION_DISABLED_REASON_UNKNOWN
;
143 if (!ManifestURL::GetUpdateURL(&extension
).is_empty()) {
144 info
->update_url
.reset(
145 new std::string(ManifestURL::GetUpdateURL(&extension
).spec()));
148 if (extension
.is_app()) {
149 info
->app_launch_url
.reset(
150 new std::string(delegate
->GetFullLaunchURL(&extension
).spec()));
153 const ExtensionIconSet::IconMap
& icons
=
154 IconsInfo::GetIcons(&extension
).map();
155 if (!icons
.empty()) {
156 info
->icons
.reset(new IconInfoList());
157 ExtensionIconSet::IconMap::const_iterator icon_iter
;
158 for (icon_iter
= icons
.begin(); icon_iter
!= icons
.end(); ++icon_iter
) {
159 management::IconInfo
* icon_info
= new management::IconInfo();
160 icon_info
->size
= icon_iter
->first
;
162 delegate
->GetIconURL(&extension
, icon_info
->size
,
163 ExtensionIconSet::MATCH_EXACTLY
, false, nullptr);
164 icon_info
->url
= url
.spec();
165 info
->icons
->push_back(make_linked_ptr
<management::IconInfo
>(icon_info
));
169 const std::set
<std::string
> perms
=
170 extension
.permissions_data()->active_permissions()->GetAPIsAsStrings();
171 if (!perms
.empty()) {
172 std::set
<std::string
>::const_iterator perms_iter
;
173 for (perms_iter
= perms
.begin(); perms_iter
!= perms
.end(); ++perms_iter
)
174 info
->permissions
.push_back(*perms_iter
);
177 if (!extension
.is_hosted_app()) {
178 // Skip host permissions for hosted apps.
179 const URLPatternSet host_perms
=
180 extension
.permissions_data()->active_permissions()->explicit_hosts();
181 if (!host_perms
.is_empty()) {
182 for (URLPatternSet::const_iterator iter
= host_perms
.begin();
183 iter
!= host_perms
.end(); ++iter
) {
184 info
->host_permissions
.push_back(iter
->GetAsString());
189 switch (extension
.location()) {
190 case Manifest::INTERNAL
:
191 info
->install_type
= management::EXTENSION_INSTALL_TYPE_NORMAL
;
193 case Manifest::UNPACKED
:
194 case Manifest::COMMAND_LINE
:
195 info
->install_type
= management::EXTENSION_INSTALL_TYPE_DEVELOPMENT
;
197 case Manifest::EXTERNAL_PREF
:
198 case Manifest::EXTERNAL_REGISTRY
:
199 case Manifest::EXTERNAL_PREF_DOWNLOAD
:
200 info
->install_type
= management::EXTENSION_INSTALL_TYPE_SIDELOAD
;
202 case Manifest::EXTERNAL_POLICY
:
203 case Manifest::EXTERNAL_POLICY_DOWNLOAD
:
204 info
->install_type
= management::EXTENSION_INSTALL_TYPE_ADMIN
;
206 case Manifest::NUM_LOCATIONS
:
208 case Manifest::INVALID_LOCATION
:
209 case Manifest::COMPONENT
:
210 case Manifest::EXTERNAL_COMPONENT
:
211 info
->install_type
= management::EXTENSION_INSTALL_TYPE_OTHER
;
215 info
->launch_type
= management::LAUNCH_TYPE_NONE
;
216 if (extension
.is_app()) {
217 LaunchType launch_type
;
218 if (extension
.is_platform_app()) {
219 launch_type
= LAUNCH_TYPE_WINDOW
;
222 delegate
->GetLaunchType(ExtensionPrefs::Get(context
), &extension
);
225 switch (launch_type
) {
226 case LAUNCH_TYPE_PINNED
:
227 info
->launch_type
= management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB
;
229 case LAUNCH_TYPE_REGULAR
:
230 info
->launch_type
= management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB
;
232 case LAUNCH_TYPE_FULLSCREEN
:
233 info
->launch_type
= management::LAUNCH_TYPE_OPEN_FULL_SCREEN
;
235 case LAUNCH_TYPE_WINDOW
:
236 info
->launch_type
= management::LAUNCH_TYPE_OPEN_AS_WINDOW
;
238 case LAUNCH_TYPE_INVALID
:
239 case NUM_LAUNCH_TYPES
:
243 info
->available_launch_types
.reset(new std::vector
<management::LaunchType
>(
244 GetAvailableLaunchTypes(extension
, delegate
)));
250 bool ShouldNotBeVisible(const Extension
* extension
,
251 content::BrowserContext
* context
) {
252 return (extension
->ShouldNotBeVisible() ||
253 ExtensionPrefs::Get(context
)->IsEphemeralApp(extension
->id()));
256 void AddExtensionInfo(const ExtensionSet
& extensions
,
257 ExtensionInfoList
* extension_list
,
258 content::BrowserContext
* context
) {
259 for (ExtensionSet::const_iterator iter
= extensions
.begin();
260 iter
!= extensions
.end(); ++iter
) {
261 const Extension
& extension
= *iter
->get();
263 if (ShouldNotBeVisible(&extension
, context
))
264 continue; // Skip built-in extensions/apps.
266 extension_list
->push_back(make_linked_ptr
<management::ExtensionInfo
>(
267 CreateExtensionInfo(extension
, context
).release()));
273 bool ManagementGetAllFunction::RunSync() {
274 ExtensionInfoList extensions
;
275 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser_context());
277 AddExtensionInfo(registry
->enabled_extensions(), &extensions
,
279 AddExtensionInfo(registry
->disabled_extensions(), &extensions
,
281 AddExtensionInfo(registry
->terminated_extensions(), &extensions
,
284 results_
= management::GetAll::Results::Create(extensions
);
288 bool ManagementGetFunction::RunSync() {
289 scoped_ptr
<management::Get::Params
> params(
290 management::Get::Params::Create(*args_
));
291 EXTENSION_FUNCTION_VALIDATE(params
.get());
292 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser_context());
294 const Extension
* extension
=
295 registry
->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
298 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
302 scoped_ptr
<management::ExtensionInfo
> info
=
303 CreateExtensionInfo(*extension
, browser_context());
304 results_
= management::Get::Results::Create(*info
);
309 bool ManagementGetSelfFunction::RunSync() {
310 scoped_ptr
<management::ExtensionInfo
> info
=
311 CreateExtensionInfo(*extension_
, browser_context());
312 results_
= management::Get::Results::Create(*info
);
317 bool ManagementGetPermissionWarningsByIdFunction::RunSync() {
318 scoped_ptr
<management::GetPermissionWarningsById::Params
> params(
319 management::GetPermissionWarningsById::Params::Create(*args_
));
320 EXTENSION_FUNCTION_VALIDATE(params
.get());
322 const Extension
* extension
=
323 ExtensionRegistry::Get(browser_context())
324 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
327 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
331 std::vector
<std::string
> warnings
= CreateWarningsList(extension
);
332 results_
= management::GetPermissionWarningsById::Results::Create(warnings
);
336 bool ManagementGetPermissionWarningsByManifestFunction::RunAsync() {
337 scoped_ptr
<management::GetPermissionWarningsByManifest::Params
> params(
338 management::GetPermissionWarningsByManifest::Params::Create(*args_
));
339 EXTENSION_FUNCTION_VALIDATE(params
.get());
341 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
342 ->Get(browser_context())
346 delegate
->GetPermissionWarningsByManifestFunctionDelegate(
347 this, params
->manifest_str
);
349 // Matched with a Release() in OnParseSuccess/Failure().
352 // Response is sent async in OnParseSuccess/Failure().
355 // TODO(lfg) add error string
361 void ManagementGetPermissionWarningsByManifestFunction::OnParseSuccess(
362 scoped_ptr
<base::Value
> value
) {
363 if (!value
->IsType(base::Value::TYPE_DICTIONARY
)) {
364 OnParseFailure(keys::kManifestParseError
);
367 const base::DictionaryValue
* parsed_manifest
=
368 static_cast<const base::DictionaryValue
*>(value
.get());
370 scoped_refptr
<Extension
> extension
=
371 Extension::Create(base::FilePath(), Manifest::INVALID_LOCATION
,
372 *parsed_manifest
, Extension::NO_FLAGS
, &error_
);
374 OnParseFailure(keys::kExtensionCreateError
);
378 std::vector
<std::string
> warnings
= CreateWarningsList(extension
.get());
380 management::GetPermissionWarningsByManifest::Results::Create(warnings
);
383 // Matched with AddRef() in RunAsync().
387 void ManagementGetPermissionWarningsByManifestFunction::OnParseFailure(
388 const std::string
& error
) {
392 // Matched with AddRef() in RunAsync().
396 bool ManagementLaunchAppFunction::RunSync() {
397 scoped_ptr
<management::LaunchApp::Params
> params(
398 management::LaunchApp::Params::Create(*args_
));
399 EXTENSION_FUNCTION_VALIDATE(params
.get());
400 const Extension
* extension
=
401 ExtensionRegistry::Get(browser_context())
402 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
405 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
408 if (!extension
->is_app()) {
409 error_
= ErrorUtils::FormatErrorMessage(keys::kNotAnAppError
, params
->id
);
413 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
414 ->Get(browser_context())
416 return delegate
->LaunchAppFunctionDelegate(extension
, browser_context());
419 ManagementSetEnabledFunction::ManagementSetEnabledFunction() {
422 ManagementSetEnabledFunction::~ManagementSetEnabledFunction() {
425 ExtensionFunction::ResponseAction
ManagementSetEnabledFunction::Run() {
426 scoped_ptr
<management::SetEnabled::Params
> params(
427 management::SetEnabled::Params::Create(*args_
));
428 EXTENSION_FUNCTION_VALIDATE(params
.get());
429 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser_context());
430 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
431 ->Get(browser_context())
434 extension_id_
= params
->id
;
436 const Extension
* extension
=
437 registry
->GetExtensionById(extension_id_
, ExtensionRegistry::EVERYTHING
);
438 if (!extension
|| ShouldNotBeVisible(extension
, browser_context()))
439 return RespondNow(Error(keys::kNoExtensionError
, extension_id_
));
441 bool enabled
= params
->enabled
;
442 const ManagementPolicy
* policy
=
443 ExtensionSystem::Get(browser_context())->management_policy();
444 if (!policy
->UserMayModifySettings(extension
, nullptr) ||
445 (!enabled
&& policy
->MustRemainEnabled(extension
, nullptr)) ||
446 (enabled
&& policy
->MustRemainDisabled(extension
, nullptr, nullptr))) {
447 return RespondNow(Error(keys::kUserCantModifyError
, extension_id_
));
450 bool currently_enabled
=
451 registry
->enabled_extensions().Contains(extension_id_
) ||
452 registry
->terminated_extensions().Contains(extension_id_
);
454 if (!currently_enabled
&& enabled
) {
455 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(browser_context());
456 if (prefs
->DidExtensionEscalatePermissions(extension_id_
)) {
458 return RespondNow(Error(keys::kGestureNeededForEscalationError
));
460 AddRef(); // Matched in InstallUIProceed/InstallUIAbort
461 install_prompt_
= delegate
->SetEnabledFunctionDelegate(this, extension
);
462 return RespondLater();
464 if (prefs
->GetDisableReasons(extension_id_
) &
465 Extension::DISABLE_UNSUPPORTED_REQUIREMENT
) {
466 // Recheck the requirements.
467 requirements_checker_
= delegate
->CreateRequirementsChecker();
468 requirements_checker_
->Check(
470 base::Bind(&ManagementSetEnabledFunction::OnRequirementsChecked
,
471 this)); // This bind creates a reference.
472 return RespondLater();
474 delegate
->EnableExtension(browser_context(), extension_id_
);
475 } else if (currently_enabled
&& !params
->enabled
) {
476 delegate
->DisableExtension(browser_context(), extension_id_
,
477 Extension::DISABLE_USER_ACTION
);
480 return RespondNow(NoArguments());
483 void ManagementSetEnabledFunction::InstallUIProceed() {
484 ManagementAPI::GetFactoryInstance()
485 ->Get(browser_context())
487 ->EnableExtension(browser_context(), extension_id_
);
488 Respond(OneArgument(new base::FundamentalValue(true)));
492 void ManagementSetEnabledFunction::InstallUIAbort(bool user_initiated
) {
493 Respond(Error(keys::kUserDidNotReEnableError
));
497 void ManagementSetEnabledFunction::OnRequirementsChecked(
498 const std::vector
<std::string
>& requirements_errors
) {
499 if (requirements_errors
.empty()) {
500 ManagementAPI::GetFactoryInstance()->Get(browser_context())->GetDelegate()->
501 EnableExtension(browser_context(), extension_id_
);
502 Respond(NoArguments());
504 // TODO(devlin): Should we really be noisy here all the time?
505 Respond(Error(keys::kMissingRequirementsError
,
506 base::JoinString(requirements_errors
, " ")));
510 ManagementUninstallFunctionBase::ManagementUninstallFunctionBase() {
513 ManagementUninstallFunctionBase::~ManagementUninstallFunctionBase() {
516 ExtensionFunction::ResponseAction
ManagementUninstallFunctionBase::Uninstall(
517 const std::string
& target_extension_id
,
518 bool show_confirm_dialog
) {
519 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
520 ->Get(browser_context())
522 target_extension_id_
= target_extension_id
;
523 const Extension
* target_extension
=
524 extensions::ExtensionRegistry::Get(browser_context())
525 ->GetExtensionById(target_extension_id_
,
526 ExtensionRegistry::EVERYTHING
);
527 if (!target_extension
||
528 ShouldNotBeVisible(target_extension
, browser_context())) {
529 return RespondNow(Error(keys::kNoExtensionError
, target_extension_id_
));
532 ManagementPolicy
* policy
=
533 ExtensionSystem::Get(browser_context())->management_policy();
534 if (!policy
->UserMayModifySettings(target_extension
, nullptr) ||
535 policy
->MustRemainInstalled(target_extension
, nullptr)) {
536 return RespondNow(Error(keys::kUserCantModifyError
, target_extension_id_
));
539 // Note: null extension() means it's WebUI.
540 bool self_uninstall
= extension() && extension_id() == target_extension_id_
;
541 // We need to show a dialog for any extension uninstalling another extension.
542 show_confirm_dialog
|= !self_uninstall
;
544 if (show_confirm_dialog
&& !user_gesture())
545 return RespondNow(Error(keys::kGestureNeededForUninstallError
));
547 if (show_confirm_dialog
) {
548 // We show the programmatic uninstall ui for extensions uninstalling
550 bool show_programmatic_uninstall_ui
= !self_uninstall
&& extension();
551 AddRef(); // Balanced in OnExtensionUninstallDialogClosed.
552 // TODO(devlin): A method called "UninstallFunctionDelegate" does not in
553 // any way imply that this actually creates a dialog and runs it.
554 uninstall_dialog_
= delegate
->UninstallFunctionDelegate(
555 this, target_extension
, show_programmatic_uninstall_ui
);
556 } else { // No confirm dialog.
557 base::MessageLoop::current()->PostTask(
559 base::Bind(&ManagementUninstallFunctionBase::UninstallExtension
, this));
562 return RespondLater();
565 void ManagementUninstallFunctionBase::Finish(bool did_start_uninstall
,
566 const std::string
& error
) {
567 Respond(did_start_uninstall
? NoArguments() : Error(error
));
570 void ManagementUninstallFunctionBase::OnExtensionUninstallDialogClosed(
571 bool did_start_uninstall
,
572 const base::string16
& error
) {
573 Finish(did_start_uninstall
,
574 ErrorUtils::FormatErrorMessage(keys::kUninstallCanceledError
,
575 target_extension_id_
));
576 Release(); // Balanced in Uninstall().
579 void ManagementUninstallFunctionBase::UninstallExtension() {
580 // The extension can be uninstalled in another window while the UI was
581 // showing. Do nothing in that case.
582 const Extension
* target_extension
=
583 extensions::ExtensionRegistry::Get(browser_context())
584 ->GetExtensionById(target_extension_id_
,
585 ExtensionRegistry::EVERYTHING
);
587 bool success
= false;
588 if (target_extension
) {
589 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
590 ->Get(browser_context())
592 base::string16 utf16_error
;
593 success
= delegate
->UninstallExtension(
594 browser_context(), target_extension_id_
,
595 extensions::UNINSTALL_REASON_MANAGEMENT_API
,
596 base::Bind(&base::DoNothing
), &utf16_error
);
597 error
= base::UTF16ToUTF8(utf16_error
);
599 error
= ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
,
600 target_extension_id_
);
602 Finish(success
, error
);
605 ManagementUninstallFunction::ManagementUninstallFunction() {
608 ManagementUninstallFunction::~ManagementUninstallFunction() {
611 ExtensionFunction::ResponseAction
ManagementUninstallFunction::Run() {
612 scoped_ptr
<management::Uninstall::Params
> params(
613 management::Uninstall::Params::Create(*args_
));
614 EXTENSION_FUNCTION_VALIDATE(params
.get());
616 bool show_confirm_dialog
= params
->options
.get() &&
617 params
->options
->show_confirm_dialog
.get() &&
618 *params
->options
->show_confirm_dialog
;
619 return Uninstall(params
->id
, show_confirm_dialog
);
622 ManagementUninstallSelfFunction::ManagementUninstallSelfFunction() {
625 ManagementUninstallSelfFunction::~ManagementUninstallSelfFunction() {
628 ExtensionFunction::ResponseAction
ManagementUninstallSelfFunction::Run() {
629 scoped_ptr
<management::UninstallSelf::Params
> params(
630 management::UninstallSelf::Params::Create(*args_
));
631 EXTENSION_FUNCTION_VALIDATE(params
.get());
632 EXTENSION_FUNCTION_VALIDATE(extension_
.get());
634 bool show_confirm_dialog
= params
->options
.get() &&
635 params
->options
->show_confirm_dialog
.get() &&
636 *params
->options
->show_confirm_dialog
;
637 return Uninstall(extension_
->id(), show_confirm_dialog
);
640 ManagementCreateAppShortcutFunction::ManagementCreateAppShortcutFunction() {
643 ManagementCreateAppShortcutFunction::~ManagementCreateAppShortcutFunction() {
647 void ManagementCreateAppShortcutFunction::SetAutoConfirmForTest(
648 bool should_proceed
) {
649 auto_confirm_for_test
= should_proceed
? PROCEED
: ABORT
;
652 void ManagementCreateAppShortcutFunction::OnCloseShortcutPrompt(bool created
) {
654 error_
= keys::kCreateShortcutCanceledError
;
655 SendResponse(created
);
659 bool ManagementCreateAppShortcutFunction::RunAsync() {
660 if (!user_gesture()) {
661 error_
= keys::kGestureNeededForCreateAppShortcutError
;
665 scoped_ptr
<management::CreateAppShortcut::Params
> params(
666 management::CreateAppShortcut::Params::Create(*args_
));
667 EXTENSION_FUNCTION_VALIDATE(params
.get());
668 const Extension
* extension
=
669 ExtensionRegistry::Get(browser_context())
670 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
673 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
677 if (!extension
->is_app()) {
678 error_
= ErrorUtils::FormatErrorMessage(keys::kNotAnAppError
, params
->id
);
682 #if defined(OS_MACOSX)
683 if (!extension
->is_platform_app()) {
684 error_
= keys::kCreateOnlyPackagedAppShortcutMac
;
689 if (auto_confirm_for_test
!= DO_NOT_SKIP
) {
690 // Matched with a Release() in OnCloseShortcutPrompt().
693 OnCloseShortcutPrompt(auto_confirm_for_test
== PROCEED
);
698 if (ManagementAPI::GetFactoryInstance()
699 ->Get(browser_context())
701 ->CreateAppShortcutFunctionDelegate(this, extension
)) {
702 // Matched with a Release() in OnCloseShortcutPrompt().
706 // Response is sent async in OnCloseShortcutPrompt().
710 bool ManagementSetLaunchTypeFunction::RunSync() {
711 if (!user_gesture()) {
712 error_
= keys::kGestureNeededForSetLaunchTypeError
;
716 scoped_ptr
<management::SetLaunchType::Params
> params(
717 management::SetLaunchType::Params::Create(*args_
));
718 EXTENSION_FUNCTION_VALIDATE(params
.get());
719 const Extension
* extension
=
720 ExtensionRegistry::Get(browser_context())
721 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
722 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
723 ->Get(browser_context())
727 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
731 if (!extension
->is_app()) {
732 error_
= ErrorUtils::FormatErrorMessage(keys::kNotAnAppError
, params
->id
);
736 std::vector
<management::LaunchType
> available_launch_types
=
737 GetAvailableLaunchTypes(*extension
, delegate
);
739 management::LaunchType app_launch_type
= params
->launch_type
;
740 if (std::find(available_launch_types
.begin(), available_launch_types
.end(),
741 app_launch_type
) == available_launch_types
.end()) {
742 error_
= keys::kLaunchTypeNotAvailableError
;
746 LaunchType launch_type
= LAUNCH_TYPE_DEFAULT
;
747 switch (app_launch_type
) {
748 case management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB
:
749 launch_type
= LAUNCH_TYPE_PINNED
;
751 case management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB
:
752 launch_type
= LAUNCH_TYPE_REGULAR
;
754 case management::LAUNCH_TYPE_OPEN_FULL_SCREEN
:
755 launch_type
= LAUNCH_TYPE_FULLSCREEN
;
757 case management::LAUNCH_TYPE_OPEN_AS_WINDOW
:
758 launch_type
= LAUNCH_TYPE_WINDOW
;
760 case management::LAUNCH_TYPE_NONE
:
764 delegate
->SetLaunchType(browser_context(), params
->id
, launch_type
);
769 ManagementGenerateAppForLinkFunction::ManagementGenerateAppForLinkFunction() {
772 ManagementGenerateAppForLinkFunction::~ManagementGenerateAppForLinkFunction() {
775 void ManagementGenerateAppForLinkFunction::FinishCreateBookmarkApp(
776 const Extension
* extension
,
777 const WebApplicationInfo
& web_app_info
) {
779 scoped_ptr
<management::ExtensionInfo
> info
=
780 CreateExtensionInfo(*extension
, browser_context());
781 results_
= management::GenerateAppForLink::Results::Create(*info
);
786 error_
= keys::kGenerateAppForLinkInstallError
;
792 bool ManagementGenerateAppForLinkFunction::RunAsync() {
793 if (!user_gesture()) {
794 error_
= keys::kGestureNeededForGenerateAppForLinkError
;
798 scoped_ptr
<management::GenerateAppForLink::Params
> params(
799 management::GenerateAppForLink::Params::Create(*args_
));
800 EXTENSION_FUNCTION_VALIDATE(params
.get());
802 GURL
launch_url(params
->url
);
803 if (!launch_url
.is_valid() || !launch_url
.SchemeIsHTTPOrHTTPS()) {
805 ErrorUtils::FormatErrorMessage(keys::kInvalidURLError
, params
->url
);
809 if (params
->title
.empty()) {
810 error_
= keys::kEmptyTitleError
;
814 app_for_link_delegate_
=
815 ManagementAPI::GetFactoryInstance()
816 ->Get(browser_context())
818 ->GenerateAppForLinkFunctionDelegate(this, browser_context(),
819 params
->title
, launch_url
);
821 // Matched with a Release() in FinishCreateBookmarkApp().
824 // Response is sent async in FinishCreateBookmarkApp().
828 ManagementEventRouter::ManagementEventRouter(content::BrowserContext
* context
)
829 : browser_context_(context
), extension_registry_observer_(this) {
830 extension_registry_observer_
.Add(ExtensionRegistry::Get(browser_context_
));
833 ManagementEventRouter::~ManagementEventRouter() {
836 void ManagementEventRouter::OnExtensionLoaded(
837 content::BrowserContext
* browser_context
,
838 const Extension
* extension
) {
839 BroadcastEvent(extension
, events::MANAGEMENT_ON_ENABLED
,
840 management::OnEnabled::kEventName
);
843 void ManagementEventRouter::OnExtensionUnloaded(
844 content::BrowserContext
* browser_context
,
845 const Extension
* extension
,
846 UnloadedExtensionInfo::Reason reason
) {
847 BroadcastEvent(extension
, events::MANAGEMENT_ON_DISABLED
,
848 management::OnDisabled::kEventName
);
851 void ManagementEventRouter::OnExtensionInstalled(
852 content::BrowserContext
* browser_context
,
853 const Extension
* extension
,
855 BroadcastEvent(extension
, events::MANAGEMENT_ON_INSTALLED
,
856 management::OnInstalled::kEventName
);
859 void ManagementEventRouter::OnExtensionUninstalled(
860 content::BrowserContext
* browser_context
,
861 const Extension
* extension
,
862 extensions::UninstallReason reason
) {
863 BroadcastEvent(extension
, events::MANAGEMENT_ON_UNINSTALLED
,
864 management::OnUninstalled::kEventName
);
867 void ManagementEventRouter::BroadcastEvent(
868 const Extension
* extension
,
869 events::HistogramValue histogram_value
,
870 const char* event_name
) {
871 if (ShouldNotBeVisible(extension
, browser_context_
))
872 return; // Don't dispatch events for built-in extenions.
873 scoped_ptr
<base::ListValue
> args(new base::ListValue());
874 if (event_name
== management::OnUninstalled::kEventName
) {
875 args
->Append(new base::StringValue(extension
->id()));
877 scoped_ptr
<management::ExtensionInfo
> info
=
878 CreateExtensionInfo(*extension
, browser_context_
);
879 args
->Append(info
->ToValue().release());
882 EventRouter::Get(browser_context_
)
883 ->BroadcastEvent(scoped_ptr
<Event
>(
884 new Event(histogram_value
, event_name
, args
.Pass())));
887 ManagementAPI::ManagementAPI(content::BrowserContext
* context
)
888 : browser_context_(context
),
889 delegate_(ExtensionsAPIClient::Get()->CreateManagementAPIDelegate()) {
890 EventRouter
* event_router
= EventRouter::Get(browser_context_
);
891 event_router
->RegisterObserver(this, management::OnInstalled::kEventName
);
892 event_router
->RegisterObserver(this, management::OnUninstalled::kEventName
);
893 event_router
->RegisterObserver(this, management::OnEnabled::kEventName
);
894 event_router
->RegisterObserver(this, management::OnDisabled::kEventName
);
897 ManagementAPI::~ManagementAPI() {
900 void ManagementAPI::Shutdown() {
901 EventRouter::Get(browser_context_
)->UnregisterObserver(this);
904 static base::LazyInstance
<BrowserContextKeyedAPIFactory
<ManagementAPI
>>
905 g_factory
= LAZY_INSTANCE_INITIALIZER
;
908 BrowserContextKeyedAPIFactory
<ManagementAPI
>*
909 ManagementAPI::GetFactoryInstance() {
910 return g_factory
.Pointer();
913 void ManagementAPI::OnListenerAdded(const EventListenerInfo
& details
) {
914 management_event_router_
.reset(new ManagementEventRouter(browser_context_
));
915 EventRouter::Get(browser_context_
)->UnregisterObserver(this);
918 } // namespace extensions