ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / extensions / browser / api / management / management_api.cc
blobc2fb30d84ef6d8359c8506334589d27400e57a6a
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 PermissionMessages warnings =
65 extension->permissions_data()->GetPermissionMessages();
66 for (PermissionMessages::const_iterator iter = warnings.begin();
67 iter != warnings.end(); ++iter) {
68 warnings_list.push_back(base::UTF16ToUTF8(iter->message()));
71 return warnings_list;
74 std::vector<management::LaunchType> GetAvailableLaunchTypes(
75 const Extension& extension,
76 const ManagementAPIDelegate* delegate) {
77 std::vector<management::LaunchType> launch_type_list;
78 if (extension.is_platform_app()) {
79 launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW);
80 return launch_type_list;
83 launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB);
84 launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW);
86 if (!delegate->IsNewBookmarkAppsEnabled()) {
87 launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB);
88 launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_FULL_SCREEN);
90 return launch_type_list;
93 scoped_ptr<management::ExtensionInfo> CreateExtensionInfo(
94 const Extension& extension,
95 content::BrowserContext* context) {
96 ExtensionSystem* system = ExtensionSystem::Get(context);
97 ExtensionRegistry* registry = ExtensionRegistry::Get(context);
98 const ManagementAPIDelegate* delegate =
99 ManagementAPI::GetFactoryInstance()->Get(context)->GetDelegate();
100 scoped_ptr<management::ExtensionInfo> info(new management::ExtensionInfo());
102 info->id = extension.id();
103 info->name = extension.name();
104 info->short_name = extension.short_name();
105 info->enabled = registry->enabled_extensions().Contains(info->id);
106 info->offline_enabled = OfflineEnabledInfo::IsOfflineEnabled(&extension);
107 info->version = extension.VersionString();
108 info->description = extension.description();
109 info->options_url = OptionsPageInfo::GetOptionsPage(&extension).spec();
110 info->homepage_url.reset(
111 new std::string(ManifestURL::GetHomepageURL(&extension).spec()));
112 info->may_disable =
113 system->management_policy()->UserMayModifySettings(&extension, NULL);
114 info->is_app = extension.is_app();
115 if (info->is_app) {
116 if (extension.is_legacy_packaged_app())
117 info->type = management::ExtensionInfo::TYPE_LEGACY_PACKAGED_APP;
118 else if (extension.is_hosted_app())
119 info->type = management::ExtensionInfo::TYPE_HOSTED_APP;
120 else
121 info->type = management::ExtensionInfo::TYPE_PACKAGED_APP;
122 } else if (extension.is_theme()) {
123 info->type = management::ExtensionInfo::TYPE_THEME;
124 } else {
125 info->type = management::ExtensionInfo::TYPE_EXTENSION;
128 if (info->enabled) {
129 info->disabled_reason = management::ExtensionInfo::DISABLED_REASON_NONE;
130 } else {
131 ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
132 if (prefs->DidExtensionEscalatePermissions(extension.id())) {
133 info->disabled_reason =
134 management::ExtensionInfo::DISABLED_REASON_PERMISSIONS_INCREASE;
135 } else {
136 info->disabled_reason =
137 management::ExtensionInfo::DISABLED_REASON_UNKNOWN;
141 if (!ManifestURL::GetUpdateURL(&extension).is_empty()) {
142 info->update_url.reset(
143 new std::string(ManifestURL::GetUpdateURL(&extension).spec()));
146 if (extension.is_app()) {
147 info->app_launch_url.reset(
148 new std::string(delegate->GetFullLaunchURL(&extension).spec()));
151 const ExtensionIconSet::IconMap& icons =
152 IconsInfo::GetIcons(&extension).map();
153 if (!icons.empty()) {
154 info->icons.reset(new IconInfoList());
155 ExtensionIconSet::IconMap::const_iterator icon_iter;
156 for (icon_iter = icons.begin(); icon_iter != icons.end(); ++icon_iter) {
157 management::IconInfo* icon_info = new management::IconInfo();
158 icon_info->size = icon_iter->first;
159 GURL url =
160 delegate->GetIconURL(&extension, icon_info->size,
161 ExtensionIconSet::MATCH_EXACTLY, false, nullptr);
162 icon_info->url = url.spec();
163 info->icons->push_back(make_linked_ptr<management::IconInfo>(icon_info));
167 const std::set<std::string> perms =
168 extension.permissions_data()->active_permissions()->GetAPIsAsStrings();
169 if (!perms.empty()) {
170 std::set<std::string>::const_iterator perms_iter;
171 for (perms_iter = perms.begin(); perms_iter != perms.end(); ++perms_iter)
172 info->permissions.push_back(*perms_iter);
175 if (!extension.is_hosted_app()) {
176 // Skip host permissions for hosted apps.
177 const URLPatternSet host_perms =
178 extension.permissions_data()->active_permissions()->explicit_hosts();
179 if (!host_perms.is_empty()) {
180 for (URLPatternSet::const_iterator iter = host_perms.begin();
181 iter != host_perms.end(); ++iter) {
182 info->host_permissions.push_back(iter->GetAsString());
187 switch (extension.location()) {
188 case Manifest::INTERNAL:
189 info->install_type = management::ExtensionInfo::INSTALL_TYPE_NORMAL;
190 break;
191 case Manifest::UNPACKED:
192 case Manifest::COMMAND_LINE:
193 info->install_type = management::ExtensionInfo::INSTALL_TYPE_DEVELOPMENT;
194 break;
195 case Manifest::EXTERNAL_PREF:
196 case Manifest::EXTERNAL_REGISTRY:
197 case Manifest::EXTERNAL_PREF_DOWNLOAD:
198 info->install_type = management::ExtensionInfo::INSTALL_TYPE_SIDELOAD;
199 break;
200 case Manifest::EXTERNAL_POLICY:
201 case Manifest::EXTERNAL_POLICY_DOWNLOAD:
202 info->install_type = management::ExtensionInfo::INSTALL_TYPE_ADMIN;
203 break;
204 case Manifest::NUM_LOCATIONS:
205 NOTREACHED();
206 case Manifest::INVALID_LOCATION:
207 case Manifest::COMPONENT:
208 case Manifest::EXTERNAL_COMPONENT:
209 info->install_type = management::ExtensionInfo::INSTALL_TYPE_OTHER;
210 break;
213 info->launch_type = management::LAUNCH_TYPE_NONE;
214 if (extension.is_app()) {
215 LaunchType launch_type;
216 if (extension.is_platform_app()) {
217 launch_type = LAUNCH_TYPE_WINDOW;
218 } else {
219 launch_type =
220 delegate->GetLaunchType(ExtensionPrefs::Get(context), &extension);
223 switch (launch_type) {
224 case LAUNCH_TYPE_PINNED:
225 info->launch_type = management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB;
226 break;
227 case LAUNCH_TYPE_REGULAR:
228 info->launch_type = management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB;
229 break;
230 case LAUNCH_TYPE_FULLSCREEN:
231 info->launch_type = management::LAUNCH_TYPE_OPEN_FULL_SCREEN;
232 break;
233 case LAUNCH_TYPE_WINDOW:
234 info->launch_type = management::LAUNCH_TYPE_OPEN_AS_WINDOW;
235 break;
236 case LAUNCH_TYPE_INVALID:
237 case NUM_LAUNCH_TYPES:
238 NOTREACHED();
241 info->available_launch_types.reset(new std::vector<management::LaunchType>(
242 GetAvailableLaunchTypes(extension, delegate)));
245 return info.Pass();
248 bool ShouldNotBeVisible(const Extension* extension,
249 content::BrowserContext* context) {
250 return (extension->ShouldNotBeVisible() ||
251 ExtensionPrefs::Get(context)->IsEphemeralApp(extension->id()));
254 void AddExtensionInfo(const ExtensionSet& extensions,
255 ExtensionInfoList* extension_list,
256 content::BrowserContext* context) {
257 for (ExtensionSet::const_iterator iter = extensions.begin();
258 iter != extensions.end(); ++iter) {
259 const Extension& extension = *iter->get();
261 if (ShouldNotBeVisible(&extension, context))
262 continue; // Skip built-in extensions/apps.
264 extension_list->push_back(make_linked_ptr<management::ExtensionInfo>(
265 CreateExtensionInfo(extension, context).release()));
269 } // namespace
271 bool ManagementGetAllFunction::RunSync() {
272 ExtensionInfoList extensions;
273 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
275 AddExtensionInfo(registry->enabled_extensions(), &extensions,
276 browser_context());
277 AddExtensionInfo(registry->disabled_extensions(), &extensions,
278 browser_context());
279 AddExtensionInfo(registry->terminated_extensions(), &extensions,
280 browser_context());
282 results_ = management::GetAll::Results::Create(extensions);
283 return true;
286 bool ManagementGetFunction::RunSync() {
287 scoped_ptr<management::Get::Params> params(
288 management::Get::Params::Create(*args_));
289 EXTENSION_FUNCTION_VALIDATE(params.get());
290 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
292 const Extension* extension =
293 registry->GetExtensionById(params->id, ExtensionRegistry::EVERYTHING);
294 if (!extension) {
295 error_ =
296 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id);
297 return false;
300 scoped_ptr<management::ExtensionInfo> info =
301 CreateExtensionInfo(*extension, browser_context());
302 results_ = management::Get::Results::Create(*info);
304 return true;
307 bool ManagementGetSelfFunction::RunSync() {
308 scoped_ptr<management::ExtensionInfo> info =
309 CreateExtensionInfo(*extension_, browser_context());
310 results_ = management::Get::Results::Create(*info);
312 return true;
315 bool ManagementGetPermissionWarningsByIdFunction::RunSync() {
316 scoped_ptr<management::GetPermissionWarningsById::Params> params(
317 management::GetPermissionWarningsById::Params::Create(*args_));
318 EXTENSION_FUNCTION_VALIDATE(params.get());
320 const Extension* extension =
321 ExtensionRegistry::Get(browser_context())
322 ->GetExtensionById(params->id, ExtensionRegistry::EVERYTHING);
323 if (!extension) {
324 error_ =
325 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id);
326 return false;
329 std::vector<std::string> warnings = CreateWarningsList(extension);
330 results_ = management::GetPermissionWarningsById::Results::Create(warnings);
331 return true;
334 bool ManagementGetPermissionWarningsByManifestFunction::RunAsync() {
335 scoped_ptr<management::GetPermissionWarningsByManifest::Params> params(
336 management::GetPermissionWarningsByManifest::Params::Create(*args_));
337 EXTENSION_FUNCTION_VALIDATE(params.get());
339 const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
340 ->Get(browser_context())
341 ->GetDelegate();
343 if (delegate) {
344 delegate->GetPermissionWarningsByManifestFunctionDelegate(
345 this, params->manifest_str);
347 // Matched with a Release() in OnParseSuccess/Failure().
348 AddRef();
350 // Response is sent async in OnParseSuccess/Failure().
351 return true;
352 } else {
353 // TODO(lfg) add error string
354 OnParseFailure("");
355 return false;
359 void ManagementGetPermissionWarningsByManifestFunction::OnParseSuccess(
360 scoped_ptr<base::Value> value) {
361 if (!value->IsType(base::Value::TYPE_DICTIONARY)) {
362 OnParseFailure(keys::kManifestParseError);
363 return;
365 const base::DictionaryValue* parsed_manifest =
366 static_cast<const base::DictionaryValue*>(value.get());
368 scoped_refptr<Extension> extension =
369 Extension::Create(base::FilePath(), Manifest::INVALID_LOCATION,
370 *parsed_manifest, Extension::NO_FLAGS, &error_);
371 if (!extension) {
372 OnParseFailure(keys::kExtensionCreateError);
373 return;
376 std::vector<std::string> warnings = CreateWarningsList(extension.get());
377 results_ =
378 management::GetPermissionWarningsByManifest::Results::Create(warnings);
379 SendResponse(true);
381 // Matched with AddRef() in RunAsync().
382 Release();
385 void ManagementGetPermissionWarningsByManifestFunction::OnParseFailure(
386 const std::string& error) {
387 error_ = error;
388 SendResponse(false);
390 // Matched with AddRef() in RunAsync().
391 Release();
394 bool ManagementLaunchAppFunction::RunSync() {
395 scoped_ptr<management::LaunchApp::Params> params(
396 management::LaunchApp::Params::Create(*args_));
397 EXTENSION_FUNCTION_VALIDATE(params.get());
398 const Extension* extension =
399 ExtensionRegistry::Get(browser_context())
400 ->GetExtensionById(params->id, ExtensionRegistry::EVERYTHING);
401 if (!extension) {
402 error_ =
403 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id);
404 return false;
406 if (!extension->is_app()) {
407 error_ = ErrorUtils::FormatErrorMessage(keys::kNotAnAppError, params->id);
408 return false;
411 const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
412 ->Get(browser_context())
413 ->GetDelegate();
414 return delegate->LaunchAppFunctionDelegate(extension, browser_context());
417 ManagementSetEnabledFunction::ManagementSetEnabledFunction() {
420 ManagementSetEnabledFunction::~ManagementSetEnabledFunction() {
423 ExtensionFunction::ResponseAction ManagementSetEnabledFunction::Run() {
424 scoped_ptr<management::SetEnabled::Params> params(
425 management::SetEnabled::Params::Create(*args_));
426 EXTENSION_FUNCTION_VALIDATE(params.get());
427 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
428 const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
429 ->Get(browser_context())
430 ->GetDelegate();
432 extension_id_ = params->id;
434 const Extension* extension =
435 registry->GetExtensionById(extension_id_, ExtensionRegistry::EVERYTHING);
436 if (!extension || ShouldNotBeVisible(extension, browser_context()))
437 return RespondNow(Error(keys::kNoExtensionError, extension_id_));
439 bool enabled = params->enabled;
440 const ManagementPolicy* policy =
441 ExtensionSystem::Get(browser_context())->management_policy();
442 if (!policy->UserMayModifySettings(extension, nullptr) ||
443 (!enabled && policy->MustRemainEnabled(extension, nullptr)) ||
444 (enabled && policy->MustRemainDisabled(extension, nullptr, nullptr))) {
445 return RespondNow(Error(keys::kUserCantModifyError, extension_id_));
448 bool currently_enabled =
449 registry->enabled_extensions().Contains(extension_id_) ||
450 registry->terminated_extensions().Contains(extension_id_);
452 if (!currently_enabled && enabled) {
453 ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context());
454 if (prefs->DidExtensionEscalatePermissions(extension_id_)) {
455 if (!user_gesture())
456 return RespondNow(Error(keys::kGestureNeededForEscalationError));
458 AddRef(); // Matched in InstallUIProceed/InstallUIAbort
459 install_prompt_ = delegate->SetEnabledFunctionDelegate(this, extension);
460 return RespondLater();
462 if (prefs->GetDisableReasons(extension_id_) &
463 Extension::DISABLE_UNSUPPORTED_REQUIREMENT) {
464 // Recheck the requirements.
465 requirements_checker_ = delegate->CreateRequirementsChecker();
466 requirements_checker_->Check(
467 extension,
468 base::Bind(&ManagementSetEnabledFunction::OnRequirementsChecked,
469 this)); // This bind creates a reference.
470 return RespondLater();
472 delegate->EnableExtension(browser_context(), extension_id_);
473 } else if (currently_enabled && !params->enabled) {
474 delegate->DisableExtension(browser_context(), extension_id_,
475 Extension::DISABLE_USER_ACTION);
478 return RespondNow(NoArguments());
481 void ManagementSetEnabledFunction::InstallUIProceed() {
482 ManagementAPI::GetFactoryInstance()
483 ->Get(browser_context())
484 ->GetDelegate()
485 ->EnableExtension(browser_context(), extension_id_);
486 Respond(OneArgument(new base::FundamentalValue(true)));
487 Release();
490 void ManagementSetEnabledFunction::InstallUIAbort(bool user_initiated) {
491 Respond(Error(keys::kUserDidNotReEnableError));
492 Release();
495 void ManagementSetEnabledFunction::OnRequirementsChecked(
496 const std::vector<std::string>& requirements_errors) {
497 if (requirements_errors.empty()) {
498 ManagementAPI::GetFactoryInstance()->Get(browser_context())->GetDelegate()->
499 EnableExtension(browser_context(), extension_id_);
500 Respond(NoArguments());
501 } else {
502 // TODO(devlin): Should we really be noisy here all the time?
503 Respond(Error(keys::kMissingRequirementsError,
504 JoinString(requirements_errors, ' ')));
508 ManagementUninstallFunctionBase::ManagementUninstallFunctionBase() {
511 ManagementUninstallFunctionBase::~ManagementUninstallFunctionBase() {
514 ExtensionFunction::ResponseAction ManagementUninstallFunctionBase::Uninstall(
515 const std::string& target_extension_id,
516 bool show_confirm_dialog) {
517 const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
518 ->Get(browser_context())
519 ->GetDelegate();
520 target_extension_id_ = target_extension_id;
521 const Extension* target_extension =
522 extensions::ExtensionRegistry::Get(browser_context())
523 ->GetExtensionById(target_extension_id_,
524 ExtensionRegistry::EVERYTHING);
525 if (!target_extension ||
526 ShouldNotBeVisible(target_extension, browser_context())) {
527 return RespondNow(Error(keys::kNoExtensionError, target_extension_id_));
530 ManagementPolicy* policy =
531 ExtensionSystem::Get(browser_context())->management_policy();
532 if (!policy->UserMayModifySettings(target_extension, nullptr) ||
533 policy->MustRemainInstalled(target_extension, nullptr)) {
534 return RespondNow(Error(keys::kUserCantModifyError, target_extension_id_));
537 // Note: null extension() means it's WebUI.
538 bool self_uninstall = extension() && extension_id() == target_extension_id_;
539 // We need to show a dialog for any extension uninstalling another extension.
540 show_confirm_dialog |= !self_uninstall;
542 if (show_confirm_dialog && !user_gesture())
543 return RespondNow(Error(keys::kGestureNeededForUninstallError));
545 if (show_confirm_dialog) {
546 if (auto_confirm_for_test == DO_NOT_SKIP) {
547 // We show the programmatic uninstall ui for extensions uninstalling
548 // other extensions.
549 bool show_programmatic_uninstall_ui = !self_uninstall && extension();
550 AddRef(); // Balanced in ExtensionUninstallAccepted/Canceled
551 // TODO(devlin): A method called "UninstallFunctionDelegate" does not in
552 // any way imply that this actually creates a dialog and runs it.
553 uninstall_dialog_ =
554 delegate->UninstallFunctionDelegate(
555 this,
556 target_extension,
557 show_programmatic_uninstall_ui);
558 } else {
559 // Skip the confirm dialog for testing.
560 base::MessageLoop::current()->PostTask(
561 FROM_HERE,
562 base::Bind(&ManagementUninstallFunctionBase::Finish,
563 this,
564 auto_confirm_for_test == PROCEED));
566 } else { // No confirm dialog.
567 base::MessageLoop::current()->PostTask(
568 FROM_HERE,
569 base::Bind(&ManagementUninstallFunctionBase::Finish, this, true));
572 return RespondLater();
575 // static
576 void ManagementUninstallFunctionBase::SetAutoConfirmForTest(
577 bool should_proceed) {
578 auto_confirm_for_test = should_proceed ? PROCEED : ABORT;
581 void ManagementUninstallFunctionBase::Finish(bool should_uninstall) {
582 if (!should_uninstall) {
583 Respond(Error(keys::kUninstallCanceledError, target_extension_id_));
584 return;
587 // The extension can be uninstalled in another window while the UI was
588 // showing. Do nothing in that case.
589 const Extension* target_extension =
590 extensions::ExtensionRegistry::Get(browser_context())
591 ->GetExtensionById(target_extension_id_,
592 ExtensionRegistry::EVERYTHING);
593 if (!target_extension) {
594 Respond(Error(keys::kNoExtensionError, target_extension_id_));
595 return;
598 const ManagementAPIDelegate* delegate =
599 ManagementAPI::GetFactoryInstance()
600 ->Get(browser_context())
601 ->GetDelegate();
602 base::string16 error;
603 bool success = delegate->UninstallExtension(
604 browser_context(), target_extension_id_,
605 extensions::UNINSTALL_REASON_MANAGEMENT_API,
606 base::Bind(&base::DoNothing), &error);
607 Respond(success ? NoArguments() : Error(base::UTF16ToUTF8(error)));
610 void ManagementUninstallFunctionBase::ExtensionUninstallAccepted() {
611 Finish(true);
612 Release();
615 void ManagementUninstallFunctionBase::ExtensionUninstallCanceled() {
616 Finish(false);
617 Release();
620 ManagementUninstallFunction::ManagementUninstallFunction() {
623 ManagementUninstallFunction::~ManagementUninstallFunction() {
626 ExtensionFunction::ResponseAction ManagementUninstallFunction::Run() {
627 scoped_ptr<management::Uninstall::Params> params(
628 management::Uninstall::Params::Create(*args_));
629 EXTENSION_FUNCTION_VALIDATE(params.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(params->id, show_confirm_dialog);
637 ManagementUninstallSelfFunction::ManagementUninstallSelfFunction() {
640 ManagementUninstallSelfFunction::~ManagementUninstallSelfFunction() {
643 ExtensionFunction::ResponseAction ManagementUninstallSelfFunction::Run() {
644 scoped_ptr<management::UninstallSelf::Params> params(
645 management::UninstallSelf::Params::Create(*args_));
646 EXTENSION_FUNCTION_VALIDATE(params.get());
647 EXTENSION_FUNCTION_VALIDATE(extension_.get());
649 bool show_confirm_dialog = params->options.get() &&
650 params->options->show_confirm_dialog.get() &&
651 *params->options->show_confirm_dialog;
652 return Uninstall(extension_->id(), show_confirm_dialog);
655 ManagementCreateAppShortcutFunction::ManagementCreateAppShortcutFunction() {
658 ManagementCreateAppShortcutFunction::~ManagementCreateAppShortcutFunction() {
661 // static
662 void ManagementCreateAppShortcutFunction::SetAutoConfirmForTest(
663 bool should_proceed) {
664 auto_confirm_for_test = should_proceed ? PROCEED : ABORT;
667 void ManagementCreateAppShortcutFunction::OnCloseShortcutPrompt(bool created) {
668 if (!created)
669 error_ = keys::kCreateShortcutCanceledError;
670 SendResponse(created);
671 Release();
674 bool ManagementCreateAppShortcutFunction::RunAsync() {
675 if (!user_gesture()) {
676 error_ = keys::kGestureNeededForCreateAppShortcutError;
677 return false;
680 scoped_ptr<management::CreateAppShortcut::Params> params(
681 management::CreateAppShortcut::Params::Create(*args_));
682 EXTENSION_FUNCTION_VALIDATE(params.get());
683 const Extension* extension =
684 ExtensionRegistry::Get(browser_context())
685 ->GetExtensionById(params->id, ExtensionRegistry::EVERYTHING);
686 if (!extension) {
687 error_ =
688 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id);
689 return false;
692 if (!extension->is_app()) {
693 error_ = ErrorUtils::FormatErrorMessage(keys::kNotAnAppError, params->id);
694 return false;
697 #if defined(OS_MACOSX)
698 if (!extension->is_platform_app()) {
699 error_ = keys::kCreateOnlyPackagedAppShortcutMac;
700 return false;
702 #endif
704 if (auto_confirm_for_test != DO_NOT_SKIP) {
705 // Matched with a Release() in OnCloseShortcutPrompt().
706 AddRef();
708 OnCloseShortcutPrompt(auto_confirm_for_test == PROCEED);
710 return true;
713 if (ManagementAPI::GetFactoryInstance()
714 ->Get(browser_context())
715 ->GetDelegate()
716 ->CreateAppShortcutFunctionDelegate(this, extension)) {
717 // Matched with a Release() in OnCloseShortcutPrompt().
718 AddRef();
721 // Response is sent async in OnCloseShortcutPrompt().
722 return true;
725 bool ManagementSetLaunchTypeFunction::RunSync() {
726 if (!user_gesture()) {
727 error_ = keys::kGestureNeededForSetLaunchTypeError;
728 return false;
731 scoped_ptr<management::SetLaunchType::Params> params(
732 management::SetLaunchType::Params::Create(*args_));
733 EXTENSION_FUNCTION_VALIDATE(params.get());
734 const Extension* extension =
735 ExtensionRegistry::Get(browser_context())
736 ->GetExtensionById(params->id, ExtensionRegistry::EVERYTHING);
737 const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
738 ->Get(browser_context())
739 ->GetDelegate();
740 if (!extension) {
741 error_ =
742 ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id);
743 return false;
746 if (!extension->is_app()) {
747 error_ = ErrorUtils::FormatErrorMessage(keys::kNotAnAppError, params->id);
748 return false;
751 std::vector<management::LaunchType> available_launch_types =
752 GetAvailableLaunchTypes(*extension, delegate);
754 management::LaunchType app_launch_type = params->launch_type;
755 if (std::find(available_launch_types.begin(), available_launch_types.end(),
756 app_launch_type) == available_launch_types.end()) {
757 error_ = keys::kLaunchTypeNotAvailableError;
758 return false;
761 LaunchType launch_type = LAUNCH_TYPE_DEFAULT;
762 switch (app_launch_type) {
763 case management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB:
764 launch_type = LAUNCH_TYPE_PINNED;
765 break;
766 case management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB:
767 launch_type = LAUNCH_TYPE_REGULAR;
768 break;
769 case management::LAUNCH_TYPE_OPEN_FULL_SCREEN:
770 launch_type = LAUNCH_TYPE_FULLSCREEN;
771 break;
772 case management::LAUNCH_TYPE_OPEN_AS_WINDOW:
773 launch_type = LAUNCH_TYPE_WINDOW;
774 break;
775 case management::LAUNCH_TYPE_NONE:
776 NOTREACHED();
779 delegate->SetLaunchType(browser_context(), params->id, launch_type);
781 return true;
784 ManagementGenerateAppForLinkFunction::ManagementGenerateAppForLinkFunction() {
787 ManagementGenerateAppForLinkFunction::~ManagementGenerateAppForLinkFunction() {
790 void ManagementGenerateAppForLinkFunction::FinishCreateBookmarkApp(
791 const Extension* extension,
792 const WebApplicationInfo& web_app_info) {
793 if (extension) {
794 scoped_ptr<management::ExtensionInfo> info =
795 CreateExtensionInfo(*extension, browser_context());
796 results_ = management::GenerateAppForLink::Results::Create(*info);
798 SendResponse(true);
799 Release();
800 } else {
801 error_ = keys::kGenerateAppForLinkInstallError;
802 SendResponse(false);
803 Release();
807 bool ManagementGenerateAppForLinkFunction::RunAsync() {
808 if (!user_gesture()) {
809 error_ = keys::kGestureNeededForGenerateAppForLinkError;
810 return false;
813 scoped_ptr<management::GenerateAppForLink::Params> params(
814 management::GenerateAppForLink::Params::Create(*args_));
815 EXTENSION_FUNCTION_VALIDATE(params.get());
817 GURL launch_url(params->url);
818 if (!launch_url.is_valid() || !launch_url.SchemeIsHTTPOrHTTPS()) {
819 error_ =
820 ErrorUtils::FormatErrorMessage(keys::kInvalidURLError, params->url);
821 return false;
824 if (params->title.empty()) {
825 error_ = keys::kEmptyTitleError;
826 return false;
829 app_for_link_delegate_ =
830 ManagementAPI::GetFactoryInstance()
831 ->Get(browser_context())
832 ->GetDelegate()
833 ->GenerateAppForLinkFunctionDelegate(this, browser_context(),
834 params->title, launch_url);
836 // Matched with a Release() in FinishCreateBookmarkApp().
837 AddRef();
839 // Response is sent async in FinishCreateBookmarkApp().
840 return true;
843 ManagementEventRouter::ManagementEventRouter(content::BrowserContext* context)
844 : browser_context_(context), extension_registry_observer_(this) {
845 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
848 ManagementEventRouter::~ManagementEventRouter() {
851 void ManagementEventRouter::OnExtensionLoaded(
852 content::BrowserContext* browser_context,
853 const Extension* extension) {
854 BroadcastEvent(extension, management::OnEnabled::kEventName);
857 void ManagementEventRouter::OnExtensionUnloaded(
858 content::BrowserContext* browser_context,
859 const Extension* extension,
860 UnloadedExtensionInfo::Reason reason) {
861 BroadcastEvent(extension, management::OnDisabled::kEventName);
864 void ManagementEventRouter::OnExtensionInstalled(
865 content::BrowserContext* browser_context,
866 const Extension* extension,
867 bool is_update) {
868 BroadcastEvent(extension, management::OnInstalled::kEventName);
871 void ManagementEventRouter::OnExtensionUninstalled(
872 content::BrowserContext* browser_context,
873 const Extension* extension,
874 extensions::UninstallReason reason) {
875 BroadcastEvent(extension, management::OnUninstalled::kEventName);
878 void ManagementEventRouter::BroadcastEvent(const Extension* extension,
879 const char* event_name) {
880 if (ShouldNotBeVisible(extension, browser_context_))
881 return; // Don't dispatch events for built-in extenions.
882 scoped_ptr<base::ListValue> args(new base::ListValue());
883 if (event_name == management::OnUninstalled::kEventName) {
884 args->Append(new base::StringValue(extension->id()));
885 } else {
886 scoped_ptr<management::ExtensionInfo> info =
887 CreateExtensionInfo(*extension, browser_context_);
888 args->Append(info->ToValue().release());
891 EventRouter::Get(browser_context_)
892 ->BroadcastEvent(scoped_ptr<Event>(new Event(event_name, args.Pass())));
895 ManagementAPI::ManagementAPI(content::BrowserContext* context)
896 : browser_context_(context),
897 delegate_(ExtensionsAPIClient::Get()->CreateManagementAPIDelegate()) {
898 EventRouter* event_router = EventRouter::Get(browser_context_);
899 event_router->RegisterObserver(this, management::OnInstalled::kEventName);
900 event_router->RegisterObserver(this, management::OnUninstalled::kEventName);
901 event_router->RegisterObserver(this, management::OnEnabled::kEventName);
902 event_router->RegisterObserver(this, management::OnDisabled::kEventName);
905 ManagementAPI::~ManagementAPI() {
908 void ManagementAPI::Shutdown() {
909 EventRouter::Get(browser_context_)->UnregisterObserver(this);
912 static base::LazyInstance<BrowserContextKeyedAPIFactory<ManagementAPI>>
913 g_factory = LAZY_INSTANCE_INITIALIZER;
915 // static
916 BrowserContextKeyedAPIFactory<ManagementAPI>*
917 ManagementAPI::GetFactoryInstance() {
918 return g_factory.Pointer();
921 void ManagementAPI::OnListenerAdded(const EventListenerInfo& details) {
922 management_event_router_.reset(new ManagementEventRouter(browser_context_));
923 EventRouter::Get(browser_context_)->UnregisterObserver(this);
926 } // namespace extensions