blob: 61a31afa6ee41930edec3f0f3f4bb2f8a9b02193 [file] [log] [blame]
[email protected]6280b5882012-06-05 21:56:411// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]502e39612011-03-26 01:36:282// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_UNINSTALL_DIALOG_H_
6#define CHROME_BROWSER_EXTENSIONS_EXTENSION_UNINSTALL_DIALOG_H_
[email protected]502e39612011-03-26 01:36:287
rdevlin.croninac8ce8c2015-05-27 23:00:028#include "base/macros.h"
[email protected]6280b5882012-06-05 21:56:419#include "base/memory/weak_ptr.h"
khmel0df822022017-06-23 02:02:5610#include "base/scoped_observer.h"
rdevlin.croninac8ce8c2015-05-27 23:00:0211#include "base/strings/string16.h"
12#include "base/threading/thread_checker.h"
khmel0df822022017-06-23 02:02:5613#include "chrome/browser/extensions/chrome_app_icon.h"
14#include "chrome/browser/extensions/chrome_app_icon_delegate.h"
15#include "extensions/browser/extension_registry_observer.h"
rdevlin.croninac8ce8c2015-05-27 23:00:0216#include "extensions/browser/uninstall_reason.h"
[email protected]6280b5882012-06-05 21:56:4117#include "ui/gfx/image/image_skia.h"
[email protected]2a4939a2014-07-25 09:22:5218#include "ui/gfx/native_widget_types.h"
[email protected]502e39612011-03-26 01:36:2819
khmel0df822022017-06-23 02:02:5620class NativeWindowTracker;
[email protected]520414b12013-01-22 19:27:3621class Profile;
[email protected]502e39612011-03-26 01:36:2822
[email protected]d4050672014-06-04 09:18:4023namespace extensions {
24class Extension;
25
[email protected]52112222012-04-07 00:52:3726class ExtensionUninstallDialog
khmel0df822022017-06-23 02:02:5627 : public base::SupportsWeakPtr<ExtensionUninstallDialog>,
28 public ChromeAppIconDelegate,
29 public ExtensionRegistryObserver {
[email protected]502e39612011-03-26 01:36:2830 public:
Bettina Dea7264a04b62018-04-06 04:27:4531 // Implement this callback to handle checking for the dialog's header message.
32 using OnWillShowCallback =
33 base::RepeatingCallback<void(ExtensionUninstallDialog*)>;
34
rdevlin.cronin4f01c5f12015-05-07 17:52:0035 // The type of action the dialog took at close.
36 // Do not reorder this enum, as it is used in UMA histograms.
37 enum CloseAction {
38 CLOSE_ACTION_UNINSTALL = 0,
39 CLOSE_ACTION_UNINSTALL_AND_REPORT_ABUSE = 1,
40 CLOSE_ACTION_CANCELED = 2,
41 CLOSE_ACTION_LAST = 3,
42 };
43
rdevlin.croninac8ce8c2015-05-27 23:00:0244 // TODO(devlin): For a single method like this, a callback is probably more
45 // appropriate than a delegate.
[email protected]502e39612011-03-26 01:36:2846 class Delegate {
47 public:
rdevlin.croninac8ce8c2015-05-27 23:00:0248 // Called when the dialog closes.
49 // |did_start_uninstall| indicates whether the uninstall process for the
50 // extension started. If this is false, |error| will contain the reason.
Alan Cuttera0ec9e442018-08-27 01:18:0651 virtual void OnExtensionUninstallDialogClosed(bool did_start_uninstall,
52 const base::string16& error) {
53 }
[email protected]502e39612011-03-26 01:36:2854
55 protected:
56 virtual ~Delegate() {}
57 };
58
[email protected]2a4939a2014-07-25 09:22:5259 // Creates a platform specific implementation of ExtensionUninstallDialog. The
60 // dialog will be modal to |parent|, or a non-modal dialog if |parent| is
61 // NULL.
[email protected]520414b12013-01-22 19:27:3662 static ExtensionUninstallDialog* Create(Profile* profile,
[email protected]2a4939a2014-07-25 09:22:5263 gfx::NativeWindow parent,
[email protected]520414b12013-01-22 19:27:3664 Delegate* delegate);
[email protected]6f03db062011-09-22 20:37:1465
Elly Fong-Jonescfb855652017-07-25 16:41:3766 // Create the Views implementation of ExtensionUninstallDialog, for use on
67 // platforms where that is not the native platform implementation.
68 static ExtensionUninstallDialog* CreateViews(Profile* profile,
69 gfx::NativeWindow parent,
70 Delegate* delegate);
71
khmel0df822022017-06-23 02:02:5672 ~ExtensionUninstallDialog() override;
[email protected]502e39612011-03-26 01:36:2873
[email protected]6f03db062011-09-22 20:37:1474 // This is called to verify whether the uninstallation should proceed.
[email protected]502e39612011-03-26 01:36:2875 // Starts the process of showing a confirmation UI, which is split into two.
76 // 1) Set off a 'load icon' task.
77 // 2) Handle the load icon response and show the UI (OnImageLoaded).
rdevlin.croninac8ce8c2015-05-27 23:00:0278 void ConfirmUninstall(const scoped_refptr<const Extension>& extension,
rdevlin.cronine18eb8cd2015-07-16 16:31:2879 UninstallReason reason,
80 UninstallSource source);
[email protected]6f03db062011-09-22 20:37:1481
[email protected]226d79ad2014-03-14 21:34:5782 // This shows the same dialog as above, except it also shows which extension
rdevlin.croninac8ce8c2015-05-27 23:00:0283 // triggered the dialog.
84 void ConfirmUninstallByExtension(
85 const scoped_refptr<const Extension>& extension,
86 const scoped_refptr<const Extension>& triggering_extension,
rdevlin.cronine18eb8cd2015-07-16 16:31:2887 UninstallReason reason,
88 UninstallSource source);
[email protected]226d79ad2014-03-14 21:34:5789
90 std::string GetHeadingText();
91
rdevlin.croninf3af70d52015-03-20 03:55:0492 // Returns true if a checkbox for reporting abuse should be shown.
93 bool ShouldShowReportAbuseCheckbox() const;
94
rdevlin.cronin4f01c5f12015-05-07 17:52:0095 // Called when the dialog is closing to do any book-keeping.
96 void OnDialogClosed(CloseAction action);
97
Bettina Dea7264a04b62018-04-06 04:27:4598 // Called from unit test to check callbacks in dialog.
99 static void SetOnShownCallbackForTesting(OnWillShowCallback* callback);
100
[email protected]6f03db062011-09-22 20:37:14101 protected:
102 // Constructor used by the derived classes.
khmel0df822022017-06-23 02:02:56103 ExtensionUninstallDialog(Profile* profile,
104 gfx::NativeWindow parent,
105 Delegate* delegate);
[email protected]520414b12013-01-22 19:27:36106
rdevlin.croninac8ce8c2015-05-27 23:00:02107 // Accessors for members.
kcarattinic4fee662015-05-26 06:02:55108 const Profile* profile() const { return profile_; }
109 Delegate* delegate() const { return delegate_; }
110 const Extension* extension() const { return extension_.get(); }
111 const Extension* triggering_extension() const {
112 return triggering_extension_.get(); }
khmel0df822022017-06-23 02:02:56113 const gfx::ImageSkia& icon() const { return icon_->image_skia(); }
114 gfx::NativeWindow parent() { return parent_; }
kcarattinic4fee662015-05-26 06:02:55115
116 private:
catmullingsff559d92017-05-20 01:43:36117 // Uninstalls the extension. Returns true on success, and populates |error| on
118 // failure.
119 bool Uninstall(base::string16* error);
120
rdevlin.croninac8ce8c2015-05-27 23:00:02121 // Handles the "report abuse" checkbox being checked at the close of the
122 // dialog.
123 void HandleReportAbuse();
124
khmel0df822022017-06-23 02:02:56125 // ChromeAppIconDelegate:
126 void OnIconUpdated(ChromeAppIcon* icon) override;
kcarattinic4fee662015-05-26 06:02:55127
khmel0df822022017-06-23 02:02:56128 // ExtensionRegistryObserver:
129 void OnExtensionUninstalled(content::BrowserContext* browser_context,
130 const Extension* extension,
131 UninstallReason reason) override;
kcarattinic4fee662015-05-26 06:02:55132
133 // Displays the prompt. This should only be called after loading the icon.
134 // The implementations of this method are platform-specific.
135 virtual void Show() = 0;
136
[email protected]520414b12013-01-22 19:27:36137 Profile* const profile_;
[email protected]6f03db062011-09-22 20:37:14138
khmel0df822022017-06-23 02:02:56139 // The dialog's parent window.
140 gfx::NativeWindow parent_;
141
[email protected]6f03db062011-09-22 20:37:14142 // The delegate we will call Accepted/Canceled on after confirmation dialog.
143 Delegate* delegate_;
144
145 // The extension we are showing the dialog for.
rdevlin.cronin903676442015-05-15 18:34:10146 scoped_refptr<const Extension> extension_;
[email protected]6f03db062011-09-22 20:37:14147
[email protected]226d79ad2014-03-14 21:34:57148 // The extension triggering the dialog if the dialog was shown by
149 // chrome.management.uninstall.
rdevlin.cronin903676442015-05-15 18:34:10150 scoped_refptr<const Extension> triggering_extension_;
[email protected]226d79ad2014-03-14 21:34:57151
khmel0df822022017-06-23 02:02:56152 std::unique_ptr<ChromeAppIcon> icon_;
[email protected]502e39612011-03-26 01:36:28153
khmel0df822022017-06-23 02:02:56154 // Tracks whether |parent_| got destroyed.
155 std::unique_ptr<NativeWindowTracker> parent_window_tracker_;
156
157 // Indicates that dialog was shown.
158 bool dialog_shown_ = false;
159
160 UninstallReason uninstall_reason_ = UNINSTALL_REASON_FOR_TESTING;
161
162 ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> observer_;
rdevlin.croninac8ce8c2015-05-27 23:00:02163
164 base::ThreadChecker thread_checker_;
[email protected]502e39612011-03-26 01:36:28165
[email protected]502e39612011-03-26 01:36:28166 DISALLOW_COPY_AND_ASSIGN(ExtensionUninstallDialog);
167};
168
[email protected]d4050672014-06-04 09:18:40169} // namespace extensions
170
[email protected]502e39612011-03-26 01:36:28171#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_UNINSTALL_DIALOG_H_