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