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