OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/apps/ephemeral_app_launcher.h" | 5 #include "chrome/browser/apps/ephemeral_app_launcher.h" |
6 | 6 |
7 #include "chrome/browser/extensions/extension_install_prompt.h" | 7 #include "chrome/browser/extensions/extension_install_prompt.h" |
8 #include "chrome/browser/extensions/extension_service.h" | |
9 #include "chrome/browser/extensions/extension_util.h" | 8 #include "chrome/browser/extensions/extension_util.h" |
10 #include "chrome/browser/profiles/profile.h" | 9 #include "chrome/browser/profiles/profile.h" |
11 #include "chrome/browser/ui/extensions/application_launch.h" | 10 #include "chrome/browser/ui/extensions/application_launch.h" |
12 #include "chrome/browser/ui/extensions/extension_enable_flow.h" | 11 #include "chrome/browser/ui/extensions/extension_enable_flow.h" |
13 #include "content/public/browser/web_contents.h" | 12 #include "content/public/browser/web_contents.h" |
14 #include "extensions/browser/extension_registry.h" | 13 #include "extensions/browser/extension_registry.h" |
15 #include "extensions/browser/extension_system.h" | |
16 #include "extensions/common/permissions/permissions_data.h" | 14 #include "extensions/common/permissions/permissions_data.h" |
17 | 15 |
18 using content::WebContents; | 16 using content::WebContents; |
19 using extensions::Extension; | 17 using extensions::Extension; |
20 using extensions::ExtensionSystem; | 18 using extensions::ExtensionRegistry; |
21 using extensions::WebstoreInstaller; | 19 using extensions::WebstoreInstaller; |
22 | 20 |
23 namespace { | 21 namespace { |
24 | 22 |
25 const char kInvalidManifestError[] = "Invalid manifest"; | 23 const char kInvalidManifestError[] = "Invalid manifest"; |
26 const char kExtensionTypeError[] = "Ephemeral extensions are not permitted"; | 24 const char kExtensionTypeError[] = "Ephemeral extensions are not permitted"; |
27 const char kLaunchAbortedError[] = "Launch aborted"; | 25 const char kLaunchAbortedError[] = "Launch aborted"; |
28 | 26 |
29 Profile* ProfileForWebContents(content::WebContents* contents) { | 27 Profile* ProfileForWebContents(content::WebContents* contents) { |
30 if (!contents) | 28 if (!contents) |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 content::WebContents* web_contents) { | 63 content::WebContents* web_contents) { |
66 scoped_refptr<EphemeralAppLauncher> installer = | 64 scoped_refptr<EphemeralAppLauncher> installer = |
67 new EphemeralAppLauncher(webstore_item_id, | 65 new EphemeralAppLauncher(webstore_item_id, |
68 web_contents, | 66 web_contents, |
69 Callback()); | 67 Callback()); |
70 installer->set_install_source(WebstoreInstaller::INSTALL_SOURCE_OTHER); | 68 installer->set_install_source(WebstoreInstaller::INSTALL_SOURCE_OTHER); |
71 return installer; | 69 return installer; |
72 } | 70 } |
73 | 71 |
74 void EphemeralAppLauncher::Start() { | 72 void EphemeralAppLauncher::Start() { |
75 ExtensionService* extension_service = | 73 const Extension* extension = |
76 extensions::ExtensionSystem::Get(profile())->extension_service(); | 74 ExtensionRegistry::Get(profile()) |
77 DCHECK(extension_service); | 75 ->GetExtensionById(id(), ExtensionRegistry::EVERYTHING); |
78 | |
79 const Extension* extension = extension_service->GetInstalledExtension(id()); | |
80 if (extension) { | 76 if (extension) { |
81 if (extensions::util::IsAppLaunchableWithoutEnabling(extension->id(), | 77 if (extensions::util::IsAppLaunchableWithoutEnabling(extension->id(), |
82 profile())) { | 78 profile())) { |
83 LaunchApp(extension); | 79 LaunchApp(extension); |
84 InvokeCallback(std::string()); | 80 InvokeCallback(std::string()); |
85 return; | 81 return; |
86 } | 82 } |
87 | 83 |
88 // The ephemeral app may have been updated and disabled as it requests | 84 // The ephemeral app may have been updated and disabled as it requests |
89 // more permissions. In this case we should always prompt before | 85 // more permissions. In this case we should always prompt before |
90 // launching. | 86 // launching. |
91 extension_enable_flow_.reset( | 87 extension_enable_flow_.reset( |
92 new ExtensionEnableFlow(profile(), extension->id(), this)); | 88 new ExtensionEnableFlow(profile(), extension->id(), this)); |
93 if (web_contents()) | 89 if (web_contents()) |
94 extension_enable_flow_->StartForWebContents(web_contents()); | 90 extension_enable_flow_->StartForWebContents(web_contents()); |
95 else | 91 else |
96 extension_enable_flow_->StartForNativeWindow(parent_window_); | 92 extension_enable_flow_->StartForNativeWindow(parent_window_); |
97 | 93 |
98 // Keep this object alive until the enable flow is complete. | 94 // Keep this object alive until the enable flow is complete. |
99 AddRef(); // Balanced in WebstoreStandaloneInstaller::CompleteInstall. | 95 AddRef(); // Balanced in WebstoreStandaloneInstaller::CompleteInstall. |
100 return; | 96 return; |
101 } | 97 } |
102 | 98 |
103 // Fetch the app from the webstore. | 99 // Fetch the app from the webstore. |
104 StartObserving(); | |
105 BeginInstall(); | 100 BeginInstall(); |
106 } | 101 } |
107 | 102 |
108 EphemeralAppLauncher::EphemeralAppLauncher(const std::string& webstore_item_id, | 103 EphemeralAppLauncher::EphemeralAppLauncher(const std::string& webstore_item_id, |
109 Profile* profile, | 104 Profile* profile, |
110 gfx::NativeWindow parent_window, | 105 gfx::NativeWindow parent_window, |
111 const Callback& callback) | 106 const Callback& callback) |
112 : WebstoreStandaloneInstaller(webstore_item_id, profile, callback), | 107 : WebstoreStandaloneInstaller(webstore_item_id, profile, callback), |
113 extension_registry_observer_(this), | |
114 parent_window_(parent_window), | 108 parent_window_(parent_window), |
115 dummy_web_contents_( | 109 dummy_web_contents_( |
116 WebContents::Create(WebContents::CreateParams(profile))) { | 110 WebContents::Create(WebContents::CreateParams(profile))) { |
117 } | 111 } |
118 | 112 |
119 EphemeralAppLauncher::EphemeralAppLauncher(const std::string& webstore_item_id, | 113 EphemeralAppLauncher::EphemeralAppLauncher(const std::string& webstore_item_id, |
120 content::WebContents* web_contents, | 114 content::WebContents* web_contents, |
121 const Callback& callback) | 115 const Callback& callback) |
122 : WebstoreStandaloneInstaller(webstore_item_id, | 116 : WebstoreStandaloneInstaller(webstore_item_id, |
123 ProfileForWebContents(web_contents), | 117 ProfileForWebContents(web_contents), |
124 callback), | 118 callback), |
125 content::WebContentsObserver(web_contents), | 119 content::WebContentsObserver(web_contents), |
126 extension_registry_observer_(this), | |
127 parent_window_(NativeWindowForWebContents(web_contents)) { | 120 parent_window_(NativeWindowForWebContents(web_contents)) { |
128 } | 121 } |
129 | 122 |
130 EphemeralAppLauncher::~EphemeralAppLauncher() {} | 123 EphemeralAppLauncher::~EphemeralAppLauncher() {} |
131 | 124 |
132 void EphemeralAppLauncher::StartObserving() { | |
133 extension_registry_observer_.Add( | |
134 extensions::ExtensionRegistry::Get(profile())); | |
135 } | |
136 | |
137 void EphemeralAppLauncher::LaunchApp(const Extension* extension) const { | 125 void EphemeralAppLauncher::LaunchApp(const Extension* extension) const { |
138 DCHECK(extension); | 126 DCHECK(extension); |
139 if (!extension->is_app()) { | 127 if (!extension->is_app()) { |
140 LOG(ERROR) << "Unable to launch extension " << extension->id() | 128 LOG(ERROR) << "Unable to launch extension " << extension->id() |
141 << ". It is not an app."; | 129 << ". It is not an app."; |
142 return; | 130 return; |
143 } | 131 } |
144 | 132 |
145 AppLaunchParams params(profile(), extension, NEW_FOREGROUND_TAB); | 133 AppLaunchParams params(profile(), extension, NEW_FOREGROUND_TAB); |
146 params.desktop_type = | 134 params.desktop_type = |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 | 219 |
232 scoped_ptr<WebstoreInstaller::Approval> | 220 scoped_ptr<WebstoreInstaller::Approval> |
233 EphemeralAppLauncher::CreateApproval() const { | 221 EphemeralAppLauncher::CreateApproval() const { |
234 scoped_ptr<WebstoreInstaller::Approval> approval = | 222 scoped_ptr<WebstoreInstaller::Approval> approval = |
235 WebstoreStandaloneInstaller::CreateApproval(); | 223 WebstoreStandaloneInstaller::CreateApproval(); |
236 approval->is_ephemeral = true; | 224 approval->is_ephemeral = true; |
237 return approval.Pass(); | 225 return approval.Pass(); |
238 } | 226 } |
239 | 227 |
240 void EphemeralAppLauncher::CompleteInstall(const std::string& error) { | 228 void EphemeralAppLauncher::CompleteInstall(const std::string& error) { |
241 if (!error.empty()) | 229 if (error.empty()) { |
242 WebstoreStandaloneInstaller::CompleteInstall(error); | 230 const Extension* extension = |
| 231 ExtensionRegistry::Get(profile()) |
| 232 ->GetExtensionById(id(), ExtensionRegistry::ENABLED); |
| 233 if (extension) |
| 234 LaunchApp(extension); |
| 235 } |
243 | 236 |
244 // If the installation succeeds, we reach this point as a result of | 237 WebstoreStandaloneInstaller::CompleteInstall(error); |
245 // chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED, but this is | |
246 // broadcasted before | |
247 // ExtensionService has added the extension to its list of installed | |
248 // extensions and is too early to launch the app. Instead, we will launch at | |
249 // EphemeralAppLauncher::OnExtensionLoaded(). | |
250 // TODO(tmdiep): Refactor extensions/WebstoreInstaller or | |
251 // WebstoreStandaloneInstaller to support this cleanly. | |
252 } | 238 } |
253 | 239 |
254 void EphemeralAppLauncher::WebContentsDestroyed() { | 240 void EphemeralAppLauncher::WebContentsDestroyed() { |
255 AbortInstall(); | 241 AbortInstall(); |
256 } | 242 } |
257 | 243 |
258 void EphemeralAppLauncher::OnExtensionLoaded( | |
259 content::BrowserContext* browser_context, | |
260 const Extension* extension) { | |
261 if (extension->id() == id()) { | |
262 LaunchApp(extension); | |
263 WebstoreStandaloneInstaller::CompleteInstall(std::string()); | |
264 } | |
265 } | |
266 | |
267 void EphemeralAppLauncher::ExtensionEnableFlowFinished() { | 244 void EphemeralAppLauncher::ExtensionEnableFlowFinished() { |
268 ExtensionService* extension_service = | 245 CompleteInstall(std::string()); |
269 extensions::ExtensionSystem::Get(profile())->extension_service(); | |
270 DCHECK(extension_service); | |
271 | |
272 const Extension* extension = extension_service->GetExtensionById(id(), false); | |
273 if (extension) { | |
274 LaunchApp(extension); | |
275 WebstoreStandaloneInstaller::CompleteInstall(std::string()); | |
276 } else { | |
277 WebstoreStandaloneInstaller::CompleteInstall(kLaunchAbortedError); | |
278 } | |
279 } | 246 } |
280 | 247 |
281 void EphemeralAppLauncher::ExtensionEnableFlowAborted(bool user_initiated) { | 248 void EphemeralAppLauncher::ExtensionEnableFlowAborted(bool user_initiated) { |
282 WebstoreStandaloneInstaller::CompleteInstall(kLaunchAbortedError); | 249 CompleteInstall(kLaunchAbortedError); |
283 } | 250 } |
OLD | NEW |