Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(138)

Side by Side Diff: chrome/browser/sync/glue/extension_sync.cc

Issue 6902054: [Sync] Rip out overly-complicated ExtensionData class (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/sync/glue/extension_sync.h" 5 #include "chrome/browser/sync/glue/extension_sync.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "chrome/browser/extensions/extension_updater.h"
11 #include "chrome/browser/extensions/extension_service.h" 10 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/extension_sync_data.h" 11 #include "chrome/browser/extensions/extension_sync_data.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/sync/engine/syncapi.h" 12 #include "chrome/browser/sync/engine/syncapi.h"
15 #include "chrome/browser/sync/glue/extension_data.h"
16 #include "chrome/browser/sync/glue/extension_sync_traits.h" 13 #include "chrome/browser/sync/glue/extension_sync_traits.h"
17 #include "chrome/browser/sync/glue/extension_util.h" 14 #include "chrome/browser/sync/glue/extension_util.h"
18 #include "chrome/browser/sync/profile_sync_service.h" 15 #include "chrome/browser/sync/protocol/extension_specifics.pb.h"
19 16
20 namespace browser_sync { 17 namespace browser_sync {
21 18
22 bool RootNodeHasChildren(const char* tag, 19 bool RootNodeHasChildren(const char* tag,
23 sync_api::UserShare* user_share, 20 sync_api::UserShare* user_share,
24 bool* has_children) { 21 bool* has_children) {
25 CHECK(has_children); 22 CHECK(has_children);
26 *has_children = false; 23 *has_children = false;
27 sync_api::ReadTransaction trans(user_share); 24 sync_api::ReadTransaction trans(user_share);
28 sync_api::ReadNode node(&trans); 25 sync_api::ReadNode node(&trans);
29 if (!node.InitByTagLookup(tag)) { 26 if (!node.InitByTagLookup(tag)) {
30 LOG(ERROR) << "Root node with tag " << tag << " does not exist"; 27 LOG(ERROR) << "Root node with tag " << tag << " does not exist";
31 return false; 28 return false;
32 } 29 }
33 *has_children = node.GetFirstChildId() != sync_api::kInvalidId; 30 *has_children = node.GetFirstChildId() != sync_api::kInvalidId;
34 return true; 31 return true;
35 } 32 }
36 33
37 namespace { 34 namespace {
38 35
39 // Updates the value in |extension_data_map| from the given data,
40 // creating an entry if necessary. Returns a pointer to the
41 // updated/created ExtensionData object.
42 ExtensionData* SetOrCreateExtensionData(
43 ExtensionDataMap* extension_data_map,
44 ExtensionData::Source source,
45 bool merge_user_properties,
46 const sync_pb::ExtensionSpecifics& data) {
47 DcheckIsExtensionSpecificsValid(data);
48 const std::string& extension_id = data.id();
49 std::pair<ExtensionDataMap::iterator, bool> result =
50 extension_data_map->insert(
51 std::make_pair(extension_id,
52 ExtensionData::FromData(source, data)));
53 ExtensionData* extension_data = &result.first->second;
54 if (result.second) {
55 // The value was just inserted, so it shouldn't need an update
56 // from source.
57 DCHECK(!extension_data->NeedsUpdate(source));
58 } else {
59 extension_data->SetData(source, merge_user_properties, data);
60 }
61 return extension_data;
62 }
63
64 // Fills in |extension_data_map| with data from 36 // Fills in |extension_data_map| with data from
65 // extension_service.GetSyncDataList(). 37 // extension_service.GetSyncDataList().
66 void SlurpClientData( 38 void SlurpClientData(
67 IsValidAndSyncablePredicate is_valid_and_syncable, 39 IsValidAndSyncablePredicate is_valid_and_syncable,
68 const ExtensionServiceInterface& extension_service, 40 const ExtensionServiceInterface& extension_service,
69 ExtensionDataMap* extension_data_map) { 41 ExtensionDataMap* extension_data_map) {
70 std::vector<ExtensionSyncData> sync_data_list = 42 std::vector<ExtensionSyncData> sync_data_list =
71 extension_service.GetSyncDataList(is_valid_and_syncable); 43 extension_service.GetSyncDataList(is_valid_and_syncable);
72 for (std::vector<ExtensionSyncData>::const_iterator it = 44 for (std::vector<ExtensionSyncData>::const_iterator it =
73 sync_data_list.begin(); 45 sync_data_list.begin();
74 it != sync_data_list.end(); ++it) { 46 it != sync_data_list.end(); ++it) {
75 sync_pb::ExtensionSpecifics client_specifics; 47 std::pair<ExtensionDataMap::iterator, bool> result =
76 SyncDataToSpecifics(*it, &client_specifics); 48 extension_data_map->insert(std::make_pair(it->id, *it));
77 const ExtensionData& extension_data = 49 if (!result.second) {
78 *SetOrCreateExtensionData( 50 // The value wasn't inserted, so merge it in.
79 extension_data_map, ExtensionData::CLIENT, 51 result.first->second.Merge(*it);
asargent_no_longer_on_chrome 2011/04/27 16:45:19 It's not really clear to me why you need this Merg
akalin 2011/04/27 17:53:25 (The above is equivalent to "(*extension_data_map)
80 true, client_specifics); 52 }
81 DcheckIsExtensionSpecificsValid(extension_data.merged_data());
82 } 53 }
83 } 54 }
84 55
85 // Gets the boilerplate error message for not being able to find a 56 // Gets the boilerplate error message for not being able to find a
86 // root node. 57 // root node.
87 // 58 //
88 // TODO(akalin): Put this somewhere where all data types can use it. 59 // TODO(akalin): Put this somewhere where all data types can use it.
89 std::string GetRootNodeDoesNotExistError(const char* root_node_tag) { 60 std::string GetRootNodeDoesNotExistError(const char* root_node_tag) {
90 return 61 return
91 std::string("Server did not create the top-level ") + 62 std::string("Server did not create the top-level ") +
92 root_node_tag + 63 root_node_tag +
93 " node. We might be running against an out-of-date server."; 64 " node. We might be running against an out-of-date server.";
94 } 65 }
95 66
96 // Gets the data from the server for extensions to be synced and 67 // Gets the data from the server for extensions to be synced and
97 // updates |extension_data_map|. Skips all extensions in 68 // updates |extension_data_map|.
98 // |unsynced_extensions|.
99 bool SlurpServerData( 69 bool SlurpServerData(
100 const char* root_node_tag, 70 const char* root_node_tag,
101 const ExtensionSpecificsGetter extension_specifics_getter, 71 const ExtensionSpecificsGetter extension_specifics_getter,
102 sync_api::UserShare* user_share, 72 sync_api::UserShare* user_share,
103 ExtensionDataMap* extension_data_map) { 73 ExtensionDataMap* extension_data_map) {
104 sync_api::WriteTransaction trans(user_share); 74 sync_api::WriteTransaction trans(user_share);
105 sync_api::ReadNode root(&trans); 75 sync_api::ReadNode root(&trans);
106 if (!root.InitByTagLookup(root_node_tag)) { 76 if (!root.InitByTagLookup(root_node_tag)) {
107 LOG(ERROR) << GetRootNodeDoesNotExistError(root_node_tag); 77 LOG(ERROR) << GetRootNodeDoesNotExistError(root_node_tag);
108 return false; 78 return false;
109 } 79 }
110 80
111 int64 id = root.GetFirstChildId(); 81 int64 id = root.GetFirstChildId();
112 while (id != sync_api::kInvalidId) { 82 while (id != sync_api::kInvalidId) {
113 sync_api::ReadNode sync_node(&trans); 83 sync_api::ReadNode sync_node(&trans);
114 if (!sync_node.InitByIdLookup(id)) { 84 if (!sync_node.InitByIdLookup(id)) {
115 LOG(ERROR) << "Failed to fetch sync node for id " << id; 85 LOG(ERROR) << "Failed to fetch sync node for id " << id;
116 return false; 86 return false;
117 } 87 }
118 const sync_pb::ExtensionSpecifics& server_data = 88 const sync_pb::ExtensionSpecifics& server_data =
119 (*extension_specifics_getter)(sync_node); 89 (*extension_specifics_getter)(sync_node);
120 if (!IsExtensionSpecificsValid(server_data)) { 90 ExtensionSyncData sync_data;
91 if (!SpecificsToSyncData(server_data, &sync_data)) {
121 LOG(ERROR) << "Invalid extensions specifics for id " << id; 92 LOG(ERROR) << "Invalid extensions specifics for id " << id;
122 return false; 93 return false;
123 } 94 }
124 // Pass in false for merge_user_properties so client user 95 (*extension_data_map)[sync_data.id] = sync_data;
125 // settings always take precedence.
126 const ExtensionData& extension_data =
127 *SetOrCreateExtensionData(
128 extension_data_map, ExtensionData::SERVER, false, server_data);
129 DcheckIsExtensionSpecificsValid(extension_data.merged_data());
130 id = sync_node.GetSuccessorId(); 96 id = sync_node.GetSuccessorId();
131 } 97 }
132 return true; 98 return true;
133 } 99 }
134 100
135 } // namespace 101 } // namespace
136 102
137 bool SlurpExtensionData(const ExtensionSyncTraits& traits, 103 bool SlurpExtensionData(const ExtensionSyncTraits& traits,
138 const ExtensionServiceInterface& extension_service, 104 const ExtensionServiceInterface& extension_service,
139 sync_api::UserShare* user_share, 105 sync_api::UserShare* user_share,
140 ExtensionDataMap* extension_data_map) { 106 ExtensionDataMap* extension_data_map) {
141 // Read client-side data first so server data takes precedence. 107 // Read server-side data first so client user settings take
142 SlurpClientData( 108 // precedence.
143 traits.is_valid_and_syncable, extension_service,
144 extension_data_map);
145
146 if (!SlurpServerData( 109 if (!SlurpServerData(
147 traits.root_node_tag, traits.extension_specifics_getter, 110 traits.root_node_tag, traits.extension_specifics_getter,
148 user_share, extension_data_map)) { 111 user_share, extension_data_map)) {
149 return false; 112 return false;
150 } 113 }
114
115 SlurpClientData(
116 traits.is_valid_and_syncable, extension_service,
117 extension_data_map);
151 return true; 118 return true;
152 } 119 }
153 120
154 namespace { 121 namespace {
155 122
156 // Updates the server data from the given extension data. 123 // Updates the server data from the given extension data. Returns
157 // extension_data->ServerNeedsUpdate() must hold before this function 124 // whether or not the update was successful.
158 // is called. Returns whether or not the update was successful. If
159 // the update was successful, extension_data->ServerNeedsUpdate() will
160 // be false after this function is called. This function leaves
161 // extension_data->ClientNeedsUpdate() unchanged.
162 bool UpdateServer( 125 bool UpdateServer(
163 const ExtensionSyncTraits& traits, 126 const ExtensionSyncTraits& traits,
164 ExtensionData* extension_data, 127 const ExtensionSyncData& data,
165 sync_api::WriteTransaction* trans) { 128 sync_api::WriteTransaction* trans) {
166 DCHECK(extension_data->NeedsUpdate(ExtensionData::SERVER)); 129 sync_pb::ExtensionSpecifics specifics;
167 const sync_pb::ExtensionSpecifics& specifics = 130 SyncDataToSpecifics(data, &specifics);
168 extension_data->merged_data(); 131 const std::string& id = data.id;
169 const std::string& id = specifics.id();
170 sync_api::WriteNode write_node(trans); 132 sync_api::WriteNode write_node(trans);
171 if (write_node.InitByClientTagLookup(traits.model_type, id)) { 133 if (write_node.InitByClientTagLookup(traits.model_type, id)) {
172 (*traits.extension_specifics_setter)(specifics, &write_node); 134 (*traits.extension_specifics_setter)(specifics, &write_node);
173 } else { 135 } else {
174 sync_api::ReadNode root(trans); 136 sync_api::ReadNode root(trans);
175 if (!root.InitByTagLookup(traits.root_node_tag)) { 137 if (!root.InitByTagLookup(traits.root_node_tag)) {
176 LOG(ERROR) << GetRootNodeDoesNotExistError(traits.root_node_tag); 138 LOG(ERROR) << GetRootNodeDoesNotExistError(traits.root_node_tag);
177 return false; 139 return false;
178 } 140 }
179 sync_api::WriteNode create_node(trans); 141 sync_api::WriteNode create_node(trans);
180 if (!create_node.InitUniqueByCreation(traits.model_type, root, id)) { 142 if (!create_node.InitUniqueByCreation(traits.model_type, root, id)) {
181 LOG(ERROR) << "Could not create node for extension " << id; 143 LOG(ERROR) << "Could not create node for extension " << id;
182 return false; 144 return false;
183 } 145 }
184 (*traits.extension_specifics_setter)(specifics, &create_node); 146 (*traits.extension_specifics_setter)(specifics, &create_node);
185 } 147 }
186 bool old_client_needs_update =
187 extension_data->NeedsUpdate(ExtensionData::CLIENT);
188 extension_data->ResolveData(ExtensionData::SERVER);
189 DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER));
190 DCHECK_EQ(extension_data->NeedsUpdate(ExtensionData::CLIENT),
191 old_client_needs_update);
192 return true; 148 return true;
193 } 149 }
194 150
195 } // namespace 151 } // namespace
196 152
197 bool FlushExtensionData(const ExtensionSyncTraits& traits, 153 bool FlushExtensionData(const ExtensionSyncTraits& traits,
198 const ExtensionDataMap& extension_data_map, 154 const ExtensionDataMap& extension_data_map,
199 ExtensionServiceInterface* extension_service, 155 ExtensionServiceInterface* extension_service,
200 sync_api::UserShare* user_share) { 156 sync_api::UserShare* user_share) {
201 sync_api::WriteTransaction trans(user_share); 157 sync_api::WriteTransaction trans(user_share);
202 sync_api::ReadNode root(&trans); 158 sync_api::ReadNode root(&trans);
203 if (!root.InitByTagLookup(traits.root_node_tag)) { 159 if (!root.InitByTagLookup(traits.root_node_tag)) {
204 LOG(ERROR) << GetRootNodeDoesNotExistError(traits.root_node_tag); 160 LOG(ERROR) << GetRootNodeDoesNotExistError(traits.root_node_tag);
205 return false; 161 return false;
206 } 162 }
207 163
208 // Update server and client as necessary. 164 // Update server and client as necessary.
209 for (ExtensionDataMap::const_iterator it = extension_data_map.begin(); 165 for (ExtensionDataMap::const_iterator it = extension_data_map.begin();
210 it != extension_data_map.end(); ++it) { 166 it != extension_data_map.end(); ++it) {
211 ExtensionData extension_data = it->second; 167 const ExtensionSyncData& extension_data = it->second;
212 // Update server first. 168 if (!UpdateServer(traits, extension_data, &trans)) {
213 if (extension_data.NeedsUpdate(ExtensionData::SERVER)) { 169 LOG(ERROR) << "Could not update server data for extension "
214 if (!UpdateServer(traits, &extension_data, &trans)) { 170 << it->first;
215 LOG(ERROR) << "Could not update server data for extension "
216 << it->first;
217 return false;
218 }
219 }
220 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER));
221 ExtensionSyncData sync_data;
222 if (!SpecificsToSyncData(extension_data.merged_data(), &sync_data)) {
223 // TODO(akalin): Should probably recover or drop.
224 NOTREACHED();
225 return false; 171 return false;
226 } 172 }
227 extension_service->ProcessSyncData(sync_data, 173 extension_service->ProcessSyncData(extension_data,
228 traits.is_valid_and_syncable); 174 traits.is_valid_and_syncable);
229 } 175 }
230 return true; 176 return true;
231 } 177 }
232 178
233 bool UpdateServerData(const ExtensionSyncTraits& traits, 179 bool UpdateServerData(const ExtensionSyncTraits& traits,
234 const std::string& id, 180 const std::string& id,
235 const ExtensionServiceInterface& extension_service, 181 const ExtensionServiceInterface& extension_service,
236 sync_api::UserShare* user_share, 182 sync_api::UserShare* user_share,
237 std::string* error) { 183 std::string* error) {
238 ExtensionSyncData data; 184 ExtensionSyncData data;
239 if (!extension_service.GetSyncData( 185 if (!extension_service.GetSyncData(
240 id, traits.is_valid_and_syncable, &data)) { 186 id, traits.is_valid_and_syncable, &data)) {
241 *error = 187 *error =
242 std::string("UpdateServerData() called for invalid or " 188 std::string("UpdateServerData() called for invalid or "
243 "unsyncable extension ") + id; 189 "unsyncable extension ") + id;
244 LOG(DFATAL) << *error; 190 LOG(DFATAL) << *error;
245 return false; 191 return false;
246 } 192 }
247 sync_pb::ExtensionSpecifics client_data;
248 SyncDataToSpecifics(data, &client_data);
249 DcheckIsExtensionSpecificsValid(client_data);
250 ExtensionData extension_data =
251 ExtensionData::FromData(ExtensionData::CLIENT, client_data);
252 193
253 sync_api::WriteTransaction trans(user_share); 194 sync_api::WriteTransaction trans(user_share);
254 195 if (!UpdateServer(traits, data, &trans)) {
255 sync_api::ReadNode node(&trans); 196 *error =
256 if (node.InitByClientTagLookup(traits.model_type, id)) { 197 std::string("Could not update server data for extension ") + id;
257 sync_pb::ExtensionSpecifics server_data = 198 LOG(ERROR) << *error;
258 (*traits.extension_specifics_getter)(node); 199 return false;
259 if (IsExtensionSpecificsValid(server_data)) {
260 // If server node exists and is valid, update |extension_data|
261 // from it (but with it taking precedence).
262 extension_data =
263 ExtensionData::FromData(ExtensionData::SERVER, server_data);
264 extension_data.SetData(ExtensionData::CLIENT, true, client_data);
265 } else {
266 LOG(ERROR) << "Invalid extensions specifics for id " << id
267 << "; treating as empty";
268 }
269 } 200 }
270
271 if (extension_data.NeedsUpdate(ExtensionData::SERVER)) {
272 if (!UpdateServer(traits, &extension_data, &trans)) {
273 *error =
274 std::string("Could not update server data for extension ") + id;
275 LOG(ERROR) << *error;
276 return false;
277 }
278 }
279 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER));
280 // Client may still need updating, e.g. if we disable an extension
281 // while it's being auto-updated. If so, then we'll be called
282 // again once the auto-update is finished.
283 //
284 // TODO(akalin): Figure out a way to tell when the above happens,
285 // so we know exactly what NeedsUpdate(CLIENT) should return.
286 return true; 201 return true;
287 } 202 }
288 203
289 void RemoveServerData(const ExtensionSyncTraits& traits, 204 void RemoveServerData(const ExtensionSyncTraits& traits,
290 const std::string& id, 205 const std::string& id,
291 sync_api::UserShare* user_share) { 206 sync_api::UserShare* user_share) {
292 sync_api::WriteTransaction trans(user_share); 207 sync_api::WriteTransaction trans(user_share);
293 sync_api::WriteNode write_node(&trans); 208 sync_api::WriteNode write_node(&trans);
294 if (write_node.InitByClientTagLookup(traits.model_type, id)) { 209 if (write_node.InitByClientTagLookup(traits.model_type, id)) {
295 write_node.Remove(); 210 write_node.Remove();
296 } else { 211 } else {
297 LOG(ERROR) << "Server data does not exist for extension " << id; 212 LOG(ERROR) << "Server data does not exist for extension " << id;
298 } 213 }
299 } 214 }
300 215
301 } // namespace browser_sync 216 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698