diff options
author | raz@chromium.org <raz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-28 21:43:31 +0000 |
---|---|---|
committer | raz@chromium.org <raz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-28 21:43:31 +0000 |
commit | 099eaf0cd8ed17455d3f6a5ee88ed2783b454971 (patch) | |
tree | 6b77231bc4d99ed285a4cf7a9b393a0ce7c6b8a8 | |
parent | 1424babd5dbbd5200d6e4b4ef71b38f791bce8b1 (diff) | |
download | chromium_src-099eaf0cd8ed17455d3f6a5ee88ed2783b454971.zip chromium_src-099eaf0cd8ed17455d3f6a5ee88ed2783b454971.tar.gz chromium_src-099eaf0cd8ed17455d3f6a5ee88ed2783b454971.tar.bz2 |
Added UI for clearing Chrome Sync data
- Created 2 tabs, one for for clearing local browsing data, one for clearing server data
- Refactored the old local browsing code to use a grid layout rather than less-wieldy math
- Controls on all tabs block while, closing dialog is disabled, new throbber is going while clear is in progress
- Clear server tab will be behind a flag until I deploy the server endpoint
- Retained old clearing behavior: dialog closes on successful lear
- Clear server UI only visible if user is syncing
Outstanding issues:
- Clearing currently causes an account to become unusable. The cause of the issue is a known problem with auth; currently investigating a fix
- Unlike local clearing, clearing server data is more likely to error out. For now I just show a label next to the clear button that says Error, allowing the user to try again
BUG=54349
TEST=Clear from UI, or run sync backend tests checked in for issue 54280
Review URL: http://codereview.chromium.org/3412032
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@60845 0039d316-1c4b-4281-b951-d872f2087c98
19 files changed, 1318 insertions, 20 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index b1c32bff..b5748b0 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -4582,7 +4582,16 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_DEL_FORM_DATA_CHKBOX" desc="Checkbox for deleting form data saved for Autofill"> Clear saved form data </message> - <message name="IDS_CLEAR_BROWSING_DATA_COMMIT" desc="Text for OK button on dialog"> + <message name="IDS_CLEAR_CHROME_DATA_TAB_LABEL" desc="Tab label for controls for clearing browser data"> + Chrome data + </message> + <message name="IDS_CLEAR_OTHER_DATA_TAB_LABEL" desc="Tab label for controls for clearing other data (including server data)"> + Other data + </message> + <message name="IDS_CLEAR_BROWSING_DATA_BUTTON" desc="Button for initiating clearing of browsing data"> + Clear browsing data + </message> + <message name="IDS_CLEAR_BROWSING_DATA_COMMIT" desc="Text for OK button on dialog"> Clear browsing data </message> <message name="IDS_FLASH_STORAGE_SETTINGS" desc="Link for opening Adobe Flash Player storage settings"> @@ -4606,6 +4615,37 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_CLEAR_DATA_DELETING" desc="The progress message"> Clearing... </message> + <message name="IDS_CLEAR_DATA_ADOBE_FLASH_TITLE" desc="Title of Adobe flash section"> + Adobe Flash + </message> + <message name="IDS_CLEAR_DATA_ADOBE_FLASH_DESCRIPTION" desc="Description of Adobe flash section"> + Flash can store data associated with your computer you can access and control this data using a website provided by Adobe + </message> + <message name="IDS_CLEAR_DATA_CHROME_SYNC_TITLE" desc="Title of Chrome Sync section"> + Chrome Sync + </message> + <message name="IDS_CLEAR_DATA_CLEAR_SERVER_DATA_DESCRIPTION" desc="Description of clearing server data"> + Chrome stores information on Google servers when it syncs. If you're absolutely sure you do not want to use sync anymore you can stop all syncing and delete the data from Google + </message> + <message name="IDS_CLEAR_DATA_CLEAR_BUTTON" desc="Button used to clear server data"> + Stop sync and delete data from Google + </message> + <message name="IDS_CLEAR_DATA_SENDING" desc="Label text indicating that we are sending a clear to the server"> + Sending + </message> + <message name="IDS_CLEAR_DATA_ERROR" desc="Label text indicating that an error occurred in sending a clear to the server"> + Error + </message> + <message name="IDS_CLEAR_DASHBOARD_DESCRIPTION" desc="Description of Google dashboard"> + The Google Dashboard has more details about what Google is storing when Chrome syncs your data. + </message> + <message name="IDS_CONFIRM_CLEAR_DESCRIPTION" desc="Clear confirmation dialog text"> + You're about to stop sync on all your computers where you use Chrome. Your data will also be deleted from Google, but will remain within Chrome + </message> + <message name="IDS_CONFIRM_CLEAR_TITLE" desc="Clear confirmation dialog title"> + Clear Browsing Data + </message> + <!-- Content Settings dialog data --> <message name="IDS_CONTENT_SETTINGS_TITLE" desc="Title for content settings dialog"> diff --git a/chrome/browser/sync/engine/clear_data_command.cc b/chrome/browser/sync/engine/clear_data_command.cc index 7d33bfe..a7b7700 100644..100755 --- a/chrome/browser/sync/engine/clear_data_command.cc +++ b/chrome/browser/sync/engine/clear_data_command.cc @@ -15,12 +15,14 @@ using syncable::ScopedDirLookup; namespace browser_sync { + using sessions::StatusController; using sessions::SyncSession; using std::string; using syncable::FIRST_REAL_MODEL_TYPE; using syncable::MODEL_TYPE_COUNT; + ClearDataCommand::ClearDataCommand() {} ClearDataCommand::~ClearDataCommand() {} @@ -53,10 +55,10 @@ void ClearDataCommand::ExecuteImpl(SyncSession* session) { DLOG(INFO) << SyncerProtoUtil::ClientToServerResponseDebugString( client_to_server_response); - if (!ok || !client_to_server_response.has_clear_user_data() || - !client_to_server_response.clear_user_data().has_status() || - client_to_server_response.clear_user_data().status() != - sync_pb::SUCCESS) { + // Clear pending indicates that the server has received our clear message + if (!ok || !client_to_server_response.has_error_code() || + client_to_server_response.error_code() != + sync_pb::ClientToServerResponse::SUCCESS) { // On failure, subsequent requests to the server will cause it to attempt // to resume the clear. The client will handle disabling of sync in // response to a store birthday error from the server. diff --git a/chrome/browser/sync/engine/clear_data_command_unittest.cc b/chrome/browser/sync/engine/clear_data_command_unittest.cc index 8a42108..a11325a 100644 --- a/chrome/browser/sync/engine/clear_data_command_unittest.cc +++ b/chrome/browser/sync/engine/clear_data_command_unittest.cc @@ -73,7 +73,7 @@ TEST_F(ClearDataCommandTest, ClearDataCommandExpectFailed) { ScopedSessionContextSyncerEventChannel s_channel(context(), channel.get()); dir->set_store_birthday(mock_server()->store_birthday()); - mock_server()->SetClearUserDataResponseStatus(sync_pb::RETRIABLE_ERROR); + mock_server()->SetServerNotReachable(); on_should_stop_syncing_permanently_called_ = false; command_.Execute(session()); @@ -100,7 +100,7 @@ TEST_F(ClearDataCommandTest, ClearDataCommandExpectFailed) { EXPECT_FALSE(on_should_stop_syncing_permanently_called_); } -TEST_F(ClearDataCommandTest, ClearDataCommandExpectSucess) { +TEST_F(ClearDataCommandTest, ClearDataCommandExpectSuccess) { syncable::ScopedDirLookup dir(syncdb()->manager(), syncdb()->name()); ASSERT_TRUE(dir.good()); @@ -112,7 +112,8 @@ TEST_F(ClearDataCommandTest, ClearDataCommandExpectSucess) { ScopedSessionContextSyncerEventChannel s_channel(context(), channel.get()); dir->set_store_birthday(mock_server()->store_birthday()); - mock_server()->SetClearUserDataResponseStatus(sync_pb::SUCCESS); + mock_server()->SetClearUserDataResponseStatus( + sync_pb::ClientToServerResponse::SUCCESS); on_should_stop_syncing_permanently_called_ = false; command_.Execute(session()); diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc index e35a5e4..9788f2c 100644 --- a/chrome/browser/sync/profile_sync_service.cc +++ b/chrome/browser/sync/profile_sync_service.cc @@ -72,7 +72,8 @@ ProfileSyncService::ProfileSyncService(ProfileSyncFactory* factory, ALLOW_THIS_IN_INITIALIZER_LIST(wizard_(this)), unrecoverable_error_detected_(false), ALLOW_THIS_IN_INITIALIZER_LIST(scoped_runnable_method_factory_(this)), - token_migrator_(NULL) { + token_migrator_(NULL), + clear_server_data_state_(CLEAR_NOT_STARTED) { DCHECK(factory); DCHECK(profile); registrar_.Add(this, @@ -222,6 +223,15 @@ browser_sync::SessionModelAssociator* syncable::SESSIONS)->second.get())->GetModelAssociator(); } +void ProfileSyncService::ResetClearServerDataState() { + clear_server_data_state_ = CLEAR_NOT_STARTED; +} + +ProfileSyncService::ClearServerDataState + ProfileSyncService::GetClearServerDataState() { + return clear_server_data_state_; +} + void ProfileSyncService::GetDataTypeControllerStates( browser_sync::DataTypeController::StateMap* state_map) const { browser_sync::DataTypeController::TypeMap::const_iterator iter @@ -422,6 +432,7 @@ void ProfileSyncService::Shutdown(bool sync_disabled) { } void ProfileSyncService::ClearServerData() { + clear_server_data_state_ = CLEAR_CLEARING; backend_->RequestClearServerData(); } @@ -584,11 +595,13 @@ void ProfileSyncService::OnStopSyncingPermanently() { } void ProfileSyncService::OnClearServerDataFailed() { - // TODO(raz): Bug#54349 Wire up to ui when available + clear_server_data_state_ = CLEAR_FAILED; + FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); } void ProfileSyncService::OnClearServerDataSucceeded() { - // TODO(raz): Bug#54349 Wire up to ui when available + clear_server_data_state_ = CLEAR_SUCCEEDED; + FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged()); } void ProfileSyncService::ShowLoginDialog(gfx::NativeWindow parent_window) { @@ -814,7 +827,7 @@ void ProfileSyncService::SetPassphrase(const std::string& passphrase) { // TODO(tim): This should be encryption-specific instead of passwords // specific. For now we have to do this to avoid NIGORI node lookups when // we haven't downloaded that node. - if (!profile_->GetPrefs()->GetBoolean(prefs::kSyncPasswords) ) { + if (!profile_->GetPrefs()->GetBoolean(prefs::kSyncPasswords)) { LOG(WARNING) << "Silently dropping SetPassphrase request."; return; } diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h index 8ff579b..dc3e67d 100644 --- a/chrome/browser/sync/profile_sync_service.h +++ b/chrome/browser/sync/profile_sync_service.h @@ -110,6 +110,14 @@ class ProfileSyncService : public browser_sync::SyncFrontend, MAX_SYNC_EVENT_CODE }; + // Keep track of where we are when clearing server data. + enum ClearServerDataState { + CLEAR_NOT_STARTED = 1, + CLEAR_CLEARING = 2, + CLEAR_FAILED = 3, + CLEAR_SUCCEEDED = 4, + }; + // Default sync server URL. static const char* kSyncServerUrl; // Sync server URL for dev channel users @@ -146,6 +154,10 @@ class ProfileSyncService : public browser_sync::SyncFrontend, // null. browser_sync::SessionModelAssociator* GetSessionModelAssociator(); + // Maintain state of where we are in a server clear operation. + void ResetClearServerDataState(); + ClearServerDataState GetClearServerDataState(); + // Fills state_map with a map of current data types that are possible to // sync, as well as their states. void GetDataTypeControllerStates( @@ -472,6 +484,9 @@ class ProfileSyncService : public browser_sync::SyncFrontend, // credentials were provided. std::string cached_passphrase_; + // Keep track of where we are in a server clear operation + ClearServerDataState clear_server_data_state_; + DISALLOW_COPY_AND_ASSIGN(ProfileSyncService); }; diff --git a/chrome/browser/views/clear_browsing_data.cc b/chrome/browser/views/clear_browsing_data.cc index 0d59298..3eb4e5c 100644 --- a/chrome/browser/views/clear_browsing_data.cc +++ b/chrome/browser/views/clear_browsing_data.cc @@ -12,6 +12,9 @@ #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/search_engines/template_url_model.h" +#if defined(OS_WIN) +#include "chrome/browser/views/clear_browsing_data_view.h" +#endif #include "chrome/common/pref_names.h" #include "gfx/insets.h" #include "grit/generated_resources.h" @@ -37,16 +40,21 @@ using views::GridLayout; static const int kExtraMarginForTimePeriodLabel = 3; namespace browser { - // Defined in browser_dialogs.h for creation of the view. void ShowClearBrowsingDataView(gfx::NativeWindow parent, Profile* profile) { +#if defined(OS_WIN) + views::Window::CreateChromeWindow(parent, gfx::Rect(), + new ClearDataView(profile))->Show(); +#else views::Window::CreateChromeWindow(parent, gfx::Rect(), new ClearBrowsingDataView(profile))->Show(); +#endif } } // namespace browser + //////////////////////////////////////////////////////////////////////////////// // ClearBrowsingDataView, public: diff --git a/chrome/browser/views/clear_browsing_data_view.cc b/chrome/browser/views/clear_browsing_data_view.cc new file mode 100644 index 0000000..d6f7ab5 --- /dev/null +++ b/chrome/browser/views/clear_browsing_data_view.cc @@ -0,0 +1,371 @@ +// 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<BrowsingDataRemover::TimePeriod>(period_selected), + base::Time()); + remover_->AddObserver(this); + remover_->Remove(remove_mask); +} + +void ClearBrowsingDataView2::OnBrowsingDataRemoverDone() { + clear_data_parent_window_->StopClearingBrowsingData(); +} diff --git a/chrome/browser/views/clear_browsing_data_view.h b/chrome/browser/views/clear_browsing_data_view.h new file mode 100644 index 0000000..92133b3 --- /dev/null +++ b/chrome/browser/views/clear_browsing_data_view.h @@ -0,0 +1,121 @@ +// Copyright (c) 2006-2008 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. + +#ifndef CHROME_BROWSER_VIEWS_CLEAR_BROWSING_DATA_VIEW_H_ +#define CHROME_BROWSER_VIEWS_CLEAR_BROWSING_DATA_VIEW_H_ +#pragma once + +#include "app/combobox_model.h" +#include "chrome/browser/browsing_data_remover.h" +#include "chrome/browser/views/clear_data_view.h" +#include "views/controls/button/button.h" +#include "views/controls/combobox/combobox.h" +#include "views/controls/label.h" +#include "views/controls/link.h" +#include "views/view.h" +#include "views/window/dialog_delegate.h" + +namespace views { +class Checkbox; +class Label; +class Throbber; +class Window; +} + +class ClearDataView; +class Profile; +class MessageLoop; + +//////////////////////////////////////////////////////////////////////////////// +// +// The ClearBrowsingData2 class is responsible for drawing the UI controls of +// the dialog that allows the user to select what to delete (history, +// downloads, etc). +// +// TODO(raz) Remove the 2 suffix when the mac/linux/chromeos versions are there +// +//////////////////////////////////////////////////////////////////////////////// +class ClearBrowsingDataView2 : public views::View, + public views::ButtonListener, + public ComboboxModel, + public views::Combobox::Listener, + public BrowsingDataRemover::Observer, + public views::LinkController { + public: + ClearBrowsingDataView2(Profile* profile, ClearDataView* clear_data_view); + + virtual ~ClearBrowsingDataView2(void); + + // Initialize the controls on the dialog. + void Init(); + + // Overridden from ComboboxModel: + virtual int GetItemCount(); + virtual string16 GetItemAt(int index); + + // Overridden from views::Combobox::Listener: + virtual void ItemChanged(views::Combobox* sender, int prev_index, + int new_index); + + // Overridden from views::ButtonListener: + virtual void ButtonPressed(views::Button* sender, const views::Event& event); + + // Overriden from views::LinkController: + virtual void LinkActivated(views::Link* source, int event_flags); + + // Enable/disable clearing from this tab + void SetAllowClear(bool allow); + + private: + // Adds a new check-box as a child to the view. + views::Checkbox* AddCheckbox(const std::wstring& text, bool checked); + + // Sets the controls on the UI to be enabled/disabled depending on whether we + // have a delete operation in progress or not. + void UpdateControlEnabledState(); + + // Hand off control layout to layout manger + void InitControlLayout(); + + // Starts the process of deleting the browsing data depending on what the + // user selected. + void OnDelete(); + + // Callback from BrowsingDataRemover. Closes the dialog. + virtual void OnBrowsingDataRemoverDone(); + + // Parent window, used for disabling close + ClearDataView* clear_data_parent_window_; + + // Allows for disabling the clear button from outside this view + bool allow_clear_; + + // UI elements + views::View* throbber_view_; + views::Throbber* throbber_; + views::Label* status_label_; + views::Label* delete_all_label_; + views::Checkbox* del_history_checkbox_; + views::Checkbox* del_downloads_checkbox_; + views::Checkbox* del_cache_checkbox_; + views::Checkbox* del_cookies_checkbox_; + views::Checkbox* del_passwords_checkbox_; + views::Checkbox* del_form_data_checkbox_; + views::Label* time_period_label_; + views::Combobox* time_period_combobox_; + views::NativeButton* clear_browsing_data_button_; + + // Used to signal enabled/disabled state for controls in the UI. + bool delete_in_progress_; + + Profile* profile_; + + // If non-null it means removal is in progress. BrowsingDataRemover takes care + // of deleting itself when done. + BrowsingDataRemover* remover_; + + DISALLOW_COPY_AND_ASSIGN(ClearBrowsingDataView2); +}; + +#endif // CHROME_BROWSER_VIEWS_CLEAR_BROWSING_DATA_VIEW_H_ diff --git a/chrome/browser/views/clear_data_view.cc b/chrome/browser/views/clear_data_view.cc new file mode 100644 index 0000000..8f349bd --- /dev/null +++ b/chrome/browser/views/clear_data_view.cc @@ -0,0 +1,174 @@ +// 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_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/browser/views/clear_browsing_data.h" +#include "chrome/browser/views/clear_server_data.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; + +//////////////////////////////////////////////////////////////////////////////// +// ClearDataView, public: + +ClearDataView::ClearDataView(Profile* profile) + : profile_(profile), + clear_server_data_tab_(NULL), + clear_browsing_data_tab_(NULL), + clearing_data_(false) { + DCHECK(profile); + Init(); +} + +void ClearDataView::Init() { + tabs_ = new views::TabbedPane; + + tabs_->SetAccessibleName(l10n_util::GetStringF(IDS_OPTIONS_DIALOG_TITLE, + l10n_util::GetString(IDS_OPTIONS_DIALOG_TITLE))); + AddChildView(tabs_); + + int tab_index = 0; + clear_browsing_data_tab_ = new ClearBrowsingDataView2(profile_, this); + tabs_->AddTabAtIndex(tab_index++, + l10n_util::GetString(IDS_CLEAR_CHROME_DATA_TAB_LABEL), + clear_browsing_data_tab_, false); + clear_server_data_tab_ = new ClearServerDataView(profile_, this); + tabs_->AddTabAtIndex(tab_index++, + l10n_util::GetString(IDS_CLEAR_OTHER_DATA_TAB_LABEL), + clear_server_data_tab_, false); + + tabs_->SelectTabAt(static_cast<int>(0)); +} + +void ClearDataView::StartClearingBrowsingData() { + // Only one clear can happen at a time + clear_server_data_tab_->SetAllowClear(false); + clearing_data_ = true; + window()->EnableClose(false); + GetDialogClientView()->UpdateDialogButtons(); +} + +void ClearDataView::StopClearingBrowsingData() { + window()->Close(); +} + +void ClearDataView::StartClearingServerData() { + // Only one clear can happen at a time + clear_browsing_data_tab_->SetAllowClear(false); + clearing_data_ = true; + window()->EnableClose(false); + GetDialogClientView()->UpdateDialogButtons(); +} + +void ClearDataView::SucceededClearingServerData() { + window()->Close(); +} + +void ClearDataView::FailedClearingServerData() { + clear_browsing_data_tab_->SetAllowClear(true); + clearing_data_ = false; + window()->EnableClose(false); + GetDialogClientView()->UpdateDialogButtons(); +} + +//////////////////////////////////////////////////////////////////////////////// +// ClearDataView, views::View implementation: + +gfx::Size ClearDataView::GetPreferredSize() { + gfx::Size size(tabs_->GetPreferredSize()); + size.Enlarge(2 * kDialogPadding, 2 * kDialogPadding); + return size; +} + +void ClearDataView::Layout() { + tabs_->SetBounds(kDialogPadding, kDialogPadding, + width() - (2 * kDialogPadding), + height() - (2 * kDialogPadding)); +} + +//////////////////////////////////////////////////////////////////////////////// +// ClearDataView, views::DialogDelegate implementation: + +int ClearDataView::GetDefaultDialogButton() const { + return MessageBoxFlags::DIALOGBUTTON_NONE; +} + +std::wstring ClearDataView::GetDialogButtonLabel( + MessageBoxFlags::DialogButton button) const { + DCHECK(button == MessageBoxFlags::DIALOGBUTTON_CANCEL); + return l10n_util::GetString(IDS_CANCEL); +} + +int ClearDataView::GetDialogButtons() const { + return MessageBoxFlags::DIALOGBUTTON_CANCEL; +} + + +bool ClearDataView::IsDialogButtonEnabled( + MessageBoxFlags::DialogButton button) const { + + return !clearing_data_; +} + +bool ClearDataView::CanResize() const { + return false; +} + +bool ClearDataView::CanMaximize() const { + return false; +} + +bool ClearDataView::IsAlwaysOnTop() const { + return false; +} + +bool ClearDataView::HasAlwaysOnTopMenu() const { + return false; +} + +bool ClearDataView::IsModal() const { + return true; +} + +std::wstring ClearDataView::GetWindowTitle() const { + return l10n_util::GetString(IDS_CLEAR_BROWSING_DATA_TITLE); +} + +views::View* ClearDataView::GetContentsView() { + return this; +} + +views::View* ClearDataView::GetInitiallyFocusedView() { + return GetDialogClientView()->cancel_button(); +} + diff --git a/chrome/browser/views/clear_data_view.h b/chrome/browser/views/clear_data_view.h new file mode 100644 index 0000000..9481ec4 --- /dev/null +++ b/chrome/browser/views/clear_data_view.h @@ -0,0 +1,99 @@ +// Copyright (c) 2006-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. + +#ifndef CHROME_BROWSER_VIEWS_CLEAR_DATA_VIEW_H_ +#define CHROME_BROWSER_VIEWS_CLEAR_DATA_VIEW_H_ +#pragma once + +#include "app/combobox_model.h" +#include "chrome/browser/browsing_data_remover.h" +#include "chrome/browser/views/clear_browsing_data_view.h" +#include "chrome/browser/views/clear_server_data.h" +#include "views/controls/button/button.h" +#include "views/controls/combobox/combobox.h" +#include "views/controls/label.h" +#include "views/controls/link.h" +#include "views/controls/tabbed_pane/tabbed_pane.h" +#include "views/view.h" +#include "views/window/dialog_delegate.h" + +namespace views { +class Checkbox; +class Label; +class Throbber; +class Window; +} + +class ClearBrowsingDataView2; +class ClearServerDataView; +class Profile; +class MessageLoop; + +//////////////////////////////////////////////////////////////////////////////// +// +// The ClearDataView class is responsible for drawing the window that allows +// the user to select what to delete (history, downloads, etc). It has tabs +// separating "local" data from "other" (e.g. server) data +// +//////////////////////////////////////////////////////////////////////////////// +class ClearDataView : public views::View, + public views::DialogDelegate { + public: + explicit ClearDataView(Profile* profile); + virtual ~ClearDataView(void) {} + + // Disallow the window closing while clearing either server or browsing + // data. After clear completes, close the window. + void StartClearingBrowsingData(); + void StopClearingBrowsingData(); + + void StartClearingServerData(); + void SucceededClearingServerData(); + void FailedClearingServerData(); + + // Initialize the controls on the dialog. + void Init(); + + // Overridden from views::View: + virtual gfx::Size GetPreferredSize(); + virtual void Layout(); + + // Overridden from views::DialogDelegate: + virtual int GetDefaultDialogButton() const; + virtual std::wstring GetDialogButtonLabel( + MessageBoxFlags::DialogButton button) const; + virtual int GetDialogButtons() const; + virtual bool IsDialogButtonEnabled( + MessageBoxFlags::DialogButton button) const; + virtual bool CanResize() const; + virtual bool CanMaximize() const; + virtual bool IsAlwaysOnTop() const; + virtual bool HasAlwaysOnTopMenu() const; + virtual bool IsModal() const; + virtual std::wstring GetWindowTitle() const; + virtual views::View* GetContentsView(); + virtual bool GetSizeExtraViewHeightToButtons() { return true; } + virtual views::View* GetInitiallyFocusedView(); + + private: + // Sets the controls on the UI to be enabled/disabled depending on whether we + // have a delete operation in progress or not. + void UpdateControlEnabledState(); + + // Currently clearing + bool clearing_data_; + + views::TabbedPane* tabs_; + ClearServerDataView* clear_server_data_tab_; + ClearBrowsingDataView2* clear_browsing_data_tab_; + + Profile* profile_; + + DISALLOW_COPY_AND_ASSIGN(ClearDataView); +}; + +static const int kDialogPadding = 7; + +#endif // CHROME_BROWSER_VIEWS_CLEAR_DATA_VIEW_H_ + diff --git a/chrome/browser/views/clear_server_data.cc b/chrome/browser/views/clear_server_data.cc new file mode 100644 index 0000000..dae4387 --- /dev/null +++ b/chrome/browser/views/clear_server_data.cc @@ -0,0 +1,326 @@ +// 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_server_data.h" + +#include "app/l10n_util.h" +#include "app/resource_bundle.h" +#include "base/command_line.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/browser/sync/profile_sync_service.h" +#include "chrome/common/chrome_switches.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; +using views::ColumnSet; + +// 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; + +//////////////////////////////////////////////////////////////////////////////// +// ClearServerDataView, public: + +ClearServerDataView::ClearServerDataView(Profile* profile, + ClearDataView* clear_data_view) + : profile_(profile), + clear_data_parent_window_(clear_data_view), + allow_clear_(true) { + DCHECK(profile); + DCHECK(clear_data_view); + + profile_->GetProfileSyncService()->ResetClearServerDataState(); + profile_->GetProfileSyncService()->AddObserver(this); + + Init(); + InitControlLayout(); + InitControlVisibility(); +} + +ClearServerDataView::~ClearServerDataView(void) { + profile_->GetProfileSyncService()->RemoveObserver(this); +} + +void ClearServerDataView::Init() { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + gfx::Font title_font = + rb.GetFont(ResourceBundle::BaseFont).DeriveFont(0, gfx::Font::BOLD); + + flash_title_label_ = new views::Label( + l10n_util::GetString(IDS_CLEAR_DATA_ADOBE_FLASH_TITLE)); + flash_title_label_->SetFont(title_font); + + flash_description_label_= new views::Label( + l10n_util::GetString(IDS_CLEAR_DATA_ADOBE_FLASH_DESCRIPTION)); + flash_link_ = + new views::Link(l10n_util::GetString(IDS_FLASH_STORAGE_SETTINGS)); + flash_link_->SetController(this); + + chrome_sync_title_label_= new views::Label( + l10n_util::GetString(IDS_CLEAR_DATA_CHROME_SYNC_TITLE)); + chrome_sync_title_label_->SetFont(title_font); + + chrome_sync_description_label_ = new views::Label( + l10n_util::GetString(IDS_CLEAR_DATA_CLEAR_SERVER_DATA_DESCRIPTION)); + + clear_server_data_button_= new views::NativeButton( + this, l10n_util::GetString(IDS_CLEAR_DATA_CLEAR_BUTTON)); + + dashboard_label_ = new views::Label( + l10n_util::GetString(IDS_CLEAR_DASHBOARD_DESCRIPTION)); + + dashboard_link_ = new views::Link(); + dashboard_link_->SetController(this); + dashboard_link_->SetText( + l10n_util::GetString(IDS_SYNC_PRIVACY_DASHBOARD_LINK_LABEL)); + + status_label_ = new views::Label( + l10n_util::GetString(IDS_CLEAR_DATA_DELETING)); + throbber_ = new views::Throbber(50, true); +} + +void ClearServerDataView::InitControlLayout() { + GridLayout* layout = CreatePanelGridLayout(this); + this->SetLayoutManager(layout); + + int centered_column_set_id = 0; + ColumnSet * column_set = layout->AddColumnSet(centered_column_set_id); + column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, + GridLayout::USE_PREF, 0, 0); + + int left_aligned_column_set_id = 1; + column_set = layout->AddColumnSet(left_aligned_column_set_id); + column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1, + GridLayout::USE_PREF, 0, 0); + + const int three_column_set_id = 2; + column_set = layout->AddColumnSet(three_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); + column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing); + column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1, + GridLayout::USE_PREF, 0, 0); + + AddWrappingLabelRow(layout, flash_title_label_, + centered_column_set_id, true); + AddWrappingLabelRow(layout, flash_description_label_, + centered_column_set_id, true); + + layout->StartRow(0, left_aligned_column_set_id); + layout->AddView(flash_link_); + layout->AddPaddingRow(0, kPanelVertMargin); + + AddWrappingLabelRow(layout, chrome_sync_title_label_, + centered_column_set_id, true); + AddWrappingLabelRow(layout, chrome_sync_description_label_, + centered_column_set_id, true); + + layout->StartRow(0, three_column_set_id); + layout->AddView(clear_server_data_button_, 1, 1, + GridLayout::LEADING, GridLayout::CENTER); + layout->AddView(status_label_, 1, 1, + GridLayout::LEADING, GridLayout::CENTER); + layout->AddView(throbber_, 1, 1, + GridLayout::TRAILING, GridLayout::CENTER); + layout->AddPaddingRow(0, kPanelVertMargin); + + AddWrappingLabelRow(layout, dashboard_label_, centered_column_set_id, true); + + layout->StartRow(0, left_aligned_column_set_id); + layout->AddView(dashboard_link_); +} + +void ClearServerDataView::InitControlVisibility() { + bool allow_clear_server_data_ui = + CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableClearServerData); + + bool sync_enabled = allow_clear_server_data_ui && + profile_->GetProfileSyncService()->HasSyncSetupCompleted(); + + // Hide progress indicators + throbber_->SetVisible(false); + status_label_->SetVisible(false); + + // Only show the sync portion if sync is enabled + chrome_sync_title_label_->SetVisible(sync_enabled); + chrome_sync_description_label_->SetVisible(sync_enabled); + clear_server_data_button_->SetVisible(sync_enabled); + dashboard_label_->SetVisible(sync_enabled); + dashboard_link_->SetVisible(sync_enabled); +} + +void ClearServerDataView::SetAllowClear(bool allow) { + allow_clear_ = allow; + UpdateControlEnabledState(); +} + +//////////////////////////////////////////////////////////////////////////////// +// ClearServerDataView, views::View implementation: + +void ClearServerDataView::AddWrappingLabelRow(views::GridLayout* layout, + views::Label* label, + int id, + bool related_follows) { + label->SetMultiLine(true); + label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); + layout->StartRow(0, id); + layout->AddView(label); + AddSpacing(layout, related_follows); +} + +void ClearServerDataView::AddSpacing(views::GridLayout* layout, + bool related_follows) { + layout->AddPaddingRow(0, related_follows ? kRelatedControlVerticalSpacing + : kUnrelatedControlVerticalSpacing); +} + +gfx::Size ClearServerDataView::GetPreferredSize() { + // If we didn't return a preferred size, the containing view auto-sizes to + // the width of the narrowest button, which is not what we want + return gfx::Size(views::Window::GetLocalizedContentsSize( + IDS_CLEARDATA_DIALOG_WIDTH_CHARS, + IDS_CLEARDATA_DIALOG_HEIGHT_LINES)); +} + +//////////////////////////////////////////////////////////////////////////////// +// ClearServerDataView, views::ButtonListener implementation: + +void ClearServerDataView::ButtonPressed( + views::Button* sender, const views::Event& event) { + + if (sender == clear_server_data_button_) { + // Protect against the unlikely case where the server received a + // message, and the syncer syncs and resets itself before the + // user tries pressing the Clear button in this dialog again. + // TODO(raz) Confirm whether we have an issue here + if (profile_->GetProfileSyncService()->HasSyncSetupCompleted()) { + ConfirmMessageBoxDialog::Run( + GetWindow()->GetNativeWindow(), + this, + l10n_util::GetString(IDS_CONFIRM_CLEAR_DESCRIPTION), + l10n_util::GetString(IDS_CONFIRM_CLEAR_TITLE)); + } + } + + UpdateControlEnabledState(); +} + +void ClearServerDataView::LinkActivated(views::Link* source, + int event_flags) { + Browser* browser = Browser::Create(profile_); + if (source == flash_link_) { + browser->OpenURL(GURL(l10n_util::GetStringUTF8(IDS_FLASH_STORAGE_URL)), + GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK); + browser->window()->Show(); + } else { + browser->OpenURL(GURL(l10n_util::GetStringUTF8(IDS_PRIVACY_DASHBOARD_URL)), + GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK); + browser->window()->Show(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// ClearServerDataView, ConfirmMessageBoxObserver implementation: + +void ClearServerDataView::OnConfirmMessageAccept() { + clear_data_parent_window_->StartClearingServerData(); + profile_->GetProfileSyncService()->ClearServerData(); + UpdateControlEnabledState(); +} + +void ClearServerDataView::OnConfirmMessageCancel() { + UpdateControlEnabledState(); +} + +//////////////////////////////////////////////////////////////////////////////// +// ClearServerDataView, ProfileSyncServiceObserver implementation: + +void ClearServerDataView::OnStateChanged() { + // Note that we are listening for all notifications here. Clearing from + // another browser should cause the "clear" button to go gray (if a + // notification nudges the syncer, causing OnStateChanged to be called with + // sync disabled) + UpdateControlEnabledState(); +} + +//////////////////////////////////////////////////////////////////////////////// +// ClearServerDataView, private: + +void ClearServerDataView::UpdateControlEnabledState() { + bool delete_in_progress = false; + + // We only want to call Suceeded/FailedClearingServerData once, not every + // time the view is refreshed. As such, on success/failure we handle that + // state and immediately reset things back to CLEAR_NOT_STARTED. + ProfileSyncService::ClearServerDataState clear_state = + profile_->GetProfileSyncService()->GetClearServerDataState(); + profile_->GetProfileSyncService()->ResetClearServerDataState(); + + switch (clear_state) { + case ProfileSyncService::CLEAR_NOT_STARTED: + // We can get here when we first start and after a failed clear (which + // does not close the tab), do nothing. + break; + case ProfileSyncService::CLEAR_CLEARING: + // Clearing buttons on all tabs are disabled at this + // point, throbber is going + status_label_->SetText(l10n_util::GetString(IDS_CLEAR_DATA_SENDING)); + status_label_->SetVisible(true); + delete_in_progress = true; + break; + case ProfileSyncService::CLEAR_FAILED: + // Show an error and reallow clearing + clear_data_parent_window_->FailedClearingServerData(); + status_label_->SetText(l10n_util::GetString(IDS_CLEAR_DATA_ERROR)); + status_label_->SetVisible(true); + delete_in_progress = false; + break; + case ProfileSyncService::CLEAR_SUCCEEDED: + // Close the dialog box, success! + status_label_->SetVisible(false); + delete_in_progress = false; + clear_data_parent_window_->SucceededClearingServerData(); + break; + } + + // allow_clear can be false when a local browsing data clear is happening + // from the neighboring tab. delete_in_progress means that a clear is + // pending in the current tab. + this->clear_server_data_button_->SetEnabled( + profile_->GetProfileSyncService()->HasSyncSetupCompleted() && + !delete_in_progress && allow_clear_); + + throbber_->SetVisible(delete_in_progress); + if (delete_in_progress) + throbber_->Start(); + else + throbber_->Stop(); +} + diff --git a/chrome/browser/views/clear_server_data.h b/chrome/browser/views/clear_server_data.h new file mode 100644 index 0000000..694060e --- /dev/null +++ b/chrome/browser/views/clear_server_data.h @@ -0,0 +1,114 @@ +// Copyright (c) 2006-2008 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. + +#ifndef CHROME_BROWSER_VIEWS_CLEAR_SERVER_DATA_H_ +#define CHROME_BROWSER_VIEWS_CLEAR_SERVER_DATA_H_ +#pragma once + +#include "app/combobox_model.h" +#include "chrome/browser/browsing_data_remover.h" +#include "chrome/browser/views/clear_data_view.h" +#include "chrome/browser/views/confirm_message_box_dialog.h" +#include "chrome/browser/sync/profile_sync_service.h" +#include "views/controls/button/button.h" +#include "views/controls/label.h" +#include "views/controls/link.h" +#include "views/grid_layout.h" +#include "views/view.h" +#include "views/window/dialog_delegate.h" + +namespace views { +class Checkbox; +class ColumnSet; +class GridLayout; +class Label; +class Throbber; +class Window; +} + +class ClearDataView; +class Profile; +class MessageLoop; + +//////////////////////////////////////////////////////////////////////////////// +// +// The ClearServerData class is responsible for drawing the UI controls of the +// dialog that allows the user to delete non-local data (e.g. Chrome Sync data) +// +//////////////////////////////////////////////////////////////////////////////// +class ClearServerDataView : public views::View, + public views::ButtonListener, + public views::LinkController, + public ProfileSyncServiceObserver, + public ConfirmMessageBoxObserver { + public: + ClearServerDataView(Profile* profile, ClearDataView* clear_data_view); + + virtual ~ClearServerDataView(); + + // Initialize the controls on the dialog. + void Init(); + + // Overridden from views::View: + virtual gfx::Size GetPreferredSize(); + + // Overridden from views::ButtonListener: + virtual void ButtonPressed(views::Button* sender, const views::Event& event); + + // Overriden from views::LinkController: + virtual void LinkActivated(views::Link* source, int event_flags); + + // Disable clearing from this tab + void SetAllowClear(bool allow); + + private: + void InitControlLayout(); + void InitControlVisibility(); + + void AddSpacing(views::GridLayout* layout, + bool related_follows); + + void AddWrappingLabelRow(views::GridLayout* layout, + views::Label* label, + int id, + bool related_follows); + + // Adds a new check-box as a child to the view. + views::Checkbox* AddCheckbox(const std::wstring& text, bool checked); + + // Sets the controls on the UI to be enabled/disabled depending on whether we + // have a delete operation in progress or not. + void UpdateControlEnabledState(); + + // Starts the process of deleting the browsing data depending on what the + // user selected. + void OnDelete(); + + // ProfileSyncServiceObserver method. + virtual void OnStateChanged(); + + // ProfileSyncServiceObserver + virtual void OnConfirmMessageAccept(); + virtual void OnConfirmMessageCancel(); + + ClearDataView* clear_data_parent_window_; + Profile* profile_; + bool allow_clear_; + + views::Label* flash_title_label_; + views::Label* flash_description_label_; + views::Label* chrome_sync_title_label_; + views::Label* chrome_sync_description_label_; + views::Label* dashboard_label_; + views::Label* status_label_; + views::Link* flash_link_; + views::Link* dashboard_link_; + views::NativeButton* clear_server_data_button_; + views::Throbber* throbber_; + + DISALLOW_COPY_AND_ASSIGN(ClearServerDataView); +}; + +#endif // CHROME_BROWSER_VIEWS_CLEAR_SERVER_DATA_H_ + diff --git a/chrome/browser/views/options/advanced_contents_view.cc b/chrome/browser/views/options/advanced_contents_view.cc index db25463..8eab863 100644 --- a/chrome/browser/views/options/advanced_contents_view.cc +++ b/chrome/browser/views/options/advanced_contents_view.cc @@ -39,7 +39,7 @@ #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/shell_dialogs.h" #include "chrome/browser/views/browser_dialogs.h" -#include "chrome/browser/views/clear_browsing_data.h" +#include "chrome/browser/views/clear_data_view.h" #include "chrome/browser/views/list_background.h" #include "chrome/browser/views/options/content_settings_window_view.h" #include "chrome/browser/views/options/fonts_languages_window_view.h" @@ -537,7 +537,7 @@ void PrivacySection::ButtonPressed( views::Window::CreateChromeWindow( GetWindow()->GetNativeWindow(), gfx::Rect(), - new ClearBrowsingDataView(profile()))->Show(); + new ClearDataView(profile()))->Show(); } } diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 7554cb7..7554cb7 100644..100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 7575488..24c5aa8 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -2847,6 +2847,12 @@ 'browser/views/chrome_views_delegate.h', 'browser/views/clear_browsing_data.cc', 'browser/views/clear_browsing_data.h', + 'browser/views/clear_browsing_data_view.cc', + 'browser/views/clear_browsing_data_view.h', + 'browser/views/clear_data_view.cc', + 'browser/views/clear_data_view.h', + 'browser/views/clear_server_data.cc', + 'browser/views/clear_server_data.h', 'browser/views/collected_cookies_win.cc', 'browser/views/collected_cookies_win.h', 'browser/views/confirm_message_box_dialog.cc', diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 639d42b..4d9d14f 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -381,6 +381,10 @@ const char kEnableBenchmarking[] = "enable-benchmarking"; // Chromoting Host Process within the service process. const char kEnableRemoting[] = "enable-remoting"; +// This flag enables UI for clearing server data. Temporarily in place +// until there's a server endpoint deployed. +const char kEnableClearServerData[] = "enable-clear-server-data"; + // This applies only when the process type is "service". Enables the // Cloud Print Proxy component within the service process. const char kEnableCloudPrintProxy[] = "enable-cloud-print-proxy"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index f52dbb9..14800a5 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -119,6 +119,7 @@ extern const char kEnableAuthNegotiatePort[]; extern const char kEnableBackgroundMode[]; extern const char kEnableBenchmarking[]; extern const char kEnableRemoting[]; +extern const char kEnableClearServerData[]; extern const char kEnableCloudPrintProxy[]; extern const char kEnableCloudPrint[]; extern const char kEnableConnectBackupJobs[]; diff --git a/chrome/test/sync/engine/mock_connection_manager.cc b/chrome/test/sync/engine/mock_connection_manager.cc index cc59915..b22a8e1 100644 --- a/chrome/test/sync/engine/mock_connection_manager.cc +++ b/chrome/test/sync/engine/mock_connection_manager.cc @@ -362,17 +362,18 @@ void MockConnectionManager::ProcessGetUpdates(ClientToServerMessage* csm, } void MockConnectionManager::SetClearUserDataResponseStatus( - sync_pb::UserDataStatus status) { + sync_pb::ClientToServerResponse::ErrorType errortype ) { // Note: this is not a thread-safe set, ok for now. NOT ok if tests // run the syncer on the background thread while this method is called. - clear_user_data_response_.set_status(status); + clear_user_data_response_errortype_ = errortype; } void MockConnectionManager::ProcessClearData(ClientToServerMessage* csm, ClientToServerResponse* response) { CHECK(csm->has_clear_user_data()); ASSERT_EQ(csm->message_contents(), ClientToServerMessage::CLEAR_DATA); - response->mutable_clear_user_data()->CopyFrom(clear_user_data_response_); + response->clear_user_data(); + response->set_error_code(clear_user_data_response_errortype_); } void MockConnectionManager::ProcessAuthenticate( diff --git a/chrome/test/sync/engine/mock_connection_manager.h b/chrome/test/sync/engine/mock_connection_manager.h index 2ed6ad4..a6edce6 100644 --- a/chrome/test/sync/engine/mock_connection_manager.h +++ b/chrome/test/sync/engine/mock_connection_manager.h @@ -128,7 +128,8 @@ class MockConnectionManager : public browser_sync::ServerConnectionManager { void FailNextPostBufferToPathCall() { fail_next_postbuffer_ = true; } - void SetClearUserDataResponseStatus(sync_pb::UserDataStatus status); + void SetClearUserDataResponseStatus( + sync_pb::ClientToServerResponse::ErrorType errortype); // A visitor class to allow a test to change some monitoring state atomically // with the action of overriding the response codes sent back to the Syncer @@ -294,7 +295,8 @@ class MockConnectionManager : public browser_sync::ServerConnectionManager { MidCommitObserver* mid_commit_observer_; // The clear data response we'll return in the next response - sync_pb::ClearUserDataResponse clear_user_data_response_; + sync_pb::ClientToServerResponse::ErrorType + clear_user_data_response_errortype_; // The AUTHENTICATE response we'll return for auth requests. sync_pb::AuthenticateResponse auth_response_; |