Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / extensions / browser / api / management / management_api.cc
blob7b2e68783812b45a5549d252a972756af113e766
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/permission_set.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 = core_api::management;
53 namespace {
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 extensions::PermissionMessageString& str :
65 extension->permissions_data()->GetPermissionMessageStrings()) {
66 warnings_list.push_back(base::UTF16ToUTF8(str.message));
69 return warnings_list;
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);
82 launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW);
84 if (!delegate->IsNewBookmarkAppsEnabled()) {
85 launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB);
86 launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_FULL_SCREEN);
88 return launch_type_list;
91 scoped_ptr<management::ExtensionInfo> CreateExtensionInfo(
92 const Extension& extension,
93 content::BrowserContext* context) {
94 ExtensionSystem* system = ExtensionSystem::Get(context);
95 ExtensionRegistry* registry = ExtensionRegistry::Get(context);
96 const ManagementAPIDelegate* delegate =
97 ManagementAPI::GetFactoryInstance()->Get(context)->GetDelegate();
98 scoped_ptr<management::ExtensionInfo> info(new management::ExtensionInfo());
100 info->id = extension.id();
101 info->name = extension.name();
102 info->short_name = extension.short_name();
103 info->enabled = registry->enabled_extensions().Contains(info->id);
104 info->offline_enabled = OfflineEnabledInfo::IsOfflineEnabled(&extension);
105 info->version = extension.VersionString();
106 info->description = extension.description();
107 info->options_url = OptionsPageInfo::GetOptionsPage(&extension).spec();
108 info->homepage_url.reset(
109 new std::string(ManifestURL::GetHomepageURL(&extension).spec()));
110 info->may_disable =
111 system->management_policy()->UserMayModifySettings(&extension, NULL);
112 info->is_app = extension.is_app();
113 if (info->is_app) {
114 if (extension.is_legacy_packaged_app())
115 info->type = management::EXTENSION_TYPE_LEGACY_PACKAGED_APP;
116 else if (extension.is_hosted_app())
117 info->type = management::EXTENSION_TYPE_HOSTED_APP;
118 else
119 info->type = management::EXTENSION_TYPE_PACKAGED_APP;
120 } else if (extension.is_theme()) {
121 info->type = management::EXTENSION_TYPE_THEME;
122 } else {
123 info->type = management::EXTENSION_TYPE_EXTENSION;
126 if (info->enabled) {
127 info->disabled_reason = management::EXTENSION_DISABLED_REASON_NONE;
128 } else {
129 ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
130 if (prefs->DidExtensionEscalatePermissions(extension.id())) {
131 info->disabled_reason =
132 management::EXTENSION_DISABLED_REASON_PERMISSIONS_INCREASE;
133 } else {
134 info->disabled_reason =
135 management::EXTENSION_DISABLED_REASON_UNKNOWN;
139 if (!ManifestURL::GetUpdateURL(&extension).is_empty()) {
140 info->update_url.reset(
141 new std::string(ManifestURL::GetUpdateURL(&extension).spec()));
144 if (extension.is_app()) {
145 info->app_launch_url.reset(
146 new std::string(delegate->GetFullLaunchURL(&extension).spec()));
149 const ExtensionIconSet::IconMap& icons =
150 IconsInfo::GetIcons(&extension).map();
151 if (!icons.empty()) {
152 info->icons.reset(new IconInfoList());
153 ExtensionIconSet::IconMap::const_iterator icon_iter;
154 for (icon_iter = icons.begin(); icon_iter != icons.end(); ++icon_iter) {
155 management::IconInfo* icon_info = new management::IconInfo();
156 icon_info->size = icon_iter->first;
157 GURL url =
158 delegate->GetIconURL(&extension, icon_info->size,
159 ExtensionIconSet::MATCH_EXACTLY, false, nullptr);
160 icon_info->url = url.spec();
161 info->icons->push_back(make_linked_ptr<management::IconInfo>(icon_info));
165 const std::set<std::string> perms =
166 extension.permissions_data()->active_permissions()->GetAPIsAsStrings();
167 if (!perms.empty()) {
168 std::set<std::string>::const_iterator perms_iter;
169 for (perms_iter = perms.begin(); perms_iter != perms.end(); ++perms_iter)
170 info->permissions.push_back(*perms_iter);
173 if (!extension.is_hosted_app()) {
174 // Skip host permissions for hosted apps.
175 const URLPatternSet host_perms =
176 extension.permissions_data()->active_permissions()->explicit_hosts();
177 if (!host_perms.is_empty()) {
178 for (URLPatternSet::const_iterator iter = host_perms.begin();
179 iter != host_perms.end(); ++iter) {
180 info->host_permissions.push_back(iter->GetAsString());
185 switch (extension.location()) {
186 case Manifest::INTERNAL:
187 info->install_type = management::EXTENSION_INSTALL_TYPE_NORMAL;
188 break;
189 case Manifest::UNPACKED:
190 case Manifest::COMMAND_LINE:
191 info->install_type = management::EXTENSION_INSTALL_TYPE_DEVELOPMENT;
192 break;
193 case Manifest::EXTERNAL_PREF:
194 case Manifest::EXTERNAL_REGISTRY:
195 case Manifest::EXTERNAL_PREF_DOWNLOAD:
196 info->install_type = management::EXTENSION_INSTALL_TYPE_SIDELOAD;
197 break;
198 case Manifest::EXTERNAL_POLICY:
199 case Manifest::EXTERNAL_POLICY_DOWNLOAD:
200 info->install_type = management::EXTENSION_INSTALL_TYPE_ADMIN;
201 break;
202 case Manifest::NUM_LOCATIONS:
203 NOTREACHED();
204 case Manifest::INVALID_LOCATION:
205 case Manifest::COMPONENT:
206 case Manifest::EXTERNAL_COMPONENT:
207 info->install_type = management::EXTENSION_INSTALL_TYPE_OTHER;
208 break;
211 info->launch_type = management::LAUNCH_TYPE_NONE;
212 if (extension.is_app()) {
213 LaunchType launch_type;
214 if (extension.is_platform_app()) {
215 launch_type = LAUNCH_TYPE_WINDOW;
216 } else {
217 launch_type =
218 delegate->GetLaunchType(ExtensionPrefs::Get(context), &extension);
221 switch (launch_type) {
222 case LAUNCH_TYPE_PINNED:
223 info->launch_type = management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB;
224 break;
225 case LAUNCH_TYPE_REGULAR:
226 info->launch_type = management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB;
227 break;
228 case LAUNCH_TYPE_FULLSCREEN:
229 info->launch_type = management::LAUNCH_TYPE_OPEN_FULL_SCREEN;
230 break;
231 case LAUNCH_TYPE_WINDOW:
232 info->launch_type = management::LAUNCH_TYPE_OPEN_AS_WINDOW;
233 break;
234 case LAUNCH_TYPE_INVALID:
235 case NUM_LAUNCH_TYPES:
236 NOTREACHED();
239 info->available_launch_types.reset(new std::vector<management::LaunchType>(
240 GetAvailableLaunchTypes(extension, delegate)));
243 return info.Pass();
246 bool ShouldNotBeVisible(const Extension* extension,
247 content::BrowserContext* context) {
248 return (extension->ShouldNotBeVisible() ||
249 ExtensionPrefs::Get(context)->IsEphemeralApp(extension->id()));
252 void AddExtensionInfo(const ExtensionSet& extensions,
253 ExtensionInfoList* extension_list,
254 content::BrowserContext* context) {
255 for (ExtensionSet::const_iterator iter = extensions.begin();
256 iter != extensions.end(); ++iter) {
257 const Extension& extension = *iter->get();
259 if (ShouldNotBeVisible(&extension, context))
260 continue; // Skip built-in extensions/apps.
262 extension_list->push_back(make_linked_ptr<management::ExtensionInfo>(
263 CreateExtensionInfo(extension, context).release()));
267 } // namespace
269 bool ManagementGetAllFunction::RunSync() {
270 ExtensionInfoList extensions;
271 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
273 AddExtensionInfo(registry->enabled_extensions(), &extensions,
274 browser_context());
275 AddExtensionInfo(registry->disabled_extensions(), &extensions,
276 browser_context());
277 AddExtensionInfo(registry->terminated_extensions(), &extensions,
278 browser_context());
280 results_ = management::GetAll::Results::Create(extensions);
281 return true;
284 bool ManagementGetFunction::RunSync() {
285 scoped_ptr<management::Get::Params> params(
286 management::Get::Params::Create(*args_));
287 EXTENSION_FUNCTION_VALIDATE(params.get());
288 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
290 const Extension* extension =
291 registry->GetExtensionById(params->id, ExtensionRegistry::EVERYTHING);
292 if (!extension) {
293 error_ =
294 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id);
295 return false;
298 scoped_ptr<management::ExtensionInfo> info =
299 CreateExtensionInfo(*extension, browser_context());
300 results_ = management::Get::Results::Create(*info);
302 return true;
305 bool ManagementGetSelfFunction::RunSync() {
306 scoped_ptr<management::ExtensionInfo> info =
307 CreateExtensionInfo(*extension_, browser_context());
308 results_ = management::Get::Results::Create(*info);
310 return true;
313 bool ManagementGetPermissionWarningsByIdFunction::RunSync() {
314 scoped_ptr<management::GetPermissionWarningsById::Params> params(
315 management::GetPermissionWarningsById::Params::Create(*args_));
316 EXTENSION_FUNCTION_VALIDATE(params.get());
318 const Extension* extension =
319 ExtensionRegistry::Get(browser_context())
320 ->GetExtensionById(params->id, ExtensionRegistry::EVERYTHING);
321 if (!extension) {
322 error_ =
323 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id);
324 return false;
327 std::vector<std::string> warnings = CreateWarningsList(extension);
328 results_ = management::GetPermissionWarningsById::Results::Create(warnings);
329 return true;
332 bool ManagementGetPermissionWarningsByManifestFunction::RunAsync() {
333 scoped_ptr<management::GetPermissionWarningsByManifest::Params> params(
334 management::GetPermissionWarningsByManifest::Params::Create(*args_));
335 EXTENSION_FUNCTION_VALIDATE(params.get());
337 const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
338 ->Get(browser_context())
339 ->GetDelegate();
341 if (delegate) {
342 delegate->GetPermissionWarningsByManifestFunctionDelegate(
343 this, params->manifest_str);
345 // Matched with a Release() in OnParseSuccess/Failure().
346 AddRef();
348 // Response is sent async in OnParseSuccess/Failure().
349 return true;
350 } else {
351 // TODO(lfg) add error string
352 OnParseFailure("");
353 return false;
357 void ManagementGetPermissionWarningsByManifestFunction::OnParseSuccess(
358 scoped_ptr<base::Value> value) {
359 if (!value->IsType(base::Value::TYPE_DICTIONARY)) {
360 OnParseFailure(keys::kManifestParseError);
361 return;
363 const base::DictionaryValue* parsed_manifest =
364 static_cast<const base::DictionaryValue*>(value.get());
366 scoped_refptr<Extension> extension =
367 Extension::Create(base::FilePath(), Manifest::INVALID_LOCATION,
368 *parsed_manifest, Extension::NO_FLAGS, &error_);
369 if (!extension) {
370 OnParseFailure(keys::kExtensionCreateError);
371 return;
374 std::vector<std::string> warnings = CreateWarningsList(extension.get());
375 results_ =
376 management::GetPermissionWarningsByManifest::Results::Create(warnings);
377 SendResponse(true);
379 // Matched with AddRef() in RunAsync().
380 Release();
383 void ManagementGetPermissionWarningsByManifestFunction::OnParseFailure(
384 const std::string& error) {
385 error_ = error;
386 SendResponse(false);
388 // Matched with AddRef() in RunAsync().
389 Release();
392 bool ManagementLaunchAppFunction::RunSync() {
393 scoped_ptr<management::LaunchApp::Params> params(
394 management::LaunchApp::Params::Create(*args_));
395 EXTENSION_FUNCTION_VALIDATE(params.get());
396 const Extension* extension =
397 ExtensionRegistry::Get(browser_context())
398 ->GetExtensionById(params->id, ExtensionRegistry::EVERYTHING);
399 if (!extension) {
400 error_ =
401 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id);
402 return false;
404 if (!extension->is_app()) {
405 error_ = ErrorUtils::FormatErrorMessage(keys::kNotAnAppError, params->id);
406 return false;
409 const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
410 ->Get(browser_context())
411 ->GetDelegate();
412 return delegate->LaunchAppFunctionDelegate(extension, browser_context());
415 ManagementSetEnabledFunction::ManagementSetEnabledFunction() {
418 ManagementSetEnabledFunction::~ManagementSetEnabledFunction() {
421 ExtensionFunction::ResponseAction ManagementSetEnabledFunction::Run() {
422 scoped_ptr<management::SetEnabled::Params> params(
423 management::SetEnabled::Params::Create(*args_));
424 EXTENSION_FUNCTION_VALIDATE(params.get());
425 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
426 const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
427 ->Get(browser_context())
428 ->GetDelegate();
430 extension_id_ = params->id;
432 const Extension* extension =
433 registry->GetExtensionById(extension_id_, ExtensionRegistry::EVERYTHING);
434 if (!extension || ShouldNotBeVisible(extension, browser_context()))
435 return RespondNow(Error(keys::kNoExtensionError, extension_id_));
437 bool enabled = params->enabled;
438 const ManagementPolicy* policy =
439 ExtensionSystem::Get(browser_context())->management_policy();
440 if (!policy->UserMayModifySettings(extension, nullptr) ||
441 (!enabled && policy->MustRemainEnabled(extension, nullptr)) ||
442 (enabled && policy->MustRemainDisabled(extension, nullptr, nullptr))) {
443 return RespondNow(Error(keys::kUserCantModifyError, extension_id_));
446 bool currently_enabled =
447 registry->enabled_extensions().Contains(extension_id_) ||
448 registry->terminated_extensions().Contains(extension_id_);
450 if (!currently_enabled && enabled) {
451 ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context());
452 if (prefs->DidExtensionEscalatePermissions(extension_id_)) {
453 if (!user_gesture())
454 return RespondNow(Error(keys::kGestureNeededForEscalationError));
456 AddRef(); // Matched in InstallUIProceed/InstallUIAbort
457 install_prompt_ = delegate->SetEnabledFunctionDelegate(this, extension);
458 return RespondLater();
460 if (prefs->GetDisableReasons(extension_id_) &
461 Extension::DISABLE_UNSUPPORTED_REQUIREMENT) {
462 // Recheck the requirements.
463 requirements_checker_ = delegate->CreateRequirementsChecker();
464 requirements_checker_->Check(
465 extension,
466 base::Bind(&ManagementSetEnabledFunction::OnRequirementsChecked,
467 this)); // This bind creates a reference.
468 return RespondLater();
470 delegate->EnableExtension(browser_context(), extension_id_);
471 } else if (currently_enabled && !params->enabled) {
472 delegate->DisableExtension(browser_context(), extension_id_,
473 Extension::DISABLE_USER_ACTION);
476 return RespondNow(NoArguments());
479 void ManagementSetEnabledFunction::InstallUIProceed() {
480 ManagementAPI::GetFactoryInstance()
481 ->Get(browser_context())
482 ->GetDelegate()
483 ->EnableExtension(browser_context(), extension_id_);
484 Respond(OneArgument(new base::FundamentalValue(true)));
485 Release();
488 void ManagementSetEnabledFunction::InstallUIAbort(bool user_initiated) {
489 Respond(Error(keys::kUserDidNotReEnableError));
490 Release();
493 void ManagementSetEnabledFunction::OnRequirementsChecked(
494 const std::vector<std::string>& requirements_errors) {
495 if (requirements_errors.empty()) {
496 ManagementAPI::GetFactoryInstance()->Get(browser_context())->GetDelegate()->
497 EnableExtension(browser_context(), extension_id_);
498 Respond(NoArguments());
499 } else {
500 // TODO(devlin): Should we really be noisy here all the time?
501 Respond(Error(keys::kMissingRequirementsError,
502 JoinString(requirements_errors, ' ')));
506 ManagementUninstallFunctionBase::ManagementUninstallFunctionBase() {
509 ManagementUninstallFunctionBase::~ManagementUninstallFunctionBase() {
512 ExtensionFunction::ResponseAction ManagementUninstallFunctionBase::Uninstall(
513 const std::string& target_extension_id,
514 bool show_confirm_dialog) {
515 const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
516 ->Get(browser_context())
517 ->GetDelegate();
518 target_extension_id_ = target_extension_id;
519 const Extension* target_extension =
520 extensions::ExtensionRegistry::Get(browser_context())
521 ->GetExtensionById(target_extension_id_,
522 ExtensionRegistry::EVERYTHING);
523 if (!target_extension ||
524 ShouldNotBeVisible(target_extension, browser_context())) {
525 return RespondNow(Error(keys::kNoExtensionError, target_extension_id_));
528 ManagementPolicy* policy =
529 ExtensionSystem::Get(browser_context())->management_policy();
530 if (!policy->UserMayModifySettings(target_extension, nullptr) ||
531 policy->MustRemainInstalled(target_extension, nullptr)) {
532 return RespondNow(Error(keys::kUserCantModifyError, target_extension_id_));
535 // Note: null extension() means it's WebUI.
536 bool self_uninstall = extension() && extension_id() == target_extension_id_;
537 // We need to show a dialog for any extension uninstalling another extension.
538 show_confirm_dialog |= !self_uninstall;
540 if (show_confirm_dialog && !user_gesture())
541 return RespondNow(Error(keys::kGestureNeededForUninstallError));
543 if (show_confirm_dialog) {
544 switch (auto_confirm_for_test) {
545 case DO_NOT_SKIP: {
546 // We show the programmatic uninstall ui for extensions uninstalling
547 // other extensions.
548 bool show_programmatic_uninstall_ui = !self_uninstall && extension();
549 AddRef(); // Balanced in OnExtensionUninstallDialogClosed.
550 // TODO(devlin): A method called "UninstallFunctionDelegate" does not in
551 // any way imply that this actually creates a dialog and runs it.
552 uninstall_dialog_ =
553 delegate->UninstallFunctionDelegate(
554 this,
555 target_extension,
556 show_programmatic_uninstall_ui);
557 break;
559 case PROCEED: {
560 // Skip the confirm dialog for testing.
561 base::MessageLoop::current()->PostTask(
562 FROM_HERE,
563 base::Bind(&ManagementUninstallFunctionBase::UninstallExtension,
564 this));
565 break;
567 case ABORT: {
568 // Fake the user canceling.
569 base::MessageLoop::current()->PostTask(
570 FROM_HERE,
571 base::Bind(
572 &ManagementUninstallFunctionBase::Finish, this, false,
573 ErrorUtils::FormatErrorMessage(keys::kUninstallCanceledError,
574 target_extension_id_)));
577 } else { // No confirm dialog.
578 base::MessageLoop::current()->PostTask(
579 FROM_HERE,
580 base::Bind(&ManagementUninstallFunctionBase::UninstallExtension, this));
583 return RespondLater();
586 void ManagementUninstallFunctionBase::Finish(bool did_start_uninstall,
587 const std::string& error) {
588 Respond(did_start_uninstall ? NoArguments() : Error(error));
591 void ManagementUninstallFunctionBase::OnExtensionUninstallDialogClosed(
592 bool did_start_uninstall,
593 const base::string16& error) {
594 Finish(did_start_uninstall, base::UTF16ToUTF8(error));
595 Release(); // Balanced in Uninstall().
598 void ManagementUninstallFunctionBase::UninstallExtension() {
599 // The extension can be uninstalled in another window while the UI was
600 // showing. Do nothing in that case.
601 const Extension* target_extension =
602 extensions::ExtensionRegistry::Get(browser_context())
603 ->GetExtensionById(target_extension_id_,
604 ExtensionRegistry::EVERYTHING);
605 std::string error;
606 bool success = false;
607 if (target_extension) {
608 const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
609 ->Get(browser_context())
610 ->GetDelegate();
611 base::string16 utf16_error;
612 success = delegate->UninstallExtension(
613 browser_context(), target_extension_id_,
614 extensions::UNINSTALL_REASON_MANAGEMENT_API,
615 base::Bind(&base::DoNothing), &utf16_error);
616 error = base::UTF16ToUTF8(utf16_error);
617 } else {
618 error = ErrorUtils::FormatErrorMessage(keys::kNoExtensionError,
619 target_extension_id_);
621 Finish(success, error);
624 // static
625 void ManagementUninstallFunctionBase::SetAutoConfirmForTest(
626 bool should_proceed) {
627 auto_confirm_for_test = should_proceed ? PROCEED : ABORT;
630 ManagementUninstallFunction::ManagementUninstallFunction() {
633 ManagementUninstallFunction::~ManagementUninstallFunction() {
636 ExtensionFunction::ResponseAction ManagementUninstallFunction::Run() {
637 scoped_ptr<management::Uninstall::Params> params(
638 management::Uninstall::Params::Create(*args_));
639 EXTENSION_FUNCTION_VALIDATE(params.get());
641 bool show_confirm_dialog = params->options.get() &&
642 params->options->show_confirm_dialog.get() &&
643 *params->options->show_confirm_dialog;
644 return Uninstall(params->id, show_confirm_dialog);
647 ManagementUninstallSelfFunction::ManagementUninstallSelfFunction() {
650 ManagementUninstallSelfFunction::~ManagementUninstallSelfFunction() {
653 ExtensionFunction::ResponseAction ManagementUninstallSelfFunction::Run() {
654 scoped_ptr<management::UninstallSelf::Params> params(
655 management::UninstallSelf::Params::Create(*args_));
656 EXTENSION_FUNCTION_VALIDATE(params.get());
657 EXTENSION_FUNCTION_VALIDATE(extension_.get());
659 bool show_confirm_dialog = params->options.get() &&
660 params->options->show_confirm_dialog.get() &&
661 *params->options->show_confirm_dialog;
662 return Uninstall(extension_->id(), show_confirm_dialog);
665 ManagementCreateAppShortcutFunction::ManagementCreateAppShortcutFunction() {
668 ManagementCreateAppShortcutFunction::~ManagementCreateAppShortcutFunction() {
671 // static
672 void ManagementCreateAppShortcutFunction::SetAutoConfirmForTest(
673 bool should_proceed) {
674 auto_confirm_for_test = should_proceed ? PROCEED : ABORT;
677 void ManagementCreateAppShortcutFunction::OnCloseShortcutPrompt(bool created) {
678 if (!created)
679 error_ = keys::kCreateShortcutCanceledError;
680 SendResponse(created);
681 Release();
684 bool ManagementCreateAppShortcutFunction::RunAsync() {
685 if (!user_gesture()) {
686 error_ = keys::kGestureNeededForCreateAppShortcutError;
687 return false;
690 scoped_ptr<management::CreateAppShortcut::Params> params(
691 management::CreateAppShortcut::Params::Create(*args_));
692 EXTENSION_FUNCTION_VALIDATE(params.get());
693 const Extension* extension =
694 ExtensionRegistry::Get(browser_context())
695 ->GetExtensionById(params->id, ExtensionRegistry::EVERYTHING);
696 if (!extension) {
697 error_ =
698 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id);
699 return false;
702 if (!extension->is_app()) {
703 error_ = ErrorUtils::FormatErrorMessage(keys::kNotAnAppError, params->id);
704 return false;
707 #if defined(OS_MACOSX)
708 if (!extension->is_platform_app()) {
709 error_ = keys::kCreateOnlyPackagedAppShortcutMac;
710 return false;
712 #endif
714 if (auto_confirm_for_test != DO_NOT_SKIP) {
715 // Matched with a Release() in OnCloseShortcutPrompt().
716 AddRef();
718 OnCloseShortcutPrompt(auto_confirm_for_test == PROCEED);
720 return true;
723 if (ManagementAPI::GetFactoryInstance()
724 ->Get(browser_context())
725 ->GetDelegate()
726 ->CreateAppShortcutFunctionDelegate(this, extension)) {
727 // Matched with a Release() in OnCloseShortcutPrompt().
728 AddRef();
731 // Response is sent async in OnCloseShortcutPrompt().
732 return true;
735 bool ManagementSetLaunchTypeFunction::RunSync() {
736 if (!user_gesture()) {
737 error_ = keys::kGestureNeededForSetLaunchTypeError;
738 return false;
741 scoped_ptr<management::SetLaunchType::Params> params(
742 management::SetLaunchType::Params::Create(*args_));
743 EXTENSION_FUNCTION_VALIDATE(params.get());
744 const Extension* extension =
745 ExtensionRegistry::Get(browser_context())
746 ->GetExtensionById(params->id, ExtensionRegistry::EVERYTHING);
747 const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
748 ->Get(browser_context())
749 ->GetDelegate();
750 if (!extension) {
751 error_ =
752 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id);
753 return false;
756 if (!extension->is_app()) {
757 error_ = ErrorUtils::FormatErrorMessage(keys::kNotAnAppError, params->id);
758 return false;
761 std::vector<management::LaunchType> available_launch_types =
762 GetAvailableLaunchTypes(*extension, delegate);
764 management::LaunchType app_launch_type = params->launch_type;
765 if (std::find(available_launch_types.begin(), available_launch_types.end(),
766 app_launch_type) == available_launch_types.end()) {
767 error_ = keys::kLaunchTypeNotAvailableError;
768 return false;
771 LaunchType launch_type = LAUNCH_TYPE_DEFAULT;
772 switch (app_launch_type) {
773 case management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB:
774 launch_type = LAUNCH_TYPE_PINNED;
775 break;
776 case management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB:
777 launch_type = LAUNCH_TYPE_REGULAR;
778 break;
779 case management::LAUNCH_TYPE_OPEN_FULL_SCREEN:
780 launch_type = LAUNCH_TYPE_FULLSCREEN;
781 break;
782 case management::LAUNCH_TYPE_OPEN_AS_WINDOW:
783 launch_type = LAUNCH_TYPE_WINDOW;
784 break;
785 case management::LAUNCH_TYPE_NONE:
786 NOTREACHED();
789 delegate->SetLaunchType(browser_context(), params->id, launch_type);
791 return true;
794 ManagementGenerateAppForLinkFunction::ManagementGenerateAppForLinkFunction() {
797 ManagementGenerateAppForLinkFunction::~ManagementGenerateAppForLinkFunction() {
800 void ManagementGenerateAppForLinkFunction::FinishCreateBookmarkApp(
801 const Extension* extension,
802 const WebApplicationInfo& web_app_info) {
803 if (extension) {
804 scoped_ptr<management::ExtensionInfo> info =
805 CreateExtensionInfo(*extension, browser_context());
806 results_ = management::GenerateAppForLink::Results::Create(*info);
808 SendResponse(true);
809 Release();
810 } else {
811 error_ = keys::kGenerateAppForLinkInstallError;
812 SendResponse(false);
813 Release();
817 bool ManagementGenerateAppForLinkFunction::RunAsync() {
818 if (!user_gesture()) {
819 error_ = keys::kGestureNeededForGenerateAppForLinkError;
820 return false;
823 scoped_ptr<management::GenerateAppForLink::Params> params(
824 management::GenerateAppForLink::Params::Create(*args_));
825 EXTENSION_FUNCTION_VALIDATE(params.get());
827 GURL launch_url(params->url);
828 if (!launch_url.is_valid() || !launch_url.SchemeIsHTTPOrHTTPS()) {
829 error_ =
830 ErrorUtils::FormatErrorMessage(keys::kInvalidURLError, params->url);
831 return false;
834 if (params->title.empty()) {
835 error_ = keys::kEmptyTitleError;
836 return false;
839 app_for_link_delegate_ =
840 ManagementAPI::GetFactoryInstance()
841 ->Get(browser_context())
842 ->GetDelegate()
843 ->GenerateAppForLinkFunctionDelegate(this, browser_context(),
844 params->title, launch_url);
846 // Matched with a Release() in FinishCreateBookmarkApp().
847 AddRef();
849 // Response is sent async in FinishCreateBookmarkApp().
850 return true;
853 ManagementEventRouter::ManagementEventRouter(content::BrowserContext* context)
854 : browser_context_(context), extension_registry_observer_(this) {
855 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
858 ManagementEventRouter::~ManagementEventRouter() {
861 void ManagementEventRouter::OnExtensionLoaded(
862 content::BrowserContext* browser_context,
863 const Extension* extension) {
864 BroadcastEvent(extension, management::OnEnabled::kEventName);
867 void ManagementEventRouter::OnExtensionUnloaded(
868 content::BrowserContext* browser_context,
869 const Extension* extension,
870 UnloadedExtensionInfo::Reason reason) {
871 BroadcastEvent(extension, management::OnDisabled::kEventName);
874 void ManagementEventRouter::OnExtensionInstalled(
875 content::BrowserContext* browser_context,
876 const Extension* extension,
877 bool is_update) {
878 BroadcastEvent(extension, management::OnInstalled::kEventName);
881 void ManagementEventRouter::OnExtensionUninstalled(
882 content::BrowserContext* browser_context,
883 const Extension* extension,
884 extensions::UninstallReason reason) {
885 BroadcastEvent(extension, management::OnUninstalled::kEventName);
888 void ManagementEventRouter::BroadcastEvent(const Extension* extension,
889 const char* event_name) {
890 if (ShouldNotBeVisible(extension, browser_context_))
891 return; // Don't dispatch events for built-in extenions.
892 scoped_ptr<base::ListValue> args(new base::ListValue());
893 if (event_name == management::OnUninstalled::kEventName) {
894 args->Append(new base::StringValue(extension->id()));
895 } else {
896 scoped_ptr<management::ExtensionInfo> info =
897 CreateExtensionInfo(*extension, browser_context_);
898 args->Append(info->ToValue().release());
901 EventRouter::Get(browser_context_)
902 ->BroadcastEvent(scoped_ptr<Event>(new Event(event_name, args.Pass())));
905 ManagementAPI::ManagementAPI(content::BrowserContext* context)
906 : browser_context_(context),
907 delegate_(ExtensionsAPIClient::Get()->CreateManagementAPIDelegate()) {
908 EventRouter* event_router = EventRouter::Get(browser_context_);
909 event_router->RegisterObserver(this, management::OnInstalled::kEventName);
910 event_router->RegisterObserver(this, management::OnUninstalled::kEventName);
911 event_router->RegisterObserver(this, management::OnEnabled::kEventName);
912 event_router->RegisterObserver(this, management::OnDisabled::kEventName);
915 ManagementAPI::~ManagementAPI() {
918 void ManagementAPI::Shutdown() {
919 EventRouter::Get(browser_context_)->UnregisterObserver(this);
922 static base::LazyInstance<BrowserContextKeyedAPIFactory<ManagementAPI>>
923 g_factory = LAZY_INSTANCE_INITIALIZER;
925 // static
926 BrowserContextKeyedAPIFactory<ManagementAPI>*
927 ManagementAPI::GetFactoryInstance() {
928 return g_factory.Pointer();
931 void ManagementAPI::OnListenerAdded(const EventListenerInfo& details) {
932 management_event_router_.reset(new ManagementEventRouter(browser_context_));
933 EventRouter::Get(browser_context_)->UnregisterObserver(this);
936 } // namespace extensions