diff options
author | csharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-11 13:48:20 +0000 |
---|---|---|
committer | csharp@chromium.org <csharp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-11 13:48:20 +0000 |
commit | 5db9adad6560d8097712114ebee730be072d97f9 (patch) | |
tree | 87d2a6f637d16ea49d441ec79c378087284a9d7f /chrome/browser | |
parent | 12aea7f4b5963426318368b50d1813f5ea159b2e (diff) | |
download | chromium_src-5db9adad6560d8097712114ebee730be072d97f9.zip chromium_src-5db9adad6560d8097712114ebee730be072d97f9.tar.gz chromium_src-5db9adad6560d8097712114ebee730be072d97f9.tar.bz2 |
Create New AppSyncData Class
Remove the application specific functionality from ExtensionSyncData and move it into its own new class.
BUG=107729
TEST=All ExtensionSyncData and AppSyncData unit tests pass
Review URL: http://codereview.chromium.org/9701076
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@131760 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/extensions/app_sync_bundle.cc | 158 | ||||
-rw-r--r-- | chrome/browser/extensions/app_sync_bundle.h | 101 | ||||
-rw-r--r-- | chrome/browser/extensions/app_sync_data.cc | 99 | ||||
-rw-r--r-- | chrome/browser/extensions/app_sync_data.h | 83 | ||||
-rw-r--r-- | chrome/browser/extensions/app_sync_data_unittest.cc | 119 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_service.cc | 405 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_service.h | 84 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_service_unittest.cc | 41 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_sync_bundle.cc | 161 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_sync_bundle.h | 101 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_sync_data.cc | 120 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_sync_data.h | 54 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_sync_data_unittest.cc | 112 |
13 files changed, 1124 insertions, 514 deletions
diff --git a/chrome/browser/extensions/app_sync_bundle.cc b/chrome/browser/extensions/app_sync_bundle.cc new file mode 100644 index 0000000..43ceb98 --- /dev/null +++ b/chrome/browser/extensions/app_sync_bundle.cc @@ -0,0 +1,158 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/app_sync_bundle.h" + +#include "base/location.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/extension_sorting.h" +#include "chrome/browser/sync/api/sync_change_processor.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_set.h" + +namespace extensions { + +AppSyncBundle::AppSyncBundle(ExtensionService* extension_service) + : extension_service_(extension_service), + sync_processor_(NULL) {} + +AppSyncBundle::~AppSyncBundle() {} + +void AppSyncBundle::SetupSync(SyncChangeProcessor* sync_change_processor, + const SyncDataList& initial_sync_data) { + sync_processor_.reset(sync_change_processor); + + for (SyncDataList::const_iterator i = initial_sync_data.begin(); + i != initial_sync_data.end(); + ++i) { + AppSyncData app_sync_data(*i); + AddApp(app_sync_data.id()); + extension_service_->ProcessAppSyncData(app_sync_data); + } +} + +void AppSyncBundle::Reset() { + sync_processor_.reset(); + synced_apps_.clear(); + pending_sync_data_.clear(); +} + +SyncChange AppSyncBundle::CreateSyncChangeToDelete(const Extension* extension) + const { + AppSyncData sync_data = extension_service_->GetAppSyncData(*extension); + return sync_data.GetSyncChange(SyncChange::ACTION_DELETE); +} + +void AppSyncBundle::ProcessDeletion(std::string extension_id, + const SyncChange& sync_change) { + RemoveApp(extension_id); + sync_processor_->ProcessSyncChanges(FROM_HERE, + SyncChangeList(1, sync_change)); +} + +SyncChange AppSyncBundle::CreateSyncChange(const SyncData& sync_data) { + if (HasExtensionId(sync_data.GetTag())) { + return SyncChange(SyncChange::ACTION_UPDATE, sync_data); + } else { + AddApp(sync_data.GetTag()); + return SyncChange(SyncChange::ACTION_ADD, sync_data); + } +} + +SyncDataList AppSyncBundle::GetAllSyncData() const { + std::vector<AppSyncData> app_sync_data = + extension_service_->GetAppSyncDataList(); + SyncDataList result(app_sync_data.size()); + for (int i = 0; i < static_cast<int>(app_sync_data.size()); ++i) { + result[i] = app_sync_data[i].GetSyncData(); + } + return result; +} + +void AppSyncBundle::SyncChangeIfNeeded(const Extension& extension) { + AppSyncData app_sync_data = extension_service_->GetAppSyncData(extension); + + SyncChangeList sync_change_list(1, app_sync_data.GetSyncChange( + HasExtensionId(extension.id()) ? + SyncChange::ACTION_UPDATE : SyncChange::ACTION_ADD)); + sync_processor_->ProcessSyncChanges(FROM_HERE, sync_change_list); + MarkPendingAppSynced(extension.id()); +} + +void AppSyncBundle::ProcessSyncChange(AppSyncData app_sync_data) { + if (app_sync_data.uninstalled()) + RemoveApp(app_sync_data.id()); + else + AddApp(app_sync_data.id()); + extension_service_->ProcessAppSyncData(app_sync_data); +} + +void AppSyncBundle::ProcessSyncChangeList(SyncChangeList sync_change_list) { + sync_processor_->ProcessSyncChanges(FROM_HERE, sync_change_list); + extension_service_->extension_prefs()->extension_sorting()-> + FixNTPOrdinalCollisions(); +} + +bool AppSyncBundle::HasExtensionId(const std::string& id) const { + return synced_apps_.find(id) != synced_apps_.end(); +} + +bool AppSyncBundle::HasPendingExtensionId(const std::string& id) const { + return pending_sync_data_.find(id) != pending_sync_data_.end(); +} + +void AppSyncBundle::AddPendingApp(const std::string& id, + const AppSyncData& app_sync_data) { + pending_sync_data_[id] = app_sync_data; +} + +bool AppSyncBundle::HandlesApp(const Extension& extension) const { + return sync_processor_ != NULL && + extension.GetSyncType() == Extension::SYNC_TYPE_APP; +} + +std::vector<AppSyncData> AppSyncBundle::GetPendingData() const { + std::vector<AppSyncData> pending_apps; + for (std::map<std::string, AppSyncData>::const_iterator + i = pending_sync_data_.begin(); + i != pending_sync_data_.end(); + ++i) { + pending_apps.push_back(i->second); + } + + return pending_apps; +} + +void AppSyncBundle::GetAppSyncDataListHelper( + const ExtensionSet& extensions, + std::vector<AppSyncData>* sync_data_list) const { + for (ExtensionSet::const_iterator it = extensions.begin(); + it != extensions.end(); ++it) { + const Extension& extension = **it; + // If we have pending app data for this app, then this + // version is out of date. We'll sync back the version we got from + // sync. + if (HandlesApp(extension) && + !HasPendingExtensionId(extension.id())) { + sync_data_list->push_back(extension_service_->GetAppSyncData(extension)); + } + } +} + +void AppSyncBundle::AddApp(const std::string& id) { + synced_apps_.insert(id); +} + +void AppSyncBundle::RemoveApp(const std::string& id) { + synced_apps_.erase(id); +} + + +void AppSyncBundle::MarkPendingAppSynced(const std::string& id) { + pending_sync_data_.erase(id); + synced_apps_.insert(id); +} + + +} // namespace extensions diff --git a/chrome/browser/extensions/app_sync_bundle.h b/chrome/browser/extensions/app_sync_bundle.h new file mode 100644 index 0000000..9872e9d --- /dev/null +++ b/chrome/browser/extensions/app_sync_bundle.h @@ -0,0 +1,101 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_APP_SYNC_BUNDLE_H_ +#define CHROME_BROWSER_EXTENSIONS_APP_SYNC_BUNDLE_H_ +#pragma once + +#include <map> +#include <set> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "chrome/browser/extensions/app_sync_data.h" +#include "chrome/browser/sync/api/syncable_service.h" + +class SyncChangeProcessor; +class Extension; +class ExtensionService; +class ExtensionSet; + +namespace extensions { + +// Bundle of app specific sync stuff. +class AppSyncBundle { + public: + explicit AppSyncBundle(ExtensionService* extension_service); + virtual ~AppSyncBundle(); + + // Setup this bundle to be sync application data. + void SetupSync(SyncChangeProcessor* sync_proccessor, + const SyncDataList& initial_sync_data); + + // Resets this class back to it default values, which will disable all syncing + // until a new sync processor is set. + void Reset(); + + // Returns a SyncChange that will delete the given application. + SyncChange CreateSyncChangeToDelete(const Extension* extension) const; + + // Process the sync deletion of the given application. + void ProcessDeletion(std::string extension_id, const SyncChange& sync_change); + + // Create a sync change based on |sync_data|. + SyncChange CreateSyncChange(const SyncData& sync_data); + + // Get all the sync data contained in this bundle. + SyncDataList GetAllSyncData() const; + + // Sync a newly-installed application or change an existing one. + void SyncChangeIfNeeded(const Extension& extension); + + // Process the given sync change and apply it. + void ProcessSyncChange(AppSyncData app_sync_data); + + // Process the list of sync changes. + void ProcessSyncChangeList(SyncChangeList sync_change_list); + + // Check to see if the given |id| is either synced or pending to be synced. + bool HasExtensionId(const std::string& id) const; + bool HasPendingExtensionId(const std::string& id) const; + + // Add a pending app to be synced. + void AddPendingApp(const std::string& id, + const AppSyncData& app_sync_data); + + // Returns true if |extension| should be handled by this sync bundle. + bool HandlesApp(const Extension& extension) const; + + // Returns a vector of all the pending sync data. + std::vector<AppSyncData> GetPendingData() const; + + // Appends sync data objects for every app in |extensions|. + void GetAppSyncDataListHelper( + const ExtensionSet& extensions, + std::vector<extensions::AppSyncData>* sync_data_list) const; + + private: + // Add a synced app. + void AddApp(const std::string& id); + + // Remove a synced app. + void RemoveApp(const std::string& id); // make private + + // Change an app from being pending to synced. + void MarkPendingAppSynced(const std::string& id); + + ExtensionService* extension_service_; // Own us. + scoped_ptr<SyncChangeProcessor> sync_processor_; + + std::set<std::string> synced_apps_; + std::map<std::string, AppSyncData> pending_sync_data_; + + DISALLOW_COPY_AND_ASSIGN(AppSyncBundle); +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_APP_SYNC_BUNDLE_H_ diff --git a/chrome/browser/extensions/app_sync_data.cc b/chrome/browser/extensions/app_sync_data.cc new file mode 100644 index 0000000..8145b0a --- /dev/null +++ b/chrome/browser/extensions/app_sync_data.cc @@ -0,0 +1,99 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/app_sync_data.h" + +#include "chrome/browser/sync/api/sync_data.h" +#include "chrome/common/extensions/extension.h" +#include "sync/protocol/app_specifics.pb.h" +#include "sync/protocol/sync.pb.h" + +namespace extensions { + +AppSyncData::AppSyncData() : notifications_disabled_(false) {} + +AppSyncData::AppSyncData(const SyncData& sync_data) + : notifications_disabled_(false) { + PopulateFromSyncData(sync_data); +} + +AppSyncData::AppSyncData(const SyncChange& sync_change) + : notifications_disabled_(false) { + PopulateFromSyncData(sync_change.sync_data()); + extension_sync_data_.set_uninstalled( + sync_change.change_type() == SyncChange::ACTION_DELETE); +} + +AppSyncData::AppSyncData(const Extension& extension, + bool enabled, + bool incognito_enabled, + const std::string& notifications_client_id, + bool notifications_disabled, + const StringOrdinal& app_launch_ordinal, + const StringOrdinal& page_ordinal) + : extension_sync_data_(extension, enabled, incognito_enabled), + notifications_client_id_(notifications_client_id), + notifications_disabled_(notifications_disabled), + app_launch_ordinal_(app_launch_ordinal), + page_ordinal_(page_ordinal) { +} + +AppSyncData::~AppSyncData() {} + +SyncData AppSyncData::GetSyncData() const { + sync_pb::EntitySpecifics specifics; + PopulateAppSpecifics(specifics.mutable_app()); + + return SyncData::CreateLocalData(extension_sync_data_.id(), + extension_sync_data_.name(), + specifics); +} + +SyncChange AppSyncData::GetSyncChange(SyncChange::SyncChangeType change_type) + const { + return SyncChange(change_type, GetSyncData()); +} + +void AppSyncData::PopulateAppSpecifics(sync_pb::AppSpecifics* specifics) const { + DCHECK(specifics); + sync_pb::AppNotificationSettings* notification_settings = + specifics->mutable_notification_settings(); + if (!notifications_client_id_.empty()) + notification_settings->set_oauth_client_id(notifications_client_id_); + notification_settings->set_disabled(notifications_disabled_); + + // Only sync the ordinal values if they are valid. + if (app_launch_ordinal_.IsValid()) + specifics->set_app_launch_ordinal(app_launch_ordinal_.ToString()); + if (page_ordinal_.IsValid()) + specifics->set_page_ordinal(page_ordinal_.ToString()); + + extension_sync_data_.PopulateExtensionSpecifics( + specifics->mutable_extension()); +} + +void AppSyncData::PopulateFromAppSpecifics( + const sync_pb::AppSpecifics& specifics) { + extension_sync_data_.PopulateFromExtensionSpecifics(specifics.extension()); + + if (specifics.has_notification_settings() && + specifics.notification_settings().has_oauth_client_id()) { + notifications_client_id_ = + specifics.notification_settings().oauth_client_id(); + } + + notifications_disabled_ = + specifics.has_notification_settings() && + specifics.notification_settings().has_disabled() && + specifics.notification_settings().disabled(); + + app_launch_ordinal_ = StringOrdinal(specifics.app_launch_ordinal()); + page_ordinal_ = StringOrdinal(specifics.page_ordinal()); +} + +void AppSyncData::PopulateFromSyncData(const SyncData& sync_data) { + PopulateFromAppSpecifics(sync_data.GetSpecifics().app()); +} + +} // namespace extensions diff --git a/chrome/browser/extensions/app_sync_data.h b/chrome/browser/extensions/app_sync_data.h new file mode 100644 index 0000000..a77ef39 --- /dev/null +++ b/chrome/browser/extensions/app_sync_data.h @@ -0,0 +1,83 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_APP_SYNC_DATA_H_ +#define CHROME_BROWSER_EXTENSIONS_APP_SYNC_DATA_H_ +#pragma once + +#include "chrome/browser/extensions/extension_sync_data.h" +#include "chrome/browser/sync/api/sync_change.h" +#include "chrome/common/string_ordinal.h" + +class Extension; +class SyncData; +namespace sync_pb { +class AppSpecifics; +} + +namespace extensions { + +class ExtensionSyncData; + +// A class that encapsulates the synced properties of an Application. +class AppSyncData { + public: + AppSyncData(); + explicit AppSyncData(const SyncData& sync_data); + explicit AppSyncData(const SyncChange& sync_change); + AppSyncData(const Extension& extension, + bool enabled, + bool incognito_enabled, + const std::string& notifications_client_id, + bool notifications_disabled, + const StringOrdinal& app_launch_ordinal, + const StringOrdinal& page_ordinal); + ~AppSyncData(); + + // Retrive sync data from this class. + SyncData GetSyncData() const; + SyncChange GetSyncChange(SyncChange::SyncChangeType change_type) const; + + const std::string& id() const { return extension_sync_data_.id(); } + + bool uninstalled() const { return extension_sync_data_.uninstalled(); } + + const std::string& notifications_client_id() const { + return notifications_client_id_; + } + + bool notifications_disabled() const { + return notifications_disabled_; + } + + // These ordinals aren't necessarily valid. Some applications don't have + // valid ordinals because they don't appear on the new tab page. + const StringOrdinal& app_launch_ordinal() const { + return app_launch_ordinal_; + } + const StringOrdinal& page_ordinal() const { return page_ordinal_; } + + const ExtensionSyncData& extension_sync_data() const { + return extension_sync_data_; + } + + private: + // Convert an AppSyncData back out to a sync structure. + void PopulateAppSpecifics(sync_pb::AppSpecifics* specifics) const; + + // Populate this class from sync inputs. + void PopulateFromAppSpecifics( + const sync_pb::AppSpecifics& specifics); + void PopulateFromSyncData(const SyncData& sync_data); + + ExtensionSyncData extension_sync_data_; + std::string notifications_client_id_; + bool notifications_disabled_; + StringOrdinal app_launch_ordinal_; + StringOrdinal page_ordinal_; +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_APP_SYNC_DATA_H_ diff --git a/chrome/browser/extensions/app_sync_data_unittest.cc b/chrome/browser/extensions/app_sync_data_unittest.cc new file mode 100644 index 0000000..0a86964 --- /dev/null +++ b/chrome/browser/extensions/app_sync_data_unittest.cc @@ -0,0 +1,119 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/app_sync_data.h" + +#include "sync/protocol/app_specifics.pb.h" +#include "sync/protocol/sync.pb.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace extensions { + +namespace { + +const char kValidId[] = "abcdefghijklmnopabcdefghijklmnop"; +const char kName[] = "MyExtension"; +const char kValidVersion[] = "0.0.0.0"; +const char kValidUpdateUrl[] = + "http://clients2.google.com/service/update2/crx"; +const char kOAuthClientId[] = "1234abcd"; + +} // namespace + +class AppSyncDataTest : public testing::Test { + public: + AppSyncDataTest() {} + virtual ~AppSyncDataTest() {} + + void SetRequiredExtensionValues( + sync_pb::ExtensionSpecifics* extension_specifics) { + extension_specifics->set_id(kValidId); + extension_specifics->set_update_url(kValidUpdateUrl); + extension_specifics->set_version(kValidVersion); + extension_specifics->set_enabled(false); + extension_specifics->set_incognito_enabled(true); + extension_specifics->set_name(kName); + } +}; + +TEST_F(AppSyncDataTest, SyncDataToExtensionSyncDataForApp) { + sync_pb::EntitySpecifics entity; + sync_pb::AppSpecifics* app_specifics = entity.mutable_app(); + app_specifics->set_app_launch_ordinal( + StringOrdinal::CreateInitialOrdinal().ToString()); + app_specifics->set_page_ordinal( + StringOrdinal::CreateInitialOrdinal().ToString()); + sync_pb::AppNotificationSettings* notif_settings = + app_specifics->mutable_notification_settings(); + notif_settings->set_oauth_client_id(kOAuthClientId); + notif_settings->set_disabled(true); + + SetRequiredExtensionValues(app_specifics->mutable_extension()); + + SyncData sync_data = + SyncData::CreateLocalData("sync_tag", "non_unique_title", entity); + + AppSyncData app_sync_data(sync_data); + EXPECT_EQ(app_specifics->app_launch_ordinal(), + app_sync_data.app_launch_ordinal().ToString()); + EXPECT_EQ(app_specifics->page_ordinal(), + app_sync_data.page_ordinal().ToString()); + EXPECT_EQ(notif_settings->oauth_client_id(), + app_sync_data.notifications_client_id()); + EXPECT_EQ(notif_settings->disabled(), + app_sync_data.notifications_disabled()); +} + + + +TEST_F(AppSyncDataTest, ExtensionSyncDataToSyncDataForApp) { + sync_pb::EntitySpecifics entity; + sync_pb::AppSpecifics* input_specifics = entity.mutable_app(); + input_specifics->set_app_launch_ordinal( + StringOrdinal::CreateInitialOrdinal().ToString()); + input_specifics->set_page_ordinal( + StringOrdinal::CreateInitialOrdinal().ToString()); + sync_pb::AppNotificationSettings* notif_settings = + input_specifics->mutable_notification_settings(); + notif_settings->set_oauth_client_id(kOAuthClientId); + notif_settings->set_disabled(true); + + SetRequiredExtensionValues(input_specifics->mutable_extension()); + + SyncData sync_data = + SyncData::CreateLocalData("sync_tag", "non_unique_title", entity); + AppSyncData app_sync_data(sync_data); + + SyncData output_sync_data = app_sync_data.GetSyncData(); + EXPECT_TRUE(sync_data.GetSpecifics().has_app()); + const sync_pb::AppSpecifics& output_specifics = + output_sync_data.GetSpecifics().app(); + EXPECT_EQ(input_specifics->SerializeAsString(), + output_specifics.SerializeAsString()); +} + +// Ensures that invalid StringOrdinals don't break ExtensionSyncData. +TEST_F(AppSyncDataTest, ExtensionSyncDataInvalidOrdinal) { + sync_pb::EntitySpecifics entity; + sync_pb::AppSpecifics* app_specifics = entity.mutable_app(); + // Set the ordinals as invalid. + app_specifics->set_app_launch_ordinal(""); + app_specifics->set_page_ordinal(""); + + sync_pb::AppNotificationSettings* notif_settings = + app_specifics->mutable_notification_settings(); + notif_settings->set_oauth_client_id(kOAuthClientId); + notif_settings->set_disabled(true); + + SetRequiredExtensionValues(app_specifics->mutable_extension()); + + SyncData sync_data = + SyncData::CreateLocalData("sync_tag", "non_unique_title", entity); + + // There should be no issue loading the sync data. + AppSyncData app_sync_data(sync_data); + app_sync_data.GetSyncData(); +} + +} // namespace extensions diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index 27bc442..891290e 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc @@ -33,11 +33,13 @@ #include "chrome/browser/download/download_extension_api.h" #include "chrome/browser/extensions/api/api_resource_controller.h" #include "chrome/browser/extensions/app_notification_manager.h" +#include "chrome/browser/extensions/app_sync_data.h" #include "chrome/browser/extensions/apps_promo.h" #include "chrome/browser/extensions/component_loader.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/api/declarative/rules_registry_service.h" #include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h" +#include "chrome/browser/extensions/app_sync_data.h" #include "chrome/browser/extensions/default_apps_trial.h" #include "chrome/browser/extensions/extension_browser_event_router.h" #include "chrome/browser/extensions/extension_cookies_api.h" @@ -391,6 +393,8 @@ ExtensionService::ExtensionService(Profile* profile, app_notification_manager_(new AppNotificationManager(profile)), apps_promo_(profile->GetPrefs()), event_routers_initialized_(false), + app_sync_bundle_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), + extension_sync_bundle_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), extension_warnings_(profile), api_resource_controller_(NULL), app_shortcut_manager_(profile) { @@ -777,20 +781,11 @@ bool ExtensionService::UninstallExtension( // Extract the data we need for sync now, but don't actually sync until we've // completed the uninstallation. - SyncBundle* sync_bundle = GetSyncBundleForExtension(*extension); - SyncChange sync_change; - if (sync_bundle) { - ExtensionSyncData extension_sync_data( - *extension, - IsExtensionEnabled(extension_id), - IsIncognitoEnabled(extension_id), - extension_prefs_->GetAppNotificationClientId(extension_id), - extension_prefs_->IsAppNotificationDisabled(extension_id), - extension_prefs_->extension_sorting()-> - GetAppLaunchOrdinal(extension_id), - extension_prefs_->extension_sorting()->GetPageOrdinal(extension_id)); - sync_change = extension_sync_data.GetSyncChange(SyncChange::ACTION_DELETE); + if (app_sync_bundle_.HandlesApp(*extension)) { + sync_change = app_sync_bundle_.CreateSyncChangeToDelete(extension); + } else if (extension_sync_bundle_.HandlesExtension(*extension)) { + sync_change = extension_sync_bundle_.CreateSyncChangeToDelete(extension); } UMA_HISTOGRAM_ENUMERATION("Extensions.UninstallType", @@ -844,10 +839,12 @@ bool ExtensionService::UninstallExtension( content::Source<Profile>(profile_), content::Details<const std::string>(&extension_id)); - if (sync_bundle && sync_bundle->HasExtensionId(extension_id)) { - sync_bundle->sync_processor->ProcessSyncChanges( - FROM_HERE, SyncChangeList(1, sync_change)); - sync_bundle->synced_extensions.erase(extension_id); + if (app_sync_bundle_.HasExtensionId(extension_id) && + sync_change.sync_data().GetDataType() == syncable::APPS) { + app_sync_bundle_.ProcessDeletion(extension_id, sync_change); + } else if (extension_sync_bundle_.HasExtensionId(extension_id) && + sync_change.sync_data().GetDataType() == syncable::EXTENSIONS) { + extension_sync_bundle_.ProcessDeletion(extension_id, sync_change); } // Track the uninstallation. @@ -1271,115 +1268,25 @@ void ExtensionService::CheckForUpdatesSoon() { } } -namespace { - bool IsSyncableNone(const Extension& extension) { return false; } -} // namespace - -ExtensionService::SyncBundle::SyncBundle() - : filter(IsSyncableNone) { -} - -ExtensionService::SyncBundle::~SyncBundle() { -} - -void ExtensionService::SyncBundle::Reset() { - filter = IsSyncableNone; - synced_extensions.clear(); - pending_sync_data.clear(); - sync_processor.reset(); -} - -bool ExtensionService::SyncBundle::HasExtensionId(const std::string& id) const { - return synced_extensions.find(id) != synced_extensions.end(); -} - -bool ExtensionService::SyncBundle::HasPendingExtensionId(const std::string& id) - const { - return pending_sync_data.find(id) != pending_sync_data.end(); -} - -ExtensionService::SyncBundle* ExtensionService::GetSyncBundleForExtension( - const Extension& extension) { - if (app_sync_bundle_.filter(extension)) - return &app_sync_bundle_; - else if (extension_sync_bundle_.filter(extension)) - return &extension_sync_bundle_; - else - return NULL; -} - -ExtensionService::SyncBundle* - ExtensionService::GetSyncBundleForExtensionSyncData( - const ExtensionSyncData& extension_sync_data) { - switch (extension_sync_data.type()) { - case Extension::SYNC_TYPE_APP: - return &app_sync_bundle_; - case Extension::SYNC_TYPE_EXTENSION: - return &extension_sync_bundle_; - default: - NOTREACHED(); - return NULL; - } -} - -#define GET_SYNC_BUNDLE_FOR_MODEL_TYPE_BODY() \ - do { \ - switch (type) { \ - case syncable::APPS: \ - return &app_sync_bundle_; \ - case syncable::EXTENSIONS: \ - return &extension_sync_bundle_; \ - default: \ - NOTREACHED(); \ - return NULL; \ - } \ - } while (0) - -const ExtensionService::SyncBundle* - ExtensionService::GetSyncBundleForModelTypeConst( - syncable::ModelType type) const { - GET_SYNC_BUNDLE_FOR_MODEL_TYPE_BODY(); -} - -ExtensionService::SyncBundle* ExtensionService::GetSyncBundleForModelType( - syncable::ModelType type) { - GET_SYNC_BUNDLE_FOR_MODEL_TYPE_BODY(); -} - -#undef GET_SYNC_BUNDLE_FOR_MODEL_TYPE_BODY - SyncError ExtensionService::MergeDataAndStartSyncing( syncable::ModelType type, const SyncDataList& initial_sync_data, scoped_ptr<SyncChangeProcessor> sync_processor) { - SyncBundle* bundle = NULL; + CHECK(sync_processor.get()); switch (type) { case syncable::EXTENSIONS: - bundle = &extension_sync_bundle_; - bundle->filter = IsSyncableExtension; + extension_sync_bundle_.SetupSync(sync_processor.release(), + initial_sync_data); break; case syncable::APPS: - bundle = &app_sync_bundle_; - bundle->filter = IsSyncableApp; + app_sync_bundle_.SetupSync(sync_processor.release(), initial_sync_data); break; default: LOG(FATAL) << "Got " << type << " ModelType"; } - DCHECK(!bundle->sync_processor.get()); - DCHECK(sync_processor.get()); - bundle->sync_processor = sync_processor.Pass(); - - // Process extensions from sync. - for (SyncDataList::const_iterator i = initial_sync_data.begin(); - i != initial_sync_data.end(); - ++i) { - ExtensionSyncData extension_sync_data = ExtensionSyncData(*i); - bundle->synced_extensions.insert(extension_sync_data.id()); - ProcessExtensionSyncData(extension_sync_data, *bundle); - } // Process local extensions. // TODO(yoz): Determine whether pending extensions should be considered too. @@ -1389,35 +1296,49 @@ SyncError ExtensionService::MergeDataAndStartSyncing( for (SyncDataList::const_iterator i = sync_data_list.begin(); i != sync_data_list.end(); ++i) { - if (bundle->HasExtensionId(i->GetTag())) { - sync_change_list.push_back(SyncChange(SyncChange::ACTION_UPDATE, *i)); - } else { - bundle->synced_extensions.insert(i->GetTag()); - sync_change_list.push_back(SyncChange(SyncChange::ACTION_ADD, *i)); - } + switch (type) { + case syncable::EXTENSIONS: + sync_change_list.push_back( + extension_sync_bundle_.CreateSyncChange(*i)); + break; + case syncable::APPS: + sync_change_list.push_back(app_sync_bundle_.CreateSyncChange(*i)); + break; + default: + LOG(FATAL) << "Got " << type << " ModelType"; + } } - bundle->sync_processor->ProcessSyncChanges(FROM_HERE, sync_change_list); - extension_prefs_->extension_sorting()->FixNTPOrdinalCollisions(); + + if (type == syncable::EXTENSIONS) { + extension_sync_bundle_.ProcessSyncChangeList(sync_change_list); + } else if (type == syncable::APPS) { + app_sync_bundle_.ProcessSyncChangeList(sync_change_list); + } return SyncError(); } void ExtensionService::StopSyncing(syncable::ModelType type) { - SyncBundle* bundle = GetSyncBundleForModelType(type); - CHECK(bundle); - bundle->Reset(); + if (type == syncable::APPS) { + app_sync_bundle_.Reset(); + } else if (type == syncable::EXTENSIONS) { + extension_sync_bundle_.Reset(); + } } SyncDataList ExtensionService::GetAllSyncData(syncable::ModelType type) const { - const SyncBundle* bundle = GetSyncBundleForModelTypeConst(type); - CHECK(bundle); - std::vector<ExtensionSyncData> extension_sync_data = GetSyncDataList(*bundle); - SyncDataList result(extension_sync_data.size()); - for (int i = 0; i < static_cast<int>(extension_sync_data.size()); ++i) { - result[i] = extension_sync_data[i].GetSyncData(); + if (type == syncable::EXTENSIONS) { + return extension_sync_bundle_.GetAllSyncData(); + + } else if (type == syncable::APPS) { + return app_sync_bundle_.GetAllSyncData(); } - return result; + + // We should only get sync data for extensions and apps. + NOTREACHED(); + + return SyncDataList(); } SyncError ExtensionService::ProcessSyncChanges( @@ -1426,15 +1347,13 @@ SyncError ExtensionService::ProcessSyncChanges( for (SyncChangeList::const_iterator i = change_list.begin(); i != change_list.end(); ++i) { - ExtensionSyncData extension_sync_data = ExtensionSyncData(*i); - SyncBundle* bundle = GetSyncBundleForExtensionSyncData(extension_sync_data); - CHECK(bundle); - - if (extension_sync_data.uninstalled()) - bundle->synced_extensions.erase(extension_sync_data.id()); - else - bundle->synced_extensions.insert(extension_sync_data.id()); - ProcessExtensionSyncData(extension_sync_data, *bundle); + syncable::ModelType type = i->sync_data().GetDataType(); + if (type == syncable::EXTENSIONS) { + extension_sync_bundle_.ProcessSyncChange( + extensions::ExtensionSyncData(*i)); + } else if (type == syncable::APPS) { + app_sync_bundle_.ProcessSyncChange(extensions::AppSyncData(*i)); + } } extension_prefs()->extension_sorting()->FixNTPOrdinalCollisions(); @@ -1442,60 +1361,134 @@ SyncError ExtensionService::ProcessSyncChanges( return SyncError(); } -void ExtensionService::GetSyncDataListHelper( - const ExtensionSet& extensions, - const SyncBundle& bundle, - std::vector<ExtensionSyncData>* sync_data_list) const { - for (ExtensionSet::const_iterator it = extensions.begin(); - it != extensions.end(); ++it) { - const Extension& extension = **it; - if (bundle.filter(extension) && - // If we have pending extension data for this extension, then this - // version is out of date. We'll sync back the version we got from - // sync. - !bundle.HasPendingExtensionId(extension.id())) { - sync_data_list->push_back(ExtensionSyncData( - extension, - IsExtensionEnabled(extension.id()), - IsIncognitoEnabled(extension.id()), - extension_prefs_->GetAppNotificationClientId(extension.id()), - extension_prefs_->IsAppNotificationDisabled(extension.id()), - extension_prefs_->extension_sorting()-> - GetAppLaunchOrdinal(extension.id()), - extension_prefs_->extension_sorting()-> - GetPageOrdinal(extension.id()))); - } +extensions::ExtensionSyncData ExtensionService::GetExtensionSyncData( + const Extension& extension) const { + return extensions::ExtensionSyncData(extension, + IsExtensionEnabled(extension.id()), + IsIncognitoEnabled(extension.id())); +} + +extensions::AppSyncData ExtensionService::GetAppSyncData( + const Extension& extension) const { + return extensions::AppSyncData( + extension, + IsExtensionEnabled(extension.id()), + IsIncognitoEnabled(extension.id()), + extension_prefs_->GetAppNotificationClientId(extension.id()), + extension_prefs_->IsAppNotificationDisabled(extension.id()), + extension_prefs_->extension_sorting()->GetAppLaunchOrdinal( + extension.id()), + extension_prefs_->extension_sorting()->GetPageOrdinal(extension.id())); +} + +std::vector<extensions::ExtensionSyncData> + ExtensionService::GetExtensionSyncDataList() const { + std::vector<extensions::ExtensionSyncData> extension_sync_list; + extension_sync_bundle_.GetExtensionSyncDataListHelper(extensions_, + &extension_sync_list); + extension_sync_bundle_.GetExtensionSyncDataListHelper(disabled_extensions_, + &extension_sync_list); + extension_sync_bundle_.GetExtensionSyncDataListHelper(terminated_extensions_, + &extension_sync_list); + + std::vector<extensions::ExtensionSyncData> pending_extensions = + extension_sync_bundle_.GetPendingData(); + extension_sync_list.insert(extension_sync_list.begin(), + pending_extensions.begin(), + pending_extensions.end()); + + return extension_sync_list; +} + +std::vector<extensions::AppSyncData> ExtensionService::GetAppSyncDataList() + const { + std::vector<extensions::AppSyncData> app_sync_list; + app_sync_bundle_.GetAppSyncDataListHelper(extensions_, &app_sync_list); + app_sync_bundle_.GetAppSyncDataListHelper(disabled_extensions_, + &app_sync_list); + app_sync_bundle_.GetAppSyncDataListHelper(terminated_extensions_, + &app_sync_list); + + std::vector<extensions::AppSyncData> pending_apps = + app_sync_bundle_.GetPendingData(); + app_sync_list.insert(app_sync_list.begin(), + pending_apps.begin(), + pending_apps.end()); + + return app_sync_list; +} + +bool ExtensionService::ProcessExtensionSyncData( + const extensions::ExtensionSyncData& extension_sync_data) { + if (!ProcessExtensionSyncDataHelper(extension_sync_data, + syncable::EXTENSIONS)) { + extension_sync_bundle_.AddPendingExtension(extension_sync_data.id(), + extension_sync_data); + CheckForUpdatesSoon(); + return false; } + + return true; } -std::vector<ExtensionSyncData> ExtensionService::GetSyncDataList( - const SyncBundle& bundle) const { - std::vector<ExtensionSyncData> extension_sync_list; - GetSyncDataListHelper(extensions_, bundle, &extension_sync_list); - GetSyncDataListHelper(disabled_extensions_, bundle, &extension_sync_list); - GetSyncDataListHelper(terminated_extensions_, bundle, &extension_sync_list); +bool ExtensionService::ProcessAppSyncData( + const extensions::AppSyncData& app_sync_data) { + const std::string& id = app_sync_data.id(); + const Extension* extension = GetInstalledExtension(id); + bool extension_installed = (extension != NULL); - for (std::map<std::string, ExtensionSyncData>::const_iterator i = - bundle.pending_sync_data.begin(); - i != bundle.pending_sync_data.end(); - ++i) { - extension_sync_list.push_back(i->second); + if (app_sync_data.app_launch_ordinal().IsValid() && + app_sync_data.page_ordinal().IsValid()) { + extension_prefs_->extension_sorting()->SetAppLaunchOrdinal( + id, + app_sync_data.app_launch_ordinal()); + extension_prefs_->extension_sorting()->SetPageOrdinal( + id, + app_sync_data.page_ordinal()); } - return extension_sync_list; + if (extension_installed) { + if (app_sync_data.notifications_disabled() != + extension_prefs_->IsAppNotificationDisabled(id)) { + extension_prefs_->SetAppNotificationDisabled( + id, app_sync_data.notifications_disabled()); + } + } + + if (!ProcessExtensionSyncDataHelper(app_sync_data.extension_sync_data(), + syncable::APPS)) { + app_sync_bundle_.AddPendingApp(id, app_sync_data); + CheckForUpdatesSoon(); + return false; + } + + return true; } -void ExtensionService::ProcessExtensionSyncData( - const ExtensionSyncData& extension_sync_data, - SyncBundle& bundle) { +bool ExtensionService::IsCorrectSyncType(const Extension& extension, + syncable::ModelType type) const { + if (type == syncable::EXTENSIONS && + extension.GetSyncType() == Extension::SYNC_TYPE_EXTENSION) + return true; + + if (type == syncable::APPS && + extension.GetSyncType() == Extension::SYNC_TYPE_APP) + return true; + + return false; +} + +bool ExtensionService::ProcessExtensionSyncDataHelper( + const extensions::ExtensionSyncData& extension_sync_data, + syncable::ModelType type) { const std::string& id = extension_sync_data.id(); const Extension* extension = GetInstalledExtension(id); // TODO(bolms): we should really handle this better. The particularly bad // case is where an app becomes an extension or vice versa, and we end up with // a zombie extension that won't go away. - if (extension && !bundle.filter(*extension)) - return; + if (extension && !IsCorrectSyncType(*extension, type)) + return true; // Handle uninstalls first. if (extension_sync_data.uninstalled()) { @@ -1504,7 +1497,7 @@ void ExtensionService::ProcessExtensionSyncData( LOG(WARNING) << "Could not uninstall extension " << id << " for sync"; } - return; + return true; } // Set user settings. @@ -1523,37 +1516,25 @@ void ExtensionService::ProcessExtensionSyncData( SetIsIncognitoEnabled(id, extension_sync_data.incognito_enabled()); extension = NULL; // No longer safe to use. - if (extension_sync_data.app_launch_ordinal().IsValid() && - extension_sync_data.page_ordinal().IsValid()) { - extension_prefs_->extension_sorting()->SetAppLaunchOrdinal( - id, - extension_sync_data.app_launch_ordinal()); - extension_prefs_->extension_sorting()->SetPageOrdinal( - id, - extension_sync_data.page_ordinal()); - } - if (extension_installed) { // If the extension is already installed, check if it's outdated. if (result < 0) { // Extension is outdated. - bundle.pending_sync_data[extension_sync_data.id()] = extension_sync_data; - CheckForUpdatesSoon(); - } - if (extension_sync_data.type() == Extension::SYNC_TYPE_APP && - extension_sync_data.notifications_disabled() != - extension_prefs_->IsAppNotificationDisabled(id)) { - extension_prefs_->SetAppNotificationDisabled( - id, extension_sync_data.notifications_disabled()); + return false; } } else { // TODO(akalin): Replace silent update with a list of enabled // permissions. const bool kInstallSilently = true; + + CHECK(type == syncable::EXTENSIONS || type == syncable::APPS); + ExtensionFilter filter = + (type == syncable::APPS) ? IsSyncableApp : IsSyncableExtension; + if (!pending_extension_manager()->AddFromSync( id, extension_sync_data.update_url(), - bundle.filter, + filter, kInstallSilently)) { LOG(WARNING) << "Could not add pending extension for " << id; // This means that the extension is already pending installation, with a @@ -1562,9 +1543,10 @@ void ExtensionService::ProcessExtensionSyncData( // extension), so that GetAllSyncData() continues to send it. } // Track pending extensions so that we can return them in GetAllSyncData(). - bundle.pending_sync_data[extension_sync_data.id()] = extension_sync_data; - CheckForUpdatesSoon(); + return false; } + + return true; } bool ExtensionService::IsIncognitoEnabled( @@ -1972,25 +1954,10 @@ void ExtensionService::GarbageCollectExtensions() { } void ExtensionService::SyncExtensionChangeIfNeeded(const Extension& extension) { - SyncBundle* sync_bundle = GetSyncBundleForExtension(extension); - if (sync_bundle) { - ExtensionSyncData extension_sync_data( - extension, - IsExtensionEnabled(extension.id()), - IsIncognitoEnabled(extension.id()), - extension_prefs_->GetAppNotificationClientId(extension.id()), - extension_prefs_->IsAppNotificationDisabled(extension.id()), - extension_prefs_->extension_sorting()-> - GetAppLaunchOrdinal(extension.id()), - extension_prefs_->extension_sorting()->GetPageOrdinal(extension.id())); - - SyncChangeList sync_change_list(1, extension_sync_data.GetSyncChange( - sync_bundle->HasExtensionId(extension.id()) ? - SyncChange::ACTION_UPDATE : SyncChange::ACTION_ADD)); - sync_bundle->sync_processor->ProcessSyncChanges( - FROM_HERE, sync_change_list); - sync_bundle->synced_extensions.insert(extension.id()); - sync_bundle->pending_sync_data.erase(extension.id()); + if (app_sync_bundle_.HandlesApp(extension)) { + app_sync_bundle_.SyncChangeIfNeeded(extension); + } else if (extension_sync_bundle_.HandlesExtension(extension)) { + extension_sync_bundle_.SyncChangeIfNeeded(extension); } } diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h index 14e7412..b24b7bb8 100644 --- a/chrome/browser/extensions/extension_service.h +++ b/chrome/browser/extensions/extension_service.h @@ -23,12 +23,13 @@ #include "base/time.h" #include "base/tuple.h" #include "chrome/browser/extensions/app_shortcut_manager.h" +#include "chrome/browser/extensions/app_sync_bundle.h" #include "chrome/browser/extensions/apps_promo.h" #include "chrome/browser/extensions/extension_icon_manager.h" #include "chrome/browser/extensions/extension_menu_manager.h" #include "chrome/browser/extensions/extension_prefs.h" #include "chrome/browser/extensions/extension_process_manager.h" -#include "chrome/browser/extensions/extension_sync_data.h" +#include "chrome/browser/extensions/extension_sync_bundle.h" #include "chrome/browser/extensions/extension_toolbar_model.h" #include "chrome/browser/extensions/extension_warning_set.h" #include "chrome/browser/extensions/extensions_quota_service.h" @@ -73,7 +74,9 @@ class ExtensionInputMethodEventRouter; namespace extensions { class APIResourceController; +class AppSyncData; class ComponentLoader; +class ExtensionSyncData; class ExtensionUpdater; class SettingsFrontend; class WebNavigationEventRouter; @@ -428,6 +431,30 @@ class ExtensionService const tracked_objects::Location& from_here, const SyncChangeList& change_list) OVERRIDE; + // Gets the sync data for the given extension, assuming that the extension is + // syncable. + extensions::ExtensionSyncData GetExtensionSyncData( + const Extension& extension) const; + + // Gets the sync data for the given app, assuming that the app is + // syncable. + extensions::AppSyncData GetAppSyncData(const Extension& extension) const; + + // Gets the ExtensionSyncData for all extensions. + std::vector<extensions::ExtensionSyncData> GetExtensionSyncDataList() const; + + // Gets the AppSyncData for all extensions. + std::vector<extensions::AppSyncData> GetAppSyncDataList() const; + + // Applies the change specified passed in by either ExtensionSyncData or + // AppSyncData to the current system. + // Returns false if the changes were not completely applied and were added + // to the pending list to be tried again. + bool ProcessExtensionSyncData( + const extensions::ExtensionSyncData& extension_sync_data); + bool ProcessAppSyncData(const extensions::AppSyncData& app_sync_data); + + void set_extensions_enabled(bool enabled) { extensions_enabled_ = enabled; } bool extensions_enabled() { return extensions_enabled_; } @@ -586,23 +613,6 @@ class ExtensionService AppShortcutManager* app_shortcut_manager() { return &app_shortcut_manager_; } private: - // Bundle of type (app or extension)-specific sync stuff. - struct SyncBundle { - SyncBundle(); - ~SyncBundle(); - - void Reset(); - - bool HasExtensionId(const std::string& id) const; - bool HasPendingExtensionId(const std::string& id) const; - - // Note: all members of the struct need to be explicitly cleared in Reset(). - ExtensionFilter filter; - std::set<std::string> synced_extensions; - std::map<std::string, ExtensionSyncData> pending_sync_data; - scoped_ptr<SyncChangeProcessor> sync_processor; - }; - // Contains Extension data that can change during the life of the process, // but does not persist across restarts. struct ExtensionRuntimeData { @@ -632,33 +642,17 @@ class ExtensionService }; typedef std::list<NaClModuleInfo> NaClModuleInfoList; - // Get the appropriate SyncBundle, given some representation of Sync data. - SyncBundle* GetSyncBundleForExtension(const Extension& extension); - SyncBundle* GetSyncBundleForExtensionSyncData( - const ExtensionSyncData& extension_sync_data); - SyncBundle* GetSyncBundleForModelType(syncable::ModelType type); - const SyncBundle* GetSyncBundleForModelTypeConst(syncable::ModelType type) + // Return true if the sync type of |extension| matches |type|. + bool IsCorrectSyncType(const Extension& extension, syncable::ModelType type) const; - // Gets the ExtensionSyncData for all extensions. - std::vector<ExtensionSyncData> GetSyncDataList( - const SyncBundle& bundle) const; - - // Gets the sync data for the given extension, assuming that the extension is - // syncable. - ExtensionSyncData GetSyncData(const Extension& extension) const; - - // Appends sync data objects for every extension in |extensions| - // that passes |filter|. - void GetSyncDataListHelper( - const ExtensionSet& extensions, - const SyncBundle& bundle, - std::vector<ExtensionSyncData>* sync_data_list) const; - - // Applies the change specified in an ExtensionSyncData to the current system. - void ProcessExtensionSyncData( - const ExtensionSyncData& extension_sync_data, - SyncBundle& bundle); + // Handles setting the extension specific values in |extension_sync_data| to + // the current system. + // Returns false if the changes were not completely applied and need to be + // tried again later. + bool ProcessExtensionSyncDataHelper( + const extensions::ExtensionSyncData& extension_sync_data, + syncable::ModelType type); // Look up an extension by ID, optionally including either or both of enabled // and disabled extensions. @@ -828,8 +822,8 @@ class ExtensionService NaClModuleInfoList nacl_module_list_; - SyncBundle app_sync_bundle_; - SyncBundle extension_sync_bundle_; + extensions::AppSyncBundle app_sync_bundle_; + extensions::ExtensionSyncBundle extension_sync_bundle_; // Contains an entry for each warning that shall be currently shown. ExtensionWarningSet extension_warnings_; diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc index 55e4867..a4925b2 100644 --- a/chrome/browser/extensions/extension_service_unittest.cc +++ b/chrome/browser/extensions/extension_service_unittest.cc @@ -27,6 +27,7 @@ #include "base/utf_string_conversions.h" #include "base/version.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/extensions/app_sync_data.h" #include "chrome/browser/extensions/component_loader.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_creator.h" @@ -4008,7 +4009,7 @@ TEST_F(ExtensionServiceTest, GetSyncData) { SyncDataList list = service_->GetAllSyncData(syncable::EXTENSIONS); ASSERT_EQ(list.size(), 1U); - ExtensionSyncData data(list[0]); + extensions::ExtensionSyncData data(list[0]); EXPECT_EQ(extension->id(), data.id()); EXPECT_FALSE(data.uninstalled()); EXPECT_EQ(service_->IsExtensionEnabled(good_crx), data.enabled()); @@ -4031,7 +4032,7 @@ TEST_F(ExtensionServiceTest, GetSyncDataTerminated) { SyncDataList list = service_->GetAllSyncData(syncable::EXTENSIONS); ASSERT_EQ(list.size(), 1U); - ExtensionSyncData data(list[0]); + extensions::ExtensionSyncData data(list[0]); EXPECT_EQ(extension->id(), data.id()); EXPECT_FALSE(data.uninstalled()); EXPECT_EQ(service_->IsExtensionEnabled(good_crx), data.enabled()); @@ -4068,7 +4069,7 @@ TEST_F(ExtensionServiceTest, GetSyncExtensionDataUserSettings) { { SyncDataList list = service_->GetAllSyncData(syncable::EXTENSIONS); ASSERT_EQ(list.size(), 1U); - ExtensionSyncData data(list[0]); + extensions::ExtensionSyncData data(list[0]); EXPECT_TRUE(data.enabled()); EXPECT_FALSE(data.incognito_enabled()); } @@ -4077,7 +4078,7 @@ TEST_F(ExtensionServiceTest, GetSyncExtensionDataUserSettings) { { SyncDataList list = service_->GetAllSyncData(syncable::EXTENSIONS); ASSERT_EQ(list.size(), 1U); - ExtensionSyncData data(list[0]); + extensions::ExtensionSyncData data(list[0]); EXPECT_FALSE(data.enabled()); EXPECT_FALSE(data.incognito_enabled()); } @@ -4086,7 +4087,7 @@ TEST_F(ExtensionServiceTest, GetSyncExtensionDataUserSettings) { { SyncDataList list = service_->GetAllSyncData(syncable::EXTENSIONS); ASSERT_EQ(list.size(), 1U); - ExtensionSyncData data(list[0]); + extensions::ExtensionSyncData data(list[0]); EXPECT_FALSE(data.enabled()); EXPECT_TRUE(data.incognito_enabled()); } @@ -4095,7 +4096,7 @@ TEST_F(ExtensionServiceTest, GetSyncExtensionDataUserSettings) { { SyncDataList list = service_->GetAllSyncData(syncable::EXTENSIONS); ASSERT_EQ(list.size(), 1U); - ExtensionSyncData data(list[0]); + extensions::ExtensionSyncData data(list[0]); EXPECT_TRUE(data.enabled()); EXPECT_TRUE(data.incognito_enabled()); } @@ -4116,9 +4117,10 @@ TEST_F(ExtensionServiceTest, GetSyncAppDataUserSettings) { { SyncDataList list = service_->GetAllSyncData(syncable::APPS); ASSERT_EQ(list.size(), 1U); - ExtensionSyncData data(list[0]); - EXPECT_TRUE(initial_ordinal.Equal(data.app_launch_ordinal())); - EXPECT_TRUE(initial_ordinal.Equal(data.page_ordinal())); + + extensions::AppSyncData app_sync_data(list[0]); + EXPECT_TRUE(initial_ordinal.Equal(app_sync_data.app_launch_ordinal())); + EXPECT_TRUE(initial_ordinal.Equal(app_sync_data.page_ordinal())); } ExtensionSorting* sorting = service_->extension_prefs()->extension_sorting(); @@ -4126,18 +4128,20 @@ TEST_F(ExtensionServiceTest, GetSyncAppDataUserSettings) { { SyncDataList list = service_->GetAllSyncData(syncable::APPS); ASSERT_EQ(list.size(), 1U); - ExtensionSyncData data(list[0]); - EXPECT_TRUE(initial_ordinal.LessThan(data.app_launch_ordinal())); - EXPECT_TRUE(initial_ordinal.Equal(data.page_ordinal())); + + extensions::AppSyncData app_sync_data(list[0]); + EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data.app_launch_ordinal())); + EXPECT_TRUE(initial_ordinal.Equal(app_sync_data.page_ordinal())); } sorting->SetPageOrdinal(app->id(), initial_ordinal.CreateAfter()); { SyncDataList list = service_->GetAllSyncData(syncable::APPS); ASSERT_EQ(list.size(), 1U); - ExtensionSyncData data(list[0]); - EXPECT_TRUE(initial_ordinal.LessThan(data.app_launch_ordinal())); - EXPECT_TRUE(initial_ordinal.LessThan(data.page_ordinal())); + + extensions::AppSyncData app_sync_data(list[0]); + EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data.app_launch_ordinal())); + EXPECT_TRUE(initial_ordinal.LessThan(app_sync_data.page_ordinal())); } } @@ -4161,9 +4165,12 @@ TEST_F(ExtensionServiceTest, GetSyncAppDataUserSettingsOnExtensionMoved) { { SyncDataList list = service_->GetAllSyncData(syncable::APPS); ASSERT_EQ(list.size(), 3U); - ExtensionSyncData data[kAppCount]; + + extensions::AppSyncData data[kAppCount]; for (size_t i = 0; i < kAppCount; ++i) - data[i] = ExtensionSyncData(list[i]); + { + data[i] = extensions::AppSyncData(list[i]); + } // The sync data is not always in the same order our apps were installed in, // so we do that sorting here so we can make sure the values are changed as diff --git a/chrome/browser/extensions/extension_sync_bundle.cc b/chrome/browser/extensions/extension_sync_bundle.cc new file mode 100644 index 0000000..d4f5f5b --- /dev/null +++ b/chrome/browser/extensions/extension_sync_bundle.cc @@ -0,0 +1,161 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/extension_sync_bundle.h" + +#include "base/location.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/extension_sorting.h" +#include "chrome/browser/sync/api/sync_change_processor.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_set.h" + +namespace extensions { + +ExtensionSyncBundle::ExtensionSyncBundle(ExtensionService* extension_service) + : extension_service_(extension_service), sync_processor_(NULL) {} + +ExtensionSyncBundle::~ExtensionSyncBundle() {} + +void ExtensionSyncBundle::SetupSync(SyncChangeProcessor* sync_processor, + const SyncDataList& initial_sync_data) { + sync_processor_.reset(sync_processor); + + for (SyncDataList::const_iterator i = initial_sync_data.begin(); + i != initial_sync_data.end(); + ++i) { + ExtensionSyncData extension_sync_data(*i); + AddExtension(extension_sync_data.id()); + extension_service_->ProcessExtensionSyncData(extension_sync_data); + } +} + +void ExtensionSyncBundle::Reset() { + sync_processor_.reset(); + synced_extensions_.clear(); + pending_sync_data_.clear(); +} + +SyncChange ExtensionSyncBundle::CreateSyncChangeToDelete( + const Extension* extension) const { + extensions::ExtensionSyncData sync_data = + extension_service_->GetExtensionSyncData(*extension); + return sync_data.GetSyncChange(SyncChange::ACTION_DELETE); +} + +void ExtensionSyncBundle::ProcessDeletion(std::string extension_id, + const SyncChange& sync_change) { + RemoveExtension(extension_id); + sync_processor_->ProcessSyncChanges(FROM_HERE, + SyncChangeList(1, sync_change)); +} + +SyncChange ExtensionSyncBundle::CreateSyncChange(const SyncData& sync_data) { + if (HasExtensionId(sync_data.GetTag())) { + return SyncChange(SyncChange::ACTION_UPDATE, sync_data); + } else { + AddExtension(sync_data.GetTag()); + return SyncChange(SyncChange::ACTION_ADD, sync_data); + } +} + +SyncDataList ExtensionSyncBundle::GetAllSyncData() const { + std::vector<ExtensionSyncData> extension_sync_data = + extension_service_->GetExtensionSyncDataList(); + SyncDataList result(extension_sync_data.size()); + for (int i = 0; i < static_cast<int>(extension_sync_data.size()); ++i) { + result[i] = extension_sync_data[i].GetSyncData(); + } + return result; +} + +void ExtensionSyncBundle::SyncChangeIfNeeded(const Extension& extension) { + ExtensionSyncData extension_sync_data = + extension_service_->GetExtensionSyncData(extension); + + SyncChangeList sync_change_list(1, extension_sync_data.GetSyncChange( + HasExtensionId(extension.id()) ? + SyncChange::ACTION_UPDATE : SyncChange::ACTION_ADD)); + sync_processor_->ProcessSyncChanges(FROM_HERE, sync_change_list); + MarkPendingExtensionSynced(extension.id()); +} + +void ExtensionSyncBundle::ProcessSyncChange( + ExtensionSyncData extension_sync_data) { + if (extension_sync_data.uninstalled()) + RemoveExtension(extension_sync_data.id()); + else + AddExtension(extension_sync_data.id()); + extension_service_->ProcessExtensionSyncData(extension_sync_data); +} + +void ExtensionSyncBundle::ProcessSyncChangeList( + SyncChangeList sync_change_list) { + sync_processor_->ProcessSyncChanges(FROM_HERE, sync_change_list); +} + +bool ExtensionSyncBundle::HasExtensionId( + const std::string& id) const { + return synced_extensions_.find(id) != synced_extensions_.end(); +} + +bool ExtensionSyncBundle::HasPendingExtensionId( + const std::string& id) const { + return pending_sync_data_.find(id) != pending_sync_data_.end(); +} + +void ExtensionSyncBundle::AddPendingExtension( + const std::string& id, + const ExtensionSyncData& extension_sync_data) { + pending_sync_data_[id] = extension_sync_data; +} + +bool ExtensionSyncBundle::HandlesExtension(const Extension& extension) const { + return sync_processor_ != NULL && + extension.GetSyncType() == Extension::SYNC_TYPE_EXTENSION; +} + +std::vector<ExtensionSyncData> ExtensionSyncBundle::GetPendingData() const { + std::vector<ExtensionSyncData> pending_extensions; + for (std::map<std::string, ExtensionSyncData>::const_iterator + i = pending_sync_data_.begin(); + i != pending_sync_data_.end(); + ++i) { + pending_extensions.push_back(i->second); + } + + return pending_extensions; +} + +void ExtensionSyncBundle::GetExtensionSyncDataListHelper( + const ExtensionSet& extensions, + std::vector<ExtensionSyncData>* sync_data_list) const { + for (ExtensionSet::const_iterator it = extensions.begin(); + it != extensions.end(); ++it) { + const Extension& extension = **it; + // If we have pending extension data for this extension, then this + // version is out of date. We'll sync back the version we got from + // sync. + if (HandlesExtension(extension) && + !HasPendingExtensionId(extension.id())) { + sync_data_list->push_back( + extension_service_->GetExtensionSyncData(extension)); + } + } +} + +void ExtensionSyncBundle::AddExtension(const std::string& id) { + synced_extensions_.insert(id); +} + +void ExtensionSyncBundle::RemoveExtension(const std::string& id) { + synced_extensions_.erase(id); +} + +void ExtensionSyncBundle::MarkPendingExtensionSynced(const std::string& id) { + pending_sync_data_.erase(id); + synced_extensions_.insert(id); +} + +} // namespace extensions diff --git a/chrome/browser/extensions/extension_sync_bundle.h b/chrome/browser/extensions/extension_sync_bundle.h new file mode 100644 index 0000000..9c79eb8 --- /dev/null +++ b/chrome/browser/extensions/extension_sync_bundle.h @@ -0,0 +1,101 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_SYNC_BUNDLE_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_SYNC_BUNDLE_H_ +#pragma once + +#include <map> +#include <set> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "chrome/browser/extensions/extension_sync_data.h" +#include "chrome/browser/sync/api/syncable_service.h" + +class SyncChangeProcessor; +class Extension; +class ExtensionService; +class ExtensionSet; + +namespace extensions { + +// Bundle of extension specific sync stuff. +class ExtensionSyncBundle { + public: + explicit ExtensionSyncBundle(ExtensionService* extension_service); + ~ExtensionSyncBundle(); + + // Setup this bundle to be sync extension data. + void SetupSync(SyncChangeProcessor* sync_processor, + const SyncDataList& initial_sync_data); + + // Resets this class back to it default values, which will disable all syncing + // until a new sync processor is set. + void Reset(); + + // Returns a SyncChange that will delete the given extension. + SyncChange CreateSyncChangeToDelete(const Extension* extension) const; + + // Process the sync deletion of the given extension. + void ProcessDeletion(std::string extension_id, const SyncChange& sync_change); + + // Create a sync change based on |sync_data|. + SyncChange CreateSyncChange(const SyncData& sync_data); + + // Get all the sync data contained in this bundle. + SyncDataList GetAllSyncData() const; + + // Process the given sync change and apply it. + void ProcessSyncChange(ExtensionSyncData extension_sync_data); + + // Sync a newly-installed extension or change an existing one. + void SyncChangeIfNeeded(const Extension& extension); + + // Process the list of sync changes. + void ProcessSyncChangeList(SyncChangeList sync_change_list); + + // Check to see if the given |id| is either synced or pending to be synced. + bool HasExtensionId(const std::string& id) const; + bool HasPendingExtensionId(const std::string& id) const; + + // Add a pending extension to be synced. + void AddPendingExtension(const std::string& id, + const ExtensionSyncData& extension_sync_data); + + // Returns true if |extension| should be handled by this sync bundle. + bool HandlesExtension(const Extension& extension) const; + + // Returns a vector of all the pending sync data. + std::vector<ExtensionSyncData> GetPendingData() const; + + // Appends sync data objects for every extension in |extensions|. + void GetExtensionSyncDataListHelper( + const ExtensionSet& extensions, + std::vector<extensions::ExtensionSyncData>* sync_data_list) const; + + private: + // Add a synced extension. + void AddExtension(const std::string& id); + + // Remove a synced extension. + void RemoveExtension(const std::string& id); + + // Change an extension from being pending to synced. + void MarkPendingExtensionSynced(const std::string& id); + + ExtensionService* extension_service_; // Owns us. + scoped_ptr<SyncChangeProcessor> sync_processor_; + + std::set<std::string> synced_extensions_; + std::map<std::string, ExtensionSyncData> pending_sync_data_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionSyncBundle); +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_SYNC_BUNDLE_H_ diff --git a/chrome/browser/extensions/extension_sync_data.cc b/chrome/browser/extensions/extension_sync_data.cc index c2095ad..52d54a1 100644 --- a/chrome/browser/extensions/extension_sync_data.cc +++ b/chrome/browser/extensions/extension_sync_data.cc @@ -5,102 +5,52 @@ #include "chrome/browser/extensions/extension_sync_data.h" #include "base/logging.h" +#include "chrome/browser/extensions/app_sync_data.h" #include "chrome/browser/extensions/extension_service.h" -#include "sync/protocol/app_specifics.pb.h" +#include "chrome/browser/sync/api/sync_data.h" +#include "chrome/common/extensions/extension.h" #include "sync/protocol/extension_specifics.pb.h" #include "sync/protocol/sync.pb.h" +namespace extensions { + ExtensionSyncData::ExtensionSyncData() : uninstalled_(false), enabled_(false), - incognito_enabled_(false), - type_(Extension::SYNC_TYPE_NONE), - notifications_disabled_(false) { + incognito_enabled_(false) { } ExtensionSyncData::ExtensionSyncData(const SyncData& sync_data) : uninstalled_(false), enabled_(false), - incognito_enabled_(false), - type_(Extension::SYNC_TYPE_NONE), - notifications_disabled_(false) { + incognito_enabled_(false) { PopulateFromSyncData(sync_data); } ExtensionSyncData::ExtensionSyncData(const SyncChange& sync_change) : uninstalled_(sync_change.change_type() == SyncChange::ACTION_DELETE), enabled_(false), - incognito_enabled_(false), - type_(Extension::SYNC_TYPE_NONE), - notifications_disabled_(false) { + incognito_enabled_(false) { PopulateFromSyncData(sync_change.sync_data()); } ExtensionSyncData::ExtensionSyncData(const Extension& extension, bool enabled, - bool incognito_enabled, - const std::string& notifications_client_id, - bool notifications_disabled, - const StringOrdinal& app_launch_ordinal, - const StringOrdinal& page_ordinal) - : id_(extension.id()), - uninstalled_(false), - enabled_(enabled), - incognito_enabled_(incognito_enabled), - type_(extension.GetSyncType()), - version_(*extension.version()), - update_url_(extension.update_url()), - name_(extension.name()), - notifications_client_id_(notifications_client_id), - notifications_disabled_(notifications_disabled), - app_launch_ordinal_(app_launch_ordinal), - page_ordinal_(page_ordinal) { + bool incognito_enabled) + : id_(extension.id()), + uninstalled_(false), + enabled_(enabled), + incognito_enabled_(incognito_enabled), + version_(*extension.version()), + update_url_(extension.update_url()), + name_(extension.name()) { } ExtensionSyncData::~ExtensionSyncData() {} -void ExtensionSyncData::PopulateAppSpecifics( - sync_pb::AppSpecifics* specifics) const { - DCHECK(specifics); - sync_pb::AppNotificationSettings* notif_settings = - specifics->mutable_notification_settings(); - if (!notifications_client_id_.empty()) - notif_settings->set_oauth_client_id(notifications_client_id_); - notif_settings->set_disabled(notifications_disabled_); - - // Only sync the ordinal values if they are valid. - if (app_launch_ordinal_.IsValid()) - specifics->set_app_launch_ordinal(app_launch_ordinal_.ToString()); - if (page_ordinal_.IsValid()) - specifics->set_page_ordinal(page_ordinal_.ToString()); - - PopulateExtensionSpecifics(specifics->mutable_extension()); -} - -void ExtensionSyncData::PopulateExtensionSpecifics( - sync_pb::ExtensionSpecifics* specifics) const { - DCHECK(Extension::IdIsValid(id_)); - specifics->set_id(id_); - specifics->set_update_url(update_url_.spec()); - specifics->set_version(version_.GetString()); - specifics->set_enabled(enabled_); - specifics->set_incognito_enabled(incognito_enabled_); - specifics->set_name(name_); -} - SyncData ExtensionSyncData::GetSyncData() const { sync_pb::EntitySpecifics specifics; - - switch (type_) { - case Extension::SYNC_TYPE_EXTENSION: - PopulateExtensionSpecifics(specifics.mutable_extension()); - break; - case Extension::SYNC_TYPE_APP: - PopulateAppSpecifics(specifics.mutable_app()); - break; - default: - LOG(FATAL) << "Attempt to get non-syncable data."; - } + PopulateExtensionSpecifics(specifics.mutable_extension()); return SyncData::CreateLocalData(id_, name_, specifics); } @@ -110,23 +60,15 @@ SyncChange ExtensionSyncData::GetSyncChange( return SyncChange(change_type, GetSyncData()); } -void ExtensionSyncData::PopulateFromAppSpecifics( - const sync_pb::AppSpecifics& specifics) { - PopulateFromExtensionSpecifics(specifics.extension()); - - if (specifics.has_notification_settings() && - specifics.notification_settings().has_oauth_client_id()) { - notifications_client_id_ = - specifics.notification_settings().oauth_client_id(); - } - - notifications_disabled_ = - specifics.has_notification_settings() && - specifics.notification_settings().has_disabled() && - specifics.notification_settings().disabled(); - - app_launch_ordinal_ = StringOrdinal(specifics.app_launch_ordinal()); - page_ordinal_ = StringOrdinal(specifics.page_ordinal()); +void ExtensionSyncData::PopulateExtensionSpecifics( + sync_pb::ExtensionSpecifics* specifics) const { + DCHECK(Extension::IdIsValid(id_)); + specifics->set_id(id_); + specifics->set_update_url(update_url_.spec()); + specifics->set_version(version_.GetString()); + specifics->set_enabled(enabled_); + specifics->set_incognito_enabled(incognito_enabled_); + specifics->set_name(name_); } void ExtensionSyncData::PopulateFromExtensionSpecifics( @@ -153,16 +95,18 @@ void ExtensionSyncData::PopulateFromExtensionSpecifics( name_ = specifics.name(); } +void ExtensionSyncData::set_uninstalled(bool uninstalled) { + uninstalled_ = uninstalled; +} + void ExtensionSyncData::PopulateFromSyncData(const SyncData& sync_data) { const sync_pb::EntitySpecifics& entity_specifics = sync_data.GetSpecifics(); if (entity_specifics.has_extension()) { PopulateFromExtensionSpecifics(entity_specifics.extension()); - type_ = Extension::SYNC_TYPE_EXTENSION; - } else if (entity_specifics.has_app()) { - PopulateFromAppSpecifics(entity_specifics.app()); - type_ = Extension::SYNC_TYPE_APP; } else { LOG(FATAL) << "Attempt to sync bad EntitySpecifics."; } } + +} // namespace extensions diff --git a/chrome/browser/extensions/extension_sync_data.h b/chrome/browser/extensions/extension_sync_data.h index a9b07af..cdd56ed 100644 --- a/chrome/browser/extensions/extension_sync_data.h +++ b/chrome/browser/extensions/extension_sync_data.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -10,19 +10,17 @@ #include "base/version.h" #include "chrome/browser/sync/api/sync_change.h" -#include "chrome/browser/sync/api/sync_data.h" -#include "chrome/common/extensions/extension.h" #include "chrome/common/string_ordinal.h" #include "googleurl/src/gurl.h" +class Extension; class SyncData; + namespace sync_pb { -class AppSpecifics; class ExtensionSpecifics; } -// TODO(csharp): Split this class up into AppSyncData and ExtensionsSyncData. -// crbug.com/107729 +namespace extensions { // A class that encapsulates the synced properties of an Extension. class ExtensionSyncData { @@ -32,19 +30,22 @@ class ExtensionSyncData { explicit ExtensionSyncData(const SyncChange& sync_change); ExtensionSyncData(const Extension& extension, bool enabled, - bool incognito_enabled, - const std::string& notifications_client_id, - bool notifications_disabled, - const StringOrdinal& app_launch_ordinal, - const StringOrdinal& page_ordinal); + bool incognito_enabled); ~ExtensionSyncData(); - // Convert an ExtensionSyncData back out to a sync structure. - void PopulateAppSpecifics(sync_pb::AppSpecifics* specifics) const; - void PopulateExtensionSpecifics(sync_pb::ExtensionSpecifics* specifics) const; + // Retrieve sync data from this class. SyncData GetSyncData() const; SyncChange GetSyncChange(SyncChange::SyncChangeType change_type) const; + // Convert an ExtensionSyncData back out to a sync structure. + void PopulateExtensionSpecifics(sync_pb::ExtensionSpecifics* specifics) const; + + // Populate this class from sync inputs. + void PopulateFromExtensionSpecifics( + const sync_pb::ExtensionSpecifics& specifics); + + void set_uninstalled(bool uninstalled); + const std::string& id() const { return id_; } // Version-independent properties (i.e., used even when the @@ -53,11 +54,6 @@ class ExtensionSyncData { bool uninstalled() const { return uninstalled_; } bool enabled() const { return enabled_; } bool incognito_enabled() const { return incognito_enabled_; } - Extension::SyncType type() const { return type_; } - // These ordinals aren't necessarily valid. - const StringOrdinal& app_launch_ordinal() const { - return app_launch_ordinal_; } - const StringOrdinal& page_ordinal() const {return page_ordinal_; } // Version-dependent properties (i.e., should be used only when the // version of the currenty-installed extension matches |version|). @@ -66,33 +62,19 @@ class ExtensionSyncData { // Used only for debugging. const std::string& name() const { return name_; } - const std::string& notifications_client_id() const { - return notifications_client_id_; - } - - bool notifications_disabled() const { - return notifications_disabled_; - } - private: - void PopulateFromAppSpecifics( - const sync_pb::AppSpecifics& specifics); - void PopulateFromExtensionSpecifics( - const sync_pb::ExtensionSpecifics& specifics); + // Populate this class from sync inputs. void PopulateFromSyncData(const SyncData& sync_data); std::string id_; bool uninstalled_; bool enabled_; bool incognito_enabled_; - Extension::SyncType type_; Version version_; GURL update_url_; std::string name_; - std::string notifications_client_id_; - bool notifications_disabled_; - StringOrdinal app_launch_ordinal_; - StringOrdinal page_ordinal_; }; +} // namespace extensions + #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_SYNC_DATA_H_ diff --git a/chrome/browser/extensions/extension_sync_data_unittest.cc b/chrome/browser/extensions/extension_sync_data_unittest.cc index b269137..e92b74f 100644 --- a/chrome/browser/extensions/extension_sync_data_unittest.cc +++ b/chrome/browser/extensions/extension_sync_data_unittest.cc @@ -4,10 +4,10 @@ #include "chrome/browser/extensions/extension_sync_data.h" +#include "base/file_path.h" #include "base/memory/scoped_ptr.h" #include "base/version.h" #include "googleurl/src/gurl.h" -#include "sync/protocol/app_specifics.pb.h" #include "sync/protocol/extension_specifics.pb.h" #include "sync/protocol/sync.pb.h" #include "testing/gtest/include/gtest/gtest.h" @@ -31,7 +31,6 @@ const char kValidUpdateUrl2[] = "https://clients2.google.com/service/update2/crx"; const char kName[] = "MyExtension"; const char kName2[] = "MyExtension2"; -const char kOAuthClientId[] = "1234abcd"; class ExtensionSyncDataTest : public testing::Test { }; @@ -48,7 +47,7 @@ TEST_F(ExtensionSyncDataTest, SyncDataToExtensionSyncDataForExtension) { SyncData sync_data = SyncData::CreateLocalData("sync_tag", "non_unique_title", entity); - ExtensionSyncData extension_sync_data(sync_data); + extensions::ExtensionSyncData extension_sync_data(sync_data); EXPECT_EQ(extension_specifics->id(), extension_sync_data.id()); EXPECT_EQ(extension_specifics->version(), extension_sync_data.version().GetString()); @@ -72,7 +71,7 @@ TEST_F(ExtensionSyncDataTest, ExtensionSyncDataToSyncDataForExtension) { input_extension->set_name(kName); SyncData sync_data = SyncData::CreateLocalData("sync_tag", "non_unique_title", entity); - ExtensionSyncData extension_sync_data(sync_data); + extensions::ExtensionSyncData extension_sync_data(sync_data); SyncData output_sync_data = extension_sync_data.GetSyncData(); const sync_pb::ExtensionSpecifics& output_specifics = @@ -88,109 +87,4 @@ TEST_F(ExtensionSyncDataTest, ExtensionSyncDataToSyncDataForExtension) { EXPECT_EQ(extension_sync_data.name(), output_specifics.name()); } -TEST_F(ExtensionSyncDataTest, SyncDataToExtensionSyncDataForApp) { - sync_pb::EntitySpecifics entity; - sync_pb::AppSpecifics* app_specifics = entity.mutable_app(); - app_specifics->set_app_launch_ordinal( - StringOrdinal::CreateInitialOrdinal().ToString()); - app_specifics->set_page_ordinal( - StringOrdinal::CreateInitialOrdinal().ToString()); - - sync_pb::ExtensionSpecifics* extension_specifics = - app_specifics->mutable_extension(); - extension_specifics->set_id(kValidId); - extension_specifics->set_update_url(kValidUpdateUrl2); - extension_specifics->set_enabled(false); - extension_specifics->set_incognito_enabled(true); - extension_specifics->set_version(kVersion1); - extension_specifics->set_name(kName); - sync_pb::AppNotificationSettings* notif_settings = - app_specifics->mutable_notification_settings(); - notif_settings->set_oauth_client_id(kOAuthClientId); - notif_settings->set_disabled(true); - SyncData sync_data = - SyncData::CreateLocalData("sync_tag", "non_unique_title", entity); - - ExtensionSyncData extension_sync_data(sync_data); - EXPECT_EQ(app_specifics->app_launch_ordinal(), - extension_sync_data.app_launch_ordinal().ToString()); - EXPECT_EQ(app_specifics->page_ordinal(), - extension_sync_data.page_ordinal().ToString()); - EXPECT_EQ(extension_specifics->id(), extension_sync_data.id()); - EXPECT_EQ(extension_specifics->version(), - extension_sync_data.version().GetString()); - EXPECT_EQ(extension_specifics->update_url(), - extension_sync_data.update_url().spec()); - EXPECT_EQ(extension_specifics->enabled(), extension_sync_data.enabled()); - EXPECT_EQ(extension_specifics->incognito_enabled(), - extension_sync_data.incognito_enabled()); - EXPECT_EQ(extension_specifics->name(), extension_sync_data.name()); - EXPECT_FALSE(extension_sync_data.uninstalled()); - EXPECT_EQ(notif_settings->oauth_client_id(), - extension_sync_data.notifications_client_id()); - EXPECT_EQ(notif_settings->disabled(), - extension_sync_data.notifications_disabled()); -} - -TEST_F(ExtensionSyncDataTest, ExtensionSyncDataToSyncDataForApp) { - sync_pb::EntitySpecifics entity; - sync_pb::AppSpecifics* input_specifics = entity.mutable_app(); - input_specifics->set_app_launch_ordinal( - StringOrdinal::CreateInitialOrdinal().ToString()); - input_specifics->set_page_ordinal( - StringOrdinal::CreateInitialOrdinal().ToString()); - - sync_pb::ExtensionSpecifics* input_extension = - input_specifics->mutable_extension(); - input_extension->set_id(kValidId); - input_extension->set_update_url(kValidUpdateUrl2); - input_extension->set_enabled(true); - input_extension->set_incognito_enabled(false); - input_extension->set_version(kVersion1); - input_extension->set_name(kName); - sync_pb::AppNotificationSettings* notif_settings = - input_specifics->mutable_notification_settings(); - notif_settings->set_oauth_client_id(kOAuthClientId); - notif_settings->set_disabled(true); - SyncData sync_data = - SyncData::CreateLocalData("sync_tag", "non_unique_title", entity); - ExtensionSyncData extension_sync_data(sync_data); - - SyncData output_sync_data = extension_sync_data.GetSyncData(); - EXPECT_TRUE(sync_data.GetSpecifics().has_app()); - const sync_pb::AppSpecifics& output_specifics = - output_sync_data.GetSpecifics().app(); - EXPECT_EQ(input_specifics->SerializeAsString(), - output_specifics.SerializeAsString()); -} - -// Ensures that invalid StringOrdinals don't break ExtensionSyncData. -TEST_F(ExtensionSyncDataTest, ExtensionSyncDataInvalidOrdinal) { - sync_pb::EntitySpecifics entity; - sync_pb::AppSpecifics* app_specifics = entity.mutable_app(); - // Set the ordinals as invalid. - app_specifics->set_app_launch_ordinal(""); - app_specifics->set_page_ordinal(""); - - sync_pb::ExtensionSpecifics* extension_specifics = - app_specifics->mutable_extension(); - extension_specifics->set_id(kValidId); - extension_specifics->set_update_url(kValidUpdateUrl2); - extension_specifics->set_enabled(false); - extension_specifics->set_incognito_enabled(true); - extension_specifics->set_version(kVersion1); - extension_specifics->set_name(kName); - sync_pb::AppNotificationSettings* notif_settings = - app_specifics->mutable_notification_settings(); - notif_settings->set_oauth_client_id(kOAuthClientId); - notif_settings->set_disabled(true); - SyncData sync_data = - SyncData::CreateLocalData("sync_tag", "non_unique_title", entity); - - ExtensionSyncData extension_sync_data(sync_data); - - // Try loading the synced data back out, there should be no problems. - extension_sync_data.PopulateAppSpecifics(app_specifics); -} - } // namespace |