OLD | NEW |
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" | 10 #include "chrome/browser/extensions/extension_updater.h" |
11 #include "chrome/browser/extensions/extension_service.h" | 11 #include "chrome/browser/extensions/extension_service.h" |
| 12 #include "chrome/browser/extensions/extension_sync_data.h" |
12 #include "chrome/browser/profiles/profile.h" | 13 #include "chrome/browser/profiles/profile.h" |
13 #include "chrome/browser/sync/engine/syncapi.h" | 14 #include "chrome/browser/sync/engine/syncapi.h" |
14 #include "chrome/browser/sync/glue/extension_data.h" | 15 #include "chrome/browser/sync/glue/extension_data.h" |
15 #include "chrome/browser/sync/glue/extension_sync_traits.h" | 16 #include "chrome/browser/sync/glue/extension_sync_traits.h" |
16 #include "chrome/browser/sync/glue/extension_util.h" | 17 #include "chrome/browser/sync/glue/extension_util.h" |
17 #include "chrome/browser/sync/profile_sync_service.h" | 18 #include "chrome/browser/sync/profile_sync_service.h" |
18 | 19 |
19 namespace browser_sync { | 20 namespace browser_sync { |
20 | 21 |
21 bool RootNodeHasChildren(const char* tag, | 22 bool RootNodeHasChildren(const char* tag, |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 } | 228 } |
228 bool old_client_needs_update = | 229 bool old_client_needs_update = |
229 extension_data->NeedsUpdate(ExtensionData::CLIENT); | 230 extension_data->NeedsUpdate(ExtensionData::CLIENT); |
230 extension_data->ResolveData(ExtensionData::SERVER); | 231 extension_data->ResolveData(ExtensionData::SERVER); |
231 DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER)); | 232 DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER)); |
232 DCHECK_EQ(extension_data->NeedsUpdate(ExtensionData::CLIENT), | 233 DCHECK_EQ(extension_data->NeedsUpdate(ExtensionData::CLIENT), |
233 old_client_needs_update); | 234 old_client_needs_update); |
234 return true; | 235 return true; |
235 } | 236 } |
236 | 237 |
237 // Tries to update the client data from the given extension data. | |
238 // extension_data->ServerNeedsUpdate() must not hold and | |
239 // extension_data->ClientNeedsUpdate() must hold before this function | |
240 // is called. If the update was successful, | |
241 // extension_data->ClientNeedsUpdate() will be false after this | |
242 // function is called. Otherwise, the extension needs updating to a | |
243 // new version. | |
244 void TryUpdateClient( | |
245 IsValidAndSyncablePredicate is_valid_and_syncable, | |
246 ExtensionServiceInterface* extensions_service, | |
247 ExtensionData* extension_data) { | |
248 DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER)); | |
249 DCHECK(extension_data->NeedsUpdate(ExtensionData::CLIENT)); | |
250 const sync_pb::ExtensionSpecifics& specifics = | |
251 extension_data->merged_data(); | |
252 DcheckIsExtensionSpecificsValid(specifics); | |
253 const std::string& id = specifics.id(); | |
254 const Extension* extension = extensions_service->GetExtensionById(id, true); | |
255 if (extension) { | |
256 if (!is_valid_and_syncable(*extension)) { | |
257 LOG(DFATAL) << "TryUpdateClient() called for non-syncable extension " | |
258 << id; | |
259 return; | |
260 } | |
261 if (specifics.name() != extension->name()) { | |
262 LOG(WARNING) << "specifics for extension " << id | |
263 << "has a different name than the extension: " | |
264 << specifics.name() << " vs. " << extension->name(); | |
265 } | |
266 GURL update_url(specifics.update_url()); | |
267 if (update_url != extension->update_url()) { | |
268 LOG(WARNING) << "specifics for extension " << id | |
269 << "has a different update URL than the extension: " | |
270 << update_url.spec() << " vs. " << extension->update_url(); | |
271 } | |
272 if (specifics.enabled()) { | |
273 extensions_service->EnableExtension(id); | |
274 } else { | |
275 extensions_service->DisableExtension(id); | |
276 } | |
277 extensions_service->SetIsIncognitoEnabled(id, | |
278 specifics.incognito_enabled()); | |
279 { | |
280 sync_pb::ExtensionSpecifics extension_specifics; | |
281 GetExtensionSpecifics(*extension, *extensions_service, | |
282 &extension_specifics); | |
283 DCHECK(AreExtensionSpecificsUserPropertiesEqual( | |
284 specifics, extension_specifics)) | |
285 << ExtensionSpecificsToString(specifics) << ", " | |
286 << ExtensionSpecificsToString(extension_specifics); | |
287 } | |
288 if (!IsExtensionOutdated(*extension, specifics)) { | |
289 extension_data->ResolveData(ExtensionData::CLIENT); | |
290 DCHECK(!extension_data->NeedsUpdate(ExtensionData::CLIENT)); | |
291 } | |
292 } else { | |
293 GURL update_url(specifics.update_url()); | |
294 // TODO(akalin): Replace silent update with a list of enabled | |
295 // permissions. | |
296 extensions_service->pending_extension_manager()->AddFromSync( | |
297 id, update_url, | |
298 is_valid_and_syncable, | |
299 true, // install_silently | |
300 specifics.enabled(), | |
301 specifics.incognito_enabled()); | |
302 } | |
303 DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER)); | |
304 } | |
305 | |
306 } // namespace | 238 } // namespace |
307 | 239 |
308 bool FlushExtensionData(const ExtensionSyncTraits& traits, | 240 bool FlushExtensionData(const ExtensionSyncTraits& traits, |
309 const ExtensionDataMap& extension_data_map, | 241 const ExtensionDataMap& extension_data_map, |
310 ExtensionServiceInterface* extensions_service, | 242 ExtensionServiceInterface* extensions_service, |
311 sync_api::UserShare* user_share) { | 243 sync_api::UserShare* user_share) { |
312 sync_api::WriteTransaction trans(user_share); | 244 sync_api::WriteTransaction trans(user_share); |
313 sync_api::ReadNode root(&trans); | 245 sync_api::ReadNode root(&trans); |
314 if (!root.InitByTagLookup(traits.root_node_tag)) { | 246 if (!root.InitByTagLookup(traits.root_node_tag)) { |
315 LOG(ERROR) << GetRootNodeDoesNotExistError(traits.root_node_tag); | 247 LOG(ERROR) << GetRootNodeDoesNotExistError(traits.root_node_tag); |
316 return false; | 248 return false; |
317 } | 249 } |
318 | 250 |
319 // Update server and client as necessary. | 251 // Update server and client as necessary. |
320 for (ExtensionDataMap::const_iterator it = extension_data_map.begin(); | 252 for (ExtensionDataMap::const_iterator it = extension_data_map.begin(); |
321 it != extension_data_map.end(); ++it) { | 253 it != extension_data_map.end(); ++it) { |
322 ExtensionData extension_data = it->second; | 254 ExtensionData extension_data = it->second; |
323 // Update server first. | 255 // Update server first. |
324 if (extension_data.NeedsUpdate(ExtensionData::SERVER)) { | 256 if (extension_data.NeedsUpdate(ExtensionData::SERVER)) { |
325 if (!UpdateServer(traits, &extension_data, &trans)) { | 257 if (!UpdateServer(traits, &extension_data, &trans)) { |
326 LOG(ERROR) << "Could not update server data for extension " | 258 LOG(ERROR) << "Could not update server data for extension " |
327 << it->first; | 259 << it->first; |
328 return false; | 260 return false; |
329 } | 261 } |
330 } | 262 } |
331 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER)); | 263 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER)); |
332 if (extension_data.NeedsUpdate(ExtensionData::CLIENT)) { | 264 ExtensionSyncData sync_data; |
333 TryUpdateClient(traits.is_valid_and_syncable, | 265 if (!GetExtensionSyncData(extension_data.merged_data(), &sync_data)) { |
334 extensions_service, &extension_data); | 266 // TODO(akalin): Should probably recover or drop. |
335 if (extension_data.NeedsUpdate(ExtensionData::CLIENT)) { | 267 NOTREACHED(); |
336 extensions_service->CheckForUpdatesSoon(); | 268 return false; |
337 } | |
338 } | 269 } |
339 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER)); | 270 extensions_service->ProcessSyncData(sync_data, |
| 271 traits.is_valid_and_syncable); |
340 } | 272 } |
341 return true; | 273 return true; |
342 } | 274 } |
343 | 275 |
344 bool UpdateServerData(const ExtensionSyncTraits& traits, | 276 bool UpdateServerData(const ExtensionSyncTraits& traits, |
345 const Extension& extension, | 277 const Extension& extension, |
346 const ExtensionServiceInterface& extensions_service, | 278 const ExtensionServiceInterface& extensions_service, |
347 sync_api::UserShare* user_share, | 279 sync_api::UserShare* user_share, |
348 std::string* error) { | 280 std::string* error) { |
349 const std::string& id = extension.id(); | 281 const std::string& id = extension.id(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 sync_api::UserShare* user_share) { | 335 sync_api::UserShare* user_share) { |
404 sync_api::WriteTransaction trans(user_share); | 336 sync_api::WriteTransaction trans(user_share); |
405 sync_api::WriteNode write_node(&trans); | 337 sync_api::WriteNode write_node(&trans); |
406 if (write_node.InitByClientTagLookup(traits.model_type, id)) { | 338 if (write_node.InitByClientTagLookup(traits.model_type, id)) { |
407 write_node.Remove(); | 339 write_node.Remove(); |
408 } else { | 340 } else { |
409 LOG(ERROR) << "Server data does not exist for extension " << id; | 341 LOG(ERROR) << "Server data does not exist for extension " << id; |
410 } | 342 } |
411 } | 343 } |
412 | 344 |
413 void UpdateClient(const ExtensionSyncTraits& traits, | |
414 const sync_pb::ExtensionSpecifics& server_data, | |
415 ExtensionServiceInterface* extensions_service) { | |
416 DcheckIsExtensionSpecificsValid(server_data); | |
417 ExtensionData extension_data = | |
418 ExtensionData::FromData(ExtensionData::SERVER, server_data); | |
419 const Extension* extension = | |
420 extensions_service->GetExtensionById(server_data.id(), true); | |
421 if (extension) { | |
422 if (!traits.is_valid_and_syncable(*extension)) { | |
423 LOG(WARNING) << "Ignoring server data for invalid or " | |
424 << "non-syncable extension " << extension->id(); | |
425 return; | |
426 } | |
427 sync_pb::ExtensionSpecifics client_data; | |
428 GetExtensionSpecifics(*extension, *extensions_service, | |
429 &client_data); | |
430 DcheckIsExtensionSpecificsValid(client_data); | |
431 extension_data = | |
432 ExtensionData::FromData(ExtensionData::CLIENT, client_data); | |
433 extension_data.SetData(ExtensionData::SERVER, true, server_data); | |
434 } | |
435 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER)); | |
436 if (extension_data.NeedsUpdate(ExtensionData::CLIENT)) { | |
437 TryUpdateClient(traits.is_valid_and_syncable, | |
438 extensions_service, &extension_data); | |
439 if (extension_data.NeedsUpdate(ExtensionData::CLIENT)) { | |
440 extensions_service->CheckForUpdatesSoon(); | |
441 } | |
442 } | |
443 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER)); | |
444 } | |
445 | |
446 void RemoveFromClient(const ExtensionSyncTraits& traits, | |
447 const std::string& id, | |
448 ExtensionServiceInterface* extensions_service) { | |
449 const Extension* extension = extensions_service->GetExtensionById(id, true); | |
450 if (extension) { | |
451 if (traits.is_valid_and_syncable(*extension)) { | |
452 extensions_service->UninstallExtension(id, false, NULL); | |
453 } else { | |
454 LOG(WARNING) << "Ignoring server data for invalid or " | |
455 << "non-syncable extension " << extension->id(); | |
456 } | |
457 } else { | |
458 LOG(ERROR) << "Trying to uninstall nonexistent extension " << id; | |
459 } | |
460 } | |
461 | |
462 } // namespace browser_sync | 345 } // namespace browser_sync |
OLD | NEW |