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

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

Issue 2884027: Added checks to handle unsyncable extensions. (Closed)
Patch Set: Fixed comment typo Created 10 years, 5 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
« no previous file with comments | « chrome/browser/sync/glue/extension_model_associator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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_model_associator.h" 5 #include "chrome/browser/sync/glue/extension_model_associator.h"
6 6
7 #include <map> 7 #include <map>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 DCHECK(!extension_data->NeedsUpdate(source)); 48 DCHECK(!extension_data->NeedsUpdate(source));
49 } else { 49 } else {
50 extension_data->SetData(source, merge_user_properties, data); 50 extension_data->SetData(source, merge_user_properties, data);
51 } 51 }
52 return extension_data; 52 return extension_data;
53 } 53 }
54 54
55 void GetSyncableExtensionsClientData( 55 void GetSyncableExtensionsClientData(
56 const ExtensionList& extensions, 56 const ExtensionList& extensions,
57 ExtensionsService* extensions_service, 57 ExtensionsService* extensions_service,
58 std::set<std::string>* unsyncable_extensions,
58 ExtensionDataMap* extension_data_map) { 59 ExtensionDataMap* extension_data_map) {
59 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 60 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
60 for (ExtensionList::const_iterator it = extensions.begin(); 61 for (ExtensionList::const_iterator it = extensions.begin();
61 it != extensions.end(); ++it) { 62 it != extensions.end(); ++it) {
62 CHECK(*it); 63 CHECK(*it);
63 const Extension& extension = **it; 64 const Extension& extension = **it;
64 if (IsExtensionSyncable(extension)) { 65 if (IsExtensionSyncable(extension)) {
65 sync_pb::ExtensionSpecifics client_specifics; 66 sync_pb::ExtensionSpecifics client_specifics;
66 GetExtensionSpecifics(extension, extensions_service, 67 GetExtensionSpecifics(extension, extensions_service,
67 &client_specifics); 68 &client_specifics);
68 DcheckIsExtensionSpecificsValid(client_specifics); 69 DcheckIsExtensionSpecificsValid(client_specifics);
69 const ExtensionData& extension_data = 70 const ExtensionData& extension_data =
70 *SetOrCreateData(extension_data_map, 71 *SetOrCreateData(extension_data_map,
71 ExtensionData::CLIENT, true, client_specifics); 72 ExtensionData::CLIENT, true, client_specifics);
72 DcheckIsExtensionSpecificsValid(extension_data.merged_data()); 73 DcheckIsExtensionSpecificsValid(extension_data.merged_data());
73 // Assumes this is called before any server data is read. 74 // Assumes this is called before any server data is read.
74 DCHECK(extension_data.NeedsUpdate(ExtensionData::SERVER)); 75 DCHECK(extension_data.NeedsUpdate(ExtensionData::SERVER));
75 DCHECK(!extension_data.NeedsUpdate(ExtensionData::CLIENT)); 76 DCHECK(!extension_data.NeedsUpdate(ExtensionData::CLIENT));
77 } else {
78 unsyncable_extensions->insert(extension.id());
76 } 79 }
77 } 80 }
78 } 81 }
79 82
80 } // namespace 83 } // namespace
81 84
82 ExtensionModelAssociator::ExtensionModelAssociator( 85 ExtensionModelAssociator::ExtensionModelAssociator(
83 ProfileSyncService* sync_service) : sync_service_(sync_service) { 86 ProfileSyncService* sync_service) : sync_service_(sync_service) {
84 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 87 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
85 DCHECK(sync_service_); 88 DCHECK(sync_service_);
86 } 89 }
87 90
88 ExtensionModelAssociator::~ExtensionModelAssociator() { 91 ExtensionModelAssociator::~ExtensionModelAssociator() {
89 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 92 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
90 } 93 }
91 94
92 bool ExtensionModelAssociator::AssociateModels() { 95 bool ExtensionModelAssociator::AssociateModels() {
93 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 96 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
94 sync_api::WriteTransaction trans( 97 sync_api::WriteTransaction trans(
95 sync_service_->backend()->GetUserShareHandle()); 98 sync_service_->backend()->GetUserShareHandle());
96 sync_api::ReadNode root(&trans); 99 sync_api::ReadNode root(&trans);
97 if (!root.InitByTagLookup(kExtensionsTag)) { 100 if (!root.InitByTagLookup(kExtensionsTag)) {
98 LOG(ERROR) << kNoExtensionsFolderError; 101 LOG(ERROR) << kNoExtensionsFolderError;
99 return false; 102 return false;
100 } 103 }
101 104
105 std::set<std::string> unsyncable_extensions;
102 ExtensionDataMap extension_data_map; 106 ExtensionDataMap extension_data_map;
103 107
104 // Read client-side data. Do this first so server data takes 108 // Read client-side data. Do this first so server data takes
105 // precedence. 109 // precedence.
106 { 110 {
107 ExtensionsService* extensions_service = GetExtensionsService(); 111 ExtensionsService* extensions_service = GetExtensionsService();
108 112
109 const ExtensionList* extensions = extensions_service->extensions(); 113 const ExtensionList* extensions = extensions_service->extensions();
110 CHECK(extensions); 114 CHECK(extensions);
111 GetSyncableExtensionsClientData( 115 GetSyncableExtensionsClientData(
112 *extensions, extensions_service, &extension_data_map); 116 *extensions, extensions_service,
117 &unsyncable_extensions, &extension_data_map);
113 118
114 const ExtensionList* disabled_extensions = 119 const ExtensionList* disabled_extensions =
115 extensions_service->disabled_extensions(); 120 extensions_service->disabled_extensions();
116 CHECK(disabled_extensions); 121 CHECK(disabled_extensions);
117 GetSyncableExtensionsClientData( 122 GetSyncableExtensionsClientData(
118 *disabled_extensions, extensions_service, &extension_data_map); 123 *disabled_extensions, extensions_service,
124 &unsyncable_extensions, &extension_data_map);
119 } 125 }
120 126
121 // Read server-side data. 127 // Read server-side data.
122 { 128 {
123 int64 id = root.GetFirstChildId(); 129 int64 id = root.GetFirstChildId();
124 while (id != sync_api::kInvalidId) { 130 while (id != sync_api::kInvalidId) {
125 sync_api::ReadNode sync_node(&trans); 131 sync_api::ReadNode sync_node(&trans);
126 if (!sync_node.InitByIdLookup(id)) { 132 if (!sync_node.InitByIdLookup(id)) {
127 LOG(ERROR) << "Failed to fetch sync node for id " << id; 133 LOG(ERROR) << "Failed to fetch sync node for id " << id;
128 return false; 134 return false;
129 } 135 }
130 const sync_pb::ExtensionSpecifics& server_data = 136 const sync_pb::ExtensionSpecifics& server_data =
131 sync_node.GetExtensionSpecifics(); 137 sync_node.GetExtensionSpecifics();
132 if (!IsExtensionSpecificsValid(server_data)) { 138 if (!IsExtensionSpecificsValid(server_data)) {
133 LOG(ERROR) << "Invalid extensions specifics for id " << id; 139 LOG(ERROR) << "Invalid extensions specifics for id " << id;
134 return false; 140 return false;
135 } 141 }
136 // Pass in false for merge_user_properties so client user 142 // Don't process server data for extensions we know are
137 // settings always take precedence. 143 // unsyncable. This doesn't catch everything, as if we don't
138 const ExtensionData& extension_data = 144 // have the extension already installed we can't check, but we
139 *SetOrCreateData(&extension_data_map, 145 // also check at extension install time.
140 ExtensionData::SERVER, false, server_data); 146 if (unsyncable_extensions.find(server_data.id()) ==
141 DcheckIsExtensionSpecificsValid(extension_data.merged_data()); 147 unsyncable_extensions.end()) {
148 // Pass in false for merge_user_properties so client user
149 // settings always take precedence.
150 const ExtensionData& extension_data =
151 *SetOrCreateData(&extension_data_map,
152 ExtensionData::SERVER, false, server_data);
153 DcheckIsExtensionSpecificsValid(extension_data.merged_data());
154 }
142 id = sync_node.GetSuccessorId(); 155 id = sync_node.GetSuccessorId();
143 } 156 }
144 } 157 }
145 158
146 // Update server and client as necessary. 159 // Update server and client as necessary.
147 bool should_nudge_extension_updater = false; 160 bool should_nudge_extension_updater = false;
148 for (ExtensionDataMap::iterator it = extension_data_map.begin(); 161 for (ExtensionDataMap::iterator it = extension_data_map.begin();
149 it != extension_data_map.end(); ++it) { 162 it != extension_data_map.end(); ++it) {
150 ExtensionData* extension_data = &it->second; 163 ExtensionData* extension_data = &it->second;
151 // Update server first. 164 // Update server first.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 } 210 }
198 211
199 bool ExtensionModelAssociator::OnClientUpdate(const std::string& id) { 212 bool ExtensionModelAssociator::OnClientUpdate(const std::string& id) {
200 sync_api::WriteTransaction trans( 213 sync_api::WriteTransaction trans(
201 sync_service_->backend()->GetUserShareHandle()); 214 sync_service_->backend()->GetUserShareHandle());
202 sync_api::ReadNode root(&trans); 215 sync_api::ReadNode root(&trans);
203 if (!root.InitByTagLookup(kExtensionsTag)) { 216 if (!root.InitByTagLookup(kExtensionsTag)) {
204 LOG(ERROR) << kNoExtensionsFolderError; 217 LOG(ERROR) << kNoExtensionsFolderError;
205 return false; 218 return false;
206 } 219 }
207 220 ExtensionsService* extensions_service = GetExtensionsService();
208 sync_pb::ExtensionSpecifics client_data; 221 Extension* extension = extensions_service->GetExtensionById(id, true);
209 if (GetExtensionDataFromClient(id, &client_data)) { 222 if (extension) {
223 if (!IsExtensionSyncable(*extension)) {
224 LOG(DFATAL) << "OnClientUpdate() called for non-syncable extension "
225 << id;
226 return false;
227 }
228 sync_pb::ExtensionSpecifics client_data;
229 GetExtensionSpecifics(*extension, extensions_service, &client_data);
230 DcheckIsExtensionSpecificsValid(client_data);
210 ExtensionData extension_data = 231 ExtensionData extension_data =
211 ExtensionData::FromData(ExtensionData::CLIENT, client_data); 232 ExtensionData::FromData(ExtensionData::CLIENT, client_data);
212 sync_pb::ExtensionSpecifics server_data; 233 sync_pb::ExtensionSpecifics server_data;
213 if (GetExtensionDataFromServer(id, &trans, root, &server_data)) { 234 if (GetExtensionDataFromServer(id, &trans, root, &server_data)) {
214 extension_data = 235 extension_data =
215 ExtensionData::FromData(ExtensionData::SERVER, server_data); 236 ExtensionData::FromData(ExtensionData::SERVER, server_data);
216 extension_data.SetData(ExtensionData::CLIENT, true, client_data); 237 extension_data.SetData(ExtensionData::CLIENT, true, client_data);
217 } 238 }
218 if (extension_data.NeedsUpdate(ExtensionData::SERVER)) { 239 if (extension_data.NeedsUpdate(ExtensionData::SERVER)) {
219 if (!UpdateServer(&extension_data, &trans, root)) { 240 if (!UpdateServer(&extension_data, &trans, root)) {
(...skipping 14 matching lines...) Expand all
234 write_node.Remove(); 255 write_node.Remove();
235 } else { 256 } else {
236 LOG(ERROR) << "Trying to remove server data for " 257 LOG(ERROR) << "Trying to remove server data for "
237 << "nonexistent extension " << id; 258 << "nonexistent extension " << id;
238 } 259 }
239 } 260 }
240 return true; 261 return true;
241 } 262 }
242 263
243 void ExtensionModelAssociator::OnServerUpdate( 264 void ExtensionModelAssociator::OnServerUpdate(
244 const sync_pb::ExtensionSpecifics& server_data) { 265 const sync_pb::ExtensionSpecifics& server_data,
266 Extension* extension) {
245 DcheckIsExtensionSpecificsValid(server_data); 267 DcheckIsExtensionSpecificsValid(server_data);
246 ExtensionData extension_data = 268 ExtensionData extension_data =
247 ExtensionData::FromData(ExtensionData::SERVER, server_data); 269 ExtensionData::FromData(ExtensionData::SERVER, server_data);
248 sync_pb::ExtensionSpecifics client_data; 270 if (extension) {
249 if (GetExtensionDataFromClient(server_data.id(), &client_data)) { 271 if (!IsExtensionSyncable(*extension)) {
250 ExtensionData extension_data = 272 LOG(DFATAL) << "OnServerUpdate() called for non-syncable extension "
273 << extension->id();
274 return;
275 }
276 sync_pb::ExtensionSpecifics client_data;
277 GetExtensionSpecifics(*extension, GetExtensionsService(), &client_data);
278 DcheckIsExtensionSpecificsValid(client_data);
279 extension_data =
251 ExtensionData::FromData(ExtensionData::CLIENT, client_data); 280 ExtensionData::FromData(ExtensionData::CLIENT, client_data);
252 extension_data.SetData(ExtensionData::SERVER, true, server_data); 281 extension_data.SetData(ExtensionData::SERVER, true, server_data);
253 } 282 }
254 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER)); 283 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER));
255 if (extension_data.NeedsUpdate(ExtensionData::CLIENT)) { 284 if (extension_data.NeedsUpdate(ExtensionData::CLIENT)) {
256 TryUpdateClient(&extension_data); 285 TryUpdateClient(&extension_data);
257 if (extension_data.NeedsUpdate(ExtensionData::CLIENT)) { 286 if (extension_data.NeedsUpdate(ExtensionData::CLIENT)) {
258 NudgeExtensionUpdater(); 287 NudgeExtensionUpdater();
259 } 288 }
260 } 289 }
261 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER)); 290 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER));
262 } 291 }
263 292
264 void ExtensionModelAssociator::OnServerRemove(const std::string& id) {
265 ExtensionsService* extensions_service = GetExtensionsService();
266 Extension* extension = extensions_service->GetExtensionById(id, true);
267 if (extension) {
268 extensions_service->UninstallExtension(id, false);
269 } else {
270 LOG(ERROR) << "Trying to uninstall nonexistent extension " << id;
271 }
272 }
273
274 ExtensionsService* ExtensionModelAssociator::GetExtensionsService() { 293 ExtensionsService* ExtensionModelAssociator::GetExtensionsService() {
275 CHECK(sync_service_); 294 CHECK(sync_service_);
276 Profile* profile = sync_service_->profile(); 295 Profile* profile = sync_service_->profile();
277 CHECK(profile); 296 CHECK(profile);
278 ExtensionsService* extensions_service = profile->GetExtensionsService(); 297 ExtensionsService* extensions_service = profile->GetExtensionsService();
279 CHECK(extensions_service); 298 CHECK(extensions_service);
280 return extensions_service; 299 return extensions_service;
281 } 300 }
282 301
283 bool ExtensionModelAssociator::GetExtensionDataFromClient(
284 const std::string& id, sync_pb::ExtensionSpecifics* client_data) {
285 ExtensionsService* extensions_service = GetExtensionsService();
286 Extension* extension = extensions_service->GetExtensionById(id, true);
287 if (!extension) {
288 return false;
289 }
290 GetExtensionSpecifics(*extension, extensions_service, client_data);
291 DcheckIsExtensionSpecificsValid(*client_data);
292 return true;
293 }
294
295 bool ExtensionModelAssociator::GetExtensionDataFromServer( 302 bool ExtensionModelAssociator::GetExtensionDataFromServer(
296 const std::string& id, sync_api::WriteTransaction* trans, 303 const std::string& id, sync_api::WriteTransaction* trans,
297 const sync_api::ReadNode& root, 304 const sync_api::ReadNode& root,
298 sync_pb::ExtensionSpecifics* server_data) { 305 sync_pb::ExtensionSpecifics* server_data) {
299 sync_api::ReadNode sync_node(trans); 306 sync_api::ReadNode sync_node(trans);
300 if (!sync_node.InitByClientTagLookup(syncable::EXTENSIONS, id)) { 307 if (!sync_node.InitByClientTagLookup(syncable::EXTENSIONS, id)) {
301 LOG(ERROR) << "Failed to fetch sync node for id " << id; 308 LOG(ERROR) << "Failed to fetch sync node for id " << id;
302 return false; 309 return false;
303 } 310 }
304 const sync_pb::ExtensionSpecifics& read_server_data = 311 const sync_pb::ExtensionSpecifics& read_server_data =
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 ExtensionData* extension_data) { 360 ExtensionData* extension_data) {
354 DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER)); 361 DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER));
355 DCHECK(extension_data->NeedsUpdate(ExtensionData::CLIENT)); 362 DCHECK(extension_data->NeedsUpdate(ExtensionData::CLIENT));
356 const sync_pb::ExtensionSpecifics& specifics = 363 const sync_pb::ExtensionSpecifics& specifics =
357 extension_data->merged_data(); 364 extension_data->merged_data();
358 DcheckIsExtensionSpecificsValid(specifics); 365 DcheckIsExtensionSpecificsValid(specifics);
359 ExtensionsService* extensions_service = GetExtensionsService(); 366 ExtensionsService* extensions_service = GetExtensionsService();
360 const std::string& id = specifics.id(); 367 const std::string& id = specifics.id();
361 Extension* extension = extensions_service->GetExtensionById(id, true); 368 Extension* extension = extensions_service->GetExtensionById(id, true);
362 if (extension) { 369 if (extension) {
370 if (!IsExtensionSyncable(*extension)) {
371 LOG(DFATAL) << "TryUpdateClient() called for non-syncable extension "
372 << extension->id();
373 return;
374 }
363 SetExtensionProperties(specifics, extensions_service, extension); 375 SetExtensionProperties(specifics, extensions_service, extension);
364 { 376 {
365 sync_pb::ExtensionSpecifics extension_specifics; 377 sync_pb::ExtensionSpecifics extension_specifics;
366 GetExtensionSpecifics(*extension, extensions_service, 378 GetExtensionSpecifics(*extension, extensions_service,
367 &extension_specifics); 379 &extension_specifics);
368 DCHECK(AreExtensionSpecificsUserPropertiesEqual( 380 DCHECK(AreExtensionSpecificsUserPropertiesEqual(
369 specifics, extension_specifics)) 381 specifics, extension_specifics))
370 << ExtensionSpecificsToString(specifics) << ", " 382 << ExtensionSpecificsToString(specifics) << ", "
371 << ExtensionSpecificsToString(extension_specifics); 383 << ExtensionSpecificsToString(extension_specifics);
372 } 384 }
(...skipping 18 matching lines...) Expand all
391 // ExtensionsService in ProfileImpl::InitExtensions()). 403 // ExtensionsService in ProfileImpl::InitExtensions()).
392 if (extension_updater) { 404 if (extension_updater) {
393 extension_updater->CheckNow(); 405 extension_updater->CheckNow();
394 } else { 406 } else {
395 LOG(DFATAL) << "Extension updater unexpectedly NULL; " 407 LOG(DFATAL) << "Extension updater unexpectedly NULL; "
396 << "auto-updates may be turned off"; 408 << "auto-updates may be turned off";
397 } 409 }
398 } 410 }
399 411
400 } // namespace browser_sync 412 } // namespace browser_sync
OLDNEW
« no previous file with comments | « chrome/browser/sync/glue/extension_model_associator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698