blob: ac7f2f227c50f0000d7fea7148f56978fd1e499d [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]453ac122014-07-28 03:32:1314#include "chrome/browser/extensions/extension_install_ui_util.h"
[email protected]655b2b1a2011-10-13 17:13:0615#include "chrome/browser/extensions/extension_service.h"
[email protected]773272b2014-07-18 05:48:3516#include "chrome/browser/extensions/install_tracker.h"
[email protected]7b3941052013-02-13 01:21:5917#include "chrome/browser/extensions/webstore_data_fetcher.h"
[email protected]8915f342011-08-29 22:14:3718#include "chrome/browser/profiles/profile.h"
[email protected]fdd28372014-08-21 02:27:2619#include "components/crx_file/id_util.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_));
72 webstore_data_fetcher_->Start();
[email protected]8915f342011-08-29 22:14:3773}
74
[email protected]9c7b3092014-06-21 01:19:0375//
76// Private interface implementation.
77//
78
79WebstoreStandaloneInstaller::~WebstoreStandaloneInstaller() {
80}
81
rdevlin.cronin5f6b69d2014-09-20 01:23:3582void WebstoreStandaloneInstaller::RunCallback(bool success,
83 const std::string& error,
84 webstore_install::Result result) {
85 callback_.Run(success, error, result);
86}
87
[email protected]9c7b3092014-06-21 01:19:0388void WebstoreStandaloneInstaller::AbortInstall() {
89 callback_.Reset();
90 // Abort any in-progress fetches.
91 if (webstore_data_fetcher_) {
92 webstore_data_fetcher_.reset();
[email protected]773272b2014-07-18 05:48:3593 scoped_active_install_.reset();
[email protected]9c7b3092014-06-21 01:19:0394 Release(); // Matches the AddRef in BeginInstall.
95 }
96}
97
[email protected]773272b2014-07-18 05:48:3598bool WebstoreStandaloneInstaller::EnsureUniqueInstall(
99 webstore_install::Result* reason,
100 std::string* error) {
101 InstallTracker* tracker = InstallTracker::Get(profile_);
102 DCHECK(tracker);
103
104 const ActiveInstallData* existing_install_data =
105 tracker->GetActiveInstall(id_);
106 if (existing_install_data) {
benwellscb4422c12015-10-13 23:38:46107 *reason = webstore_install::INSTALL_IN_PROGRESS;
rdevlin.cronind30a8bd2016-06-30 16:02:29108 *error = webstore_install::kInstallInProgressError;
[email protected]773272b2014-07-18 05:48:35109 return false;
110 }
111
112 ActiveInstallData install_data(id_);
113 InitInstallData(&install_data);
114 scoped_active_install_.reset(new ScopedActiveInstall(tracker, install_data));
115 return true;
116}
117
[email protected]9c7b3092014-06-21 01:19:03118void WebstoreStandaloneInstaller::CompleteInstall(
119 webstore_install::Result result,
120 const std::string& error) {
[email protected]773272b2014-07-18 05:48:35121 scoped_active_install_.reset();
[email protected]9c7b3092014-06-21 01:19:03122 if (!callback_.is_null())
[email protected]ced522c2014-07-23 20:23:59123 callback_.Run(result == webstore_install::SUCCESS, error, result);
[email protected]9c7b3092014-06-21 01:19:03124 Release(); // Matches the AddRef in BeginInstall.
125}
126
127void WebstoreStandaloneInstaller::ProceedWithInstallPrompt() {
128 install_prompt_ = CreateInstallPrompt();
dchengc7047942014-08-26 05:05:31129 if (install_prompt_.get()) {
[email protected]9c7b3092014-06-21 01:19:03130 ShowInstallUI();
rdevlin.cronin41593052016-01-08 01:40:12131 // Control flow finishes up in OnInstallPromptDone().
[email protected]9c7b3092014-06-21 01:19:03132 } else {
rdevlin.cronin41593052016-01-08 01:40:12133 OnInstallPromptDone(ExtensionInstallPrompt::Result::ACCEPTED);
[email protected]9c7b3092014-06-21 01:19:03134 }
135}
136
137scoped_refptr<const Extension>
138WebstoreStandaloneInstaller::GetLocalizedExtensionForDisplay() {
139 if (!localized_extension_for_display_.get()) {
140 DCHECK(manifest_.get());
141 if (!manifest_.get())
142 return NULL;
143
144 std::string error;
145 localized_extension_for_display_ =
146 ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
147 manifest_.get(),
148 Extension::REQUIRE_KEY | Extension::FROM_WEBSTORE,
149 id_,
150 localized_name_,
151 localized_description_,
152 &error);
153 }
154 return localized_extension_for_display_.get();
155}
156
[email protected]773272b2014-07-18 05:48:35157void WebstoreStandaloneInstaller::InitInstallData(
158 ActiveInstallData* install_data) const {
159 // Default implementation sets no properties.
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() {
dchengc963c7142016-04-08 03:55:22168 return base::WrapUnique(new 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_,
176 std::unique_ptr<base::DictionaryValue>(manifest_.get()->DeepCopy()),
[email protected]ce35418b2013-11-25 01:22:33177 true));
178 approval->skip_post_install_ui = !ShouldShowPostInstallUI();
179 approval->use_app_installed_bubble = ShouldShowAppInstalledBubble();
180 approval->installing_icon = gfx::ImageSkia::CreateFrom1xBitmap(icon_);
dcheng1fc00f12015-12-26 22:18:03181 return approval;
[email protected]ce35418b2013-11-25 01:22:33182}
183
rdevlin.cronin41593052016-01-08 01:40:12184void WebstoreStandaloneInstaller::OnInstallPromptDone(
185 ExtensionInstallPrompt::Result result) {
186 if (result == ExtensionInstallPrompt::Result::USER_CANCELED) {
rdevlin.cronind30a8bd2016-06-30 16:02:29187 CompleteInstall(webstore_install::USER_CANCELLED,
188 webstore_install::kUserCancelledError);
rdevlin.cronin41593052016-01-08 01:40:12189 return;
190 }
191
192 if (result == ExtensionInstallPrompt::Result::ABORTED ||
193 !CheckRequestorAlive()) {
rdevlin.cronin5f6b69d2014-09-20 01:23:35194 CompleteInstall(webstore_install::ABORTED, std::string());
195 return;
196 }
197
rdevlin.cronin41593052016-01-08 01:40:12198 DCHECK(result == ExtensionInstallPrompt::Result::ACCEPTED);
199
dchengc963c7142016-04-08 03:55:22200 std::unique_ptr<WebstoreInstaller::Approval> approval = CreateApproval();
rdevlin.cronin5f6b69d2014-09-20 01:23:35201
202 ExtensionService* extension_service =
203 ExtensionSystem::Get(profile_)->extension_service();
204 const Extension* installed_extension =
205 extension_service->GetExtensionById(id_, true /* include disabled */);
206 if (installed_extension) {
207 std::string install_message;
208 webstore_install::Result install_result = webstore_install::SUCCESS;
209 bool done = true;
210
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
221 if (done) {
222 CompleteInstall(install_result, install_message);
223 return;
224 }
225 }
226
dcheng1fc00f12015-12-26 22:18:03227 scoped_refptr<WebstoreInstaller> installer =
228 new WebstoreInstaller(profile_, this, GetWebContents(), id_,
229 std::move(approval), install_source_);
rdevlin.cronin5f6b69d2014-09-20 01:23:35230 installer->Start();
231}
232
[email protected]7b3941052013-02-13 01:21:59233void WebstoreStandaloneInstaller::OnWebstoreRequestFailure() {
[email protected]e263a6b62014-06-05 23:19:49234 OnWebStoreDataFetcherDone();
[email protected]9c7b3092014-06-21 01:19:03235 CompleteInstall(webstore_install::WEBSTORE_REQUEST_ERROR,
rdevlin.cronind30a8bd2016-06-30 16:02:29236 webstore_install::kWebstoreRequestError);
[email protected]8915f342011-08-29 22:14:37237}
238
[email protected]734bcec2012-10-08 20:29:05239void WebstoreStandaloneInstaller::OnWebstoreResponseParseSuccess(
dchengc963c7142016-04-08 03:55:22240 std::unique_ptr<base::DictionaryValue> webstore_data) {
[email protected]e263a6b62014-06-05 23:19:49241 OnWebStoreDataFetcherDone();
242
[email protected]d44ec7b2013-03-15 04:34:34243 if (!CheckRequestorAlive()) {
[email protected]9c7b3092014-06-21 01:19:03244 CompleteInstall(webstore_install::ABORTED, std::string());
[email protected]4693243e2011-09-09 23:52:37245 return;
246 }
247
[email protected]d44ec7b2013-03-15 04:34:34248 std::string error;
[email protected]8915f342011-08-29 22:14:37249
[email protected]d44ec7b2013-03-15 04:34:34250 if (!CheckInlineInstallPermitted(*webstore_data, &error)) {
[email protected]9c7b3092014-06-21 01:19:03251 CompleteInstall(webstore_install::NOT_PERMITTED, error);
[email protected]8915f342011-08-29 22:14:37252 return;
253 }
254
[email protected]d44ec7b2013-03-15 04:34:34255 if (!CheckRequestorPermitted(*webstore_data, &error)) {
[email protected]9c7b3092014-06-21 01:19:03256 CompleteInstall(webstore_install::NOT_PERMITTED, error);
[email protected]dd5161a2011-09-14 17:40:17257 return;
258 }
259
260 // Manifest, number of users, average rating and rating count are required.
261 std::string manifest;
262 if (!webstore_data->GetString(kManifestKey, &manifest) ||
263 !webstore_data->GetString(kUsersKey, &localized_user_count_) ||
[email protected]5fdbd6f2011-09-01 17:33:04264 !webstore_data->GetDouble(kAverageRatingKey, &average_rating_) ||
265 !webstore_data->GetInteger(kRatingCountKey, &rating_count_)) {
[email protected]9c7b3092014-06-21 01:19:03266 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29267 webstore_install::kInvalidWebstoreResponseError);
[email protected]5fdbd6f2011-09-01 17:33:04268 return;
269 }
270
[email protected]dcde34b32013-07-31 02:28:45271 // Optional.
272 show_user_count_ = true;
273 webstore_data->GetBoolean(kShowUserCountKey, &show_user_count_);
274
[email protected]c82da8c42012-06-08 19:49:11275 if (average_rating_ < ExtensionInstallPrompt::kMinExtensionRating ||
276 average_rating_ > ExtensionInstallPrompt::kMaxExtensionRating) {
[email protected]9c7b3092014-06-21 01:19:03277 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29278 webstore_install::kInvalidWebstoreResponseError);
[email protected]5fdbd6f2011-09-01 17:33:04279 return;
280 }
281
282 // Localized name and description are optional.
283 if ((webstore_data->HasKey(kLocalizedNameKey) &&
284 !webstore_data->GetString(kLocalizedNameKey, &localized_name_)) ||
285 (webstore_data->HasKey(kLocalizedDescriptionKey) &&
286 !webstore_data->GetString(
287 kLocalizedDescriptionKey, &localized_description_))) {
[email protected]9c7b3092014-06-21 01:19:03288 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29289 webstore_install::kInvalidWebstoreResponseError);
[email protected]8915f342011-08-29 22:14:37290 return;
291 }
292
293 // Icon URL is optional.
294 GURL icon_url;
295 if (webstore_data->HasKey(kIconUrlKey)) {
296 std::string icon_url_string;
297 if (!webstore_data->GetString(kIconUrlKey, &icon_url_string)) {
[email protected]9c7b3092014-06-21 01:19:03298 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29299 webstore_install::kInvalidWebstoreResponseError);
[email protected]8915f342011-08-29 22:14:37300 return;
301 }
302 icon_url = GURL(extension_urls::GetWebstoreLaunchURL()).Resolve(
303 icon_url_string);
304 if (!icon_url.is_valid()) {
[email protected]9c7b3092014-06-21 01:19:03305 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE,
rdevlin.cronind30a8bd2016-06-30 16:02:29306 webstore_install::kInvalidWebstoreResponseError);
[email protected]8915f342011-08-29 22:14:37307 return;
308 }
309 }
310
[email protected]d44ec7b2013-03-15 04:34:34311 // Assume ownership of webstore_data.
dcheng1fc00f12015-12-26 22:18:03312 webstore_data_ = std::move(webstore_data);
[email protected]a221ef092011-09-07 01:34:10313
[email protected]007b3f82013-04-09 08:46:45314 scoped_refptr<WebstoreInstallHelper> helper =
315 new WebstoreInstallHelper(this,
316 id_,
317 manifest,
[email protected]007b3f82013-04-09 08:46:45318 icon_url,
319 profile_->GetRequestContext());
[email protected]8915f342011-08-29 22:14:37320 // The helper will call us back via OnWebstoreParseSucces or
321 // OnWebstoreParseFailure.
322 helper->Start();
323}
324
[email protected]734bcec2012-10-08 20:29:05325void WebstoreStandaloneInstaller::OnWebstoreResponseParseFailure(
[email protected]8915f342011-08-29 22:14:37326 const std::string& error) {
[email protected]e263a6b62014-06-05 23:19:49327 OnWebStoreDataFetcherDone();
[email protected]9c7b3092014-06-21 01:19:03328 CompleteInstall(webstore_install::INVALID_WEBSTORE_RESPONSE, error);
[email protected]8915f342011-08-29 22:14:37329}
330
[email protected]734bcec2012-10-08 20:29:05331void WebstoreStandaloneInstaller::OnWebstoreParseSuccess(
[email protected]98e4e522011-10-25 13:00:16332 const std::string& id,
[email protected]8915f342011-08-29 22:14:37333 const SkBitmap& icon,
334 base::DictionaryValue* manifest) {
[email protected]d44ec7b2013-03-15 04:34:34335 CHECK_EQ(id_, id);
336
337 if (!CheckRequestorAlive()) {
[email protected]9c7b3092014-06-21 01:19:03338 CompleteInstall(webstore_install::ABORTED, std::string());
[email protected]2fd920fb2011-09-08 23:33:00339 return;
340 }
341
[email protected]8915f342011-08-29 22:14:37342 manifest_.reset(manifest);
343 icon_ = icon;
344
[email protected]9c7b3092014-06-21 01:19:03345 OnManifestParsed();
[email protected]8915f342011-08-29 22:14:37346}
347
[email protected]734bcec2012-10-08 20:29:05348void WebstoreStandaloneInstaller::OnWebstoreParseFailure(
[email protected]98e4e522011-10-25 13:00:16349 const std::string& id,
[email protected]8915f342011-08-29 22:14:37350 InstallHelperResultCode result_code,
351 const std::string& error_message) {
[email protected]ced522c2014-07-23 20:23:59352 webstore_install::Result install_result = webstore_install::OTHER_ERROR;
[email protected]9c7b3092014-06-21 01:19:03353 switch (result_code) {
354 case WebstoreInstallHelper::Delegate::MANIFEST_ERROR:
355 install_result = webstore_install::INVALID_MANIFEST;
356 break;
357 case WebstoreInstallHelper::Delegate::ICON_ERROR:
358 install_result = webstore_install::ICON_ERROR;
359 break;
360 default:
361 break;
362 }
363
364 CompleteInstall(install_result, error_message);
[email protected]8915f342011-08-29 22:14:37365}
366
[email protected]734bcec2012-10-08 20:29:05367void WebstoreStandaloneInstaller::OnExtensionInstallSuccess(
368 const std::string& id) {
[email protected]cb08ba22011-10-19 21:41:40369 CHECK_EQ(id_, id);
[email protected]9c7b3092014-06-21 01:19:03370 CompleteInstall(webstore_install::SUCCESS, std::string());
[email protected]cb08ba22011-10-19 21:41:40371}
372
[email protected]734bcec2012-10-08 20:29:05373void WebstoreStandaloneInstaller::OnExtensionInstallFailure(
[email protected]bcd1eaf72012-10-03 05:42:29374 const std::string& id,
375 const std::string& error,
[email protected]9c7b3092014-06-21 01:19:03376 WebstoreInstaller::FailureReason reason) {
[email protected]cb08ba22011-10-19 21:41:40377 CHECK_EQ(id_, id);
[email protected]cb08ba22011-10-19 21:41:40378
[email protected]ced522c2014-07-23 20:23:59379 webstore_install::Result install_result = webstore_install::OTHER_ERROR;
[email protected]9c7b3092014-06-21 01:19:03380 switch (reason) {
381 case WebstoreInstaller::FAILURE_REASON_CANCELLED:
382 install_result = webstore_install::USER_CANCELLED;
383 break;
384 case WebstoreInstaller::FAILURE_REASON_DEPENDENCY_NOT_FOUND:
385 case WebstoreInstaller::FAILURE_REASON_DEPENDENCY_NOT_SHARED_MODULE:
386 install_result = webstore_install::MISSING_DEPENDENCIES;
387 break;
388 default:
389 break;
[email protected]d44ec7b2013-03-15 04:34:34390 }
[email protected]d44ec7b2013-03-15 04:34:34391
[email protected]9c7b3092014-06-21 01:19:03392 CompleteInstall(install_result, error);
[email protected]8915f342011-08-29 22:14:37393}
[email protected]5f2a4752012-04-27 22:18:58394
[email protected]e263a6b62014-06-05 23:19:49395void WebstoreStandaloneInstaller::ShowInstallUI() {
dchengc7047942014-08-26 05:05:31396 scoped_refptr<const Extension> localized_extension =
397 GetLocalizedExtensionForDisplay();
dcheng40eae712014-08-27 16:56:10398 if (!localized_extension.get()) {
rdevlin.cronind30a8bd2016-06-30 16:02:29399 CompleteInstall(webstore_install::INVALID_MANIFEST,
400 webstore_install::kInvalidManifestError);
[email protected]d44ec7b2013-03-15 04:34:34401 return;
[email protected]5f2a4752012-04-27 22:18:58402 }
[email protected]5f2a4752012-04-27 22:18:58403
[email protected]f8b23b42013-06-27 20:12:14404 install_ui_ = CreateInstallUI();
rdevlin.croninf84cab72015-12-12 03:45:23405 install_ui_->ShowDialog(
rdevlin.cronin41593052016-01-08 01:40:12406 base::Bind(&WebstoreStandaloneInstaller::OnInstallPromptDone, this),
407 localized_extension.get(), &icon_, std::move(install_prompt_),
rdevlin.croninf84cab72015-12-12 03:45:23408 ExtensionInstallPrompt::GetDefaultShowDialogCallback());
[email protected]5f2a4752012-04-27 22:18:58409}
[email protected]3d61a7f2012-07-12 19:11:25410
[email protected]e263a6b62014-06-05 23:19:49411void WebstoreStandaloneInstaller::OnWebStoreDataFetcherDone() {
412 // An instance of this class is passed in as a delegate for the
413 // WebstoreInstallHelper, ExtensionInstallPrompt and WebstoreInstaller, and
414 // therefore needs to remain alive until they are done. Clear the webstore
415 // data fetcher to avoid calling Release in AbortInstall while any of these
416 // operations are in progress.
417 webstore_data_fetcher_.reset();
418}
419
[email protected]3d61a7f2012-07-12 19:11:25420} // namespace extensions