OLD | NEW |
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_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/extensions_service.h" | 11 #include "chrome/browser/extensions/extension_service.h" |
12 #include "chrome/browser/profiles/profile.h" | 12 #include "chrome/browser/profiles/profile.h" |
13 #include "chrome/browser/sync/engine/syncapi.h" | 13 #include "chrome/browser/sync/engine/syncapi.h" |
14 #include "chrome/browser/sync/glue/extension_data.h" | 14 #include "chrome/browser/sync/glue/extension_data.h" |
15 #include "chrome/browser/sync/glue/extension_sync_traits.h" | 15 #include "chrome/browser/sync/glue/extension_sync_traits.h" |
16 #include "chrome/browser/sync/profile_sync_service.h" | 16 #include "chrome/browser/sync/profile_sync_service.h" |
17 | 17 |
18 namespace browser_sync { | 18 namespace browser_sync { |
19 | 19 |
20 bool RootNodeHasChildren(const char* tag, | 20 bool RootNodeHasChildren(const char* tag, |
21 ProfileSyncService* sync_service, | 21 ProfileSyncService* sync_service, |
22 bool* has_children) { | 22 bool* has_children) { |
23 CHECK(has_children); | 23 CHECK(has_children); |
24 *has_children = false; | 24 *has_children = false; |
25 sync_api::ReadTransaction trans( | 25 sync_api::ReadTransaction trans( |
26 sync_service->backend()->GetUserShareHandle()); | 26 sync_service->backend()->GetUserShareHandle()); |
27 sync_api::ReadNode node(&trans); | 27 sync_api::ReadNode node(&trans); |
28 if (!node.InitByTagLookup(tag)) { | 28 if (!node.InitByTagLookup(tag)) { |
29 LOG(ERROR) << "Root node with tag " << tag << " does not exist"; | 29 LOG(ERROR) << "Root node with tag " << tag << " does not exist"; |
30 return false; | 30 return false; |
31 } | 31 } |
32 *has_children = node.GetFirstChildId() != sync_api::kInvalidId; | 32 *has_children = node.GetFirstChildId() != sync_api::kInvalidId; |
33 return true; | 33 return true; |
34 } | 34 } |
35 | 35 |
36 ExtensionsService* GetExtensionsServiceFromProfile( | 36 ExtensionService* GetExtensionServiceFromProfile( |
37 Profile* profile) { | 37 Profile* profile) { |
38 CHECK(profile); | 38 CHECK(profile); |
39 ExtensionsService* extensions_service = profile->GetExtensionsService(); | 39 ExtensionService* extensions_service = profile->GetExtensionService(); |
40 CHECK(extensions_service); | 40 CHECK(extensions_service); |
41 return extensions_service; | 41 return extensions_service; |
42 } | 42 } |
43 | 43 |
44 namespace { | 44 namespace { |
45 | 45 |
46 ExtensionsService* GetExtensionsServiceFromProfileSyncService( | 46 ExtensionService* GetExtensionServiceFromProfileSyncService( |
47 ProfileSyncService* sync_service) { | 47 ProfileSyncService* sync_service) { |
48 CHECK(sync_service); | 48 CHECK(sync_service); |
49 return GetExtensionsServiceFromProfile(sync_service->profile()); | 49 return GetExtensionServiceFromProfile(sync_service->profile()); |
50 } | 50 } |
51 | 51 |
52 // Updates the value in |extension_data_map| from the given data, | 52 // Updates the value in |extension_data_map| from the given data, |
53 // creating an entry if necessary. Returns a pointer to the | 53 // creating an entry if necessary. Returns a pointer to the |
54 // updated/created ExtensionData object. | 54 // updated/created ExtensionData object. |
55 ExtensionData* SetOrCreateExtensionData( | 55 ExtensionData* SetOrCreateExtensionData( |
56 ExtensionDataMap* extension_data_map, | 56 ExtensionDataMap* extension_data_map, |
57 ExtensionData::Source source, | 57 ExtensionData::Source source, |
58 bool merge_user_properties, | 58 bool merge_user_properties, |
59 const sync_pb::ExtensionSpecifics& data) { | 59 const sync_pb::ExtensionSpecifics& data) { |
(...skipping 13 matching lines...) Expand all Loading... |
73 } | 73 } |
74 return extension_data; | 74 return extension_data; |
75 } | 75 } |
76 | 76 |
77 // Reads the client data for each extension in |extensions| to be | 77 // Reads the client data for each extension in |extensions| to be |
78 // synced and updates |extension_data_map|. Puts all unsynced | 78 // synced and updates |extension_data_map|. Puts all unsynced |
79 // extensions in |unsynced_extensions|. | 79 // extensions in |unsynced_extensions|. |
80 void ReadClientDataFromExtensionList( | 80 void ReadClientDataFromExtensionList( |
81 const ExtensionList& extensions, | 81 const ExtensionList& extensions, |
82 const ExtensionTypeSet& allowed_extension_types, | 82 const ExtensionTypeSet& allowed_extension_types, |
83 ExtensionsService* extensions_service, | 83 ExtensionService* extensions_service, |
84 std::set<std::string>* unsynced_extensions, | 84 std::set<std::string>* unsynced_extensions, |
85 ExtensionDataMap* extension_data_map) { | 85 ExtensionDataMap* extension_data_map) { |
86 for (ExtensionList::const_iterator it = extensions.begin(); | 86 for (ExtensionList::const_iterator it = extensions.begin(); |
87 it != extensions.end(); ++it) { | 87 it != extensions.end(); ++it) { |
88 CHECK(*it); | 88 CHECK(*it); |
89 const Extension& extension = **it; | 89 const Extension& extension = **it; |
90 if (IsExtensionValidAndSyncable(extension, allowed_extension_types)) { | 90 if (IsExtensionValidAndSyncable(extension, allowed_extension_types)) { |
91 sync_pb::ExtensionSpecifics client_specifics; | 91 sync_pb::ExtensionSpecifics client_specifics; |
92 GetExtensionSpecifics(extension, extensions_service->extension_prefs(), | 92 GetExtensionSpecifics(extension, extensions_service->extension_prefs(), |
93 &client_specifics); | 93 &client_specifics); |
94 DcheckIsExtensionSpecificsValid(client_specifics); | 94 DcheckIsExtensionSpecificsValid(client_specifics); |
95 const ExtensionData& extension_data = | 95 const ExtensionData& extension_data = |
96 *SetOrCreateExtensionData( | 96 *SetOrCreateExtensionData( |
97 extension_data_map, ExtensionData::CLIENT, | 97 extension_data_map, ExtensionData::CLIENT, |
98 true, client_specifics); | 98 true, client_specifics); |
99 DcheckIsExtensionSpecificsValid(extension_data.merged_data()); | 99 DcheckIsExtensionSpecificsValid(extension_data.merged_data()); |
100 // Assumes this is called before any server data is read. | 100 // Assumes this is called before any server data is read. |
101 DCHECK(extension_data.NeedsUpdate(ExtensionData::SERVER)); | 101 DCHECK(extension_data.NeedsUpdate(ExtensionData::SERVER)); |
102 DCHECK(!extension_data.NeedsUpdate(ExtensionData::CLIENT)); | 102 DCHECK(!extension_data.NeedsUpdate(ExtensionData::CLIENT)); |
103 } else { | 103 } else { |
104 unsynced_extensions->insert(extension.id()); | 104 unsynced_extensions->insert(extension.id()); |
105 } | 105 } |
106 } | 106 } |
107 } | 107 } |
108 | 108 |
109 // Simply calls ReadClientDataFromExtensionList() on the list of | 109 // Simply calls ReadClientDataFromExtensionList() on the list of |
110 // enabled and disabled extensions from |extensions_service|. | 110 // enabled and disabled extensions from |extensions_service|. |
111 void SlurpClientData( | 111 void SlurpClientData( |
112 const ExtensionTypeSet& allowed_extension_types, | 112 const ExtensionTypeSet& allowed_extension_types, |
113 ExtensionsService* extensions_service, | 113 ExtensionService* extensions_service, |
114 std::set<std::string>* unsynced_extensions, | 114 std::set<std::string>* unsynced_extensions, |
115 ExtensionDataMap* extension_data_map) { | 115 ExtensionDataMap* extension_data_map) { |
116 const ExtensionList* extensions = extensions_service->extensions(); | 116 const ExtensionList* extensions = extensions_service->extensions(); |
117 CHECK(extensions); | 117 CHECK(extensions); |
118 ReadClientDataFromExtensionList( | 118 ReadClientDataFromExtensionList( |
119 *extensions, allowed_extension_types, extensions_service, | 119 *extensions, allowed_extension_types, extensions_service, |
120 unsynced_extensions, extension_data_map); | 120 unsynced_extensions, extension_data_map); |
121 | 121 |
122 const ExtensionList* disabled_extensions = | 122 const ExtensionList* disabled_extensions = |
123 extensions_service->disabled_extensions(); | 123 extensions_service->disabled_extensions(); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 id = sync_node.GetSuccessorId(); | 184 id = sync_node.GetSuccessorId(); |
185 } | 185 } |
186 return true; | 186 return true; |
187 } | 187 } |
188 | 188 |
189 } // namespace | 189 } // namespace |
190 | 190 |
191 bool SlurpExtensionData(const ExtensionSyncTraits& traits, | 191 bool SlurpExtensionData(const ExtensionSyncTraits& traits, |
192 ProfileSyncService* sync_service, | 192 ProfileSyncService* sync_service, |
193 ExtensionDataMap* extension_data_map) { | 193 ExtensionDataMap* extension_data_map) { |
194 ExtensionsService* extensions_service = | 194 ExtensionService* extensions_service = |
195 GetExtensionsServiceFromProfileSyncService(sync_service); | 195 GetExtensionServiceFromProfileSyncService(sync_service); |
196 std::set<std::string> unsynced_extensions; | 196 std::set<std::string> unsynced_extensions; |
197 | 197 |
198 // Read client-side data first so server data takes precedence, and | 198 // Read client-side data first so server data takes precedence, and |
199 // also so we have an idea of which extensions are unsyncable. | 199 // also so we have an idea of which extensions are unsyncable. |
200 SlurpClientData( | 200 SlurpClientData( |
201 traits.allowed_extension_types, extensions_service, | 201 traits.allowed_extension_types, extensions_service, |
202 &unsynced_extensions, extension_data_map); | 202 &unsynced_extensions, extension_data_map); |
203 | 203 |
204 if (!SlurpServerData( | 204 if (!SlurpServerData( |
205 traits.root_node_tag, traits.extension_specifics_getter, | 205 traits.root_node_tag, traits.extension_specifics_getter, |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 // Tries to update the client data from the given extension data. | 253 // Tries to update the client data from the given extension data. |
254 // extension_data->ServerNeedsUpdate() must not hold and | 254 // extension_data->ServerNeedsUpdate() must not hold and |
255 // extension_data->ClientNeedsUpdate() must hold before this function | 255 // extension_data->ClientNeedsUpdate() must hold before this function |
256 // is called. If the update was successful, | 256 // is called. If the update was successful, |
257 // extension_data->ClientNeedsUpdate() will be false after this | 257 // extension_data->ClientNeedsUpdate() will be false after this |
258 // function is called. Otherwise, the extension needs updating to a | 258 // function is called. Otherwise, the extension needs updating to a |
259 // new version. | 259 // new version. |
260 void TryUpdateClient( | 260 void TryUpdateClient( |
261 const ExtensionTypeSet& allowed_extension_types, | 261 const ExtensionTypeSet& allowed_extension_types, |
262 PendingExtensionInfo::ExpectedCrxType expected_crx_type, | 262 PendingExtensionInfo::ExpectedCrxType expected_crx_type, |
263 ExtensionsService* extensions_service, | 263 ExtensionService* extensions_service, |
264 ExtensionData* extension_data) { | 264 ExtensionData* extension_data) { |
265 DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER)); | 265 DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER)); |
266 DCHECK(extension_data->NeedsUpdate(ExtensionData::CLIENT)); | 266 DCHECK(extension_data->NeedsUpdate(ExtensionData::CLIENT)); |
267 const sync_pb::ExtensionSpecifics& specifics = | 267 const sync_pb::ExtensionSpecifics& specifics = |
268 extension_data->merged_data(); | 268 extension_data->merged_data(); |
269 DcheckIsExtensionSpecificsValid(specifics); | 269 DcheckIsExtensionSpecificsValid(specifics); |
270 const std::string& id = specifics.id(); | 270 const std::string& id = specifics.id(); |
271 const Extension* extension = extensions_service->GetExtensionById(id, true); | 271 const Extension* extension = extensions_service->GetExtensionById(id, true); |
272 if (extension) { | 272 if (extension) { |
273 if (!IsExtensionValidAndSyncable(*extension, allowed_extension_types)) { | 273 if (!IsExtensionValidAndSyncable(*extension, allowed_extension_types)) { |
(...skipping 26 matching lines...) Expand all Loading... |
300 specifics.enabled(), | 300 specifics.enabled(), |
301 specifics.incognito_enabled()); | 301 specifics.incognito_enabled()); |
302 } | 302 } |
303 DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER)); | 303 DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER)); |
304 } | 304 } |
305 | 305 |
306 // Kick off a run of the extension updater. | 306 // Kick off a run of the extension updater. |
307 // | 307 // |
308 // TODO(akalin): Combine this with the similar function in | 308 // TODO(akalin): Combine this with the similar function in |
309 // theme_util.cc. | 309 // theme_util.cc. |
310 void NudgeExtensionUpdater(ExtensionsService* extensions_service) { | 310 void NudgeExtensionUpdater(ExtensionService* extensions_service) { |
311 ExtensionUpdater* extension_updater = extensions_service->updater(); | 311 ExtensionUpdater* extension_updater = extensions_service->updater(); |
312 // Auto-updates should now be on always (see the construction of the | 312 // Auto-updates should now be on always (see the construction of the |
313 // ExtensionsService in ProfileImpl::InitExtensions()). | 313 // ExtensionService in ProfileImpl::InitExtensions()). |
314 if (extension_updater) { | 314 if (extension_updater) { |
315 extension_updater->CheckNow(); | 315 extension_updater->CheckNow(); |
316 } else { | 316 } else { |
317 LOG(DFATAL) << "Extension updater unexpectedly NULL; " | 317 LOG(DFATAL) << "Extension updater unexpectedly NULL; " |
318 << "auto-updates may be turned off"; | 318 << "auto-updates may be turned off"; |
319 } | 319 } |
320 } | 320 } |
321 | 321 |
322 } // namespace | 322 } // namespace |
323 | 323 |
324 bool FlushExtensionData(const ExtensionSyncTraits& traits, | 324 bool FlushExtensionData(const ExtensionSyncTraits& traits, |
325 const ExtensionDataMap& extension_data_map, | 325 const ExtensionDataMap& extension_data_map, |
326 ProfileSyncService* sync_service) { | 326 ProfileSyncService* sync_service) { |
327 sync_api::WriteTransaction trans( | 327 sync_api::WriteTransaction trans( |
328 sync_service->backend()->GetUserShareHandle()); | 328 sync_service->backend()->GetUserShareHandle()); |
329 sync_api::ReadNode root(&trans); | 329 sync_api::ReadNode root(&trans); |
330 if (!root.InitByTagLookup(traits.root_node_tag)) { | 330 if (!root.InitByTagLookup(traits.root_node_tag)) { |
331 LOG(ERROR) << GetRootNodeDoesNotExistError(traits.root_node_tag); | 331 LOG(ERROR) << GetRootNodeDoesNotExistError(traits.root_node_tag); |
332 return false; | 332 return false; |
333 } | 333 } |
334 | 334 |
335 ExtensionsService* extensions_service = | 335 ExtensionService* extensions_service = |
336 GetExtensionsServiceFromProfileSyncService(sync_service); | 336 GetExtensionServiceFromProfileSyncService(sync_service); |
337 | 337 |
338 // Update server and client as necessary. | 338 // Update server and client as necessary. |
339 bool should_nudge_extension_updater = false; | 339 bool should_nudge_extension_updater = false; |
340 for (ExtensionDataMap::const_iterator it = extension_data_map.begin(); | 340 for (ExtensionDataMap::const_iterator it = extension_data_map.begin(); |
341 it != extension_data_map.end(); ++it) { | 341 it != extension_data_map.end(); ++it) { |
342 ExtensionData extension_data = it->second; | 342 ExtensionData extension_data = it->second; |
343 // Update server first. | 343 // Update server first. |
344 if (extension_data.NeedsUpdate(ExtensionData::SERVER)) { | 344 if (extension_data.NeedsUpdate(ExtensionData::SERVER)) { |
345 if (!UpdateServer(traits, &extension_data, &trans)) { | 345 if (!UpdateServer(traits, &extension_data, &trans)) { |
346 LOG(ERROR) << "Could not update server data for extension " | 346 LOG(ERROR) << "Could not update server data for extension " |
(...skipping 27 matching lines...) Expand all Loading... |
374 const std::string& id = extension.id(); | 374 const std::string& id = extension.id(); |
375 if (!IsExtensionValidAndSyncable(extension, | 375 if (!IsExtensionValidAndSyncable(extension, |
376 traits.allowed_extension_types)) { | 376 traits.allowed_extension_types)) { |
377 *error = | 377 *error = |
378 std::string("UpdateServerData() called for invalid or " | 378 std::string("UpdateServerData() called for invalid or " |
379 "unsyncable extension ") + id; | 379 "unsyncable extension ") + id; |
380 LOG(DFATAL) << *error; | 380 LOG(DFATAL) << *error; |
381 return false; | 381 return false; |
382 } | 382 } |
383 | 383 |
384 ExtensionsService* extensions_service = | 384 ExtensionService* extensions_service = |
385 GetExtensionsServiceFromProfileSyncService(sync_service); | 385 GetExtensionServiceFromProfileSyncService(sync_service); |
386 sync_pb::ExtensionSpecifics client_data; | 386 sync_pb::ExtensionSpecifics client_data; |
387 GetExtensionSpecifics(extension, extensions_service->extension_prefs(), | 387 GetExtensionSpecifics(extension, extensions_service->extension_prefs(), |
388 &client_data); | 388 &client_data); |
389 DcheckIsExtensionSpecificsValid(client_data); | 389 DcheckIsExtensionSpecificsValid(client_data); |
390 ExtensionData extension_data = | 390 ExtensionData extension_data = |
391 ExtensionData::FromData(ExtensionData::CLIENT, client_data); | 391 ExtensionData::FromData(ExtensionData::CLIENT, client_data); |
392 | 392 |
393 sync_api::WriteTransaction trans( | 393 sync_api::WriteTransaction trans( |
394 sync_service->backend()->GetUserShareHandle()); | 394 sync_service->backend()->GetUserShareHandle()); |
395 | 395 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 sync_api::WriteNode write_node(&trans); | 435 sync_api::WriteNode write_node(&trans); |
436 if (write_node.InitByClientTagLookup(traits.model_type, id)) { | 436 if (write_node.InitByClientTagLookup(traits.model_type, id)) { |
437 write_node.Remove(); | 437 write_node.Remove(); |
438 } else { | 438 } else { |
439 LOG(ERROR) << "Server data does not exist for extension " << id; | 439 LOG(ERROR) << "Server data does not exist for extension " << id; |
440 } | 440 } |
441 } | 441 } |
442 | 442 |
443 void UpdateClient(const ExtensionSyncTraits& traits, | 443 void UpdateClient(const ExtensionSyncTraits& traits, |
444 const sync_pb::ExtensionSpecifics& server_data, | 444 const sync_pb::ExtensionSpecifics& server_data, |
445 ExtensionsService* extensions_service) { | 445 ExtensionService* extensions_service) { |
446 DcheckIsExtensionSpecificsValid(server_data); | 446 DcheckIsExtensionSpecificsValid(server_data); |
447 ExtensionData extension_data = | 447 ExtensionData extension_data = |
448 ExtensionData::FromData(ExtensionData::SERVER, server_data); | 448 ExtensionData::FromData(ExtensionData::SERVER, server_data); |
449 const Extension* extension = | 449 const Extension* extension = |
450 extensions_service->GetExtensionById(server_data.id(), true); | 450 extensions_service->GetExtensionById(server_data.id(), true); |
451 if (extension) { | 451 if (extension) { |
452 if (!IsExtensionValidAndSyncable( | 452 if (!IsExtensionValidAndSyncable( |
453 *extension, traits.allowed_extension_types)) { | 453 *extension, traits.allowed_extension_types)) { |
454 LOG(WARNING) << "Ignoring server data for invalid or " | 454 LOG(WARNING) << "Ignoring server data for invalid or " |
455 << "non-syncable extension " << extension->id(); | 455 << "non-syncable extension " << extension->id(); |
(...skipping 14 matching lines...) Expand all Loading... |
470 extensions_service, &extension_data); | 470 extensions_service, &extension_data); |
471 if (extension_data.NeedsUpdate(ExtensionData::CLIENT)) { | 471 if (extension_data.NeedsUpdate(ExtensionData::CLIENT)) { |
472 NudgeExtensionUpdater(extensions_service); | 472 NudgeExtensionUpdater(extensions_service); |
473 } | 473 } |
474 } | 474 } |
475 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER)); | 475 DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER)); |
476 } | 476 } |
477 | 477 |
478 void RemoveFromClient(const ExtensionSyncTraits& traits, | 478 void RemoveFromClient(const ExtensionSyncTraits& traits, |
479 const std::string& id, | 479 const std::string& id, |
480 ExtensionsService* extensions_service) { | 480 ExtensionService* extensions_service) { |
481 const Extension* extension = extensions_service->GetExtensionById(id, true); | 481 const Extension* extension = extensions_service->GetExtensionById(id, true); |
482 if (extension) { | 482 if (extension) { |
483 if (IsExtensionValidAndSyncable(*extension, | 483 if (IsExtensionValidAndSyncable(*extension, |
484 traits.allowed_extension_types)) { | 484 traits.allowed_extension_types)) { |
485 extensions_service->UninstallExtension(id, false); | 485 extensions_service->UninstallExtension(id, false); |
486 } else { | 486 } else { |
487 LOG(WARNING) << "Ignoring server data for invalid or " | 487 LOG(WARNING) << "Ignoring server data for invalid or " |
488 << "non-syncable extension " << extension->id(); | 488 << "non-syncable extension " << extension->id(); |
489 } | 489 } |
490 } else { | 490 } else { |
491 LOG(ERROR) << "Trying to uninstall nonexistent extension " << id; | 491 LOG(ERROR) << "Trying to uninstall nonexistent extension " << id; |
492 } | 492 } |
493 } | 493 } |
494 | 494 |
495 } // namespace browser_sync | 495 } // namespace browser_sync |
OLD | NEW |