blob: 8f7199d2d56eeb31012957e74d0f351930d5963b [file] [log] [blame]
[email protected]2894a512014-06-26 19:03:561// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/external_install_error.h"
6
avia2f4804a2015-12-24 23:11:137#include <stddef.h>
dcheng1fc00f12015-12-26 22:18:038#include <utility>
avia2f4804a2015-12-24 23:11:139
[email protected]2894a512014-06-26 19:03:5610#include "base/bind.h"
fdoray283082bd2016-06-02 20:18:4611#include "base/location.h"
avia2f4804a2015-12-24 23:11:1312#include "base/macros.h"
probergebc529d62018-04-24 14:48:2613#include "base/metrics/field_trial_params.h"
rdevlin.croninb2daf2e42016-01-14 20:00:5414#include "base/metrics/histogram_macros.h"
fdoray283082bd2016-06-02 20:18:4615#include "base/single_thread_task_runner.h"
[email protected]2894a512014-06-26 19:03:5616#include "base/strings/utf_string_conversions.h"
fdoray283082bd2016-06-02 20:18:4617#include "base/threading/thread_task_runner_handle.h"
[email protected]2894a512014-06-26 19:03:5618#include "chrome/app/chrome_command_ids.h"
lazyboy0b9b30f2016-01-05 03:15:3719#include "chrome/browser/extensions/extension_install_error_menu_item_id_provider.h"
pkotwicz2f181782014-10-29 17:33:4520#include "chrome/browser/extensions/extension_install_prompt_show_params.h"
[email protected]2894a512014-06-26 19:03:5621#include "chrome/browser/extensions/extension_service.h"
probergebc529d62018-04-24 14:48:2622#include "chrome/browser/extensions/external_install_error_constants.h"
[email protected]2894a512014-06-26 19:03:5623#include "chrome/browser/extensions/external_install_manager.h"
24#include "chrome/browser/extensions/webstore_data_fetcher.h"
25#include "chrome/browser/profiles/profile.h"
26#include "chrome/browser/ui/browser.h"
27#include "chrome/browser/ui/browser_finder.h"
28#include "chrome/browser/ui/global_error/global_error.h"
29#include "chrome/browser/ui/global_error/global_error_service.h"
30#include "chrome/browser/ui/global_error/global_error_service_factory.h"
31#include "chrome/browser/ui/tabs/tab_strip_model.h"
probergebc529d62018-04-24 14:48:2632#include "chrome/common/chrome_features.h"
[email protected]af39f002014-08-22 10:18:1833#include "chrome/grit/generated_resources.h"
rdevlin.cronina1c3f1a2017-05-18 17:45:4634#include "components/keyed_service/content/browser_context_dependency_manager.h"
jamb84299e2016-04-12 16:58:5935#include "content/public/browser/storage_partition.h"
[email protected]2894a512014-06-26 19:03:5636#include "extensions/browser/extension_registry.h"
37#include "extensions/browser/extension_system.h"
[email protected]e43c61f2014-07-20 21:46:3438#include "extensions/browser/uninstall_reason.h"
[email protected]2894a512014-06-26 19:03:5639#include "extensions/common/constants.h"
40#include "extensions/common/extension.h"
[email protected]2894a512014-06-26 19:03:5641#include "ui/base/l10n/l10n_util.h"
42#include "ui/gfx/image/image.h"
rdevlin.cronin3fe4bd32016-01-12 18:45:4043#include "ui/gfx/image/image_skia.h"
[email protected]2894a512014-06-26 19:03:5644#include "ui/gfx/image/image_skia_operations.h"
45
46namespace extensions {
47
48namespace {
49
50// Return the menu label for a global error.
51base::string16 GetMenuItemLabel(const Extension* extension) {
52 if (!extension)
53 return base::string16();
54
55 int id = -1;
56 if (extension->is_app())
57 id = IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_APP;
58 else if (extension->is_theme())
59 id = IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_THEME;
60 else
61 id = IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_EXTENSION;
62
63 return l10n_util::GetStringFUTF16(id, base::UTF8ToUTF16(extension->name()));
64}
65
probergebc529d62018-04-24 14:48:2666ExternalInstallError::DefaultDialogButtonSetting
67MapDefaultButtonStringToSetting(const std::string& button_setting_string) {
68 if (button_setting_string == kDefaultDialogButtonSettingOk)
69 return ExternalInstallError::DIALOG_BUTTON_OK;
70 if (button_setting_string == kDefaultDialogButtonSettingCancel)
71 return ExternalInstallError::DIALOG_BUTTON_CANCEL;
72 if (button_setting_string == kDefaultDialogButtonSettingNoDefault)
73 return ExternalInstallError::NO_DEFAULT_DIALOG_BUTTON;
74
75 NOTREACHED() << "Unexpected default button string: " << button_setting_string;
76 return ExternalInstallError::NOT_SPECIFIED;
77}
78
[email protected]2894a512014-06-26 19:03:5679// A global error that spawns a dialog when the menu item is clicked.
80class ExternalInstallMenuAlert : public GlobalError {
81 public:
82 explicit ExternalInstallMenuAlert(ExternalInstallError* error);
dchengae36a4a2014-10-21 12:36:3683 ~ExternalInstallMenuAlert() override;
[email protected]2894a512014-06-26 19:03:5684
85 private:
86 // GlobalError implementation.
dchengae36a4a2014-10-21 12:36:3687 Severity GetSeverity() override;
88 bool HasMenuItem() override;
89 int MenuItemCommandID() override;
90 base::string16 MenuItemLabel() override;
91 void ExecuteMenuItem(Browser* browser) override;
92 bool HasBubbleView() override;
93 bool HasShownBubbleView() override;
94 void ShowBubbleView(Browser* browser) override;
95 GlobalErrorBubbleViewBase* GetBubbleView() override;
[email protected]2894a512014-06-26 19:03:5696
97 // The owning ExternalInstallError.
98 ExternalInstallError* error_;
99
lazyboy0b9b30f2016-01-05 03:15:37100 // Provides menu item id for GlobalError.
101 ExtensionInstallErrorMenuItemIdProvider id_provider_;
102
[email protected]2894a512014-06-26 19:03:56103 DISALLOW_COPY_AND_ASSIGN(ExternalInstallMenuAlert);
104};
105
106// A global error that spawns a bubble when the menu item is clicked.
107class ExternalInstallBubbleAlert : public GlobalErrorWithStandardBubble {
108 public:
rdevlin.cronin2e252692015-12-15 21:47:02109 ExternalInstallBubbleAlert(ExternalInstallError* error,
110 ExtensionInstallPrompt::Prompt* prompt);
dchengae36a4a2014-10-21 12:36:36111 ~ExternalInstallBubbleAlert() override;
[email protected]2894a512014-06-26 19:03:56112
113 private:
114 // GlobalError implementation.
dchengae36a4a2014-10-21 12:36:36115 Severity GetSeverity() override;
116 bool HasMenuItem() override;
117 int MenuItemCommandID() override;
118 base::string16 MenuItemLabel() override;
119 void ExecuteMenuItem(Browser* browser) override;
[email protected]2894a512014-06-26 19:03:56120
121 // GlobalErrorWithStandardBubble implementation.
dchengae36a4a2014-10-21 12:36:36122 gfx::Image GetBubbleViewIcon() override;
123 base::string16 GetBubbleViewTitle() override;
124 std::vector<base::string16> GetBubbleViewMessages() override;
125 base::string16 GetBubbleViewAcceptButtonLabel() override;
126 base::string16 GetBubbleViewCancelButtonLabel() override;
probergebc529d62018-04-24 14:48:26127 int GetDefaultDialogButton() const override;
dchengae36a4a2014-10-21 12:36:36128 void OnBubbleViewDidClose(Browser* browser) override;
129 void BubbleViewAcceptButtonPressed(Browser* browser) override;
130 void BubbleViewCancelButtonPressed(Browser* browser) override;
[email protected]2894a512014-06-26 19:03:56131
132 // The owning ExternalInstallError.
133 ExternalInstallError* error_;
lazyboy0b9b30f2016-01-05 03:15:37134 ExtensionInstallErrorMenuItemIdProvider id_provider_;
[email protected]2894a512014-06-26 19:03:56135
136 // The Prompt with all information, which we then use to populate the bubble.
rdevlin.cronin2e252692015-12-15 21:47:02137 // Owned by |error|.
[email protected]2894a512014-06-26 19:03:56138 ExtensionInstallPrompt::Prompt* prompt_;
139
140 DISALLOW_COPY_AND_ASSIGN(ExternalInstallBubbleAlert);
141};
142
143////////////////////////////////////////////////////////////////////////////////
144// ExternalInstallMenuAlert
145
146ExternalInstallMenuAlert::ExternalInstallMenuAlert(ExternalInstallError* error)
147 : error_(error) {
148}
149
150ExternalInstallMenuAlert::~ExternalInstallMenuAlert() {
151}
152
153GlobalError::Severity ExternalInstallMenuAlert::GetSeverity() {
154 return SEVERITY_LOW;
155}
156
157bool ExternalInstallMenuAlert::HasMenuItem() {
158 return true;
159}
160
161int ExternalInstallMenuAlert::MenuItemCommandID() {
lazyboy0b9b30f2016-01-05 03:15:37162 return id_provider_.menu_command_id();
[email protected]2894a512014-06-26 19:03:56163}
164
165base::string16 ExternalInstallMenuAlert::MenuItemLabel() {
166 return GetMenuItemLabel(error_->GetExtension());
167}
168
169void ExternalInstallMenuAlert::ExecuteMenuItem(Browser* browser) {
170 error_->ShowDialog(browser);
171}
172
173bool ExternalInstallMenuAlert::HasBubbleView() {
174 return false;
175}
176
177bool ExternalInstallMenuAlert::HasShownBubbleView() {
178 NOTREACHED();
179 return true;
180}
181
182void ExternalInstallMenuAlert::ShowBubbleView(Browser* browser) {
183 NOTREACHED();
184}
185
186GlobalErrorBubbleViewBase* ExternalInstallMenuAlert::GetBubbleView() {
187 return NULL;
188}
189
190////////////////////////////////////////////////////////////////////////////////
191// ExternalInstallBubbleAlert
192
193ExternalInstallBubbleAlert::ExternalInstallBubbleAlert(
194 ExternalInstallError* error,
195 ExtensionInstallPrompt::Prompt* prompt)
196 : error_(error), prompt_(prompt) {
197 DCHECK(error_);
198 DCHECK(prompt_);
199}
200
201ExternalInstallBubbleAlert::~ExternalInstallBubbleAlert() {
202}
203
204GlobalError::Severity ExternalInstallBubbleAlert::GetSeverity() {
205 return SEVERITY_LOW;
206}
207
208bool ExternalInstallBubbleAlert::HasMenuItem() {
209 return true;
210}
211
212int ExternalInstallBubbleAlert::MenuItemCommandID() {
lazyboy0b9b30f2016-01-05 03:15:37213 return id_provider_.menu_command_id();
[email protected]2894a512014-06-26 19:03:56214}
215
216base::string16 ExternalInstallBubbleAlert::MenuItemLabel() {
217 return GetMenuItemLabel(error_->GetExtension());
218}
219
220void ExternalInstallBubbleAlert::ExecuteMenuItem(Browser* browser) {
lazyboy1899eec42016-03-08 19:00:50221 // |browser| is nullptr in unit test.
222 if (browser)
223 ShowBubbleView(browser);
224 error_->DidOpenBubbleView();
[email protected]2894a512014-06-26 19:03:56225}
226
227gfx::Image ExternalInstallBubbleAlert::GetBubbleViewIcon() {
228 if (prompt_->icon().IsEmpty())
229 return GlobalErrorWithStandardBubble::GetBubbleViewIcon();
230 // Scale icon to a reasonable size.
231 return gfx::Image(gfx::ImageSkiaOperations::CreateResizedImage(
232 *prompt_->icon().ToImageSkia(),
233 skia::ImageOperations::RESIZE_BEST,
234 gfx::Size(extension_misc::EXTENSION_ICON_SMALL,
235 extension_misc::EXTENSION_ICON_SMALL)));
236}
237
238base::string16 ExternalInstallBubbleAlert::GetBubbleViewTitle() {
treib5e16e452015-06-19 09:55:39239 return l10n_util::GetStringFUTF16(
240 IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_BUBBLE_TITLE,
241 base::UTF8ToUTF16(prompt_->extension()->name()));
[email protected]2894a512014-06-26 19:03:56242}
243
244std::vector<base::string16>
245ExternalInstallBubbleAlert::GetBubbleViewMessages() {
gpdavis.chromium0fbac4d2014-09-19 20:57:54246 ExtensionInstallPrompt::PermissionsType regular_permissions =
247 ExtensionInstallPrompt::PermissionsType::REGULAR_PERMISSIONS;
248 ExtensionInstallPrompt::PermissionsType withheld_permissions =
249 ExtensionInstallPrompt::PermissionsType::WITHHELD_PERMISSIONS;
250
[email protected]2894a512014-06-26 19:03:56251 std::vector<base::string16> messages;
treib5e16e452015-06-19 09:55:39252 int heading_id =
253 IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_BUBBLE_HEADING_EXTENSION;
254 if (prompt_->extension()->is_app())
255 heading_id = IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_BUBBLE_HEADING_APP;
256 else if (prompt_->extension()->is_theme())
257 heading_id = IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_BUBBLE_HEADING_THEME;
258 messages.push_back(l10n_util::GetStringUTF16(heading_id));
259
gpdavis.chromium0fbac4d2014-09-19 20:57:54260 if (prompt_->GetPermissionCount(regular_permissions)) {
261 messages.push_back(prompt_->GetPermissionsHeading(regular_permissions));
262 for (size_t i = 0; i < prompt_->GetPermissionCount(regular_permissions);
263 ++i) {
[email protected]2894a512014-06-26 19:03:56264 messages.push_back(l10n_util::GetStringFUTF16(
gpdavis.chromium0fbac4d2014-09-19 20:57:54265 IDS_EXTENSION_PERMISSION_LINE,
266 prompt_->GetPermission(i, regular_permissions)));
267 }
268 }
269 if (prompt_->GetPermissionCount(withheld_permissions)) {
270 messages.push_back(prompt_->GetPermissionsHeading(withheld_permissions));
271 for (size_t i = 0; i < prompt_->GetPermissionCount(withheld_permissions);
272 ++i) {
273 messages.push_back(l10n_util::GetStringFUTF16(
274 IDS_EXTENSION_PERMISSION_LINE,
275 prompt_->GetPermission(i, withheld_permissions)));
[email protected]2894a512014-06-26 19:03:56276 }
277 }
278 // TODO(yoz): OAuth issue advice?
279 return messages;
280}
281
probergebc529d62018-04-24 14:48:26282int ExternalInstallBubbleAlert::GetDefaultDialogButton() const {
283 switch (error_->default_dialog_button_setting()) {
284 case ExternalInstallError::DIALOG_BUTTON_OK:
285 return ui::DIALOG_BUTTON_OK;
286 case ExternalInstallError::DIALOG_BUTTON_CANCEL:
287 return ui::DIALOG_BUTTON_CANCEL;
288 case ExternalInstallError::NO_DEFAULT_DIALOG_BUTTON:
289 return ui::DIALOG_BUTTON_NONE;
290 case ExternalInstallError::NOT_SPECIFIED:
291 break;
292 }
293 return GlobalErrorWithStandardBubble::GetDefaultDialogButton();
294}
295
[email protected]2894a512014-06-26 19:03:56296base::string16 ExternalInstallBubbleAlert::GetBubbleViewAcceptButtonLabel() {
297 return prompt_->GetAcceptButtonLabel();
298}
299
300base::string16 ExternalInstallBubbleAlert::GetBubbleViewCancelButtonLabel() {
301 return prompt_->GetAbortButtonLabel();
302}
303
304void ExternalInstallBubbleAlert::OnBubbleViewDidClose(Browser* browser) {
lazyboy1899eec42016-03-08 19:00:50305 error_->DidCloseBubbleView();
[email protected]2894a512014-06-26 19:03:56306}
307
308void ExternalInstallBubbleAlert::BubbleViewAcceptButtonPressed(
309 Browser* browser) {
rdevlin.cronin41593052016-01-08 01:40:12310 error_->OnInstallPromptDone(ExtensionInstallPrompt::Result::ACCEPTED);
[email protected]2894a512014-06-26 19:03:56311}
312
313void ExternalInstallBubbleAlert::BubbleViewCancelButtonPressed(
314 Browser* browser) {
rdevlin.cronin41593052016-01-08 01:40:12315 error_->OnInstallPromptDone(ExtensionInstallPrompt::Result::USER_CANCELED);
[email protected]2894a512014-06-26 19:03:56316}
317
318} // namespace
319
320////////////////////////////////////////////////////////////////////////////////
321// ExternalInstallError
322
probergebc529d62018-04-24 14:48:26323// static
324ExternalInstallError::DefaultDialogButtonSetting
325ExternalInstallError::GetDefaultDialogButton(
326 const base::Value& webstore_response) {
327 const base::Value* value = webstore_response.FindKeyOfType(
328 kExternalInstallDefaultButtonKey, base::Value::Type::STRING);
329 if (value) {
330 return MapDefaultButtonStringToSetting(value->GetString());
331 }
332
333 if (base::FeatureList::IsEnabled(
334 features::kExternalExtensionDefaultButtonControl)) {
335 std::string default_button = base::GetFieldTrialParamValueByFeature(
336 features::kExternalExtensionDefaultButtonControl,
337 kExternalInstallDefaultButtonKey);
338 if (!default_button.empty()) {
339 return MapDefaultButtonStringToSetting(default_button);
340 }
341 }
342
343 return NOT_SPECIFIED;
344}
345
[email protected]2894a512014-06-26 19:03:56346ExternalInstallError::ExternalInstallError(
347 content::BrowserContext* browser_context,
348 const std::string& extension_id,
349 AlertType alert_type,
350 ExternalInstallManager* manager)
351 : browser_context_(browser_context),
352 extension_id_(extension_id),
353 alert_type_(alert_type),
354 manager_(manager),
355 error_service_(GlobalErrorServiceFactory::GetForProfile(
356 Profile::FromBrowserContext(browser_context_))),
357 weak_factory_(this) {
rdevlin.cronin2e252692015-12-15 21:47:02358 prompt_.reset(new ExtensionInstallPrompt::Prompt(
359 ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT));
[email protected]2894a512014-06-26 19:03:56360
361 webstore_data_fetcher_.reset(new WebstoreDataFetcher(
jamb84299e2016-04-12 16:58:59362 this,
363 content::BrowserContext::GetDefaultStoragePartition(browser_context_)->
364 GetURLRequestContext(),
365 GURL(), extension_id_));
[email protected]2894a512014-06-26 19:03:56366 webstore_data_fetcher_->Start();
367}
368
369ExternalInstallError::~ExternalInstallError() {
rdevlin.cronina1c3f1a2017-05-18 17:45:46370#if DCHECK_IS_ON()
371 // Errors should only be removed while the profile is valid, since removing
372 // the error can trigger other subsystems listening for changes.
373 BrowserContextDependencyManager::GetInstance()
374 ->AssertBrowserContextWasntDestroyed(browser_context_);
375#endif
[email protected]2894a512014-06-26 19:03:56376 if (global_error_.get())
avi2451b252016-12-13 16:55:17377 error_service_->RemoveUnownedGlobalError(global_error_.get());
[email protected]2894a512014-06-26 19:03:56378}
379
rdevlin.cronin41593052016-01-08 01:40:12380void ExternalInstallError::OnInstallPromptDone(
381 ExtensionInstallPrompt::Result result) {
[email protected]2894a512014-06-26 19:03:56382 const Extension* extension = GetExtension();
rdevlin.croninb2daf2e42016-01-14 20:00:54383
384 // If the error isn't removed and deleted as part of handling the user's
385 // response (which can happen, e.g., if an uninstall fails), be sure to remove
386 // the error directly in order to ensure it's not called twice.
fdoray283082bd2016-06-02 20:18:46387 base::ThreadTaskRunnerHandle::Get()->PostTask(
tzik8d880ee2017-04-20 19:46:24388 FROM_HERE, base::BindOnce(&ExternalInstallError::RemoveError,
389 weak_factory_.GetWeakPtr()));
rdevlin.croninb2daf2e42016-01-14 20:00:54390
rdevlin.cronin41593052016-01-08 01:40:12391 switch (result) {
392 case ExtensionInstallPrompt::Result::ACCEPTED:
393 if (extension) {
394 ExtensionSystem::Get(browser_context_)
395 ->extension_service()
396 ->GrantPermissionsAndEnableExtension(extension);
rdevlin.cronin41593052016-01-08 01:40:12397 }
398 break;
399 case ExtensionInstallPrompt::Result::USER_CANCELED:
400 if (extension) {
rdevlin.croninb2daf2e42016-01-14 20:00:54401 bool uninstallation_result = ExtensionSystem::Get(browser_context_)
rdevlin.cronin41593052016-01-08 01:40:12402 ->extension_service()
403 ->UninstallExtension(extension_id_,
404 extensions::UNINSTALL_REASON_INSTALL_CANCELED,
rdevlin.cronin41593052016-01-08 01:40:12405 nullptr); // Ignore error.
rdevlin.croninb2daf2e42016-01-14 20:00:54406 UMA_HISTOGRAM_BOOLEAN("Extensions.ExternalWarningUninstallationResult",
407 uninstallation_result);
rdevlin.cronin41593052016-01-08 01:40:12408 }
409 break;
410 case ExtensionInstallPrompt::Result::ABORTED:
lazyboy1899eec42016-03-08 19:00:50411 manager_->DidChangeInstallAlertVisibility(this, false);
rdevlin.cronin41593052016-01-08 01:40:12412 break;
[email protected]2894a512014-06-26 19:03:56413 }
rdevlin.croninb2daf2e42016-01-14 20:00:54414 // NOTE: We may be deleted here!
[email protected]2894a512014-06-26 19:03:56415}
416
lazyboy1899eec42016-03-08 19:00:50417void ExternalInstallError::DidOpenBubbleView() {
418 manager_->DidChangeInstallAlertVisibility(this, true);
419}
420
421void ExternalInstallError::DidCloseBubbleView() {
422 manager_->DidChangeInstallAlertVisibility(this, false);
423}
424
[email protected]2894a512014-06-26 19:03:56425void ExternalInstallError::ShowDialog(Browser* browser) {
426 DCHECK(install_ui_.get());
427 DCHECK(prompt_.get());
428 DCHECK(browser);
429 content::WebContents* web_contents = NULL;
[email protected]2894a512014-06-26 19:03:56430 web_contents = browser->tab_strip_model()->GetActiveWebContents();
pkotwicz2f181782014-10-29 17:33:45431 install_ui_show_params_.reset(
432 new ExtensionInstallPromptShowParams(web_contents));
lazyboy1899eec42016-03-08 19:00:50433 manager_->DidChangeInstallAlertVisibility(this, true);
[email protected]2894a512014-06-26 19:03:56434 ExtensionInstallPrompt::GetDefaultShowDialogCallback().Run(
rdevlin.cronin41593052016-01-08 01:40:12435 install_ui_show_params_.get(),
436 base::Bind(&ExternalInstallError::OnInstallPromptDone,
437 weak_factory_.GetWeakPtr()),
438 std::move(prompt_));
[email protected]2894a512014-06-26 19:03:56439}
440
441const Extension* ExternalInstallError::GetExtension() const {
442 return ExtensionRegistry::Get(browser_context_)
443 ->GetExtensionById(extension_id_, ExtensionRegistry::EVERYTHING);
444}
445
446void ExternalInstallError::OnWebstoreRequestFailure() {
447 OnFetchComplete();
448}
449
450void ExternalInstallError::OnWebstoreResponseParseSuccess(
dchengc963c7142016-04-08 03:55:22451 std::unique_ptr<base::DictionaryValue> webstore_data) {
[email protected]2894a512014-06-26 19:03:56452 std::string localized_user_count;
[email protected]96aebe22014-07-16 04:07:51453 double average_rating = 0;
454 int rating_count = 0;
[email protected]2894a512014-06-26 19:03:56455 if (!webstore_data->GetString(kUsersKey, &localized_user_count) ||
456 !webstore_data->GetDouble(kAverageRatingKey, &average_rating) ||
457 !webstore_data->GetInteger(kRatingCountKey, &rating_count)) {
458 // If we don't get a valid webstore response, short circuit, and continue
459 // to show a prompt without webstore data.
460 OnFetchComplete();
461 return;
462 }
463
probergebc529d62018-04-24 14:48:26464 default_dialog_button_setting_ = GetDefaultDialogButton(*webstore_data.get());
465
[email protected]2894a512014-06-26 19:03:56466 bool show_user_count = true;
467 webstore_data->GetBoolean(kShowUserCountKey, &show_user_count);
468
469 prompt_->SetWebstoreData(
470 localized_user_count, show_user_count, average_rating, rating_count);
471 OnFetchComplete();
472}
473
474void ExternalInstallError::OnWebstoreResponseParseFailure(
475 const std::string& error) {
476 OnFetchComplete();
477}
478
479void ExternalInstallError::OnFetchComplete() {
480 // Create a new ExtensionInstallPrompt. We pass in NULL for the UI
481 // components because we display at a later point, and don't want
482 // to pass ones which may be invalidated.
483 install_ui_.reset(
484 new ExtensionInstallPrompt(Profile::FromBrowserContext(browser_context_),
pkotwicz2175c622014-10-22 19:56:28485 NULL)); // NULL native window.
[email protected]2894a512014-06-26 19:03:56486
rdevlin.cronin41593052016-01-08 01:40:12487 install_ui_->ShowDialog(base::Bind(&ExternalInstallError::OnInstallPromptDone,
488 weak_factory_.GetWeakPtr()),
489 GetExtension(),
rdevlin.croninf84cab72015-12-12 03:45:23490 nullptr, // Force a fetch of the icon.
dcheng1fc00f12015-12-26 22:18:03491 std::move(prompt_),
rdevlin.croninf84cab72015-12-12 03:45:23492 base::Bind(&ExternalInstallError::OnDialogReady,
493 weak_factory_.GetWeakPtr()));
[email protected]2894a512014-06-26 19:03:56494}
495
496void ExternalInstallError::OnDialogReady(
pkotwicz2f181782014-10-29 17:33:45497 ExtensionInstallPromptShowParams* show_params,
rdevlin.cronin41593052016-01-08 01:40:12498 const ExtensionInstallPrompt::DoneCallback& callback,
dchengc963c7142016-04-08 03:55:22499 std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt) {
dcheng1fc00f12015-12-26 22:18:03500 prompt_ = std::move(prompt);
[email protected]2894a512014-06-26 19:03:56501
502 if (alert_type_ == BUBBLE_ALERT) {
dchengc7047942014-08-26 05:05:31503 global_error_.reset(new ExternalInstallBubbleAlert(this, prompt_.get()));
avi2451b252016-12-13 16:55:17504 error_service_->AddUnownedGlobalError(global_error_.get());
[email protected]2894a512014-06-26 19:03:56505
lazyboy1899eec42016-03-08 19:00:50506 if (!manager_->has_currently_visible_install_alert()) {
507 // |browser| is nullptr during unit tests, so call
508 // DidChangeInstallAlertVisibility() regardless because we depend on this
509 // in unit tests.
510 manager_->DidChangeInstallAlertVisibility(this, true);
511 Browser* browser = chrome::FindTabbedBrowser(
512 Profile::FromBrowserContext(browser_context_), true);
513 if (browser)
514 global_error_->ShowBubbleView(browser);
515 }
[email protected]2894a512014-06-26 19:03:56516 } else {
517 DCHECK(alert_type_ == MENU_ALERT);
518 global_error_.reset(new ExternalInstallMenuAlert(this));
avi2451b252016-12-13 16:55:17519 error_service_->AddUnownedGlobalError(global_error_.get());
[email protected]2894a512014-06-26 19:03:56520 }
521}
522
rdevlin.croninb2daf2e42016-01-14 20:00:54523void ExternalInstallError::RemoveError() {
524 manager_->RemoveExternalInstallError(extension_id_);
525}
526
[email protected]2894a512014-06-26 19:03:56527} // namespace extensions