1 // Copyright (c) 2012 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.
5 #include "chrome/browser/ui/views/uninstall_view.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/process/launch.h"
9 #include "base/run_loop.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/shell_integration.h"
12 #include "chrome/browser/ui/uninstall_browser_prompt.h"
13 #include "chrome/common/chrome_result_codes.h"
14 #include "chrome/installer/util/browser_distribution.h"
15 #include "chrome/installer/util/shell_util.h"
16 #include "grit/chromium_strings.h"
17 #include "ui/base/l10n/l10n_util.h"
18 #include "ui/views/controls/button/checkbox.h"
19 #include "ui/views/controls/combobox/combobox.h"
20 #include "ui/views/controls/label.h"
21 #include "ui/views/focus/accelerator_handler.h"
22 #include "ui/views/layout/grid_layout.h"
23 #include "ui/views/layout/layout_constants.h"
24 #include "ui/views/widget/widget.h"
26 UninstallView::UninstallView(int* user_selection
,
27 const base::Closure
& quit_closure
,
28 bool show_delete_profile
)
29 : confirm_label_(NULL
),
30 show_delete_profile_(show_delete_profile
),
31 delete_profile_(NULL
),
32 change_default_browser_(NULL
),
33 browsers_combo_(NULL
),
34 user_selection_(*user_selection
),
35 quit_closure_(quit_closure
) {
39 UninstallView::~UninstallView() {
40 // Exit the message loop we were started with so that uninstall can continue.
43 // Delete Combobox as it holds a reference to us.
44 delete browsers_combo_
;
47 void UninstallView::SetupControls() {
48 using views::ColumnSet
;
49 using views::GridLayout
;
51 GridLayout
* layout
= GridLayout::CreatePanel(this);
52 SetLayoutManager(layout
);
54 // Message to confirm uninstallation.
55 int column_set_id
= 0;
56 ColumnSet
* column_set
= layout
->AddColumnSet(column_set_id
);
57 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
, 0,
58 GridLayout::USE_PREF
, 0, 0);
59 layout
->StartRow(0, column_set_id
);
60 confirm_label_
= new views::Label(
61 l10n_util::GetStringUTF16(IDS_UNINSTALL_VERIFY
));
62 confirm_label_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
63 layout
->AddView(confirm_label_
);
65 layout
->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing
);
67 // The "delete profile" check box.
68 if (show_delete_profile_
) {
70 column_set
= layout
->AddColumnSet(column_set_id
);
71 column_set
->AddPaddingColumn(0, views::kPanelHorizIndentation
);
72 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
, 0,
73 GridLayout::USE_PREF
, 0, 0);
74 layout
->StartRow(0, column_set_id
);
75 delete_profile_
= new views::Checkbox(
76 l10n_util::GetStringUTF16(IDS_UNINSTALL_DELETE_PROFILE
));
77 layout
->AddView(delete_profile_
);
80 // Set default browser combo box. If the default should not or cannot be
81 // changed, widgets are not shown. We assume here that if Chrome cannot
82 // be set programatically as default, neither can any other browser (for
83 // instance because the OS doesn't permit that).
84 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
85 if (dist
->GetDefaultBrowserControlPolicy() !=
86 BrowserDistribution::DEFAULT_BROWSER_UNSUPPORTED
&&
87 ShellIntegration::GetDefaultBrowser() == ShellIntegration::IS_DEFAULT
&&
88 (ShellIntegration::CanSetAsDefaultBrowser() !=
89 ShellIntegration::SET_DEFAULT_INTERACTIVE
)) {
90 browsers_
.reset(new BrowsersMap());
91 ShellUtil::GetRegisteredBrowsers(dist
, browsers_
.get());
92 if (!browsers_
->empty()) {
93 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
96 column_set
= layout
->AddColumnSet(column_set_id
);
97 column_set
->AddPaddingColumn(0, views::kPanelHorizIndentation
);
98 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
, 0,
99 GridLayout::USE_PREF
, 0, 0);
100 column_set
->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing
);
101 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
, 0,
102 GridLayout::USE_PREF
, 0, 0);
103 layout
->StartRow(0, column_set_id
);
104 change_default_browser_
= new views::Checkbox(
105 l10n_util::GetStringUTF16(IDS_UNINSTALL_SET_DEFAULT_BROWSER
));
106 change_default_browser_
->set_listener(this);
107 layout
->AddView(change_default_browser_
);
108 browsers_combo_
= new views::Combobox(this);
109 layout
->AddView(browsers_combo_
);
110 browsers_combo_
->SetEnabled(false);
114 layout
->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing
);
117 bool UninstallView::Accept() {
118 user_selection_
= content::RESULT_CODE_NORMAL_EXIT
;
119 if (show_delete_profile_
&& delete_profile_
->checked())
120 user_selection_
= chrome::RESULT_CODE_UNINSTALL_DELETE_PROFILE
;
121 if (change_default_browser_
&& change_default_browser_
->checked()) {
122 BrowsersMap::const_iterator i
= browsers_
->begin();
123 std::advance(i
, browsers_combo_
->selected_index());
124 base::LaunchOptions options
;
125 options
.start_hidden
= true;
126 base::LaunchProcess(i
->second
, options
, NULL
);
131 bool UninstallView::Cancel() {
132 user_selection_
= chrome::RESULT_CODE_UNINSTALL_USER_CANCEL
;
136 base::string16
UninstallView::GetDialogButtonLabel(
137 ui::DialogButton button
) const {
138 // Label the OK button 'Uninstall'; Cancel remains the same.
139 if (button
== ui::DIALOG_BUTTON_OK
)
140 return l10n_util::GetStringUTF16(IDS_UNINSTALL_BUTTON_TEXT
);
141 return views::DialogDelegateView::GetDialogButtonLabel(button
);
144 void UninstallView::ButtonPressed(views::Button
* sender
,
145 const ui::Event
& event
) {
146 if (change_default_browser_
== sender
) {
147 // Disable the browsers combobox if the user unchecks the checkbox.
148 DCHECK(browsers_combo_
);
149 browsers_combo_
->SetEnabled(change_default_browser_
->checked());
153 base::string16
UninstallView::GetWindowTitle() const {
154 return l10n_util::GetStringUTF16(IDS_UNINSTALL_CHROME
);
157 int UninstallView::GetItemCount() const {
158 DCHECK(!browsers_
->empty());
159 return browsers_
->size();
162 base::string16
UninstallView::GetItemAt(int index
) {
163 DCHECK_LT(index
, static_cast<int>(browsers_
->size()));
164 BrowsersMap::const_iterator i
= browsers_
->begin();
165 std::advance(i
, index
);
171 int ShowUninstallBrowserPrompt(bool show_delete_profile
) {
172 DCHECK(base::MessageLoopForUI::IsCurrent());
173 int result
= content::RESULT_CODE_NORMAL_EXIT
;
174 views::AcceleratorHandler accelerator_handler
;
176 // Take a reference on g_browser_process while showing the dialog. This is
177 // done because the dialog uses the views framework which may increment
178 // and decrement the module ref count during the course of displaying UI and
179 // this code can be called while the module refcount is still at 0.
180 // Note that this reference is never released, as this code is shown on a path
181 // that immediately exits Chrome anyway.
182 // See http://crbug.com/241366 for details.
183 g_browser_process
->AddRefModule();
185 base::RunLoop
run_loop(&accelerator_handler
);
186 UninstallView
* view
= new UninstallView(&result
,
187 run_loop
.QuitClosure(),
188 show_delete_profile
);
189 views::DialogDelegate::CreateDialogWidget(view
, NULL
, NULL
)->Show();
194 } // namespace chrome