blob: 14c564300242c4490f6ccf3bb54949d63987035d [file] [log] [blame]
[email protected]bdb74a22012-01-25 20:33:331// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]8915f342011-08-29 22:14:372// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]734bcec2012-10-08 20:29:055#include "chrome/browser/extensions/webstore_standalone_installer.h"
[email protected]8915f342011-08-29 22:14:376
[email protected]8915f342011-08-29 22:14:377#include "base/values.h"
[email protected]9c7b3092014-06-21 01:19:038#include "base/version.h"
[email protected]8915f342011-08-29 22:14:379#include "chrome/browser/extensions/crx_installer.h"
[email protected]d44ec7b2013-03-15 04:34:3410#include "chrome/browser/extensions/extension_install_prompt.h"
[email protected]00b38242012-07-18 18:43:2211#include "chrome/browser/extensions/extension_install_ui.h"
[email protected]453ac122014-07-28 03:32:1312#include "chrome/browser/extensions/extension_install_ui_util.h"
[email protected]655b2b1a2011-10-13 17:13:0613#include "chrome/browser/extensions/extension_service.h"
[email protected]773272b2014-07-18 05:48:3514#include "chrome/browser/extensions/install_tracker.h"
[email protected]7b3941052013-02-13 01:21:5915#include "chrome/browser/extensions/webstore_data_fetcher.h"
[email protected]8915f342011-08-29 22:14:3716#include "chrome/browser/profiles/profile.h"
[email protected]fdd28372014-08-21 02:27:2617#include "components/crx_file/id_util.h"
[email protected]10c2d692012-05-11 05:32:2318#include "content/public/browser/web_contents.h"
[email protected]489db0842014-01-22 18:20:0319#include "extensions/browser/extension_prefs.h"
[email protected]760f743b2014-05-28 13:52:0220#include "extensions/browser/extension_registry.h"
[email protected]59b0e602014-01-30 00:41:2421#include "extensions/browser/extension_system.h"
[email protected]411f8ae2014-05-22 11:12:2322#include "extensions/browser/extension_util.h"
[email protected]e4452d32013-11-15 23:07:4123#include "extensions/common/extension.h"
[email protected]a6483d22013-07-03 22:11:0024#include "url/gurl.h"
[email protected]8915f342011-08-29 22:14:3725
[email protected]26b5e322011-12-23 01:36:4726using content::WebContents;
[email protected]631bb742011-11-02 11:29:3927
[email protected]3d61a7f2012-07-12 19:11:2528namespace extensions {
29
[email protected]a221ef092011-09-07 01:34:1030const char kInvalidWebstoreItemId[] = "Invalid Chrome Web Store item ID";
31const char kWebstoreRequestError[] =
32 "Could not fetch data from the Chrome Web Store";
33const char kInvalidWebstoreResponseError[] = "Invalid Chrome Web Store reponse";
[email protected]8915f342011-08-29 22:14:3734const char kInvalidManifestError[] = "Invalid manifest";
35const char kUserCancelledError[] = "User cancelled install";
[email protected]f6b88d92014-01-09 19:45:3436const char kExtensionIsBlacklisted[] = "Extension is blacklisted";
[email protected]773272b2014-07-18 05:48:3537const char kInstallInProgressError[] = "An install is already in progress";
38const char kLaunchInProgressError[] = "A launch is already in progress";
[email protected]8915f342011-08-29 22:14:3739
[email protected]734bcec2012-10-08 20:29:0540WebstoreStandaloneInstaller::WebstoreStandaloneInstaller(
[email protected]d44ec7b2013-03-15 04:34:3441 const std::string& webstore_item_id,
[email protected]c1b2d042013-02-23 00:31:0442 Profile* profile,
[email protected]c1b2d042013-02-23 00:31:0443 const Callback& callback)
[email protected]d44ec7b2013-03-15 04:34:3444 : id_(webstore_item_id),
[email protected]d2a639e2012-09-17 07:41:2145 callback_(callback),
[email protected]d44ec7b2013-03-15 04:34:3446 profile_(profile),
[email protected]084e35482013-09-25 02:46:1947 install_source_(WebstoreInstaller::INSTALL_SOURCE_INLINE),
[email protected]dcde34b32013-07-31 02:28:4548 show_user_count_(true),
[email protected]c7bf7452011-09-12 21:31:5049 average_rating_(0.0),
[email protected]5f2a4752012-04-27 22:18:5850 rating_count_(0) {
[email protected]c1b2d042013-02-23 00:31:0451}
52
[email protected]734bcec2012-10-08 20:29:0553void WebstoreStandaloneInstaller::BeginInstall() {
[email protected]3d6d676522013-10-14 20:44:5554 // Add a ref to keep this alive for WebstoreDataFetcher.
55 // All code paths from here eventually lead to either CompleteInstall or
56 // AbortInstall, which both release this ref.
57 AddRef();
[email protected]8915f342011-08-29 22:14:3758
[email protected]fdd28372014-08-21 02:27:2659 if (!crx_file::id_util::IdIsValid(id_)) {
[email protected]9c7b3092014-06-21 01:19:0360 CompleteInstall(webstore_install::INVALID_ID, kInvalidWebstoreItemId);
[email protected]8915f342011-08-29 22:14:3761 return;
62 }
63
[email protected]ced522c2014-07-23 20:23:5964 webstore_install::Result result = webstore_install::OTHER_ERROR;
[email protected]773272b2014-07-18 05:48:3565 std::string error;
66 if (!EnsureUniqueInstall(&result, &error)) {
67 CompleteInstall(result, error);
68 return;
69 }
70
[email protected]b4574c02011-11-17 06:19:1371 // Use the requesting page as the referrer both since that is more correct
72 // (it is the page that caused this request to happen) and so that we can
73 // track top sites that trigger inline install requests.
[email protected]7b3941052013-02-13 01:21:5974 webstore_data_fetcher_.reset(new WebstoreDataFetcher(
75 this,
[email protected]c1b2d042013-02-23 00:31:0476 profile_->GetRequestContext(),
[email protected]d44ec7b2013-03-15 04:34:3477 GetRequestorURL(),
[email protected]7b3941052013-02-13 01:21:5978 id_));
79 webstore_data_fetcher_->Start();
[email protected]8915f342011-08-29 22:14:3780}
81
[email protected]9c7b3092014-06-21 01:19:0382//
83// Private interface implementation.
84//
85
86WebstoreStandaloneInstaller::~WebstoreStandaloneInstaller() {
87}
88
89void WebstoreStandaloneInstaller::AbortInstall() {
90 callback_.Reset();
91 // Abort any in-progress fetches.
92 if (webstore_data_fetcher_) {
93 webstore_data_fetcher_.reset();
[email protected]773272b2014-07-18 05:48:3594 scoped_active_install_.reset();
[email protected]9c7b3092014-06-21 01:19:0395 Release(); // Matches the AddRef in BeginInstall.
96 }
97}
98
[email protected]773272b2014-07-18 05:48:3599bool WebstoreStandaloneInstaller::EnsureUniqueInstall(
100 webstore_install::Result* reason,
101 std::string* error) {
102 InstallTracker* tracker = InstallTracker::Get(profile_);
103 DCHECK(tracker);
104
105 const ActiveInstallData* existing_install_data =
106 tracker->GetActiveInstall(id_);
107 if (existing_install_data) {
108 if (existing_install_data->is_ephemeral) {
109 *reason = webstore_install::LAUNCH_IN_PROGRESS;
110 *error = kLaunchInProgressError;
111 } else {
112 *reason = webstore_install::INSTALL_IN_PROGRESS;
113 *error = kInstallInProgressError;
114 }
115 return false;
116 }
117
118 ActiveInstallData install_data(id_);
119 InitInstallData(&install_data);
120 scoped_active_install_.reset(new ScopedActiveInstall(tracker, install_data));
121 return true;
122}
123
[email protected]9c7b3092014-06-21 01:19:03124void WebstoreStandaloneInstaller::CompleteInstall(
125 webstore_install::Result result,
126 const std::string& error) {
[email protected]773272b2014-07-18 05:48:35127 scoped_active_install_.reset();
[email protected]9c7b3092014-06-21 01:19:03128 if (!callback_.is_null())
[email protected]ced522c2014-07-23 20:23:59129 callback_.Run(result == webstore_install::SUCCESS, error, result);
[email protected]9c7b3092014-06-21 01:19:03130 Release(); // Matches the AddRef in BeginInstall.
131}
132
133void WebstoreStandaloneInstaller::ProceedWithInstallPrompt() {
134 install_prompt_ = CreateInstallPrompt();
dchengc7047942014-08-26 05:05:31135 if (install_prompt_.get()) {
[email protected]9c7b3092014-06-21 01:19:03136 ShowInstallUI();
137 // Control flow finishes up in InstallUIProceed or InstallUIAbort.
138 } else {
139 InstallUIProceed();
140 }
141}
142
143scoped_refptr<const Extension>
144WebstoreStandaloneInstaller::GetLocalizedExtensionForDisplay() {
145 if (!localized_extension_for_display_.get()) {
146 DCHECK(manifest_.get());
147 if (!manifest_.get())
148 return NULL;
149
150 std::string error;
151 localized_extension_for_display_ =
152 ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
153 manifest_.get(),
154 Extension::REQUIRE_KEY | Extension::FROM_WEBSTORE,
155 id_,
156 localized_name_,
157 localized_description_,
158 &error);
159 }
160 return localized_extension_for_display_.get();
161}
162
[email protected]773272b2014-07-18 05:48:35163void WebstoreStandaloneInstaller::InitInstallData(
164 ActiveInstallData* install_data) const {
165 // Default implementation sets no properties.
166}
167
[email protected]9c7b3092014-06-21 01:19:03168void WebstoreStandaloneInstaller::OnManifestParsed() {
169 ProceedWithInstallPrompt();
[email protected]ce35418b2013-11-25 01:22:33170}
171
[email protected]f8b23b42013-06-27 20:12:14172scoped_ptr<ExtensionInstallPrompt>
173WebstoreStandaloneInstaller::CreateInstallUI() {
174 return make_scoped_ptr(new ExtensionInstallPrompt(GetWebContents()));
175}
176
[email protected]ce35418b2013-11-25 01:22:33177scoped_ptr<WebstoreInstaller::Approval>
178WebstoreStandaloneInstaller::CreateApproval() const {
179 scoped_ptr<WebstoreInstaller::Approval> approval(
180 WebstoreInstaller::Approval::CreateWithNoInstallPrompt(
181 profile_,
182 id_,
183 scoped_ptr<base::DictionaryValue>(manifest_.get()->DeepCopy()),
184 true));
185 approval->skip_post_install_ui = !ShouldShowPostInstallUI();
186 approval->use_app_installed_bubble = ShouldShowAppInstalledBubble();
187 approval->installing_icon = gfx::ImageSkia::CreateFrom1xBitmap(icon_);
188 return approval.Pass();
189}
190
[email protected]7b3941052013-02-13 01:21:59191void WebstoreStandaloneInstaller::OnWebstoreRequestFailure() {
[email protected]e263a6b62014-06-05 23:19:49192 OnWebStoreDataFetcherDone();
[email protected]9c7b3092014-06-21 01:19:03193 CompleteInstall(webstore_install::WEBSTORE_REQUEST_ERROR,
194 kWebstoreRequestError);
[email protected]8915f342011-08-29 22:14:37195}
196
[email protected]734bcec2012-10-08 20:29:05197void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess(
[email protected]cb1078de2013-12-23 20:04:22198 scoped_ptr<base::DictionaryValue> webstore_data) {
[email protected]e263a6b62014-06-05 23:19:49199 OnWebStoreDataFetcherDone();
200
[email protected]d44ec7b2013-03-15 04:34:34201 if (!CheckRequestorAlive()) {
[email protected]9c7b3092014-06-21 01:19:03202 CompleteInstall(webstore_install::ABORTED, std::string());
[email protected]4693243e2011-09-09 23:52:37203 return;
204 }
205
[email protected]d44ec7b2013-03-15 04:34:34206 std::string error;
[email protected]8915f342011-08-29 22:14:37207
[email protected]d44ec7b2013-03-15 04:34:34208 if (!CheckInlineInstallPermitted(*webstore_data, &error)) {
[email protected]9c7b3092014-06-21 01:19:03209 CompleteInstall(webstore_install::NOT_PERMITTED, error);
[email protected]8915f342011-08-29 22:14:37210 return;
211 }
212
[email protected]d44ec7b2013-03-15 04:34:34213 if (!CheckRequestorPermitted(*webstore_data, &error)) {
[email protected]9c7b3092014-06-21 01:19:03214 CompleteInstall(webstore_install::NOT_PERMITTED, error);
[email protected]dd5161a2011-09-14 17:40:17215 return;
216 }
217
218 // Manifest, number of users, average rating and rating count are required.
219 std::string manifest;
220 if (!webstore_data->GetString(kManifestKey, &manifest) ||
221 !webstore_data->GetString(kUsersKey, &localized_user_count_) ||
[email protected]5fdbd6f2011-09-01 17:33:04222 !webstore_data->GetDouble(kAverageRatingKey, &average_rating_) ||
223 !webstore_data->GetInteger(kRatingCountKey, &rating_count_)) {
[email protected]9c7b3092014-06-21 01:19:03224 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
225 kInvalidWebstoreResponseError);
[email protected]5fdbd6f2011-09-01 17:33:04226 return;
227 }
228
[email protected]dcde34b32013-07-31 02:28:45229 // Optional.
230 show_user_count_ = true;
231 webstore_data->GetBoolean(kShowUserCountKey, &show_user_count_);
232
[email protected]c82da8c42012-06-08 19:49:11233 if (average_rating_ < ExtensionInstallPrompt::kMinExtensionRating ||
234 average_rating_ > ExtensionInstallPrompt::kMaxExtensionRating) {
[email protected]9c7b3092014-06-21 01:19:03235 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
236 kInvalidWebstoreResponseError);
[email protected]5fdbd6f2011-09-01 17:33:04237 return;
238 }
239
240 // Localized name and description are optional.
241 if ((webstore_data->HasKey(kLocalizedNameKey) &&
242 !webstore_data->GetString(kLocalizedNameKey, &localized_name_)) ||
243 (webstore_data->HasKey(kLocalizedDescriptionKey) &&
244 !webstore_data->GetString(
245 kLocalizedDescriptionKey, &localized_description_))) {
[email protected]9c7b3092014-06-21 01:19:03246 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
247 kInvalidWebstoreResponseError);
[email protected]8915f342011-08-29 22:14:37248 return;
249 }
250
251 // Icon URL is optional.
252 GURL icon_url;
253 if (webstore_data->HasKey(kIconUrlKey)) {
254 std::string icon_url_string;
255 if (!webstore_data->GetString(kIconUrlKey, &icon_url_string)) {
[email protected]9c7b3092014-06-21 01:19:03256 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
257 kInvalidWebstoreResponseError);
[email protected]8915f342011-08-29 22:14:37258 return;
259 }
260 icon_url = GURL(extension_urls::GetWebstoreLaunchURL()).Resolve(
261 icon_url_string);
262 if (!icon_url.is_valid()) {
[email protected]9c7b3092014-06-21 01:19:03263 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
264 kInvalidWebstoreResponseError);
[email protected]8915f342011-08-29 22:14:37265 return;
266 }
267 }
268
[email protected]d44ec7b2013-03-15 04:34:34269 // Assume ownership of webstore_data.
[email protected]b3188ec2013-11-06 10:26:13270 webstore_data_ = webstore_data.Pass();
[email protected]a221ef092011-09-07 01:34:10271
[email protected]007b3f82013-04-09 08:46:45272 scoped_refptr<WebstoreInstallHelper> helper =
273 new WebstoreInstallHelper(this,
274 id_,
275 manifest,
276 std::string(), // We don't have any icon data.
277 icon_url,
278 profile_->GetRequestContext());
[email protected]8915f342011-08-29 22:14:37279 // The helper will call us back via OnWebstoreParseSucces or
280 // OnWebstoreParseFailure.
281 helper->Start();
282}
283
[email protected]734bcec2012-10-08 20:29:05284void WebstoreStandaloneInstaller::OnWebstoreResponseParseFailure(
[email protected]8915f342011-08-29 22:14:37285 const std::string& error) {
[email protected]e263a6b62014-06-05 23:19:49286 OnWebStoreDataFetcherDone();
[email protected]9c7b3092014-06-21 01:19:03287 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE, error);
[email protected]8915f342011-08-29 22:14:37288}
289
[email protected]734bcec2012-10-08 20:29:05290void WebstoreStandaloneInstaller::OnWebstoreParseSuccess(
[email protected]98e4e522011-10-25 13:00:16291 const std::string& id,
[email protected]8915f342011-08-29 22:14:37292 const SkBitmap& icon,
293 base::DictionaryValue* manifest) {
[email protected]d44ec7b2013-03-15 04:34:34294 CHECK_EQ(id_, id);
295
296 if (!CheckRequestorAlive()) {
[email protected]9c7b3092014-06-21 01:19:03297 CompleteInstall(webstore_install::ABORTED, std::string());
[email protected]2fd920fb2011-09-08 23:33:00298 return;
299 }
300
[email protected]8915f342011-08-29 22:14:37301 manifest_.reset(manifest);
302 icon_ = icon;
303
[email protected]9c7b3092014-06-21 01:19:03304 OnManifestParsed();
[email protected]8915f342011-08-29 22:14:37305}
306
[email protected]734bcec2012-10-08 20:29:05307void WebstoreStandaloneInstaller::OnWebstoreParseFailure(
[email protected]98e4e522011-10-25 13:00:16308 const std::string& id,
[email protected]8915f342011-08-29 22:14:37309 InstallHelperResultCode result_code,
310 const std::string& error_message) {
[email protected]ced522c2014-07-23 20:23:59311 webstore_install::Result install_result = webstore_install::OTHER_ERROR;
[email protected]9c7b3092014-06-21 01:19:03312 switch (result_code) {
313 case WebstoreInstallHelper::Delegate::MANIFEST_ERROR:
314 install_result = webstore_install::INVALID_MANIFEST;
315 break;
316 case WebstoreInstallHelper::Delegate::ICON_ERROR:
317 install_result = webstore_install::ICON_ERROR;
318 break;
319 default:
320 break;
321 }
322
323 CompleteInstall(install_result, error_message);
[email protected]8915f342011-08-29 22:14:37324}
325
[email protected]734bcec2012-10-08 20:29:05326void WebstoreStandaloneInstaller::InstallUIProceed() {
[email protected]d44ec7b2013-03-15 04:34:34327 if (!CheckRequestorAlive()) {
[email protected]9c7b3092014-06-21 01:19:03328 CompleteInstall(webstore_install::ABORTED, std::string());
[email protected]2fd920fb2011-09-08 23:33:00329 return;
330 }
331
[email protected]760f743b2014-05-28 13:52:02332 scoped_ptr<WebstoreInstaller::Approval> approval = CreateApproval();
333
[email protected]f6b88d92014-01-09 19:45:34334 ExtensionService* extension_service =
335 ExtensionSystem::Get(profile_)->extension_service();
[email protected]9c7b3092014-06-21 01:19:03336 const Extension* installed_extension =
[email protected]f6b88d92014-01-09 19:45:34337 extension_service->GetExtensionById(id_, true /* include disabled */);
[email protected]9c7b3092014-06-21 01:19:03338 if (installed_extension) {
339 std::string install_message;
340 webstore_install::Result install_result = webstore_install::SUCCESS;
341 bool done = true;
[email protected]ba9ca762014-02-24 02:12:40342
[email protected]760f743b2014-05-28 13:52:02343 if (ExtensionPrefs::Get(profile_)->IsExtensionBlacklisted(id_)) {
344 // Don't install a blacklisted extension.
[email protected]9c7b3092014-06-21 01:19:03345 install_result = webstore_install::BLACKLISTED;
346 install_message = kExtensionIsBlacklisted;
347 } else if (util::IsEphemeralApp(installed_extension->id(), profile_) &&
[email protected]760f743b2014-05-28 13:52:02348 !approval->is_ephemeral) {
[email protected]9c7b3092014-06-21 01:19:03349 // If the target extension has already been installed ephemerally and is
350 // up to date, it can be promoted to a regular installed extension and
351 // downloading from the Web Store is not necessary.
dchengc7047942014-08-26 05:05:31352 scoped_refptr<const Extension> extension_to_install =
353 GetLocalizedExtensionForDisplay();
dcheng40eae712014-08-27 16:56:10354 if (!extension_to_install.get()) {
[email protected]9c7b3092014-06-21 01:19:03355 CompleteInstall(webstore_install::INVALID_MANIFEST,
356 kInvalidManifestError);
357 return;
358 }
359
360 if (installed_extension->version()->CompareTo(
361 *extension_to_install->version()) < 0) {
362 // If the existing extension is out of date, proceed with the install
363 // to update the extension.
364 done = false;
365 } else {
[email protected]453ac122014-07-28 03:32:13366 install_ui::ShowPostInstallUIForApproval(
367 profile_, *approval, installed_extension);
[email protected]9c7b3092014-06-21 01:19:03368 extension_service->PromoteEphemeralApp(installed_extension, false);
369 }
[email protected]760f743b2014-05-28 13:52:02370 } else if (!extension_service->IsExtensionEnabled(id_)) {
371 // If the extension is installed but disabled, and not blacklisted,
372 // enable it.
373 extension_service->EnableExtension(id_);
374 } // else extension is installed and enabled; no work to be done.
375
[email protected]9c7b3092014-06-21 01:19:03376 if (done) {
377 CompleteInstall(install_result, install_message);
378 return;
379 }
[email protected]f6b88d92014-01-09 19:45:34380 }
381
[email protected]98e4e522011-10-25 13:00:16382 scoped_refptr<WebstoreInstaller> installer = new WebstoreInstaller(
[email protected]d44ec7b2013-03-15 04:34:34383 profile_,
384 this,
[email protected]2acf3a52014-02-13 00:26:00385 GetWebContents(),
[email protected]d44ec7b2013-03-15 04:34:34386 id_,
387 approval.Pass(),
[email protected]084e35482013-09-25 02:46:19388 install_source_);
[email protected]98e4e522011-10-25 13:00:16389 installer->Start();
[email protected]8915f342011-08-29 22:14:37390}
391
[email protected]734bcec2012-10-08 20:29:05392void WebstoreStandaloneInstaller::InstallUIAbort(bool user_initiated) {
[email protected]9c7b3092014-06-21 01:19:03393 CompleteInstall(webstore_install::USER_CANCELLED, kUserCancelledError);
[email protected]8915f342011-08-29 22:14:37394}
395
[email protected]734bcec2012-10-08 20:29:05396void WebstoreStandaloneInstaller::OnExtensionInstallSuccess(
397 const std::string& id) {
[email protected]cb08ba22011-10-19 21:41:40398 CHECK_EQ(id_, id);
[email protected]9c7b3092014-06-21 01:19:03399 CompleteInstall(webstore_install::SUCCESS, std::string());
[email protected]cb08ba22011-10-19 21:41:40400}
401
[email protected]734bcec2012-10-08 20:29:05402void WebstoreStandaloneInstaller::OnExtensionInstallFailure(
[email protected]bcd1eaf72012-10-03 05:42:29403 const std::string& id,
404 const std::string& error,
[email protected]9c7b3092014-06-21 01:19:03405 WebstoreInstaller::FailureReason reason) {
[email protected]cb08ba22011-10-19 21:41:40406 CHECK_EQ(id_, id);
[email protected]cb08ba22011-10-19 21:41:40407
[email protected]ced522c2014-07-23 20:23:59408 webstore_install::Result install_result = webstore_install::OTHER_ERROR;
[email protected]9c7b3092014-06-21 01:19:03409 switch (reason) {
410 case WebstoreInstaller::FAILURE_REASON_CANCELLED:
411 install_result = webstore_install::USER_CANCELLED;
412 break;
413 case WebstoreInstaller::FAILURE_REASON_DEPENDENCY_NOT_FOUND:
414 case WebstoreInstaller::FAILURE_REASON_DEPENDENCY_NOT_SHARED_MODULE:
415 install_result = webstore_install::MISSING_DEPENDENCIES;
416 break;
417 default:
418 break;
[email protected]d44ec7b2013-03-15 04:34:34419 }
[email protected]d44ec7b2013-03-15 04:34:34420
[email protected]9c7b3092014-06-21 01:19:03421 CompleteInstall(install_result, error);
[email protected]8915f342011-08-29 22:14:37422}
[email protected]5f2a4752012-04-27 22:18:58423
[email protected]e263a6b62014-06-05 23:19:49424void WebstoreStandaloneInstaller::ShowInstallUI() {
dchengc7047942014-08-26 05:05:31425 scoped_refptr<const Extension> localized_extension =
426 GetLocalizedExtensionForDisplay();
dcheng40eae712014-08-27 16:56:10427 if (!localized_extension.get()) {
[email protected]9c7b3092014-06-21 01:19:03428 CompleteInstall(webstore_install::INVALID_MANIFEST, kInvalidManifestError);
[email protected]d44ec7b2013-03-15 04:34:34429 return;
[email protected]5f2a4752012-04-27 22:18:58430 }
[email protected]5f2a4752012-04-27 22:18:58431
[email protected]f8b23b42013-06-27 20:12:14432 install_ui_ = CreateInstallUI();
[email protected]dc24976f2013-06-02 21:15:09433 install_ui_->ConfirmStandaloneInstall(
dcheng40eae712014-08-27 16:56:10434 this, localized_extension.get(), &icon_, install_prompt_);
[email protected]5f2a4752012-04-27 22:18:58435}
[email protected]3d61a7f2012-07-12 19:11:25436
[email protected]e263a6b62014-06-05 23:19:49437void WebstoreStandaloneInstaller::OnWebStoreDataFetcherDone() {
438 // An instance of this class is passed in as a delegate for the
439 // WebstoreInstallHelper, ExtensionInstallPrompt and WebstoreInstaller, and
440 // therefore needs to remain alive until they are done. Clear the webstore
441 // data fetcher to avoid calling Release in AbortInstall while any of these
442 // operations are in progress.
443 webstore_data_fetcher_.reset();
444}
445
[email protected]3d61a7f2012-07-12 19:11:25446} // namespace extensions