Revert "Fix broken channel icon in chrome://help on CrOS" and try again
[chromium-blink-merge.git] / extensions / browser / api / management / management_api.cc
blob74a95fcf2a621e62ef8c5a885179c9278f7408b3
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);
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()));
114 info->may_disable =
115 system->management_policy()->UserMayModifySettings(&extension, NULL);
116 info->is_app = extension.is_app();
117 if (info->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;
122 else
123 info->type = management::EXTENSION_TYPE_PACKAGED_APP;
124 } else if (extension.is_theme()) {
125 info->type = management::EXTENSION_TYPE_THEME;
126 } else {
127 info->type = management::EXTENSION_TYPE_EXTENSION;
130 if (info->enabled) {
131 info->disabled_reason = management::EXTENSION_DISABLED_REASON_NONE;
132 } else {
133 ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
134 if (prefs->DidExtensionEscalatePermissions(extension.id())) {
135 info->disabled_reason =
136 management::EXTENSION_DISABLED_REASON_PERMISSIONS_INCREASE;
137 } else {
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;
161 GURL url =
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;
192 break;
193 case Manifest::UNPACKED:
194 case Manifest::COMMAND_LINE:
195 info->install_type = management::EXTENSION_INSTALL_TYPE_DEVELOPMENT;
196 break;
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;
201 break;
202 case Manifest::EXTERNAL_POLICY:
203 case Manifest::EXTERNAL_POLICY_DOWNLOAD:
204 info->install_type = management::EXTENSION_INSTALL_TYPE_ADMIN;
205 break;
206 case Manifest::NUM_LOCATIONS:
207 NOTREACHED();
208 case Manifest::INVALID_LOCATION:
209 case Manifest::COMPONENT:
210 case Manifest::EXTERNAL_COMPONENT:
211 info->install_type = management::EXTENSION_INSTALL_TYPE_OTHER;
212 break;
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;
220 } else {
221 launch_type =
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;
228 break;
229 case LAUNCH_TYPE_REGULAR:
230 info->launch_type = management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB;
231 break;
232 case LAUNCH_TYPE_FULLSCREEN:
233 info->launch_type = management::LAUNCH_TYPE_OPEN_FULL_SCREEN;
234 break;
235 case LAUNCH_TYPE_WINDOW:
236 info->launch_type = management::LAUNCH_TYPE_OPEN_AS_WINDOW;
237 break;
238 case LAUNCH_TYPE_INVALID:
239 case NUM_LAUNCH_TYPES:
240 NOTREACHED();
243 info->available_launch_types.reset(new std::vector<management::LaunchType>(
244 GetAvailableLaunchTypes(extension, delegate)));
247 return info.Pass();
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()));
271 } // namespace
273 bool ManagementGetAllFunction::RunSync() {
274 ExtensionInfoList extensions;
275 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
277 AddExtensionInfo(registry->enabled_extensions(), &extensions,
278 browser_context());
279 AddExtensionInfo(registry->disabled_extensions(), &extensions,
280 browser_context());
281 AddExtensionInfo(registry->terminated_extensions(), &extensions,
282 browser_context());
284 results_ = management::GetAll::Results::Create(extensions);
285 return true;
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);
296 if (!extension) {
297 error_ =
298 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id);
299 return false;
302 scoped_ptr<management::ExtensionInfo> info =
303 CreateExtensionInfo(*extension, browser_context());
304 results_ = management::Get::Results::Create(*info);
306 return true;
309 bool ManagementGetSelfFunction::RunSync() {
310 scoped_ptr<management::ExtensionInfo> info =
311 CreateExtensionInfo(*extension_, browser_context());
312 results_ = management::Get::Results::Create(*info);
314 return true;
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);
325 if (!extension) {
326 error_ =
327 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id);
328 return false;
331 std::vector<std::string> warnings = CreateWarningsList(extension);
332 results_ = management::GetPermissionWarningsById::Results::Create(warnings);
333 return true;
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())
343 ->GetDelegate();
345 if (delegate) {
346 delegate->GetPermissionWarningsByManifestFunctionDelegate(
347 this, params->manifest_str);
349 // Matched with a Release() in OnParseSuccess/Failure().
350 AddRef();
352 // Response is sent async in OnParseSuccess/Failure().
353 return true;
354 } else {
355 // TODO(lfg) add error string
356 OnParseFailure("");
357 return false;
361 void ManagementGetPermissionWarningsByManifestFunction::OnParseSuccess(
362 scoped_ptr<base::Value> value) {
363 if (!value->IsType(base::Value::TYPE_DICTIONARY)) {
364 OnParseFailure(keys::kManifestParseError);
365 return;
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_);
373 if (!extension) {
374 OnParseFailure(keys::kExtensionCreateError);
375 return;
378 std::vector<std::string> warnings = CreateWarningsList(extension.get());
379 results_ =
380 management::GetPermissionWarningsByManifest::Results::Create(warnings);
381 SendResponse(true);
383 // Matched with AddRef() in RunAsync().
384 Release();
387 void ManagementGetPermissionWarningsByManifestFunction::OnParseFailure(
388 const std::string& error) {
389 error_ = error;
390 SendResponse(false);
392 // Matched with AddRef() in RunAsync().
393 Release();
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);
403 if (!extension) {
404 error_ =
405 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id);
406 return false;
408 if (!extension->is_app()) {
409 error_ = ErrorUtils::FormatErrorMessage(keys::kNotAnAppError, params->id);
410 return false;
413 const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
414 ->Get(browser_context())
415 ->GetDelegate();
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())
432 ->GetDelegate();
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_)) {
457 if (!user_gesture())
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(
469 extension,
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())
486 ->GetDelegate()
487 ->EnableExtension(browser_context(), extension_id_);
488 Respond(OneArgument(new base::FundamentalValue(true)));
489 Release();
492 void ManagementSetEnabledFunction::InstallUIAbort(bool user_initiated) {
493 Respond(Error(keys::kUserDidNotReEnableError));
494 Release();
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());
503 } else {
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())
521 ->GetDelegate();
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
549 // other extensions.
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(
558 FROM_HERE,
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);
586 std::string error;
587 bool success = false;
588 if (target_extension) {
589 const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
590 ->Get(browser_context())
591 ->GetDelegate();
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);
598 } else {
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() {
646 // static
647 void ManagementCreateAppShortcutFunction::SetAutoConfirmForTest(
648 bool should_proceed) {
649 auto_confirm_for_test = should_proceed ? PROCEED : ABORT;
652 void ManagementCreateAppShortcutFunction::OnCloseShortcutPrompt(bool created) {
653 if (!created)
654 error_ = keys::kCreateShortcutCanceledError;
655 SendResponse(created);
656 Release();
659 bool ManagementCreateAppShortcutFunction::RunAsync() {
660 if (!user_gesture()) {
661 error_ = keys::kGestureNeededForCreateAppShortcutError;
662 return false;
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);
671 if (!extension) {
672 error_ =
673 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id);
674 return false;
677 if (!extension->is_app()) {
678 error_ = ErrorUtils::FormatErrorMessage(keys::kNotAnAppError, params->id);
679 return false;
682 #if defined(OS_MACOSX)
683 if (!extension->is_platform_app()) {
684 error_ = keys::kCreateOnlyPackagedAppShortcutMac;
685 return false;
687 #endif
689 if (auto_confirm_for_test != DO_NOT_SKIP) {
690 // Matched with a Release() in OnCloseShortcutPrompt().
691 AddRef();
693 OnCloseShortcutPrompt(auto_confirm_for_test == PROCEED);
695 return true;
698 if (ManagementAPI::GetFactoryInstance()
699 ->Get(browser_context())
700 ->GetDelegate()
701 ->CreateAppShortcutFunctionDelegate(this, extension)) {
702 // Matched with a Release() in OnCloseShortcutPrompt().
703 AddRef();
706 // Response is sent async in OnCloseShortcutPrompt().
707 return true;
710 bool ManagementSetLaunchTypeFunction::RunSync() {
711 if (!user_gesture()) {
712 error_ = keys::kGestureNeededForSetLaunchTypeError;
713 return false;
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())
724 ->GetDelegate();
725 if (!extension) {
726 error_ =
727 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id);
728 return false;
731 if (!extension->is_app()) {
732 error_ = ErrorUtils::FormatErrorMessage(keys::kNotAnAppError, params->id);
733 return false;
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;
743 return false;
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;
750 break;
751 case management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB:
752 launch_type = LAUNCH_TYPE_REGULAR;
753 break;
754 case management::LAUNCH_TYPE_OPEN_FULL_SCREEN:
755 launch_type = LAUNCH_TYPE_FULLSCREEN;
756 break;
757 case management::LAUNCH_TYPE_OPEN_AS_WINDOW:
758 launch_type = LAUNCH_TYPE_WINDOW;
759 break;
760 case management::LAUNCH_TYPE_NONE:
761 NOTREACHED();
764 delegate->SetLaunchType(browser_context(), params->id, launch_type);
766 return true;
769 ManagementGenerateAppForLinkFunction::ManagementGenerateAppForLinkFunction() {
772 ManagementGenerateAppForLinkFunction::~ManagementGenerateAppForLinkFunction() {
775 void ManagementGenerateAppForLinkFunction::FinishCreateBookmarkApp(
776 const Extension* extension,
777 const WebApplicationInfo& web_app_info) {
778 if (extension) {
779 scoped_ptr<management::ExtensionInfo> info =
780 CreateExtensionInfo(*extension, browser_context());
781 results_ = management::GenerateAppForLink::Results::Create(*info);
783 SendResponse(true);
784 Release();
785 } else {
786 error_ = keys::kGenerateAppForLinkInstallError;
787 SendResponse(false);
788 Release();
792 bool ManagementGenerateAppForLinkFunction::RunAsync() {
793 if (!user_gesture()) {
794 error_ = keys::kGestureNeededForGenerateAppForLinkError;
795 return false;
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()) {
804 error_ =
805 ErrorUtils::FormatErrorMessage(keys::kInvalidURLError, params->url);
806 return false;
809 if (params->title.empty()) {
810 error_ = keys::kEmptyTitleError;
811 return false;
814 app_for_link_delegate_ =
815 ManagementAPI::GetFactoryInstance()
816 ->Get(browser_context())
817 ->GetDelegate()
818 ->GenerateAppForLinkFunctionDelegate(this, browser_context(),
819 params->title, launch_url);
821 // Matched with a Release() in FinishCreateBookmarkApp().
822 AddRef();
824 // Response is sent async in FinishCreateBookmarkApp().
825 return true;
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,
854 bool is_update) {
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()));
876 } else {
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;
907 // static
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