blob: b2b33ef90882a94662948833ae827b057787e9fd [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
dcheng1fc00f12015-12-26 22:18:037#include <utility>
8
[email protected]8915f342011-08-29 22:14:379#include "base/values.h"
[email protected]9c7b3092014-06-21 01:19:0310#include "base/version.h"
[email protected]8915f342011-08-29 22:14:3711#include "chrome/browser/extensions/crx_installer.h"
[email protected]d44ec7b2013-03-15 04:34:3412#include "chrome/browser/extensions/extension_install_prompt.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"
Mark Pilgrim445bb782017-12-08 19:47:1218#include "content/public/browser/storage_partition.h"
[email protected]10c2d692012-05-11 05:32:2319#include "content/public/browser/web_contents.h"
[email protected]489db0842014-01-22 18:20:0320#include "extensions/browser/extension_prefs.h"
[email protected]760f743b2014-05-28 13:52:0221#include "extensions/browser/extension_registry.h"
[email protected]59b0e602014-01-30 00:41:2422#include "extensions/browser/extension_system.h"
[email protected]e4452d32013-11-15 23:07:4123#include "extensions/common/extension.h"
rockot90659852014-09-18 19:31:5224#include "extensions/common/extension_urls.h"
[email protected]a6483d22013-07-03 22:11:0025#include "url/gurl.h"
[email protected]8915f342011-08-29 22:14:3726
[email protected]26b5e322011-12-23 01:36:4727using content::WebContents;
[email protected]631bb742011-11-02 11:29:3928
[email protected]3d61a7f2012-07-12 19:11:2529namespace extensions {
30
[email protected]734bcec2012-10-08 20:29:0531WebstoreStandaloneInstaller::WebstoreStandaloneInstaller(
[email protected]d44ec7b2013-03-15 04:34:3432 const std::string& webstore_item_id,
[email protected]c1b2d042013-02-23 00:31:0433 Profile* profile,
[email protected]c1b2d042013-02-23 00:31:0434 const Callback& callback)
[email protected]d44ec7b2013-03-15 04:34:3435 : id_(webstore_item_id),
[email protected]d2a639e2012-09-17 07:41:2136 callback_(callback),
[email protected]d44ec7b2013-03-15 04:34:3437 profile_(profile),
[email protected]084e35482013-09-25 02:46:1938 install_source_(WebstoreInstaller::INSTALL_SOURCE_INLINE),
[email protected]dcde34b32013-07-31 02:28:4539 show_user_count_(true),
[email protected]c7bf7452011-09-12 21:31:5040 average_rating_(0.0),
[email protected]5f2a4752012-04-27 22:18:5841 rating_count_(0) {
[email protected]c1b2d042013-02-23 00:31:0442}
43
[email protected]734bcec2012-10-08 20:29:0544void WebstoreStandaloneInstaller::BeginInstall() {
[email protected]3d6d676522013-10-14 20:44:5545 // Add a ref to keep this alive for WebstoreDataFetcher.
46 // All code paths from here eventually lead to either CompleteInstall or
47 // AbortInstall, which both release this ref.
48 AddRef();
[email protected]8915f342011-08-29 22:14:3749
[email protected]fdd28372014-08-21 02:27:2650 if (!crx_file::id_util::IdIsValid(id_)) {
rdevlin.cronind30a8bd2016-06-30 16:02:2951 CompleteInstall(webstore_install::INVALID_ID,
52 webstore_install::kInvalidWebstoreItemId);
[email protected]8915f342011-08-29 22:14:3753 return;
54 }
55
[email protected]ced522c2014-07-23 20:23:5956 webstore_install::Result result = webstore_install::OTHER_ERROR;
[email protected]773272b2014-07-18 05:48:3557 std::string error;
58 if (!EnsureUniqueInstall(&result, &error)) {
59 CompleteInstall(result, error);
60 return;
61 }
62
[email protected]b4574c02011-11-17 06:19:1363 // Use the requesting page as the referrer both since that is more correct
64 // (it is the page that caused this request to happen) and so that we can
65 // track top sites that trigger inline install requests.
Mark Pilgrim1a72e0512018-04-25 13:48:4866 webstore_data_fetcher_.reset(
67 new WebstoreDataFetcher(this, GetRequestorURL(), id_));
robertshield1fc1a4a2017-02-01 15:18:3368
Jialiu Linfc668ec12018-01-31 01:28:4469 webstore_data_fetcher_->SetPostData(
70 GetPostData(webstore_data_fetcher_->upload_content_type()));
robertshield1fc1a4a2017-02-01 15:18:3371
Mark Pilgrim1a72e0512018-04-25 13:48:4872 webstore_data_fetcher_->Start(
73 content::BrowserContext::GetDefaultStoragePartition(profile_)
74 ->GetURLLoaderFactoryForBrowserProcess()
75 .get());
[email protected]8915f342011-08-29 22:14:3776}
77
[email protected]9c7b3092014-06-21 01:19:0378//
79// Private interface implementation.
80//
81
82WebstoreStandaloneInstaller::~WebstoreStandaloneInstaller() {
83}
84
rdevlin.cronin5f6b69d2014-09-20 01:23:3585void WebstoreStandaloneInstaller::RunCallback(bool success,
86 const std::string& error,
87 webstore_install::Result result) {
88 callback_.Run(success, error, result);
89}
90
[email protected]9c7b3092014-06-21 01:19:0391void WebstoreStandaloneInstaller::AbortInstall() {
92 callback_.Reset();
93 // Abort any in-progress fetches.
94 if (webstore_data_fetcher_) {
95 webstore_data_fetcher_.reset();
[email protected]773272b2014-07-18 05:48:3596 scoped_active_install_.reset();
[email protected]9c7b3092014-06-21 01:19:0397 Release(); // Matches the AddRef in BeginInstall.
98 }
99}
100
[email protected]773272b2014-07-18 05:48:35101bool WebstoreStandaloneInstaller::EnsureUniqueInstall(
102 webstore_install::Result* reason,
103 std::string* error) {
104 InstallTracker* tracker = InstallTracker::Get(profile_);
105 DCHECK(tracker);
106
107 const ActiveInstallData* existing_install_data =
108 tracker->GetActiveInstall(id_);
109 if (existing_install_data) {
benwellscb4422c12015-10-13 23:38:46110 *reason = webstore_install::INSTALL_IN_PROGRESS;
rdevlin.cronind30a8bd2016-06-30 16:02:29111 *error = webstore_install::kInstallInProgressError;
[email protected]773272b2014-07-18 05:48:35112 return false;
113 }
114
115 ActiveInstallData install_data(id_);
[email protected]773272b2014-07-18 05:48:35116 scoped_active_install_.reset(new ScopedActiveInstall(tracker, install_data));
117 return true;
118}
119
[email protected]9c7b3092014-06-21 01:19:03120void WebstoreStandaloneInstaller::CompleteInstall(
121 webstore_install::Result result,
122 const std::string& error) {
[email protected]773272b2014-07-18 05:48:35123 scoped_active_install_.reset();
[email protected]9c7b3092014-06-21 01:19:03124 if (!callback_.is_null())
[email protected]ced522c2014-07-23 20:23:59125 callback_.Run(result == webstore_install::SUCCESS, error, result);
[email protected]9c7b3092014-06-21 01:19:03126 Release(); // Matches the AddRef in BeginInstall.
127}
128
129void WebstoreStandaloneInstaller::ProceedWithInstallPrompt() {
130 install_prompt_ = CreateInstallPrompt();
dchengc7047942014-08-26 05:05:31131 if (install_prompt_.get()) {
[email protected]9c7b3092014-06-21 01:19:03132 ShowInstallUI();
rdevlin.cronin41593052016-01-08 01:40:12133 // Control flow finishes up in OnInstallPromptDone().
[email protected]9c7b3092014-06-21 01:19:03134 } else {
rdevlin.cronin41593052016-01-08 01:40:12135 OnInstallPromptDone(ExtensionInstallPrompt::Result::ACCEPTED);
[email protected]9c7b3092014-06-21 01:19:03136 }
137}
138
139scoped_refptr<const Extension>
140WebstoreStandaloneInstaller::GetLocalizedExtensionForDisplay() {
141 if (!localized_extension_for_display_.get()) {
142 DCHECK(manifest_.get());
143 if (!manifest_.get())
144 return NULL;
145
146 std::string error;
147 localized_extension_for_display_ =
148 ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
149 manifest_.get(),
150 Extension::REQUIRE_KEY | Extension::FROM_WEBSTORE,
151 id_,
152 localized_name_,
153 localized_description_,
154 &error);
155 }
156 return localized_extension_for_display_.get();
157}
158
Jialiu Linfc668ec12018-01-31 01:28:44159std::string WebstoreStandaloneInstaller::GetPostData(
160 const std::string& upload_content_type_unused) {
robertshield1fc1a4a2017-02-01 15:18:33161 return std::string();
162}
163
[email protected]9c7b3092014-06-21 01:19:03164void WebstoreStandaloneInstaller::OnManifestParsed() {
165 ProceedWithInstallPrompt();
[email protected]ce35418b2013-11-25 01:22:33166}
167
dchengc963c7142016-04-08 03:55:22168std::unique_ptr<ExtensionInstallPrompt>
[email protected]f8b23b42013-06-27 20:12:14169WebstoreStandaloneInstaller::CreateInstallUI() {
Jinho Bangb5216cec2018-01-17 19:43:11170 return std::make_unique<ExtensionInstallPrompt>(GetWebContents());
[email protected]f8b23b42013-06-27 20:12:14171}
172
dchengc963c7142016-04-08 03:55:22173std::unique_ptr<WebstoreInstaller::Approval>
[email protected]ce35418b2013-11-25 01:22:33174WebstoreStandaloneInstaller::CreateApproval() const {
dchengc963c7142016-04-08 03:55:22175 std::unique_ptr<WebstoreInstaller::Approval> approval(
[email protected]ce35418b2013-11-25 01:22:33176 WebstoreInstaller::Approval::CreateWithNoInstallPrompt(
dchengc963c7142016-04-08 03:55:22177 profile_, id_,
rdevlin.cronin165732a42016-07-18 22:25:08178 std::unique_ptr<base::DictionaryValue>(manifest_->DeepCopy()), true));
[email protected]ce35418b2013-11-25 01:22:33179 approval->skip_post_install_ui = !ShouldShowPostInstallUI();
180 approval->use_app_installed_bubble = ShouldShowAppInstalledBubble();
181 approval->installing_icon = gfx::ImageSkia::CreateFrom1xBitmap(icon_);
dcheng1fc00f12015-12-26 22:18:03182 return approval;
[email protected]ce35418b2013-11-25 01:22:33183}
184
rdevlin.cronin41593052016-01-08 01:40:12185void WebstoreStandaloneInstaller::OnInstallPromptDone(
186 ExtensionInstallPrompt::Result result) {
187 if (result == ExtensionInstallPrompt::Result::USER_CANCELED) {
rdevlin.cronind30a8bd2016-06-30 16:02:29188 CompleteInstall(webstore_install::USER_CANCELLED,
189 webstore_install::kUserCancelledError);
rdevlin.cronin41593052016-01-08 01:40:12190 return;
191 }
192
193 if (result == ExtensionInstallPrompt::Result::ABORTED ||
194 !CheckRequestorAlive()) {
rdevlin.cronin5f6b69d2014-09-20 01:23:35195 CompleteInstall(webstore_install::ABORTED, std::string());
196 return;
197 }
198
rdevlin.cronin41593052016-01-08 01:40:12199 DCHECK(result == ExtensionInstallPrompt::Result::ACCEPTED);
200
dchengc963c7142016-04-08 03:55:22201 std::unique_ptr<WebstoreInstaller::Approval> approval = CreateApproval();
rdevlin.cronin5f6b69d2014-09-20 01:23:35202
203 ExtensionService* extension_service =
204 ExtensionSystem::Get(profile_)->extension_service();
205 const Extension* installed_extension =
206 extension_service->GetExtensionById(id_, true /* include disabled */);
207 if (installed_extension) {
208 std::string install_message;
209 webstore_install::Result install_result = webstore_install::SUCCESS;
rdevlin.cronin5f6b69d2014-09-20 01:23:35210
211 if (ExtensionPrefs::Get(profile_)->IsExtensionBlacklisted(id_)) {
212 // Don't install a blacklisted extension.
213 install_result = webstore_install::BLACKLISTED;
rdevlin.cronind30a8bd2016-06-30 16:02:29214 install_message = webstore_install::kExtensionIsBlacklisted;
rdevlin.cronin5f6b69d2014-09-20 01:23:35215 } else if (!extension_service->IsExtensionEnabled(id_)) {
216 // If the extension is installed but disabled, and not blacklisted,
217 // enable it.
218 extension_service->EnableExtension(id_);
219 } // else extension is installed and enabled; no work to be done.
220
lazyboy39a52e7c2017-04-06 18:18:38221 CompleteInstall(install_result, install_message);
222 return;
rdevlin.cronin5f6b69d2014-09-20 01:23:35223 }
224
dcheng1fc00f12015-12-26 22:18:03225 scoped_refptr<WebstoreInstaller> installer =
226 new WebstoreInstaller(profile_, this, GetWebContents(), id_,
227 std::move(approval), install_source_);
rdevlin.cronin5f6b69d2014-09-20 01:23:35228 installer->Start();
229}
230
[email protected]7b3941052013-02-13 01:21:59231void WebstoreStandaloneInstaller::OnWebstoreRequestFailure() {
[email protected]e263a6b62014-06-05 23:19:49232 OnWebStoreDataFetcherDone();
[email protected]9c7b3092014-06-21 01:19:03233 CompleteInstall(webstore_install::WEBSTORE_REQUEST_ERROR,
rdevlin.cronind30a8bd2016-06-30 16:02:29234 webstore_install::kWebstoreRequestError);
[email protected]8915f342011-08-29 22:14:37235}
236
[email protected]734bcec2012-10-08 20:29:05237void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess(
dchengc963c7142016-04-08 03:55:22238 std::unique_ptr<base::DictionaryValue> webstore_data) {
[email protected]e263a6b62014-06-05 23:19:49239 OnWebStoreDataFetcherDone();
240
[email protected]d44ec7b2013-03-15 04:34:34241 if (!CheckRequestorAlive()) {
[email protected]9c7b3092014-06-21 01:19:03242 CompleteInstall(webstore_install::ABORTED, std::string());
[email protected]4693243e2011-09-09 23:52:37243 return;
244 }
245
[email protected]d44ec7b2013-03-15 04:34:34246 std::string error;
[email protected]8915f342011-08-29 22:14:37247
[email protected]d44ec7b2013-03-15 04:34:34248 if (!CheckInlineInstallPermitted(*webstore_data, &error)) {
[email protected]9c7b3092014-06-21 01:19:03249 CompleteInstall(webstore_install::NOT_PERMITTED, error);
[email protected]8915f342011-08-29 22:14:37250 return;
251 }
252
[email protected]d44ec7b2013-03-15 04:34:34253 if (!CheckRequestorPermitted(*webstore_data, &error)) {
[email protected]9c7b3092014-06-21 01:19:03254 CompleteInstall(webstore_install::NOT_PERMITTED, error);
[email protected]dd5161a2011-09-14 17:40:17255 return;
256 }
257
258 // Manifest, number of users, average rating and rating count are required.
259 std::string manifest;
260 if (!webstore_data->GetString(kManifestKey, &manifest) ||
261 !webstore_data->GetString(kUsersKey, &localized_user_count_) ||
[email protected]5fdbd6f2011-09-01 17:33:04262 !webstore_data->GetDouble(kAverageRatingKey, &average_rating_) ||
263 !webstore_data->GetInteger(kRatingCountKey, &rating_count_)) {
[email protected]9c7b3092014-06-21 01:19:03264 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29265 webstore_install::kInvalidWebstoreResponseError);
[email protected]5fdbd6f2011-09-01 17:33:04266 return;
267 }
268
[email protected]dcde34b32013-07-31 02:28:45269 // Optional.
270 show_user_count_ = true;
271 webstore_data->GetBoolean(kShowUserCountKey, &show_user_count_);
272
[email protected]c82da8c42012-06-08 19:49:11273 if (average_rating_ < ExtensionInstallPrompt::kMinExtensionRating ||
274 average_rating_ > ExtensionInstallPrompt::kMaxExtensionRating) {
[email protected]9c7b3092014-06-21 01:19:03275 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29276 webstore_install::kInvalidWebstoreResponseError);
[email protected]5fdbd6f2011-09-01 17:33:04277 return;
278 }
279
280 // Localized name and description are optional.
281 if ((webstore_data->HasKey(kLocalizedNameKey) &&
282 !webstore_data->GetString(kLocalizedNameKey, &localized_name_)) ||
283 (webstore_data->HasKey(kLocalizedDescriptionKey) &&
284 !webstore_data->GetString(
285 kLocalizedDescriptionKey, &localized_description_))) {
[email protected]9c7b3092014-06-21 01:19:03286 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29287 webstore_install::kInvalidWebstoreResponseError);
[email protected]8915f342011-08-29 22:14:37288 return;
289 }
290
291 // Icon URL is optional.
292 GURL icon_url;
293 if (webstore_data->HasKey(kIconUrlKey)) {
294 std::string icon_url_string;
295 if (!webstore_data->GetString(kIconUrlKey, &icon_url_string)) {
[email protected]9c7b3092014-06-21 01:19:03296 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29297 webstore_install::kInvalidWebstoreResponseError);
[email protected]8915f342011-08-29 22:14:37298 return;
299 }
csharrison5d1f2142016-11-22 20:25:47300 icon_url = extension_urls::GetWebstoreLaunchURL().Resolve(icon_url_string);
[email protected]8915f342011-08-29 22:14:37301 if (!icon_url.is_valid()) {
[email protected]9c7b3092014-06-21 01:19:03302 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29303 webstore_install::kInvalidWebstoreResponseError);
[email protected]8915f342011-08-29 22:14:37304 return;
305 }
306 }
307
[email protected]d44ec7b2013-03-15 04:34:34308 // Assume ownership of webstore_data.
dcheng1fc00f12015-12-26 22:18:03309 webstore_data_ = std::move(webstore_data);
[email protected]a221ef092011-09-07 01:34:10310
[email protected]007b3f82013-04-09 08:46:45311 scoped_refptr<WebstoreInstallHelper> helper =
Mark Pilgrim445bb782017-12-08 19:47:12312 new WebstoreInstallHelper(this, id_, manifest, icon_url);
thestig144c0c92017-05-18 05:58:02313 // The helper will call us back via OnWebstoreParseSuccess() or
314 // OnWebstoreParseFailure().
Mark Pilgrim445bb782017-12-08 19:47:12315 helper->Start(content::BrowserContext::GetDefaultStoragePartition(profile_)
John Abd-El-Maleka7289152018-02-17 00:16:19316 ->GetURLLoaderFactoryForBrowserProcess()
317 .get());
[email protected]8915f342011-08-29 22:14:37318}
319
[email protected]734bcec2012-10-08 20:29:05320void WebstoreStandaloneInstaller::OnWebstoreResponseParseFailure(
[email protected]8915f342011-08-29 22:14:37321 const std::string& error) {
[email protected]e263a6b62014-06-05 23:19:49322 OnWebStoreDataFetcherDone();
[email protected]9c7b3092014-06-21 01:19:03323 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE, error);
[email protected]8915f342011-08-29 22:14:37324}
325
[email protected]734bcec2012-10-08 20:29:05326void WebstoreStandaloneInstaller::OnWebstoreParseSuccess(
[email protected]98e4e522011-10-25 13:00:16327 const std::string& id,
[email protected]8915f342011-08-29 22:14:37328 const SkBitmap& icon,
329 base::DictionaryValue* manifest) {
[email protected]d44ec7b2013-03-15 04:34:34330 CHECK_EQ(id_, id);
331
332 if (!CheckRequestorAlive()) {
[email protected]9c7b3092014-06-21 01:19:03333 CompleteInstall(webstore_install::ABORTED, std::string());
[email protected]2fd920fb2011-09-08 23:33:00334 return;
335 }
336
[email protected]8915f342011-08-29 22:14:37337 manifest_.reset(manifest);
338 icon_ = icon;
339
[email protected]9c7b3092014-06-21 01:19:03340 OnManifestParsed();
[email protected]8915f342011-08-29 22:14:37341}
342
[email protected]734bcec2012-10-08 20:29:05343void WebstoreStandaloneInstaller::OnWebstoreParseFailure(
[email protected]98e4e522011-10-25 13:00:16344 const std::string& id,
[email protected]8915f342011-08-29 22:14:37345 InstallHelperResultCode result_code,
346 const std::string& error_message) {
[email protected]ced522c2014-07-23 20:23:59347 webstore_install::Result install_result = webstore_install::OTHER_ERROR;
[email protected]9c7b3092014-06-21 01:19:03348 switch (result_code) {
349 case WebstoreInstallHelper::Delegate::MANIFEST_ERROR:
350 install_result = webstore_install::INVALID_MANIFEST;
351 break;
352 case WebstoreInstallHelper::Delegate::ICON_ERROR:
353 install_result = webstore_install::ICON_ERROR;
354 break;
355 default:
356 break;
357 }
358
359 CompleteInstall(install_result, error_message);
[email protected]8915f342011-08-29 22:14:37360}
361
[email protected]734bcec2012-10-08 20:29:05362void WebstoreStandaloneInstaller::OnExtensionInstallSuccess(
363 const std::string& id) {
[email protected]cb08ba22011-10-19 21:41:40364 CHECK_EQ(id_, id);
[email protected]9c7b3092014-06-21 01:19:03365 CompleteInstall(webstore_install::SUCCESS, std::string());
[email protected]cb08ba22011-10-19 21:41:40366}
367
[email protected]734bcec2012-10-08 20:29:05368void WebstoreStandaloneInstaller::OnExtensionInstallFailure(
[email protected]bcd1eaf72012-10-03 05:42:29369 const std::string& id,
370 const std::string& error,
[email protected]9c7b3092014-06-21 01:19:03371 WebstoreInstaller::FailureReason reason) {
[email protected]cb08ba22011-10-19 21:41:40372 CHECK_EQ(id_, id);
[email protected]cb08ba22011-10-19 21:41:40373
[email protected]ced522c2014-07-23 20:23:59374 webstore_install::Result install_result = webstore_install::OTHER_ERROR;
[email protected]9c7b3092014-06-21 01:19:03375 switch (reason) {
376 case WebstoreInstaller::FAILURE_REASON_CANCELLED:
377 install_result = webstore_install::USER_CANCELLED;
378 break;
379 case WebstoreInstaller::FAILURE_REASON_DEPENDENCY_NOT_FOUND:
380 case WebstoreInstaller::FAILURE_REASON_DEPENDENCY_NOT_SHARED_MODULE:
381 install_result = webstore_install::MISSING_DEPENDENCIES;
382 break;
383 default:
384 break;
[email protected]d44ec7b2013-03-15 04:34:34385 }
[email protected]d44ec7b2013-03-15 04:34:34386
[email protected]9c7b3092014-06-21 01:19:03387 CompleteInstall(install_result, error);
[email protected]8915f342011-08-29 22:14:37388}
[email protected]5f2a4752012-04-27 22:18:58389
[email protected]e263a6b62014-06-05 23:19:49390void WebstoreStandaloneInstaller::ShowInstallUI() {
dchengc7047942014-08-26 05:05:31391 scoped_refptr<const Extension> localized_extension =
392 GetLocalizedExtensionForDisplay();
dcheng40eae712014-08-27 16:56:10393 if (!localized_extension.get()) {
rdevlin.cronind30a8bd2016-06-30 16:02:29394 CompleteInstall(webstore_install::INVALID_MANIFEST,
395 webstore_install::kInvalidManifestError);
[email protected]d44ec7b2013-03-15 04:34:34396 return;
[email protected]5f2a4752012-04-27 22:18:58397 }
[email protected]5f2a4752012-04-27 22:18:58398
[email protected]f8b23b42013-06-27 20:12:14399 install_ui_ = CreateInstallUI();
rdevlin.croninf84cab72015-12-12 03:45:23400 install_ui_->ShowDialog(
rdevlin.cronin41593052016-01-08 01:40:12401 base::Bind(&WebstoreStandaloneInstaller::OnInstallPromptDone, this),
402 localized_extension.get(), &icon_, std::move(install_prompt_),
rdevlin.croninf84cab72015-12-12 03:45:23403 ExtensionInstallPrompt::GetDefaultShowDialogCallback());
[email protected]5f2a4752012-04-27 22:18:58404}
[email protected]3d61a7f2012-07-12 19:11:25405
[email protected]e263a6b62014-06-05 23:19:49406void WebstoreStandaloneInstaller::OnWebStoreDataFetcherDone() {
407 // An instance of this class is passed in as a delegate for the
408 // WebstoreInstallHelper, ExtensionInstallPrompt and WebstoreInstaller, and
409 // therefore needs to remain alive until they are done. Clear the webstore
410 // data fetcher to avoid calling Release in AbortInstall while any of these
411 // operations are in progress.
412 webstore_data_fetcher_.reset();
413}
414
[email protected]3d61a7f2012-07-12 19:11:25415} // namespace extensions