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

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

Issue 7564037: Apps/Extensions Sync refactoring -- delete most of the old glue, implement new sync API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 9 years, 4 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/sync/glue/extension_sync.h"
6
7 #include <utility>
8
9 #include "base/logging.h"
10 #include "base/tracked.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/extension_sync_data.h"
13 #include "chrome/browser/sync/engine/syncapi.h"
14 #include "chrome/browser/sync/glue/extension_sync_traits.h"
15 #include "chrome/browser/sync/glue/extension_util.h"
16 #include "chrome/browser/sync/protocol/extension_specifics.pb.h"
17
18 namespace browser_sync {
19
20 bool RootNodeHasChildren(const char* tag,
21 sync_api::UserShare* user_share,
22 bool* has_children) {
23 CHECK(has_children);
24 *has_children = false;
25 sync_api::ReadTransaction trans(FROM_HERE, user_share);
26 sync_api::ReadNode node(&trans);
27 if (!node.InitByTagLookup(tag)) {
28 LOG(ERROR) << "Root node with tag " << tag << " does not exist";
29 return false;
30 }
31 *has_children = node.GetFirstChildId() != sync_api::kInvalidId;
32 return true;
33 }
34
35 namespace {
36
37 // Fills in |extension_data_map| with data from
38 // extension_service.GetSyncDataList().
39 void SlurpClientData(
40 IsValidAndSyncablePredicate is_valid_and_syncable,
41 const ExtensionServiceInterface& extension_service,
42 ExtensionDataMap* extension_data_map) {
43 std::vector<ExtensionSyncData> sync_data_list =
44 extension_service.GetSyncDataList(is_valid_and_syncable);
45 for (std::vector<ExtensionSyncData>::const_iterator it =
46 sync_data_list.begin();
47 it != sync_data_list.end(); ++it) {
48 std::pair<ExtensionDataMap::iterator, bool> result =
49 extension_data_map->insert(std::make_pair(it->id, *it));
50 if (!result.second) {
51 // The value wasn't inserted, so merge it in.
52 result.first->second.Merge(*it);
53 }
54 }
55 }
56
57 // Gets the boilerplate error message for not being able to find a
58 // root node.
59 //
60 // TODO(akalin): Put this somewhere where all data types can use it.
61 std::string GetRootNodeDoesNotExistError(const char* root_node_tag) {
62 return
63 std::string("Server did not create the top-level ") +
64 root_node_tag +
65 " node. We might be running against an out-of-date server.";
66 }
67
68 // Gets the data from the server for extensions to be synced and
69 // updates |extension_data_map|.
70 bool SlurpServerData(
71 const char* root_node_tag,
72 const ExtensionSpecificsGetter extension_specifics_getter,
73 sync_api::UserShare* user_share,
74 ExtensionDataMap* extension_data_map) {
75 sync_api::WriteTransaction trans(FROM_HERE, user_share);
76 sync_api::ReadNode root(&trans);
77 if (!root.InitByTagLookup(root_node_tag)) {
78 LOG(ERROR) << GetRootNodeDoesNotExistError(root_node_tag);
79 return false;
80 }
81
82 int64 id = root.GetFirstChildId();
83 while (id != sync_api::kInvalidId) {
84 sync_api::ReadNode sync_node(&trans);
85 if (!sync_node.InitByIdLookup(id)) {
86 LOG(ERROR) << "Failed to fetch sync node for id " << id;
87 return false;
88 }
89 const sync_pb::ExtensionSpecifics& server_data =
90 (*extension_specifics_getter)(sync_node);
91 ExtensionSyncData sync_data;
92 if (!SpecificsToSyncData(server_data, &sync_data)) {
93 LOG(ERROR) << "Invalid extensions specifics for id " << id;
94 return false;
95 }
96 (*extension_data_map)[sync_data.id] = sync_data;
97 id = sync_node.GetSuccessorId();
98 }
99 return true;
100 }
101
102 } // namespace
103
104 bool SlurpExtensionData(const ExtensionSyncTraits& traits,
105 const ExtensionServiceInterface& extension_service,
106 sync_api::UserShare* user_share,
107 ExtensionDataMap* extension_data_map) {
108 // Read server-side data first so client user settings take
109 // precedence.
110 if (!SlurpServerData(
111 traits.root_node_tag, traits.extension_specifics_getter,
112 user_share, extension_data_map)) {
113 return false;
114 }
115
116 SlurpClientData(
117 traits.is_valid_and_syncable, extension_service,
118 extension_data_map);
119 return true;
120 }
121
122 namespace {
123
124 // Updates the server data from the given extension data. Returns
125 // whether or not the update was successful.
126 bool UpdateServer(
127 const ExtensionSyncTraits& traits,
128 const ExtensionSyncData& data,
129 sync_api::WriteTransaction* trans) {
130 sync_pb::ExtensionSpecifics specifics;
131 SyncDataToSpecifics(data, &specifics);
132 const std::string& id = data.id;
133 sync_api::WriteNode write_node(trans);
134 if (write_node.InitByClientTagLookup(traits.model_type, id)) {
135 (*traits.extension_specifics_setter)(specifics, &write_node);
136 } else {
137 sync_api::ReadNode root(trans);
138 if (!root.InitByTagLookup(traits.root_node_tag)) {
139 LOG(ERROR) << GetRootNodeDoesNotExistError(traits.root_node_tag);
140 return false;
141 }
142 sync_api::WriteNode create_node(trans);
143 if (!create_node.InitUniqueByCreation(traits.model_type, root, id)) {
144 LOG(ERROR) << "Could not create node for extension " << id;
145 return false;
146 }
147 (*traits.extension_specifics_setter)(specifics, &create_node);
148 }
149 return true;
150 }
151
152 } // namespace
153
154 bool FlushExtensionData(const ExtensionSyncTraits& traits,
155 const ExtensionDataMap& extension_data_map,
156 ExtensionServiceInterface* extension_service,
157 sync_api::UserShare* user_share) {
158 sync_api::WriteTransaction trans(FROM_HERE, user_share);
159 sync_api::ReadNode root(&trans);
160 if (!root.InitByTagLookup(traits.root_node_tag)) {
161 LOG(ERROR) << GetRootNodeDoesNotExistError(traits.root_node_tag);
162 return false;
163 }
164
165 // Update server and client as necessary.
166 for (ExtensionDataMap::const_iterator it = extension_data_map.begin();
167 it != extension_data_map.end(); ++it) {
168 const ExtensionSyncData& extension_data = it->second;
169 if (!UpdateServer(traits, extension_data, &trans)) {
170 LOG(ERROR) << "Could not update server data for extension "
171 << it->first;
172 return false;
173 }
174 extension_service->ProcessSyncData(extension_data,
175 traits.is_valid_and_syncable);
176 }
177 return true;
178 }
179
180 bool UpdateServerData(const ExtensionSyncTraits& traits,
181 const Extension& extension,
182 const ExtensionServiceInterface& extension_service,
183 sync_api::UserShare* user_share,
184 std::string* error) {
185 const std::string& id = extension.id();
186 ExtensionSyncData data;
187 if (!extension_service.GetSyncData(
188 extension, traits.is_valid_and_syncable, &data)) {
189 *error =
190 std::string("UpdateServerData() called for invalid or "
191 "unsyncable extension ") + id;
192 LOG(DFATAL) << *error;
193 return false;
194 }
195
196 sync_api::WriteTransaction trans(FROM_HERE, user_share);
197 if (!UpdateServer(traits, data, &trans)) {
198 *error =
199 std::string("Could not update server data for extension ") + id;
200 LOG(ERROR) << *error;
201 return false;
202 }
203 return true;
204 }
205
206 void RemoveServerData(const ExtensionSyncTraits& traits,
207 const std::string& id,
208 sync_api::UserShare* user_share) {
209 sync_api::WriteTransaction trans(FROM_HERE, user_share);
210 sync_api::WriteNode write_node(&trans);
211 if (write_node.InitByClientTagLookup(traits.model_type, id)) {
212 write_node.Remove();
213 } else {
214 LOG(ERROR) << "Server data does not exist for extension " << id;
215 }
216 }
217
218 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698