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   // Delete Combobox as it holds a reference to us.
     44   delete browsers_combo_;
     45 }
     46 
     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 
    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 
    131 bool UninstallView::Cancel() {
    132   user_selection_ = chrome::RESULT_CODE_UNINSTALL_USER_CANCEL;
    133   return true;
    134 }
    135 
    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);
    142 }
    143 
    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 
    153 base::string16 UninstallView::GetWindowTitle() const {
    154   return l10n_util::GetStringUTF16(IDS_UNINSTALL_CHROME);
    155 }
    156 
    157 int UninstallView::GetItemCount() const {
    158   DCHECK(!browsers_->empty());
    159   return browsers_->size();
    160 }
    161 
    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 
    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