• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/ui/views/uninstall_view.h"
6 
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"
25 
UninstallView(int * user_selection,const base::Closure & quit_closure,bool show_delete_profile)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) {
36   SetupControls();
37 }
38 
~UninstallView()39 UninstallView::~UninstallView() {
40   // Exit the message loop we were started with so that uninstall can continue.
41   quit_closure_.Run();
42 
43   // Delete Combobox as it holds a reference to us.
44   delete browsers_combo_;
45 }
46 
SetupControls()47 void UninstallView::SetupControls() {
48   using views::ColumnSet;
49   using views::GridLayout;
50 
51   GridLayout* layout = GridLayout::CreatePanel(this);
52   SetLayoutManager(layout);
53 
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_);
64 
65   layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
66 
67   // The "delete profile" check box.
68   if (show_delete_profile_) {
69     ++column_set_id;
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_);
78   }
79 
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);
94 
95       ++column_set_id;
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);
111     }
112   }
113 
114   layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
115 }
116 
Accept()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);
127   }
128   return true;
129 }
130 
Cancel()131 bool UninstallView::Cancel() {
132   user_selection_ = chrome::RESULT_CODE_UNINSTALL_USER_CANCEL;
133   return true;
134 }
135 
GetDialogButtonLabel(ui::DialogButton button) const136 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);
142 }
143 
ButtonPressed(views::Button * sender,const ui::Event & event)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());
150   }
151 }
152 
GetWindowTitle() const153 base::string16 UninstallView::GetWindowTitle() const {
154   return l10n_util::GetStringUTF16(IDS_UNINSTALL_CHROME);
155 }
156 
GetItemCount() const157 int UninstallView::GetItemCount() const {
158   DCHECK(!browsers_->empty());
159   return browsers_->size();
160 }
161 
GetItemAt(int index)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);
166   return i->first;
167 }
168 
169 namespace chrome {
170 
ShowUninstallBrowserPrompt(bool show_delete_profile)171 int ShowUninstallBrowserPrompt(bool show_delete_profile) {
172   DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
173   int result = content::RESULT_CODE_NORMAL_EXIT;
174   views::AcceleratorHandler accelerator_handler;
175 
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();
184 
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();
190   run_loop.Run();
191   return result;
192 }
193 
194 }  // namespace chrome
195