Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / ui / extensions / extension_enable_flow.cc
blobdb518c7a631d538a69a7914cd802485fa7d37f02
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 "chrome/browser/ui/extensions/extension_enable_flow.h"
7 #include "chrome/browser/chrome_notification_types.h"
8 #include "chrome/browser/extensions/extension_service.h"
9 #include "chrome/browser/extensions/extension_util.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/profiles/profiles_state.h"
12 #include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h"
13 #include "chrome/browser/ui/user_manager.h"
14 #include "content/public/browser/notification_details.h"
15 #include "content/public/browser/notification_source.h"
16 #include "extensions/browser/extension_prefs.h"
17 #include "extensions/browser/extension_registry.h"
18 #include "extensions/browser/extension_system.h"
20 using extensions::Extension;
22 ExtensionEnableFlow::ExtensionEnableFlow(Profile* profile,
23 const std::string& extension_id,
24 ExtensionEnableFlowDelegate* delegate)
25 : profile_(profile),
26 extension_id_(extension_id),
27 delegate_(delegate),
28 parent_contents_(NULL),
29 parent_window_(NULL),
30 extension_registry_observer_(this) {
33 ExtensionEnableFlow::~ExtensionEnableFlow() {
36 void ExtensionEnableFlow::StartForWebContents(
37 content::WebContents* parent_contents) {
38 parent_contents_ = parent_contents;
39 parent_window_ = NULL;
40 Run();
43 void ExtensionEnableFlow::StartForNativeWindow(
44 gfx::NativeWindow parent_window) {
45 parent_contents_ = NULL;
46 parent_window_ = parent_window;
47 Run();
50 void ExtensionEnableFlow::StartForCurrentlyNonexistentWindow(
51 base::Callback<gfx::NativeWindow(void)> window_getter) {
52 window_getter_ = window_getter;
53 Run();
56 void ExtensionEnableFlow::Run() {
57 ExtensionService* service =
58 extensions::ExtensionSystem::Get(profile_)->extension_service();
59 const Extension* extension = service->GetExtensionById(extension_id_, true);
60 if (!extension) {
61 extension = extensions::ExtensionRegistry::Get(profile_)->GetExtensionById(
62 extension_id_, extensions::ExtensionRegistry::TERMINATED);
63 // It's possible (though unlikely) the app could have been uninstalled since
64 // the user clicked on it.
65 if (!extension)
66 return;
67 // If the app was terminated, reload it first.
68 service->ReloadExtension(extension_id_);
70 // ReloadExtension reallocates the Extension object.
71 extension = service->GetExtensionById(extension_id_, true);
73 // |extension| could be NULL for asynchronous load, such as the case of
74 // an unpacked extension. Wait for the load to continue the flow.
75 if (!extension) {
76 StartObserving();
77 return;
81 CheckPermissionAndMaybePromptUser();
84 void ExtensionEnableFlow::CheckPermissionAndMaybePromptUser() {
85 ExtensionService* service =
86 extensions::ExtensionSystem::Get(profile_)->extension_service();
87 const Extension* extension = service->GetExtensionById(extension_id_, true);
88 if (!extension) {
89 delegate_->ExtensionEnableFlowAborted(false); // |delegate_| may delete us.
90 return;
93 // Supervised users can't re-enable custodian-installed extensions.
94 if (extensions::util::IsExtensionSupervised(extension, profile_)) {
95 delegate_->ExtensionEnableFlowAborted(false); // |delegate_| may delete us.
96 return;
99 if (profiles::IsProfileLocked(profile_)) {
100 UserManager::Show(base::FilePath(),
101 profiles::USER_MANAGER_NO_TUTORIAL,
102 profiles::USER_MANAGER_SELECT_PROFILE_APP_LAUNCHER);
103 return;
106 extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_);
107 if (!prefs->DidExtensionEscalatePermissions(extension_id_)) {
108 // Enable the extension immediately if its privileges weren't escalated.
109 // This is a no-op if the extension was previously terminated.
110 service->EnableExtension(extension_id_);
112 delegate_->ExtensionEnableFlowFinished(); // |delegate_| may delete us.
113 return;
116 CreatePrompt();
117 prompt_->ConfirmReEnable(this, extension);
120 void ExtensionEnableFlow::CreatePrompt() {
121 if (!window_getter_.is_null())
122 parent_window_ = window_getter_.Run();
123 prompt_.reset(parent_contents_ ?
124 new ExtensionInstallPrompt(parent_contents_) :
125 new ExtensionInstallPrompt(profile_, parent_window_));
128 void ExtensionEnableFlow::StartObserving() {
129 extension_registry_observer_.Add(
130 extensions::ExtensionRegistry::Get(profile_));
131 registrar_.Add(this,
132 extensions::NOTIFICATION_EXTENSION_LOAD_ERROR,
133 content::Source<Profile>(profile_));
136 void ExtensionEnableFlow::StopObserving() {
137 registrar_.RemoveAll();
138 extension_registry_observer_.RemoveAll();
141 void ExtensionEnableFlow::Observe(int type,
142 const content::NotificationSource& source,
143 const content::NotificationDetails& details) {
144 DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_LOAD_ERROR, type);
145 StopObserving();
146 delegate_->ExtensionEnableFlowAborted(false);
149 void ExtensionEnableFlow::OnExtensionLoaded(
150 content::BrowserContext* browser_context,
151 const Extension* extension) {
152 if (extension->id() == extension_id_) {
153 StopObserving();
154 CheckPermissionAndMaybePromptUser();
158 void ExtensionEnableFlow::OnExtensionUninstalled(
159 content::BrowserContext* browser_context,
160 const Extension* extension,
161 extensions::UninstallReason reason) {
162 if (extension->id() == extension_id_) {
163 StopObserving();
164 delegate_->ExtensionEnableFlowAborted(false);
168 void ExtensionEnableFlow::InstallUIProceed() {
169 ExtensionService* service =
170 extensions::ExtensionSystem::Get(profile_)->extension_service();
172 // The extension can be uninstalled in another window while the UI was
173 // showing. Treat it as a cancellation and notify |delegate_|.
174 const Extension* extension = service->GetExtensionById(extension_id_, true);
175 if (!extension) {
176 delegate_->ExtensionEnableFlowAborted(true);
177 return;
180 service->GrantPermissionsAndEnableExtension(extension);
181 delegate_->ExtensionEnableFlowFinished(); // |delegate_| may delete us.
184 void ExtensionEnableFlow::InstallUIAbort(bool user_initiated) {
185 delegate_->ExtensionEnableFlowAborted(user_initiated);
186 // |delegate_| may delete us.