15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/uninstall_view.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 79ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 8bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/launch.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/run_loop.h" 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/browser_process.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/shell_integration.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/uninstall_browser_prompt.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_result_codes.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/browser_distribution.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/shell_util.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/chromium_strings.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/button/checkbox.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/combobox/combobox.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/label.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/focus/accelerator_handler.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/grid_layout.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/layout/layout_constants.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UninstallView::UninstallView(int* user_selection, 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Closure& quit_closure, 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool show_delete_profile) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : confirm_label_(NULL), 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) show_delete_profile_(show_delete_profile), 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete_profile_(NULL), 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) change_default_browser_(NULL), 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browsers_combo_(NULL), 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_selection_(*user_selection), 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) quit_closure_(quit_closure) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetupControls(); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UninstallView::~UninstallView() { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Exit the message loop we were started with so that uninstall can continue. 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) quit_closure_.Run(); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UninstallView::SetupControls() { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using views::ColumnSet; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) using views::GridLayout; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GridLayout* layout = GridLayout::CreatePanel(this); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetLayoutManager(layout); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Message to confirm uninstallation. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int column_set_id = 0; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ColumnSet* column_set = layout->AddColumnSet(column_set_id); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GridLayout::USE_PREF, 0, 0); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->StartRow(0, column_set_id); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) confirm_label_ = new views::Label( 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_UNINSTALL_VERIFY)); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) confirm_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddView(confirm_label_); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The "delete profile" check box. 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (show_delete_profile_) { 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++column_set_id; 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) column_set = layout->AddColumnSet(column_set_id); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) column_set->AddPaddingColumn(0, views::kPanelHorizIndentation); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GridLayout::USE_PREF, 0, 0); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) layout->StartRow(0, column_set_id); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete_profile_ = new views::Checkbox( 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) l10n_util::GetStringUTF16(IDS_UNINSTALL_DELETE_PROFILE)); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) layout->AddView(delete_profile_); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set default browser combo box. If the default should not or cannot be 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // changed, widgets are not shown. We assume here that if Chrome cannot 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be set programatically as default, neither can any other browser (for 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instance because the OS doesn't permit that). 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dist->CanSetAsDefault() && 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ShellIntegration::GetDefaultBrowser() == ShellIntegration::IS_DEFAULT && 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (ShellIntegration::CanSetAsDefaultBrowser() != 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellIntegration::SET_DEFAULT_INTERACTIVE)) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browsers_.reset(new BrowsersMap()); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellUtil::GetRegisteredBrowsers(dist, browsers_.get()); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!browsers_->empty()) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++column_set_id; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) column_set = layout->AddColumnSet(column_set_id); 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) column_set->AddPaddingColumn(0, views::kPanelHorizIndentation); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GridLayout::USE_PREF, 0, 0); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GridLayout::USE_PREF, 0, 0); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->StartRow(0, column_set_id); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) change_default_browser_ = new views::Checkbox( 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l10n_util::GetStringUTF16(IDS_UNINSTALL_SET_DEFAULT_BROWSER)); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) change_default_browser_->set_listener(this); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddView(change_default_browser_); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browsers_combo_ = new views::Combobox(this); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddView(browsers_combo_); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browsers_combo_->SetEnabled(false); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UninstallView::Accept() { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_selection_ = content::RESULT_CODE_NORMAL_EXIT; 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (show_delete_profile_ && delete_profile_->checked()) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_selection_ = chrome::RESULT_CODE_UNINSTALL_DELETE_PROFILE; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (change_default_browser_ && change_default_browser_->checked()) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowsersMap::const_iterator i = browsers_->begin(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::advance(i, browsers_combo_->selected_index()); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchOptions options; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.start_hidden = true; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::LaunchProcess(i->second, options, NULL); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UninstallView::Cancel() { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_selection_ = chrome::RESULT_CODE_UNINSTALL_USER_CANCEL; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 UninstallView::GetDialogButtonLabel(ui::DialogButton button) const { 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Label the OK button 'Uninstall'; Cancel remains the same. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (button == ui::DIALOG_BUTTON_OK) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return l10n_util::GetStringUTF16(IDS_UNINSTALL_BUTTON_TEXT); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return views::DialogDelegateView::GetDialogButtonLabel(button); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UninstallView::ButtonPressed(views::Button* sender, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::Event& event) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (change_default_browser_ == sender) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Disable the browsers combobox if the user unchecks the checkbox. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(browsers_combo_); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browsers_combo_->SetEnabled(change_default_browser_->checked()); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 UninstallView::GetWindowTitle() const { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return l10n_util::GetStringUTF16(IDS_UNINSTALL_CHROME); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int UninstallView::GetItemCount() const { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!browsers_->empty()); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return browsers_->size(); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 UninstallView::GetItemAt(int index) { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(index, static_cast<int>(browsers_->size())); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowsersMap::const_iterator i = browsers_->begin(); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::advance(i, index); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i->first; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int ShowUninstallBrowserPrompt(bool show_delete_profile) { 167b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type()); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = content::RESULT_CODE_NORMAL_EXIT; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::AcceleratorHandler accelerator_handler; 17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Take a reference on g_browser_process while showing the dialog. This is 17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // done because the dialog uses the views framework which may increment 17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // and decrement the module ref count during the course of displaying UI and 17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // this code can be called while the module refcount is still at 0. 17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Note that this reference is never released, as this code is shown on a path 17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // that immediately exits Chrome anyway. 17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // See http://crbug.com/241366 for details. 17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) g_browser_process->AddRefModule(); 17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::RunLoop run_loop(&accelerator_handler); 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UninstallView* view = new UninstallView(&result, 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) run_loop.QuitClosure(), 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) show_delete_profile); 18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) views::DialogDelegate::CreateDialogWidget(view, NULL, NULL)->Show(); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) run_loop.Run(); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace chrome 190