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_message.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
= 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 PermissionMessage
& msg
:
65 extension
->permissions_data()->GetPermissionMessages()) {
66 warnings_list
.push_back(base::UTF16ToUTF8(msg
.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
);
83 // TODO(dominickn): remove check when hosted apps can open in windows on Mac.
84 if (delegate
->CanHostedAppsOpenInWindows())
85 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW
);
87 if (!delegate
->IsNewBookmarkAppsEnabled()) {
88 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB
);
89 launch_type_list
.push_back(management::LAUNCH_TYPE_OPEN_FULL_SCREEN
);
91 return launch_type_list
;
94 scoped_ptr
<management::ExtensionInfo
> CreateExtensionInfo(
95 const Extension
& extension
,
96 content::BrowserContext
* context
) {
97 ExtensionSystem
* system
= ExtensionSystem::Get(context
);
98 ExtensionRegistry
* registry
= ExtensionRegistry::Get(context
);
99 const ManagementAPIDelegate
* delegate
=
100 ManagementAPI::GetFactoryInstance()->Get(context
)->GetDelegate();
101 scoped_ptr
<management::ExtensionInfo
> info(new management::ExtensionInfo());
103 info
->id
= extension
.id();
104 info
->name
= extension
.name();
105 info
->short_name
= extension
.short_name();
106 info
->enabled
= registry
->enabled_extensions().Contains(info
->id
);
107 info
->offline_enabled
= OfflineEnabledInfo::IsOfflineEnabled(&extension
);
108 info
->version
= extension
.VersionString();
109 info
->description
= extension
.description();
110 info
->options_url
= OptionsPageInfo::GetOptionsPage(&extension
).spec();
111 info
->homepage_url
.reset(
112 new std::string(ManifestURL::GetHomepageURL(&extension
).spec()));
114 system
->management_policy()->UserMayModifySettings(&extension
, NULL
);
115 info
->is_app
= extension
.is_app();
117 if (extension
.is_legacy_packaged_app())
118 info
->type
= management::EXTENSION_TYPE_LEGACY_PACKAGED_APP
;
119 else if (extension
.is_hosted_app())
120 info
->type
= management::EXTENSION_TYPE_HOSTED_APP
;
122 info
->type
= management::EXTENSION_TYPE_PACKAGED_APP
;
123 } else if (extension
.is_theme()) {
124 info
->type
= management::EXTENSION_TYPE_THEME
;
126 info
->type
= management::EXTENSION_TYPE_EXTENSION
;
130 info
->disabled_reason
= management::EXTENSION_DISABLED_REASON_NONE
;
132 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(context
);
133 if (prefs
->DidExtensionEscalatePermissions(extension
.id())) {
134 info
->disabled_reason
=
135 management::EXTENSION_DISABLED_REASON_PERMISSIONS_INCREASE
;
137 info
->disabled_reason
=
138 management::EXTENSION_DISABLED_REASON_UNKNOWN
;
142 if (!ManifestURL::GetUpdateURL(&extension
).is_empty()) {
143 info
->update_url
.reset(
144 new std::string(ManifestURL::GetUpdateURL(&extension
).spec()));
147 if (extension
.is_app()) {
148 info
->app_launch_url
.reset(
149 new std::string(delegate
->GetFullLaunchURL(&extension
).spec()));
152 const ExtensionIconSet::IconMap
& icons
=
153 IconsInfo::GetIcons(&extension
).map();
154 if (!icons
.empty()) {
155 info
->icons
.reset(new IconInfoList());
156 ExtensionIconSet::IconMap::const_iterator icon_iter
;
157 for (icon_iter
= icons
.begin(); icon_iter
!= icons
.end(); ++icon_iter
) {
158 management::IconInfo
* icon_info
= new management::IconInfo();
159 icon_info
->size
= icon_iter
->first
;
161 delegate
->GetIconURL(&extension
, icon_info
->size
,
162 ExtensionIconSet::MATCH_EXACTLY
, false, nullptr);
163 icon_info
->url
= url
.spec();
164 info
->icons
->push_back(make_linked_ptr
<management::IconInfo
>(icon_info
));
168 const std::set
<std::string
> perms
=
169 extension
.permissions_data()->active_permissions()->GetAPIsAsStrings();
170 if (!perms
.empty()) {
171 std::set
<std::string
>::const_iterator perms_iter
;
172 for (perms_iter
= perms
.begin(); perms_iter
!= perms
.end(); ++perms_iter
)
173 info
->permissions
.push_back(*perms_iter
);
176 if (!extension
.is_hosted_app()) {
177 // Skip host permissions for hosted apps.
178 const URLPatternSet host_perms
=
179 extension
.permissions_data()->active_permissions()->explicit_hosts();
180 if (!host_perms
.is_empty()) {
181 for (URLPatternSet::const_iterator iter
= host_perms
.begin();
182 iter
!= host_perms
.end(); ++iter
) {
183 info
->host_permissions
.push_back(iter
->GetAsString());
188 switch (extension
.location()) {
189 case Manifest::INTERNAL
:
190 info
->install_type
= management::EXTENSION_INSTALL_TYPE_NORMAL
;
192 case Manifest::UNPACKED
:
193 case Manifest::COMMAND_LINE
:
194 info
->install_type
= management::EXTENSION_INSTALL_TYPE_DEVELOPMENT
;
196 case Manifest::EXTERNAL_PREF
:
197 case Manifest::EXTERNAL_REGISTRY
:
198 case Manifest::EXTERNAL_PREF_DOWNLOAD
:
199 info
->install_type
= management::EXTENSION_INSTALL_TYPE_SIDELOAD
;
201 case Manifest::EXTERNAL_POLICY
:
202 case Manifest::EXTERNAL_POLICY_DOWNLOAD
:
203 info
->install_type
= management::EXTENSION_INSTALL_TYPE_ADMIN
;
205 case Manifest::NUM_LOCATIONS
:
207 case Manifest::INVALID_LOCATION
:
208 case Manifest::COMPONENT
:
209 case Manifest::EXTERNAL_COMPONENT
:
210 info
->install_type
= management::EXTENSION_INSTALL_TYPE_OTHER
;
214 info
->launch_type
= management::LAUNCH_TYPE_NONE
;
215 if (extension
.is_app()) {
216 LaunchType launch_type
;
217 if (extension
.is_platform_app()) {
218 launch_type
= LAUNCH_TYPE_WINDOW
;
221 delegate
->GetLaunchType(ExtensionPrefs::Get(context
), &extension
);
224 switch (launch_type
) {
225 case LAUNCH_TYPE_PINNED
:
226 info
->launch_type
= management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB
;
228 case LAUNCH_TYPE_REGULAR
:
229 info
->launch_type
= management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB
;
231 case LAUNCH_TYPE_FULLSCREEN
:
232 info
->launch_type
= management::LAUNCH_TYPE_OPEN_FULL_SCREEN
;
234 case LAUNCH_TYPE_WINDOW
:
235 info
->launch_type
= management::LAUNCH_TYPE_OPEN_AS_WINDOW
;
237 case LAUNCH_TYPE_INVALID
:
238 case NUM_LAUNCH_TYPES
:
242 info
->available_launch_types
.reset(new std::vector
<management::LaunchType
>(
243 GetAvailableLaunchTypes(extension
, delegate
)));
249 bool ShouldNotBeVisible(const Extension
* extension
,
250 content::BrowserContext
* context
) {
251 return (extension
->ShouldNotBeVisible() ||
252 ExtensionPrefs::Get(context
)->IsEphemeralApp(extension
->id()));
255 void AddExtensionInfo(const ExtensionSet
& extensions
,
256 ExtensionInfoList
* extension_list
,
257 content::BrowserContext
* context
) {
258 for (ExtensionSet::const_iterator iter
= extensions
.begin();
259 iter
!= extensions
.end(); ++iter
) {
260 const Extension
& extension
= *iter
->get();
262 if (ShouldNotBeVisible(&extension
, context
))
263 continue; // Skip built-in extensions/apps.
265 extension_list
->push_back(make_linked_ptr
<management::ExtensionInfo
>(
266 CreateExtensionInfo(extension
, context
).release()));
272 bool ManagementGetAllFunction::RunSync() {
273 ExtensionInfoList extensions
;
274 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser_context());
276 AddExtensionInfo(registry
->enabled_extensions(), &extensions
,
278 AddExtensionInfo(registry
->disabled_extensions(), &extensions
,
280 AddExtensionInfo(registry
->terminated_extensions(), &extensions
,
283 results_
= management::GetAll::Results::Create(extensions
);
287 bool ManagementGetFunction::RunSync() {
288 scoped_ptr
<management::Get::Params
> params(
289 management::Get::Params::Create(*args_
));
290 EXTENSION_FUNCTION_VALIDATE(params
.get());
291 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser_context());
293 const Extension
* extension
=
294 registry
->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
297 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
301 scoped_ptr
<management::ExtensionInfo
> info
=
302 CreateExtensionInfo(*extension
, browser_context());
303 results_
= management::Get::Results::Create(*info
);
308 bool ManagementGetSelfFunction::RunSync() {
309 scoped_ptr
<management::ExtensionInfo
> info
=
310 CreateExtensionInfo(*extension_
, browser_context());
311 results_
= management::Get::Results::Create(*info
);
316 bool ManagementGetPermissionWarningsByIdFunction::RunSync() {
317 scoped_ptr
<management::GetPermissionWarningsById::Params
> params(
318 management::GetPermissionWarningsById::Params::Create(*args_
));
319 EXTENSION_FUNCTION_VALIDATE(params
.get());
321 const Extension
* extension
=
322 ExtensionRegistry::Get(browser_context())
323 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
326 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
330 std::vector
<std::string
> warnings
= CreateWarningsList(extension
);
331 results_
= management::GetPermissionWarningsById::Results::Create(warnings
);
335 bool ManagementGetPermissionWarningsByManifestFunction::RunAsync() {
336 scoped_ptr
<management::GetPermissionWarningsByManifest::Params
> params(
337 management::GetPermissionWarningsByManifest::Params::Create(*args_
));
338 EXTENSION_FUNCTION_VALIDATE(params
.get());
340 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
341 ->Get(browser_context())
345 delegate
->GetPermissionWarningsByManifestFunctionDelegate(
346 this, params
->manifest_str
);
348 // Matched with a Release() in OnParseSuccess/Failure().
351 // Response is sent async in OnParseSuccess/Failure().
354 // TODO(lfg) add error string
360 void ManagementGetPermissionWarningsByManifestFunction::OnParseSuccess(
361 scoped_ptr
<base::Value
> value
) {
362 if (!value
->IsType(base::Value::TYPE_DICTIONARY
)) {
363 OnParseFailure(keys::kManifestParseError
);
366 const base::DictionaryValue
* parsed_manifest
=
367 static_cast<const base::DictionaryValue
*>(value
.get());
369 scoped_refptr
<Extension
> extension
=
370 Extension::Create(base::FilePath(), Manifest::INVALID_LOCATION
,
371 *parsed_manifest
, Extension::NO_FLAGS
, &error_
);
373 OnParseFailure(keys::kExtensionCreateError
);
377 std::vector
<std::string
> warnings
= CreateWarningsList(extension
.get());
379 management::GetPermissionWarningsByManifest::Results::Create(warnings
);
382 // Matched with AddRef() in RunAsync().
386 void ManagementGetPermissionWarningsByManifestFunction::OnParseFailure(
387 const std::string
& error
) {
391 // Matched with AddRef() in RunAsync().
395 bool ManagementLaunchAppFunction::RunSync() {
396 scoped_ptr
<management::LaunchApp::Params
> params(
397 management::LaunchApp::Params::Create(*args_
));
398 EXTENSION_FUNCTION_VALIDATE(params
.get());
399 const Extension
* extension
=
400 ExtensionRegistry::Get(browser_context())
401 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
404 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
407 if (!extension
->is_app()) {
408 error_
= ErrorUtils::FormatErrorMessage(keys::kNotAnAppError
, params
->id
);
412 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
413 ->Get(browser_context())
415 return delegate
->LaunchAppFunctionDelegate(extension
, browser_context());
418 ManagementSetEnabledFunction::ManagementSetEnabledFunction() {
421 ManagementSetEnabledFunction::~ManagementSetEnabledFunction() {
424 ExtensionFunction::ResponseAction
ManagementSetEnabledFunction::Run() {
425 scoped_ptr
<management::SetEnabled::Params
> params(
426 management::SetEnabled::Params::Create(*args_
));
427 EXTENSION_FUNCTION_VALIDATE(params
.get());
428 ExtensionRegistry
* registry
= ExtensionRegistry::Get(browser_context());
429 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
430 ->Get(browser_context())
433 extension_id_
= params
->id
;
435 const Extension
* extension
=
436 registry
->GetExtensionById(extension_id_
, ExtensionRegistry::EVERYTHING
);
437 if (!extension
|| ShouldNotBeVisible(extension
, browser_context()))
438 return RespondNow(Error(keys::kNoExtensionError
, extension_id_
));
440 bool enabled
= params
->enabled
;
441 const ManagementPolicy
* policy
=
442 ExtensionSystem::Get(browser_context())->management_policy();
443 if (!policy
->UserMayModifySettings(extension
, nullptr) ||
444 (!enabled
&& policy
->MustRemainEnabled(extension
, nullptr)) ||
445 (enabled
&& policy
->MustRemainDisabled(extension
, nullptr, nullptr))) {
446 return RespondNow(Error(keys::kUserCantModifyError
, extension_id_
));
449 bool currently_enabled
=
450 registry
->enabled_extensions().Contains(extension_id_
) ||
451 registry
->terminated_extensions().Contains(extension_id_
);
453 if (!currently_enabled
&& enabled
) {
454 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(browser_context());
455 if (prefs
->DidExtensionEscalatePermissions(extension_id_
)) {
457 return RespondNow(Error(keys::kGestureNeededForEscalationError
));
459 AddRef(); // Matched in InstallUIProceed/InstallUIAbort
460 install_prompt_
= delegate
->SetEnabledFunctionDelegate(this, extension
);
461 return RespondLater();
463 if (prefs
->GetDisableReasons(extension_id_
) &
464 Extension::DISABLE_UNSUPPORTED_REQUIREMENT
) {
465 // Recheck the requirements.
466 requirements_checker_
= delegate
->CreateRequirementsChecker();
467 requirements_checker_
->Check(
469 base::Bind(&ManagementSetEnabledFunction::OnRequirementsChecked
,
470 this)); // This bind creates a reference.
471 return RespondLater();
473 delegate
->EnableExtension(browser_context(), extension_id_
);
474 } else if (currently_enabled
&& !params
->enabled
) {
475 delegate
->DisableExtension(browser_context(), extension_id_
,
476 Extension::DISABLE_USER_ACTION
);
479 return RespondNow(NoArguments());
482 void ManagementSetEnabledFunction::InstallUIProceed() {
483 ManagementAPI::GetFactoryInstance()
484 ->Get(browser_context())
486 ->EnableExtension(browser_context(), extension_id_
);
487 Respond(OneArgument(new base::FundamentalValue(true)));
491 void ManagementSetEnabledFunction::InstallUIAbort(bool user_initiated
) {
492 Respond(Error(keys::kUserDidNotReEnableError
));
496 void ManagementSetEnabledFunction::OnRequirementsChecked(
497 const std::vector
<std::string
>& requirements_errors
) {
498 if (requirements_errors
.empty()) {
499 ManagementAPI::GetFactoryInstance()->Get(browser_context())->GetDelegate()->
500 EnableExtension(browser_context(), extension_id_
);
501 Respond(NoArguments());
503 // TODO(devlin): Should we really be noisy here all the time?
504 Respond(Error(keys::kMissingRequirementsError
,
505 base::JoinString(requirements_errors
, " ")));
509 ManagementUninstallFunctionBase::ManagementUninstallFunctionBase() {
512 ManagementUninstallFunctionBase::~ManagementUninstallFunctionBase() {
515 ExtensionFunction::ResponseAction
ManagementUninstallFunctionBase::Uninstall(
516 const std::string
& target_extension_id
,
517 bool show_confirm_dialog
) {
518 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
519 ->Get(browser_context())
521 target_extension_id_
= target_extension_id
;
522 const Extension
* target_extension
=
523 extensions::ExtensionRegistry::Get(browser_context())
524 ->GetExtensionById(target_extension_id_
,
525 ExtensionRegistry::EVERYTHING
);
526 if (!target_extension
||
527 ShouldNotBeVisible(target_extension
, browser_context())) {
528 return RespondNow(Error(keys::kNoExtensionError
, target_extension_id_
));
531 ManagementPolicy
* policy
=
532 ExtensionSystem::Get(browser_context())->management_policy();
533 if (!policy
->UserMayModifySettings(target_extension
, nullptr) ||
534 policy
->MustRemainInstalled(target_extension
, nullptr)) {
535 return RespondNow(Error(keys::kUserCantModifyError
, target_extension_id_
));
538 // Note: null extension() means it's WebUI.
539 bool self_uninstall
= extension() && extension_id() == target_extension_id_
;
540 // We need to show a dialog for any extension uninstalling another extension.
541 show_confirm_dialog
|= !self_uninstall
;
543 if (show_confirm_dialog
&& !user_gesture())
544 return RespondNow(Error(keys::kGestureNeededForUninstallError
));
546 if (show_confirm_dialog
) {
547 // We show the programmatic uninstall ui for extensions uninstalling
549 bool show_programmatic_uninstall_ui
= !self_uninstall
&& extension();
550 AddRef(); // Balanced in OnExtensionUninstallDialogClosed.
551 // TODO(devlin): A method called "UninstallFunctionDelegate" does not in
552 // any way imply that this actually creates a dialog and runs it.
553 uninstall_dialog_
= delegate
->UninstallFunctionDelegate(
554 this, target_extension
, show_programmatic_uninstall_ui
);
555 } else { // No confirm dialog.
556 base::MessageLoop::current()->PostTask(
558 base::Bind(&ManagementUninstallFunctionBase::UninstallExtension
, this));
561 return RespondLater();
564 void ManagementUninstallFunctionBase::Finish(bool did_start_uninstall
,
565 const std::string
& error
) {
566 Respond(did_start_uninstall
? NoArguments() : Error(error
));
569 void ManagementUninstallFunctionBase::OnExtensionUninstallDialogClosed(
570 bool did_start_uninstall
,
571 const base::string16
& error
) {
572 Finish(did_start_uninstall
,
573 ErrorUtils::FormatErrorMessage(keys::kUninstallCanceledError
,
574 target_extension_id_
));
575 Release(); // Balanced in Uninstall().
578 void ManagementUninstallFunctionBase::UninstallExtension() {
579 // The extension can be uninstalled in another window while the UI was
580 // showing. Do nothing in that case.
581 const Extension
* target_extension
=
582 extensions::ExtensionRegistry::Get(browser_context())
583 ->GetExtensionById(target_extension_id_
,
584 ExtensionRegistry::EVERYTHING
);
586 bool success
= false;
587 if (target_extension
) {
588 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
589 ->Get(browser_context())
591 base::string16 utf16_error
;
592 success
= delegate
->UninstallExtension(
593 browser_context(), target_extension_id_
,
594 extensions::UNINSTALL_REASON_MANAGEMENT_API
,
595 base::Bind(&base::DoNothing
), &utf16_error
);
596 error
= base::UTF16ToUTF8(utf16_error
);
598 error
= ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
,
599 target_extension_id_
);
601 Finish(success
, error
);
604 ManagementUninstallFunction::ManagementUninstallFunction() {
607 ManagementUninstallFunction::~ManagementUninstallFunction() {
610 ExtensionFunction::ResponseAction
ManagementUninstallFunction::Run() {
611 scoped_ptr
<management::Uninstall::Params
> params(
612 management::Uninstall::Params::Create(*args_
));
613 EXTENSION_FUNCTION_VALIDATE(params
.get());
615 bool show_confirm_dialog
= params
->options
.get() &&
616 params
->options
->show_confirm_dialog
.get() &&
617 *params
->options
->show_confirm_dialog
;
618 return Uninstall(params
->id
, show_confirm_dialog
);
621 ManagementUninstallSelfFunction::ManagementUninstallSelfFunction() {
624 ManagementUninstallSelfFunction::~ManagementUninstallSelfFunction() {
627 ExtensionFunction::ResponseAction
ManagementUninstallSelfFunction::Run() {
628 scoped_ptr
<management::UninstallSelf::Params
> params(
629 management::UninstallSelf::Params::Create(*args_
));
630 EXTENSION_FUNCTION_VALIDATE(params
.get());
631 EXTENSION_FUNCTION_VALIDATE(extension_
.get());
633 bool show_confirm_dialog
= params
->options
.get() &&
634 params
->options
->show_confirm_dialog
.get() &&
635 *params
->options
->show_confirm_dialog
;
636 return Uninstall(extension_
->id(), show_confirm_dialog
);
639 ManagementCreateAppShortcutFunction::ManagementCreateAppShortcutFunction() {
642 ManagementCreateAppShortcutFunction::~ManagementCreateAppShortcutFunction() {
646 void ManagementCreateAppShortcutFunction::SetAutoConfirmForTest(
647 bool should_proceed
) {
648 auto_confirm_for_test
= should_proceed
? PROCEED
: ABORT
;
651 void ManagementCreateAppShortcutFunction::OnCloseShortcutPrompt(bool created
) {
653 error_
= keys::kCreateShortcutCanceledError
;
654 SendResponse(created
);
658 bool ManagementCreateAppShortcutFunction::RunAsync() {
659 if (!user_gesture()) {
660 error_
= keys::kGestureNeededForCreateAppShortcutError
;
664 scoped_ptr
<management::CreateAppShortcut::Params
> params(
665 management::CreateAppShortcut::Params::Create(*args_
));
666 EXTENSION_FUNCTION_VALIDATE(params
.get());
667 const Extension
* extension
=
668 ExtensionRegistry::Get(browser_context())
669 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
672 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
676 if (!extension
->is_app()) {
677 error_
= ErrorUtils::FormatErrorMessage(keys::kNotAnAppError
, params
->id
);
681 #if defined(OS_MACOSX)
682 if (!extension
->is_platform_app()) {
683 error_
= keys::kCreateOnlyPackagedAppShortcutMac
;
688 if (auto_confirm_for_test
!= DO_NOT_SKIP
) {
689 // Matched with a Release() in OnCloseShortcutPrompt().
692 OnCloseShortcutPrompt(auto_confirm_for_test
== PROCEED
);
697 if (ManagementAPI::GetFactoryInstance()
698 ->Get(browser_context())
700 ->CreateAppShortcutFunctionDelegate(this, extension
)) {
701 // Matched with a Release() in OnCloseShortcutPrompt().
705 // Response is sent async in OnCloseShortcutPrompt().
709 bool ManagementSetLaunchTypeFunction::RunSync() {
710 if (!user_gesture()) {
711 error_
= keys::kGestureNeededForSetLaunchTypeError
;
715 scoped_ptr
<management::SetLaunchType::Params
> params(
716 management::SetLaunchType::Params::Create(*args_
));
717 EXTENSION_FUNCTION_VALIDATE(params
.get());
718 const Extension
* extension
=
719 ExtensionRegistry::Get(browser_context())
720 ->GetExtensionById(params
->id
, ExtensionRegistry::EVERYTHING
);
721 const ManagementAPIDelegate
* delegate
= ManagementAPI::GetFactoryInstance()
722 ->Get(browser_context())
726 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError
, params
->id
);
730 if (!extension
->is_app()) {
731 error_
= ErrorUtils::FormatErrorMessage(keys::kNotAnAppError
, params
->id
);
735 std::vector
<management::LaunchType
> available_launch_types
=
736 GetAvailableLaunchTypes(*extension
, delegate
);
738 management::LaunchType app_launch_type
= params
->launch_type
;
739 if (std::find(available_launch_types
.begin(), available_launch_types
.end(),
740 app_launch_type
) == available_launch_types
.end()) {
741 error_
= keys::kLaunchTypeNotAvailableError
;
745 LaunchType launch_type
= LAUNCH_TYPE_DEFAULT
;
746 switch (app_launch_type
) {
747 case management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB
:
748 launch_type
= LAUNCH_TYPE_PINNED
;
750 case management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB
:
751 launch_type
= LAUNCH_TYPE_REGULAR
;
753 case management::LAUNCH_TYPE_OPEN_FULL_SCREEN
:
754 launch_type
= LAUNCH_TYPE_FULLSCREEN
;
756 case management::LAUNCH_TYPE_OPEN_AS_WINDOW
:
757 launch_type
= LAUNCH_TYPE_WINDOW
;
759 case management::LAUNCH_TYPE_NONE
:
763 delegate
->SetLaunchType(browser_context(), params
->id
, launch_type
);
768 ManagementGenerateAppForLinkFunction::ManagementGenerateAppForLinkFunction() {
771 ManagementGenerateAppForLinkFunction::~ManagementGenerateAppForLinkFunction() {
774 void ManagementGenerateAppForLinkFunction::FinishCreateBookmarkApp(
775 const Extension
* extension
,
776 const WebApplicationInfo
& web_app_info
) {
778 scoped_ptr
<management::ExtensionInfo
> info
=
779 CreateExtensionInfo(*extension
, browser_context());
780 results_
= management::GenerateAppForLink::Results::Create(*info
);
785 error_
= keys::kGenerateAppForLinkInstallError
;
791 bool ManagementGenerateAppForLinkFunction::RunAsync() {
792 if (!user_gesture()) {
793 error_
= keys::kGestureNeededForGenerateAppForLinkError
;
797 scoped_ptr
<management::GenerateAppForLink::Params
> params(
798 management::GenerateAppForLink::Params::Create(*args_
));
799 EXTENSION_FUNCTION_VALIDATE(params
.get());
801 GURL
launch_url(params
->url
);
802 if (!launch_url
.is_valid() || !launch_url
.SchemeIsHTTPOrHTTPS()) {
804 ErrorUtils::FormatErrorMessage(keys::kInvalidURLError
, params
->url
);
808 if (params
->title
.empty()) {
809 error_
= keys::kEmptyTitleError
;
813 app_for_link_delegate_
=
814 ManagementAPI::GetFactoryInstance()
815 ->Get(browser_context())
817 ->GenerateAppForLinkFunctionDelegate(this, browser_context(),
818 params
->title
, launch_url
);
820 // Matched with a Release() in FinishCreateBookmarkApp().
823 // Response is sent async in FinishCreateBookmarkApp().
827 ManagementEventRouter::ManagementEventRouter(content::BrowserContext
* context
)
828 : browser_context_(context
), extension_registry_observer_(this) {
829 extension_registry_observer_
.Add(ExtensionRegistry::Get(browser_context_
));
832 ManagementEventRouter::~ManagementEventRouter() {
835 void ManagementEventRouter::OnExtensionLoaded(
836 content::BrowserContext
* browser_context
,
837 const Extension
* extension
) {
838 BroadcastEvent(extension
, events::MANAGEMENT_ON_ENABLED
,
839 management::OnEnabled::kEventName
);
842 void ManagementEventRouter::OnExtensionUnloaded(
843 content::BrowserContext
* browser_context
,
844 const Extension
* extension
,
845 UnloadedExtensionInfo::Reason reason
) {
846 BroadcastEvent(extension
, events::MANAGEMENT_ON_DISABLED
,
847 management::OnDisabled::kEventName
);
850 void ManagementEventRouter::OnExtensionInstalled(
851 content::BrowserContext
* browser_context
,
852 const Extension
* extension
,
854 BroadcastEvent(extension
, events::MANAGEMENT_ON_INSTALLED
,
855 management::OnInstalled::kEventName
);
858 void ManagementEventRouter::OnExtensionUninstalled(
859 content::BrowserContext
* browser_context
,
860 const Extension
* extension
,
861 extensions::UninstallReason reason
) {
862 BroadcastEvent(extension
, events::MANAGEMENT_ON_UNINSTALLED
,
863 management::OnUninstalled::kEventName
);
866 void ManagementEventRouter::BroadcastEvent(
867 const Extension
* extension
,
868 events::HistogramValue histogram_value
,
869 const char* event_name
) {
870 if (ShouldNotBeVisible(extension
, browser_context_
))
871 return; // Don't dispatch events for built-in extenions.
872 scoped_ptr
<base::ListValue
> args(new base::ListValue());
873 if (event_name
== management::OnUninstalled::kEventName
) {
874 args
->Append(new base::StringValue(extension
->id()));
876 scoped_ptr
<management::ExtensionInfo
> info
=
877 CreateExtensionInfo(*extension
, browser_context_
);
878 args
->Append(info
->ToValue().release());
881 EventRouter::Get(browser_context_
)
882 ->BroadcastEvent(scoped_ptr
<Event
>(
883 new Event(histogram_value
, event_name
, args
.Pass())));
886 ManagementAPI::ManagementAPI(content::BrowserContext
* context
)
887 : browser_context_(context
),
888 delegate_(ExtensionsAPIClient::Get()->CreateManagementAPIDelegate()) {
889 EventRouter
* event_router
= EventRouter::Get(browser_context_
);
890 event_router
->RegisterObserver(this, management::OnInstalled::kEventName
);
891 event_router
->RegisterObserver(this, management::OnUninstalled::kEventName
);
892 event_router
->RegisterObserver(this, management::OnEnabled::kEventName
);
893 event_router
->RegisterObserver(this, management::OnDisabled::kEventName
);
896 ManagementAPI::~ManagementAPI() {
899 void ManagementAPI::Shutdown() {
900 EventRouter::Get(browser_context_
)->UnregisterObserver(this);
903 static base::LazyInstance
<BrowserContextKeyedAPIFactory
<ManagementAPI
>>
904 g_factory
= LAZY_INSTANCE_INITIALIZER
;
907 BrowserContextKeyedAPIFactory
<ManagementAPI
>*
908 ManagementAPI::GetFactoryInstance() {
909 return g_factory
.Pointer();
912 void ManagementAPI::OnListenerAdded(const EventListenerInfo
& details
) {
913 management_event_router_
.reset(new ManagementEventRouter(browser_context_
));
914 EventRouter::Get(browser_context_
)->UnregisterObserver(this);
917 } // namespace extensions