blob: a4499af419c56ad568f32d2752c610c8d2bfd889 [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 Lin9aa277c2018-05-08 00:02:1969 webstore_data_fetcher_->SetPostData(GetPostData());
robertshield1fc1a4a2017-02-01 15:18:3370
Mark Pilgrim1a72e0512018-04-25 13:48:4871 webstore_data_fetcher_->Start(
72 content::BrowserContext::GetDefaultStoragePartition(profile_)
73 ->GetURLLoaderFactoryForBrowserProcess()
74 .get());
[email protected]8915f342011-08-29 22:14:3775}
76
[email protected]9c7b3092014-06-21 01:19:0377//
78// Private interface implementation.
79//
80
81WebstoreStandaloneInstaller::~WebstoreStandaloneInstaller() {
82}
83
rdevlin.cronin5f6b69d2014-09-20 01:23:3584void WebstoreStandaloneInstaller::RunCallback(bool success,
85 const std::string& error,
86 webstore_install::Result result) {
87 callback_.Run(success, error, result);
88}
89
[email protected]9c7b3092014-06-21 01:19:0390void WebstoreStandaloneInstaller::AbortInstall() {
91 callback_.Reset();
92 // Abort any in-progress fetches.
93 if (webstore_data_fetcher_) {
94 webstore_data_fetcher_.reset();
[email protected]773272b2014-07-18 05:48:3595 scoped_active_install_.reset();
[email protected]9c7b3092014-06-21 01:19:0396 Release(); // Matches the AddRef in BeginInstall.
97 }
98}
99
[email protected]773272b2014-07-18 05:48:35100bool WebstoreStandaloneInstaller::EnsureUniqueInstall(
101 webstore_install::Result* reason,
102 std::string* error) {
103 InstallTracker* tracker = InstallTracker::Get(profile_);
104 DCHECK(tracker);
105
106 const ActiveInstallData* existing_install_data =
107 tracker->GetActiveInstall(id_);
108 if (existing_install_data) {
benwellscb4422c12015-10-13 23:38:46109 *reason = webstore_install::INSTALL_IN_PROGRESS;
rdevlin.cronind30a8bd2016-06-30 16:02:29110 *error = webstore_install::kInstallInProgressError;
[email protected]773272b2014-07-18 05:48:35111 return false;
112 }
113
114 ActiveInstallData install_data(id_);
[email protected]773272b2014-07-18 05:48:35115 scoped_active_install_.reset(new ScopedActiveInstall(tracker, install_data));
116 return true;
117}
118
[email protected]9c7b3092014-06-21 01:19:03119void WebstoreStandaloneInstaller::CompleteInstall(
120 webstore_install::Result result,
121 const std::string& error) {
[email protected]773272b2014-07-18 05:48:35122 scoped_active_install_.reset();
[email protected]9c7b3092014-06-21 01:19:03123 if (!callback_.is_null())
[email protected]ced522c2014-07-23 20:23:59124 callback_.Run(result == webstore_install::SUCCESS, error, result);
[email protected]9c7b3092014-06-21 01:19:03125 Release(); // Matches the AddRef in BeginInstall.
126}
127
128void WebstoreStandaloneInstaller::ProceedWithInstallPrompt() {
129 install_prompt_ = CreateInstallPrompt();
dchengc7047942014-08-26 05:05:31130 if (install_prompt_.get()) {
[email protected]9c7b3092014-06-21 01:19:03131 ShowInstallUI();
rdevlin.cronin41593052016-01-08 01:40:12132 // Control flow finishes up in OnInstallPromptDone().
[email protected]9c7b3092014-06-21 01:19:03133 } else {
rdevlin.cronin41593052016-01-08 01:40:12134 OnInstallPromptDone(ExtensionInstallPrompt::Result::ACCEPTED);
[email protected]9c7b3092014-06-21 01:19:03135 }
136}
137
138scoped_refptr<const Extension>
139WebstoreStandaloneInstaller::GetLocalizedExtensionForDisplay() {
140 if (!localized_extension_for_display_.get()) {
141 DCHECK(manifest_.get());
142 if (!manifest_.get())
143 return NULL;
144
145 std::string error;
146 localized_extension_for_display_ =
147 ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
148 manifest_.get(),
149 Extension::REQUIRE_KEY | Extension::FROM_WEBSTORE,
150 id_,
151 localized_name_,
152 localized_description_,
153 &error);
154 }
155 return localized_extension_for_display_.get();
156}
157
Jialiu Lin9aa277c2018-05-08 00:02:19158std::string WebstoreStandaloneInstaller::GetPostData() {
robertshield1fc1a4a2017-02-01 15:18:33159 return std::string();
160}
161
[email protected]9c7b3092014-06-21 01:19:03162void WebstoreStandaloneInstaller::OnManifestParsed() {
163 ProceedWithInstallPrompt();
[email protected]ce35418b2013-11-25 01:22:33164}
165
dchengc963c7142016-04-08 03:55:22166std::unique_ptr<ExtensionInstallPrompt>
[email protected]f8b23b42013-06-27 20:12:14167WebstoreStandaloneInstaller::CreateInstallUI() {
Jinho Bangb5216cec2018-01-17 19:43:11168 return std::make_unique<ExtensionInstallPrompt>(GetWebContents());
[email protected]f8b23b42013-06-27 20:12:14169}
170
dchengc963c7142016-04-08 03:55:22171std::unique_ptr<WebstoreInstaller::Approval>
[email protected]ce35418b2013-11-25 01:22:33172WebstoreStandaloneInstaller::CreateApproval() const {
dchengc963c7142016-04-08 03:55:22173 std::unique_ptr<WebstoreInstaller::Approval> approval(
[email protected]ce35418b2013-11-25 01:22:33174 WebstoreInstaller::Approval::CreateWithNoInstallPrompt(
dchengc963c7142016-04-08 03:55:22175 profile_, id_,
rdevlin.cronin165732a42016-07-18 22:25:08176 std::unique_ptr<base::DictionaryValue>(manifest_->DeepCopy()), true));
[email protected]ce35418b2013-11-25 01:22:33177 approval->skip_post_install_ui = !ShouldShowPostInstallUI();
178 approval->use_app_installed_bubble = ShouldShowAppInstalledBubble();
179 approval->installing_icon = gfx::ImageSkia::CreateFrom1xBitmap(icon_);
dcheng1fc00f12015-12-26 22:18:03180 return approval;
[email protected]ce35418b2013-11-25 01:22:33181}
182
rdevlin.cronin41593052016-01-08 01:40:12183void WebstoreStandaloneInstaller::OnInstallPromptDone(
184 ExtensionInstallPrompt::Result result) {
185 if (result == ExtensionInstallPrompt::Result::USER_CANCELED) {
rdevlin.cronind30a8bd2016-06-30 16:02:29186 CompleteInstall(webstore_install::USER_CANCELLED,
187 webstore_install::kUserCancelledError);
rdevlin.cronin41593052016-01-08 01:40:12188 return;
189 }
190
191 if (result == ExtensionInstallPrompt::Result::ABORTED ||
192 !CheckRequestorAlive()) {
rdevlin.cronin5f6b69d2014-09-20 01:23:35193 CompleteInstall(webstore_install::ABORTED, std::string());
194 return;
195 }
196
rdevlin.cronin41593052016-01-08 01:40:12197 DCHECK(result == ExtensionInstallPrompt::Result::ACCEPTED);
198
dchengc963c7142016-04-08 03:55:22199 std::unique_ptr<WebstoreInstaller::Approval> approval = CreateApproval();
rdevlin.cronin5f6b69d2014-09-20 01:23:35200
201 ExtensionService* extension_service =
202 ExtensionSystem::Get(profile_)->extension_service();
203 const Extension* installed_extension =
204 extension_service->GetExtensionById(id_, true /* include disabled */);
205 if (installed_extension) {
206 std::string install_message;
207 webstore_install::Result install_result = webstore_install::SUCCESS;
rdevlin.cronin5f6b69d2014-09-20 01:23:35208
209 if (ExtensionPrefs::Get(profile_)->IsExtensionBlacklisted(id_)) {
210 // Don't install a blacklisted extension.
211 install_result = webstore_install::BLACKLISTED;
rdevlin.cronind30a8bd2016-06-30 16:02:29212 install_message = webstore_install::kExtensionIsBlacklisted;
rdevlin.cronin5f6b69d2014-09-20 01:23:35213 } else if (!extension_service->IsExtensionEnabled(id_)) {
214 // If the extension is installed but disabled, and not blacklisted,
215 // enable it.
216 extension_service->EnableExtension(id_);
217 } // else extension is installed and enabled; no work to be done.
218
lazyboy39a52e7c2017-04-06 18:18:38219 CompleteInstall(install_result, install_message);
220 return;
rdevlin.cronin5f6b69d2014-09-20 01:23:35221 }
222
dcheng1fc00f12015-12-26 22:18:03223 scoped_refptr<WebstoreInstaller> installer =
224 new WebstoreInstaller(profile_, this, GetWebContents(), id_,
225 std::move(approval), install_source_);
rdevlin.cronin5f6b69d2014-09-20 01:23:35226 installer->Start();
227}
228
[email protected]7b3941052013-02-13 01:21:59229void WebstoreStandaloneInstaller::OnWebstoreRequestFailure() {
[email protected]e263a6b62014-06-05 23:19:49230 OnWebStoreDataFetcherDone();
[email protected]9c7b3092014-06-21 01:19:03231 CompleteInstall(webstore_install::WEBSTORE_REQUEST_ERROR,
rdevlin.cronind30a8bd2016-06-30 16:02:29232 webstore_install::kWebstoreRequestError);
[email protected]8915f342011-08-29 22:14:37233}
234
[email protected]734bcec2012-10-08 20:29:05235void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess(
dchengc963c7142016-04-08 03:55:22236 std::unique_ptr<base::DictionaryValue> webstore_data) {
[email protected]e263a6b62014-06-05 23:19:49237 OnWebStoreDataFetcherDone();
238
[email protected]d44ec7b2013-03-15 04:34:34239 if (!CheckRequestorAlive()) {
[email protected]9c7b3092014-06-21 01:19:03240 CompleteInstall(webstore_install::ABORTED, std::string());
[email protected]4693243e2011-09-09 23:52:37241 return;
242 }
243
[email protected]d44ec7b2013-03-15 04:34:34244 std::string error;
[email protected]8915f342011-08-29 22:14:37245
[email protected]d44ec7b2013-03-15 04:34:34246 if (!CheckInlineInstallPermitted(*webstore_data, &error)) {
[email protected]9c7b3092014-06-21 01:19:03247 CompleteInstall(webstore_install::NOT_PERMITTED, error);
[email protected]8915f342011-08-29 22:14:37248 return;
249 }
250
[email protected]d44ec7b2013-03-15 04:34:34251 if (!CheckRequestorPermitted(*webstore_data, &error)) {
[email protected]9c7b3092014-06-21 01:19:03252 CompleteInstall(webstore_install::NOT_PERMITTED, error);
[email protected]dd5161a2011-09-14 17:40:17253 return;
254 }
255
256 // Manifest, number of users, average rating and rating count are required.
257 std::string manifest;
258 if (!webstore_data->GetString(kManifestKey, &manifest) ||
259 !webstore_data->GetString(kUsersKey, &localized_user_count_) ||
[email protected]5fdbd6f2011-09-01 17:33:04260 !webstore_data->GetDouble(kAverageRatingKey, &average_rating_) ||
261 !webstore_data->GetInteger(kRatingCountKey, &rating_count_)) {
[email protected]9c7b3092014-06-21 01:19:03262 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29263 webstore_install::kInvalidWebstoreResponseError);
[email protected]5fdbd6f2011-09-01 17:33:04264 return;
265 }
266
[email protected]dcde34b32013-07-31 02:28:45267 // Optional.
268 show_user_count_ = true;
269 webstore_data->GetBoolean(kShowUserCountKey, &show_user_count_);
270
[email protected]c82da8c42012-06-08 19:49:11271 if (average_rating_ < ExtensionInstallPrompt::kMinExtensionRating ||
272 average_rating_ > ExtensionInstallPrompt::kMaxExtensionRating) {
[email protected]9c7b3092014-06-21 01:19:03273 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29274 webstore_install::kInvalidWebstoreResponseError);
[email protected]5fdbd6f2011-09-01 17:33:04275 return;
276 }
277
278 // Localized name and description are optional.
279 if ((webstore_data->HasKey(kLocalizedNameKey) &&
280 !webstore_data->GetString(kLocalizedNameKey, &localized_name_)) ||
281 (webstore_data->HasKey(kLocalizedDescriptionKey) &&
282 !webstore_data->GetString(
283 kLocalizedDescriptionKey, &localized_description_))) {
[email protected]9c7b3092014-06-21 01:19:03284 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29285 webstore_install::kInvalidWebstoreResponseError);
[email protected]8915f342011-08-29 22:14:37286 return;
287 }
288
289 // Icon URL is optional.
290 GURL icon_url;
291 if (webstore_data->HasKey(kIconUrlKey)) {
292 std::string icon_url_string;
293 if (!webstore_data->GetString(kIconUrlKey, &icon_url_string)) {
[email protected]9c7b3092014-06-21 01:19:03294 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29295 webstore_install::kInvalidWebstoreResponseError);
[email protected]8915f342011-08-29 22:14:37296 return;
297 }
csharrison5d1f2142016-11-22 20:25:47298 icon_url = extension_urls::GetWebstoreLaunchURL().Resolve(icon_url_string);
[email protected]8915f342011-08-29 22:14:37299 if (!icon_url.is_valid()) {
[email protected]9c7b3092014-06-21 01:19:03300 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29301 webstore_install::kInvalidWebstoreResponseError);
[email protected]8915f342011-08-29 22:14:37302 return;
303 }
304 }
305
[email protected]d44ec7b2013-03-15 04:34:34306 // Assume ownership of webstore_data.
dcheng1fc00f12015-12-26 22:18:03307 webstore_data_ = std::move(webstore_data);
[email protected]a221ef092011-09-07 01:34:10308
[email protected]007b3f82013-04-09 08:46:45309 scoped_refptr<WebstoreInstallHelper> helper =
Mark Pilgrim445bb782017-12-08 19:47:12310 new WebstoreInstallHelper(this, id_, manifest, icon_url);
thestig144c0c92017-05-18 05:58:02311 // The helper will call us back via OnWebstoreParseSuccess() or
312 // OnWebstoreParseFailure().
Mark Pilgrim445bb782017-12-08 19:47:12313 helper->Start(content::BrowserContext::GetDefaultStoragePartition(profile_)
John Abd-El-Maleka7289152018-02-17 00:16:19314 ->GetURLLoaderFactoryForBrowserProcess()
315 .get());
[email protected]8915f342011-08-29 22:14:37316}
317
[email protected]734bcec2012-10-08 20:29:05318void WebstoreStandaloneInstaller::OnWebstoreResponseParseFailure(
[email protected]8915f342011-08-29 22:14:37319 const std::string& error) {
[email protected]e263a6b62014-06-05 23:19:49320 OnWebStoreDataFetcherDone();
[email protected]9c7b3092014-06-21 01:19:03321 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE, error);
[email protected]8915f342011-08-29 22:14:37322}
323
[email protected]734bcec2012-10-08 20:29:05324void WebstoreStandaloneInstaller::OnWebstoreParseSuccess(
[email protected]98e4e522011-10-25 13:00:16325 const std::string& id,
[email protected]8915f342011-08-29 22:14:37326 const SkBitmap& icon,
327 base::DictionaryValue* manifest) {
[email protected]d44ec7b2013-03-15 04:34:34328 CHECK_EQ(id_, id);
329
330 if (!CheckRequestorAlive()) {
[email protected]9c7b3092014-06-21 01:19:03331 CompleteInstall(webstore_install::ABORTED, std::string());
[email protected]2fd920fb2011-09-08 23:33:00332 return;
333 }
334
[email protected]8915f342011-08-29 22:14:37335 manifest_.reset(manifest);
336 icon_ = icon;
337
[email protected]9c7b3092014-06-21 01:19:03338 OnManifestParsed();
[email protected]8915f342011-08-29 22:14:37339}
340
[email protected]734bcec2012-10-08 20:29:05341void WebstoreStandaloneInstaller::OnWebstoreParseFailure(
[email protected]98e4e522011-10-25 13:00:16342 const std::string& id,
[email protected]8915f342011-08-29 22:14:37343 InstallHelperResultCode result_code,
344 const std::string& error_message) {
[email protected]ced522c2014-07-23 20:23:59345 webstore_install::Result install_result = webstore_install::OTHER_ERROR;
[email protected]9c7b3092014-06-21 01:19:03346 switch (result_code) {
347 case WebstoreInstallHelper::Delegate::MANIFEST_ERROR:
348 install_result = webstore_install::INVALID_MANIFEST;
349 break;
350 case WebstoreInstallHelper::Delegate::ICON_ERROR:
351 install_result = webstore_install::ICON_ERROR;
352 break;
353 default:
354 break;
355 }
356
357 CompleteInstall(install_result, error_message);
[email protected]8915f342011-08-29 22:14:37358}
359
[email protected]734bcec2012-10-08 20:29:05360void WebstoreStandaloneInstaller::OnExtensionInstallSuccess(
361 const std::string& id) {
[email protected]cb08ba22011-10-19 21:41:40362 CHECK_EQ(id_, id);
[email protected]9c7b3092014-06-21 01:19:03363 CompleteInstall(webstore_install::SUCCESS, std::string());
[email protected]cb08ba22011-10-19 21:41:40364}
365
[email protected]734bcec2012-10-08 20:29:05366void WebstoreStandaloneInstaller::OnExtensionInstallFailure(
[email protected]bcd1eaf72012-10-03 05:42:29367 const std::string& id,
368 const std::string& error,
[email protected]9c7b3092014-06-21 01:19:03369 WebstoreInstaller::FailureReason reason) {
[email protected]cb08ba22011-10-19 21:41:40370 CHECK_EQ(id_, id);
[email protected]cb08ba22011-10-19 21:41:40371
[email protected]ced522c2014-07-23 20:23:59372 webstore_install::Result install_result = webstore_install::OTHER_ERROR;
[email protected]9c7b3092014-06-21 01:19:03373 switch (reason) {
374 case WebstoreInstaller::FAILURE_REASON_CANCELLED:
375 install_result = webstore_install::USER_CANCELLED;
376 break;
377 case WebstoreInstaller::FAILURE_REASON_DEPENDENCY_NOT_FOUND:
378 case WebstoreInstaller::FAILURE_REASON_DEPENDENCY_NOT_SHARED_MODULE:
379 install_result = webstore_install::MISSING_DEPENDENCIES;
380 break;
381 default:
382 break;
[email protected]d44ec7b2013-03-15 04:34:34383 }
[email protected]d44ec7b2013-03-15 04:34:34384
[email protected]9c7b3092014-06-21 01:19:03385 CompleteInstall(install_result, error);
[email protected]8915f342011-08-29 22:14:37386}
[email protected]5f2a4752012-04-27 22:18:58387
[email protected]e263a6b62014-06-05 23:19:49388void WebstoreStandaloneInstaller::ShowInstallUI() {
dchengc7047942014-08-26 05:05:31389 scoped_refptr<const Extension> localized_extension =
390 GetLocalizedExtensionForDisplay();
dcheng40eae712014-08-27 16:56:10391 if (!localized_extension.get()) {
rdevlin.cronind30a8bd2016-06-30 16:02:29392 CompleteInstall(webstore_install::INVALID_MANIFEST,
393 webstore_install::kInvalidManifestError);
[email protected]d44ec7b2013-03-15 04:34:34394 return;
[email protected]5f2a4752012-04-27 22:18:58395 }
[email protected]5f2a4752012-04-27 22:18:58396
[email protected]f8b23b42013-06-27 20:12:14397 install_ui_ = CreateInstallUI();
rdevlin.croninf84cab72015-12-12 03:45:23398 install_ui_->ShowDialog(
rdevlin.cronin41593052016-01-08 01:40:12399 base::Bind(&WebstoreStandaloneInstaller::OnInstallPromptDone, this),
400 localized_extension.get(), &icon_, std::move(install_prompt_),
rdevlin.croninf84cab72015-12-12 03:45:23401 ExtensionInstallPrompt::GetDefaultShowDialogCallback());
[email protected]5f2a4752012-04-27 22:18:58402}
[email protected]3d61a7f2012-07-12 19:11:25403
[email protected]e263a6b62014-06-05 23:19:49404void WebstoreStandaloneInstaller::OnWebStoreDataFetcherDone() {
405 // An instance of this class is passed in as a delegate for the
406 // WebstoreInstallHelper, ExtensionInstallPrompt and WebstoreInstaller, and
407 // therefore needs to remain alive until they are done. Clear the webstore
408 // data fetcher to avoid calling Release in AbortInstall while any of these
409 // operations are in progress.
410 webstore_data_fetcher_.reset();
411}
412
[email protected]3d61a7f2012-07-12 19:11:25413} // namespace extensions