Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / sync / engine / download.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "sync/engine/download.h"
6
7 #include <string>
8
9 #include "sync/engine/syncer_proto_util.h"
10 #include "sync/sessions/sync_session.h"
11 #include "sync/sessions/sync_session_context.h"
12 #include "sync/syncable/directory.h"
13 #include "sync/syncable/nigori_handler.h"
14 #include "sync/syncable/syncable_read_transaction.h"
15
16 namespace syncer {
17
18 using sessions::StatusController;
19 using sessions::SyncSession;
20 using sessions::SyncSessionContext;
21 using std::string;
22
23 namespace {
24
25 SyncerError HandleGetEncryptionKeyResponse(
26     const sync_pb::ClientToServerResponse& update_response,
27     syncable::Directory* dir) {
28   bool success = false;
29   if (update_response.get_updates().encryption_keys_size() == 0) {
30     LOG(ERROR) << "Failed to receive encryption key from server.";
31     return SERVER_RESPONSE_VALIDATION_FAILED;
32   }
33   syncable::ReadTransaction trans(FROM_HERE, dir);
34   syncable::NigoriHandler* nigori_handler = dir->GetNigoriHandler();
35   success = nigori_handler->SetKeystoreKeys(
36       update_response.get_updates().encryption_keys(),
37       &trans);
38
39   DVLOG(1) << "GetUpdates returned "
40            << update_response.get_updates().encryption_keys_size()
41            << "encryption keys. Nigori keystore key "
42            << (success ? "" : "not ") << "updated.";
43   return (success ? SYNCER_OK : SERVER_RESPONSE_VALIDATION_FAILED);
44 }
45
46 bool ShouldRequestEncryptionKey(
47     SyncSessionContext* context) {
48   bool need_encryption_key = false;
49   if (context->keystore_encryption_enabled()) {
50     syncable::Directory* dir = context->directory();
51     syncable::ReadTransaction trans(FROM_HERE, dir);
52     syncable::NigoriHandler* nigori_handler = dir->GetNigoriHandler();
53     need_encryption_key = nigori_handler->NeedKeystoreKey(&trans);
54   }
55   return need_encryption_key;
56 }
57
58 }  // namespace
59
60 namespace download {
61
62 void InitDownloadUpdatesContext(
63     SyncSession* session,
64     bool create_mobile_bookmarks_folder,
65     sync_pb::ClientToServerMessage* message) {
66   message->set_share(session->context()->account_name());
67   message->set_message_contents(sync_pb::ClientToServerMessage::GET_UPDATES);
68
69   sync_pb::GetUpdatesMessage* get_updates = message->mutable_get_updates();
70
71   // We want folders for our associated types, always.  If we were to set
72   // this to false, the server would send just the non-container items
73   // (e.g. Bookmark URLs but not their containing folders).
74   get_updates->set_fetch_folders(true);
75
76   get_updates->set_create_mobile_bookmarks_folder(
77       create_mobile_bookmarks_folder);
78   bool need_encryption_key = ShouldRequestEncryptionKey(session->context());
79   get_updates->set_need_encryption_key(need_encryption_key);
80
81   // Set legacy GetUpdatesMessage.GetUpdatesCallerInfo information.
82   get_updates->mutable_caller_info()->set_notifications_enabled(
83       session->context()->notifications_enabled());
84 }
85
86 SyncerError ExecuteDownloadUpdates(
87     ModelTypeSet request_types,
88     SyncSession* session,
89     GetUpdatesProcessor* get_updates_processor,
90     sync_pb::ClientToServerMessage* msg) {
91   sync_pb::ClientToServerResponse update_response;
92   StatusController* status = session->mutable_status_controller();
93   bool need_encryption_key = ShouldRequestEncryptionKey(session->context());
94
95   if (session->context()->debug_info_getter()) {
96     sync_pb::DebugInfo* debug_info = msg->mutable_debug_info();
97     CopyClientDebugInfo(session->context()->debug_info_getter(), debug_info);
98   }
99
100   SyncerError result = SyncerProtoUtil::PostClientToServerMessage(
101       msg,
102       &update_response,
103       session);
104
105   DVLOG(2) << SyncerProtoUtil::ClientToServerResponseDebugString(
106       update_response);
107
108   if (result != SYNCER_OK) {
109     LOG(ERROR) << "PostClientToServerMessage() failed during GetUpdates";
110     return result;
111   }
112
113   DVLOG(1) << "GetUpdates "
114            << " returned " << update_response.get_updates().entries_size()
115            << " updates and indicated "
116            << update_response.get_updates().changes_remaining()
117            << " updates left on server.";
118
119   if (session->context()->debug_info_getter()) {
120     // Clear debug info now that we have successfully sent it to the server.
121     DVLOG(1) << "Clearing client debug info.";
122     session->context()->debug_info_getter()->ClearDebugInfo();
123   }
124
125   if (need_encryption_key ||
126       update_response.get_updates().encryption_keys_size() > 0) {
127     syncable::Directory* dir = session->context()->directory();
128     status->set_last_get_key_result(
129         HandleGetEncryptionKeyResponse(update_response, dir));
130   }
131
132   return ProcessResponse(update_response.get_updates(),
133                          request_types,
134                          get_updates_processor,
135                          status);
136 }
137
138 SyncerError ProcessResponse(
139     const sync_pb::GetUpdatesResponse& gu_response,
140     ModelTypeSet request_types,
141     GetUpdatesProcessor* get_updates_processor,
142     StatusController* status) {
143   status->increment_num_updates_downloaded_by(gu_response.entries_size());
144
145   // The changes remaining field is used to prevent the client from looping.  If
146   // that field is being set incorrectly, we're in big trouble.
147   if (!gu_response.has_changes_remaining()) {
148     return SERVER_RESPONSE_VALIDATION_FAILED;
149   }
150   status->set_num_server_changes_remaining(gu_response.changes_remaining());
151
152
153   if (!get_updates_processor->ProcessGetUpdatesResponse(request_types,
154                                                         gu_response,
155                                                         status)) {
156     return SERVER_RESPONSE_VALIDATION_FAILED;
157   }
158
159   if (gu_response.changes_remaining() == 0) {
160     return SYNCER_OK;
161   } else {
162     return SERVER_MORE_TO_DOWNLOAD;
163   }
164 }
165
166 void CopyClientDebugInfo(
167     sessions::DebugInfoGetter* debug_info_getter,
168     sync_pb::DebugInfo* debug_info) {
169   DVLOG(1) << "Copying client debug info to send.";
170   debug_info_getter->GetDebugInfo(debug_info);
171 }
172
173 }  // namespace download
174
175 }  // namespace syncer