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 "chrome/browser/extensions/api/management/management_api.h"
11 #include "base/basictypes.h"
12 #include "base/bind.h"
13 #include "base/json/json_writer.h"
14 #include "base/lazy_instance.h"
15 #include "base/logging.h"
16 #include "base/memory/linked_ptr.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/metrics/histogram.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "chrome/browser/chrome_notification_types.h"
23 #include "chrome/browser/extensions/api/management/management_api_constants.h"
24 #include "chrome/browser/extensions/extension_service.h"
25 #include "chrome/browser/extensions/extension_uninstall_dialog.h"
26 #include "chrome/browser/extensions/launch_util.h"
27 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/ui/browser_dialogs.h"
29 #include "chrome/browser/ui/browser_finder.h"
30 #include "chrome/browser/ui/browser_window.h"
31 #include "chrome/browser/ui/extensions/application_launch.h"
32 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
33 #include "chrome/common/chrome_utility_messages.h"
34 #include "chrome/common/extensions/api/management.h"
35 #include "chrome/common/extensions/extension_constants.h"
36 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
37 #include "chrome/common/extensions/manifest_url_handler.h"
38 #include "content/public/browser/notification_details.h"
39 #include "content/public/browser/notification_source.h"
40 #include "content/public/browser/utility_process_host.h"
41 #include "content/public/browser/utility_process_host_client.h"
42 #include "extensions/browser/event_router.h"
43 #include "extensions/browser/extension_registry.h"
44 #include "extensions/browser/extension_system.h"
45 #include "extensions/browser/management_policy.h"
46 #include "extensions/common/constants.h"
47 #include "extensions/common/error_utils.h"
48 #include "extensions/common/extension.h"
49 #include "extensions/common/extension_icon_set.h"
50 #include "extensions/common/manifest_handlers/icons_handler.h"
51 #include "extensions/common/manifest_handlers/offline_enabled_info.h"
52 #include "extensions/common/permissions/permission_set.h"
53 #include "extensions/common/permissions/permissions_data.h"
54 #include "extensions/common/url_pattern.h"
56 #if !defined(OS_ANDROID)
57 #include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
60 using base::IntToString;
61 using content::BrowserThread;
62 using content::UtilityProcessHost;
63 using content::UtilityProcessHostClient;
65 namespace keys = extension_management_api_constants;
67 namespace extensions {
69 namespace management = api::management;
73 typedef std::vector<linked_ptr<management::ExtensionInfo> > ExtensionInfoList;
74 typedef std::vector<linked_ptr<management::IconInfo> > IconInfoList;
76 enum AutoConfirmForTest {
82 AutoConfirmForTest auto_confirm_for_test = DO_NOT_SKIP;
84 std::vector<std::string> CreateWarningsList(const Extension* extension) {
85 std::vector<std::string> warnings_list;
86 PermissionMessages warnings =
87 PermissionsData::GetPermissionMessages(extension);
88 for (PermissionMessages::const_iterator iter = warnings.begin();
89 iter != warnings.end(); ++iter) {
90 warnings_list.push_back(base::UTF16ToUTF8(iter->message()));
96 scoped_ptr<management::ExtensionInfo> CreateExtensionInfo(
97 const Extension& extension,
98 ExtensionSystem* system) {
99 scoped_ptr<management::ExtensionInfo> info(new management::ExtensionInfo());
100 ExtensionService* service = system->extension_service();
102 info->id = extension.id();
103 info->name = extension.name();
104 info->short_name = extension.short_name();
105 info->enabled = service->IsExtensionEnabled(info->id);
106 info->offline_enabled = OfflineEnabledInfo::IsOfflineEnabled(&extension);
107 info->version = extension.VersionString();
108 info->description = extension.description();
109 info->options_url = ManifestURL::GetOptionsPage(&extension).spec();
110 info->homepage_url.reset(new std::string(
111 ManifestURL::GetHomepageURL(&extension).spec()));
112 info->may_disable = system->management_policy()->
113 UserMayModifySettings(&extension, NULL);
114 info->is_app = extension.is_app();
116 if (extension.is_legacy_packaged_app())
117 info->type = management::ExtensionInfo::TYPE_LEGACY_PACKAGED_APP;
118 else if (extension.is_hosted_app())
119 info->type = management::ExtensionInfo::TYPE_HOSTED_APP;
121 info->type = management::ExtensionInfo::TYPE_PACKAGED_APP;
122 } else if (extension.is_theme()) {
123 info->type = management::ExtensionInfo::TYPE_THEME;
125 info->type = management::ExtensionInfo::TYPE_EXTENSION;
129 info->disabled_reason = management::ExtensionInfo::DISABLED_REASON_NONE;
131 ExtensionPrefs* prefs = ExtensionPrefs::Get(service->profile());
132 if (prefs->DidExtensionEscalatePermissions(extension.id())) {
133 info->disabled_reason =
134 management::ExtensionInfo::DISABLED_REASON_PERMISSIONS_INCREASE;
136 info->disabled_reason =
137 management::ExtensionInfo::DISABLED_REASON_UNKNOWN;
141 if (!ManifestURL::GetUpdateURL(&extension).is_empty()) {
142 info->update_url.reset(new std::string(
143 ManifestURL::GetUpdateURL(&extension).spec()));
146 if (extension.is_app()) {
147 info->app_launch_url.reset(new std::string(
148 AppLaunchInfo::GetFullLaunchURL(&extension).spec()));
151 const ExtensionIconSet::IconMap& icons =
152 IconsInfo::GetIcons(&extension).map();
153 if (!icons.empty()) {
154 info->icons.reset(new IconInfoList());
155 ExtensionIconSet::IconMap::const_iterator icon_iter;
156 for (icon_iter = icons.begin(); icon_iter != icons.end(); ++icon_iter) {
157 management::IconInfo* icon_info = new management::IconInfo();
158 icon_info->size = icon_iter->first;
159 GURL url = ExtensionIconSource::GetIconURL(
160 &extension, icon_info->size, ExtensionIconSet::MATCH_EXACTLY, false,
162 icon_info->url = url.spec();
163 info->icons->push_back(make_linked_ptr<management::IconInfo>(icon_info));
167 const std::set<std::string> perms =
168 extension.GetActivePermissions()->GetAPIsAsStrings();
169 if (!perms.empty()) {
170 std::set<std::string>::const_iterator perms_iter;
171 for (perms_iter = perms.begin(); perms_iter != perms.end(); ++perms_iter)
172 info->permissions.push_back(*perms_iter);
175 if (!extension.is_hosted_app()) {
176 // Skip host permissions for hosted apps.
177 const URLPatternSet host_perms =
178 extension.GetActivePermissions()->explicit_hosts();
179 if (!host_perms.is_empty()) {
180 for (URLPatternSet::const_iterator iter = host_perms.begin();
181 iter != host_perms.end(); ++iter) {
182 info->host_permissions.push_back(iter->GetAsString());
187 switch (extension.location()) {
188 case Manifest::INTERNAL:
189 info->install_type = management::ExtensionInfo::INSTALL_TYPE_NORMAL;
191 case Manifest::UNPACKED:
192 case Manifest::COMMAND_LINE:
193 info->install_type = management::ExtensionInfo::INSTALL_TYPE_DEVELOPMENT;
195 case Manifest::EXTERNAL_PREF:
196 case Manifest::EXTERNAL_REGISTRY:
197 case Manifest::EXTERNAL_PREF_DOWNLOAD:
198 info->install_type = management::ExtensionInfo::INSTALL_TYPE_SIDELOAD;
200 case Manifest::EXTERNAL_POLICY:
201 case Manifest::EXTERNAL_POLICY_DOWNLOAD:
202 info->install_type = management::ExtensionInfo::INSTALL_TYPE_ADMIN;
204 case Manifest::NUM_LOCATIONS:
206 case Manifest::INVALID_LOCATION:
207 case Manifest::COMPONENT:
208 case Manifest::EXTERNAL_COMPONENT:
209 info->install_type = management::ExtensionInfo::INSTALL_TYPE_OTHER;
216 void AddExtensionInfo(const ExtensionSet& extensions,
217 ExtensionSystem* system,
218 ExtensionInfoList* extension_list) {
219 for (ExtensionSet::const_iterator iter = extensions.begin();
220 iter != extensions.end(); ++iter) {
221 const Extension& extension = *iter->get();
223 if (extension.ShouldNotBeVisible())
224 continue; // Skip built-in extensions/apps.
226 extension_list->push_back(make_linked_ptr<management::ExtensionInfo>(
227 CreateExtensionInfo(extension, system).release()));
233 ExtensionService* ManagementFunction::service() {
234 return GetProfile()->GetExtensionService();
237 ExtensionService* AsyncManagementFunction::service() {
238 return GetProfile()->GetExtensionService();
241 bool ManagementGetAllFunction::RunSync() {
242 ExtensionInfoList extensions;
243 ExtensionRegistry* registry = ExtensionRegistry::Get(GetProfile());
244 ExtensionSystem* system = ExtensionSystem::Get(GetProfile());
246 AddExtensionInfo(registry->enabled_extensions(), system, &extensions);
247 AddExtensionInfo(registry->disabled_extensions(), system, &extensions);
248 AddExtensionInfo(registry->terminated_extensions(), system, &extensions);
250 results_ = management::GetAll::Results::Create(extensions);
254 bool ManagementGetFunction::RunSync() {
255 scoped_ptr<management::Get::Params> params(
256 management::Get::Params::Create(*args_));
257 EXTENSION_FUNCTION_VALIDATE(params.get());
259 const Extension* extension = service()->GetExtensionById(params->id, true);
261 error_ = ErrorUtils::FormatErrorMessage(keys::kNoExtensionError,
266 scoped_ptr<management::ExtensionInfo> info =
267 CreateExtensionInfo(*extension, ExtensionSystem::Get(GetProfile()));
268 results_ = management::Get::Results::Create(*info);
273 bool ManagementGetPermissionWarningsByIdFunction::RunSync() {
274 scoped_ptr<management::GetPermissionWarningsById::Params> params(
275 management::GetPermissionWarningsById::Params::Create(*args_));
276 EXTENSION_FUNCTION_VALIDATE(params.get());
278 const Extension* extension = service()->GetExtensionById(params->id, true);
280 error_ = ErrorUtils::FormatErrorMessage(keys::kNoExtensionError,
285 std::vector<std::string> warnings = CreateWarningsList(extension);
286 results_ = management::GetPermissionWarningsById::Results::Create(warnings);
292 // This class helps ManagementGetPermissionWarningsByManifestFunction manage
293 // sending manifest JSON strings to the utility process for parsing.
294 class SafeManifestJSONParser : public UtilityProcessHostClient {
296 SafeManifestJSONParser(
297 ManagementGetPermissionWarningsByManifestFunction* client,
298 const std::string& manifest)
300 manifest_(manifest) {}
303 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
304 BrowserThread::PostTask(
307 base::Bind(&SafeManifestJSONParser::StartWorkOnIOThread, this));
310 void StartWorkOnIOThread() {
311 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
312 UtilityProcessHost* host = UtilityProcessHost::Create(
313 this, base::MessageLoopProxy::current().get());
314 host->Send(new ChromeUtilityMsg_ParseJSON(manifest_));
317 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
319 IPC_BEGIN_MESSAGE_MAP(SafeManifestJSONParser, message)
320 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Succeeded,
321 OnJSONParseSucceeded)
322 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Failed,
324 IPC_MESSAGE_UNHANDLED(handled = false)
325 IPC_END_MESSAGE_MAP()
329 void OnJSONParseSucceeded(const base::ListValue& wrapper) {
330 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
331 const base::Value* value = NULL;
332 CHECK(wrapper.Get(0, &value));
333 if (value->IsType(base::Value::TYPE_DICTIONARY))
334 parsed_manifest_.reset(
335 static_cast<const base::DictionaryValue*>(value)->DeepCopy());
337 error_ = keys::kManifestParseError;
339 BrowserThread::PostTask(
342 base::Bind(&SafeManifestJSONParser::ReportResultFromUIThread, this));
345 void OnJSONParseFailed(const std::string& error) {
346 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
348 BrowserThread::PostTask(
351 base::Bind(&SafeManifestJSONParser::ReportResultFromUIThread, this));
354 void ReportResultFromUIThread() {
355 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
356 if (error_.empty() && parsed_manifest_.get())
357 client_->OnParseSuccess(parsed_manifest_.Pass());
359 client_->OnParseFailure(error_);
363 virtual ~SafeManifestJSONParser() {}
365 // The client who we'll report results back to.
366 ManagementGetPermissionWarningsByManifestFunction* client_;
369 std::string manifest_;
371 // Results of parsing.
372 scoped_ptr<base::DictionaryValue> parsed_manifest_;
379 bool ManagementGetPermissionWarningsByManifestFunction::RunAsync() {
380 scoped_ptr<management::GetPermissionWarningsByManifest::Params> params(
381 management::GetPermissionWarningsByManifest::Params::Create(*args_));
382 EXTENSION_FUNCTION_VALIDATE(params.get());
384 scoped_refptr<SafeManifestJSONParser> parser =
385 new SafeManifestJSONParser(this, params->manifest_str);
388 // Matched with a Release() in OnParseSuccess/Failure().
391 // Response is sent async in OnParseSuccess/Failure().
395 void ManagementGetPermissionWarningsByManifestFunction::OnParseSuccess(
396 scoped_ptr<base::DictionaryValue> parsed_manifest) {
397 CHECK(parsed_manifest.get());
399 scoped_refptr<Extension> extension = Extension::Create(
400 base::FilePath(), Manifest::INVALID_LOCATION, *parsed_manifest,
401 Extension::NO_FLAGS, &error_);
402 if (!extension.get()) {
403 OnParseFailure(keys::kExtensionCreateError);
407 std::vector<std::string> warnings = CreateWarningsList(extension.get());
409 management::GetPermissionWarningsByManifest::Results::Create(warnings);
412 // Matched with AddRef() in RunAsync().
416 void ManagementGetPermissionWarningsByManifestFunction::OnParseFailure(
417 const std::string& error) {
421 // Matched with AddRef() in RunAsync().
425 bool ManagementLaunchAppFunction::RunSync() {
426 scoped_ptr<management::LaunchApp::Params> params(
427 management::LaunchApp::Params::Create(*args_));
428 EXTENSION_FUNCTION_VALIDATE(params.get());
429 const Extension* extension = service()->GetExtensionById(params->id, true);
431 error_ = ErrorUtils::FormatErrorMessage(keys::kNoExtensionError,
435 if (!extension->is_app()) {
436 error_ = ErrorUtils::FormatErrorMessage(keys::kNotAnAppError,
441 // Look at prefs to find the right launch container.
442 // If the user has not set a preference, the default launch value will be
444 LaunchContainer launch_container =
445 GetLaunchContainer(ExtensionPrefs::Get(GetProfile()), extension);
446 OpenApplication(AppLaunchParams(
447 GetProfile(), extension, launch_container, NEW_FOREGROUND_TAB));
448 #if !defined(OS_ANDROID)
449 CoreAppLauncherHandler::RecordAppLaunchType(
450 extension_misc::APP_LAUNCH_EXTENSION_API,
451 extension->GetType());
457 ManagementSetEnabledFunction::ManagementSetEnabledFunction() {
460 ManagementSetEnabledFunction::~ManagementSetEnabledFunction() {
463 bool ManagementSetEnabledFunction::RunAsync() {
464 scoped_ptr<management::SetEnabled::Params> params(
465 management::SetEnabled::Params::Create(*args_));
466 EXTENSION_FUNCTION_VALIDATE(params.get());
468 extension_id_ = params->id;
470 const Extension* extension = service()->GetInstalledExtension(extension_id_);
471 if (!extension || extension->ShouldNotBeVisible()) {
472 error_ = ErrorUtils::FormatErrorMessage(
473 keys::kNoExtensionError, extension_id_);
477 const ManagementPolicy* policy =
478 ExtensionSystem::Get(GetProfile())->management_policy();
479 if (!policy->UserMayModifySettings(extension, NULL) ||
480 (!params->enabled && policy->MustRemainEnabled(extension, NULL)) ||
481 (params->enabled && policy->MustRemainDisabled(extension, NULL, NULL))) {
482 error_ = ErrorUtils::FormatErrorMessage(
483 keys::kUserCantModifyError, extension_id_);
487 bool currently_enabled = service()->IsExtensionEnabled(extension_id_);
489 if (!currently_enabled && params->enabled) {
490 ExtensionPrefs* prefs = ExtensionPrefs::Get(GetProfile());
491 if (prefs->DidExtensionEscalatePermissions(extension_id_)) {
492 if (!user_gesture()) {
493 error_ = keys::kGestureNeededForEscalationError;
496 AddRef(); // Matched in InstallUIProceed/InstallUIAbort
497 install_prompt_.reset(
498 new ExtensionInstallPrompt(GetAssociatedWebContents()));
499 install_prompt_->ConfirmReEnable(this, extension);
502 service()->EnableExtension(extension_id_);
503 } else if (currently_enabled && !params->enabled) {
504 service()->DisableExtension(extension_id_, Extension::DISABLE_USER_ACTION);
507 BrowserThread::PostTask(
510 base::Bind(&ManagementSetEnabledFunction::SendResponse, this, true));
515 void ManagementSetEnabledFunction::InstallUIProceed() {
516 service()->EnableExtension(extension_id_);
521 void ManagementSetEnabledFunction::InstallUIAbort(bool user_initiated) {
522 error_ = keys::kUserDidNotReEnableError;
527 ManagementUninstallFunctionBase::ManagementUninstallFunctionBase() {
530 ManagementUninstallFunctionBase::~ManagementUninstallFunctionBase() {
533 bool ManagementUninstallFunctionBase::Uninstall(
534 const std::string& target_extension_id,
535 bool show_confirm_dialog) {
536 extension_id_ = target_extension_id;
537 const Extension* target_extension =
538 service()->GetExtensionById(extension_id_, true);
539 if (!target_extension || target_extension->ShouldNotBeVisible()) {
540 error_ = ErrorUtils::FormatErrorMessage(
541 keys::kNoExtensionError, extension_id_);
545 if (!ExtensionSystem::Get(GetProfile())
546 ->management_policy()
547 ->UserMayModifySettings(target_extension, NULL)) {
548 error_ = ErrorUtils::FormatErrorMessage(
549 keys::kUserCantModifyError, extension_id_);
553 if (auto_confirm_for_test == DO_NOT_SKIP) {
554 if (show_confirm_dialog) {
555 AddRef(); // Balanced in ExtensionUninstallAccepted/Canceled
556 extension_uninstall_dialog_.reset(ExtensionUninstallDialog::Create(
557 GetProfile(), GetCurrentBrowser(), this));
558 if (extension_id() != target_extension_id) {
559 extension_uninstall_dialog_->ConfirmProgrammaticUninstall(
560 target_extension, GetExtension());
562 // If this is a self uninstall, show the generic uninstall dialog.
563 extension_uninstall_dialog_->ConfirmUninstall(target_extension);
569 Finish(auto_confirm_for_test == PROCEED);
576 void ManagementUninstallFunctionBase::SetAutoConfirmForTest(
577 bool should_proceed) {
578 auto_confirm_for_test = should_proceed ? PROCEED : ABORT;
581 void ManagementUninstallFunctionBase::Finish(bool should_uninstall) {
582 if (should_uninstall) {
583 // The extension can be uninstalled in another window while the UI was
584 // showing. Do nothing in that case.
585 ExtensionRegistry* registry = ExtensionRegistry::Get(GetProfile());
586 const Extension* extension = registry->GetExtensionById(
587 extension_id_, ExtensionRegistry::EVERYTHING);
589 error_ = ErrorUtils::FormatErrorMessage(keys::kNoExtensionError,
594 service()->UninstallExtension(extension_id_,
595 false, /* external uninstall */
598 // TODO set error_ if !success
599 SendResponse(success);
602 error_ = ErrorUtils::FormatErrorMessage(
603 keys::kUninstallCanceledError, extension_id_);
609 void ManagementUninstallFunctionBase::ExtensionUninstallAccepted() {
614 void ManagementUninstallFunctionBase::ExtensionUninstallCanceled() {
619 ManagementUninstallFunction::ManagementUninstallFunction() {
622 ManagementUninstallFunction::~ManagementUninstallFunction() {
625 bool ManagementUninstallFunction::RunAsync() {
626 scoped_ptr<management::Uninstall::Params> params(
627 management::Uninstall::Params::Create(*args_));
628 EXTENSION_FUNCTION_VALIDATE(extension_);
629 EXTENSION_FUNCTION_VALIDATE(params.get());
631 bool show_confirm_dialog = true;
632 // By default confirmation dialog isn't shown when uninstalling self, but this
633 // can be overridden with showConfirmDialog.
634 if (params->id == extension_->id()) {
635 show_confirm_dialog = params->options.get() &&
636 params->options->show_confirm_dialog.get() &&
637 *params->options->show_confirm_dialog;
639 if (show_confirm_dialog && !user_gesture()) {
640 error_ = keys::kGestureNeededForUninstallError;
643 return Uninstall(params->id, show_confirm_dialog);
646 ManagementUninstallSelfFunction::ManagementUninstallSelfFunction() {
649 ManagementUninstallSelfFunction::~ManagementUninstallSelfFunction() {
652 bool ManagementUninstallSelfFunction::RunAsync() {
653 scoped_ptr<management::UninstallSelf::Params> params(
654 management::UninstallSelf::Params::Create(*args_));
655 EXTENSION_FUNCTION_VALIDATE(params.get());
657 bool show_confirm_dialog = false;
658 if (params->options.get() && params->options->show_confirm_dialog.get())
659 show_confirm_dialog = *params->options->show_confirm_dialog;
660 return Uninstall(extension_->id(), show_confirm_dialog);
663 ManagementCreateAppShortcutFunction::ManagementCreateAppShortcutFunction() {
666 ManagementCreateAppShortcutFunction::~ManagementCreateAppShortcutFunction() {
670 void ManagementCreateAppShortcutFunction::SetAutoConfirmForTest(
671 bool should_proceed) {
672 auto_confirm_for_test = should_proceed ? PROCEED : ABORT;
675 void ManagementCreateAppShortcutFunction::OnCloseShortcutPrompt(bool created) {
677 error_ = keys::kCreateShortcutCanceledError;
678 SendResponse(created);
682 bool ManagementCreateAppShortcutFunction::RunAsync() {
683 if (!user_gesture()) {
684 error_ = keys::kGestureNeededForCreateAppShortcutError;
688 scoped_ptr<management::CreateAppShortcut::Params> params(
689 management::CreateAppShortcut::Params::Create(*args_));
690 EXTENSION_FUNCTION_VALIDATE(params.get());
691 const Extension* extension = service()->GetExtensionById(params->id, true);
693 error_ = ErrorUtils::FormatErrorMessage(keys::kNoExtensionError,
698 if (!extension->is_app()) {
699 error_ = ErrorUtils::FormatErrorMessage(keys::kNotAnAppError, params->id);
703 #if defined(OS_MACOSX)
704 if (!extension->is_platform_app()) {
705 error_ = keys::kCreateOnlyPackagedAppShortcutMac;
710 Browser* browser = chrome::FindBrowserWithProfile(
711 GetProfile(), chrome::HOST_DESKTOP_TYPE_NATIVE);
713 // Shouldn't happen if we have user gesture.
714 error_ = keys::kNoBrowserToCreateShortcut;
718 // Matched with a Release() in OnCloseShortcutPrompt().
721 if (auto_confirm_for_test == DO_NOT_SKIP) {
722 chrome::ShowCreateChromeAppShortcutsDialog(
723 browser->window()->GetNativeWindow(), browser->profile(), extension,
724 base::Bind(&ManagementCreateAppShortcutFunction::OnCloseShortcutPrompt,
727 OnCloseShortcutPrompt(auto_confirm_for_test == PROCEED);
730 // Response is sent async in OnCloseShortcutPrompt().
734 ManagementEventRouter::ManagementEventRouter(Profile* profile)
735 : profile_(profile) {
736 int types[] = {chrome::NOTIFICATION_EXTENSION_INSTALLED,
737 chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
738 chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
739 chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED};
741 CHECK(registrar_.IsEmpty());
742 for (size_t i = 0; i < arraysize(types); i++) {
745 content::Source<Profile>(profile_));
749 ManagementEventRouter::~ManagementEventRouter() {}
751 void ManagementEventRouter::Observe(
753 const content::NotificationSource& source,
754 const content::NotificationDetails& details) {
755 const char* event_name = NULL;
756 const Extension* extension = NULL;
757 Profile* profile = content::Source<Profile>(source).ptr();
759 CHECK(profile_->IsSameProfile(profile));
762 case chrome::NOTIFICATION_EXTENSION_INSTALLED:
763 event_name = management::OnInstalled::kEventName;
765 content::Details<const InstalledExtensionInfo>(details)->extension;
767 case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
768 event_name = management::OnUninstalled::kEventName;
769 extension = content::Details<const Extension>(details).ptr();
771 case chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED:
772 event_name = management::OnEnabled::kEventName;
773 extension = content::Details<const Extension>(details).ptr();
775 case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED:
776 event_name = management::OnDisabled::kEventName;
778 content::Details<const UnloadedExtensionInfo>(details)->extension;
787 if (extension->ShouldNotBeVisible())
788 return; // Don't dispatch events for built-in extensions.
790 scoped_ptr<base::ListValue> args(new base::ListValue());
791 if (event_name == management::OnUninstalled::kEventName) {
792 args->Append(new base::StringValue(extension->id()));
794 scoped_ptr<management::ExtensionInfo> info = CreateExtensionInfo(
795 *extension, ExtensionSystem::Get(profile));
796 args->Append(info->ToValue().release());
799 scoped_ptr<Event> event(new Event(event_name, args.Pass()));
800 EventRouter::Get(profile)->BroadcastEvent(event.Pass());
803 ManagementAPI::ManagementAPI(content::BrowserContext* context)
804 : browser_context_(context) {
805 EventRouter* event_router = EventRouter::Get(browser_context_);
806 event_router->RegisterObserver(this, management::OnInstalled::kEventName);
807 event_router->RegisterObserver(this, management::OnUninstalled::kEventName);
808 event_router->RegisterObserver(this, management::OnEnabled::kEventName);
809 event_router->RegisterObserver(this, management::OnDisabled::kEventName);
812 ManagementAPI::~ManagementAPI() {
815 void ManagementAPI::Shutdown() {
816 EventRouter::Get(browser_context_)->UnregisterObserver(this);
819 static base::LazyInstance<BrowserContextKeyedAPIFactory<ManagementAPI> >
820 g_factory = LAZY_INSTANCE_INITIALIZER;
823 BrowserContextKeyedAPIFactory<ManagementAPI>*
824 ManagementAPI::GetFactoryInstance() {
825 return g_factory.Pointer();
828 void ManagementAPI::OnListenerAdded(const EventListenerInfo& details) {
829 management_event_router_.reset(
830 new ManagementEventRouter(Profile::FromBrowserContext(browser_context_)));
831 EventRouter::Get(browser_context_)->UnregisterObserver(this);
834 } // namespace extensions