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

Unified Diff: chrome/browser/extensions/extension_sync_service.cc

Issue 1240573012: Extension syncing: Introduce a NeedsSync pref (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@ext_sync_uninstall
Patch Set: (b); hackfix sync_integration_tests Created 5 years, 5 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
Index: chrome/browser/extensions/extension_sync_service.cc
diff --git a/chrome/browser/extensions/extension_sync_service.cc b/chrome/browser/extensions/extension_sync_service.cc
index 33613fe76b5be2c31fb9b20f4842f3e408538206..5272d5448f0b3f03c5f2b1a98d4af9920b6be5d1 100644
--- a/chrome/browser/extensions/extension_sync_service.cc
+++ b/chrome/browser/extensions/extension_sync_service.cc
@@ -35,7 +35,6 @@ using extensions::ExtensionPrefs;
using extensions::ExtensionRegistry;
using extensions::ExtensionSet;
using extensions::ExtensionSyncData;
-using extensions::PendingEnables;
using extensions::SyncBundle;
namespace {
@@ -79,6 +78,15 @@ bool IsCorrectSyncType(const Extension& extension, syncer::ModelType type) {
(type == syncer::APPS && extension.is_app());
}
+syncer::SyncDataList ToSyncerSyncDataList(
+ const std::vector<ExtensionSyncData>& data) {
+ syncer::SyncDataList result;
+ result.reserve(data.size());
+ for (const ExtensionSyncData& item : data)
+ result.push_back(item.GetSyncData());
+ return result;
+}
+
} // namespace
ExtensionSyncService::ExtensionSyncService(Profile* profile,
@@ -86,21 +94,10 @@ ExtensionSyncService::ExtensionSyncService(Profile* profile,
ExtensionService* extension_service)
: profile_(profile),
extension_prefs_(extension_prefs),
- extension_service_(extension_service),
- app_sync_bundle_(this),
- extension_sync_bundle_(this),
- pending_app_enables_(make_scoped_ptr(new sync_driver::SyncPrefs(
- extension_prefs_->pref_service())),
- &app_sync_bundle_,
- syncer::APPS),
- pending_extension_enables_(make_scoped_ptr(new sync_driver::SyncPrefs(
- extension_prefs_->pref_service())),
- &extension_sync_bundle_,
- syncer::EXTENSIONS) {
+ extension_service_(extension_service) {
SetSyncStartFlare(sync_start_util::GetFlareForSyncableService(
profile_->GetPath()));
- extension_service_->set_extension_sync_service(this);
extension_prefs_->app_sorting()->SetExtensionSyncService(this);
}
@@ -124,30 +121,12 @@ void ExtensionSyncService::SyncUninstallExtension(
syncer::ModelType type =
extension.is_app() ? syncer::APPS : syncer::EXTENSIONS;
SyncBundle* bundle = GetSyncBundle(type);
- if (!bundle->IsSyncing()) {
- if (extension_service_->is_ready() && !flare_.is_null())
- flare_.Run(type); // Tell sync to start ASAP.
- return;
+ if (bundle->IsSyncing()) {
+ bundle->PushSyncDeletion(extension.id(),
+ CreateSyncData(extension).GetSyncData());
+ } else if (extension_service_->is_ready() && !flare_.is_null()) {
+ flare_.Run(type); // Tell sync to start ASAP.
}
- const std::string& id = extension.id();
- if (bundle->HasExtensionId(id))
- bundle->PushSyncDeletion(id, CreateSyncData(extension).GetSyncData());
-}
-
-void ExtensionSyncService::SyncEnableExtension(const Extension& extension) {
- // Syncing may not have started yet, so handle pending enables.
- if (extensions::util::ShouldSync(&extension, profile_))
- GetPendingEnables(extension.is_app())->Add(extension.id());
-
- SyncExtensionChangeIfNeeded(extension);
-}
-
-void ExtensionSyncService::SyncDisableExtension(const Extension& extension) {
- // Syncing may not have started yet, so handle pending enables.
- if (extensions::util::ShouldSync(&extension, profile_))
- GetPendingEnables(extension.is_app())->Remove(extension.id());
-
- SyncExtensionChangeIfNeeded(extension);
}
void ExtensionSyncService::SyncExtensionChangeIfNeeded(
@@ -158,10 +137,15 @@ void ExtensionSyncService::SyncExtensionChangeIfNeeded(
syncer::ModelType type =
extension.is_app() ? syncer::APPS : syncer::EXTENSIONS;
SyncBundle* bundle = GetSyncBundle(type);
- if (bundle->IsSyncing())
- bundle->PushSyncAddOrUpdate(extension);
- else if (extension_service_->is_ready() && !flare_.is_null())
- flare_.Run(type);
+ if (bundle->IsSyncing()) {
+ bundle->PushSyncAddOrUpdate(extension.id(),
+ CreateSyncData(extension).GetSyncData());
+ DCHECK(!ExtensionPrefs::Get(profile_)->NeedsSync(extension.id()));
+ } else {
+ ExtensionPrefs::Get(profile_)->SetNeedsSync(extension.id(), true);
+ if (extension_service_->is_ready() && !flare_.is_null())
+ flare_.Run(type); // Tell sync to start ASAP.
+ }
}
syncer::SyncMergeResult ExtensionSyncService::MergeDataAndStartSyncing(
@@ -174,17 +158,31 @@ syncer::SyncMergeResult ExtensionSyncService::MergeDataAndStartSyncing(
<< "Got " << type << " ModelType";
SyncBundle* bundle = GetSyncBundle(type);
- bool is_apps = (type == syncer::APPS);
-
- bundle->MergeDataAndStartSyncing(initial_sync_data, sync_processor.Pass());
- GetPendingEnables(is_apps)->OnSyncStarted(extension_service_);
+ bundle->StartSyncing(sync_processor.Pass());
+
+ // Apply the initial sync data, filtering out any items where we have more
+ // recent local changes. Also tell the SyncBundle the extension IDs.
+ for (const syncer::SyncData& sync_data : initial_sync_data) {
+ scoped_ptr<ExtensionSyncData> extension_sync_data(
+ ExtensionSyncData::CreateFromSyncData(sync_data));
+ // If the extension has local state that needs to be synced, ignore this
+ // change (we assume the local state is more recent).
+ if (extension_sync_data &&
+ !ExtensionPrefs::Get(profile_)->NeedsSync(extension_sync_data->id())) {
+ ApplySyncData(*extension_sync_data);
+ }
+ }
- // Process local extensions.
- // TODO(yoz): Determine whether pending extensions should be considered too.
- // See crbug.com/104399.
- bundle->PushSyncDataList(GetAllSyncData(type));
+ // Now push those local changes to sync.
+ // TODO(treib,kalman): We should only have to send out changes for extensions
+ // which have NeedsSync set (i.e. |GetLocalSyncDataList(type, false)|). That
+ // makes some sync_integration_tests fail though - figure out why and fix it!
+ std::vector<ExtensionSyncData> data_list = GetLocalSyncDataList(type, true);
Marc Treib 2015/07/21 10:54:00 I still haven't figured out the actual problem her
not at google - send to devlin 2015/07/21 13:43:30 I'll leave it to your judgement. If you think it's
+ bundle->PushSyncDataList(ToSyncerSyncDataList(data_list));
+ for (const ExtensionSyncData& data : data_list)
+ ExtensionPrefs::Get(profile_)->SetNeedsSync(data.id(), false);
- if (is_apps)
+ if (type == syncer::APPS)
extension_prefs_->app_sorting()->FixNTPOrdinalCollisions();
return syncer::SyncMergeResult(type);
@@ -196,20 +194,31 @@ void ExtensionSyncService::StopSyncing(syncer::ModelType type) {
syncer::SyncDataList ExtensionSyncService::GetAllSyncData(
syncer::ModelType type) const {
- std::vector<ExtensionSyncData> data = GetSyncDataList(type);
- syncer::SyncDataList result;
- result.reserve(data.size());
- for (const ExtensionSyncData& item : data)
- result.push_back(item.GetSyncData());
- return result;
+ const SyncBundle* bundle = GetSyncBundle(type);
+ if (!bundle->IsSyncing())
+ return syncer::SyncDataList();
+
+ std::vector<extensions::ExtensionSyncData> sync_data_list =
+ GetLocalSyncDataList(type, true);
+
+ // Add pending data (where the local extension is either not installed yet or
+ // outdated).
+ std::vector<ExtensionSyncData> pending_extensions = bundle->GetPendingData();
+ sync_data_list.insert(sync_data_list.begin(),
+ pending_extensions.begin(),
+ pending_extensions.end());
+
+ return ToSyncerSyncDataList(sync_data_list);
}
syncer::SyncError ExtensionSyncService::ProcessSyncChanges(
const tracked_objects::Location& from_here,
const syncer::SyncChangeList& change_list) {
for (const syncer::SyncChange& sync_change : change_list) {
- syncer::ModelType type = sync_change.sync_data().GetDataType();
- GetSyncBundle(type)->ApplySyncChange(sync_change);
+ scoped_ptr<ExtensionSyncData> extension_sync_data(
+ ExtensionSyncData::CreateFromSyncChange(sync_change));
+ if (extension_sync_data)
+ ApplySyncData(*extension_sync_data);
}
extension_prefs_->app_sorting()->FixNTPOrdinalCollisions();
@@ -243,6 +252,11 @@ ExtensionSyncData ExtensionSyncService::CreateSyncData(
bool ExtensionSyncService::ApplySyncData(
const ExtensionSyncData& extension_sync_data) {
+ syncer::ModelType type = extension_sync_data.is_app() ? syncer::APPS
+ : syncer::EXTENSIONS;
+ SyncBundle* bundle = GetSyncBundle(type);
+ bundle->ApplySyncData(extension_sync_data);
+
const std::string& id = extension_sync_data.id();
if (extension_sync_data.is_app()) {
@@ -256,8 +270,8 @@ bool ExtensionSyncService::ApplySyncData(
extension_sync_data.page_ordinal());
}
- // The corresponding validation of this value during AppSyncData population
- // is in AppSyncData::PopulateAppSpecifics.
+ // The corresponding validation of this value during ExtensionSyncData
+ // population is in ExtensionSyncData::ToAppSpecifics.
if (extension_sync_data.launch_type() >= extensions::LAUNCH_TYPE_FIRST &&
extension_sync_data.launch_type() < extensions::NUM_LAUNCH_TYPES) {
extensions::SetLaunchType(
@@ -268,11 +282,8 @@ bool ExtensionSyncService::ApplySyncData(
ApplyBookmarkAppSyncData(extension_sync_data);
}
- syncer::ModelType type = extension_sync_data.is_app() ? syncer::APPS
- : syncer::EXTENSIONS;
-
if (!ApplyExtensionSyncDataHelper(extension_sync_data, type)) {
- GetSyncBundle(type)->AddPendingExtension(id, extension_sync_data);
+ bundle->AddPendingExtension(id, extension_sync_data);
extension_service_->CheckForUpdatesSoon();
return false;
}
@@ -345,12 +356,6 @@ void ExtensionSyncService::SetSyncStartFlare(
flare_ = flare;
}
-bool ExtensionSyncService::IsPendingEnable(
- const std::string& extension_id) const {
- return pending_app_enables_.Contains(extension_id) ||
- pending_extension_enables_.Contains(extension_id);
-}
-
SyncBundle* ExtensionSyncService::GetSyncBundle(syncer::ModelType type) {
return const_cast<SyncBundle*>(
const_cast<const ExtensionSyncService&>(*this).GetSyncBundle(type));
@@ -361,38 +366,40 @@ const SyncBundle* ExtensionSyncService::GetSyncBundle(
return (type == syncer::APPS) ? &app_sync_bundle_ : &extension_sync_bundle_;
}
-extensions::PendingEnables* ExtensionSyncService::GetPendingEnables(
- bool is_apps) {
- return is_apps ? &pending_app_enables_ : &pending_extension_enables_;
-}
-
-std::vector<ExtensionSyncData> ExtensionSyncService::GetSyncDataList(
- syncer::ModelType type) const {
+std::vector<ExtensionSyncData> ExtensionSyncService::GetLocalSyncDataList(
+ syncer::ModelType type,
+ bool include_everything) const {
+ // Collect the local state. FillSyncDataList will filter out extensions for
+ // which we have pending data that should be used instead.
ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
- std::vector<ExtensionSyncData> extension_sync_list;
- FillSyncDataList(registry->enabled_extensions(), type, &extension_sync_list);
- FillSyncDataList(registry->disabled_extensions(), type, &extension_sync_list);
+ std::vector<ExtensionSyncData> data;
+ // TODO(treib, kalman): Should we be including blacklisted/blocked extensions
+ // here? I.e. just calling registry->GeneratedInstalledExtensionsSet()?
+ // It would be more consistent, but the danger is that the black/blocklist
+ // hasn't been updated on all clients by the time sync has kicked in -
+ // so it's safest not to. Take care to add any other extension lists here
+ // in the future if they are added.
FillSyncDataList(
- registry->terminated_extensions(), type, &extension_sync_list);
-
- std::vector<ExtensionSyncData> pending_extensions =
- GetSyncBundle(type)->GetPendingData();
- extension_sync_list.insert(extension_sync_list.begin(),
- pending_extensions.begin(),
- pending_extensions.end());
-
- return extension_sync_list;
+ registry->enabled_extensions(), type, include_everything, &data);
+ FillSyncDataList(
+ registry->disabled_extensions(), type, include_everything, &data);
+ FillSyncDataList(
+ registry->terminated_extensions(), type, include_everything, &data);
+ return data;
}
void ExtensionSyncService::FillSyncDataList(
const ExtensionSet& extensions,
syncer::ModelType type,
+ bool include_everything,
std::vector<ExtensionSyncData>* sync_data_list) const {
const SyncBundle* bundle = GetSyncBundle(type);
for (const scoped_refptr<const Extension>& extension : extensions) {
if (IsCorrectSyncType(*extension, type) &&
extensions::util::ShouldSync(extension.get(), profile_) &&
- bundle->ShouldIncludeInLocalSyncDataList(*extension)) {
+ !bundle->HasPendingExtensionId(extension->id()) &&
+ (include_everything ||
+ ExtensionPrefs::Get(profile_)->NeedsSync(extension->id()))) {
sync_data_list->push_back(CreateSyncData(*extension));
}
}
@@ -448,7 +455,7 @@ bool ExtensionSyncService::ApplyExtensionSyncDataHelper(
extension_service_->GrantPermissionsAndEnableExtension(extension);
else
extension_service_->EnableExtension(id);
- } else if (!IsPendingEnable(id)) {
+ } else {
int disable_reasons = extension_sync_data.disable_reasons();
if (extension_sync_data.remote_install()) {
if (!(disable_reasons & Extension::DISABLE_REMOTE_INSTALL)) {

Powered by Google App Engine
This is Rietveld 408576698