| 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 |