Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1333)

Side by Side Diff: chrome/browser/apps/ephemeral_app_launcher.cc

Issue 339103002: Update the EphemeralAppLauncher for use by the webstorePrivate API (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Self nit Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "base/command_line.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/extensions/extension_install_checker.h"
7 #include "chrome/browser/extensions/extension_install_prompt.h" 10 #include "chrome/browser/extensions/extension_install_prompt.h"
8 #include "chrome/browser/extensions/extension_util.h" 11 #include "chrome/browser/extensions/extension_util.h"
9 #include "chrome/browser/profiles/profile.h" 12 #include "chrome/browser/profiles/profile.h"
10 #include "chrome/browser/ui/extensions/application_launch.h" 13 #include "chrome/browser/ui/extensions/application_launch.h"
11 #include "chrome/browser/ui/extensions/extension_enable_flow.h" 14 #include "chrome/browser/ui/extensions/extension_enable_flow.h"
15 #include "chrome/common/chrome_switches.h"
12 #include "content/public/browser/web_contents.h" 16 #include "content/public/browser/web_contents.h"
17 #include "extensions/browser/extension_prefs.h"
13 #include "extensions/browser/extension_registry.h" 18 #include "extensions/browser/extension_registry.h"
19 #include "extensions/browser/extension_system.h"
20 #include "extensions/browser/management_policy.h"
14 #include "extensions/common/permissions/permissions_data.h" 21 #include "extensions/common/permissions/permissions_data.h"
15 22
16 using content::WebContents; 23 using content::WebContents;
17 using extensions::Extension; 24 using extensions::Extension;
25 using extensions::ExtensionInstallChecker;
26 using extensions::ExtensionPrefs;
18 using extensions::ExtensionRegistry; 27 using extensions::ExtensionRegistry;
28 using extensions::ExtensionSystem;
29 using extensions::ManagementPolicy;
19 using extensions::WebstoreInstaller; 30 using extensions::WebstoreInstaller;
20 31
21 namespace { 32 namespace {
22 33
23 const char kInvalidManifestError[] = "Invalid manifest"; 34 const char kInvalidManifestError[] = "Invalid manifest";
24 const char kExtensionTypeError[] = "Ephemeral extensions are not permitted"; 35 const char kExtensionTypeError[] = "Cannot launch an extension";
25 const char kLaunchAbortedError[] = "Launch aborted"; 36 const char kUserCancelledError[] = "Launch cancelled by the user";
37 const char kBlacklistedError[] = "App is blacklisted for malware";
38 const char kDependenciesError[] = "App has missing requirements";
39 const char kFeatureDisabledError[] = "Launching ephemeral apps is not enabled";
40 const char kMissingAppError[] = "App is not installed";
41 const char kAppDisabledError[] = "App is disabled";
26 42
27 Profile* ProfileForWebContents(content::WebContents* contents) { 43 Profile* ProfileForWebContents(content::WebContents* contents) {
28 if (!contents) 44 if (!contents)
29 return NULL; 45 return NULL;
30 46
31 return Profile::FromBrowserContext(contents->GetBrowserContext()); 47 return Profile::FromBrowserContext(contents->GetBrowserContext());
32 } 48 }
33 49
34 gfx::NativeWindow NativeWindowForWebContents(content::WebContents* contents) { 50 gfx::NativeWindow NativeWindowForWebContents(content::WebContents* contents) {
35 if (!contents) 51 if (!contents)
36 return NULL; 52 return NULL;
37 53
38 return contents->GetTopLevelNativeWindow(); 54 return contents->GetTopLevelNativeWindow();
39 } 55 }
40 56
57 // Check whether an extension can be launched. The extension does not need to
58 // be currently installed.
59 bool CheckCommonLaunchCriteria(Profile* profile,
60 const extensions::Extension* extension,
61 EphemeralAppLauncher::LaunchResult* reason,
62 std::string* error) {
63 // Only apps can be launched.
64 if (!extension->is_app()) {
65 *reason = EphemeralAppLauncher::LAUNCH_UNSUPPORTED_EXTENSION_TYPE;
66 *error = kExtensionTypeError;
67 return false;
68 }
69
70 // Do not launch apps blocked by management policies.
71 ManagementPolicy* management_policy =
72 ExtensionSystem::Get(profile)->management_policy();
73 base::string16 policy_error;
74 if (!management_policy->UserMayLoad(extension, &policy_error)) {
75 *reason = EphemeralAppLauncher::LAUNCH_BLOCKED_BY_POLICY;
76 *error = base::UTF16ToUTF8(policy_error);
77 return false;
78 }
79
80 return true;
81 }
82
41 } // namespace 83 } // namespace
42 84
43 // static 85 // static
44 scoped_refptr<EphemeralAppLauncher> 86 bool EphemeralAppLauncher::IsFeatureEnabled() {
45 EphemeralAppLauncher::CreateForLauncher( 87 return CommandLine::ForCurrentProcess()->HasSwitch(
88 switches::kEnableEphemeralApps);
89 }
90
91 // static
92 scoped_refptr<EphemeralAppLauncher> EphemeralAppLauncher::CreateForLauncher(
46 const std::string& webstore_item_id, 93 const std::string& webstore_item_id,
47 Profile* profile, 94 Profile* profile,
48 gfx::NativeWindow parent_window, 95 gfx::NativeWindow parent_window,
49 const Callback& callback) { 96 const LaunchCallback& callback) {
50 scoped_refptr<EphemeralAppLauncher> installer = 97 scoped_refptr<EphemeralAppLauncher> installer =
51 new EphemeralAppLauncher(webstore_item_id, 98 new EphemeralAppLauncher(webstore_item_id,
52 profile, 99 profile,
53 parent_window, 100 parent_window,
54 callback); 101 callback);
55 installer->set_install_source(WebstoreInstaller::INSTALL_SOURCE_APP_LAUNCHER); 102 installer->set_install_source(WebstoreInstaller::INSTALL_SOURCE_APP_LAUNCHER);
56 return installer; 103 return installer;
57 } 104 }
58 105
59 // static 106 // static
60 scoped_refptr<EphemeralAppLauncher> 107 scoped_refptr<EphemeralAppLauncher> EphemeralAppLauncher::CreateForWebContents(
61 EphemeralAppLauncher::CreateForLink(
62 const std::string& webstore_item_id, 108 const std::string& webstore_item_id,
63 content::WebContents* web_contents) { 109 content::WebContents* web_contents,
110 const LaunchCallback& callback) {
64 scoped_refptr<EphemeralAppLauncher> installer = 111 scoped_refptr<EphemeralAppLauncher> installer =
65 new EphemeralAppLauncher(webstore_item_id, 112 new EphemeralAppLauncher(webstore_item_id, web_contents, callback);
66 web_contents,
67 Callback());
68 installer->set_install_source(WebstoreInstaller::INSTALL_SOURCE_OTHER); 113 installer->set_install_source(WebstoreInstaller::INSTALL_SOURCE_OTHER);
69 return installer; 114 return installer;
70 } 115 }
71 116
72 void EphemeralAppLauncher::Start() { 117 void EphemeralAppLauncher::Start() {
118 if (!IsFeatureEnabled()) {
119 InvokeCallback(LAUNCH_FEATURE_DISABLED, kFeatureDisabledError);
120 return;
121 }
122
123 // Check whether the app already exists in extension system before downloading
124 // from the webstore.
73 const Extension* extension = 125 const Extension* extension =
74 ExtensionRegistry::Get(profile()) 126 ExtensionRegistry::Get(profile())
75 ->GetExtensionById(id(), ExtensionRegistry::EVERYTHING); 127 ->GetExtensionById(id(), ExtensionRegistry::EVERYTHING);
76 if (extension) { 128 if (extension) {
129 LaunchResult result = LAUNCH_UNKNOWN_ERROR;
130 std::string error;
131 if (!CanLaunchInstalledApp(extension, &result, &error)) {
132 InvokeCallback(result, error);
133 return;
134 }
135
77 if (extensions::util::IsAppLaunchableWithoutEnabling(extension->id(), 136 if (extensions::util::IsAppLaunchableWithoutEnabling(extension->id(),
78 profile())) { 137 profile())) {
79 LaunchApp(extension); 138 LaunchApp(extension);
80 InvokeCallback(std::string()); 139 InvokeCallback(LAUNCH_SUCCESS, std::string());
81 return; 140 return;
82 } 141 }
83 142
84 // The ephemeral app may have been updated and disabled as it requests 143 EnableInstalledApp(extension);
85 // more permissions. In this case we should always prompt before
86 // launching.
87 extension_enable_flow_.reset(
88 new ExtensionEnableFlow(profile(), extension->id(), this));
89 if (web_contents())
90 extension_enable_flow_->StartForWebContents(web_contents());
91 else
92 extension_enable_flow_->StartForNativeWindow(parent_window_);
93
94 // Keep this object alive until the enable flow is complete.
95 AddRef(); // Balanced in WebstoreStandaloneInstaller::CompleteInstall.
96 return; 144 return;
97 } 145 }
98 146
99 // Fetch the app from the webstore. 147 // Install the app ephemerally and launch when complete.
100 BeginInstall(); 148 BeginInstall();
101 } 149 }
102 150
103 EphemeralAppLauncher::EphemeralAppLauncher(const std::string& webstore_item_id, 151 EphemeralAppLauncher::EphemeralAppLauncher(const std::string& webstore_item_id,
104 Profile* profile, 152 Profile* profile,
105 gfx::NativeWindow parent_window, 153 gfx::NativeWindow parent_window,
106 const Callback& callback) 154 const LaunchCallback& callback)
107 : WebstoreStandaloneInstaller(webstore_item_id, profile, callback), 155 : WebstoreStandaloneInstaller(webstore_item_id, profile, Callback()),
156 launch_callback_(callback),
108 parent_window_(parent_window), 157 parent_window_(parent_window),
109 dummy_web_contents_( 158 dummy_web_contents_(
110 WebContents::Create(WebContents::CreateParams(profile))) { 159 WebContents::Create(WebContents::CreateParams(profile))) {
111 } 160 }
112 161
113 EphemeralAppLauncher::EphemeralAppLauncher(const std::string& webstore_item_id, 162 EphemeralAppLauncher::EphemeralAppLauncher(const std::string& webstore_item_id,
114 content::WebContents* web_contents, 163 content::WebContents* web_contents,
115 const Callback& callback) 164 const LaunchCallback& callback)
116 : WebstoreStandaloneInstaller(webstore_item_id, 165 : WebstoreStandaloneInstaller(webstore_item_id,
117 ProfileForWebContents(web_contents), 166 ProfileForWebContents(web_contents),
118 callback), 167 Callback()),
119 content::WebContentsObserver(web_contents), 168 content::WebContentsObserver(web_contents),
169 launch_callback_(callback),
120 parent_window_(NativeWindowForWebContents(web_contents)) { 170 parent_window_(NativeWindowForWebContents(web_contents)) {
121 } 171 }
122 172
123 EphemeralAppLauncher::~EphemeralAppLauncher() {} 173 EphemeralAppLauncher::~EphemeralAppLauncher() {}
124 174
175 bool EphemeralAppLauncher::CanLaunchInstalledApp(
176 const extensions::Extension* extension,
177 LaunchResult* reason,
178 std::string* error) {
179 if (!CheckCommonLaunchCriteria(profile(), extension, reason, error))
180 return false;
181
182 // Do not launch blacklisted apps.
183 if (ExtensionPrefs::Get(profile())->IsExtensionBlacklisted(extension->id())) {
184 *reason = LAUNCH_BLACKLISTED;
185 *error = kBlacklistedError;
186 return false;
187 }
188
189 // If the app has missing requirements, it cannot be launched.
190 if (!extensions::util::IsAppLaunchable(extension->id(), profile())) {
191 *reason = LAUNCH_MISSING_DEPENDENCIES;
192 *error = kDependenciesError;
193 return false;
194 }
195
196 return true;
197 }
198
199 void EphemeralAppLauncher::EnableInstalledApp(const Extension* extension) {
200 extension_enable_flow_.reset(
201 new ExtensionEnableFlow(profile(), extension->id(), this));
202 if (web_contents())
203 extension_enable_flow_->StartForWebContents(web_contents());
204 else
205 extension_enable_flow_->StartForNativeWindow(parent_window_);
206
207 // Keep this object alive until the enable flow is complete. Either
208 // ExtensionEnableFlowFinished() or ExtensionEnableFlowAborted() will be
209 // called.
210 AddRef();
211 }
212
213 void EphemeralAppLauncher::MaybeLaunchApp() {
214 LaunchResult result = LAUNCH_UNKNOWN_ERROR;
215 std::string error;
216
217 ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
218 const Extension* extension =
219 registry->GetExtensionById(id(), ExtensionRegistry::EVERYTHING);
220 if (extension) {
221 // Although the installation was successful, the app may not be
222 // launchable.
223 if (registry->enabled_extensions().Contains(extension->id())) {
224 result = LAUNCH_SUCCESS;
225 LaunchApp(extension);
226 } else {
227 error = kAppDisabledError;
228 // Determine why the app cannot be launched.
229 CanLaunchInstalledApp(extension, &result, &error);
230 }
231 } else {
232 // The extension must be present in the registry if installed.
233 NOTREACHED();
234 error = kMissingAppError;
235 }
236
237 InvokeCallback(result, error);
238 }
239
125 void EphemeralAppLauncher::LaunchApp(const Extension* extension) const { 240 void EphemeralAppLauncher::LaunchApp(const Extension* extension) const {
126 DCHECK(extension); 241 DCHECK(extension && extension->is_app() &&
127 if (!extension->is_app()) { 242 ExtensionRegistry::Get(profile())
128 LOG(ERROR) << "Unable to launch extension " << extension->id() 243 ->GetExtensionById(extension->id(), ExtensionRegistry::ENABLED));
129 << ". It is not an app.";
130 return;
131 }
132 244
133 AppLaunchParams params(profile(), extension, NEW_FOREGROUND_TAB); 245 AppLaunchParams params(profile(), extension, NEW_FOREGROUND_TAB);
134 params.desktop_type = 246 params.desktop_type =
135 chrome::GetHostDesktopTypeForNativeWindow(parent_window_); 247 chrome::GetHostDesktopTypeForNativeWindow(parent_window_);
136 OpenApplication(params); 248 OpenApplication(params);
137 } 249 }
138 250
251 void EphemeralAppLauncher::InvokeCallback(LaunchResult result,
252 const std::string& error) {
253 if (!launch_callback_.is_null()) {
254 launch_callback_.Run(result, error);
255 launch_callback_.Reset();
256 }
257 }
258
259 void EphemeralAppLauncher::AbortLaunch(LaunchResult result,
260 const std::string& error) {
261 InvokeCallback(result, error);
262 WebstoreStandaloneInstaller::CompleteInstall(INSTALL_ABORTED, std::string());
263 }
264
265 scoped_ptr<extensions::ExtensionInstallChecker>
266 EphemeralAppLauncher::CreateInstallChecker() {
267 return make_scoped_ptr(new ExtensionInstallChecker(profile()));
268 }
269
270 void EphemeralAppLauncher::CheckEphemeralInstallPermitted() {
271 scoped_refptr<const Extension> extension = GetLocalizedExtensionForDisplay();
272 DCHECK(extension.get()); // Checked in OnManifestParsed().
273
274 install_checker_ = CreateInstallChecker();
275 DCHECK(install_checker_.get());
276
277 install_checker_->set_extension(extension);
278 install_checker_->Start(ExtensionInstallChecker::CHECK_BLACKLIST |
279 ExtensionInstallChecker::CHECK_REQUIREMENTS,
280 true,
281 base::Bind(&EphemeralAppLauncher::OnInstallChecked,
282 base::Unretained(this)));
283 }
284
285 void EphemeralAppLauncher::OnInstallChecked(int check_failures) {
286 if (!CheckRequestorAlive()) {
287 AbortLaunch(LAUNCH_UNKNOWN_ERROR, std::string());
288 return;
289 }
290
291 if (install_checker_->blacklist_state() == extensions::BLACKLISTED_MALWARE) {
292 AbortLaunch(LAUNCH_BLACKLISTED, kBlacklistedError);
293 return;
294 }
295
296 if (!install_checker_->requirement_errors().empty()) {
297 AbortLaunch(LAUNCH_MISSING_DEPENDENCIES,
298 install_checker_->requirement_errors().front());
299 return;
300 }
301
302 // Proceed with the normal install flow.
303 ProceedWithInstallPrompt();
304 }
305
139 bool EphemeralAppLauncher::CheckRequestorAlive() const { 306 bool EphemeralAppLauncher::CheckRequestorAlive() const {
140 return dummy_web_contents_.get() != NULL || web_contents() != NULL; 307 return dummy_web_contents_.get() != NULL || web_contents() != NULL;
141 } 308 }
142 309
143 const GURL& EphemeralAppLauncher::GetRequestorURL() const { 310 const GURL& EphemeralAppLauncher::GetRequestorURL() const {
144 return GURL::EmptyGURL(); 311 return GURL::EmptyGURL();
145 } 312 }
146 313
147 bool EphemeralAppLauncher::ShouldShowPostInstallUI() const { 314 bool EphemeralAppLauncher::ShouldShowPostInstallUI() const {
148 return false; 315 return false;
149 } 316 }
150 317
151 bool EphemeralAppLauncher::ShouldShowAppInstalledBubble() const { 318 bool EphemeralAppLauncher::ShouldShowAppInstalledBubble() const {
152 return false; 319 return false;
153 } 320 }
154 321
155 WebContents* EphemeralAppLauncher::GetWebContents() const { 322 WebContents* EphemeralAppLauncher::GetWebContents() const {
156 return web_contents() ? web_contents() : dummy_web_contents_.get(); 323 return web_contents() ? web_contents() : dummy_web_contents_.get();
157 } 324 }
158 325
159 scoped_ptr<ExtensionInstallPrompt::Prompt> 326 scoped_ptr<ExtensionInstallPrompt::Prompt>
160 EphemeralAppLauncher::CreateInstallPrompt() const { 327 EphemeralAppLauncher::CreateInstallPrompt() const {
161 DCHECK(extension_.get() != NULL); 328 const Extension* extension = localized_extension_for_display();
329 DCHECK(extension); // Checked in OnManifestParsed().
162 330
163 // Skip the prompt by returning null if the app does not need to display 331 // Skip the prompt by returning null if the app does not need to display
164 // permission warnings. 332 // permission warnings.
165 extensions::PermissionMessages permissions = 333 extensions::PermissionMessages permissions =
166 extension_->permissions_data()->GetPermissionMessages(); 334 extension->permissions_data()->GetPermissionMessages();
167 if (permissions.empty()) 335 if (permissions.empty())
168 return scoped_ptr<ExtensionInstallPrompt::Prompt>(); 336 return scoped_ptr<ExtensionInstallPrompt::Prompt>();
169 337
170 return make_scoped_ptr(new ExtensionInstallPrompt::Prompt( 338 return make_scoped_ptr(new ExtensionInstallPrompt::Prompt(
171 ExtensionInstallPrompt::LAUNCH_PROMPT)); 339 ExtensionInstallPrompt::LAUNCH_PROMPT));
172 } 340 }
173 341
174 bool EphemeralAppLauncher::CheckInlineInstallPermitted( 342 bool EphemeralAppLauncher::CheckInlineInstallPermitted(
175 const base::DictionaryValue& webstore_data, 343 const base::DictionaryValue& webstore_data,
176 std::string* error) const { 344 std::string* error) const {
177 *error = ""; 345 *error = "";
178 return true; 346 return true;
179 } 347 }
180 348
181 bool EphemeralAppLauncher::CheckRequestorPermitted( 349 bool EphemeralAppLauncher::CheckRequestorPermitted(
182 const base::DictionaryValue& webstore_data, 350 const base::DictionaryValue& webstore_data,
183 std::string* error) const { 351 std::string* error) const {
184 *error = ""; 352 *error = "";
185 return true; 353 return true;
186 } 354 }
187 355
188 bool EphemeralAppLauncher::CheckInstallValid( 356 void EphemeralAppLauncher::OnManifestParsed() {
189 const base::DictionaryValue& manifest, 357 const Extension* extension = GetLocalizedExtensionForDisplay();
190 std::string* error) { 358 if (!extension) {
191 extension_ = Extension::Create( 359 AbortLaunch(LAUNCH_INVALID_MANIFEST, kInvalidManifestError);
192 base::FilePath(), 360 return;
193 extensions::Manifest::INTERNAL,
194 manifest,
195 Extension::REQUIRE_KEY | Extension::FROM_WEBSTORE,
196 id(),
197 error);
198 if (!extension_.get()) {
199 *error = kInvalidManifestError;
200 return false;
201 } 361 }
202 362
203 if (!extension_->is_app()) { 363 LaunchResult result = LAUNCH_UNKNOWN_ERROR;
204 *error = kExtensionTypeError; 364 std::string error;
205 return false; 365 if (!CheckCommonLaunchCriteria(profile(), extension, &result, &error)) {
366 AbortLaunch(result, error);
367 return;
206 } 368 }
207 369
208 return true; 370 CheckEphemeralInstallPermitted();
209 } 371 }
210 372
211 scoped_ptr<ExtensionInstallPrompt> 373 scoped_ptr<ExtensionInstallPrompt> EphemeralAppLauncher::CreateInstallUI() {
212 EphemeralAppLauncher::CreateInstallUI() {
213 if (web_contents()) 374 if (web_contents())
214 return make_scoped_ptr(new ExtensionInstallPrompt(web_contents())); 375 return make_scoped_ptr(new ExtensionInstallPrompt(web_contents()));
215 376
216 return make_scoped_ptr( 377 return make_scoped_ptr(
217 new ExtensionInstallPrompt(profile(), parent_window_, NULL)); 378 new ExtensionInstallPrompt(profile(), parent_window_, NULL));
218 } 379 }
219 380
220 scoped_ptr<WebstoreInstaller::Approval> 381 scoped_ptr<WebstoreInstaller::Approval>
221 EphemeralAppLauncher::CreateApproval() const { 382 EphemeralAppLauncher::CreateApproval() const {
222 scoped_ptr<WebstoreInstaller::Approval> approval = 383 scoped_ptr<WebstoreInstaller::Approval> approval =
223 WebstoreStandaloneInstaller::CreateApproval(); 384 WebstoreStandaloneInstaller::CreateApproval();
224 approval->is_ephemeral = true; 385 approval->is_ephemeral = true;
225 return approval.Pass(); 386 return approval.Pass();
226 } 387 }
227 388
228 void EphemeralAppLauncher::CompleteInstall(const std::string& error) { 389 void EphemeralAppLauncher::CompleteInstall(InstallResult result,
229 if (error.empty()) { 390 const std::string& error) {
230 const Extension* extension = 391 if (result == INSTALL_SUCCESS) {
231 ExtensionRegistry::Get(profile()) 392 MaybeLaunchApp();
232 ->GetExtensionById(id(), ExtensionRegistry::ENABLED); 393 } else if (!launch_callback_.is_null()) {
233 if (extension) 394 // Convert the install error codes to launch error codes.
234 LaunchApp(extension); 395 LaunchResult launch_result = LAUNCH_UNKNOWN_ERROR;
396 switch (result) {
397 case INSTALL_USER_CANCELLED:
398 launch_result = LAUNCH_USER_CANCELLED;
399 break;
400 case INSTALL_INVALID_ID:
401 launch_result = LAUNCH_INVALID_ID;
402 break;
403 case INSTALL_INVALID_MANIFEST:
404 launch_result = LAUNCH_INVALID_MANIFEST;
405 break;
406 case INSTALL_NOT_PERMITTED:
407 case INSTALL_WEBSTORE_REQUEST_ERROR:
408 case INSTALL_INVALID_WEBSTORE_RESPONSE:
409 case INSTALL_ICON_ERROR:
410 launch_result = LAUNCH_INSTALL_ERROR;
411 break;
412 case INSTALL_BLACKLISTED:
413 launch_result = LAUNCH_BLACKLISTED;
414 break;
415 case INSTALL_MISSING_DEPENDENCIES:
416 launch_result = LAUNCH_MISSING_DEPENDENCIES;
417 break;
418 default:
419 break;
420 }
421
422 InvokeCallback(launch_result, error);
235 } 423 }
236 424
237 WebstoreStandaloneInstaller::CompleteInstall(error); 425 WebstoreStandaloneInstaller::CompleteInstall(result, error);
238 } 426 }
239 427
240 void EphemeralAppLauncher::WebContentsDestroyed() { 428 void EphemeralAppLauncher::WebContentsDestroyed() {
429 launch_callback_.Reset();
241 AbortInstall(); 430 AbortInstall();
242 } 431 }
243 432
244 void EphemeralAppLauncher::ExtensionEnableFlowFinished() { 433 void EphemeralAppLauncher::ExtensionEnableFlowFinished() {
245 CompleteInstall(std::string()); 434 MaybeLaunchApp();
435 Release(); // Matches the AddRef in EnableInstalledApp().
246 } 436 }
247 437
248 void EphemeralAppLauncher::ExtensionEnableFlowAborted(bool user_initiated) { 438 void EphemeralAppLauncher::ExtensionEnableFlowAborted(bool user_initiated) {
249 CompleteInstall(kLaunchAbortedError); 439 InvokeCallback(LAUNCH_USER_CANCELLED, kUserCancelledError);
440 Release(); // Matches the AddRef in EnableInstalledApp().
250 } 441 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698