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.
4 
5 #include "extensions/browser/api/management/management_api.h"
6 
7 #include <memory>
8 #include <string>
9 #include <utility>
10 #include <vector>
11 
12 #include "base/bind.h"
13 #include "base/json/json_writer.h"
14 #include "base/lazy_instance.h"
15 #include "base/location.h"
16 #include "base/logging.h"
17 #include "base/metrics/histogram.h"
18 #include "base/single_thread_task_runner.h"
19 #include "base/stl_util.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/threading/thread_task_runner_handle.h"
23 #include "build/build_config.h"
24 #include "build/chromeos_buildflags.h"
25 #include "content/public/browser/browser_context.h"
26 #include "extensions/browser/api/extensions_api_client.h"
27 #include "extensions/browser/api/management/management_api_constants.h"
28 #include "extensions/browser/disable_reason.h"
29 #include "extensions/browser/event_router.h"
30 #include "extensions/browser/extension_prefs.h"
31 #include "extensions/browser/extension_registry.h"
32 #include "extensions/browser/extension_system.h"
33 #include "extensions/browser/management_policy.h"
34 #include "extensions/browser/requirements_checker.h"
35 #include "extensions/browser/uninstall_reason.h"
36 #include "extensions/common/api/management.h"
37 #include "extensions/common/error_utils.h"
38 #include "extensions/common/extension.h"
39 #include "extensions/common/extension_icon_set.h"
40 #include "extensions/common/manifest.h"
41 #include "extensions/common/manifest_handlers/icons_handler.h"
42 #include "extensions/common/manifest_handlers/offline_enabled_info.h"
43 #include "extensions/common/manifest_handlers/options_page_info.h"
44 #include "extensions/common/manifest_handlers/replacement_apps.h"
45 #include "extensions/common/manifest_url_handlers.h"
46 #include "extensions/common/permissions/permission_message.h"
47 #include "extensions/common/permissions/permissions_data.h"
48 #include "extensions/common/url_pattern.h"
49 #include "url/gurl.h"
50 #include "url/url_constants.h"
51 
52 using content::BrowserThread;
53 
54 namespace keys = extension_management_api_constants;
55 
56 namespace extensions {
57 
58 namespace management = api::management;
59 
60 namespace {
61 
62 typedef std::vector<management::ExtensionInfo> ExtensionInfoList;
63 typedef std::vector<management::IconInfo> IconInfoList;
64 
65 enum AutoConfirmForTest { DO_NOT_SKIP = 0, PROCEED, ABORT };
66 
67 AutoConfirmForTest auto_confirm_for_test = DO_NOT_SKIP;
68 
CreateWarningsList(const Extension * extension)69 std::vector<std::string> CreateWarningsList(const Extension* extension) {
70   std::vector<std::string> warnings_list;
71   for (const PermissionMessage& msg :
72        extension->permissions_data()->GetPermissionMessages()) {
73     warnings_list.push_back(base::UTF16ToUTF8(msg.message()));
74   }
75 
76   return warnings_list;
77 }
78 
GetAvailableLaunchTypes(const Extension & extension,const ManagementAPIDelegate * delegate)79 std::vector<management::LaunchType> GetAvailableLaunchTypes(
80     const Extension& extension,
81     const ManagementAPIDelegate* delegate) {
82   std::vector<management::LaunchType> launch_type_list;
83   if (extension.is_platform_app()) {
84     launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW);
85     return launch_type_list;
86   }
87 
88   launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB);
89   launch_type_list.push_back(management::LAUNCH_TYPE_OPEN_AS_WINDOW);
90   return launch_type_list;
91 }
92 
CreateExtensionInfo(const Extension * source_extension,const Extension & extension,content::BrowserContext * context)93 management::ExtensionInfo CreateExtensionInfo(
94     const Extension* source_extension,
95     const Extension& extension,
96     content::BrowserContext* context) {
97   ExtensionSystem* system = ExtensionSystem::Get(context);
98   ExtensionRegistry* registry = ExtensionRegistry::Get(context);
99   const ManagementAPIDelegate* delegate =
100       ManagementAPI::GetFactoryInstance()->Get(context)->GetDelegate();
101   management::ExtensionInfo info;
102 
103   info.id = extension.id();
104   info.name = extension.name();
105   info.short_name = extension.short_name();
106   info.enabled = registry->enabled_extensions().Contains(info.id);
107   info.offline_enabled = OfflineEnabledInfo::IsOfflineEnabled(&extension);
108   info.version = extension.VersionString();
109   if (!extension.version_name().empty())
110     info.version_name.reset(new std::string(extension.version_name()));
111   info.description = extension.description();
112   info.options_url = OptionsPageInfo::GetOptionsPage(&extension).spec();
113   info.homepage_url.reset(
114       new std::string(ManifestURL::GetHomepageURL(&extension).spec()));
115   info.may_disable =
116       !system->management_policy()->MustRemainEnabled(&extension, nullptr);
117   info.is_app = extension.is_app();
118   if (info.is_app) {
119     if (extension.is_legacy_packaged_app())
120       info.type = management::EXTENSION_TYPE_LEGACY_PACKAGED_APP;
121     else if (extension.is_hosted_app())
122       info.type = management::EXTENSION_TYPE_HOSTED_APP;
123     else
124       info.type = management::EXTENSION_TYPE_PACKAGED_APP;
125   } else if (extension.is_theme()) {
126     info.type = management::EXTENSION_TYPE_THEME;
127   } else if (extension.is_login_screen_extension()) {
128     info.type = management::EXTENSION_TYPE_LOGIN_SCREEN_EXTENSION;
129   } else {
130     info.type = management::EXTENSION_TYPE_EXTENSION;
131   }
132 
133   if (info.enabled) {
134     info.disabled_reason = management::EXTENSION_DISABLED_REASON_NONE;
135   } else {
136     ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
137     if (prefs->DidExtensionEscalatePermissions(extension.id())) {
138       info.disabled_reason =
139           management::EXTENSION_DISABLED_REASON_PERMISSIONS_INCREASE;
140     } else {
141       info.disabled_reason = management::EXTENSION_DISABLED_REASON_UNKNOWN;
142     }
143 
144     info.may_enable = std::make_unique<bool>(
145         system->management_policy()->ExtensionMayModifySettings(
146             source_extension, &extension, nullptr) &&
147         !system->management_policy()->MustRemainDisabled(&extension, nullptr,
148                                                          nullptr));
149   }
150 
151   if (!ManifestURL::GetUpdateURL(&extension).is_empty()) {
152     info.update_url.reset(
153         new std::string(ManifestURL::GetUpdateURL(&extension).spec()));
154   }
155 
156   if (extension.is_app()) {
157     info.app_launch_url.reset(
158         new std::string(delegate->GetFullLaunchURL(&extension).spec()));
159   }
160 
161   const ExtensionIconSet::IconMap& icons =
162       IconsInfo::GetIcons(&extension).map();
163   if (!icons.empty()) {
164     info.icons.reset(new IconInfoList());
165     ExtensionIconSet::IconMap::const_iterator icon_iter;
166     for (icon_iter = icons.begin(); icon_iter != icons.end(); ++icon_iter) {
167       management::IconInfo icon_info;
168       icon_info.size = icon_iter->first;
169       GURL url = delegate->GetIconURL(&extension, icon_info.size,
170                                       ExtensionIconSet::MATCH_EXACTLY, false);
171       icon_info.url = url.spec();
172       info.icons->push_back(std::move(icon_info));
173     }
174   }
175 
176   const std::set<std::string> perms =
177       extension.permissions_data()->active_permissions().GetAPIsAsStrings();
178   if (!perms.empty()) {
179     std::set<std::string>::const_iterator perms_iter;
180     for (perms_iter = perms.begin(); perms_iter != perms.end(); ++perms_iter)
181       info.permissions.push_back(*perms_iter);
182   }
183 
184   if (!extension.is_hosted_app()) {
185     // Skip host permissions for hosted apps.
186     const URLPatternSet& host_perms =
187         extension.permissions_data()->active_permissions().explicit_hosts();
188     if (!host_perms.is_empty()) {
189       for (auto iter = host_perms.begin(); iter != host_perms.end(); ++iter) {
190         info.host_permissions.push_back(iter->GetAsString());
191       }
192     }
193   }
194 
195   switch (extension.location()) {
196     case Manifest::INTERNAL:
197       info.install_type = management::EXTENSION_INSTALL_TYPE_NORMAL;
198       break;
199     case Manifest::UNPACKED:
200     case Manifest::COMMAND_LINE:
201       info.install_type = management::EXTENSION_INSTALL_TYPE_DEVELOPMENT;
202       break;
203     case Manifest::EXTERNAL_PREF:
204     case Manifest::EXTERNAL_REGISTRY:
205     case Manifest::EXTERNAL_PREF_DOWNLOAD:
206       info.install_type = management::EXTENSION_INSTALL_TYPE_SIDELOAD;
207       break;
208     case Manifest::EXTERNAL_POLICY:
209     case Manifest::EXTERNAL_POLICY_DOWNLOAD:
210       info.install_type = management::EXTENSION_INSTALL_TYPE_ADMIN;
211       break;
212     case Manifest::NUM_LOCATIONS:
213       NOTREACHED();
214       FALLTHROUGH;
215     case Manifest::INVALID_LOCATION:
216     case Manifest::COMPONENT:
217     case Manifest::EXTERNAL_COMPONENT:
218       info.install_type = management::EXTENSION_INSTALL_TYPE_OTHER;
219       break;
220   }
221 
222   info.launch_type = management::LAUNCH_TYPE_NONE;
223   if (extension.is_app()) {
224     LaunchType launch_type;
225     if (extension.is_platform_app()) {
226       launch_type = LAUNCH_TYPE_WINDOW;
227     } else {
228       launch_type =
229           delegate->GetLaunchType(ExtensionPrefs::Get(context), &extension);
230     }
231 
232     switch (launch_type) {
233       case LAUNCH_TYPE_PINNED:
234         info.launch_type = management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB;
235         break;
236       case LAUNCH_TYPE_REGULAR:
237         info.launch_type = management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB;
238         break;
239       case LAUNCH_TYPE_FULLSCREEN:
240         info.launch_type = management::LAUNCH_TYPE_OPEN_FULL_SCREEN;
241         break;
242       case LAUNCH_TYPE_WINDOW:
243         info.launch_type = management::LAUNCH_TYPE_OPEN_AS_WINDOW;
244         break;
245       case LAUNCH_TYPE_INVALID:
246       case NUM_LAUNCH_TYPES:
247         NOTREACHED();
248     }
249 
250     info.available_launch_types.reset(new std::vector<management::LaunchType>(
251         GetAvailableLaunchTypes(extension, delegate)));
252   }
253 
254   return info;
255 }
256 
AddExtensionInfo(const Extension * source_extension,const ExtensionSet & extensions,ExtensionInfoList * extension_list,content::BrowserContext * context)257 void AddExtensionInfo(const Extension* source_extension,
258                       const ExtensionSet& extensions,
259                       ExtensionInfoList* extension_list,
260                       content::BrowserContext* context) {
261   for (ExtensionSet::const_iterator iter = extensions.begin();
262        iter != extensions.end(); ++iter) {
263     const Extension& extension = **iter;
264 
265     if (!extension.ShouldExposeViaManagementAPI())
266       continue;
267 
268     extension_list->push_back(
269         CreateExtensionInfo(source_extension, extension, context));
270   }
271 }
272 
273 }  // namespace
274 
Run()275 ExtensionFunction::ResponseAction ManagementGetAllFunction::Run() {
276   ExtensionInfoList extensions;
277   ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
278 
279   AddExtensionInfo(extension(), registry->enabled_extensions(), &extensions,
280                    browser_context());
281   AddExtensionInfo(extension(), registry->disabled_extensions(), &extensions,
282                    browser_context());
283   AddExtensionInfo(extension(), registry->terminated_extensions(), &extensions,
284                    browser_context());
285 
286   return RespondNow(
287       ArgumentList(management::GetAll::Results::Create(extensions)));
288 }
289 
Run()290 ExtensionFunction::ResponseAction ManagementGetFunction::Run() {
291   std::unique_ptr<management::Get::Params> params(
292       management::Get::Params::Create(*args_));
293   EXTENSION_FUNCTION_VALIDATE(params.get());
294   ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
295 
296   const Extension* target_extension =
297       registry->GetExtensionById(params->id, ExtensionRegistry::EVERYTHING);
298   if (!target_extension)
299     return RespondNow(Error(keys::kNoExtensionError, params->id));
300 
301   return RespondNow(ArgumentList(management::Get::Results::Create(
302       CreateExtensionInfo(extension(), *target_extension, browser_context()))));
303 }
304 
Run()305 ExtensionFunction::ResponseAction ManagementGetSelfFunction::Run() {
306   return RespondNow(ArgumentList(management::Get::Results::Create(
307       CreateExtensionInfo(extension(), *extension_, browser_context()))));
308 }
309 
310 ExtensionFunction::ResponseAction
Run()311 ManagementGetPermissionWarningsByIdFunction::Run() {
312   std::unique_ptr<management::GetPermissionWarningsById::Params> params(
313       management::GetPermissionWarningsById::Params::Create(*args_));
314   EXTENSION_FUNCTION_VALIDATE(params.get());
315 
316   const Extension* extension =
317       ExtensionRegistry::Get(browser_context())
318           ->GetExtensionById(params->id, ExtensionRegistry::EVERYTHING);
319   if (!extension)
320     return RespondNow(Error(keys::kNoExtensionError, params->id));
321 
322   std::vector<std::string> warnings = CreateWarningsList(extension);
323   return RespondNow(ArgumentList(
324       management::GetPermissionWarningsById::Results::Create(warnings)));
325 }
326 
327 ExtensionFunction::ResponseAction
Run()328 ManagementGetPermissionWarningsByManifestFunction::Run() {
329   std::unique_ptr<management::GetPermissionWarningsByManifest::Params> params(
330       management::GetPermissionWarningsByManifest::Params::Create(*args_));
331   EXTENSION_FUNCTION_VALIDATE(params.get());
332 
333   const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
334                                               ->Get(browser_context())
335                                               ->GetDelegate();
336 
337   if (delegate) {
338     delegate->GetPermissionWarningsByManifestFunctionDelegate(
339         this, params->manifest_str);
340 
341     // Matched with a Release() in OnParse().
342     AddRef();
343 
344     // Response is sent async in OnParse().
345     return RespondLater();
346   } else {
347     // TODO(lfg) add error string
348     return RespondNow(Error(kUnknownErrorDoNotUse));
349   }
350 }
OnParse(data_decoder::DataDecoder::ValueOrError result)351 void ManagementGetPermissionWarningsByManifestFunction::OnParse(
352     data_decoder::DataDecoder::ValueOrError result) {
353   if (!result.value) {
354     Respond(Error(*result.error));
355 
356     // Matched with AddRef() in Run().
357     Release();
358     return;
359   }
360 
361   const base::DictionaryValue* parsed_manifest;
362   if (!result.value->GetAsDictionary(&parsed_manifest)) {
363     Respond(Error(keys::kManifestParseError));
364     Release();
365     return;
366   }
367 
368   std::string error;
369   scoped_refptr<Extension> extension =
370       Extension::Create(base::FilePath(), Manifest::INVALID_LOCATION,
371                         *parsed_manifest, Extension::NO_FLAGS, &error);
372   // TODO(lazyboy): Do we need to use |error|?
373   if (!extension) {
374     Respond(Error(keys::kExtensionCreateError));
375     Release();
376     return;
377   }
378 
379   std::vector<std::string> warnings = CreateWarningsList(extension.get());
380   Respond(ArgumentList(
381       management::GetPermissionWarningsByManifest::Results::Create(warnings)));
382 
383   // Matched with AddRef() in Run().
384   Release();
385 }
386 
Run()387 ExtensionFunction::ResponseAction ManagementLaunchAppFunction::Run() {
388   std::unique_ptr<management::LaunchApp::Params> params(
389       management::LaunchApp::Params::Create(*args_));
390   EXTENSION_FUNCTION_VALIDATE(params.get());
391 
392   if (ExtensionsBrowserClient::Get()->IsRunningInForcedAppMode())
393     return RespondNow(Error(keys::kNotAllowedInKioskError));
394 
395   const Extension* extension =
396       ExtensionRegistry::Get(browser_context())
397           ->GetExtensionById(params->id, ExtensionRegistry::EVERYTHING);
398   if (!extension)
399     return RespondNow(Error(keys::kNoExtensionError, params->id));
400   if (!extension->is_app())
401     return RespondNow(Error(keys::kNotAnAppError, params->id));
402 
403   const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
404                                               ->Get(browser_context())
405                                               ->GetDelegate();
406   delegate->LaunchAppFunctionDelegate(extension, browser_context());
407   return RespondNow(NoArguments());
408 }
409 
410 ManagementSetEnabledFunction::ManagementSetEnabledFunction() = default;
411 
412 ManagementSetEnabledFunction::~ManagementSetEnabledFunction() = default;
413 
Run()414 ExtensionFunction::ResponseAction ManagementSetEnabledFunction::Run() {
415   std::unique_ptr<management::SetEnabled::Params> params(
416       management::SetEnabled::Params::Create(*args_));
417   EXTENSION_FUNCTION_VALIDATE(params.get());
418   extension_id_ = params->id;
419 
420   if (ExtensionsBrowserClient::Get()->IsAppModeForcedForApp(extension_id_))
421     return RespondNow(Error(keys::kCannotChangePrimaryKioskAppError));
422 
423   ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
424   const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
425                                               ->Get(browser_context())
426                                               ->GetDelegate();
427 
428   const Extension* target_extension =
429       registry->GetExtensionById(extension_id_, ExtensionRegistry::EVERYTHING);
430   if (!target_extension || !target_extension->ShouldExposeViaManagementAPI())
431     return RespondNow(Error(keys::kNoExtensionError, extension_id_));
432 
433   bool should_enable = params->enabled;
434 
435   const ManagementPolicy* policy =
436       ExtensionSystem::Get(browser_context())->management_policy();
437   if (!policy->ExtensionMayModifySettings(extension(), target_extension,
438                                           nullptr)) {
439     return RespondNow(Error(keys::kUserCantModifyError, extension_id_));
440   }
441 
442   SupervisedUserExtensionsDelegate* supervised_user_extensions_delegate =
443       ManagementAPI::GetFactoryInstance()
444           ->Get(browser_context())
445           ->GetSupervisedUserExtensionsDelegate();
446   if (supervised_user_extensions_delegate &&
447       supervised_user_extensions_delegate->IsChild(browser_context()) &&
448       // Don't prompt the user if the extension has unsupported requirements.
449       // TODO(crbug/1071978): If OnRequirementsChecked() passes, the extension
450       // will enable, bypassing parent approval.
451       !HasUnsupportedRequirements(extension_id_) &&
452       // Only ask for parent approval if the extension still requires approval.
453       !supervised_user_extensions_delegate->IsExtensionAllowedByParent(
454           *target_extension, browser_context())) {
455     // Either ask for parent permission or notify the child that their parent
456     // has disabled this action.
457     auto parent_permission_callback = base::BindOnce(
458         &ManagementSetEnabledFunction::OnParentPermissionDialogDone, this);
459     auto error_callback = base::BindOnce(
460         &ManagementSetEnabledFunction::OnBlockedByParentDialogDone, this);
461     AddRef();  // Matched in OnParentPermissionDialogDone() or
462                // OnBlockedByParentDialogDone().
463     supervised_user_extensions_delegate->PromptForParentPermissionOrShowError(
464         *target_extension, browser_context(), GetSenderWebContents(),
465         std::move(parent_permission_callback), std::move(error_callback));
466     return RespondLater();
467   }
468 
469   if (should_enable &&
470       policy->MustRemainDisabled(target_extension, nullptr, nullptr)) {
471     return RespondNow(Error(keys::kUserCantModifyError, extension_id_));
472   }
473 
474   bool currently_enabled =
475       registry->enabled_extensions().Contains(extension_id_) ||
476       registry->terminated_extensions().Contains(extension_id_);
477 
478   if (!currently_enabled && should_enable) {
479     ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context());
480     if (prefs->DidExtensionEscalatePermissions(extension_id_)) {
481       if (!user_gesture())
482         return RespondNow(Error(keys::kGestureNeededForEscalationError));
483 
484       AddRef();  // Matched in OnInstallPromptDone().
485       install_prompt_ = delegate->SetEnabledFunctionDelegate(
486           GetSenderWebContents(), browser_context(), target_extension,
487           base::Bind(&ManagementSetEnabledFunction::OnInstallPromptDone, this));
488       return RespondLater();
489     }
490     if (HasUnsupportedRequirements(extension_id_)) {
491       // Recheck the requirements.
492       requirements_checker_ =
493           std::make_unique<RequirementsChecker>(target_extension);
494       requirements_checker_->Start(
495           base::BindOnce(&ManagementSetEnabledFunction::OnRequirementsChecked,
496                          this));  // This bind creates a reference.
497       return RespondLater();
498     }
499     delegate->EnableExtension(browser_context(), extension_id_);
500   } else if (currently_enabled && !params->enabled) {
501     delegate->DisableExtension(
502         browser_context(), extension(), extension_id_,
503         Manifest::IsPolicyLocation(target_extension->location())
504             ? disable_reason::DISABLE_BLOCKED_BY_POLICY
505             : disable_reason::DISABLE_USER_ACTION);
506   }
507 
508   return RespondNow(NoArguments());
509 }
510 
OnInstallPromptDone(bool did_accept)511 void ManagementSetEnabledFunction::OnInstallPromptDone(bool did_accept) {
512   if (did_accept) {
513     ManagementAPI::GetFactoryInstance()
514         ->Get(browser_context())
515         ->GetDelegate()
516         ->EnableExtension(browser_context(), extension_id_);
517     Respond(NoArguments());
518   } else {
519     Respond(Error(keys::kUserDidNotReEnableError));
520   }
521 
522   Release();  // Balanced in Run().
523 }
524 
HasUnsupportedRequirements(const std::string & extension_id)525 bool ManagementSetEnabledFunction::HasUnsupportedRequirements(
526     const std::string& extension_id) {
527   ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context());
528   return prefs->GetDisableReasons(extension_id) &
529          disable_reason::DISABLE_UNSUPPORTED_REQUIREMENT;
530 }
531 
OnRequirementsChecked(const PreloadCheck::Errors & errors)532 void ManagementSetEnabledFunction::OnRequirementsChecked(
533     const PreloadCheck::Errors& errors) {
534   if (errors.empty()) {
535     ManagementAPI::GetFactoryInstance()->Get(browser_context())->GetDelegate()->
536         EnableExtension(browser_context(), extension_id_);
537     Respond(NoArguments());
538   } else {
539     // TODO(devlin): Should we really be noisy here all the time?
540     Respond(Error(keys::kMissingRequirementsError,
541                   base::UTF16ToUTF8(requirements_checker_->GetErrorMessage())));
542   }
543 }
544 
OnParentPermissionDialogDone(SupervisedUserExtensionsDelegate::ParentPermissionDialogResult result)545 void ManagementSetEnabledFunction::OnParentPermissionDialogDone(
546     SupervisedUserExtensionsDelegate::ParentPermissionDialogResult result) {
547 #if BUILDFLAG(IS_CHROMEOS_ASH)
548   switch (result) {
549     case SupervisedUserExtensionsDelegate::ParentPermissionDialogResult::
550         kParentPermissionReceived: {
551       const ManagementAPIDelegate* delegate =
552           ManagementAPI::GetFactoryInstance()
553               ->Get(browser_context())
554               ->GetDelegate();
555       delegate->EnableExtension(browser_context(), extension_id_);
556       Respond(NoArguments());
557       break;
558     }
559 
560     case SupervisedUserExtensionsDelegate::ParentPermissionDialogResult::
561         kParentPermissionCanceled: {
562       Respond(Error(keys::kUserDidNotReEnableError));
563       break;
564     }
565 
566     case SupervisedUserExtensionsDelegate::ParentPermissionDialogResult::
567         kParentPermissionFailed: {
568       Respond(Error(keys::kParentPermissionFailedError));
569       break;
570     }
571   }
572   // Matches the AddRef in Run().
573   Release();
574 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
575 }
576 
OnBlockedByParentDialogDone()577 void ManagementSetEnabledFunction::OnBlockedByParentDialogDone() {
578 #if BUILDFLAG(IS_CHROMEOS_ASH)
579   Respond(Error(keys::kUserCantModifyError, extension_id_));
580   // Matches the AddRef in Run().
581   Release();
582 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
583 }
584 
585 ManagementUninstallFunctionBase::ManagementUninstallFunctionBase() = default;
586 
587 ManagementUninstallFunctionBase::~ManagementUninstallFunctionBase() = default;
588 
Uninstall(const std::string & target_extension_id,bool show_confirm_dialog)589 ExtensionFunction::ResponseAction ManagementUninstallFunctionBase::Uninstall(
590     const std::string& target_extension_id,
591     bool show_confirm_dialog) {
592   if (ExtensionsBrowserClient::Get()->IsRunningInForcedAppMode())
593     return RespondNow(Error(keys::kNotAllowedInKioskError));
594 
595   const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
596                                               ->Get(browser_context())
597                                               ->GetDelegate();
598   target_extension_id_ = target_extension_id;
599   const Extension* target_extension =
600       extensions::ExtensionRegistry::Get(browser_context())
601           ->GetExtensionById(target_extension_id_,
602                              ExtensionRegistry::EVERYTHING);
603   if (!target_extension || !target_extension->ShouldExposeViaManagementAPI()) {
604     return RespondNow(Error(keys::kNoExtensionError, target_extension_id_));
605   }
606 
607   ManagementPolicy* policy =
608       ExtensionSystem::Get(browser_context())->management_policy();
609   if (!policy->UserMayModifySettings(target_extension, nullptr) ||
610       policy->MustRemainInstalled(target_extension, nullptr)) {
611     return RespondNow(Error(keys::kUserCantModifyError, target_extension_id_));
612   }
613 
614   // Note: null extension() means it's WebUI.
615   bool self_uninstall = extension() && extension_id() == target_extension_id_;
616   // We need to show a dialog for any extension uninstalling another extension.
617   show_confirm_dialog |= !self_uninstall;
618 
619   if (show_confirm_dialog && !user_gesture())
620     return RespondNow(Error(keys::kGestureNeededForUninstallError));
621 
622   if (show_confirm_dialog) {
623     // We show the programmatic uninstall ui for extensions uninstalling
624     // other extensions.
625     bool show_programmatic_uninstall_ui =
626         !self_uninstall && extension() &&
627         extension()->id() != extensions::kWebStoreAppId;
628     AddRef();  // Balanced in OnExtensionUninstallDialogClosed.
629     // TODO(devlin): A method called "UninstallFunctionDelegate" does not in
630     // any way imply that this actually creates a dialog and runs it.
631     uninstall_dialog_ = delegate->UninstallFunctionDelegate(
632         this, target_extension, show_programmatic_uninstall_ui);
633   } else {  // No confirm dialog.
634     base::ThreadTaskRunnerHandle::Get()->PostTask(
635         FROM_HERE,
636         base::BindOnce(&ManagementUninstallFunctionBase::UninstallExtension,
637                        this));
638   }
639 
640   return RespondLater();
641 }
642 
Finish(bool did_start_uninstall,const std::string & error)643 void ManagementUninstallFunctionBase::Finish(bool did_start_uninstall,
644                                              const std::string& error) {
645   Respond(did_start_uninstall ? NoArguments() : Error(error));
646 }
647 
OnExtensionUninstallDialogClosed(bool did_start_uninstall,const base::string16 & error)648 void ManagementUninstallFunctionBase::OnExtensionUninstallDialogClosed(
649     bool did_start_uninstall,
650     const base::string16& error) {
651   Finish(did_start_uninstall,
652          ErrorUtils::FormatErrorMessage(keys::kUninstallCanceledError,
653                                         target_extension_id_));
654   Release();  // Balanced in Uninstall().
655 }
656 
UninstallExtension()657 void ManagementUninstallFunctionBase::UninstallExtension() {
658   // The extension can be uninstalled in another window while the UI was
659   // showing. Do nothing in that case.
660   const Extension* target_extension =
661       extensions::ExtensionRegistry::Get(browser_context())
662           ->GetExtensionById(target_extension_id_,
663                              ExtensionRegistry::EVERYTHING);
664   std::string error;
665   bool success = false;
666   if (target_extension) {
667     const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
668                                                 ->Get(browser_context())
669                                                 ->GetDelegate();
670     base::string16 utf16_error;
671     success = delegate->UninstallExtension(
672         browser_context(), target_extension_id_,
673         extensions::UNINSTALL_REASON_MANAGEMENT_API, &utf16_error);
674     error = base::UTF16ToUTF8(utf16_error);
675   } else {
676     error = ErrorUtils::FormatErrorMessage(keys::kNoExtensionError,
677                                            target_extension_id_);
678   }
679   Finish(success, error);
680 }
681 
ManagementUninstallFunction()682 ManagementUninstallFunction::ManagementUninstallFunction() {
683 }
684 
~ManagementUninstallFunction()685 ManagementUninstallFunction::~ManagementUninstallFunction() {
686 }
687 
Run()688 ExtensionFunction::ResponseAction ManagementUninstallFunction::Run() {
689   std::unique_ptr<management::Uninstall::Params> params(
690       management::Uninstall::Params::Create(*args_));
691   EXTENSION_FUNCTION_VALIDATE(params.get());
692 
693   bool show_confirm_dialog = params->options.get() &&
694                              params->options->show_confirm_dialog.get() &&
695                              *params->options->show_confirm_dialog;
696   return Uninstall(params->id, show_confirm_dialog);
697 }
698 
ManagementUninstallSelfFunction()699 ManagementUninstallSelfFunction::ManagementUninstallSelfFunction() {
700 }
701 
~ManagementUninstallSelfFunction()702 ManagementUninstallSelfFunction::~ManagementUninstallSelfFunction() {
703 }
704 
Run()705 ExtensionFunction::ResponseAction ManagementUninstallSelfFunction::Run() {
706   std::unique_ptr<management::UninstallSelf::Params> params(
707       management::UninstallSelf::Params::Create(*args_));
708   EXTENSION_FUNCTION_VALIDATE(params.get());
709   EXTENSION_FUNCTION_VALIDATE(extension_.get());
710 
711   bool show_confirm_dialog = params->options.get() &&
712                              params->options->show_confirm_dialog.get() &&
713                              *params->options->show_confirm_dialog;
714   return Uninstall(extension_->id(), show_confirm_dialog);
715 }
716 
ManagementCreateAppShortcutFunction()717 ManagementCreateAppShortcutFunction::ManagementCreateAppShortcutFunction() {
718 }
719 
~ManagementCreateAppShortcutFunction()720 ManagementCreateAppShortcutFunction::~ManagementCreateAppShortcutFunction() {
721 }
722 
723 // static
SetAutoConfirmForTest(bool should_proceed)724 void ManagementCreateAppShortcutFunction::SetAutoConfirmForTest(
725     bool should_proceed) {
726   auto_confirm_for_test = should_proceed ? PROCEED : ABORT;
727 }
728 
OnCloseShortcutPrompt(bool created)729 void ManagementCreateAppShortcutFunction::OnCloseShortcutPrompt(bool created) {
730   Respond(created ? NoArguments() : Error(keys::kCreateShortcutCanceledError));
731   Release();  // Balanced in Run().
732 }
733 
Run()734 ExtensionFunction::ResponseAction ManagementCreateAppShortcutFunction::Run() {
735   if (ExtensionsBrowserClient::Get()->IsRunningInForcedAppMode())
736     return RespondNow(Error(keys::kNotAllowedInKioskError));
737 
738   if (!user_gesture())
739     return RespondNow(Error(keys::kGestureNeededForCreateAppShortcutError));
740 
741   std::unique_ptr<management::CreateAppShortcut::Params> params(
742       management::CreateAppShortcut::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   if (!extension) {
748     return RespondNow(Error(
749         ErrorUtils::FormatErrorMessage(keys::kNoExtensionError, params->id)));
750   }
751 
752   if (!extension->is_app()) {
753     return RespondNow(Error(
754         ErrorUtils::FormatErrorMessage(keys::kNotAnAppError, params->id)));
755   }
756 
757 #if defined(OS_MAC)
758   if (!extension->is_platform_app())
759     return RespondNow(Error(keys::kCreateOnlyPackagedAppShortcutMac));
760 #endif
761 
762   if (auto_confirm_for_test != DO_NOT_SKIP) {
763     // Matched with a Release() in OnCloseShortcutPrompt().
764     AddRef();
765 
766     OnCloseShortcutPrompt(auto_confirm_for_test == PROCEED);
767     // OnCloseShortcutPrompt() might have called Respond() already.
768     return did_respond() ? AlreadyResponded() : RespondLater();
769   }
770 
771   std::string error;
772   if (ManagementAPI::GetFactoryInstance()
773           ->Get(browser_context())
774           ->GetDelegate()
775           ->CreateAppShortcutFunctionDelegate(this, extension, &error)) {
776     // Matched with a Release() in OnCloseShortcutPrompt().
777     AddRef();
778     // Response is sent async in OnCloseShortcutPrompt().
779     return RespondLater();
780   } else {
781     return RespondNow(Error(std::move(error)));
782   }
783 }
784 
Run()785 ExtensionFunction::ResponseAction ManagementSetLaunchTypeFunction::Run() {
786   if (ExtensionsBrowserClient::Get()->IsRunningInForcedAppMode())
787     return RespondNow(Error(keys::kNotAllowedInKioskError));
788 
789   if (!user_gesture())
790     return RespondNow(Error(keys::kGestureNeededForSetLaunchTypeError));
791 
792   std::unique_ptr<management::SetLaunchType::Params> params(
793       management::SetLaunchType::Params::Create(*args_));
794   EXTENSION_FUNCTION_VALIDATE(params.get());
795   const Extension* extension =
796       ExtensionRegistry::Get(browser_context())
797           ->GetExtensionById(params->id, ExtensionRegistry::EVERYTHING);
798   const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance()
799                                               ->Get(browser_context())
800                                               ->GetDelegate();
801   if (!extension)
802     return RespondNow(Error(keys::kNoExtensionError, params->id));
803 
804   if (!extension->is_app())
805     return RespondNow(Error(keys::kNotAnAppError, params->id));
806 
807   std::vector<management::LaunchType> available_launch_types =
808       GetAvailableLaunchTypes(*extension, delegate);
809 
810   management::LaunchType app_launch_type = params->launch_type;
811   if (!base::Contains(available_launch_types, app_launch_type)) {
812     return RespondNow(Error(keys::kLaunchTypeNotAvailableError));
813   }
814 
815   LaunchType launch_type = LAUNCH_TYPE_DEFAULT;
816   switch (app_launch_type) {
817     case management::LAUNCH_TYPE_OPEN_AS_PINNED_TAB:
818       launch_type = LAUNCH_TYPE_PINNED;
819       break;
820     case management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB:
821       launch_type = LAUNCH_TYPE_REGULAR;
822       break;
823     case management::LAUNCH_TYPE_OPEN_FULL_SCREEN:
824       launch_type = LAUNCH_TYPE_FULLSCREEN;
825       break;
826     case management::LAUNCH_TYPE_OPEN_AS_WINDOW:
827       launch_type = LAUNCH_TYPE_WINDOW;
828       break;
829     case management::LAUNCH_TYPE_NONE:
830       NOTREACHED();
831   }
832 
833   delegate->SetLaunchType(browser_context(), params->id, launch_type);
834 
835   return RespondNow(NoArguments());
836 }
837 
ManagementGenerateAppForLinkFunction()838 ManagementGenerateAppForLinkFunction::ManagementGenerateAppForLinkFunction() {}
839 
~ManagementGenerateAppForLinkFunction()840 ManagementGenerateAppForLinkFunction::~ManagementGenerateAppForLinkFunction() {}
841 
FinishCreateWebApp(const std::string & web_app_id,bool install_success)842 void ManagementGenerateAppForLinkFunction::FinishCreateWebApp(
843     const std::string& web_app_id,
844     bool install_success) {
845   ResponseValue response;
846   if (install_success) {
847     response = ArgumentList(management::GenerateAppForLink::Results::Create(
848         app_for_link_delegate_->CreateExtensionInfoFromWebApp(
849             web_app_id, browser_context())));
850   } else {
851     response = Error(keys::kGenerateAppForLinkInstallError);
852   }
853 
854   Respond(std::move(response));
855   Release();  // Balanced in Run().
856 }
857 
Run()858 ExtensionFunction::ResponseAction ManagementGenerateAppForLinkFunction::Run() {
859   if (ExtensionsBrowserClient::Get()->IsRunningInForcedAppMode())
860     return RespondNow(Error(keys::kNotAllowedInKioskError));
861 
862   if (!user_gesture())
863     return RespondNow(Error(keys::kGestureNeededForGenerateAppForLinkError));
864 
865   std::unique_ptr<management::GenerateAppForLink::Params> params(
866       management::GenerateAppForLink::Params::Create(*args_));
867   EXTENSION_FUNCTION_VALIDATE(params.get());
868 
869   GURL launch_url(params->url);
870   if (!launch_url.is_valid() || !launch_url.SchemeIsHTTPOrHTTPS()) {
871     return RespondNow(Error(
872         ErrorUtils::FormatErrorMessage(keys::kInvalidURLError, params->url)));
873   }
874 
875   if (params->title.empty())
876     return RespondNow(Error(keys::kEmptyTitleError));
877 
878   app_for_link_delegate_ =
879       ManagementAPI::GetFactoryInstance()
880           ->Get(browser_context())
881           ->GetDelegate()
882           ->GenerateAppForLinkFunctionDelegate(this, browser_context(),
883                                                params->title, launch_url);
884 
885   // Matched with a Release() in FinishCreateWebApp().
886   AddRef();
887 
888   // Response is sent async in FinishCreateWebApp().
889   return RespondLater();
890 }
891 
892 ManagementCanInstallReplacementAndroidAppFunction::
ManagementCanInstallReplacementAndroidAppFunction()893     ManagementCanInstallReplacementAndroidAppFunction() {}
894 
895 ManagementCanInstallReplacementAndroidAppFunction::
~ManagementCanInstallReplacementAndroidAppFunction()896     ~ManagementCanInstallReplacementAndroidAppFunction() {}
897 
898 ExtensionFunction::ResponseAction
Run()899 ManagementCanInstallReplacementAndroidAppFunction::Run() {
900   if (ExtensionsBrowserClient::Get()->IsRunningInForcedAppMode())
901     return RespondNow(Error(keys::kNotAllowedInKioskError));
902 
903   if (!extension()->from_webstore()) {
904     return RespondNow(
905         Error(keys::kInstallReplacementAndroidAppNotFromWebstoreError));
906   }
907 
908   auto* api_delegate = ManagementAPI::GetFactoryInstance()
909                            ->Get(browser_context())
910                            ->GetDelegate();
911 
912   DCHECK(api_delegate);
913 
914   if (!api_delegate->CanContextInstallAndroidApps(browser_context())) {
915     return RespondNow(ArgumentList(
916         management::CanInstallReplacementAndroidApp::Results::Create(false)));
917   }
918 
919   DCHECK(ReplacementAppsInfo::HasReplacementAndroidApp(extension()));
920 
921   const std::string& package_name =
922       ReplacementAppsInfo::GetReplacementAndroidApp(extension());
923 
924   api_delegate->CheckAndroidAppInstallStatus(
925       package_name,
926       base::BindOnce(&ManagementCanInstallReplacementAndroidAppFunction::
927                          OnFinishedAndroidAppCheck,
928                      this));
929 
930   // Response is sent async in FinishCheckAndroidApp().
931   return RespondLater();
932 }
933 
934 void ManagementCanInstallReplacementAndroidAppFunction::
OnFinishedAndroidAppCheck(bool installable)935     OnFinishedAndroidAppCheck(bool installable) {
936   Respond(
937       ArgumentList(management::CanInstallReplacementAndroidApp::Results::Create(
938           installable)));
939 }
940 
941 ManagementInstallReplacementAndroidAppFunction::
ManagementInstallReplacementAndroidAppFunction()942     ManagementInstallReplacementAndroidAppFunction() {}
943 
944 ManagementInstallReplacementAndroidAppFunction::
~ManagementInstallReplacementAndroidAppFunction()945     ~ManagementInstallReplacementAndroidAppFunction() {}
946 
947 ExtensionFunction::ResponseAction
Run()948 ManagementInstallReplacementAndroidAppFunction::Run() {
949   if (ExtensionsBrowserClient::Get()->IsRunningInForcedAppMode())
950     return RespondNow(Error(keys::kNotAllowedInKioskError));
951 
952   if (!extension()->from_webstore()) {
953     return RespondNow(
954         Error(keys::kInstallReplacementAndroidAppNotFromWebstoreError));
955   }
956 
957   if (!user_gesture()) {
958     return RespondNow(
959         Error(keys::kGestureNeededForInstallReplacementAndroidAppError));
960   }
961 
962   auto* api_delegate = ManagementAPI::GetFactoryInstance()
963                            ->Get(browser_context())
964                            ->GetDelegate();
965 
966   DCHECK(api_delegate);
967   if (!api_delegate->CanContextInstallAndroidApps(browser_context())) {
968     return RespondNow(
969         Error(keys::kInstallReplacementAndroidAppInvalidContextError));
970   }
971 
972   DCHECK(ReplacementAppsInfo::HasReplacementAndroidApp(extension()));
973 
974   api_delegate->InstallReplacementAndroidApp(
975       ReplacementAppsInfo::GetReplacementAndroidApp(extension()),
976       base::BindOnce(&ManagementInstallReplacementAndroidAppFunction::
977                          OnAppInstallInitiated,
978                      this));
979 
980   // Response is sent async in OnAppInstallInitiated().
981   return RespondLater();
982 }
983 
OnAppInstallInitiated(bool initiated)984 void ManagementInstallReplacementAndroidAppFunction::OnAppInstallInitiated(
985     bool initiated) {
986   if (!initiated)
987     return Respond(Error(keys::kInstallReplacementAndroidAppCannotInstallApp));
988 
989   return Respond(NoArguments());
990 }
991 
992 ManagementInstallReplacementWebAppFunction::
ManagementInstallReplacementWebAppFunction()993     ManagementInstallReplacementWebAppFunction() {}
994 
995 ManagementInstallReplacementWebAppFunction::
~ManagementInstallReplacementWebAppFunction()996     ~ManagementInstallReplacementWebAppFunction() {}
997 
998 ExtensionFunction::ResponseAction
Run()999 ManagementInstallReplacementWebAppFunction::Run() {
1000   if (ExtensionsBrowserClient::Get()->IsRunningInForcedAppMode())
1001     return RespondNow(Error(keys::kNotAllowedInKioskError));
1002 
1003   if (!extension()->from_webstore()) {
1004     return RespondNow(
1005         Error(keys::kInstallReplacementWebAppNotFromWebstoreError));
1006   }
1007 
1008   if (!user_gesture()) {
1009     return RespondNow(
1010         Error(keys::kGestureNeededForInstallReplacementWebAppError));
1011   }
1012 
1013   DCHECK(ReplacementAppsInfo::HasReplacementWebApp(extension()));
1014   const GURL& web_app_url =
1015       ReplacementAppsInfo::GetReplacementWebApp(extension());
1016 
1017   DCHECK(web_app_url.is_valid());
1018   DCHECK(web_app_url.SchemeIs(url::kHttpsScheme));
1019 
1020   auto* api_delegate = ManagementAPI::GetFactoryInstance()
1021                            ->Get(browser_context())
1022                            ->GetDelegate();
1023   if (!api_delegate->CanContextInstallWebApps(browser_context())) {
1024     return RespondNow(
1025         Error(keys::kInstallReplacementWebAppInvalidContextError));
1026   }
1027 
1028   // Adds a ref-count.
1029   api_delegate->InstallOrLaunchReplacementWebApp(
1030       browser_context(), web_app_url,
1031       base::BindOnce(
1032           &ManagementInstallReplacementWebAppFunction::FinishResponse, this));
1033 
1034   // Response is sent async in FinishResponse().
1035   return RespondLater();
1036 }
1037 
FinishResponse(ManagementAPIDelegate::InstallOrLaunchWebAppResult result)1038 void ManagementInstallReplacementWebAppFunction::FinishResponse(
1039     ManagementAPIDelegate::InstallOrLaunchWebAppResult result) {
1040   ResponseValue response;
1041   switch (result) {
1042     case ManagementAPIDelegate::InstallOrLaunchWebAppResult::kSuccess:
1043       response = NoArguments();
1044       break;
1045     case ManagementAPIDelegate::InstallOrLaunchWebAppResult::kInvalidWebApp:
1046       response = Error(keys::kInstallReplacementWebAppInvalidWebAppError);
1047       break;
1048     case ManagementAPIDelegate::InstallOrLaunchWebAppResult::kUnknownError:
1049       response = Error(keys::kGenerateAppForLinkInstallError);
1050   }
1051   Respond(std::move(response));
1052 }
1053 
ManagementEventRouter(content::BrowserContext * context)1054 ManagementEventRouter::ManagementEventRouter(content::BrowserContext* context)
1055     : browser_context_(context) {
1056   extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
1057 }
1058 
~ManagementEventRouter()1059 ManagementEventRouter::~ManagementEventRouter() {}
1060 
OnExtensionLoaded(content::BrowserContext * browser_context,const Extension * extension)1061 void ManagementEventRouter::OnExtensionLoaded(
1062     content::BrowserContext* browser_context,
1063     const Extension* extension) {
1064   BroadcastEvent(extension, events::MANAGEMENT_ON_ENABLED,
1065                  management::OnEnabled::kEventName);
1066 }
1067 
OnExtensionUnloaded(content::BrowserContext * browser_context,const Extension * extension,UnloadedExtensionReason reason)1068 void ManagementEventRouter::OnExtensionUnloaded(
1069     content::BrowserContext* browser_context,
1070     const Extension* extension,
1071     UnloadedExtensionReason reason) {
1072   BroadcastEvent(extension, events::MANAGEMENT_ON_DISABLED,
1073                  management::OnDisabled::kEventName);
1074 }
1075 
OnExtensionInstalled(content::BrowserContext * browser_context,const Extension * extension,bool is_update)1076 void ManagementEventRouter::OnExtensionInstalled(
1077     content::BrowserContext* browser_context,
1078     const Extension* extension,
1079     bool is_update) {
1080   BroadcastEvent(extension, events::MANAGEMENT_ON_INSTALLED,
1081                  management::OnInstalled::kEventName);
1082 }
1083 
OnExtensionUninstalled(content::BrowserContext * browser_context,const Extension * extension,extensions::UninstallReason reason)1084 void ManagementEventRouter::OnExtensionUninstalled(
1085     content::BrowserContext* browser_context,
1086     const Extension* extension,
1087     extensions::UninstallReason reason) {
1088   BroadcastEvent(extension, events::MANAGEMENT_ON_UNINSTALLED,
1089                  management::OnUninstalled::kEventName);
1090 }
1091 
BroadcastEvent(const Extension * extension,events::HistogramValue histogram_value,const char * event_name)1092 void ManagementEventRouter::BroadcastEvent(
1093     const Extension* extension,
1094     events::HistogramValue histogram_value,
1095     const char* event_name) {
1096   if (!extension->ShouldExposeViaManagementAPI())
1097     return;
1098   std::unique_ptr<base::ListValue> args(new base::ListValue());
1099   if (event_name == management::OnUninstalled::kEventName) {
1100     args->AppendString(extension->id());
1101   } else {
1102     args->Append(
1103         CreateExtensionInfo(nullptr, *extension, browser_context_).ToValue());
1104   }
1105 
1106   EventRouter::Get(browser_context_)
1107       ->BroadcastEvent(std::unique_ptr<Event>(
1108           new Event(histogram_value, event_name, std::move(args))));
1109 }
1110 
ManagementAPI(content::BrowserContext * context)1111 ManagementAPI::ManagementAPI(content::BrowserContext* context)
1112     : browser_context_(context),
1113       delegate_(ExtensionsAPIClient::Get()->CreateManagementAPIDelegate()),
1114       supervised_user_extensions_delegate_(
1115           ExtensionsAPIClient::Get()
1116               ->CreateSupervisedUserExtensionsDelegate()) {
1117   EventRouter* event_router = EventRouter::Get(browser_context_);
1118   event_router->RegisterObserver(this, management::OnInstalled::kEventName);
1119   event_router->RegisterObserver(this, management::OnUninstalled::kEventName);
1120   event_router->RegisterObserver(this, management::OnEnabled::kEventName);
1121   event_router->RegisterObserver(this, management::OnDisabled::kEventName);
1122 }
1123 
~ManagementAPI()1124 ManagementAPI::~ManagementAPI() {
1125 }
1126 
Shutdown()1127 void ManagementAPI::Shutdown() {
1128   EventRouter::Get(browser_context_)->UnregisterObserver(this);
1129 }
1130 
1131 static base::LazyInstance<
1132     BrowserContextKeyedAPIFactory<ManagementAPI>>::DestructorAtExit g_factory =
1133     LAZY_INSTANCE_INITIALIZER;
1134 
1135 // static
1136 BrowserContextKeyedAPIFactory<ManagementAPI>*
GetFactoryInstance()1137 ManagementAPI::GetFactoryInstance() {
1138   return g_factory.Pointer();
1139 }
1140 
OnListenerAdded(const EventListenerInfo & details)1141 void ManagementAPI::OnListenerAdded(const EventListenerInfo& details) {
1142   management_event_router_.reset(new ManagementEventRouter(browser_context_));
1143   EventRouter::Get(browser_context_)->UnregisterObserver(this);
1144 }
1145 
1146 }  // namespace extensions
1147