Home | History | Annotate | Download | only in views
      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 
     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 
     39 UninstallView::~UninstallView() {
     40   // Exit the message loop we were started with so that uninstall can continue.
     41   quit_closure_.Run();
     42 }
     43 
     44 void UninstallView::SetupControls() {
     45   using views::ColumnSet;
     46   using views::GridLayout;
     47 
     48   GridLayout* layout = GridLayout::CreatePanel(this);
     49   SetLayoutManager(layout);
     50 
     51   // Message to confirm uninstallation.
     52   int column_set_id = 0;
     53   ColumnSet* column_set = layout->AddColumnSet(column_set_id);
     54   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
     55                         GridLayout::USE_PREF, 0, 0);
     56   layout->StartRow(0, column_set_id);
     57   confirm_label_ = new views::Label(
     58       l10n_util::GetStringUTF16(IDS_UNINSTALL_VERIFY));
     59   confirm_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
     60   layout->AddView(confirm_label_);
     61 
     62   layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
     63 
     64   // The "delete profile" check box.
     65   if (show_delete_profile_) {
     66     ++column_set_id;
     67     column_set = layout->AddColumnSet(column_set_id);
     68     column_set->AddPaddingColumn(0, views::kPanelHorizIndentation);
     69     column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
     70                           GridLayout::USE_PREF, 0, 0);
     71     layout->StartRow(0, column_set_id);
     72     delete_profile_ = new views::Checkbox(
     73         l10n_util::GetStringUTF16(IDS_UNINSTALL_DELETE_PROFILE));
     74     layout->AddView(delete_profile_);
     75   }
     76 
     77   // Set default browser combo box. If the default should not or cannot be
     78   // changed, widgets are not shown. We assume here that if Chrome cannot
     79   // be set programatically as default, neither can any other browser (for
     80   // instance because the OS doesn't permit that).
     81   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
     82   if (dist->CanSetAsDefault() &&
     83       ShellIntegration::GetDefaultBrowser() == ShellIntegration::IS_DEFAULT &&
     84       (ShellIntegration::CanSetAsDefaultBrowser() !=
     85           ShellIntegration::SET_DEFAULT_INTERACTIVE)) {
     86     browsers_.reset(new BrowsersMap());
     87     ShellUtil::GetRegisteredBrowsers(dist, browsers_.get());
     88     if (!browsers_->empty()) {
     89       layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
     90 
     91       ++column_set_id;
     92       column_set = layout->AddColumnSet(column_set_id);
     93       column_set->AddPaddingColumn(0, views::kPanelHorizIndentation);
     94       column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
     95                             GridLayout::USE_PREF, 0, 0);
     96       column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
     97       column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
     98                             GridLayout::USE_PREF, 0, 0);
     99       layout->StartRow(0, column_set_id);
    100       change_default_browser_ = new views::Checkbox(
    101           l10n_util::GetStringUTF16(IDS_UNINSTALL_SET_DEFAULT_BROWSER));
    102       change_default_browser_->set_listener(this);
    103       layout->AddView(change_default_browser_);
    104       browsers_combo_ = new views::Combobox(this);
    105       layout->AddView(browsers_combo_);
    106       browsers_combo_->SetEnabled(false);
    107     }
    108   }
    109 
    110   layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing);
    111 }
    112 
    113 bool UninstallView::Accept() {
    114   user_selection_ = content::RESULT_CODE_NORMAL_EXIT;
    115   if (show_delete_profile_ && delete_profile_->checked())
    116     user_selection_ = chrome::RESULT_CODE_UNINSTALL_DELETE_PROFILE;
    117   if (change_default_browser_ && change_default_browser_->checked()) {
    118     BrowsersMap::const_iterator i = browsers_->begin();
    119     std::advance(i, browsers_combo_->selected_index());
    120     base::LaunchOptions options;
    121     options.start_hidden = true;
    122     base::LaunchProcess(i->second, options, NULL);
    123   }
    124   return true;
    125 }
    126 
    127 bool UninstallView::Cancel() {
    128   user_selection_ = chrome::RESULT_CODE_UNINSTALL_USER_CANCEL;
    129   return true;
    130 }
    131 
    132 string16 UninstallView::GetDialogButtonLabel(ui::DialogButton button) const {
    133   // Label the OK button 'Uninstall'; Cancel remains the same.
    134   if (button == ui::DIALOG_BUTTON_OK)
    135     return l10n_util::GetStringUTF16(IDS_UNINSTALL_BUTTON_TEXT);
    136   return views::DialogDelegateView::GetDialogButtonLabel(button);
    137 }
    138 
    139 void UninstallView::ButtonPressed(views::Button* sender,
    140                                   const ui::Event& event) {
    141   if (change_default_browser_ == sender) {
    142     // Disable the browsers combobox if the user unchecks the checkbox.
    143     DCHECK(browsers_combo_);
    144     browsers_combo_->SetEnabled(change_default_browser_->checked());
    145   }
    146 }
    147 
    148 string16 UninstallView::GetWindowTitle() const {
    149   return l10n_util::GetStringUTF16(IDS_UNINSTALL_CHROME);
    150 }
    151 
    152 int UninstallView::GetItemCount() const {
    153   DCHECK(!browsers_->empty());
    154   return browsers_->size();
    155 }
    156 
    157 string16 UninstallView::GetItemAt(int index) {
    158   DCHECK_LT(index, static_cast<int>(browsers_->size()));
    159   BrowsersMap::const_iterator i = browsers_->begin();
    160   std::advance(i, index);
    161   return i->first;
    162 }
    163 
    164 namespace chrome {
    165 
    166 int ShowUninstallBrowserPrompt(bool show_delete_profile) {
    167   DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
    168   int result = content::RESULT_CODE_NORMAL_EXIT;
    169   views::AcceleratorHandler accelerator_handler;
    170 
    171   // Take a reference on g_browser_process while showing the dialog. This is
    172   // done because the dialog uses the views framework which may increment
    173   // and decrement the module ref count during the course of displaying UI and
    174   // this code can be called while the module refcount is still at 0.
    175   // Note that this reference is never released, as this code is shown on a path
    176   // that immediately exits Chrome anyway.
    177   // See http://crbug.com/241366 for details.
    178   g_browser_process->AddRefModule();
    179 
    180   base::RunLoop run_loop(&accelerator_handler);
    181   UninstallView* view = new UninstallView(&result,
    182                                           run_loop.QuitClosure(),
    183                                           show_delete_profile);
    184   views::DialogDelegate::CreateDialogWidget(view, NULL, NULL)->Show();
    185   run_loop.Run();
    186   return result;
    187 }
    188 
    189 }  // namespace chrome
    190