// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/views/clear_browsing_data_view.h" #include "app/l10n_util.h" #include "base/string16.h" #include "base/utf_string_conversions.h" #include "chrome/browser/browser.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/search_engines/template_url_model.h" #include "chrome/common/pref_names.h" #include "gfx/insets.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" #include "net/url_request/url_request_context.h" #include "views/background.h" #include "views/controls/button/checkbox.h" #include "views/controls/label.h" #include "views/controls/separator.h" #include "views/controls/throbber.h" #include "views/grid_layout.h" #include "views/standard_layout.h" #include "views/widget/widget.h" #include "views/window/dialog_client_view.h" #include "views/window/window.h" using views::GridLayout; // The combo box is vertically aligned to the 'time-period' label, which makes // the combo box look a little too close to the check box above it when we use // standard layout to separate them. We therefore add a little extra margin to // the label, giving it a little breathing space. static const int kExtraMarginForTimePeriodLabel = 3; //////////////////////////////////////////////////////////////////////////////// // ClearBrowsingDataView2, public: ClearBrowsingDataView2::ClearBrowsingDataView2(Profile* profile, ClearDataView* clear_data_view) : clear_data_parent_window_(clear_data_view), allow_clear_(true), throbber_view_(NULL), throbber_(NULL), status_label_(NULL), delete_all_label_(NULL), del_history_checkbox_(NULL), del_downloads_checkbox_(NULL), del_cache_checkbox_(NULL), del_cookies_checkbox_(NULL), del_passwords_checkbox_(NULL), del_form_data_checkbox_(NULL), time_period_label_(NULL), time_period_combobox_(NULL), clear_browsing_data_button_(NULL), delete_in_progress_(false), profile_(profile), remover_(NULL) { DCHECK(profile); Init(); InitControlLayout(); } ClearBrowsingDataView2::~ClearBrowsingDataView2(void) { if (remover_) { // We were destroyed while clearing history was in progress. This can only // occur during automated tests (normally the user can't close the dialog // while clearing is in progress as the dialog is modal and not closeable). remover_->RemoveObserver(this); } } void ClearBrowsingDataView2::SetAllowClear(bool allow) { allow_clear_ = allow; UpdateControlEnabledState(); } void ClearBrowsingDataView2::Init() { throbber_ = new views::Throbber(50, true); throbber_->SetVisible(false); status_label_ = new views::Label( l10n_util::GetString(IDS_CLEAR_DATA_DELETING)); status_label_->SetVisible(false); // Regular view controls we draw by ourself. First, we add the dialog label. delete_all_label_ = new views::Label( l10n_util::GetString(IDS_CLEAR_BROWSING_DATA_LABEL)); // Add all the check-boxes. del_history_checkbox_ = AddCheckbox(l10n_util::GetString(IDS_DEL_BROWSING_HISTORY_CHKBOX), profile_->GetPrefs()->GetBoolean(prefs::kDeleteBrowsingHistory)); del_downloads_checkbox_ = AddCheckbox(l10n_util::GetString(IDS_DEL_DOWNLOAD_HISTORY_CHKBOX), profile_->GetPrefs()->GetBoolean(prefs::kDeleteDownloadHistory)); del_cache_checkbox_ = AddCheckbox(l10n_util::GetString(IDS_DEL_CACHE_CHKBOX), profile_->GetPrefs()->GetBoolean(prefs::kDeleteCache)); del_cookies_checkbox_ = AddCheckbox(l10n_util::GetString(IDS_DEL_COOKIES_CHKBOX), profile_->GetPrefs()->GetBoolean(prefs::kDeleteCookies)); del_passwords_checkbox_ = AddCheckbox(l10n_util::GetString(IDS_DEL_PASSWORDS_CHKBOX), profile_->GetPrefs()->GetBoolean(prefs::kDeletePasswords)); del_form_data_checkbox_ = AddCheckbox(l10n_util::GetString(IDS_DEL_FORM_DATA_CHKBOX), profile_->GetPrefs()->GetBoolean(prefs::kDeleteFormData)); clear_browsing_data_button_ = new views::NativeButton( this, l10n_util::GetString(IDS_CLEAR_BROWSING_DATA_BUTTON)); // Add a label which appears before the combo box for the time period. time_period_label_ = new views::Label( l10n_util::GetString(IDS_CLEAR_BROWSING_DATA_TIME_LABEL)); // Add the combo box showing how far back in time we want to delete. time_period_combobox_ = new views::Combobox(this); time_period_combobox_->SetSelectedItem(profile_->GetPrefs()->GetInteger( prefs::kDeleteTimePeriod)); time_period_combobox_->set_listener(this); time_period_combobox_->SetAccessibleName(time_period_label_->GetText()); // Create the throbber and related views. The throbber and status link are // contained in throbber_view_, which is positioned by DialogClientView right // next to the buttons. throbber_view_ = new views::View(); GridLayout* layout = new GridLayout(throbber_view_); throbber_view_->SetLayoutManager(layout); views::ColumnSet* column_set = layout->AddColumnSet(0); // DialogClientView positions the extra view at kButtonHEdgeMargin, but we // put all our controls at kPanelHorizMargin. Add a padding column so things // line up nicely. if (kPanelHorizMargin - kButtonHEdgeMargin > 0) column_set->AddPaddingColumn(0, kPanelHorizMargin - kButtonHEdgeMargin); column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, GridLayout::USE_PREF, 0, 0); column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); column_set->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, GridLayout::USE_PREF, 0, 0); layout->StartRow(1, 0); layout->AddView(throbber_); layout->AddView(status_label_); } void ClearBrowsingDataView2::InitControlLayout() { GridLayout* layout = CreatePanelGridLayout(this); this->SetLayoutManager(layout); int leading_column_set_id = 0; views::ColumnSet* column_set = layout->AddColumnSet(leading_column_set_id); column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, 0); const int indented_column_set_id = 1; column_set = layout->AddColumnSet(indented_column_set_id); column_set->AddPaddingColumn(0, views::Checkbox::GetTextIndent()); column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1, GridLayout::USE_PREF, 0, 0); const int two_column_set_id = 2; column_set = layout->AddColumnSet(two_column_set_id); column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0, GridLayout::USE_PREF, 0, 0); column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1, GridLayout::USE_PREF, 0, 0); const int fill_column_set_id = 3; column_set = layout->AddColumnSet(fill_column_set_id); column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, 0); // Delete All label goes to the top left corner. layout->StartRow(0, leading_column_set_id); layout->AddView(delete_all_label_); layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); // Check-boxes go beneath it (with a little indentation). layout->StartRow(0, indented_column_set_id); layout->AddView(del_history_checkbox_); layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); layout->StartRow(0, indented_column_set_id); layout->AddView(del_downloads_checkbox_); layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); layout->StartRow(0, indented_column_set_id); layout->AddView(del_cache_checkbox_); layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); layout->StartRow(0, indented_column_set_id); layout->AddView(del_cookies_checkbox_); layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); layout->StartRow(0, indented_column_set_id); layout->AddView(del_passwords_checkbox_); layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); layout->StartRow(0, indented_column_set_id); layout->AddView(del_form_data_checkbox_); layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); // Time period label is next below the combo boxes followed by time // period combo box layout->StartRow(0, two_column_set_id); layout->AddView(time_period_label_); time_period_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); layout->AddView(time_period_combobox_, 1, 1, views::GridLayout::LEADING, views::GridLayout::CENTER); layout->AddPaddingRow(0, kUnrelatedControlLargeVerticalSpacing); // Left-align the throbber layout->StartRow(0, two_column_set_id); layout->AddView(throbber_view_, 1, 1, GridLayout::LEADING, GridLayout::CENTER); // Right-align the clear button layout->AddView(clear_browsing_data_button_, 1, 1, GridLayout::TRAILING, GridLayout::CENTER); } //////////////////////////////////////////////////////////////////////////////// // ClearBrowsingDataView2, ComboboxModel implementation: int ClearBrowsingDataView2::GetItemCount() { return 5; } string16 ClearBrowsingDataView2::GetItemAt(int index) { switch (index) { case 0: return l10n_util::GetStringUTF16(IDS_CLEAR_DATA_HOUR); case 1: return l10n_util::GetStringUTF16(IDS_CLEAR_DATA_DAY); case 2: return l10n_util::GetStringUTF16(IDS_CLEAR_DATA_WEEK); case 3: return l10n_util::GetStringUTF16(IDS_CLEAR_DATA_4WEEKS); case 4: return l10n_util::GetStringUTF16(IDS_CLEAR_DATA_EVERYTHING); default: NOTREACHED() << "Missing item"; return ASCIIToUTF16("?"); } } //////////////////////////////////////////////////////////////////////////////// // ClearBrowsingDataView2, views::ComboBoxListener implementation: void ClearBrowsingDataView2::ItemChanged(views::Combobox* sender, int prev_index, int new_index) { if (sender == time_period_combobox_ && prev_index != new_index) profile_->GetPrefs()->SetInteger(prefs::kDeleteTimePeriod, new_index); } //////////////////////////////////////////////////////////////////////////////// // ClearBrowsingDataView2, views::ButtonListener implementation: void ClearBrowsingDataView2::ButtonPressed( views::Button* sender, const views::Event& event) { if (sender == clear_browsing_data_button_) { profile_->GetPrefs()->SetBoolean(prefs::kDeleteBrowsingHistory, del_history_checkbox_->checked() ? true : false); profile_->GetPrefs()->SetBoolean(prefs::kDeleteDownloadHistory, del_downloads_checkbox_->checked() ? true : false); profile_->GetPrefs()->SetBoolean(prefs::kDeleteCache, del_cache_checkbox_->checked() ? true : false); profile_->GetPrefs()->SetBoolean(prefs::kDeleteCookies, del_cookies_checkbox_->checked() ? true : false); profile_->GetPrefs()->SetBoolean(prefs::kDeletePasswords, del_passwords_checkbox_->checked() ? true : false); profile_->GetPrefs()->SetBoolean(prefs::kDeleteFormData, del_form_data_checkbox_->checked() ? true : false); clear_data_parent_window_->StartClearingBrowsingData(); OnDelete(); } // When no checkbox is checked we should not have the action button enabled. // This forces the button to evaluate what state they should be in. UpdateControlEnabledState(); } void ClearBrowsingDataView2::LinkActivated(views::Link* source, int event_flags) { Browser* browser = Browser::Create(profile_); browser->OpenURL(GURL(l10n_util::GetStringUTF8(IDS_FLASH_STORAGE_URL)), GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK); browser->window()->Show(); } //////////////////////////////////////////////////////////////////////////////// // ClearBrowsingDataView2, private: views::Checkbox* ClearBrowsingDataView2::AddCheckbox(const std::wstring& text, bool checked) { views::Checkbox* checkbox = new views::Checkbox(text); checkbox->SetChecked(checked); checkbox->set_listener(this); return checkbox; } void ClearBrowsingDataView2::UpdateControlEnabledState() { del_history_checkbox_->SetEnabled(!delete_in_progress_); del_downloads_checkbox_->SetEnabled(!delete_in_progress_); del_cache_checkbox_->SetEnabled(!delete_in_progress_); del_cookies_checkbox_->SetEnabled(!delete_in_progress_); del_passwords_checkbox_->SetEnabled(!delete_in_progress_); del_form_data_checkbox_->SetEnabled(!delete_in_progress_); time_period_combobox_->SetEnabled(!delete_in_progress_); status_label_->SetVisible(delete_in_progress_); throbber_->SetVisible(delete_in_progress_); if (delete_in_progress_) throbber_->Start(); else throbber_->Stop(); clear_browsing_data_button_->SetEnabled( allow_clear_ && !delete_in_progress_ && (del_history_checkbox_->checked() || del_downloads_checkbox_->checked() || del_cache_checkbox_->checked() || del_cookies_checkbox_->checked() || del_passwords_checkbox_->checked() || del_form_data_checkbox_->checked())); } // Convenience method that returns true if the supplied checkbox is selected // and enabled. static bool IsCheckBoxEnabledAndSelected(views::Checkbox* cb) { return (cb->IsEnabled() && cb->checked()); } void ClearBrowsingDataView2::OnDelete() { int period_selected = time_period_combobox_->selected_item(); int remove_mask = 0; if (IsCheckBoxEnabledAndSelected(del_history_checkbox_)) remove_mask |= BrowsingDataRemover::REMOVE_HISTORY; if (IsCheckBoxEnabledAndSelected(del_downloads_checkbox_)) remove_mask |= BrowsingDataRemover::REMOVE_DOWNLOADS; if (IsCheckBoxEnabledAndSelected(del_cookies_checkbox_)) remove_mask |= BrowsingDataRemover::REMOVE_COOKIES; if (IsCheckBoxEnabledAndSelected(del_passwords_checkbox_)) remove_mask |= BrowsingDataRemover::REMOVE_PASSWORDS; if (IsCheckBoxEnabledAndSelected(del_form_data_checkbox_)) remove_mask |= BrowsingDataRemover::REMOVE_FORM_DATA; if (IsCheckBoxEnabledAndSelected(del_cache_checkbox_)) remove_mask |= BrowsingDataRemover::REMOVE_CACHE; delete_in_progress_ = true; UpdateControlEnabledState(); // BrowsingDataRemover deletes itself when done. remover_ = new BrowsingDataRemover(profile_, static_cast(period_selected), base::Time()); remover_->AddObserver(this); remover_->Remove(remove_mask); } void ClearBrowsingDataView2::OnBrowsingDataRemoverDone() { clear_data_parent_window_->StopClearingBrowsingData(); }