summaryrefslogtreecommitdiffstats
path: root/sync/engine/get_updates_processor.cc
diff options
context:
space:
mode:
authorrlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-28 21:40:13 +0000
committerrlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-28 21:40:13 +0000
commit2ac7a56c9e98ccb061b557e2b0365ce60457062d (patch)
treecb5b2be26c20357099e877d5258a15321a61e6ef /sync/engine/get_updates_processor.cc
parent06b242db0d9ca51e5699fbed24f9cb4858368080 (diff)
downloadchromium_src-2ac7a56c9e98ccb061b557e2b0365ce60457062d.zip
chromium_src-2ac7a56c9e98ccb061b557e2b0365ce60457062d.tar.gz
chromium_src-2ac7a56c9e98ccb061b557e2b0365ce60457062d.tar.bz2
sync: Move download logic into GetUpdatesProcessor
Moves more of the logic to build and process GetUpdates messages into the GetUpdatesProcessor. When refactoring the sync engine, some functions ended up being left orphaned in download.h. This CL gets them back into a class. This change should make the download updates logic a bit clearer, since the most of the update request building, sending, and processing logic will now live entirely in GetUpdatesProcessor and its helper class, GetUpdatesDelegate. BUG=278484 Review URL: https://codereview.chromium.org/174063003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@254238 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'sync/engine/get_updates_processor.cc')
-rw-r--r--sync/engine/get_updates_processor.cc167
1 files changed, 166 insertions, 1 deletions
diff --git a/sync/engine/get_updates_processor.cc b/sync/engine/get_updates_processor.cc
index 449f718..2ffc4b3 100644
--- a/sync/engine/get_updates_processor.cc
+++ b/sync/engine/get_updates_processor.cc
@@ -6,9 +6,16 @@
#include <map>
+#include "base/debug/trace_event.h"
#include "sync/engine/get_updates_delegate.h"
+#include "sync/engine/syncer_proto_util.h"
#include "sync/engine/update_handler.h"
#include "sync/protocol/sync.pb.h"
+#include "sync/sessions/status_controller.h"
+#include "sync/sessions/sync_session.h"
+#include "sync/syncable/directory.h"
+#include "sync/syncable/nigori_handler.h"
+#include "sync/syncable/syncable_read_transaction.h"
typedef std::vector<const sync_pb::SyncEntity*> SyncEntityList;
typedef std::map<syncer::ModelType, SyncEntityList> TypeSyncEntityMap;
@@ -19,6 +26,35 @@ typedef std::map<ModelType, size_t> TypeToIndexMap;
namespace {
+bool ShouldRequestEncryptionKey(sessions::SyncSessionContext* context) {
+ syncable::Directory* dir = context->directory();
+ syncable::ReadTransaction trans(FROM_HERE, dir);
+ syncable::NigoriHandler* nigori_handler = dir->GetNigoriHandler();
+ return nigori_handler->NeedKeystoreKey(&trans);
+}
+
+
+SyncerError HandleGetEncryptionKeyResponse(
+ const sync_pb::ClientToServerResponse& update_response,
+ syncable::Directory* dir) {
+ bool success = false;
+ if (update_response.get_updates().encryption_keys_size() == 0) {
+ LOG(ERROR) << "Failed to receive encryption key from server.";
+ return SERVER_RESPONSE_VALIDATION_FAILED;
+ }
+ syncable::ReadTransaction trans(FROM_HERE, dir);
+ syncable::NigoriHandler* nigori_handler = dir->GetNigoriHandler();
+ success = nigori_handler->SetKeystoreKeys(
+ update_response.get_updates().encryption_keys(),
+ &trans);
+
+ DVLOG(1) << "GetUpdates returned "
+ << update_response.get_updates().encryption_keys_size()
+ << "encryption keys. Nigori keystore key "
+ << (success ? "" : "not ") << "updated.";
+ return (success ? SYNCER_OK : SERVER_RESPONSE_VALIDATION_FAILED);
+}
+
// Given a GetUpdates response, iterates over all the returned items and
// divides them according to their type. Outputs a map from model types to
// received SyncEntities. The output map will have entries (possibly empty)
@@ -74,6 +110,34 @@ void PartitionProgressMarkersByType(
}
}
+// Initializes the parts of the GetUpdatesMessage that depend on shared state,
+// like the ShouldRequestEncryptionKey() status. This is kept separate from the
+// other of the message-building functions to make the rest of the code easier
+// to test.
+void InitDownloadUpdatesContext(
+ sessions::SyncSession* session,
+ bool create_mobile_bookmarks_folder,
+ sync_pb::ClientToServerMessage* message) {
+ message->set_share(session->context()->account_name());
+ message->set_message_contents(sync_pb::ClientToServerMessage::GET_UPDATES);
+
+ sync_pb::GetUpdatesMessage* get_updates = message->mutable_get_updates();
+
+ // We want folders for our associated types, always. If we were to set
+ // this to false, the server would send just the non-container items
+ // (e.g. Bookmark URLs but not their containing folders).
+ get_updates->set_fetch_folders(true);
+
+ get_updates->set_create_mobile_bookmarks_folder(
+ create_mobile_bookmarks_folder);
+ bool need_encryption_key = ShouldRequestEncryptionKey(session->context());
+ get_updates->set_need_encryption_key(need_encryption_key);
+
+ // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information.
+ get_updates->mutable_caller_info()->set_notifications_enabled(
+ session->context()->notifications_enabled());
+}
+
} // namespace
GetUpdatesProcessor::GetUpdatesProcessor(UpdateHandlerMap* update_handler_map,
@@ -82,9 +146,29 @@ GetUpdatesProcessor::GetUpdatesProcessor(UpdateHandlerMap* update_handler_map,
GetUpdatesProcessor::~GetUpdatesProcessor() {}
+SyncerError GetUpdatesProcessor::DownloadUpdates(
+ ModelTypeSet request_types,
+ sessions::SyncSession* session,
+ bool create_mobile_bookmarks_folder) {
+ TRACE_EVENT0("sync", "DownloadUpdates");
+
+ sync_pb::ClientToServerMessage message;
+ InitDownloadUpdatesContext(session,
+ create_mobile_bookmarks_folder,
+ &message);
+ PrepareGetUpdates(request_types, &message);
+
+ SyncerError result = ExecuteDownloadUpdates(request_types, session, &message);
+ session->mutable_status_controller()->set_last_download_updates_result(
+ result);
+ return result;
+}
+
void GetUpdatesProcessor::PrepareGetUpdates(
ModelTypeSet gu_types,
- sync_pb::GetUpdatesMessage* get_updates) {
+ sync_pb::ClientToServerMessage* message) {
+ sync_pb::GetUpdatesMessage* get_updates = message->mutable_get_updates();
+
for (ModelTypeSet::Iterator it = gu_types.First(); it.Good(); it.Inc()) {
UpdateHandlerMap::iterator handler_it = update_handler_map_->find(it.Get());
DCHECK(handler_it != update_handler_map_->end());
@@ -95,6 +179,80 @@ void GetUpdatesProcessor::PrepareGetUpdates(
delegate_.HelpPopulateGuMessage(get_updates);
}
+SyncerError GetUpdatesProcessor::ExecuteDownloadUpdates(
+ ModelTypeSet request_types,
+ sessions::SyncSession* session,
+ sync_pb::ClientToServerMessage* msg) {
+ sync_pb::ClientToServerResponse update_response;
+ sessions::StatusController* status = session->mutable_status_controller();
+ bool need_encryption_key = ShouldRequestEncryptionKey(session->context());
+
+ if (session->context()->debug_info_getter()) {
+ sync_pb::DebugInfo* debug_info = msg->mutable_debug_info();
+ CopyClientDebugInfo(session->context()->debug_info_getter(), debug_info);
+ }
+
+ SyncerError result = SyncerProtoUtil::PostClientToServerMessage(
+ msg,
+ &update_response,
+ session);
+
+ DVLOG(2) << SyncerProtoUtil::ClientToServerResponseDebugString(
+ update_response);
+
+ if (result != SYNCER_OK) {
+ LOG(ERROR) << "PostClientToServerMessage() failed during GetUpdates";
+ return result;
+ }
+
+ DVLOG(1) << "GetUpdates "
+ << " returned " << update_response.get_updates().entries_size()
+ << " updates and indicated "
+ << update_response.get_updates().changes_remaining()
+ << " updates left on server.";
+
+ if (session->context()->debug_info_getter()) {
+ // Clear debug info now that we have successfully sent it to the server.
+ DVLOG(1) << "Clearing client debug info.";
+ session->context()->debug_info_getter()->ClearDebugInfo();
+ }
+
+ if (need_encryption_key ||
+ update_response.get_updates().encryption_keys_size() > 0) {
+ syncable::Directory* dir = session->context()->directory();
+ status->set_last_get_key_result(
+ HandleGetEncryptionKeyResponse(update_response, dir));
+ }
+
+ return ProcessResponse(update_response.get_updates(),
+ request_types,
+ status);
+}
+
+SyncerError GetUpdatesProcessor::ProcessResponse(
+ const sync_pb::GetUpdatesResponse& gu_response,
+ ModelTypeSet request_types,
+ sessions::StatusController* status) {
+ status->increment_num_updates_downloaded_by(gu_response.entries_size());
+
+ // The changes remaining field is used to prevent the client from looping. If
+ // that field is being set incorrectly, we're in big trouble.
+ if (!gu_response.has_changes_remaining()) {
+ return SERVER_RESPONSE_VALIDATION_FAILED;
+ }
+ status->set_num_server_changes_remaining(gu_response.changes_remaining());
+
+ if (!ProcessGetUpdatesResponse(request_types, gu_response, status)) {
+ return SERVER_RESPONSE_VALIDATION_FAILED;
+ }
+
+ if (gu_response.changes_remaining() == 0) {
+ return SYNCER_OK;
+ } else {
+ return SERVER_MORE_TO_DOWNLOAD;
+ }
+}
+
bool GetUpdatesProcessor::ProcessGetUpdatesResponse(
ModelTypeSet gu_types,
const sync_pb::GetUpdatesResponse& gu_response,
@@ -148,4 +306,11 @@ void GetUpdatesProcessor::ApplyUpdates(
delegate_.ApplyUpdates(status_controller, update_handler_map_);
}
+void GetUpdatesProcessor::CopyClientDebugInfo(
+ sessions::DebugInfoGetter* debug_info_getter,
+ sync_pb::DebugInfo* debug_info) {
+ DVLOG(1) << "Copying client debug info to send.";
+ debug_info_getter->GetDebugInfo(debug_info);
+}
+
} // namespace syncer