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

Unified Diff: chrome/browser/sync/glue/extension_model_associator.cc

Issue 3110008: Massive refactoring of extensions sync code (Closed) Base URL: 76.121.192.83:~/projects/chromium/src
Patch Set: Fixed compile error Created 10 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/sync/glue/extension_model_associator.h ('k') | chrome/browser/sync/glue/extension_sync.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/sync/glue/extension_model_associator.cc
diff --git a/chrome/browser/sync/glue/extension_model_associator.cc b/chrome/browser/sync/glue/extension_model_associator.cc
index 03374821d9de53c08cd784d0203c3a6ef8717f84..cb2890f5fd8ee3f950c86ba5a1d77e3dfa8c4eda 100644
--- a/chrome/browser/sync/glue/extension_model_associator.cc
+++ b/chrome/browser/sync/glue/extension_model_associator.cc
@@ -4,84 +4,15 @@
#include "chrome/browser/sync/glue/extension_model_associator.h"
-#include <map>
-#include <utility>
-
#include "base/logging.h"
-#include "base/utf_string_conversions.h"
-#include "chrome/browser/extensions/extension_updater.h"
-#include "chrome/browser/extensions/extensions_service.h"
-#include "chrome/browser/profile.h"
-#include "chrome/browser/sync/engine/syncapi.h"
-#include "chrome/browser/sync/glue/extension_util.h"
-#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/sync/glue/extension_data.h"
+#include "chrome/browser/sync/glue/extension_sync_traits.h"
+#include "chrome/browser/sync/glue/extension_sync.h"
#include "chrome/browser/sync/protocol/extension_specifics.pb.h"
-#include "chrome/common/extensions/extension.h"
namespace browser_sync {
-namespace {
-
-static const char kExtensionsTag[] = "google_chrome_extensions";
-
-static const char kNoExtensionsFolderError[] =
- "Server did not create the top-level extensions node. We "
- "might be running against an out-of-date server.";
-
-typedef std::map<std::string, ExtensionData> ExtensionDataMap;
-
-ExtensionData* SetOrCreateData(
- ExtensionDataMap* extension_data_map,
- ExtensionData::Source source,
- bool merge_user_properties,
- const sync_pb::ExtensionSpecifics& data) {
- DcheckIsExtensionSpecificsValid(data);
- const std::string& extension_id = data.id();
- std::pair<ExtensionDataMap::iterator, bool> result =
- extension_data_map->insert(
- std::make_pair(extension_id,
- ExtensionData::FromData(source, data)));
- ExtensionData* extension_data = &result.first->second;
- if (result.second) {
- // The value was just inserted, so it shouldn't need an update
- // from source.
- DCHECK(!extension_data->NeedsUpdate(source));
- } else {
- extension_data->SetData(source, merge_user_properties, data);
- }
- return extension_data;
-}
-
-void GetSyncableExtensionsClientData(
- const ExtensionList& extensions,
- ExtensionsService* extensions_service,
- std::set<std::string>* unsyncable_extensions,
- ExtensionDataMap* extension_data_map) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- for (ExtensionList::const_iterator it = extensions.begin();
- it != extensions.end(); ++it) {
- CHECK(*it);
- const Extension& extension = **it;
- if (IsExtensionSyncable(extension)) {
- sync_pb::ExtensionSpecifics client_specifics;
- GetExtensionSpecifics(extension, extensions_service,
- &client_specifics);
- DcheckIsExtensionSpecificsValid(client_specifics);
- const ExtensionData& extension_data =
- *SetOrCreateData(extension_data_map,
- ExtensionData::CLIENT, true, client_specifics);
- DcheckIsExtensionSpecificsValid(extension_data.merged_data());
- // Assumes this is called before any server data is read.
- DCHECK(extension_data.NeedsUpdate(ExtensionData::SERVER));
- DCHECK(!extension_data.NeedsUpdate(ExtensionData::CLIENT));
- } else {
- unsyncable_extensions->insert(extension.id());
- }
- }
-}
-
-} // namespace
-
ExtensionModelAssociator::ExtensionModelAssociator(
ProfileSyncService* sync_service) : sync_service_(sync_service) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
@@ -94,93 +25,14 @@ ExtensionModelAssociator::~ExtensionModelAssociator() {
bool ExtensionModelAssociator::AssociateModels() {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- sync_api::WriteTransaction trans(
- sync_service_->backend()->GetUserShareHandle());
- sync_api::ReadNode root(&trans);
- if (!root.InitByTagLookup(kExtensionsTag)) {
- LOG(ERROR) << kNoExtensionsFolderError;
- return false;
- }
+ const ExtensionSyncTraits traits = GetExtensionSyncTraits();
- std::set<std::string> unsyncable_extensions;
ExtensionDataMap extension_data_map;
-
- // Read client-side data. Do this first so server data takes
- // precedence.
- {
- ExtensionsService* extensions_service = GetExtensionsService();
-
- const ExtensionList* extensions = extensions_service->extensions();
- CHECK(extensions);
- GetSyncableExtensionsClientData(
- *extensions, extensions_service,
- &unsyncable_extensions, &extension_data_map);
-
- const ExtensionList* disabled_extensions =
- extensions_service->disabled_extensions();
- CHECK(disabled_extensions);
- GetSyncableExtensionsClientData(
- *disabled_extensions, extensions_service,
- &unsyncable_extensions, &extension_data_map);
- }
-
- // Read server-side data.
- {
- int64 id = root.GetFirstChildId();
- while (id != sync_api::kInvalidId) {
- sync_api::ReadNode sync_node(&trans);
- if (!sync_node.InitByIdLookup(id)) {
- LOG(ERROR) << "Failed to fetch sync node for id " << id;
- return false;
- }
- const sync_pb::ExtensionSpecifics& server_data =
- sync_node.GetExtensionSpecifics();
- if (!IsExtensionSpecificsValid(server_data)) {
- LOG(ERROR) << "Invalid extensions specifics for id " << id;
- return false;
- }
- // Don't process server data for extensions we know are
- // unsyncable. This doesn't catch everything, as if we don't
- // have the extension already installed we can't check, but we
- // also check at extension install time.
- if (unsyncable_extensions.find(server_data.id()) ==
- unsyncable_extensions.end()) {
- // Pass in false for merge_user_properties so client user
- // settings always take precedence.
- const ExtensionData& extension_data =
- *SetOrCreateData(&extension_data_map,
- ExtensionData::SERVER, false, server_data);
- DcheckIsExtensionSpecificsValid(extension_data.merged_data());
- }
- id = sync_node.GetSuccessorId();
- }
- }
-
- // Update server and client as necessary.
- bool should_nudge_extension_updater = false;
- for (ExtensionDataMap::iterator it = extension_data_map.begin();
- it != extension_data_map.end(); ++it) {
- ExtensionData* extension_data = &it->second;
- // Update server first.
- if (extension_data->NeedsUpdate(ExtensionData::SERVER)) {
- if (!UpdateServer(extension_data, &trans, root)) {
- LOG(ERROR) << "Could not update server data for extension "
- << it->first;
- return false;
- }
- }
- DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER));
- if (extension_data->NeedsUpdate(ExtensionData::CLIENT)) {
- TryUpdateClient(extension_data);
- if (extension_data->NeedsUpdate(ExtensionData::CLIENT)) {
- should_nudge_extension_updater = true;
- }
- }
- DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER));
+ if (!SlurpExtensionData(traits, sync_service_, &extension_data_map)) {
+ return false;
}
-
- if (should_nudge_extension_updater) {
- NudgeExtensionUpdater();
+ if (!FlushExtensionData(traits, extension_data_map, sync_service_)) {
+ return false;
}
return true;
@@ -194,233 +46,8 @@ bool ExtensionModelAssociator::DisassociateModels() {
bool ExtensionModelAssociator::SyncModelHasUserCreatedNodes(bool* has_nodes) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
- CHECK(has_nodes);
- *has_nodes = false;
- sync_api::ReadTransaction trans(
- sync_service_->backend()->GetUserShareHandle());
- sync_api::ReadNode root(&trans);
- if (!root.InitByTagLookup(kExtensionsTag)) {
- LOG(ERROR) << kNoExtensionsFolderError;
- return false;
- }
- // The sync model has user created nodes iff the extensions folder has
- // any children.
- *has_nodes = root.GetFirstChildId() != sync_api::kInvalidId;
- return true;
-}
-
-bool ExtensionModelAssociator::OnClientUpdate(const std::string& id) {
- sync_api::WriteTransaction trans(
- sync_service_->backend()->GetUserShareHandle());
- sync_api::ReadNode root(&trans);
- if (!root.InitByTagLookup(kExtensionsTag)) {
- LOG(ERROR) << kNoExtensionsFolderError;
- return false;
- }
- ExtensionsService* extensions_service = GetExtensionsService();
- Extension* extension = extensions_service->GetExtensionById(id, true);
- if (extension) {
- if (!IsExtensionSyncable(*extension)) {
- LOG(DFATAL) << "OnClientUpdate() called for non-syncable extension "
- << id;
- return false;
- }
- sync_pb::ExtensionSpecifics client_data;
- GetExtensionSpecifics(*extension, extensions_service, &client_data);
- DcheckIsExtensionSpecificsValid(client_data);
- ExtensionData extension_data =
- ExtensionData::FromData(ExtensionData::CLIENT, client_data);
- sync_pb::ExtensionSpecifics server_data;
- if (GetExtensionDataFromServer(id, &trans, root, &server_data)) {
- extension_data =
- ExtensionData::FromData(ExtensionData::SERVER, server_data);
- extension_data.SetData(ExtensionData::CLIENT, true, client_data);
- }
- if (extension_data.NeedsUpdate(ExtensionData::SERVER)) {
- if (!UpdateServer(&extension_data, &trans, root)) {
- LOG(ERROR) << "Could not update server data for extension " << id;
- return false;
- }
- }
- DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER));
- // Client may still need updating, e.g. if we disable an extension
- // while it's being auto-updated. If so, then we'll be called
- // again once the auto-update is finished.
- //
- // TODO(akalin): Figure out a way to tell when the above happens,
- // so we know exactly what NeedsUpdate(CLIENT) should return.
- } else {
- sync_api::WriteNode write_node(&trans);
- if (write_node.InitByClientTagLookup(syncable::EXTENSIONS, id)) {
- write_node.Remove();
- } else {
- LOG(ERROR) << "Trying to remove server data for "
- << "nonexistent extension " << id;
- }
- }
- return true;
-}
-
-void ExtensionModelAssociator::OnServerUpdate(
- const sync_pb::ExtensionSpecifics& server_data) {
- DcheckIsExtensionSpecificsValid(server_data);
- ExtensionData extension_data =
- ExtensionData::FromData(ExtensionData::SERVER, server_data);
- ExtensionsService* extensions_service = GetExtensionsService();
- Extension* extension =
- extensions_service->GetExtensionById(server_data.id(), true);
- if (extension) {
- if (!IsExtensionSyncable(*extension)) {
- // Ignore updates for non-syncable extensions (we may get those
- // for extensions that were previously syncable).
- return;
- }
- sync_pb::ExtensionSpecifics client_data;
- GetExtensionSpecifics(*extension, extensions_service, &client_data);
- DcheckIsExtensionSpecificsValid(client_data);
- extension_data =
- ExtensionData::FromData(ExtensionData::CLIENT, client_data);
- extension_data.SetData(ExtensionData::SERVER, true, server_data);
- }
- DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER));
- if (extension_data.NeedsUpdate(ExtensionData::CLIENT)) {
- TryUpdateClient(&extension_data);
- if (extension_data.NeedsUpdate(ExtensionData::CLIENT)) {
- NudgeExtensionUpdater();
- }
- }
- DCHECK(!extension_data.NeedsUpdate(ExtensionData::SERVER));
-}
-
-void ExtensionModelAssociator::OnServerRemove(const std::string& id) {
- ExtensionsService* extensions_service = GetExtensionsService();
- Extension* extension = extensions_service->GetExtensionById(id, true);
- if (extension) {
- if (IsExtensionSyncable(*extension)) {
- extensions_service->UninstallExtension(id, false);
- }
- } else {
- LOG(ERROR) << "Trying to uninstall nonexistent extension " << id;
- }
-}
-
-ExtensionsService* ExtensionModelAssociator::GetExtensionsService() {
- CHECK(sync_service_);
- Profile* profile = sync_service_->profile();
- CHECK(profile);
- ExtensionsService* extensions_service = profile->GetExtensionsService();
- CHECK(extensions_service);
- return extensions_service;
-}
-
-bool ExtensionModelAssociator::GetExtensionDataFromServer(
- const std::string& id, sync_api::WriteTransaction* trans,
- const sync_api::ReadNode& root,
- sync_pb::ExtensionSpecifics* server_data) {
- sync_api::ReadNode sync_node(trans);
- if (!sync_node.InitByClientTagLookup(syncable::EXTENSIONS, id)) {
- LOG(ERROR) << "Failed to fetch sync node for id " << id;
- return false;
- }
- const sync_pb::ExtensionSpecifics& read_server_data =
- sync_node.GetExtensionSpecifics();
- if (!IsExtensionSpecificsValid(read_server_data)) {
- LOG(ERROR) << "Invalid extensions specifics for id " << id;
- return false;
- }
- *server_data = read_server_data;
- return true;
-}
-
-namespace {
-
-void SetNodeData(const sync_pb::ExtensionSpecifics& specifics,
- sync_api::WriteNode* node) {
- node->SetTitle(UTF8ToWide(specifics.name()));
- node->SetExtensionSpecifics(specifics);
-}
-
-} // namespace
-
-bool ExtensionModelAssociator::UpdateServer(
- ExtensionData* extension_data,
- sync_api::WriteTransaction* trans,
- const sync_api::ReadNode& root) {
- DCHECK(extension_data->NeedsUpdate(ExtensionData::SERVER));
- const sync_pb::ExtensionSpecifics& specifics =
- extension_data->merged_data();
- const std::string& id = specifics.id();
- sync_api::WriteNode write_node(trans);
- if (write_node.InitByClientTagLookup(syncable::EXTENSIONS, id)) {
- SetNodeData(specifics, &write_node);
- } else {
- sync_api::WriteNode create_node(trans);
- if (!create_node.InitUniqueByCreation(syncable::EXTENSIONS, root, id)) {
- LOG(ERROR) << "Could not create node for extension " << id;
- return false;
- }
- SetNodeData(specifics, &create_node);
- }
- bool old_client_needs_update =
- extension_data->NeedsUpdate(ExtensionData::CLIENT);
- extension_data->ResolveData(ExtensionData::SERVER);
- DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER));
- DCHECK_EQ(extension_data->NeedsUpdate(ExtensionData::CLIENT),
- old_client_needs_update);
- return true;
-}
-
-void ExtensionModelAssociator::TryUpdateClient(
- ExtensionData* extension_data) {
- DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER));
- DCHECK(extension_data->NeedsUpdate(ExtensionData::CLIENT));
- const sync_pb::ExtensionSpecifics& specifics =
- extension_data->merged_data();
- DcheckIsExtensionSpecificsValid(specifics);
- ExtensionsService* extensions_service = GetExtensionsService();
- const std::string& id = specifics.id();
- Extension* extension = extensions_service->GetExtensionById(id, true);
- if (extension) {
- if (!IsExtensionSyncable(*extension)) {
- LOG(DFATAL) << "TryUpdateClient() called for non-syncable extension "
- << extension->id();
- return;
- }
- SetExtensionProperties(specifics, extensions_service, extension);
- {
- sync_pb::ExtensionSpecifics extension_specifics;
- GetExtensionSpecifics(*extension, extensions_service,
- &extension_specifics);
- DCHECK(AreExtensionSpecificsUserPropertiesEqual(
- specifics, extension_specifics))
- << ExtensionSpecificsToString(specifics) << ", "
- << ExtensionSpecificsToString(extension_specifics);
- }
- if (!IsExtensionOutdated(*extension, specifics)) {
- extension_data->ResolveData(ExtensionData::CLIENT);
- DCHECK(!extension_data->NeedsUpdate(ExtensionData::CLIENT));
- }
- } else {
- GURL update_url(specifics.update_url());
- // TODO(akalin): Replace silent update with a list of enabled
- // permissions.
- extensions_service->AddPendingExtension(
- id, update_url, false, true,
- specifics.enabled(), specifics.incognito_enabled());
- }
- DCHECK(!extension_data->NeedsUpdate(ExtensionData::SERVER));
-}
-
-void ExtensionModelAssociator::NudgeExtensionUpdater() {
- ExtensionUpdater* extension_updater = GetExtensionsService()->updater();
- // Auto-updates should now be on always (see the construction of the
- // ExtensionsService in ProfileImpl::InitExtensions()).
- if (extension_updater) {
- extension_updater->CheckNow();
- } else {
- LOG(DFATAL) << "Extension updater unexpectedly NULL; "
- << "auto-updates may be turned off";
- }
+ const ExtensionSyncTraits traits = GetExtensionSyncTraits();
+ return RootNodeHasChildren(traits.root_node_tag, sync_service_, has_nodes);
}
} // namespace browser_sync
« no previous file with comments | « chrome/browser/sync/glue/extension_model_associator.h ('k') | chrome/browser/sync/glue/extension_sync.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698