diff options
Diffstat (limited to 'chrome/browser/sync/engine')
| -rw-r--r-- | chrome/browser/sync/engine/clear_data_command.cc | 80 | ||||
| -rw-r--r-- | chrome/browser/sync/engine/clear_data_command.h | 36 | ||||
| -rw-r--r-- | chrome/browser/sync/engine/clear_data_command_unittest.cc | 130 | ||||
| -rw-r--r-- | chrome/browser/sync/engine/syncapi.cc | 14 | ||||
| -rw-r--r-- | chrome/browser/sync/engine/syncapi.h | 8 | ||||
| -rw-r--r-- | chrome/browser/sync/engine/syncer.cc | 42 | ||||
| -rw-r--r-- | chrome/browser/sync/engine/syncer.h | 1 | ||||
| -rw-r--r-- | chrome/browser/sync/engine/syncer_thread.cc | 3 | ||||
| -rw-r--r-- | chrome/browser/sync/engine/syncer_thread.h | 3 | ||||
| -rw-r--r-- | chrome/browser/sync/engine/syncer_types.h | 5 | ||||
| -rw-r--r-- | chrome/browser/sync/engine/syncproto.h | 1 |
11 files changed, 308 insertions, 15 deletions
diff --git a/chrome/browser/sync/engine/clear_data_command.cc b/chrome/browser/sync/engine/clear_data_command.cc new file mode 100644 index 0000000..7d33bfe --- /dev/null +++ b/chrome/browser/sync/engine/clear_data_command.cc @@ -0,0 +1,80 @@ +// 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. + +#include "chrome/browser/sync/engine/clear_data_command.h" + +#include <string> + +#include "chrome/browser/sync/engine/syncer.h" +#include "chrome/browser/sync/engine/syncer_proto_util.h" +#include "chrome/browser/sync/engine/syncproto.h" +#include "chrome/browser/sync/sessions/sync_session.h" +#include "chrome/browser/sync/syncable/directory_manager.h" + +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() {} + +void ClearDataCommand::ExecuteImpl(SyncSession* session) { + ClientToServerMessage client_to_server_message; + ClientToServerResponse client_to_server_response; + + client_to_server_message.set_share(session->context()->account_name()); + client_to_server_message.set_message_contents( + ClientToServerMessage::CLEAR_DATA); + + client_to_server_message.mutable_clear_user_data(); + + ScopedDirLookup dir(session->context()->directory_manager(), + session->context()->account_name()); + if (!dir.good()) { + LOG(ERROR) << "Scoped dir lookup failed!"; + return; + } + + SyncerProtoUtil::AddRequestBirthday(dir, &client_to_server_message); + + LOG(INFO) << "Clearing server data"; + + bool ok = SyncerProtoUtil::PostClientToServerMessage( + client_to_server_message, + &client_to_server_response, + 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) { + // 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. + SyncerEvent event(SyncerEvent::CLEAR_SERVER_DATA_FAILED); + session->context()->syncer_event_channel()->Notify(event); + + LOG(ERROR) << "Error posting ClearData."; + + return; + } + + SyncerEvent event(SyncerEvent::CLEAR_SERVER_DATA_SUCCEEDED); + session->context()->syncer_event_channel()->Notify(event); + + session->delegate()->OnShouldStopSyncingPermanently(); + + LOG(INFO) << "ClearData succeeded."; +} + +} // namespace browser_sync + diff --git a/chrome/browser/sync/engine/clear_data_command.h b/chrome/browser/sync/engine/clear_data_command.h new file mode 100644 index 0000000..cdf51f2 --- /dev/null +++ b/chrome/browser/sync/engine/clear_data_command.h @@ -0,0 +1,36 @@ +// 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_SYNC_ENGINE_CLEAR_DATA_COMMAND_H_ +#define CHROME_BROWSER_SYNC_ENGINE_CLEAR_DATA_COMMAND_H_ +#pragma once + +#include "base/basictypes.h" +#include "chrome/browser/sync/engine/model_safe_worker.h" +#include "chrome/browser/sync/engine/syncer_command.h" +#include "chrome/browser/sync/syncable/model_type.h" + +namespace sync_pb { +class EntitySpecifics; +} + +namespace browser_sync { + +// Clears server data associated with this user's account +class ClearDataCommand : public SyncerCommand { + public: + ClearDataCommand(); + virtual ~ClearDataCommand(); + + // SyncerCommand implementation. + virtual void ExecuteImpl(sessions::SyncSession* session); + + private: + DISALLOW_COPY_AND_ASSIGN(ClearDataCommand); +}; + +} // namespace browser_sync + +#endif // CHROME_BROWSER_SYNC_ENGINE_CLEAR_DATA_COMMAND_H_ + diff --git a/chrome/browser/sync/engine/clear_data_command_unittest.cc b/chrome/browser/sync/engine/clear_data_command_unittest.cc new file mode 100644 index 0000000..cd05e12 --- /dev/null +++ b/chrome/browser/sync/engine/clear_data_command_unittest.cc @@ -0,0 +1,130 @@ +// 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/sync/engine/clear_data_command.h" +#include "chrome/browser/sync/protocol/autofill_specifics.pb.h" +#include "chrome/browser/sync/protocol/bookmark_specifics.pb.h" +#include "chrome/browser/sync/protocol/preference_specifics.pb.h" +#include "chrome/browser/sync/protocol/sync.pb.h" +#include "chrome/browser/sync/syncable/directory_manager.h" +#include "chrome/test/sync/engine/proto_extension_validator.h" +#include "chrome/test/sync/engine/syncer_command_test.h" + +namespace browser_sync { + +using sessions::ScopedSessionContextSyncerEventChannel; +using syncable::FIRST_REAL_MODEL_TYPE; +using syncable::MODEL_TYPE_COUNT; + +// A test fixture for tests exercising ClearDataCommandTest. +class ClearDataCommandTest : public SyncerCommandTest { + protected: + ClearDataCommandTest() {} + ClearDataCommand command_; + + virtual void OnShouldStopSyncingPermanently() { + on_should_stop_syncing_permanently_called_ = true; + } + + protected: + bool on_should_stop_syncing_permanently_called_; + + private: + DISALLOW_COPY_AND_ASSIGN(ClearDataCommandTest); +}; + +class ClearEventHandler : public ChannelEventHandler<SyncerEvent> { + public: + ClearEventHandler() { + ResetReceivedEvents(); + } + bool ReceievedClearSuccessEvent() { return received_clear_success_event_; } + bool ReceievedClearFailedEvent() { return received_clear_failed_event_; } + void ResetReceivedEvents() { + received_clear_success_event_ = false; + received_clear_failed_event_ = false; + } + + void HandleChannelEvent(const SyncerEvent& event); + + private: + bool received_clear_success_event_; + bool received_clear_failed_event_; +}; + +void ClearEventHandler::HandleChannelEvent(const SyncerEvent& event) { + if (event.what_happened == SyncerEvent::CLEAR_SERVER_DATA_FAILED) { + received_clear_failed_event_ = true; + } else if (event.what_happened == SyncerEvent::CLEAR_SERVER_DATA_SUCCEEDED) { + received_clear_success_event_ = true; + } +} + +TEST_F(ClearDataCommandTest, ClearDataCommandExpectFailed) { + syncable::ScopedDirLookup dir(syncdb()->manager(), syncdb()->name()); + ASSERT_TRUE(dir.good()); + + ConfigureMockServerConnection(); + SyncerEventChannel* channel = new SyncerEventChannel(); + ClearEventHandler* handler = new ClearEventHandler(); + channel->AddObserver(handler); + ScopedSessionContextSyncerEventChannel s_channel(context(), channel); + + dir->set_store_birthday(mock_server()->store_birthday()); + mock_server()->SetClearUserDataResponseStatus(sync_pb::RETRIABLE_ERROR); + on_should_stop_syncing_permanently_called_ = false; + + command_.Execute(session()); + + // Expect that the client sent a clear request, received failure, + // fired a failure event, but did not disable sync. + // + // A failure event will be bubbled back to the user's UI, and the + // user can press "clear" again. + // + // We do not want to disable sync in the client because the user may + // incorrectly get the impression that their private data has been cleared + // from the server (from the fact that their data is gone on the client). + // + // Any subsequent GetUpdates/Commit requests or attempts to enable sync + // will cause the server to attempt to resume the clearing process (within + // a bounded window of time) + const sync_pb::ClientToServerMessage& r = mock_server()->last_request(); + EXPECT_TRUE(r.has_clear_user_data()); + + EXPECT_TRUE(handler->ReceievedClearFailedEvent()); + + EXPECT_FALSE(handler->ReceievedClearSuccessEvent()); + EXPECT_FALSE(on_should_stop_syncing_permanently_called_); +} + +TEST_F(ClearDataCommandTest, ClearDataCommandExpectSucess) { + syncable::ScopedDirLookup dir(syncdb()->manager(), syncdb()->name()); + ASSERT_TRUE(dir.good()); + + ConfigureMockServerConnection(); + SyncerEventChannel* channel = new SyncerEventChannel(); + ClearEventHandler* handler = new ClearEventHandler(); + channel->AddObserver(handler); + ScopedSessionContextSyncerEventChannel s_channel(context(), channel); + + dir->set_store_birthday(mock_server()->store_birthday()); + mock_server()->SetClearUserDataResponseStatus(sync_pb::SUCCESS); + on_should_stop_syncing_permanently_called_ = false; + + command_.Execute(session()); + + // Expect that the client sent a clear request, fired off the success event + // in response, and disabled sync + const sync_pb::ClientToServerMessage& r = mock_server()->last_request(); + EXPECT_TRUE(r.has_clear_user_data()); + + EXPECT_TRUE(handler->ReceievedClearSuccessEvent()); + EXPECT_TRUE(on_should_stop_syncing_permanently_called_); + + EXPECT_FALSE(handler->ReceievedClearFailedEvent()); +} + +} // namespace browser_sync + diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc index 00d1c4f..a0b5f29 100644 --- a/chrome/browser/sync/engine/syncapi.cc +++ b/chrome/browser/sync/engine/syncapi.cc @@ -1329,6 +1329,10 @@ void SyncManager::RequestNudge() { data_->syncer_thread()->NudgeSyncer(0, SyncerThread::kLocal); } +void SyncManager::RequestClearServerData() { + data_->syncer_thread()->NudgeSyncer(0, SyncerThread::kClearPrivateData); +} + const std::string& SyncManager::GetAuthenticatedUsername() { DCHECK(data_); return data_->username_for_share(); @@ -1981,6 +1985,16 @@ void SyncManager::SyncInternal::HandleChannelEvent(const SyncerEvent& event) { observer_->OnStopSyncingPermanently(); return; } + + if (event.what_happened == SyncerEvent::CLEAR_SERVER_DATA_SUCCEEDED) { + observer_->OnClearServerDataSucceeded(); + return; + } + + if (event.what_happened == SyncerEvent::CLEAR_SERVER_DATA_FAILED) { + observer_->OnClearServerDataFailed(); + return; + } } void SyncManager::SyncInternal::HandleAuthWatcherEvent( diff --git a/chrome/browser/sync/engine/syncapi.h b/chrome/browser/sync/engine/syncapi.h index e4e8510..c49fc67 100644 --- a/chrome/browser/sync/engine/syncapi.h +++ b/chrome/browser/sync/engine/syncapi.h @@ -700,6 +700,11 @@ class SyncManager { // global stop syncing operation has wiped the store. virtual void OnStopSyncingPermanently() = 0; + // After a request to clear server data, these callbacks are invoked to + // indicate success or failure + virtual void OnClearServerDataSucceeded() = 0; + virtual void OnClearServerDataFailed() = 0; + private: DISALLOW_COPY_AND_ASSIGN(Observer); }; @@ -814,6 +819,9 @@ class SyncManager { // to run at the next available opportunity. void RequestNudge(); + // Request a clearing of all data on the server + void RequestClearServerData(); + // Adds a listener to be notified of sync events. // NOTE: It is OK (in fact, it's probably a good idea) to call this before // having received OnInitializationCompleted. diff --git a/chrome/browser/sync/engine/syncer.cc b/chrome/browser/sync/engine/syncer.cc index daf3bf0..112f474 100644 --- a/chrome/browser/sync/engine/syncer.cc +++ b/chrome/browser/sync/engine/syncer.cc @@ -11,6 +11,7 @@ #include "chrome/browser/sync/engine/build_and_process_conflict_sets_command.h" #include "chrome/browser/sync/engine/build_commit_command.h" #include "chrome/browser/sync/engine/cleanup_disabled_types_command.h" +#include "chrome/browser/sync/engine/clear_data_command.h" #include "chrome/browser/sync/engine/conflict_resolver.h" #include "chrome/browser/sync/engine/download_updates_command.h" #include "chrome/browser/sync/engine/get_commit_ids_command.h" @@ -96,20 +97,27 @@ bool Syncer::SyncShare(sessions::SyncSession::Delegate* delegate) { } bool Syncer::SyncShare(sessions::SyncSession* session) { - session->set_source(TestAndSetUpdatesSource()); - // This isn't perfect, as we can end up bundling extensions activity - // intended for the next session into the current one. We could do a - // test-and-reset as with the source, but note that also falls short if - // the commit request fails (due to lost connection, for example), as we will - // fall all the way back to the syncer thread main loop in that case, and - // wind up creating a new session when a connection is established, losing - // the records set here on the original attempt. This should provide us - // with the right data "most of the time", and we're only using this for - // analysis purposes, so Law of Large Numbers FTW. - context_->extensions_monitor()->GetAndClearRecords( - session->mutable_extensions_activity()); - SyncShare(session, SYNCER_BEGIN, SYNCER_END); - return session->HasMoreToSync(); + sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source = + TestAndSetUpdatesSource(); + session->set_source(source); + if (sync_pb::GetUpdatesCallerInfo::CLEAR_PRIVATE_DATA == source) { + SyncShare(session, CLEAR_PRIVATE_DATA, SYNCER_END); + return false; + } else { + // This isn't perfect, as we can end up bundling extensions activity + // intended for the next session into the current one. We could do a + // test-and-reset as with the source, but note that also falls short if + // the commit request fails (e.g. due to lost connection), as we will + // fall all the way back to the syncer thread main loop in that case, and + // wind up creating a new session when a connection is established, losing + // the records set here on the original attempt. This should provide us + // with the right data "most of the time", and we're only using this for + // analysis purposes, so Law of Large Numbers FTW. + context_->extensions_monitor()->GetAndClearRecords( + session->mutable_extensions_activity()); + SyncShare(session, SYNCER_BEGIN, SYNCER_END); + return session->HasMoreToSync(); + } } bool Syncer::SyncShare(SyncerStep first_step, SyncerStep last_step, @@ -276,6 +284,12 @@ void Syncer::SyncShare(sessions::SyncSession* session, next_step = SYNCER_END; break; } + case CLEAR_PRIVATE_DATA: { + LOG(INFO) << "Clear Private Data"; + ClearDataCommand clear_data_command; + clear_data_command.Execute(session); + next_step = SYNCER_END; + } case SYNCER_END: { LOG(INFO) << "Syncer End"; SyncerEndCommand syncer_end_command; diff --git a/chrome/browser/sync/engine/syncer.h b/chrome/browser/sync/engine/syncer.h index ce765da..9a07400 100644 --- a/chrome/browser/sync/engine/syncer.h +++ b/chrome/browser/sync/engine/syncer.h @@ -57,6 +57,7 @@ enum SyncerStep { BUILD_AND_PROCESS_CONFLICT_SETS, RESOLVE_CONFLICTS, APPLY_UPDATES_TO_RESOLVE_CONFLICTS, + CLEAR_PRIVATE_DATA, SYNCER_END }; diff --git a/chrome/browser/sync/engine/syncer_thread.cc b/chrome/browser/sync/engine/syncer_thread.cc index 800ddddb..324b65e 100644 --- a/chrome/browser/sync/engine/syncer_thread.cc +++ b/chrome/browser/sync/engine/syncer_thread.cc @@ -569,6 +569,9 @@ void SyncerThread::SetUpdatesSource(bool nudged, NudgeSource nudge_source, case kContinuation: updates_source = sync_pb::GetUpdatesCallerInfo::SYNC_CYCLE_CONTINUATION; break; + case kClearPrivateData: + updates_source = sync_pb::GetUpdatesCallerInfo::CLEAR_PRIVATE_DATA; + break; case kUnknown: default: updates_source = sync_pb::GetUpdatesCallerInfo::UNKNOWN; diff --git a/chrome/browser/sync/engine/syncer_thread.h b/chrome/browser/sync/engine/syncer_thread.h index 8c71db4..1b0d9de 100644 --- a/chrome/browser/sync/engine/syncer_thread.h +++ b/chrome/browser/sync/engine/syncer_thread.h @@ -91,7 +91,8 @@ class SyncerThread : public base::RefCountedThreadSafe<SyncerThread>, kUnknown = 0, kNotification, kLocal, - kContinuation + kContinuation, + kClearPrivateData }; // Server can overwrite these values via client commands. // Standard short poll. This is used when XMPP is off. diff --git a/chrome/browser/sync/engine/syncer_types.h b/chrome/browser/sync/engine/syncer_types.h index 19be54e..414f7ae 100644 --- a/chrome/browser/sync/engine/syncer_types.h +++ b/chrome/browser/sync/engine/syncer_types.h @@ -115,6 +115,11 @@ struct SyncerEvent { // data (i.e. as if the user clicked 'Stop Syncing' in the browser. STOP_SYNCING_PERMANENTLY, + // These events are sent to indicate when we know the clearing of + // server data have failed or succeeded. + CLEAR_SERVER_DATA_SUCCEEDED, + CLEAR_SERVER_DATA_FAILED, + // Sent when the main syncer loop finishes. SYNCER_THREAD_EXITING, }; diff --git a/chrome/browser/sync/engine/syncproto.h b/chrome/browser/sync/engine/syncproto.h index 4bd4596..6fca8e4 100644 --- a/chrome/browser/sync/engine/syncproto.h +++ b/chrome/browser/sync/engine/syncproto.h @@ -84,6 +84,7 @@ typedef sync_pb::ClientToServerResponse ClientToServerResponse; typedef sync_pb::CommitResponse CommitResponse; typedef sync_pb::GetUpdatesResponse GetUpdatesResponse; typedef sync_pb::GetUpdatesMessage GetUpdatesMessage; +typedef sync_pb::ClearUserDataRequest ClearDataRequest; } // namespace browser_sync |
