blob: cb4172ff2a5e462fcaf05f80e766161b524a1189 [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() {
246 std::vector<base::string16> messages;
treib5e16e452015-06-19 09:55:39247 int heading_id =
248 IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_BUBBLE_HEADING_EXTENSION;
249 if (prompt_->extension()->is_app())
250 heading_id = IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_BUBBLE_HEADING_APP;
251 else if (prompt_->extension()->is_theme())
252 heading_id = IDS_EXTENSION_EXTERNAL_INSTALL_ALERT_BUBBLE_HEADING_THEME;
253 messages.push_back(l10n_util::GetStringUTF16(heading_id));
254
Devlin Cronind6e136a2018-05-15 23:39:32255 if (prompt_->GetPermissionCount()) {
256 messages.push_back(prompt_->GetPermissionsHeading());
257 for (size_t i = 0; i < prompt_->GetPermissionCount(); ++i) {
[email protected]2894a512014-06-26 19:03:56258 messages.push_back(l10n_util::GetStringFUTF16(
Devlin Cronind6e136a2018-05-15 23:39:32259 IDS_EXTENSION_PERMISSION_LINE, prompt_->GetPermission(i)));
[email protected]2894a512014-06-26 19:03:56260 }
261 }
262 // TODO(yoz): OAuth issue advice?
263 return messages;
264}
265
probergebc529d62018-04-24 14:48:26266int ExternalInstallBubbleAlert::GetDefaultDialogButton() const {
267 switch (error_->default_dialog_button_setting()) {
268 case ExternalInstallError::DIALOG_BUTTON_OK:
269 return ui::DIALOG_BUTTON_OK;
270 case ExternalInstallError::DIALOG_BUTTON_CANCEL:
271 return ui::DIALOG_BUTTON_CANCEL;
272 case ExternalInstallError::NO_DEFAULT_DIALOG_BUTTON:
273 return ui::DIALOG_BUTTON_NONE;
274 case ExternalInstallError::NOT_SPECIFIED:
275 break;
276 }
277 return GlobalErrorWithStandardBubble::GetDefaultDialogButton();
278}
279
[email protected]2894a512014-06-26 19:03:56280base::string16 ExternalInstallBubbleAlert::GetBubbleViewAcceptButtonLabel() {
281 return prompt_->GetAcceptButtonLabel();
282}
283
284base::string16 ExternalInstallBubbleAlert::GetBubbleViewCancelButtonLabel() {
285 return prompt_->GetAbortButtonLabel();
286}
287
288void ExternalInstallBubbleAlert::OnBubbleViewDidClose(Browser* browser) {
lazyboy1899eec42016-03-08 19:00:50289 error_->DidCloseBubbleView();
[email protected]2894a512014-06-26 19:03:56290}
291
292void ExternalInstallBubbleAlert::BubbleViewAcceptButtonPressed(
293 Browser* browser) {
rdevlin.cronin41593052016-01-08 01:40:12294 error_->OnInstallPromptDone(ExtensionInstallPrompt::Result::ACCEPTED);
[email protected]2894a512014-06-26 19:03:56295}
296
297void ExternalInstallBubbleAlert::BubbleViewCancelButtonPressed(
298 Browser* browser) {
rdevlin.cronin41593052016-01-08 01:40:12299 error_->OnInstallPromptDone(ExtensionInstallPrompt::Result::USER_CANCELED);
[email protected]2894a512014-06-26 19:03:56300}
301
302} // namespace
303
304////////////////////////////////////////////////////////////////////////////////
305// ExternalInstallError
306
probergebc529d62018-04-24 14:48:26307// static
308ExternalInstallError::DefaultDialogButtonSetting
309ExternalInstallError::GetDefaultDialogButton(
310 const base::Value& webstore_response) {
311 const base::Value* value = webstore_response.FindKeyOfType(
312 kExternalInstallDefaultButtonKey, base::Value::Type::STRING);
313 if (value) {
314 return MapDefaultButtonStringToSetting(value->GetString());
315 }
316
317 if (base::FeatureList::IsEnabled(
Oscar Johansson7f4c1b932018-06-12 06:11:58318 ::features::kExternalExtensionDefaultButtonControl)) {
probergebc529d62018-04-24 14:48:26319 std::string default_button = base::GetFieldTrialParamValueByFeature(
Oscar Johansson7f4c1b932018-06-12 06:11:58320 ::features::kExternalExtensionDefaultButtonControl,
probergebc529d62018-04-24 14:48:26321 kExternalInstallDefaultButtonKey);
322 if (!default_button.empty()) {
323 return MapDefaultButtonStringToSetting(default_button);
324 }
325 }
326
327 return NOT_SPECIFIED;
328}
329
[email protected]2894a512014-06-26 19:03:56330ExternalInstallError::ExternalInstallError(
331 content::BrowserContext* browser_context,
332 const std::string& extension_id,
333 AlertType alert_type,
334 ExternalInstallManager* manager)
335 : browser_context_(browser_context),
336 extension_id_(extension_id),
337 alert_type_(alert_type),
338 manager_(manager),
339 error_service_(GlobalErrorServiceFactory::GetForProfile(
Jeremy Roman495db682019-07-12 16:03:24340 Profile::FromBrowserContext(browser_context_))) {
rdevlin.cronin2e252692015-12-15 21:47:02341 prompt_.reset(new ExtensionInstallPrompt::Prompt(
342 ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT));
[email protected]2894a512014-06-26 19:03:56343
Mark Pilgrim1a72e0512018-04-25 13:48:48344 webstore_data_fetcher_.reset(
345 new WebstoreDataFetcher(this, GURL(), extension_id_));
346 webstore_data_fetcher_->Start(
347 content::BrowserContext::GetDefaultStoragePartition(browser_context_)
348 ->GetURLLoaderFactoryForBrowserProcess()
349 .get());
[email protected]2894a512014-06-26 19:03:56350}
351
352ExternalInstallError::~ExternalInstallError() {
rdevlin.cronina1c3f1a2017-05-18 17:45:46353#if DCHECK_IS_ON()
354 // Errors should only be removed while the profile is valid, since removing
355 // the error can trigger other subsystems listening for changes.
356 BrowserContextDependencyManager::GetInstance()
357 ->AssertBrowserContextWasntDestroyed(browser_context_);
358#endif
[email protected]2894a512014-06-26 19:03:56359 if (global_error_.get())
avi2451b252016-12-13 16:55:17360 error_service_->RemoveUnownedGlobalError(global_error_.get());
[email protected]2894a512014-06-26 19:03:56361}
362
rdevlin.cronin41593052016-01-08 01:40:12363void ExternalInstallError::OnInstallPromptDone(
364 ExtensionInstallPrompt::Result result) {
[email protected]2894a512014-06-26 19:03:56365 const Extension* extension = GetExtension();
rdevlin.croninb2daf2e42016-01-14 20:00:54366
367 // If the error isn't removed and deleted as part of handling the user's
368 // response (which can happen, e.g., if an uninstall fails), be sure to remove
369 // the error directly in order to ensure it's not called twice.
fdoray283082bd2016-06-02 20:18:46370 base::ThreadTaskRunnerHandle::Get()->PostTask(
tzik8d880ee2017-04-20 19:46:24371 FROM_HERE, base::BindOnce(&ExternalInstallError::RemoveError,
372 weak_factory_.GetWeakPtr()));
rdevlin.croninb2daf2e42016-01-14 20:00:54373
rdevlin.cronin41593052016-01-08 01:40:12374 switch (result) {
375 case ExtensionInstallPrompt::Result::ACCEPTED:
376 if (extension) {
377 ExtensionSystem::Get(browser_context_)
378 ->extension_service()
379 ->GrantPermissionsAndEnableExtension(extension);
rdevlin.cronin41593052016-01-08 01:40:12380 }
381 break;
382 case ExtensionInstallPrompt::Result::USER_CANCELED:
383 if (extension) {
Devlin Cronin24cd22c32019-01-29 18:14:36384 ExtensionSystem::Get(browser_context_)
rdevlin.cronin41593052016-01-08 01:40:12385 ->extension_service()
386 ->UninstallExtension(extension_id_,
387 extensions::UNINSTALL_REASON_INSTALL_CANCELED,
rdevlin.cronin41593052016-01-08 01:40:12388 nullptr); // Ignore error.
rdevlin.cronin41593052016-01-08 01:40:12389 }
390 break;
391 case ExtensionInstallPrompt::Result::ABORTED:
lazyboy1899eec42016-03-08 19:00:50392 manager_->DidChangeInstallAlertVisibility(this, false);
rdevlin.cronin41593052016-01-08 01:40:12393 break;
[email protected]2894a512014-06-26 19:03:56394 }
rdevlin.croninb2daf2e42016-01-14 20:00:54395 // NOTE: We may be deleted here!
[email protected]2894a512014-06-26 19:03:56396}
397
lazyboy1899eec42016-03-08 19:00:50398void ExternalInstallError::DidOpenBubbleView() {
399 manager_->DidChangeInstallAlertVisibility(this, true);
400}
401
402void ExternalInstallError::DidCloseBubbleView() {
403 manager_->DidChangeInstallAlertVisibility(this, false);
404}
405
[email protected]2894a512014-06-26 19:03:56406void ExternalInstallError::ShowDialog(Browser* browser) {
407 DCHECK(install_ui_.get());
408 DCHECK(prompt_.get());
409 DCHECK(browser);
410 content::WebContents* web_contents = NULL;
[email protected]2894a512014-06-26 19:03:56411 web_contents = browser->tab_strip_model()->GetActiveWebContents();
pkotwicz2f181782014-10-29 17:33:45412 install_ui_show_params_.reset(
413 new ExtensionInstallPromptShowParams(web_contents));
lazyboy1899eec42016-03-08 19:00:50414 manager_->DidChangeInstallAlertVisibility(this, true);
[email protected]2894a512014-06-26 19:03:56415 ExtensionInstallPrompt::GetDefaultShowDialogCallback().Run(
rdevlin.cronin41593052016-01-08 01:40:12416 install_ui_show_params_.get(),
417 base::Bind(&ExternalInstallError::OnInstallPromptDone,
418 weak_factory_.GetWeakPtr()),
419 std::move(prompt_));
[email protected]2894a512014-06-26 19:03:56420}
421
422const Extension* ExternalInstallError::GetExtension() const {
423 return ExtensionRegistry::Get(browser_context_)
424 ->GetExtensionById(extension_id_, ExtensionRegistry::EVERYTHING);
425}
426
427void ExternalInstallError::OnWebstoreRequestFailure() {
428 OnFetchComplete();
429}
430
431void ExternalInstallError::OnWebstoreResponseParseSuccess(
dchengc963c7142016-04-08 03:55:22432 std::unique_ptr<base::DictionaryValue> webstore_data) {
[email protected]2894a512014-06-26 19:03:56433 std::string localized_user_count;
[email protected]96aebe22014-07-16 04:07:51434 double average_rating = 0;
435 int rating_count = 0;
[email protected]2894a512014-06-26 19:03:56436 if (!webstore_data->GetString(kUsersKey, &localized_user_count) ||
437 !webstore_data->GetDouble(kAverageRatingKey, &average_rating) ||
438 !webstore_data->GetInteger(kRatingCountKey, &rating_count)) {
439 // If we don't get a valid webstore response, short circuit, and continue
440 // to show a prompt without webstore data.
441 OnFetchComplete();
442 return;
443 }
444
probergebc529d62018-04-24 14:48:26445 default_dialog_button_setting_ = GetDefaultDialogButton(*webstore_data.get());
446
[email protected]2894a512014-06-26 19:03:56447 bool show_user_count = true;
448 webstore_data->GetBoolean(kShowUserCountKey, &show_user_count);
449
450 prompt_->SetWebstoreData(
451 localized_user_count, show_user_count, average_rating, rating_count);
452 OnFetchComplete();
453}
454
455void ExternalInstallError::OnWebstoreResponseParseFailure(
456 const std::string& error) {
457 OnFetchComplete();
458}
459
460void ExternalInstallError::OnFetchComplete() {
461 // Create a new ExtensionInstallPrompt. We pass in NULL for the UI
462 // components because we display at a later point, and don't want
463 // to pass ones which may be invalidated.
464 install_ui_.reset(
465 new ExtensionInstallPrompt(Profile::FromBrowserContext(browser_context_),
pkotwicz2175c622014-10-22 19:56:28466 NULL)); // NULL native window.
[email protected]2894a512014-06-26 19:03:56467
rdevlin.cronin41593052016-01-08 01:40:12468 install_ui_->ShowDialog(base::Bind(&ExternalInstallError::OnInstallPromptDone,
469 weak_factory_.GetWeakPtr()),
470 GetExtension(),
rdevlin.croninf84cab72015-12-12 03:45:23471 nullptr, // Force a fetch of the icon.
dcheng1fc00f12015-12-26 22:18:03472 std::move(prompt_),
rdevlin.croninf84cab72015-12-12 03:45:23473 base::Bind(&ExternalInstallError::OnDialogReady,
474 weak_factory_.GetWeakPtr()));
[email protected]2894a512014-06-26 19:03:56475}
476
477void ExternalInstallError::OnDialogReady(
pkotwicz2f181782014-10-29 17:33:45478 ExtensionInstallPromptShowParams* show_params,
rdevlin.cronin41593052016-01-08 01:40:12479 const ExtensionInstallPrompt::DoneCallback& callback,
dchengc963c7142016-04-08 03:55:22480 std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt) {
dcheng1fc00f12015-12-26 22:18:03481 prompt_ = std::move(prompt);
[email protected]2894a512014-06-26 19:03:56482
483 if (alert_type_ == BUBBLE_ALERT) {
dchengc7047942014-08-26 05:05:31484 global_error_.reset(new ExternalInstallBubbleAlert(this, prompt_.get()));
avi2451b252016-12-13 16:55:17485 error_service_->AddUnownedGlobalError(global_error_.get());
[email protected]2894a512014-06-26 19:03:56486
lazyboy1899eec42016-03-08 19:00:50487 if (!manager_->has_currently_visible_install_alert()) {
488 // |browser| is nullptr during unit tests, so call
489 // DidChangeInstallAlertVisibility() regardless because we depend on this
490 // in unit tests.
491 manager_->DidChangeInstallAlertVisibility(this, true);
492 Browser* browser = chrome::FindTabbedBrowser(
493 Profile::FromBrowserContext(browser_context_), true);
494 if (browser)
495 global_error_->ShowBubbleView(browser);
496 }
[email protected]2894a512014-06-26 19:03:56497 } else {
498 DCHECK(alert_type_ == MENU_ALERT);
499 global_error_.reset(new ExternalInstallMenuAlert(this));
avi2451b252016-12-13 16:55:17500 error_service_->AddUnownedGlobalError(global_error_.get());
[email protected]2894a512014-06-26 19:03:56501 }
502}
503
rdevlin.croninb2daf2e42016-01-14 20:00:54504void ExternalInstallError::RemoveError() {
505 manager_->RemoveExternalInstallError(extension_id_);
506}
507
[email protected]2894a512014-06-26 19:03:56508} // namespace extensions