blob: d7e83ec2fcfe0c81c9c730b5937bbf10d0a15fff [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.
[email protected]7b3941052013-02-13 01:21:5966 webstore_data_fetcher_.reset(new WebstoreDataFetcher(
67 this,
[email protected]c1b2d042013-02-23 00:31:0468 profile_->GetRequestContext(),
[email protected]d44ec7b2013-03-15 04:34:3469 GetRequestorURL(),
[email protected]7b3941052013-02-13 01:21:5970 id_));
robertshield1fc1a4a2017-02-01 15:18:3371
72 std::string json_post_data = GetJsonPostData();
73 if (!json_post_data.empty())
74 webstore_data_fetcher_->SetJsonPostData(json_post_data);
75
[email protected]7b3941052013-02-13 01:21:5976 webstore_data_fetcher_->Start();
[email protected]8915f342011-08-29 22:14:3777}
78
[email protected]9c7b3092014-06-21 01:19:0379//
80// Private interface implementation.
81//
82
83WebstoreStandaloneInstaller::~WebstoreStandaloneInstaller() {
84}
85
rdevlin.cronin5f6b69d2014-09-20 01:23:3586void WebstoreStandaloneInstaller::RunCallback(bool success,
87 const std::string& error,
88 webstore_install::Result result) {
89 callback_.Run(success, error, result);
90}
91
[email protected]9c7b3092014-06-21 01:19:0392void WebstoreStandaloneInstaller::AbortInstall() {
93 callback_.Reset();
94 // Abort any in-progress fetches.
95 if (webstore_data_fetcher_) {
96 webstore_data_fetcher_.reset();
[email protected]773272b2014-07-18 05:48:3597 scoped_active_install_.reset();
[email protected]9c7b3092014-06-21 01:19:0398 Release(); // Matches the AddRef in BeginInstall.
99 }
100}
101
[email protected]773272b2014-07-18 05:48:35102bool WebstoreStandaloneInstaller::EnsureUniqueInstall(
103 webstore_install::Result* reason,
104 std::string* error) {
105 InstallTracker* tracker = InstallTracker::Get(profile_);
106 DCHECK(tracker);
107
108 const ActiveInstallData* existing_install_data =
109 tracker->GetActiveInstall(id_);
110 if (existing_install_data) {
benwellscb4422c12015-10-13 23:38:46111 *reason = webstore_install::INSTALL_IN_PROGRESS;
rdevlin.cronind30a8bd2016-06-30 16:02:29112 *error = webstore_install::kInstallInProgressError;
[email protected]773272b2014-07-18 05:48:35113 return false;
114 }
115
116 ActiveInstallData install_data(id_);
[email protected]773272b2014-07-18 05:48:35117 scoped_active_install_.reset(new ScopedActiveInstall(tracker, install_data));
118 return true;
119}
120
[email protected]9c7b3092014-06-21 01:19:03121void WebstoreStandaloneInstaller::CompleteInstall(
122 webstore_install::Result result,
123 const std::string& error) {
[email protected]773272b2014-07-18 05:48:35124 scoped_active_install_.reset();
[email protected]9c7b3092014-06-21 01:19:03125 if (!callback_.is_null())
[email protected]ced522c2014-07-23 20:23:59126 callback_.Run(result == webstore_install::SUCCESS, error, result);
[email protected]9c7b3092014-06-21 01:19:03127 Release(); // Matches the AddRef in BeginInstall.
128}
129
130void WebstoreStandaloneInstaller::ProceedWithInstallPrompt() {
131 install_prompt_ = CreateInstallPrompt();
dchengc7047942014-08-26 05:05:31132 if (install_prompt_.get()) {
[email protected]9c7b3092014-06-21 01:19:03133 ShowInstallUI();
rdevlin.cronin41593052016-01-08 01:40:12134 // Control flow finishes up in OnInstallPromptDone().
[email protected]9c7b3092014-06-21 01:19:03135 } else {
rdevlin.cronin41593052016-01-08 01:40:12136 OnInstallPromptDone(ExtensionInstallPrompt::Result::ACCEPTED);
[email protected]9c7b3092014-06-21 01:19:03137 }
138}
139
140scoped_refptr<const Extension>
141WebstoreStandaloneInstaller::GetLocalizedExtensionForDisplay() {
142 if (!localized_extension_for_display_.get()) {
143 DCHECK(manifest_.get());
144 if (!manifest_.get())
145 return NULL;
146
147 std::string error;
148 localized_extension_for_display_ =
149 ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
150 manifest_.get(),
151 Extension::REQUIRE_KEY | Extension::FROM_WEBSTORE,
152 id_,
153 localized_name_,
154 localized_description_,
155 &error);
156 }
157 return localized_extension_for_display_.get();
158}
159
robertshield1fc1a4a2017-02-01 15:18:33160std::string WebstoreStandaloneInstaller::GetJsonPostData() {
161 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_)
316 ->GetURLLoaderFactoryForBrowserProcess());
[email protected]8915f342011-08-29 22:14:37317}
318
[email protected]734bcec2012-10-08 20:29:05319void WebstoreStandaloneInstaller::OnWebstoreResponseParseFailure(
[email protected]8915f342011-08-29 22:14:37320 const std::string& error) {
[email protected]e263a6b62014-06-05 23:19:49321 OnWebStoreDataFetcherDone();
[email protected]9c7b3092014-06-21 01:19:03322 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE, error);
[email protected]8915f342011-08-29 22:14:37323}
324
[email protected]734bcec2012-10-08 20:29:05325void WebstoreStandaloneInstaller::OnWebstoreParseSuccess(
[email protected]98e4e522011-10-25 13:00:16326 const std::string& id,
[email protected]8915f342011-08-29 22:14:37327 const SkBitmap& icon,
328 base::DictionaryValue* manifest) {
[email protected]d44ec7b2013-03-15 04:34:34329 CHECK_EQ(id_, id);
330
331 if (!CheckRequestorAlive()) {
[email protected]9c7b3092014-06-21 01:19:03332 CompleteInstall(webstore_install::ABORTED, std::string());
[email protected]2fd920fb2011-09-08 23:33:00333 return;
334 }
335
[email protected]8915f342011-08-29 22:14:37336 manifest_.reset(manifest);
337 icon_ = icon;
338
[email protected]9c7b3092014-06-21 01:19:03339 OnManifestParsed();
[email protected]8915f342011-08-29 22:14:37340}
341
[email protected]734bcec2012-10-08 20:29:05342void WebstoreStandaloneInstaller::OnWebstoreParseFailure(
[email protected]98e4e522011-10-25 13:00:16343 const std::string& id,
[email protected]8915f342011-08-29 22:14:37344 InstallHelperResultCode result_code,
345 const std::string& error_message) {
[email protected]ced522c2014-07-23 20:23:59346 webstore_install::Result install_result = webstore_install::OTHER_ERROR;
[email protected]9c7b3092014-06-21 01:19:03347 switch (result_code) {
348 case WebstoreInstallHelper::Delegate::MANIFEST_ERROR:
349 install_result = webstore_install::INVALID_MANIFEST;
350 break;
351 case WebstoreInstallHelper::Delegate::ICON_ERROR:
352 install_result = webstore_install::ICON_ERROR;
353 break;
354 default:
355 break;
356 }
357
358 CompleteInstall(install_result, error_message);
[email protected]8915f342011-08-29 22:14:37359}
360
[email protected]734bcec2012-10-08 20:29:05361void WebstoreStandaloneInstaller::OnExtensionInstallSuccess(
362 const std::string& id) {
[email protected]cb08ba22011-10-19 21:41:40363 CHECK_EQ(id_, id);
[email protected]9c7b3092014-06-21 01:19:03364 CompleteInstall(webstore_install::SUCCESS, std::string());
[email protected]cb08ba22011-10-19 21:41:40365}
366
[email protected]734bcec2012-10-08 20:29:05367void WebstoreStandaloneInstaller::OnExtensionInstallFailure(
[email protected]bcd1eaf72012-10-03 05:42:29368 const std::string& id,
369 const std::string& error,
[email protected]9c7b3092014-06-21 01:19:03370 WebstoreInstaller::FailureReason reason) {
[email protected]cb08ba22011-10-19 21:41:40371 CHECK_EQ(id_, id);
[email protected]cb08ba22011-10-19 21:41:40372
[email protected]ced522c2014-07-23 20:23:59373 webstore_install::Result install_result = webstore_install::OTHER_ERROR;
[email protected]9c7b3092014-06-21 01:19:03374 switch (reason) {
375 case WebstoreInstaller::FAILURE_REASON_CANCELLED:
376 install_result = webstore_install::USER_CANCELLED;
377 break;
378 case WebstoreInstaller::FAILURE_REASON_DEPENDENCY_NOT_FOUND:
379 case WebstoreInstaller::FAILURE_REASON_DEPENDENCY_NOT_SHARED_MODULE:
380 install_result = webstore_install::MISSING_DEPENDENCIES;
381 break;
382 default:
383 break;
[email protected]d44ec7b2013-03-15 04:34:34384 }
[email protected]d44ec7b2013-03-15 04:34:34385
[email protected]9c7b3092014-06-21 01:19:03386 CompleteInstall(install_result, error);
[email protected]8915f342011-08-29 22:14:37387}
[email protected]5f2a4752012-04-27 22:18:58388
[email protected]e263a6b62014-06-05 23:19:49389void WebstoreStandaloneInstaller::ShowInstallUI() {
dchengc7047942014-08-26 05:05:31390 scoped_refptr<const Extension> localized_extension =
391 GetLocalizedExtensionForDisplay();
dcheng40eae712014-08-27 16:56:10392 if (!localized_extension.get()) {
rdevlin.cronind30a8bd2016-06-30 16:02:29393 CompleteInstall(webstore_install::INVALID_MANIFEST,
394 webstore_install::kInvalidManifestError);
[email protected]d44ec7b2013-03-15 04:34:34395 return;
[email protected]5f2a4752012-04-27 22:18:58396 }
[email protected]5f2a4752012-04-27 22:18:58397
[email protected]f8b23b42013-06-27 20:12:14398 install_ui_ = CreateInstallUI();
rdevlin.croninf84cab72015-12-12 03:45:23399 install_ui_->ShowDialog(
rdevlin.cronin41593052016-01-08 01:40:12400 base::Bind(&WebstoreStandaloneInstaller::OnInstallPromptDone, this),
401 localized_extension.get(), &icon_, std::move(install_prompt_),
rdevlin.croninf84cab72015-12-12 03:45:23402 ExtensionInstallPrompt::GetDefaultShowDialogCallback());
[email protected]5f2a4752012-04-27 22:18:58403}
[email protected]3d61a7f2012-07-12 19:11:25404
[email protected]e263a6b62014-06-05 23:19:49405void WebstoreStandaloneInstaller::OnWebStoreDataFetcherDone() {
406 // An instance of this class is passed in as a delegate for the
407 // WebstoreInstallHelper, ExtensionInstallPrompt and WebstoreInstaller, and
408 // therefore needs to remain alive until they are done. Clear the webstore
409 // data fetcher to avoid calling Release in AbortInstall while any of these
410 // operations are in progress.
411 webstore_data_fetcher_.reset();
412}
413
[email protected]3d61a7f2012-07-12 19:11:25414} // namespace extensions