blob: cc15d80b95a768fa5543084eeb29339e2149f795 [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
dchengc963c7142016-04-08 03:55:229#include "base/memory/ptr_util.h"
[email protected]8915f342011-08-29 22:14:3710#include "base/values.h"
[email protected]9c7b3092014-06-21 01:19:0311#include "base/version.h"
[email protected]8915f342011-08-29 22:14:3712#include "chrome/browser/extensions/crx_installer.h"
[email protected]d44ec7b2013-03-15 04:34:3413#include "chrome/browser/extensions/extension_install_prompt.h"
[email protected]655b2b1a2011-10-13 17:13:0614#include "chrome/browser/extensions/extension_service.h"
[email protected]773272b2014-07-18 05:48:3515#include "chrome/browser/extensions/install_tracker.h"
[email protected]7b3941052013-02-13 01:21:5916#include "chrome/browser/extensions/webstore_data_fetcher.h"
[email protected]8915f342011-08-29 22:14:3717#include "chrome/browser/profiles/profile.h"
[email protected]fdd28372014-08-21 02:27:2618#include "components/crx_file/id_util.h"
Mark Pilgrim445bb782017-12-08 19:47:1219#include "content/public/browser/storage_partition.h"
[email protected]10c2d692012-05-11 05:32:2320#include "content/public/browser/web_contents.h"
[email protected]489db0842014-01-22 18:20:0321#include "extensions/browser/extension_prefs.h"
[email protected]760f743b2014-05-28 13:52:0222#include "extensions/browser/extension_registry.h"
[email protected]59b0e602014-01-30 00:41:2423#include "extensions/browser/extension_system.h"
[email protected]e4452d32013-11-15 23:07:4124#include "extensions/common/extension.h"
rockot90659852014-09-18 19:31:5225#include "extensions/common/extension_urls.h"
[email protected]a6483d22013-07-03 22:11:0026#include "url/gurl.h"
[email protected]8915f342011-08-29 22:14:3727
[email protected]26b5e322011-12-23 01:36:4728using content::WebContents;
[email protected]631bb742011-11-02 11:29:3929
[email protected]3d61a7f2012-07-12 19:11:2530namespace extensions {
31
[email protected]734bcec2012-10-08 20:29:0532WebstoreStandaloneInstaller::WebstoreStandaloneInstaller(
[email protected]d44ec7b2013-03-15 04:34:3433 const std::string& webstore_item_id,
[email protected]c1b2d042013-02-23 00:31:0434 Profile* profile,
[email protected]c1b2d042013-02-23 00:31:0435 const Callback& callback)
[email protected]d44ec7b2013-03-15 04:34:3436 : id_(webstore_item_id),
[email protected]d2a639e2012-09-17 07:41:2137 callback_(callback),
[email protected]d44ec7b2013-03-15 04:34:3438 profile_(profile),
[email protected]084e35482013-09-25 02:46:1939 install_source_(WebstoreInstaller::INSTALL_SOURCE_INLINE),
[email protected]dcde34b32013-07-31 02:28:4540 show_user_count_(true),
[email protected]c7bf7452011-09-12 21:31:5041 average_rating_(0.0),
[email protected]5f2a4752012-04-27 22:18:5842 rating_count_(0) {
[email protected]c1b2d042013-02-23 00:31:0443}
44
[email protected]734bcec2012-10-08 20:29:0545void WebstoreStandaloneInstaller::BeginInstall() {
[email protected]3d6d676522013-10-14 20:44:5546 // Add a ref to keep this alive for WebstoreDataFetcher.
47 // All code paths from here eventually lead to either CompleteInstall or
48 // AbortInstall, which both release this ref.
49 AddRef();
[email protected]8915f342011-08-29 22:14:3750
[email protected]fdd28372014-08-21 02:27:2651 if (!crx_file::id_util::IdIsValid(id_)) {
rdevlin.cronind30a8bd2016-06-30 16:02:2952 CompleteInstall(webstore_install::INVALID_ID,
53 webstore_install::kInvalidWebstoreItemId);
[email protected]8915f342011-08-29 22:14:3754 return;
55 }
56
[email protected]ced522c2014-07-23 20:23:5957 webstore_install::Result result = webstore_install::OTHER_ERROR;
[email protected]773272b2014-07-18 05:48:3558 std::string error;
59 if (!EnsureUniqueInstall(&result, &error)) {
60 CompleteInstall(result, error);
61 return;
62 }
63
[email protected]b4574c02011-11-17 06:19:1364 // Use the requesting page as the referrer both since that is more correct
65 // (it is the page that caused this request to happen) and so that we can
66 // track top sites that trigger inline install requests.
[email protected]7b3941052013-02-13 01:21:5967 webstore_data_fetcher_.reset(new WebstoreDataFetcher(
68 this,
[email protected]c1b2d042013-02-23 00:31:0469 profile_->GetRequestContext(),
[email protected]d44ec7b2013-03-15 04:34:3470 GetRequestorURL(),
[email protected]7b3941052013-02-13 01:21:5971 id_));
robertshield1fc1a4a2017-02-01 15:18:3372
73 std::string json_post_data = GetJsonPostData();
74 if (!json_post_data.empty())
75 webstore_data_fetcher_->SetJsonPostData(json_post_data);
76
[email protected]7b3941052013-02-13 01:21:5977 webstore_data_fetcher_->Start();
[email protected]8915f342011-08-29 22:14:3778}
79
[email protected]9c7b3092014-06-21 01:19:0380//
81// Private interface implementation.
82//
83
84WebstoreStandaloneInstaller::~WebstoreStandaloneInstaller() {
85}
86
rdevlin.cronin5f6b69d2014-09-20 01:23:3587void WebstoreStandaloneInstaller::RunCallback(bool success,
88 const std::string& error,
89 webstore_install::Result result) {
90 callback_.Run(success, error, result);
91}
92
[email protected]9c7b3092014-06-21 01:19:0393void WebstoreStandaloneInstaller::AbortInstall() {
94 callback_.Reset();
95 // Abort any in-progress fetches.
96 if (webstore_data_fetcher_) {
97 webstore_data_fetcher_.reset();
[email protected]773272b2014-07-18 05:48:3598 scoped_active_install_.reset();
[email protected]9c7b3092014-06-21 01:19:0399 Release(); // Matches the AddRef in BeginInstall.
100 }
101}
102
[email protected]773272b2014-07-18 05:48:35103bool WebstoreStandaloneInstaller::EnsureUniqueInstall(
104 webstore_install::Result* reason,
105 std::string* error) {
106 InstallTracker* tracker = InstallTracker::Get(profile_);
107 DCHECK(tracker);
108
109 const ActiveInstallData* existing_install_data =
110 tracker->GetActiveInstall(id_);
111 if (existing_install_data) {
benwellscb4422c12015-10-13 23:38:46112 *reason = webstore_install::INSTALL_IN_PROGRESS;
rdevlin.cronind30a8bd2016-06-30 16:02:29113 *error = webstore_install::kInstallInProgressError;
[email protected]773272b2014-07-18 05:48:35114 return false;
115 }
116
117 ActiveInstallData install_data(id_);
[email protected]773272b2014-07-18 05:48:35118 scoped_active_install_.reset(new ScopedActiveInstall(tracker, install_data));
119 return true;
120}
121
[email protected]9c7b3092014-06-21 01:19:03122void WebstoreStandaloneInstaller::CompleteInstall(
123 webstore_install::Result result,
124 const std::string& error) {
[email protected]773272b2014-07-18 05:48:35125 scoped_active_install_.reset();
[email protected]9c7b3092014-06-21 01:19:03126 if (!callback_.is_null())
[email protected]ced522c2014-07-23 20:23:59127 callback_.Run(result == webstore_install::SUCCESS, error, result);
[email protected]9c7b3092014-06-21 01:19:03128 Release(); // Matches the AddRef in BeginInstall.
129}
130
131void WebstoreStandaloneInstaller::ProceedWithInstallPrompt() {
132 install_prompt_ = CreateInstallPrompt();
dchengc7047942014-08-26 05:05:31133 if (install_prompt_.get()) {
[email protected]9c7b3092014-06-21 01:19:03134 ShowInstallUI();
rdevlin.cronin41593052016-01-08 01:40:12135 // Control flow finishes up in OnInstallPromptDone().
[email protected]9c7b3092014-06-21 01:19:03136 } else {
rdevlin.cronin41593052016-01-08 01:40:12137 OnInstallPromptDone(ExtensionInstallPrompt::Result::ACCEPTED);
[email protected]9c7b3092014-06-21 01:19:03138 }
139}
140
141scoped_refptr<const Extension>
142WebstoreStandaloneInstaller::GetLocalizedExtensionForDisplay() {
143 if (!localized_extension_for_display_.get()) {
144 DCHECK(manifest_.get());
145 if (!manifest_.get())
146 return NULL;
147
148 std::string error;
149 localized_extension_for_display_ =
150 ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
151 manifest_.get(),
152 Extension::REQUIRE_KEY | Extension::FROM_WEBSTORE,
153 id_,
154 localized_name_,
155 localized_description_,
156 &error);
157 }
158 return localized_extension_for_display_.get();
159}
160
robertshield1fc1a4a2017-02-01 15:18:33161std::string WebstoreStandaloneInstaller::GetJsonPostData() {
162 return std::string();
163}
164
[email protected]9c7b3092014-06-21 01:19:03165void WebstoreStandaloneInstaller::OnManifestParsed() {
166 ProceedWithInstallPrompt();
[email protected]ce35418b2013-11-25 01:22:33167}
168
dchengc963c7142016-04-08 03:55:22169std::unique_ptr<ExtensionInstallPrompt>
[email protected]f8b23b42013-06-27 20:12:14170WebstoreStandaloneInstaller::CreateInstallUI() {
ricea91d6fc122016-08-30 08:47:14171 return base::MakeUnique<ExtensionInstallPrompt>(GetWebContents());
[email protected]f8b23b42013-06-27 20:12:14172}
173
dchengc963c7142016-04-08 03:55:22174std::unique_ptr<WebstoreInstaller::Approval>
[email protected]ce35418b2013-11-25 01:22:33175WebstoreStandaloneInstaller::CreateApproval() const {
dchengc963c7142016-04-08 03:55:22176 std::unique_ptr<WebstoreInstaller::Approval> approval(
[email protected]ce35418b2013-11-25 01:22:33177 WebstoreInstaller::Approval::CreateWithNoInstallPrompt(
dchengc963c7142016-04-08 03:55:22178 profile_, id_,
rdevlin.cronin165732a42016-07-18 22:25:08179 std::unique_ptr<base::DictionaryValue>(manifest_->DeepCopy()), true));
[email protected]ce35418b2013-11-25 01:22:33180 approval->skip_post_install_ui = !ShouldShowPostInstallUI();
181 approval->use_app_installed_bubble = ShouldShowAppInstalledBubble();
182 approval->installing_icon = gfx::ImageSkia::CreateFrom1xBitmap(icon_);
dcheng1fc00f12015-12-26 22:18:03183 return approval;
[email protected]ce35418b2013-11-25 01:22:33184}
185
rdevlin.cronin41593052016-01-08 01:40:12186void WebstoreStandaloneInstaller::OnInstallPromptDone(
187 ExtensionInstallPrompt::Result result) {
188 if (result == ExtensionInstallPrompt::Result::USER_CANCELED) {
rdevlin.cronind30a8bd2016-06-30 16:02:29189 CompleteInstall(webstore_install::USER_CANCELLED,
190 webstore_install::kUserCancelledError);
rdevlin.cronin41593052016-01-08 01:40:12191 return;
192 }
193
194 if (result == ExtensionInstallPrompt::Result::ABORTED ||
195 !CheckRequestorAlive()) {
rdevlin.cronin5f6b69d2014-09-20 01:23:35196 CompleteInstall(webstore_install::ABORTED, std::string());
197 return;
198 }
199
rdevlin.cronin41593052016-01-08 01:40:12200 DCHECK(result == ExtensionInstallPrompt::Result::ACCEPTED);
201
dchengc963c7142016-04-08 03:55:22202 std::unique_ptr<WebstoreInstaller::Approval> approval = CreateApproval();
rdevlin.cronin5f6b69d2014-09-20 01:23:35203
204 ExtensionService* extension_service =
205 ExtensionSystem::Get(profile_)->extension_service();
206 const Extension* installed_extension =
207 extension_service->GetExtensionById(id_, true /* include disabled */);
208 if (installed_extension) {
209 std::string install_message;
210 webstore_install::Result install_result = webstore_install::SUCCESS;
rdevlin.cronin5f6b69d2014-09-20 01:23:35211
212 if (ExtensionPrefs::Get(profile_)->IsExtensionBlacklisted(id_)) {
213 // Don't install a blacklisted extension.
214 install_result = webstore_install::BLACKLISTED;
rdevlin.cronind30a8bd2016-06-30 16:02:29215 install_message = webstore_install::kExtensionIsBlacklisted;
rdevlin.cronin5f6b69d2014-09-20 01:23:35216 } else if (!extension_service->IsExtensionEnabled(id_)) {
217 // If the extension is installed but disabled, and not blacklisted,
218 // enable it.
219 extension_service->EnableExtension(id_);
220 } // else extension is installed and enabled; no work to be done.
221
lazyboy39a52e7c2017-04-06 18:18:38222 CompleteInstall(install_result, install_message);
223 return;
rdevlin.cronin5f6b69d2014-09-20 01:23:35224 }
225
dcheng1fc00f12015-12-26 22:18:03226 scoped_refptr<WebstoreInstaller> installer =
227 new WebstoreInstaller(profile_, this, GetWebContents(), id_,
228 std::move(approval), install_source_);
rdevlin.cronin5f6b69d2014-09-20 01:23:35229 installer->Start();
230}
231
[email protected]7b3941052013-02-13 01:21:59232void WebstoreStandaloneInstaller::OnWebstoreRequestFailure() {
[email protected]e263a6b62014-06-05 23:19:49233 OnWebStoreDataFetcherDone();
[email protected]9c7b3092014-06-21 01:19:03234 CompleteInstall(webstore_install::WEBSTORE_REQUEST_ERROR,
rdevlin.cronind30a8bd2016-06-30 16:02:29235 webstore_install::kWebstoreRequestError);
[email protected]8915f342011-08-29 22:14:37236}
237
[email protected]734bcec2012-10-08 20:29:05238void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess(
dchengc963c7142016-04-08 03:55:22239 std::unique_ptr<base::DictionaryValue> webstore_data) {
[email protected]e263a6b62014-06-05 23:19:49240 OnWebStoreDataFetcherDone();
241
[email protected]d44ec7b2013-03-15 04:34:34242 if (!CheckRequestorAlive()) {
[email protected]9c7b3092014-06-21 01:19:03243 CompleteInstall(webstore_install::ABORTED, std::string());
[email protected]4693243e2011-09-09 23:52:37244 return;
245 }
246
[email protected]d44ec7b2013-03-15 04:34:34247 std::string error;
[email protected]8915f342011-08-29 22:14:37248
[email protected]d44ec7b2013-03-15 04:34:34249 if (!CheckInlineInstallPermitted(*webstore_data, &error)) {
[email protected]9c7b3092014-06-21 01:19:03250 CompleteInstall(webstore_install::NOT_PERMITTED, error);
[email protected]8915f342011-08-29 22:14:37251 return;
252 }
253
[email protected]d44ec7b2013-03-15 04:34:34254 if (!CheckRequestorPermitted(*webstore_data, &error)) {
[email protected]9c7b3092014-06-21 01:19:03255 CompleteInstall(webstore_install::NOT_PERMITTED, error);
[email protected]dd5161a2011-09-14 17:40:17256 return;
257 }
258
259 // Manifest, number of users, average rating and rating count are required.
260 std::string manifest;
261 if (!webstore_data->GetString(kManifestKey, &manifest) ||
262 !webstore_data->GetString(kUsersKey, &localized_user_count_) ||
[email protected]5fdbd6f2011-09-01 17:33:04263 !webstore_data->GetDouble(kAverageRatingKey, &average_rating_) ||
264 !webstore_data->GetInteger(kRatingCountKey, &rating_count_)) {
[email protected]9c7b3092014-06-21 01:19:03265 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29266 webstore_install::kInvalidWebstoreResponseError);
[email protected]5fdbd6f2011-09-01 17:33:04267 return;
268 }
269
[email protected]dcde34b32013-07-31 02:28:45270 // Optional.
271 show_user_count_ = true;
272 webstore_data->GetBoolean(kShowUserCountKey, &show_user_count_);
273
[email protected]c82da8c42012-06-08 19:49:11274 if (average_rating_ < ExtensionInstallPrompt::kMinExtensionRating ||
275 average_rating_ > ExtensionInstallPrompt::kMaxExtensionRating) {
[email protected]9c7b3092014-06-21 01:19:03276 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29277 webstore_install::kInvalidWebstoreResponseError);
[email protected]5fdbd6f2011-09-01 17:33:04278 return;
279 }
280
281 // Localized name and description are optional.
282 if ((webstore_data->HasKey(kLocalizedNameKey) &&
283 !webstore_data->GetString(kLocalizedNameKey, &localized_name_)) ||
284 (webstore_data->HasKey(kLocalizedDescriptionKey) &&
285 !webstore_data->GetString(
286 kLocalizedDescriptionKey, &localized_description_))) {
[email protected]9c7b3092014-06-21 01:19:03287 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29288 webstore_install::kInvalidWebstoreResponseError);
[email protected]8915f342011-08-29 22:14:37289 return;
290 }
291
292 // Icon URL is optional.
293 GURL icon_url;
294 if (webstore_data->HasKey(kIconUrlKey)) {
295 std::string icon_url_string;
296 if (!webstore_data->GetString(kIconUrlKey, &icon_url_string)) {
[email protected]9c7b3092014-06-21 01:19:03297 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29298 webstore_install::kInvalidWebstoreResponseError);
[email protected]8915f342011-08-29 22:14:37299 return;
300 }
csharrison5d1f2142016-11-22 20:25:47301 icon_url = extension_urls::GetWebstoreLaunchURL().Resolve(icon_url_string);
[email protected]8915f342011-08-29 22:14:37302 if (!icon_url.is_valid()) {
[email protected]9c7b3092014-06-21 01:19:03303 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29304 webstore_install::kInvalidWebstoreResponseError);
[email protected]8915f342011-08-29 22:14:37305 return;
306 }
307 }
308
[email protected]d44ec7b2013-03-15 04:34:34309 // Assume ownership of webstore_data.
dcheng1fc00f12015-12-26 22:18:03310 webstore_data_ = std::move(webstore_data);
[email protected]a221ef092011-09-07 01:34:10311
[email protected]007b3f82013-04-09 08:46:45312 scoped_refptr<WebstoreInstallHelper> helper =
Mark Pilgrim445bb782017-12-08 19:47:12313 new WebstoreInstallHelper(this, id_, manifest, icon_url);
thestig144c0c92017-05-18 05:58:02314 // The helper will call us back via OnWebstoreParseSuccess() or
315 // OnWebstoreParseFailure().
Mark Pilgrim445bb782017-12-08 19:47:12316 helper->Start(content::BrowserContext::GetDefaultStoragePartition(profile_)
317 ->GetURLLoaderFactoryForBrowserProcess());
[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