summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorskrul@chromium.org <skrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-14 20:31:25 +0000
committerskrul@chromium.org <skrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-14 20:31:25 +0000
commit76353a19f68031f9364c647f74c02deb957cdeed (patch)
treef0cc06c605e23e403fd33615d7003188f5284ae2
parent923f3e2a704f61e3155c4e5555197962d50b854e (diff)
downloadchromium_src-76353a19f68031f9364c647f74c02deb957cdeed.zip
chromium_src-76353a19f68031f9364c647f74c02deb957cdeed.tar.gz
chromium_src-76353a19f68031f9364c647f74c02deb957cdeed.tar.bz2
Revert "Revert 48932 - Merge certain preferences during model association."
This reverts commit 392d1efa36fba717950cbfec40055939493a27b2. Review URL: http://codereview.chromium.org/2676007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@49720 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/sync/abstract_profile_sync_service_test.h125
-rw-r--r--chrome/browser/sync/glue/preference_change_processor.cc54
-rw-r--r--chrome/browser/sync/glue/preference_change_processor.h3
-rw-r--r--chrome/browser/sync/glue/preference_model_associator.cc128
-rw-r--r--chrome/browser/sync/glue/preference_model_associator.h22
-rw-r--r--chrome/browser/sync/glue/preference_model_associator_unittest.cc282
-rw-r--r--chrome/browser/sync/profile_sync_service_autofill_unittest.cc301
-rw-r--r--chrome/browser/sync/profile_sync_service_preference_unittest.cc372
-rwxr-xr-xchrome/chrome_tests.gypi2
9 files changed, 1003 insertions, 286 deletions
diff --git a/chrome/browser/sync/abstract_profile_sync_service_test.h b/chrome/browser/sync/abstract_profile_sync_service_test.h
new file mode 100644
index 0000000..7554528
--- /dev/null
+++ b/chrome/browser/sync/abstract_profile_sync_service_test.h
@@ -0,0 +1,125 @@
+// Copyright (c) 2010 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_SYNC_ABSTRACT_PROFILE_SYNC_SERVICE_TEST_H_
+#define CHROME_BROWSER_SYNC_ABSTRACT_PROFILE_SYNC_SERVICE_TEST_H_
+
+#include <string>
+
+#include "base/message_loop.h"
+#include "base/scoped_ptr.h"
+#include "base/task.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/sync/engine/syncapi.h"
+#include "chrome/browser/sync/glue/autofill_model_associator.h"
+#include "chrome/browser/sync/glue/preference_model_associator.h"
+#include "chrome/browser/sync/glue/sync_backend_host_mock.h"
+#include "chrome/browser/sync/profile_sync_factory_mock.h"
+#include "chrome/browser/sync/protocol/sync.pb.h"
+#include "chrome/browser/sync/syncable/directory_manager.h"
+#include "chrome/browser/sync/syncable/model_type.h"
+#include "chrome/browser/sync/syncable/syncable.h"
+#include "chrome/browser/sync/test_profile_sync_service.h"
+#include "chrome/test/profile_mock.h"
+#include "chrome/test/sync/engine/test_id_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using browser_sync::SyncBackendHostMock;
+using browser_sync::TestIdFactory;
+using sync_api::UserShare;
+using syncable::BASE_VERSION;
+using syncable::CREATE;
+using syncable::DirectoryManager;
+using syncable::ID;
+using syncable::IS_DEL;
+using syncable::IS_DIR;
+using syncable::IS_UNAPPLIED_UPDATE;
+using syncable::IS_UNSYNCED;
+using syncable::ModelType;
+using syncable::MutableEntry;
+using syncable::SERVER_IS_DIR;
+using syncable::SERVER_VERSION;
+using syncable::SPECIFICS;
+using syncable::ScopedDirLookup;
+using syncable::UNIQUE_SERVER_TAG;
+using syncable::UNITTEST;
+using syncable::WriteTransaction;
+
+class AbstractProfileSyncServiceTest : public testing::Test {
+ protected:
+ AbstractProfileSyncServiceTest()
+ : ui_thread_(ChromeThread::UI, &message_loop_) {}
+
+ bool CreateRoot(ModelType model_type) {
+ UserShare* user_share = service_->backend()->GetUserShareHandle();
+ DirectoryManager* dir_manager = user_share->dir_manager.get();
+
+ ScopedDirLookup dir(dir_manager, user_share->authenticated_name);
+ if (!dir.good())
+ return false;
+
+ std::string tag_name;
+ switch (model_type) {
+ case syncable::AUTOFILL:
+ tag_name = browser_sync::kAutofillTag;
+ break;
+ case syncable::PREFERENCES:
+ tag_name = browser_sync::kPreferencesTag;
+ break;
+ default:
+ return false;
+ }
+
+ WriteTransaction wtrans(dir, UNITTEST, __FILE__, __LINE__);
+ MutableEntry node(&wtrans,
+ CREATE,
+ wtrans.root_id(),
+ tag_name);
+ node.Put(UNIQUE_SERVER_TAG, tag_name);
+ node.Put(IS_DIR, true);
+ node.Put(SERVER_IS_DIR, false);
+ node.Put(IS_UNSYNCED, false);
+ node.Put(IS_UNAPPLIED_UPDATE, false);
+ node.Put(SERVER_VERSION, 20);
+ node.Put(BASE_VERSION, 20);
+ node.Put(IS_DEL, false);
+ node.Put(ID, ids_.MakeServer(tag_name));
+ sync_pb::EntitySpecifics specifics;
+ syncable::AddDefaultExtensionValue(model_type, &specifics);
+ node.Put(SPECIFICS, specifics);
+
+ return true;
+ }
+
+ friend class CreateRootTask;
+
+ MessageLoopForUI message_loop_;
+ ChromeThread ui_thread_;
+ ProfileSyncFactoryMock factory_;
+ ProfileSyncServiceObserverMock observer_;
+ SyncBackendHostMock backend_;
+ scoped_ptr<TestProfileSyncService> service_;
+ TestIdFactory ids_;
+};
+
+class CreateRootTask : public Task {
+ public:
+ explicit CreateRootTask(AbstractProfileSyncServiceTest* test,
+ ModelType model_type)
+ : test_(test), model_type_(model_type), success_(false) {
+ }
+
+ virtual void Run() {
+ success_ = test_->CreateRoot(model_type_);
+ }
+
+ bool success() { return success_; }
+
+ private:
+ AbstractProfileSyncServiceTest* test_;
+ ModelType model_type_;
+ bool success_;
+};
+
+#endif // CHROME_BROWSER_SYNC_ABSTRACT_PROFILE_SYNC_SERVICE_TEST_H_
diff --git a/chrome/browser/sync/glue/preference_change_processor.cc b/chrome/browser/sync/glue/preference_change_processor.cc
index 8e11f9d..a379052 100644
--- a/chrome/browser/sync/glue/preference_change_processor.cc
+++ b/chrome/browser/sync/glue/preference_change_processor.cc
@@ -48,7 +48,7 @@ void PreferenceChangeProcessor::Observe(NotificationType type,
pref_service_->FindPreference((*name).c_str());
DCHECK(preference);
- // TODO (mnissler) Detect preference->IsManaged() state changes here and call
+ // TODO(mnissler): Detect preference->IsManaged() state changes here and call
// into PreferenceModelAssociator to associate/disassociate sync nodes when
// the state changes.
@@ -59,11 +59,26 @@ void PreferenceChangeProcessor::Observe(NotificationType type,
sync_api::WriteTransaction trans(share_handle());
sync_api::WriteNode node(&trans);
+ // Since we don't create sync nodes for preferences that still have
+ // their default values, this changed preference may not have a sync
+ // node yet. If not, create it.
int64 sync_id = model_associator_->GetSyncIdFromChromeId(*name);
if (sync_api::kInvalidId == sync_id) {
- std::wstring err = L"Unexpected notification for: " + *name;
- error_handler()->OnUnrecoverableError(FROM_HERE, WideToUTF8(err));
- return;
+ sync_api::ReadNode root(&trans);
+ if (!root.InitByTagLookup(browser_sync::kPreferencesTag)) {
+ error_handler()->OnUnrecoverableError(FROM_HERE, "Can't find root.");
+ return;
+ }
+
+ std::string tag = WideToUTF8(*name);
+ if (!node.InitUniqueByCreation(syncable::PREFERENCES, root, tag)) {
+ error_handler()->OnUnrecoverableError(
+ FROM_HERE,
+ "Failed to create preference sync node.");
+ return;
+ }
+
+ model_associator_->Associate(preference, node.GetId());
} else {
if (!node.InitByIdLookup(sync_id)) {
error_handler()->OnUnrecoverableError(FROM_HERE,
@@ -72,7 +87,7 @@ void PreferenceChangeProcessor::Observe(NotificationType type,
}
}
- if (!WritePreference(&node, *name, preference->GetValue())) {
+ if (!PreferenceModelAssociator::WritePreferenceToNode(*preference, &node)) {
error_handler()->OnUnrecoverableError(FROM_HERE,
"Failed to update preference node.");
return;
@@ -135,6 +150,15 @@ void PreferenceChangeProcessor::ApplyChangesFromSyncModel(
pref_service_->ClearPref(pref_name);
} else {
pref_service_->Set(pref_name, *value);
+
+ // If this is a newly added node, associate.
+ if (sync_api::SyncManager::ChangeRecord::ACTION_ADD ==
+ changes[i].action) {
+ const PrefService::Preference* preference =
+ pref_service_->FindPreference(name.c_str());
+ model_associator_->Associate(preference, changes[i].id);
+ }
+
if (0 == name.compare(prefs::kShowBookmarkBar)) {
// If it was the bookmark bar, send an additional notification.
NotificationService::current()->Notify(
@@ -147,26 +171,6 @@ void PreferenceChangeProcessor::ApplyChangesFromSyncModel(
StartObserving();
}
-bool PreferenceChangeProcessor::WritePreference(
- sync_api::WriteNode* node,
- const std::wstring& name,
- const Value* value) {
- std::string serialized;
- JSONStringValueSerializer json(&serialized);
- if (!json.Serialize(*value)) {
- error_handler()->OnUnrecoverableError(FROM_HERE,
- "Failed to serialize preference value.");
- return false;
- }
-
- sync_pb::PreferenceSpecifics preference;
- preference.set_name(WideToUTF8(name));
- preference.set_value(serialized);
- node->SetPreferenceSpecifics(preference);
- node->SetTitle(name);
- return true;
-}
-
Value* PreferenceChangeProcessor::ReadPreference(
sync_api::ReadNode* node,
std::wstring* name) {
diff --git a/chrome/browser/sync/glue/preference_change_processor.h b/chrome/browser/sync/glue/preference_change_processor.h
index 10f16bcb..b604c96 100644
--- a/chrome/browser/sync/glue/preference_change_processor.h
+++ b/chrome/browser/sync/glue/preference_change_processor.h
@@ -46,9 +46,6 @@ class PreferenceChangeProcessor : public ChangeProcessor,
virtual void StopImpl();
private:
- bool WritePreference(sync_api::WriteNode* node,
- const std::wstring& name,
- const Value* value);
Value* ReadPreference(sync_api::ReadNode* node, std::wstring* name);
void StartObserving();
diff --git a/chrome/browser/sync/glue/preference_model_associator.cc b/chrome/browser/sync/glue/preference_model_associator.cc
index 03794a3..2314824 100644
--- a/chrome/browser/sync/glue/preference_model_associator.cc
+++ b/chrome/browser/sync/glue/preference_model_associator.cc
@@ -16,6 +16,7 @@
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/protocol/preference_specifics.pb.h"
#include "chrome/common/json_value_serializer.h"
+#include "chrome/common/pref_names.h"
namespace browser_sync {
@@ -69,7 +70,7 @@ bool PreferenceModelAssociator::AssociateModels() {
pref_service->FindPreference((*it).c_str());
DCHECK(pref);
- sync_api::ReadNode node(&trans);
+ sync_api::WriteNode node(&trans);
if (node.InitByClientTagLookup(syncable::PREFERENCES, tag)) {
const sync_pb::PreferenceSpecifics& preference(
node.GetPreferenceSpecifics());
@@ -85,32 +86,36 @@ bool PreferenceModelAssociator::AssociateModels() {
return false;
}
- // Update the local preference based on what we got from the sync
- // server.
+ // Merge the server value of this preference with the local value.
+ bool node_needs_update = MergePreference(*pref, value.get());
+
+ // Update the local preference based on what we got from the
+ // sync server.
pref_service->Set(pref_name.c_str(), *value);
+
+ // If the merge resulted in an updated value, write it back to
+ // the sync node.
+ if (node_needs_update && !WritePreferenceToNode(*pref, &node))
+ return false;
}
Associate(pref, node.GetId());
} else if (!pref->IsManaged()) {
- sync_api::WriteNode node(&trans);
- if (!node.InitUniqueByCreation(syncable::PREFERENCES, root, tag)) {
+ // If there is no server value for this preference and it is
+ // currently its default value, don't create a new server node.
+ if (pref->IsDefaultValue())
+ continue;
+
+ sync_api::WriteNode write_node(&trans);
+ if (!write_node.InitUniqueByCreation(syncable::PREFERENCES, root, tag)) {
LOG(ERROR) << "Failed to create preference sync node.";
return false;
}
// Update the sync node with the local value for this preference.
- std::string serialized;
- JSONStringValueSerializer json(&serialized);
- if (!json.Serialize(*(pref->GetValue()))) {
- LOG(ERROR) << "Failed to serialize preference value.";
+ if (!WritePreferenceToNode(*pref, &write_node))
return false;
- }
- sync_pb::PreferenceSpecifics preference;
- preference.set_name(tag);
- preference.set_value(serialized);
- node.SetPreferenceSpecifics(preference);
- node.SetTitle(*it);
- Associate(pref, node.GetId());
+ Associate(pref, write_node.GetId());
}
}
return true;
@@ -192,4 +197,95 @@ bool PreferenceModelAssociator::GetSyncIdForTaggedNode(const std::string& tag,
return true;
}
+bool PreferenceModelAssociator::MergePreference(
+ const PrefService::Preference& local_pref,
+ Value* server_value) {
+
+ if (local_pref.name() == prefs::kURLsToRestoreOnStartup ||
+ local_pref.name() == prefs::kDesktopNotificationAllowedOrigins ||
+ local_pref.name() == prefs::kDesktopNotificationDeniedOrigins) {
+ return MergeListValues(*local_pref.GetValue(), server_value);
+ }
+
+ if (local_pref.name() == prefs::kContentSettingsPatterns ||
+ local_pref.name() == prefs::kGeolocationContentSettings) {
+ return MergeDictionaryValues(*local_pref.GetValue(), server_value);
+ }
+ return false;
+}
+
+bool PreferenceModelAssociator::WritePreferenceToNode(
+ const PrefService::Preference& pref,
+ sync_api::WriteNode* node) {
+ std::string serialized;
+ JSONStringValueSerializer json(&serialized);
+ if (!json.Serialize(*pref.GetValue())) {
+ LOG(ERROR) << "Failed to serialize preference value.";
+ return false;
+ }
+
+ sync_pb::PreferenceSpecifics preference;
+ preference.set_name(WideToUTF8(pref.name()));
+ preference.set_value(serialized);
+ node->SetPreferenceSpecifics(preference);
+ node->SetTitle(pref.name());
+ return true;
+}
+
+bool PreferenceModelAssociator::MergeListValues(const Value& from_value,
+ Value* to_value) {
+ if (from_value.GetType() == Value::TYPE_NULL)
+ return false;
+ bool to_changed = false;
+
+ DCHECK(from_value.GetType() == Value::TYPE_LIST);
+ DCHECK(to_value->GetType() == Value::TYPE_LIST);
+ const ListValue& from_list_value = static_cast<const ListValue&>(from_value);
+ ListValue* to_list_value = static_cast<ListValue*>(to_value);
+
+ for (ListValue::const_iterator i = from_list_value.begin();
+ i != from_list_value.end(); ++i) {
+ Value* value = (*i)->DeepCopy();
+ if (to_list_value->AppendIfNotPresent(value)) {
+ to_changed = true;
+ } else {
+ delete value;
+ }
+ }
+ return to_changed;
+}
+
+bool PreferenceModelAssociator::MergeDictionaryValues(const Value& from_value,
+ Value* to_value) {
+ if (from_value.GetType() == Value::TYPE_NULL)
+ return false;
+ bool to_changed = false;
+
+ DCHECK(from_value.GetType() == Value::TYPE_DICTIONARY);
+ DCHECK(to_value->GetType() == Value::TYPE_DICTIONARY);
+ const DictionaryValue& from_dict_value =
+ static_cast<const DictionaryValue&>(from_value);
+ DictionaryValue* to_dict_value = static_cast<DictionaryValue*>(to_value);
+
+ for (DictionaryValue::key_iterator key = from_dict_value.begin_keys();
+ key != from_dict_value.end_keys(); ++key) {
+ Value* from_value;
+ bool success = from_dict_value.GetWithoutPathExpansion(*key, &from_value);
+ DCHECK(success);
+
+ Value* to_value;
+ if (to_dict_value->GetWithoutPathExpansion(*key, &to_value)) {
+ if (to_value->GetType() == Value::TYPE_DICTIONARY) {
+ to_changed = MergeDictionaryValues(*from_value, to_value);
+ }
+ // Note that for all other types we want to preserve the "to"
+ // values so we do nothing here.
+ } else {
+ to_dict_value->SetWithoutPathExpansion(*key, from_value->DeepCopy());
+ to_changed = true;
+ }
+ }
+ return to_changed;
+}
+
} // namespace browser_sync
diff --git a/chrome/browser/sync/glue/preference_model_associator.h b/chrome/browser/sync/glue/preference_model_associator.h
index 89f2fb9..cbf890e 100644
--- a/chrome/browser/sync/glue/preference_model_associator.h
+++ b/chrome/browser/sync/glue/preference_model_associator.h
@@ -16,6 +16,11 @@
#include "chrome/browser/sync/unrecoverable_error_handler.h"
class ProfileSyncService;
+class Value;
+
+namespace sync_api {
+class WriteNode;
+}
namespace browser_sync {
@@ -86,6 +91,20 @@ class PreferenceModelAssociator
// |sync_id| with that node's id.
virtual bool GetSyncIdForTaggedNode(const std::string& tag, int64* sync_id);
+ // Merges the value of local_pref into the supplies server_value.
+ // If there is a conflict, the server value always takes precedence.
+ // The method returns true if server_value was modified. Note that
+ // only certain preferences are allowed to be merged, see the
+ // method's implementation for details.
+ static bool MergePreference(const PrefService::Preference& local_pref,
+ Value* server_value);
+
+ // Writes the value of pref into the specified node. Returns true
+ // upon success.
+ static bool WritePreferenceToNode(const PrefService::Preference& pref,
+ sync_api::WriteNode* node);
+
+ protected:
// Returns sync service instance.
ProfileSyncService* sync_service() { return sync_service_; }
@@ -93,6 +112,9 @@ class PreferenceModelAssociator
typedef std::map<std::wstring, int64> PreferenceNameToSyncIdMap;
typedef std::map<int64, std::wstring> SyncIdToPreferenceNameMap;
+ static bool MergeListValues(const Value& from_value, Value* to_value);
+ static bool MergeDictionaryValues(const Value& from_value, Value* to_value);
+
ProfileSyncService* sync_service_;
std::set<std::wstring> synced_preferences_;
int64 preferences_node_id_;
diff --git a/chrome/browser/sync/glue/preference_model_associator_unittest.cc b/chrome/browser/sync/glue/preference_model_associator_unittest.cc
new file mode 100644
index 0000000..e8f87f6
--- /dev/null
+++ b/chrome/browser/sync/glue/preference_model_associator_unittest.cc
@@ -0,0 +1,282 @@
+// Copyright (c) 2010 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 "base/scoped_ptr.h"
+#include "base/values.h"
+#include "chrome/browser/sync/glue/preference_model_associator.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/testing_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using browser_sync::PreferenceModelAssociator;
+
+class AbstractPreferenceMergeTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ pref_service_ = profile_.GetPrefs();
+ }
+
+ void SetContentPattern(DictionaryValue* patterns_dict,
+ const std::wstring& expression,
+ const std::wstring& content_type,
+ int setting) {
+ DictionaryValue* expression_dict;
+ bool found =
+ patterns_dict->GetDictionaryWithoutPathExpansion(expression,
+ &expression_dict);
+ if (!found) {
+ expression_dict = new DictionaryValue;
+ patterns_dict->SetWithoutPathExpansion(expression, expression_dict);
+ }
+ expression_dict->SetWithoutPathExpansion(
+ content_type,
+ Value::CreateIntegerValue(setting));
+ }
+
+ TestingProfile profile_;
+ PrefService* pref_service_;
+};
+
+class ListPreferenceMergeTest : public AbstractPreferenceMergeTest {
+ protected:
+ ListPreferenceMergeTest() :
+ server_url0_(L"http://example.com/server0"),
+ server_url1_(L"http://example.com/server1"),
+ local_url0_(L"http://example.com/local0"),
+ local_url1_(L"http://example.com/local1") {}
+
+ virtual void SetUp() {
+ AbstractPreferenceMergeTest::SetUp();
+ server_url_list_.Append(Value::CreateStringValue(server_url0_));
+ server_url_list_.Append(Value::CreateStringValue(server_url1_));
+ }
+
+ std::wstring server_url0_;
+ std::wstring server_url1_;
+ std::wstring local_url0_;
+ std::wstring local_url1_;
+ ListValue server_url_list_;
+};
+
+TEST_F(ListPreferenceMergeTest, LocalNull) {
+ const PrefService::Preference* pref =
+ pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup);
+ scoped_ptr<Value> original(server_url_list_.DeepCopy());
+ EXPECT_FALSE(PreferenceModelAssociator::MergePreference(*pref,
+ &server_url_list_));
+ EXPECT_TRUE(server_url_list_.Equals(original.get()));
+}
+
+TEST_F(ListPreferenceMergeTest, Merge) {
+ ListValue* local_list_value =
+ pref_service_->GetMutableList(prefs::kURLsToRestoreOnStartup);
+ local_list_value->Append(Value::CreateStringValue(local_url0_));
+ local_list_value->Append(Value::CreateStringValue(local_url1_));
+
+ const PrefService::Preference* pref =
+ pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup);
+ EXPECT_TRUE(PreferenceModelAssociator::MergePreference(*pref,
+ &server_url_list_));
+
+ ListValue expected;
+ expected.Append(Value::CreateStringValue(server_url0_));
+ expected.Append(Value::CreateStringValue(server_url1_));
+ expected.Append(Value::CreateStringValue(local_url0_));
+ expected.Append(Value::CreateStringValue(local_url1_));
+ EXPECT_TRUE(server_url_list_.Equals(&expected));
+}
+
+TEST_F(ListPreferenceMergeTest, Duplicates) {
+ ListValue* local_list_value =
+ pref_service_->GetMutableList(prefs::kURLsToRestoreOnStartup);
+ local_list_value->Append(Value::CreateStringValue(local_url0_));
+ local_list_value->Append(Value::CreateStringValue(server_url0_));
+ local_list_value->Append(Value::CreateStringValue(server_url1_));
+
+ const PrefService::Preference* pref =
+ pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup);
+ EXPECT_TRUE(PreferenceModelAssociator::MergePreference(*pref,
+ &server_url_list_));
+
+ ListValue expected;
+ expected.Append(Value::CreateStringValue(server_url0_));
+ expected.Append(Value::CreateStringValue(server_url1_));
+ expected.Append(Value::CreateStringValue(local_url0_));
+ EXPECT_TRUE(server_url_list_.Equals(&expected));
+}
+
+TEST_F(ListPreferenceMergeTest, Equals) {
+ ListValue* local_list_value =
+ pref_service_->GetMutableList(prefs::kURLsToRestoreOnStartup);
+ local_list_value->Append(Value::CreateStringValue(server_url0_));
+ local_list_value->Append(Value::CreateStringValue(server_url1_));
+
+ scoped_ptr<Value> original(server_url_list_.DeepCopy());
+ const PrefService::Preference* pref =
+ pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup);
+ EXPECT_FALSE(PreferenceModelAssociator::MergePreference(*pref,
+ &server_url_list_));
+ EXPECT_TRUE(server_url_list_.Equals(original.get()));
+}
+
+class DictionaryPreferenceMergeTest : public AbstractPreferenceMergeTest {
+ protected:
+ DictionaryPreferenceMergeTest() :
+ expression0_(L"expression0"),
+ expression1_(L"expression1"),
+ expression2_(L"expression2"),
+ content_type0_(L"content_type0"),
+ content_type1_(L"content_type1") {}
+
+ virtual void SetUp() {
+ AbstractPreferenceMergeTest::SetUp();
+ SetContentPattern(&server_patterns_, expression0_, content_type0_, 1);
+ SetContentPattern(&server_patterns_, expression0_, content_type1_, 2);
+ SetContentPattern(&server_patterns_, expression1_, content_type0_, 1);
+ }
+
+ std::wstring expression0_;
+ std::wstring expression1_;
+ std::wstring expression2_;
+ std::wstring content_type0_;
+ std::wstring content_type1_;
+ DictionaryValue server_patterns_;
+};
+
+TEST_F(DictionaryPreferenceMergeTest, LocalNull) {
+ scoped_ptr<Value> original(server_patterns_.DeepCopy());
+ EXPECT_FALSE(PreferenceModelAssociator::MergePreference(
+ *pref_service_->FindPreference(prefs::kContentSettingsPatterns),
+ &server_patterns_));
+ EXPECT_TRUE(server_patterns_.Equals(original.get()));
+}
+
+TEST_F(DictionaryPreferenceMergeTest, MergeNoConflicts) {
+ DictionaryValue* local_dict_value =
+ pref_service_->GetMutableDictionary(prefs::kContentSettingsPatterns);
+ SetContentPattern(local_dict_value, expression2_, content_type0_, 1);
+
+ EXPECT_TRUE(PreferenceModelAssociator::MergePreference(
+ *pref_service_->FindPreference(prefs::kContentSettingsPatterns),
+ &server_patterns_));
+
+ DictionaryValue expected;
+ SetContentPattern(&expected, expression0_, content_type0_, 1);
+ SetContentPattern(&expected, expression0_, content_type1_, 2);
+ SetContentPattern(&expected, expression1_, content_type0_, 1);
+ SetContentPattern(&expected, expression2_, content_type0_, 1);
+ EXPECT_TRUE(server_patterns_.Equals(&expected));
+}
+
+TEST_F(DictionaryPreferenceMergeTest, MergeConflicts) {
+ DictionaryValue* local_dict_value =
+ pref_service_->GetMutableDictionary(prefs::kContentSettingsPatterns);
+ SetContentPattern(local_dict_value, expression0_, content_type0_, 2);
+ SetContentPattern(local_dict_value, expression1_, content_type0_, 1);
+ SetContentPattern(local_dict_value, expression1_, content_type1_, 1);
+ SetContentPattern(local_dict_value, expression2_, content_type0_, 2);
+
+ EXPECT_TRUE(PreferenceModelAssociator::MergePreference(
+ *pref_service_->FindPreference(prefs::kContentSettingsPatterns),
+ &server_patterns_));
+
+ DictionaryValue expected;
+ SetContentPattern(&expected, expression0_, content_type0_, 1);
+ SetContentPattern(&expected, expression0_, content_type1_, 2);
+ SetContentPattern(&expected, expression1_, content_type0_, 1);
+ SetContentPattern(&expected, expression1_, content_type1_, 1);
+ SetContentPattern(&expected, expression2_, content_type0_, 2);
+ EXPECT_TRUE(server_patterns_.Equals(&expected));
+}
+
+TEST_F(DictionaryPreferenceMergeTest, Equal) {
+ DictionaryValue* local_dict_value =
+ pref_service_->GetMutableDictionary(prefs::kContentSettingsPatterns);
+ SetContentPattern(local_dict_value, expression0_, content_type0_, 1);
+ SetContentPattern(local_dict_value, expression0_, content_type1_, 2);
+ SetContentPattern(local_dict_value, expression1_, content_type0_, 1);
+
+ scoped_ptr<Value> original(server_patterns_.DeepCopy());
+ EXPECT_FALSE(PreferenceModelAssociator::MergePreference(
+ *pref_service_->FindPreference(prefs::kContentSettingsPatterns),
+ &server_patterns_));
+ EXPECT_TRUE(server_patterns_.Equals(original.get()));
+}
+
+TEST_F(DictionaryPreferenceMergeTest, ConflictButServerWins) {
+ DictionaryValue* local_dict_value =
+ pref_service_->GetMutableDictionary(prefs::kContentSettingsPatterns);
+ SetContentPattern(local_dict_value, expression0_, content_type0_, 2);
+ SetContentPattern(local_dict_value, expression0_, content_type1_, 2);
+ SetContentPattern(local_dict_value, expression1_, content_type0_, 1);
+
+ scoped_ptr<Value> original(server_patterns_.DeepCopy());
+ EXPECT_FALSE(PreferenceModelAssociator::MergePreference(
+ *pref_service_->FindPreference(prefs::kContentSettingsPatterns),
+ &server_patterns_));
+ EXPECT_TRUE(server_patterns_.Equals(original.get()));
+}
+
+class IndividualPreferenceMergeTest : public AbstractPreferenceMergeTest {
+ protected:
+ IndividualPreferenceMergeTest() :
+ url0_(L"http://example.com/server0"),
+ url1_(L"http://example.com/server1"),
+ expression0_(L"expression0"),
+ expression1_(L"expression1"),
+ content_type0_(L"content_type0") {}
+
+ virtual void SetUp() {
+ AbstractPreferenceMergeTest::SetUp();
+ server_url_list_.Append(Value::CreateStringValue(url0_));
+ SetContentPattern(&server_patterns_, expression0_, content_type0_, 1);
+ }
+
+ bool MergeListPreference(const wchar_t* pref) {
+ ListValue* local_list_value = pref_service_->GetMutableList(pref);
+ local_list_value->Append(Value::CreateStringValue(url1_));
+
+ return PreferenceModelAssociator::MergePreference(
+ *pref_service_->FindPreference(pref),
+ &server_url_list_);
+ }
+
+ bool MergeDictionaryPreference(const wchar_t* pref) {
+ DictionaryValue* local_dict_value =
+ pref_service_->GetMutableDictionary(pref);
+ SetContentPattern(local_dict_value, expression1_, content_type0_, 1);
+
+ return PreferenceModelAssociator::MergePreference(
+ *pref_service_->FindPreference(pref),
+ &server_patterns_);
+ }
+
+ std::wstring url0_;
+ std::wstring url1_;
+ std::wstring expression0_;
+ std::wstring expression1_;
+ std::wstring content_type0_;
+ ListValue server_url_list_;
+ DictionaryValue server_patterns_;
+};
+
+TEST_F(IndividualPreferenceMergeTest, URLsToRestoreOnStartup) {
+ EXPECT_TRUE(MergeListPreference(prefs::kURLsToRestoreOnStartup));
+}
+
+TEST_F(IndividualPreferenceMergeTest, DesktopNotificationAllowedOrigins) {
+ EXPECT_TRUE(MergeListPreference(prefs::kDesktopNotificationAllowedOrigins));
+}
+
+TEST_F(IndividualPreferenceMergeTest, DesktopNotificationDeniedOrigins) {
+ EXPECT_TRUE(MergeListPreference(prefs::kDesktopNotificationDeniedOrigins));
+}
+
+TEST_F(IndividualPreferenceMergeTest, ContentSettingsPatterns) {
+ EXPECT_TRUE(MergeDictionaryPreference(prefs::kContentSettingsPatterns));
+}
+
+TEST_F(IndividualPreferenceMergeTest, GeolocationContentSettings) {
+ EXPECT_TRUE(MergeDictionaryPreference(prefs::kGeolocationContentSettings));
+}
diff --git a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
index 4ca8e6e..21a7b07 100644
--- a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
@@ -8,32 +8,31 @@
#include "testing/gtest/include/gtest/gtest.h"
+#include "base/message_loop.h"
#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
#include "base/string16.h"
#include "base/task.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "base/waitable_event.h"
#include "chrome/browser/autofill/autofill_common_unittest.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/sync/abstract_profile_sync_service_test.h"
#include "chrome/browser/sync/engine/syncapi.h"
#include "chrome/browser/sync/glue/autofill_change_processor.h"
#include "chrome/browser/sync/glue/autofill_data_type_controller.h"
#include "chrome/browser/sync/glue/autofill_model_associator.h"
-#include "chrome/browser/sync/glue/sync_backend_host_mock.h"
#include "chrome/browser/sync/profile_sync_factory.h"
-#include "chrome/browser/sync/profile_sync_factory_mock.h"
#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/profile_sync_test_util.h"
-#include "chrome/browser/sync/test_profile_sync_service.h"
#include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
-#include "chrome/browser/sync/syncable/directory_manager.h"
+#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/test_profile_sync_service.h"
#include "chrome/browser/webdata/autofill_change.h"
#include "chrome/browser/webdata/autofill_entry.h"
#include "chrome/browser/webdata/web_database.h"
#include "chrome/common/notification_source.h"
#include "chrome/common/notification_type.h"
-#include "chrome/test/sync/engine/test_id_factory.h"
#include "chrome/test/profile_mock.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -42,26 +41,6 @@ using base::WaitableEvent;
using browser_sync::AutofillChangeProcessor;
using browser_sync::AutofillDataTypeController;
using browser_sync::AutofillModelAssociator;
-using browser_sync::SyncBackendHostMock;
-using browser_sync::TestIdFactory;
-using browser_sync::UnrecoverableErrorHandler;
-using sync_api::SyncManager;
-using sync_api::UserShare;
-using syncable::BASE_VERSION;
-using syncable::CREATE;
-using syncable::DirectoryManager;
-using syncable::ID;
-using syncable::IS_DEL;
-using syncable::IS_DIR;
-using syncable::IS_UNAPPLIED_UPDATE;
-using syncable::IS_UNSYNCED;
-using syncable::MutableEntry;
-using syncable::SERVER_IS_DIR;
-using syncable::SERVER_VERSION;
-using syncable::SPECIFICS;
-using syncable::ScopedDirLookup;
-using syncable::UNIQUE_SERVER_TAG;
-using syncable::UNITTEST;
using syncable::WriteTransaction;
using testing::_;
using testing::DoAll;
@@ -120,7 +99,9 @@ class PersonalDataManagerMock: public PersonalDataManager {
};
ACTION_P4(MakeAutofillSyncComponents, service, wd, pdm, dtc) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::DB));
+ EXPECT_TRUE(ChromeThread::CurrentlyOn(ChromeThread::DB));
+ if (!ChromeThread::CurrentlyOn(ChromeThread::DB))
+ return ProfileSyncFactory::SyncComponents(NULL, NULL);
AutofillModelAssociator* model_associator =
new AutofillModelAssociator(service, wd, pdm);
AutofillChangeProcessor* change_processor =
@@ -129,16 +110,16 @@ ACTION_P4(MakeAutofillSyncComponents, service, wd, pdm, dtc) {
change_processor);
}
-class ProfileSyncServiceAutofillTest : public testing::Test {
+class ProfileSyncServiceAutofillTest : public AbstractProfileSyncServiceTest {
protected:
- ProfileSyncServiceAutofillTest()
- : ui_thread_(ChromeThread::UI, &message_loop_),
- db_thread_(ChromeThread::DB) {
+ ProfileSyncServiceAutofillTest() : db_thread_(ChromeThread::DB) {
}
virtual void SetUp() {
web_data_service_ = new WebDataServiceFake(&web_database_);
personal_data_manager_ = new PersonalDataManagerMock();
+ EXPECT_CALL(*personal_data_manager_, LoadProfiles()).Times(1);
+ EXPECT_CALL(*personal_data_manager_, LoadCreditCards()).Times(1);
personal_data_manager_->Init(&profile_);
db_thread_.Start();
@@ -153,7 +134,7 @@ class ProfileSyncServiceAutofillTest : public testing::Test {
MessageLoop::current()->RunAllPending();
}
- void StartSyncService(Task* task) {
+ void StartSyncService(Task* task, bool will_fail_association) {
if (!service_.get()) {
service_.reset(
new TestProfileSyncService(&factory_, &profile_, false, false));
@@ -177,9 +158,17 @@ class ProfileSyncServiceAutofillTest : public testing::Test {
EXPECT_CALL(profile_, GetPersonalDataManager()).
WillRepeatedly(Return(personal_data_manager_.get()));
- EXPECT_CALL(*(personal_data_manager_.get()), IsDataLoaded()).
+ EXPECT_CALL(*personal_data_manager_, IsDataLoaded()).
WillRepeatedly(Return(true));
+ EXPECT_CALL(backend_, RequestPause()).Times(1);
+ EXPECT_CALL(backend_, ConfigureDataTypes(_, _)).Times(1);
+ if (will_fail_association) {
+ EXPECT_CALL(backend_, RequestResume()).Times(0);
+ } else {
+ EXPECT_CALL(backend_, RequestResume()).Times(1);
+ }
+
// State changes once for the backend init and once for startup done.
EXPECT_CALL(observer_, OnStateChanged()).
WillOnce(InvokeTask(task)).
@@ -191,74 +180,53 @@ class ProfileSyncServiceAutofillTest : public testing::Test {
}
}
- void CreateAutofillRoot() {
- UserShare* user_share = service_->backend()->GetUserShareHandle();
- DirectoryManager* dir_manager = user_share->dir_manager.get();
-
- ScopedDirLookup dir(dir_manager, user_share->authenticated_name);
- ASSERT_TRUE(dir.good());
-
- WriteTransaction wtrans(dir, UNITTEST, __FILE__, __LINE__);
- MutableEntry node(&wtrans,
- CREATE,
- wtrans.root_id(),
- browser_sync::kAutofillTag);
- node.Put(UNIQUE_SERVER_TAG, browser_sync::kAutofillTag);
- node.Put(IS_DIR, true);
- node.Put(SERVER_IS_DIR, false);
- node.Put(IS_UNSYNCED, false);
- node.Put(IS_UNAPPLIED_UPDATE, false);
- node.Put(SERVER_VERSION, 20);
- node.Put(BASE_VERSION, 20);
- node.Put(IS_DEL, false);
- node.Put(ID, ids_.MakeServer(browser_sync::kAutofillTag));
- sync_pb::EntitySpecifics specifics;
- specifics.MutableExtension(sync_pb::autofill);
- node.Put(SPECIFICS, specifics);
- }
-
- void AddAutofillSyncNode(const AutofillEntry& entry) {
+ bool AddAutofillSyncNode(const AutofillEntry& entry) {
sync_api::WriteTransaction trans(
service_->backend()->GetUserShareHandle());
sync_api::ReadNode autofill_root(&trans);
- ASSERT_TRUE(autofill_root.InitByTagLookup(browser_sync::kAutofillTag));
+ if (!autofill_root.InitByTagLookup(browser_sync::kAutofillTag))
+ return false;
sync_api::WriteNode node(&trans);
std::string tag = AutofillModelAssociator::KeyToTag(entry.key().name(),
entry.key().value());
- ASSERT_TRUE(node.InitUniqueByCreation(syncable::AUTOFILL,
- autofill_root,
- tag));
+ if (!node.InitUniqueByCreation(syncable::AUTOFILL, autofill_root, tag))
+ return false;
+
AutofillChangeProcessor::WriteAutofillEntry(entry, &node);
+ return true;
}
- void AddAutofillProfileSyncNode(const AutoFillProfile& profile) {
+ bool AddAutofillProfileSyncNode(const AutoFillProfile& profile) {
sync_api::WriteTransaction trans(
service_->backend()->GetUserShareHandle());
sync_api::ReadNode autofill_root(&trans);
- ASSERT_TRUE(autofill_root.InitByTagLookup(browser_sync::kAutofillTag));
+ if (!autofill_root.InitByTagLookup(browser_sync::kAutofillTag))
+ return false;
sync_api::WriteNode node(&trans);
std::string tag = AutofillModelAssociator::ProfileLabelToTag(
profile.Label());
- ASSERT_TRUE(node.InitUniqueByCreation(syncable::AUTOFILL,
- autofill_root,
- tag));
+ if (!node.InitUniqueByCreation(syncable::AUTOFILL, autofill_root, tag))
+ return false;
AutofillChangeProcessor::WriteAutofillProfile(profile, &node);
sync_pb::AutofillSpecifics s(node.GetAutofillSpecifics());
s.mutable_profile()->set_label(UTF16ToUTF8(profile.Label()));
node.SetAutofillSpecifics(s);
+ return true;
}
- void GetAutofillEntriesFromSyncDB(std::vector<AutofillEntry>* entries,
+ bool GetAutofillEntriesFromSyncDB(std::vector<AutofillEntry>* entries,
std::vector<AutoFillProfile>* profiles) {
sync_api::ReadTransaction trans(service_->backend()->GetUserShareHandle());
sync_api::ReadNode autofill_root(&trans);
- ASSERT_TRUE(autofill_root.InitByTagLookup(browser_sync::kAutofillTag));
+ if (!autofill_root.InitByTagLookup(browser_sync::kAutofillTag))
+ return false;
int64 child_id = autofill_root.GetFirstChildId();
while (child_id != sync_api::kInvalidId) {
sync_api::ReadNode child_node(&trans);
- ASSERT_TRUE(child_node.InitByIdLookup(child_id));
+ if (!child_node.InitByIdLookup(child_id))
+ return false;
const sync_pb::AutofillSpecifics& autofill(
child_node.GetAutofillSpecifics());
@@ -280,6 +248,7 @@ class ProfileSyncServiceAutofillTest : public testing::Test {
}
child_id = child_node.GetSuccessorId();
}
+ return true;
}
void SetIdleChangeProcessorExpectations() {
@@ -307,38 +276,15 @@ class ProfileSyncServiceAutofillTest : public testing::Test {
return MakeAutofillEntry(name, value, timestamp, -1);
}
- friend class CreateAutofillRootTask;
friend class AddAutofillEntriesTask;
- MessageLoopForUI message_loop_;
- ChromeThread ui_thread_;
ChromeThread db_thread_;
scoped_refptr<ThreadNotificationService> notification_service_;
- scoped_ptr<TestProfileSyncService> service_;
ProfileMock profile_;
- ProfileSyncFactoryMock factory_;
- ProfileSyncServiceObserverMock observer_;
- SyncBackendHostMock backend_;
WebDatabaseMock web_database_;
scoped_refptr<WebDataService> web_data_service_;
scoped_refptr<PersonalDataManagerMock> personal_data_manager_;
-
- TestIdFactory ids_;
-};
-
-class CreateAutofillRootTask : public Task {
- public:
- explicit CreateAutofillRootTask(ProfileSyncServiceAutofillTest* test)
- : test_(test) {
- }
-
- virtual void Run() {
- test_->CreateAutofillRoot();
- }
-
- private:
- ProfileSyncServiceAutofillTest* test_;
};
class AddAutofillEntriesTask : public Task {
@@ -346,24 +292,30 @@ class AddAutofillEntriesTask : public Task {
AddAutofillEntriesTask(ProfileSyncServiceAutofillTest* test,
const std::vector<AutofillEntry>& entries,
const std::vector<AutoFillProfile>& profiles)
- : test_(test), entries_(entries), profiles_(profiles) {
+ : test_(test), entries_(entries), profiles_(profiles), success_(false) {
}
virtual void Run() {
- test_->CreateAutofillRoot();
+ if (!test_->CreateRoot(syncable::AUTOFILL))
+ return;
for (size_t i = 0; i < entries_.size(); ++i) {
- test_->AddAutofillSyncNode(entries_[i]);
+ if (!test_->AddAutofillSyncNode(entries_[i]))
+ return;
}
for (size_t i = 0; i < profiles_.size(); ++i) {
- test_->AddAutofillProfileSyncNode(profiles_[i]);
+ if (!test_->AddAutofillProfileSyncNode(profiles_[i]))
+ return;
}
-
+ success_ = true;
}
+ bool success() { return success_; }
+
private:
ProfileSyncServiceAutofillTest* test_;
const std::vector<AutofillEntry>& entries_;
const std::vector<AutoFillProfile>& profiles_;
+ bool success_;
};
// TODO(skrul): Test abort startup.
@@ -371,12 +323,8 @@ class AddAutofillEntriesTask : public Task {
// TODO(tim): Add autofill data type controller test, and a case to cover
// waiting for the PersonalDataManager.
TEST_F(ProfileSyncServiceAutofillTest, FailModelAssociation) {
- // Backend will be paused but not resumed.
- EXPECT_CALL(backend_, RequestPause()).
- WillOnce(testing::DoAll(Notify(NotificationType::SYNC_PAUSED),
- testing::Return(true)));
// Don't create the root autofill node so startup fails.
- StartSyncService(NULL);
+ StartSyncService(NULL, true);
EXPECT_TRUE(service_->unrecoverable_error_detected());
}
@@ -384,11 +332,12 @@ TEST_F(ProfileSyncServiceAutofillTest, EmptyNativeEmptySync) {
EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true));
EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
SetIdleChangeProcessorExpectations();
- CreateAutofillRootTask task(this);
- StartSyncService(&task);
+ CreateRootTask task(this, syncable::AUTOFILL);
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
std::vector<AutofillEntry> sync_entries;
std::vector<AutoFillProfile> sync_profiles;
- GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles));
EXPECT_EQ(0U, sync_entries.size());
EXPECT_EQ(0U, sync_profiles.size());
}
@@ -400,11 +349,12 @@ TEST_F(ProfileSyncServiceAutofillTest, HasNativeEntriesEmptySync) {
WillOnce(DoAll(SetArgumentPointee<0>(entries), Return(true)));
EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
SetIdleChangeProcessorExpectations();
- CreateAutofillRootTask task(this);
- StartSyncService(&task);
+ CreateRootTask task(this, syncable::AUTOFILL);
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
std::vector<AutofillEntry> sync_entries;
std::vector<AutoFillProfile> sync_profiles;
- GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles));
ASSERT_EQ(1U, entries.size());
EXPECT_TRUE(entries[0] == sync_entries[0]);
EXPECT_EQ(0U, sync_profiles.size());
@@ -428,13 +378,14 @@ TEST_F(ProfileSyncServiceAutofillTest, HasMixedNativeEmptySync) {
expected_profiles.push_back(*profile0);
EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).
WillOnce(DoAll(SetArgumentPointee<0>(profiles), Return(true)));
- EXPECT_CALL(*(personal_data_manager_.get()), Refresh());
+ EXPECT_CALL(*personal_data_manager_, Refresh());
SetIdleChangeProcessorExpectations();
- CreateAutofillRootTask task(this);
- StartSyncService(&task);
+ CreateRootTask task(this, syncable::AUTOFILL);
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
std::vector<AutofillEntry> sync_entries;
std::vector<AutoFillProfile> sync_profiles;
- GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles));
ASSERT_EQ(1U, entries.size());
EXPECT_TRUE(entries[0] == sync_entries[0]);
EXPECT_EQ(1U, sync_profiles.size());
@@ -489,7 +440,7 @@ TEST_F(ProfileSyncServiceAutofillTest, HasDuplicateProfileLabelsEmptySync) {
expected_profiles.push_back(*profile1);
AutoFillProfile relabelled_profile;
EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true));
- EXPECT_CALL(*(personal_data_manager_.get()), Refresh());
+ EXPECT_CALL(*personal_data_manager_, Refresh());
EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).
WillOnce(DoAll(SetArgumentPointee<0>(profiles), Return(true)));
EXPECT_CALL(web_database_, UpdateAutoFillProfile(
@@ -497,11 +448,12 @@ TEST_F(ProfileSyncServiceAutofillTest, HasDuplicateProfileLabelsEmptySync) {
WillOnce(DoAll(SaveArg<0>(&relabelled_profile), Return(true)));
SetIdleChangeProcessorExpectations();
- CreateAutofillRootTask task(this);
- StartSyncService(&task);
+ CreateRootTask task(this, syncable::AUTOFILL);
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
std::vector<AutofillEntry> sync_entries;
std::vector<AutoFillProfile> sync_profiles;
- GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles));
EXPECT_EQ(0U, sync_entries.size());
EXPECT_EQ(2U, sync_profiles.size());
EXPECT_EQ(expected_profiles[0], sync_profiles[1]);
@@ -521,11 +473,12 @@ TEST_F(ProfileSyncServiceAutofillTest, HasNativeWithDuplicatesEmptySync) {
WillOnce(DoAll(SetArgumentPointee<0>(entries), Return(true)));
EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
SetIdleChangeProcessorExpectations();
- CreateAutofillRootTask task(this);
- StartSyncService(&task);
+ CreateRootTask task(this, syncable::AUTOFILL);
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
std::vector<AutofillEntry> sync_entries;
std::vector<AutoFillProfile> sync_profiles;
- GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&sync_entries, &sync_profiles));
EXPECT_EQ(2U, sync_entries.size());
}
@@ -569,8 +522,9 @@ TEST_F(ProfileSyncServiceAutofillTest, HasNativeHasSyncNoMerge) {
WillOnce(Return(true));
EXPECT_CALL(web_database_, AddAutoFillProfile(Eq(to_be_added))).
WillOnce(Return(true));
- EXPECT_CALL(*(personal_data_manager_.get()), Refresh());
- StartSyncService(&task);
+ EXPECT_CALL(*personal_data_manager_, Refresh());
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
std::set<AutofillEntry> expected_entries;
expected_entries.insert(native_entry);
@@ -578,7 +532,8 @@ TEST_F(ProfileSyncServiceAutofillTest, HasNativeHasSyncNoMerge) {
std::vector<AutofillEntry> new_sync_entries;
std::vector<AutoFillProfile> new_sync_profiles;
- GetAutofillEntriesFromSyncDB(&new_sync_entries, &new_sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
+ &new_sync_profiles));
std::set<AutofillEntry> new_sync_entries_set(new_sync_entries.begin(),
new_sync_entries.end());
@@ -606,11 +561,13 @@ TEST_F(ProfileSyncServiceAutofillTest, HasNativeHasSyncMergeEntry) {
EXPECT_CALL(web_database_, UpdateAutofillEntries(ElementsAre(merged_entry))).
WillOnce(Return(true));
- StartSyncService(&task);
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
std::vector<AutofillEntry> new_sync_entries;
std::vector<AutoFillProfile> new_sync_profiles;
- GetAutofillEntriesFromSyncDB(&new_sync_entries, &new_sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
+ &new_sync_profiles));
ASSERT_EQ(1U, new_sync_entries.size());
EXPECT_TRUE(merged_entry == new_sync_entries[0]);
}
@@ -641,12 +598,14 @@ TEST_F(ProfileSyncServiceAutofillTest, HasNativeHasSyncMergeProfile) {
EXPECT_CALL(web_database_, UpdateAutoFillProfile(Eq(sync_profile))).
WillOnce(Return(true));
- EXPECT_CALL(*(personal_data_manager_.get()), Refresh());
- StartSyncService(&task);
+ EXPECT_CALL(*personal_data_manager_, Refresh());
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
std::vector<AutofillEntry> new_sync_entries;
std::vector<AutoFillProfile> new_sync_profiles;
- GetAutofillEntriesFromSyncDB(&new_sync_entries, &new_sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
+ &new_sync_profiles));
ASSERT_EQ(1U, new_sync_profiles.size());
EXPECT_TRUE(sync_profile == new_sync_profiles[0]);
}
@@ -655,8 +614,9 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeAddEntry) {
EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true));
EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
SetIdleChangeProcessorExpectations();
- CreateAutofillRootTask task(this);
- StartSyncService(&task);
+ CreateRootTask task(this, syncable::AUTOFILL);
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
AutofillEntry added_entry(MakeAutofillEntry("added", "entry", 1));
std::vector<base::Time> timestamps(added_entry.timestamps());
@@ -673,7 +633,8 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeAddEntry) {
std::vector<AutofillEntry> new_sync_entries;
std::vector<AutoFillProfile> new_sync_profiles;
- GetAutofillEntriesFromSyncDB(&new_sync_entries, &new_sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
+ &new_sync_profiles));
ASSERT_EQ(1U, new_sync_entries.size());
EXPECT_TRUE(added_entry == new_sync_entries[0]);
}
@@ -682,8 +643,9 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeAddProfile) {
EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true));
EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
SetIdleChangeProcessorExpectations();
- CreateAutofillRootTask task(this);
- StartSyncService(&task);
+ CreateRootTask task(this, syncable::AUTOFILL);
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
AutoFillProfile added_profile(string16(), 0);
autofill_unittest::SetProfileInfo(&added_profile,
@@ -700,7 +662,8 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeAddProfile) {
std::vector<AutofillEntry> new_sync_entries;
std::vector<AutoFillProfile> new_sync_profiles;
- GetAutofillEntriesFromSyncDB(&new_sync_entries, &new_sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
+ &new_sync_profiles));
ASSERT_EQ(1U, new_sync_profiles.size());
EXPECT_TRUE(added_profile == new_sync_profiles[0]);
}
@@ -723,7 +686,8 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeAddProfileConflict) {
EXPECT_CALL(web_database_, AddAutoFillProfile(Eq(sync_profile))).
WillOnce(Return(true));
SetIdleChangeProcessorExpectations();
- StartSyncService(&task);
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
AutoFillProfile added_profile(string16(), 0);
autofill_unittest::SetProfileInfo(&added_profile,
@@ -738,7 +702,7 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeAddProfileConflict) {
EXPECT_CALL(web_database_, UpdateAutoFillProfile(
ProfileMatchesExceptLabel(added_profile))).
WillOnce(DoAll(SaveArg<0>(&relabelled_profile), Return(true)));
- EXPECT_CALL(*(personal_data_manager_.get()), Refresh());
+ EXPECT_CALL(*personal_data_manager_, Refresh());
scoped_refptr<ThreadNotifier> notifier = new ThreadNotifier(&db_thread_);
notifier->Notify(NotificationType::AUTOFILL_PROFILE_CHANGED,
@@ -747,7 +711,8 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeAddProfileConflict) {
std::vector<AutofillEntry> new_sync_entries;
std::vector<AutoFillProfile> new_sync_profiles;
- GetAutofillEntriesFromSyncDB(&new_sync_entries, &new_sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
+ &new_sync_profiles));
ASSERT_EQ(2U, new_sync_profiles.size());
sync_profile.set_unique_id(0); // The sync DB doesn't store IDs.
EXPECT_EQ(sync_profile, new_sync_profiles[1]);
@@ -764,8 +729,9 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeUpdateEntry) {
EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).
WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true)));
EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
- CreateAutofillRootTask task(this);
- StartSyncService(&task);
+ CreateRootTask task(this, syncable::AUTOFILL);
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
AutofillEntry updated_entry(MakeAutofillEntry("my", "entry", 1, 2));
std::vector<base::Time> timestamps(updated_entry.timestamps());
@@ -783,7 +749,8 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeUpdateEntry) {
std::vector<AutofillEntry> new_sync_entries;
std::vector<AutoFillProfile> new_sync_profiles;
- GetAutofillEntriesFromSyncDB(&new_sync_entries, &new_sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
+ &new_sync_profiles));
ASSERT_EQ(1U, new_sync_entries.size());
EXPECT_TRUE(updated_entry == new_sync_entries[0]);
}
@@ -800,8 +767,9 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeUpdateProfile) {
EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). WillOnce(Return(true));
EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).
WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true)));
- CreateAutofillRootTask task(this);
- StartSyncService(&task);
+ CreateRootTask task(this, syncable::AUTOFILL);
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
AutoFillProfile update_profile(string16(), 0);
autofill_unittest::SetProfileInfo(&update_profile,
@@ -819,7 +787,8 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeUpdateProfile) {
std::vector<AutofillEntry> new_sync_entries;
std::vector<AutoFillProfile> new_sync_profiles;
- GetAutofillEntriesFromSyncDB(&new_sync_entries, &new_sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
+ &new_sync_profiles));
ASSERT_EQ(1U, new_sync_profiles.size());
EXPECT_TRUE(update_profile == new_sync_profiles[0]);
}
@@ -835,8 +804,9 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeUpdateProfileRelabel) {
EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). WillOnce(Return(true));
EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).
WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true)));
- CreateAutofillRootTask task(this);
- StartSyncService(&task);
+ CreateRootTask task(this, syncable::AUTOFILL);
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
AutoFillProfile update_profile(string16(), 0);
autofill_unittest::SetProfileInfo(&update_profile,
@@ -854,7 +824,8 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeUpdateProfileRelabel) {
std::vector<AutofillEntry> new_sync_entries;
std::vector<AutoFillProfile> new_sync_profiles;
- GetAutofillEntriesFromSyncDB(&new_sync_entries, &new_sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
+ &new_sync_profiles));
ASSERT_EQ(1U, new_sync_profiles.size());
EXPECT_TRUE(update_profile == new_sync_profiles[0]);
}
@@ -880,15 +851,16 @@ TEST_F(ProfileSyncServiceAutofillTest,
EXPECT_CALL(web_database_, GetAllAutofillEntries(_)). WillOnce(Return(true));
EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).
WillOnce(DoAll(SetArgumentPointee<0>(native_profiles), Return(true)));
- CreateAutofillRootTask task(this);
- StartSyncService(&task);
+ CreateRootTask task(this, syncable::AUTOFILL);
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
josephine_update.set_label(ASCIIToUTF16("ExistingLabel"));
AutoFillProfile relabelled_profile;
EXPECT_CALL(web_database_, UpdateAutoFillProfile(
ProfileMatchesExceptLabel(josephine_update))).
WillOnce(DoAll(SaveArg<0>(&relabelled_profile), Return(true)));
- EXPECT_CALL(*(personal_data_manager_.get()), Refresh());
+ EXPECT_CALL(*personal_data_manager_, Refresh());
AutofillProfileChange change(AutofillProfileChange::UPDATE,
josephine_update.Label(), &josephine_update,
@@ -900,7 +872,8 @@ TEST_F(ProfileSyncServiceAutofillTest,
std::vector<AutofillEntry> new_sync_entries;
std::vector<AutoFillProfile> new_sync_profiles;
- GetAutofillEntriesFromSyncDB(&new_sync_entries, &new_sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
+ &new_sync_profiles));
ASSERT_EQ(2U, new_sync_profiles.size());
marion.set_unique_id(0); // The sync DB doesn't store IDs.
EXPECT_EQ(marion, new_sync_profiles[1]);
@@ -917,8 +890,9 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeRemoveEntry) {
EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).
WillOnce(DoAll(SetArgumentPointee<0>(original_entries), Return(true)));
EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
- CreateAutofillRootTask task(this);
- StartSyncService(&task);
+ CreateRootTask task(this, syncable::AUTOFILL);
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
AutofillChangeList changes;
changes.push_back(AutofillChange(AutofillChange::REMOVE,
@@ -930,7 +904,8 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeRemoveEntry) {
std::vector<AutofillEntry> new_sync_entries;
std::vector<AutoFillProfile> new_sync_profiles;
- GetAutofillEntriesFromSyncDB(&new_sync_entries, &new_sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
+ &new_sync_profiles));
ASSERT_EQ(0U, new_sync_entries.size());
}
@@ -956,9 +931,9 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeRemoveProfile) {
std::vector<AutoFillProfile> sync_profiles;
sync_profiles.push_back(sync_profile);
AddAutofillEntriesTask task(this, sync_entries, sync_profiles);
-
- EXPECT_CALL(*(personal_data_manager_.get()), Refresh());
- StartSyncService(&task);
+ EXPECT_CALL(*personal_data_manager_, Refresh());
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
AutofillProfileChange change(AutofillProfileChange::REMOVE,
sync_profile.Label(), NULL, string16());
@@ -969,20 +944,22 @@ TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeRemoveProfile) {
std::vector<AutofillEntry> new_sync_entries;
std::vector<AutoFillProfile> new_sync_profiles;
- GetAutofillEntriesFromSyncDB(&new_sync_entries, &new_sync_profiles);
+ ASSERT_TRUE(GetAutofillEntriesFromSyncDB(&new_sync_entries,
+ &new_sync_profiles));
ASSERT_EQ(0U, new_sync_entries.size());
}
TEST_F(ProfileSyncServiceAutofillTest, ProcessUserChangeError) {
EXPECT_CALL(web_database_, GetAllAutofillEntries(_)).WillOnce(Return(true));
EXPECT_CALL(web_database_, GetAutoFillProfiles(_)).WillOnce(Return(true));
- CreateAutofillRootTask task(this);
- StartSyncService(&task);
+ CreateRootTask task(this, syncable::AUTOFILL);
+ StartSyncService(&task, false);
+ ASSERT_TRUE(task.success());
// Inject an evil entry into the sync db to conflict with the same
// entry added by the user.
AutofillEntry evil_entry(MakeAutofillEntry("evil", "entry", 1));
- AddAutofillSyncNode(evil_entry);
+ ASSERT_TRUE(AddAutofillSyncNode(evil_entry));
AutofillChangeList changes;
changes.push_back(AutofillChange(AutofillChange::ADD,
diff --git a/chrome/browser/sync/profile_sync_service_preference_unittest.cc b/chrome/browser/sync/profile_sync_service_preference_unittest.cc
index 79a1c6b..542875f 100644
--- a/chrome/browser/sync/profile_sync_service_preference_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_preference_unittest.cc
@@ -2,16 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <map>
+#include <string>
+
#include "base/json/json_reader.h"
+#include "base/stl_util-inl.h"
+#include "base/task.h"
+#include "chrome/browser/sync/abstract_profile_sync_service_test.h"
#include "chrome/browser/sync/engine/syncapi.h"
#include "chrome/browser/sync/glue/preference_change_processor.h"
#include "chrome/browser/sync/glue/preference_data_type_controller.h"
#include "chrome/browser/sync/glue/preference_model_associator.h"
#include "chrome/browser/sync/glue/sync_backend_host.h"
-#include "chrome/browser/sync/glue/sync_backend_host_mock.h"
-#include "chrome/browser/sync/profile_sync_factory_mock.h"
#include "chrome/browser/sync/profile_sync_test_util.h"
#include "chrome/browser/sync/protocol/preference_specifics.pb.h"
+#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/test_profile_sync_service.h"
#include "chrome/common/json_value_serializer.h"
#include "chrome/common/pref_names.h"
@@ -24,33 +29,30 @@ using browser_sync::PreferenceChangeProcessor;
using browser_sync::PreferenceDataTypeController;
using browser_sync::PreferenceModelAssociator;
using browser_sync::SyncBackendHost;
-using browser_sync::SyncBackendHostMock;
using sync_api::SyncManager;
using testing::_;
using testing::Return;
-class TestPreferenceModelAssociator : public PreferenceModelAssociator {
- public:
- TestPreferenceModelAssociator(ProfileSyncService* service)
- : PreferenceModelAssociator(service),
- helper_(new TestModelAssociatorHelper()) {
- }
- virtual bool GetSyncIdForTaggedNode(const std::string& tag, int64* sync_id) {
- return helper_->GetSyncIdForTaggedNode(this, tag, sync_id);
- }
- private:
- scoped_ptr<TestModelAssociatorHelper> helper_;
-};
+typedef std::map<const std::wstring, const Value*> PreferenceValues;
-class ProfileSyncServicePreferenceTest : public testing::Test {
+class ProfileSyncServicePreferenceTest
+ : public AbstractProfileSyncServiceTest {
protected:
ProfileSyncServicePreferenceTest()
- : ui_thread_(ChromeThread::UI, &message_loop_) {
- }
+ : example_url0_(L"http://example.com/0"),
+ example_url1_(L"http://example.com/1"),
+ example_url2_(L"http://example.com/2"),
+ not_synced_preference_name_(L"nonsense_pref_name"),
+ not_synced_preference_default_value_(L"default"),
+ non_default_charset_value_(L"foo") {}
virtual void SetUp() {
profile_.reset(new TestingProfile());
profile_->set_has_history_service(true);
+ prefs_ = profile_->GetPrefs();
+
+ prefs_->RegisterStringPref(not_synced_preference_name_.c_str(),
+ not_synced_preference_default_value_);
}
virtual void TearDown() {
@@ -59,51 +61,64 @@ class ProfileSyncServicePreferenceTest : public testing::Test {
MessageLoop::current()->RunAllPending();
}
- void StartSyncService() {
- if (!service_.get()) {
- service_.reset(new TestProfileSyncService(&factory_,
- profile_.get(),
- false,
- true));
-
- // Register the preference data type.
- model_associator_ = new TestPreferenceModelAssociator(service_.get());
- change_processor_ = new PreferenceChangeProcessor(model_associator_,
- service_.get());
- EXPECT_CALL(factory_, CreatePreferenceSyncComponents(_, _)).
- WillOnce(Return(ProfileSyncFactory::SyncComponents(
- model_associator_, change_processor_)));
- EXPECT_CALL(factory_, CreateDataTypeManager(_, _)).
- WillOnce(MakeDataTypeManager(&backend_mock_));
-
- service_->RegisterDataTypeController(
- new PreferenceDataTypeController(&factory_,
- service_.get()));
- service_->Initialize();
+ bool StartSyncService(Task* task, bool will_fail_association) {
+ if (service_.get())
+ return false;
+
+ service_.reset(new TestProfileSyncService(
+ &factory_, profile_.get(), false, false));
+ service_->AddObserver(&observer_);
+
+ // Register the preference data type.
+ model_associator_ =
+ new PreferenceModelAssociator(service_.get());
+ change_processor_ = new PreferenceChangeProcessor(model_associator_,
+ service_.get());
+ EXPECT_CALL(factory_, CreatePreferenceSyncComponents(_, _)).
+ WillOnce(Return(ProfileSyncFactory::SyncComponents(
+ model_associator_, change_processor_)));
+
+ EXPECT_CALL(factory_, CreateDataTypeManager(_, _)).
+ WillOnce(MakeDataTypeManager(&backend_));
+
+ EXPECT_CALL(backend_, RequestPause()).Times(1);
+ EXPECT_CALL(backend_, ConfigureDataTypes(_, _)).Times(1);
+ if (will_fail_association) {
+ EXPECT_CALL(backend_, RequestResume()).Times(0);
+ } else {
+ EXPECT_CALL(backend_, RequestResume()).Times(1);
}
- // The service may have already started sync automatically if it's already
- // enabled by user once.
- if (!service_->HasSyncSetupCompleted())
- service_->EnableForUser();
+
+ EXPECT_CALL(observer_, OnStateChanged()).
+ WillOnce(InvokeTask(task)).
+ WillOnce(Return()).
+ WillOnce(QuitUIMessageLoop());
+ service_->RegisterDataTypeController(
+ new PreferenceDataTypeController(&factory_,
+ service_.get()));
+ service_->Initialize();
+ MessageLoop::current()->Run();
+ return true;
}
SyncBackendHost* backend() { return service_->backend_.get(); }
const Value& GetPreferenceValue(const std::wstring& name) {
const PrefService::Preference* preference =
- profile_->GetPrefs()->FindPreference(name.c_str());
+ prefs_->FindPreference(name.c_str());
return *preference->GetValue();
}
// Caller gets ownership of the returned value.
const Value* GetSyncedValue(const std::wstring& name) {
- sync_api::ReadTransaction trans(backend()->GetUserShareHandle());
+ sync_api::ReadTransaction trans(service_->backend()->GetUserShareHandle());
sync_api::ReadNode node(&trans);
int64 node_id = model_associator_->GetSyncIdFromChromeId(name);
- EXPECT_NE(sync_api::kInvalidId, node_id);
- EXPECT_TRUE(node.InitByIdLookup(node_id));
- EXPECT_EQ(name, node.GetTitle());
+ if (node_id == sync_api::kInvalidId)
+ return NULL;
+ if (!node.InitByIdLookup(node_id))
+ return NULL;
const sync_pb::PreferenceSpecifics& specifics(
node.GetPreferenceSpecifics());
@@ -112,15 +127,26 @@ class ProfileSyncServicePreferenceTest : public testing::Test {
return reader.JsonToValue(specifics.value(), false, false);
}
- // Caller gets ownership of the returned change record.
- SyncManager::ChangeRecord* SetSyncedValue(const std::wstring& name,
- const Value& value) {
+ int64 SetSyncedValue(const std::wstring& name, const Value& value) {
sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
+ sync_api::ReadNode root(&trans);
+ if (!root.InitByTagLookup(browser_sync::kPreferencesTag))
+ return sync_api::kInvalidId;
+
sync_api::WriteNode node(&trans);
int64 node_id = model_associator_->GetSyncIdFromChromeId(name);
- EXPECT_NE(sync_api::kInvalidId, node_id);
- EXPECT_TRUE(node.InitByIdLookup(node_id));
+ if (node_id == sync_api::kInvalidId) {
+ if (!node.InitUniqueByCreation(syncable::PREFERENCES,
+ root,
+ WideToUTF8(name))) {
+ return sync_api::kInvalidId;
+ }
+ } else {
+ if (!node.InitByIdLookup(node_id)) {
+ return sync_api::kInvalidId;
+ }
+ }
std::string serialized;
JSONStringValueSerializer json(&serialized);
@@ -132,60 +158,246 @@ class ProfileSyncServicePreferenceTest : public testing::Test {
node.SetPreferenceSpecifics(preference);
node.SetTitle(name);
+ return node.GetId();
+ }
+
+ SyncManager::ChangeRecord* MakeChangeRecord(const std::wstring& name,
+ SyncManager::ChangeRecord) {
+ int64 node_id = model_associator_->GetSyncIdFromChromeId(name);
SyncManager::ChangeRecord* record = new SyncManager::ChangeRecord();
record->action = SyncManager::ChangeRecord::ACTION_UPDATE;
record->id = node_id;
return record;
}
- scoped_ptr<TestProfileSyncService> service_;
+ bool IsSynced(const std::wstring& pref_name) {
+ return model_associator_->synced_preferences().count(pref_name) > 0;
+ }
+
+ std::string ValueString(const Value& value) {
+ std::string serialized;
+ JSONStringValueSerializer json(&serialized);
+ json.Serialize(value);
+ return serialized;
+ }
+
+ friend class AddPreferenceEntriesTask;
+
scoped_ptr<TestingProfile> profile_;
- ProfileSyncFactoryMock factory_;
- SyncBackendHostMock backend_mock_;
+ PrefService* prefs_;
PreferenceModelAssociator* model_associator_;
PreferenceChangeProcessor* change_processor_;
-
- MessageLoopForUI message_loop_;
- ChromeThread ui_thread_;
+ std::wstring example_url0_;
+ std::wstring example_url1_;
+ std::wstring example_url2_;
+ std::wstring not_synced_preference_name_;
+ std::wstring not_synced_preference_default_value_;
+ std::wstring non_default_charset_value_;
};
-TEST_F(ProfileSyncServicePreferenceTest, ModelAssociation) {
- StartSyncService();
- const std::set<std::wstring>& names = model_associator_->synced_preferences();
- ASSERT_LT(0U, names.size());
+class AddPreferenceEntriesTask : public Task {
+ public:
+ AddPreferenceEntriesTask(ProfileSyncServicePreferenceTest* test,
+ const PreferenceValues& entries)
+ : test_(test), entries_(entries), success_(false) {
+ }
- for (std::set<std::wstring>::const_iterator it = names.begin();
- it != names.end(); ++it) {
- const Value& expected = GetPreferenceValue(*it);
- scoped_ptr<const Value> actual(GetSyncedValue(*it));
- EXPECT_TRUE(expected.Equals(actual.get())) << *it;
+ virtual void Run() {
+ if (!test_->CreateRoot(syncable::PREFERENCES))
+ return;
+ for (PreferenceValues::const_iterator i = entries_.begin();
+ i != entries_.end(); ++i) {
+ if (test_->SetSyncedValue(i->first, *i->second) == sync_api::kInvalidId)
+ return;
+ }
+ success_ = true;
}
+
+ bool success() { return success_; }
+
+ private:
+ ProfileSyncServicePreferenceTest* test_;
+ const PreferenceValues& entries_;
+ bool success_;
+};
+
+TEST_F(ProfileSyncServicePreferenceTest, WritePreferenceToNode) {
+ prefs_->SetString(prefs::kHomePage, example_url0_);
+ CreateRootTask task(this, syncable::PREFERENCES);
+ ASSERT_TRUE(StartSyncService(&task, false));
+ ASSERT_TRUE(task.success());
+
+ const PrefService::Preference* pref =
+ prefs_->FindPreference(prefs::kHomePage);
+ sync_api::WriteTransaction trans(service_->backend()->GetUserShareHandle());
+ sync_api::WriteNode node(&trans);
+ EXPECT_TRUE(node.InitByClientTagLookup(syncable::PREFERENCES,
+ WideToUTF8(prefs::kHomePage)));
+
+ EXPECT_TRUE(PreferenceModelAssociator::WritePreferenceToNode(*pref, &node));
+ EXPECT_EQ(std::wstring(prefs::kHomePage), node.GetTitle());
+ const sync_pb::PreferenceSpecifics& specifics(node.GetPreferenceSpecifics());
+ EXPECT_EQ(WideToUTF8(prefs::kHomePage), specifics.name());
+
+ base::JSONReader reader;
+ scoped_ptr<Value> value(reader.JsonToValue(specifics.value(), false, false));
+ EXPECT_TRUE(pref->GetValue()->Equals(value.get()));
+}
+
+TEST_F(ProfileSyncServicePreferenceTest, ModelAssociationDoNotSyncDefaults) {
+ const PrefService::Preference* pref =
+ prefs_->FindPreference(prefs::kHomePage);
+ EXPECT_TRUE(pref->IsDefaultValue());
+ CreateRootTask task(this, syncable::PREFERENCES);
+ ASSERT_TRUE(StartSyncService(&task, false));
+ ASSERT_TRUE(task.success());
+ EXPECT_TRUE(IsSynced(prefs::kHomePage));
+ EXPECT_TRUE(pref->IsDefaultValue());
+ EXPECT_TRUE(GetSyncedValue(prefs::kHomePage) == NULL);
+ EXPECT_TRUE(GetSyncedValue(not_synced_preference_name_) == NULL);
+}
+
+TEST_F(ProfileSyncServicePreferenceTest, ModelAssociationEmptyCloud) {
+ prefs_->SetString(prefs::kHomePage, example_url0_);
+ ListValue* url_list = prefs_->GetMutableList(prefs::kURLsToRestoreOnStartup);
+ url_list->Append(Value::CreateStringValue(example_url0_));
+ url_list->Append(Value::CreateStringValue(example_url1_));
+ CreateRootTask task(this, syncable::PREFERENCES);
+ ASSERT_TRUE(StartSyncService(&task, false));
+ ASSERT_TRUE(task.success());
+
+ scoped_ptr<const Value> value(GetSyncedValue(prefs::kHomePage));
+ ASSERT_TRUE(value.get());
+ EXPECT_TRUE(GetPreferenceValue(prefs::kHomePage).Equals(value.get()));
+ value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup));
+ ASSERT_TRUE(value.get());
+ EXPECT_TRUE(
+ GetPreferenceValue(prefs::kURLsToRestoreOnStartup).Equals(value.get()));
+}
+
+TEST_F(ProfileSyncServicePreferenceTest, ModelAssociationCloudHasData) {
+ prefs_->SetString(prefs::kHomePage, example_url0_);
+ ListValue* url_list = prefs_->GetMutableList(prefs::kURLsToRestoreOnStartup);
+ url_list->Append(Value::CreateStringValue(example_url0_));
+ url_list->Append(Value::CreateStringValue(example_url1_));
+
+ PreferenceValues cloud_data;
+ cloud_data[prefs::kHomePage] = Value::CreateStringValue(example_url1_);
+ ListValue* urls_to_restore = new ListValue;
+ urls_to_restore->Append(Value::CreateStringValue(example_url1_));
+ urls_to_restore->Append(Value::CreateStringValue(example_url2_));
+ cloud_data[prefs::kURLsToRestoreOnStartup] = urls_to_restore;
+ cloud_data[prefs::kDefaultCharset] =
+ Value::CreateStringValue(non_default_charset_value_);
+
+ AddPreferenceEntriesTask task(this, cloud_data);
+ ASSERT_TRUE(StartSyncService(&task, false));
+ ASSERT_TRUE(task.success());
+
+ scoped_ptr<const Value> value(GetSyncedValue(prefs::kHomePage));
+ ASSERT_TRUE(value.get());
+ std::wstring string_value;
+ EXPECT_TRUE(static_cast<const StringValue*>(value.get())->
+ GetAsString(&string_value));
+ EXPECT_EQ(example_url1_, string_value);
+ EXPECT_EQ(example_url1_, prefs_->GetString(prefs::kHomePage));
+
+ scoped_ptr<ListValue> expected_urls(new ListValue);
+ expected_urls->Append(Value::CreateStringValue(example_url1_));
+ expected_urls->Append(Value::CreateStringValue(example_url2_));
+ expected_urls->Append(Value::CreateStringValue(example_url0_));
+ value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup));
+ ASSERT_TRUE(value.get());
+ EXPECT_TRUE(value->Equals(expected_urls.get()));
+ EXPECT_TRUE(GetPreferenceValue(prefs::kURLsToRestoreOnStartup).
+ Equals(expected_urls.get()));
+
+ value.reset(GetSyncedValue(prefs::kDefaultCharset));
+ ASSERT_TRUE(value.get());
+ EXPECT_TRUE(static_cast<const StringValue*>(value.get())->
+ GetAsString(&string_value));
+ EXPECT_EQ(non_default_charset_value_, string_value);
+ EXPECT_EQ(non_default_charset_value_,
+ prefs_->GetString(prefs::kDefaultCharset));
+ STLDeleteValues(&cloud_data);
+}
+
+TEST_F(ProfileSyncServicePreferenceTest, FailModelAssociation) {
+ ASSERT_TRUE(StartSyncService(NULL, true));
+ EXPECT_TRUE(service_->unrecoverable_error_detected());
}
-TEST_F(ProfileSyncServicePreferenceTest, UpdatedPreference) {
- StartSyncService();
+TEST_F(ProfileSyncServicePreferenceTest, UpdatedPreferenceWithDefaultValue) {
+ const PrefService::Preference* pref =
+ prefs_->FindPreference(prefs::kHomePage);
+ EXPECT_TRUE(pref->IsDefaultValue());
- scoped_ptr<Value> expected(
- Value::CreateStringValue("http://example.com/test/foo"));
+ CreateRootTask task(this, syncable::PREFERENCES);
+ ASSERT_TRUE(StartSyncService(&task, false));
+ ASSERT_TRUE(task.success());
+
+ scoped_ptr<Value> expected(Value::CreateStringValue(example_url0_));
+ profile_->GetPrefs()->Set(prefs::kHomePage, *expected);
+
+ scoped_ptr<const Value> actual(GetSyncedValue(prefs::kHomePage));
+ ASSERT_TRUE(actual.get());
+ EXPECT_TRUE(expected->Equals(actual.get()));
+}
+
+TEST_F(ProfileSyncServicePreferenceTest, UpdatedPreferenceWithValue) {
+ profile_->GetPrefs()->SetString(prefs::kHomePage, example_url0_);
+ CreateRootTask task(this, syncable::PREFERENCES);
+ ASSERT_TRUE(StartSyncService(&task, false));
+ ASSERT_TRUE(task.success());
+
+ scoped_ptr<Value> expected(Value::CreateStringValue(example_url1_));
profile_->GetPrefs()->Set(prefs::kHomePage, *expected);
scoped_ptr<const Value> actual(GetSyncedValue(prefs::kHomePage));
- ASSERT_TRUE(expected->Equals(actual.get()));
+ ASSERT_TRUE(actual.get());
+ EXPECT_TRUE(expected->Equals(actual.get()));
+}
+
+TEST_F(ProfileSyncServicePreferenceTest, UpdatedSyncNodeActionUpdate) {
+ profile_->GetPrefs()->SetString(prefs::kHomePage, example_url0_);
+ CreateRootTask task(this, syncable::PREFERENCES);
+ ASSERT_TRUE(StartSyncService(&task, false));
+ ASSERT_TRUE(task.success());
+
+ scoped_ptr<Value> expected(Value::CreateStringValue(example_url1_));
+ ASSERT_NE(SetSyncedValue(prefs::kHomePage, *expected), sync_api::kInvalidId);
+ int64 node_id = model_associator_->GetSyncIdFromChromeId(prefs::kHomePage);
+ scoped_ptr<SyncManager::ChangeRecord> record(new SyncManager::ChangeRecord);
+ record->action = SyncManager::ChangeRecord::ACTION_UPDATE;
+ record->id = node_id;
+ {
+ sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
+ change_processor_->ApplyChangesFromSyncModel(&trans, record.get(), 1);
+ }
+
+ const Value& actual = GetPreferenceValue(prefs::kHomePage);
+ EXPECT_TRUE(expected->Equals(&actual));
}
-TEST_F(ProfileSyncServicePreferenceTest, UpdatedSyncNode) {
- StartSyncService();
+TEST_F(ProfileSyncServicePreferenceTest, UpdatedSyncNodeActionAdd) {
+ CreateRootTask task(this, syncable::PREFERENCES);
+ ASSERT_TRUE(StartSyncService(&task, false));
+ ASSERT_TRUE(task.success());
- scoped_ptr<Value> expected(
- Value::CreateStringValue("http://example.com/test/bar"));
- scoped_ptr<SyncManager::ChangeRecord> record(
- SetSyncedValue(prefs::kHomePage, *expected));
+ scoped_ptr<Value> expected(Value::CreateStringValue(example_url0_));
+ int64 node_id = SetSyncedValue(prefs::kHomePage, *expected);
+ ASSERT_NE(node_id, sync_api::kInvalidId);
+ scoped_ptr<SyncManager::ChangeRecord> record(new SyncManager::ChangeRecord);
+ record->action = SyncManager::ChangeRecord::ACTION_ADD;
+ record->id = node_id;
{
sync_api::WriteTransaction trans(backend()->GetUserShareHandle());
change_processor_->ApplyChangesFromSyncModel(&trans, record.get(), 1);
}
const Value& actual = GetPreferenceValue(prefs::kHomePage);
- ASSERT_TRUE(expected->Equals(&actual));
+ EXPECT_TRUE(expected->Equals(&actual));
+ EXPECT_EQ(node_id,
+ model_associator_->GetSyncIdFromChromeId(prefs::kHomePage));
}
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index ab34683..8b06e38 100755
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -913,6 +913,7 @@
'browser/ssl/ssl_host_state_unittest.cc',
'browser/status_icons/status_icon_unittest.cc',
'browser/status_icons/status_tray_unittest.cc',
+ 'browser/sync/abstract_profile_sync_service_test.h',
'browser/sync/glue/autofill_data_type_controller_unittest.cc',
'browser/sync/glue/autofill_model_associator_unittest.cc',
'browser/sync/glue/bookmark_data_type_controller_unittest.cc',
@@ -926,6 +927,7 @@
'browser/sync/glue/extension_util_unittest.cc',
'browser/sync/glue/http_bridge_unittest.cc',
'browser/sync/glue/preference_data_type_controller_unittest.cc',
+ 'browser/sync/glue/preference_model_associator_unittest.cc',
'browser/sync/glue/sync_backend_host_mock.h',
'browser/sync/glue/theme_data_type_controller_unittest.cc',
'browser/sync/glue/theme_util_unittest.cc',