blob: 65016ef4056ea02cbbc424dc886fdc9f1036d1e9 [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>
Peter Boströmf47f505d2021-04-15 05:03:208
9#include <memory>
dcheng1fc00f12015-12-26 22:18:0310#include <utility>
avia2f4804a2015-12-24 23:11:1311
[email protected]2894a512014-06-26 19:03:5612#include "base/bind.h"
fdoray283082bd2016-06-02 20:18:4613#include "base/location.h"
avia2f4804a2015-12-24 23:11:1314#include "base/macros.h"
probergebc529d62018-04-24 14:48:2615#include "base/metrics/field_trial_params.h"
rdevlin.croninb2daf2e42016-01-14 20:00:5416#include "base/metrics/histogram_macros.h"
fdoray283082bd2016-06-02 20:18:4617#include "base/single_thread_task_runner.h"
[email protected]2894a512014-06-26 19:03:5618#include "base/strings/utf_string_conversions.h"
fdoray283082bd2016-06-02 20:18:4619#include "base/threading/thread_task_runner_handle.h"
[email protected]2894a512014-06-26 19:03:5620#include "chrome/app/chrome_command_ids.h"
lazyboy0b9b30f2016-01-05 03:15:3721#include "chrome/browser/extensions/extension_install_error_menu_item_id_provider.h"
pkotwicz2f181782014-10-29 17:33:4522#include "chrome/browser/extensions/extension_install_prompt_show_params.h"
[email protected]2894a512014-06-26 19:03:5623#include "chrome/browser/extensions/extension_service.h"
probergebc529d62018-04-24 14:48:2624#include "chrome/browser/extensions/external_install_error_constants.h"
[email protected]2894a512014-06-26 19:03:5625#include "chrome/browser/extensions/external_install_manager.h"
26#include "chrome/browser/extensions/webstore_data_fetcher.h"
27#include "chrome/browser/profiles/profile.h"
28#include "chrome/browser/ui/browser.h"
29#include "chrome/browser/ui/browser_finder.h"
30#include "chrome/browser/ui/global_error/global_error.h"
31#include "chrome/browser/ui/global_error/global_error_service.h"
32#include "chrome/browser/ui/global_error/global_error_service_factory.h"
33#include "chrome/browser/ui/tabs/tab_strip_model.h"
probergebc529d62018-04-24 14:48:2634#include "chrome/common/chrome_features.h"
[email protected]af39f002014-08-22 10:18:1835#include "chrome/grit/generated_resources.h"
rdevlin.cronina1c3f1a2017-05-18 17:45:4636#include "components/keyed_service/content/browser_context_dependency_manager.h"
jamb84299e2016-04-12 16:58:5937#include "content/public/browser/storage_partition.h"
[email protected]2894a512014-06-26 19:03:5638#include "extensions/browser/extension_registry.h"
39#include "extensions/browser/extension_system.h"
[email protected]e43c61f2014-07-20 21:46:3440#include "extensions/browser/uninstall_reason.h"
[email protected]2894a512014-06-26 19:03:5641#include "extensions/common/constants.h"
42#include "extensions/common/extension.h"
[email protected]2894a512014-06-26 19:03:5643#include "ui/base/l10n/l10n_util.h"
44#include "ui/gfx/image/image.h"
rdevlin.cronin3fe4bd32016-01-12 18:45:4045#include "ui/gfx/image/image_skia.h"
[email protected]2894a512014-06-26 19:03:5646#include "ui/gfx/image/image_skia_operations.h"
47
48namespace extensions {
49
50namespace {
51
52// Return the menu label for a global error.
Jan Wilken Dörrief27844b2021-03-11 23:18:4853std::u16string GetMenuItemLabel(const Extension* extension) {
[email protected]2894a512014-06-26 19:03:5654 if (!extension)
Jan Wilken Dörrief27844b2021-03-11 23:18:4855 return std::u16string();
[email protected]2894a512014-06-26 19:03:5656
57 int id = -1;
58 if (extension->is_app())
59 id = IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_APP;
60 else if (extension->is_theme())
61 id = IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_THEME;
62 else
63 id = IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_EXTENSION;
64
65 return l10n_util::GetStringFUTF16(id, base::UTF8ToUTF16(extension->name()));
66}
67
probergebc529d62018-04-24 14:48:2668ExternalInstallError::DefaultDialogButtonSetting
69MapDefaultButtonStringToSetting(const std::string& button_setting_string) {
70 if (button_setting_string == kDefaultDialogButtonSettingOk)
71 return ExternalInstallError::DIALOG_BUTTON_OK;
72 if (button_setting_string == kDefaultDialogButtonSettingCancel)
73 return ExternalInstallError::DIALOG_BUTTON_CANCEL;
74 if (button_setting_string == kDefaultDialogButtonSettingNoDefault)
75 return ExternalInstallError::NO_DEFAULT_DIALOG_BUTTON;
76
77 NOTREACHED() << "Unexpected default button string: " << button_setting_string;
78 return ExternalInstallError::NOT_SPECIFIED;
79}
80
[email protected]2894a512014-06-26 19:03:5681// A global error that spawns a dialog when the menu item is clicked.
82class ExternalInstallMenuAlert : public GlobalError {
83 public:
84 explicit ExternalInstallMenuAlert(ExternalInstallError* error);
dchengae36a4a2014-10-21 12:36:3685 ~ExternalInstallMenuAlert() override;
[email protected]2894a512014-06-26 19:03:5686
87 private:
88 // GlobalError implementation.
dchengae36a4a2014-10-21 12:36:3689 Severity GetSeverity() override;
90 bool HasMenuItem() override;
91 int MenuItemCommandID() override;
Jan Wilken Dörrief27844b2021-03-11 23:18:4892 std::u16string MenuItemLabel() override;
dchengae36a4a2014-10-21 12:36:3693 void ExecuteMenuItem(Browser* browser) override;
94 bool HasBubbleView() override;
95 bool HasShownBubbleView() override;
96 void ShowBubbleView(Browser* browser) override;
97 GlobalErrorBubbleViewBase* GetBubbleView() override;
[email protected]2894a512014-06-26 19:03:5698
99 // The owning ExternalInstallError.
100 ExternalInstallError* error_;
101
lazyboy0b9b30f2016-01-05 03:15:37102 // Provides menu item id for GlobalError.
103 ExtensionInstallErrorMenuItemIdProvider id_provider_;
104
[email protected]2894a512014-06-26 19:03:56105 DISALLOW_COPY_AND_ASSIGN(ExternalInstallMenuAlert);
106};
107
108// A global error that spawns a bubble when the menu item is clicked.
109class ExternalInstallBubbleAlert : public GlobalErrorWithStandardBubble {
110 public:
rdevlin.cronin2e252692015-12-15 21:47:02111 ExternalInstallBubbleAlert(ExternalInstallError* error,
112 ExtensionInstallPrompt::Prompt* prompt);
dchengae36a4a2014-10-21 12:36:36113 ~ExternalInstallBubbleAlert() override;
[email protected]2894a512014-06-26 19:03:56114
115 private:
116 // GlobalError implementation.
dchengae36a4a2014-10-21 12:36:36117 Severity GetSeverity() override;
118 bool HasMenuItem() override;
119 int MenuItemCommandID() override;
Jan Wilken Dörrief27844b2021-03-11 23:18:48120 std::u16string MenuItemLabel() override;
dchengae36a4a2014-10-21 12:36:36121 void ExecuteMenuItem(Browser* browser) override;
[email protected]2894a512014-06-26 19:03:56122
123 // GlobalErrorWithStandardBubble implementation.
Jan Wilken Dörrief27844b2021-03-11 23:18:48124 std::u16string GetBubbleViewTitle() override;
125 std::vector<std::u16string> GetBubbleViewMessages() override;
126 std::u16string GetBubbleViewAcceptButtonLabel() override;
127 std::u16string GetBubbleViewCancelButtonLabel() override;
probergebc529d62018-04-24 14:48:26128 int GetDefaultDialogButton() const override;
dchengae36a4a2014-10-21 12:36:36129 void OnBubbleViewDidClose(Browser* browser) override;
130 void BubbleViewAcceptButtonPressed(Browser* browser) override;
131 void BubbleViewCancelButtonPressed(Browser* browser) override;
[email protected]2894a512014-06-26 19:03:56132
133 // The owning ExternalInstallError.
134 ExternalInstallError* error_;
lazyboy0b9b30f2016-01-05 03:15:37135 ExtensionInstallErrorMenuItemIdProvider id_provider_;
[email protected]2894a512014-06-26 19:03:56136
137 // The Prompt with all information, which we then use to populate the bubble.
rdevlin.cronin2e252692015-12-15 21:47:02138 // Owned by |error|.
[email protected]2894a512014-06-26 19:03:56139 ExtensionInstallPrompt::Prompt* prompt_;
140
141 DISALLOW_COPY_AND_ASSIGN(ExternalInstallBubbleAlert);
142};
143
144////////////////////////////////////////////////////////////////////////////////
145// ExternalInstallMenuAlert
146
147ExternalInstallMenuAlert::ExternalInstallMenuAlert(ExternalInstallError* error)
148 : error_(error) {
149}
150
151ExternalInstallMenuAlert::~ExternalInstallMenuAlert() {
152}
153
154GlobalError::Severity ExternalInstallMenuAlert::GetSeverity() {
155 return SEVERITY_LOW;
156}
157
158bool ExternalInstallMenuAlert::HasMenuItem() {
159 return true;
160}
161
162int ExternalInstallMenuAlert::MenuItemCommandID() {
lazyboy0b9b30f2016-01-05 03:15:37163 return id_provider_.menu_command_id();
[email protected]2894a512014-06-26 19:03:56164}
165
Jan Wilken Dörrief27844b2021-03-11 23:18:48166std::u16string ExternalInstallMenuAlert::MenuItemLabel() {
[email protected]2894a512014-06-26 19:03:56167 return GetMenuItemLabel(error_->GetExtension());
168}
169
170void ExternalInstallMenuAlert::ExecuteMenuItem(Browser* browser) {
171 error_->ShowDialog(browser);
172}
173
174bool ExternalInstallMenuAlert::HasBubbleView() {
175 return false;
176}
177
178bool ExternalInstallMenuAlert::HasShownBubbleView() {
179 NOTREACHED();
180 return true;
181}
182
183void ExternalInstallMenuAlert::ShowBubbleView(Browser* browser) {
184 NOTREACHED();
185}
186
187GlobalErrorBubbleViewBase* ExternalInstallMenuAlert::GetBubbleView() {
188 return NULL;
189}
190
191////////////////////////////////////////////////////////////////////////////////
192// ExternalInstallBubbleAlert
193
194ExternalInstallBubbleAlert::ExternalInstallBubbleAlert(
195 ExternalInstallError* error,
196 ExtensionInstallPrompt::Prompt* prompt)
197 : error_(error), prompt_(prompt) {
198 DCHECK(error_);
199 DCHECK(prompt_);
200}
201
202ExternalInstallBubbleAlert::~ExternalInstallBubbleAlert() {
203}
204
205GlobalError::Severity ExternalInstallBubbleAlert::GetSeverity() {
206 return SEVERITY_LOW;
207}
208
209bool ExternalInstallBubbleAlert::HasMenuItem() {
210 return true;
211}
212
213int ExternalInstallBubbleAlert::MenuItemCommandID() {
lazyboy0b9b30f2016-01-05 03:15:37214 return id_provider_.menu_command_id();
[email protected]2894a512014-06-26 19:03:56215}
216
Jan Wilken Dörrief27844b2021-03-11 23:18:48217std::u16string ExternalInstallBubbleAlert::MenuItemLabel() {
[email protected]2894a512014-06-26 19:03:56218 return GetMenuItemLabel(error_->GetExtension());
219}
220
221void ExternalInstallBubbleAlert::ExecuteMenuItem(Browser* browser) {
lazyboy1899eec42016-03-08 19:00:50222 // |browser| is nullptr in unit test.
223 if (browser)
224 ShowBubbleView(browser);
225 error_->DidOpenBubbleView();
[email protected]2894a512014-06-26 19:03:56226}
227
Jan Wilken Dörrief27844b2021-03-11 23:18:48228std::u16string ExternalInstallBubbleAlert::GetBubbleViewTitle() {
treib5e16e452015-06-19 09:55:39229 return l10n_util::GetStringFUTF16(
230 IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_BUBBLE_TITLE,
231 base::UTF8ToUTF16(prompt_->extension()->name()));
[email protected]2894a512014-06-26 19:03:56232}
233
Jan Wilken Dörrief27844b2021-03-11 23:18:48234std::vector<std::u16string>
[email protected]2894a512014-06-26 19:03:56235ExternalInstallBubbleAlert::GetBubbleViewMessages() {
Jan Wilken Dörrief27844b2021-03-11 23:18:48236 std::vector<std::u16string> messages;
treib5e16e452015-06-19 09:55:39237 int heading_id =
238 IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_BUBBLE_HEADING_EXTENSION;
239 if (prompt_->extension()->is_app())
240 heading_id = IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_BUBBLE_HEADING_APP;
241 else if (prompt_->extension()->is_theme())
242 heading_id = IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_BUBBLE_HEADING_THEME;
243 messages.push_back(l10n_util::GetStringUTF16(heading_id));
244
Devlin Cronind6e136a2018-05-15 23:39:32245 if (prompt_->GetPermissionCount()) {
246 messages.push_back(prompt_->GetPermissionsHeading());
247 for (size_t i = 0; i < prompt_->GetPermissionCount(); ++i) {
[email protected]2894a512014-06-26 19:03:56248 messages.push_back(l10n_util::GetStringFUTF16(
Devlin Cronind6e136a2018-05-15 23:39:32249 IDS_EXTENSION_PERMISSION_LINE, prompt_->GetPermission(i)));
[email protected]2894a512014-06-26 19:03:56250 }
251 }
252 // TODO(yoz): OAuth issue advice?
253 return messages;
254}
255
probergebc529d62018-04-24 14:48:26256int ExternalInstallBubbleAlert::GetDefaultDialogButton() const {
257 switch (error_->default_dialog_button_setting()) {
258 case ExternalInstallError::DIALOG_BUTTON_OK:
259 return ui::DIALOG_BUTTON_OK;
260 case ExternalInstallError::DIALOG_BUTTON_CANCEL:
261 return ui::DIALOG_BUTTON_CANCEL;
262 case ExternalInstallError::NO_DEFAULT_DIALOG_BUTTON:
263 return ui::DIALOG_BUTTON_NONE;
264 case ExternalInstallError::NOT_SPECIFIED:
265 break;
266 }
267 return GlobalErrorWithStandardBubble::GetDefaultDialogButton();
268}
269
Jan Wilken Dörrief27844b2021-03-11 23:18:48270std::u16string ExternalInstallBubbleAlert::GetBubbleViewAcceptButtonLabel() {
[email protected]2894a512014-06-26 19:03:56271 return prompt_->GetAcceptButtonLabel();
272}
273
Jan Wilken Dörrief27844b2021-03-11 23:18:48274std::u16string ExternalInstallBubbleAlert::GetBubbleViewCancelButtonLabel() {
[email protected]2894a512014-06-26 19:03:56275 return prompt_->GetAbortButtonLabel();
276}
277
278void ExternalInstallBubbleAlert::OnBubbleViewDidClose(Browser* browser) {
lazyboy1899eec42016-03-08 19:00:50279 error_->DidCloseBubbleView();
[email protected]2894a512014-06-26 19:03:56280}
281
282void ExternalInstallBubbleAlert::BubbleViewAcceptButtonPressed(
283 Browser* browser) {
Igor Ruvinov6cbc8922021-07-14 17:51:41284 error_->OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload(
285 ExtensionInstallPrompt::Result::ACCEPTED));
[email protected]2894a512014-06-26 19:03:56286}
287
288void ExternalInstallBubbleAlert::BubbleViewCancelButtonPressed(
289 Browser* browser) {
Igor Ruvinov6cbc8922021-07-14 17:51:41290 error_->OnInstallPromptDone(ExtensionInstallPrompt::DoneCallbackPayload(
291 ExtensionInstallPrompt::Result::USER_CANCELED));
[email protected]2894a512014-06-26 19:03:56292}
293
294} // namespace
295
296////////////////////////////////////////////////////////////////////////////////
297// ExternalInstallError
298
probergebc529d62018-04-24 14:48:26299// static
300ExternalInstallError::DefaultDialogButtonSetting
301ExternalInstallError::GetDefaultDialogButton(
302 const base::Value& webstore_response) {
303 const base::Value* value = webstore_response.FindKeyOfType(
304 kExternalInstallDefaultButtonKey, base::Value::Type::STRING);
305 if (value) {
306 return MapDefaultButtonStringToSetting(value->GetString());
307 }
308
309 if (base::FeatureList::IsEnabled(
Oscar Johansson7f4c1b932018-06-12 06:11:58310 ::features::kExternalExtensionDefaultButtonControl)) {
probergebc529d62018-04-24 14:48:26311 std::string default_button = base::GetFieldTrialParamValueByFeature(
Oscar Johansson7f4c1b932018-06-12 06:11:58312 ::features::kExternalExtensionDefaultButtonControl,
probergebc529d62018-04-24 14:48:26313 kExternalInstallDefaultButtonKey);
314 if (!default_button.empty()) {
315 return MapDefaultButtonStringToSetting(default_button);
316 }
317 }
318
319 return NOT_SPECIFIED;
320}
321
[email protected]2894a512014-06-26 19:03:56322ExternalInstallError::ExternalInstallError(
323 content::BrowserContext* browser_context,
324 const std::string& extension_id,
325 AlertType alert_type,
326 ExternalInstallManager* manager)
327 : browser_context_(browser_context),
328 extension_id_(extension_id),
329 alert_type_(alert_type),
330 manager_(manager),
331 error_service_(GlobalErrorServiceFactory::GetForProfile(
Jeremy Roman495db682019-07-12 16:03:24332 Profile::FromBrowserContext(browser_context_))) {
Peter Boströmf47f505d2021-04-15 05:03:20333 prompt_ = std::make_unique<ExtensionInstallPrompt::Prompt>(
334 ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT);
[email protected]2894a512014-06-26 19:03:56335
Peter Boströmf47f505d2021-04-15 05:03:20336 webstore_data_fetcher_ =
337 std::make_unique<WebstoreDataFetcher>(this, GURL(), extension_id_);
Lukasz Anforowiczb9a969a2021-04-29 15:26:25338 webstore_data_fetcher_->Start(browser_context_->GetDefaultStoragePartition()
339 ->GetURLLoaderFactoryForBrowserProcess()
340 .get());
[email protected]2894a512014-06-26 19:03:56341}
342
343ExternalInstallError::~ExternalInstallError() {
rdevlin.cronina1c3f1a2017-05-18 17:45:46344#if DCHECK_IS_ON()
345 // Errors should only be removed while the profile is valid, since removing
346 // the error can trigger other subsystems listening for changes.
347 BrowserContextDependencyManager::GetInstance()
348 ->AssertBrowserContextWasntDestroyed(browser_context_);
349#endif
[email protected]2894a512014-06-26 19:03:56350 if (global_error_.get())
avi2451b252016-12-13 16:55:17351 error_service_->RemoveUnownedGlobalError(global_error_.get());
[email protected]2894a512014-06-26 19:03:56352}
353
rdevlin.cronin41593052016-01-08 01:40:12354void ExternalInstallError::OnInstallPromptDone(
Igor Ruvinov6cbc8922021-07-14 17:51:41355 ExtensionInstallPrompt::DoneCallbackPayload payload) {
[email protected]2894a512014-06-26 19:03:56356 const Extension* extension = GetExtension();
rdevlin.croninb2daf2e42016-01-14 20:00:54357
358 // If the error isn't removed and deleted as part of handling the user's
359 // response (which can happen, e.g., if an uninstall fails), be sure to remove
360 // the error directly in order to ensure it's not called twice.
fdoray283082bd2016-06-02 20:18:46361 base::ThreadTaskRunnerHandle::Get()->PostTask(
tzik8d880ee2017-04-20 19:46:24362 FROM_HERE, base::BindOnce(&ExternalInstallError::RemoveError,
363 weak_factory_.GetWeakPtr()));
rdevlin.croninb2daf2e42016-01-14 20:00:54364
Igor Ruvinov6cbc8922021-07-14 17:51:41365 switch (payload.result) {
rdevlin.cronin41593052016-01-08 01:40:12366 case ExtensionInstallPrompt::Result::ACCEPTED:
Tim Judkinse9221872020-01-25 01:37:53367 case ExtensionInstallPrompt::Result::ACCEPTED_AND_OPTION_CHECKED:
rdevlin.cronin41593052016-01-08 01:40:12368 if (extension) {
369 ExtensionSystem::Get(browser_context_)
370 ->extension_service()
371 ->GrantPermissionsAndEnableExtension(extension);
rdevlin.cronin41593052016-01-08 01:40:12372 }
373 break;
374 case ExtensionInstallPrompt::Result::USER_CANCELED:
375 if (extension) {
Devlin Cronin24cd22c32019-01-29 18:14:36376 ExtensionSystem::Get(browser_context_)
rdevlin.cronin41593052016-01-08 01:40:12377 ->extension_service()
378 ->UninstallExtension(extension_id_,
379 extensions::UNINSTALL_REASON_INSTALL_CANCELED,
rdevlin.cronin41593052016-01-08 01:40:12380 nullptr); // Ignore error.
rdevlin.cronin41593052016-01-08 01:40:12381 }
382 break;
383 case ExtensionInstallPrompt::Result::ABORTED:
lazyboy1899eec42016-03-08 19:00:50384 manager_->DidChangeInstallAlertVisibility(this, false);
rdevlin.cronin41593052016-01-08 01:40:12385 break;
[email protected]2894a512014-06-26 19:03:56386 }
rdevlin.croninb2daf2e42016-01-14 20:00:54387 // NOTE: We may be deleted here!
[email protected]2894a512014-06-26 19:03:56388}
389
lazyboy1899eec42016-03-08 19:00:50390void ExternalInstallError::DidOpenBubbleView() {
391 manager_->DidChangeInstallAlertVisibility(this, true);
392}
393
394void ExternalInstallError::DidCloseBubbleView() {
395 manager_->DidChangeInstallAlertVisibility(this, false);
396}
397
[email protected]2894a512014-06-26 19:03:56398void ExternalInstallError::ShowDialog(Browser* browser) {
399 DCHECK(install_ui_.get());
400 DCHECK(prompt_.get());
401 DCHECK(browser);
402 content::WebContents* web_contents = NULL;
[email protected]2894a512014-06-26 19:03:56403 web_contents = browser->tab_strip_model()->GetActiveWebContents();
lazyboy1899eec42016-03-08 19:00:50404 manager_->DidChangeInstallAlertVisibility(this, true);
[email protected]2894a512014-06-26 19:03:56405 ExtensionInstallPrompt::GetDefaultShowDialogCallback().Run(
Istiaque Ahmed52f8fec2021-05-19 20:15:39406 std::make_unique<ExtensionInstallPromptShowParams>(web_contents),
Yi Gu7fabef122020-12-16 13:03:31407 base::BindOnce(&ExternalInstallError::OnInstallPromptDone,
408 weak_factory_.GetWeakPtr()),
rdevlin.cronin41593052016-01-08 01:40:12409 std::move(prompt_));
[email protected]2894a512014-06-26 19:03:56410}
411
412const Extension* ExternalInstallError::GetExtension() const {
413 return ExtensionRegistry::Get(browser_context_)
414 ->GetExtensionById(extension_id_, ExtensionRegistry::EVERYTHING);
415}
416
Toby Huang7b4816f2020-02-07 23:54:07417void ExternalInstallError::OnWebstoreRequestFailure(
418 const std::string& extension_id) {
[email protected]2894a512014-06-26 19:03:56419 OnFetchComplete();
420}
421
422void ExternalInstallError::OnWebstoreResponseParseSuccess(
Toby Huang7b4816f2020-02-07 23:54:07423 const std::string& extension_id,
dchengc963c7142016-04-08 03:55:22424 std::unique_ptr<base::DictionaryValue> webstore_data) {
[email protected]2894a512014-06-26 19:03:56425 std::string localized_user_count;
[email protected]96aebe22014-07-16 04:07:51426 double average_rating = 0;
427 int rating_count = 0;
[email protected]2894a512014-06-26 19:03:56428 if (!webstore_data->GetString(kUsersKey, &localized_user_count) ||
429 !webstore_data->GetDouble(kAverageRatingKey, &average_rating) ||
430 !webstore_data->GetInteger(kRatingCountKey, &rating_count)) {
431 // If we don't get a valid webstore response, short circuit, and continue
432 // to show a prompt without webstore data.
433 OnFetchComplete();
434 return;
435 }
436
probergebc529d62018-04-24 14:48:26437 default_dialog_button_setting_ = GetDefaultDialogButton(*webstore_data.get());
438
[email protected]2894a512014-06-26 19:03:56439 bool show_user_count = true;
440 webstore_data->GetBoolean(kShowUserCountKey, &show_user_count);
441
442 prompt_->SetWebstoreData(
443 localized_user_count, show_user_count, average_rating, rating_count);
444 OnFetchComplete();
445}
446
447void ExternalInstallError::OnWebstoreResponseParseFailure(
Toby Huang7b4816f2020-02-07 23:54:07448 const std::string& extension_id,
[email protected]2894a512014-06-26 19:03:56449 const std::string& error) {
450 OnFetchComplete();
451}
452
453void ExternalInstallError::OnFetchComplete() {
454 // Create a new ExtensionInstallPrompt. We pass in NULL for the UI
455 // components because we display at a later point, and don't want
456 // to pass ones which may be invalidated.
Peter Boströmf47f505d2021-04-15 05:03:20457 install_ui_ = base::WrapUnique(
[email protected]2894a512014-06-26 19:03:56458 new ExtensionInstallPrompt(Profile::FromBrowserContext(browser_context_),
Peter Boströmf47f505d2021-04-15 05:03:20459 /*native_window=*/nullptr));
[email protected]2894a512014-06-26 19:03:56460
Yi Gu7fabef122020-12-16 13:03:31461 install_ui_->ShowDialog(
462 base::BindOnce(&ExternalInstallError::OnInstallPromptDone,
463 weak_factory_.GetWeakPtr()),
464 GetExtension(),
465 nullptr, // Force a fetch of the icon.
466 std::move(prompt_),
467 base::BindRepeating(&ExternalInstallError::OnDialogReady,
468 weak_factory_.GetWeakPtr()));
[email protected]2894a512014-06-26 19:03:56469}
470
471void ExternalInstallError::OnDialogReady(
Istiaque Ahmed52f8fec2021-05-19 20:15:39472 std::unique_ptr<ExtensionInstallPromptShowParams> show_params,
Yi Gu7fabef122020-12-16 13:03:31473 ExtensionInstallPrompt::DoneCallback callback,
dchengc963c7142016-04-08 03:55:22474 std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt) {
dcheng1fc00f12015-12-26 22:18:03475 prompt_ = std::move(prompt);
[email protected]2894a512014-06-26 19:03:56476
477 if (alert_type_ == BUBBLE_ALERT) {
Peter Boströmf47f505d2021-04-15 05:03:20478 global_error_ =
479 std::make_unique<ExternalInstallBubbleAlert>(this, prompt_.get());
avi2451b252016-12-13 16:55:17480 error_service_->AddUnownedGlobalError(global_error_.get());
[email protected]2894a512014-06-26 19:03:56481
lazyboy1899eec42016-03-08 19:00:50482 if (!manager_->has_currently_visible_install_alert()) {
483 // |browser| is nullptr during unit tests, so call
484 // DidChangeInstallAlertVisibility() regardless because we depend on this
485 // in unit tests.
486 manager_->DidChangeInstallAlertVisibility(this, true);
487 Browser* browser = chrome::FindTabbedBrowser(
488 Profile::FromBrowserContext(browser_context_), true);
489 if (browser)
490 global_error_->ShowBubbleView(browser);
491 }
[email protected]2894a512014-06-26 19:03:56492 } else {
493 DCHECK(alert_type_ == MENU_ALERT);
Peter Boströmf47f505d2021-04-15 05:03:20494 global_error_ = std::make_unique<ExternalInstallMenuAlert>(this);
avi2451b252016-12-13 16:55:17495 error_service_->AddUnownedGlobalError(global_error_.get());
[email protected]2894a512014-06-26 19:03:56496 }
497}
498
rdevlin.croninb2daf2e42016-01-14 20:00:54499void ExternalInstallError::RemoveError() {
500 manager_->RemoveExternalInstallError(extension_id_);
501}
502
[email protected]2894a512014-06-26 19:03:56503} // namespace extensions