| // Copyright (c) 2013 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 <string> |
| |
| #include <vector> |
| |
| #include "base/guid.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/prefs/pref_service.h" |
| #include "base/values.h" |
| #include "chrome/browser/extensions/api/signedin_devices/signedin_devices_api.h" |
| #include "chrome/browser/extensions/extension_function_test_utils.h" |
| #include "chrome/browser/extensions/test_extension_prefs.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/sync/glue/device_info.h" |
| #include "chrome/browser/sync/profile_sync_service_factory.h" |
| #include "chrome/browser/sync/profile_sync_service_mock.h" |
| #include "chrome/common/extensions/extension.h" |
| #include "chrome/common/extensions/extension_manifest_constants.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/browser_with_test_window_test.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using extensions::Extension; |
| using extensions::TestExtensionPrefs; |
| using browser_sync::DeviceInfo; |
| using testing::Return; |
| |
| namespace extensions { |
| |
| namespace utils = extension_function_test_utils; |
| |
| TEST(SignedinDevicesAPITest, GetSignedInDevices) { |
| ProfileSyncServiceMock pss_mock; |
| base::MessageLoop message_loop_; |
| TestExtensionPrefs extension_prefs( |
| message_loop_.message_loop_proxy().get()); |
| |
| // Add a couple of devices and make sure we get back public ids for them. |
| std::string extension_name = "test"; |
| scoped_refptr<Extension> extension_test = |
| extension_prefs.AddExtension(extension_name); |
| |
| DeviceInfo device_info1( |
| base::GenerateGUID(), |
| "abc Device", "XYZ v1", "XYZ SyncAgent v1", |
| sync_pb::SyncEnums_DeviceType_TYPE_LINUX); |
| |
| DeviceInfo device_info2( |
| base::GenerateGUID(), |
| "def Device", "XYZ v2", "XYZ SyncAgent v2", |
| sync_pb::SyncEnums_DeviceType_TYPE_LINUX); |
| |
| std::vector<DeviceInfo*> devices; |
| devices.push_back(&device_info1); |
| devices.push_back(&device_info2); |
| |
| EXPECT_CALL(pss_mock, GetAllSignedinDevicesMock()). |
| WillOnce(Return(&devices)); |
| |
| ScopedVector<DeviceInfo> output1 = GetAllSignedinDevices( |
| extension_test.get()->id(), |
| &pss_mock, |
| extension_prefs.prefs()); |
| |
| std::string public_id1 = device_info1.public_id(); |
| std::string public_id2 = device_info2.public_id(); |
| |
| EXPECT_FALSE(public_id1.empty()); |
| EXPECT_FALSE(public_id2.empty()); |
| EXPECT_NE(public_id1, public_id2); |
| |
| // Now clear output1 so its destructor will not destroy the pointers for |
| // |device_info1| and |device_info2|. |
| output1.weak_clear(); |
| |
| // Add a third device and make sure the first 2 ids are retained and a new |
| // id is generated for the third device. |
| DeviceInfo device_info3( |
| base::GenerateGUID(), |
| "def Device", "jkl v2", "XYZ SyncAgent v2", |
| sync_pb::SyncEnums_DeviceType_TYPE_LINUX); |
| |
| devices.push_back(&device_info3); |
| |
| EXPECT_CALL(pss_mock, GetAllSignedinDevicesMock()). |
| WillOnce(Return(&devices)); |
| |
| ScopedVector<DeviceInfo> output2 = GetAllSignedinDevices( |
| extension_test.get()->id(), |
| &pss_mock, |
| extension_prefs.prefs()); |
| |
| EXPECT_EQ(device_info1.public_id(), public_id1); |
| EXPECT_EQ(device_info2.public_id(), public_id2); |
| |
| std::string public_id3 = device_info3.public_id(); |
| EXPECT_FALSE(public_id3.empty()); |
| EXPECT_NE(public_id3, public_id1); |
| EXPECT_NE(public_id3, public_id2); |
| |
| // Now clear output2 so that its destructor does not destroy the |
| // |DeviceInfo| pointers. |
| output2.weak_clear(); |
| } |
| |
| class ProfileSyncServiceMockForExtensionTests: |
| public ProfileSyncServiceMock { |
| public: |
| ProfileSyncServiceMockForExtensionTests() {} |
| ~ProfileSyncServiceMockForExtensionTests() {} |
| MOCK_METHOD0(Shutdown, void()); |
| }; |
| |
| BrowserContextKeyedService* CreateProfileSyncServiceMock( |
| content::BrowserContext* profile) { |
| return new ProfileSyncServiceMockForExtensionTests(); |
| } |
| |
| class ExtensionSignedinDevicesTest : public BrowserWithTestWindowTest { |
| public: |
| virtual void SetUp() { |
| BrowserWithTestWindowTest::SetUp(); |
| |
| ProfileSyncServiceFactory::GetInstance()->SetTestingFactory( |
| profile(), CreateProfileSyncServiceMock); |
| |
| extension_ = utils::CreateEmptyExtensionWithLocation( |
| extensions::Manifest::UNPACKED); |
| |
| } |
| |
| base::Value* RunFunctionWithExtension( |
| UIThreadExtensionFunction* function, |
| const std::string& args) { |
| scoped_refptr<UIThreadExtensionFunction> delete_function(function); |
| function->set_extension(extension_.get()); |
| return utils::RunFunctionAndReturnSingleResult(function, args, browser()); |
| } |
| |
| base::ListValue* RunFunctionAndReturnList( |
| UIThreadExtensionFunction* function, |
| const std::string& args) { |
| base::Value* result = RunFunctionWithExtension(function, args); |
| return result ? utils::ToList(result) : NULL; |
| } |
| |
| protected: |
| scoped_refptr<extensions::Extension> extension_; |
| }; |
| |
| DeviceInfo* CreateDeviceInfo(const DeviceInfo& device_info) { |
| return new DeviceInfo(device_info.guid(), |
| device_info.client_name(), |
| device_info.chrome_version(), |
| device_info.sync_user_agent(), |
| device_info.device_type()); |
| } |
| |
| std::string GetPublicId(const base::DictionaryValue* dictionary) { |
| std::string public_id; |
| if (!dictionary->GetString("id", &public_id)) { |
| ADD_FAILURE() << "Not able to find public id in the dictionary"; |
| } |
| |
| return public_id; |
| } |
| |
| void VerifyDictionaryWithDeviceInfo(const base::DictionaryValue* actual_value, |
| DeviceInfo* device_info) { |
| std::string public_id = GetPublicId(actual_value); |
| device_info->set_public_id(public_id); |
| |
| scoped_ptr<base::DictionaryValue> expected_value(device_info->ToValue()); |
| EXPECT_TRUE(expected_value->Equals(actual_value)); |
| } |
| |
| base::DictionaryValue* GetDictionaryFromList(int index, |
| base::ListValue* value) { |
| base::DictionaryValue* dictionary; |
| if (!value->GetDictionary(index, &dictionary)) { |
| ADD_FAILURE() << "Expected a list of dictionaries"; |
| return NULL; |
| } |
| return dictionary; |
| } |
| |
| TEST_F(ExtensionSignedinDevicesTest, GetAll) { |
| ProfileSyncServiceMockForExtensionTests* pss_mock = |
| static_cast<ProfileSyncServiceMockForExtensionTests*>( |
| ProfileSyncServiceFactory::GetForProfile(profile())); |
| |
| DeviceInfo device_info1( |
| base::GenerateGUID(), |
| "abc Device", "XYZ v1", "XYZ SyncAgent v1", |
| sync_pb::SyncEnums_DeviceType_TYPE_LINUX); |
| |
| DeviceInfo device_info2( |
| base::GenerateGUID(), |
| "def Device", "XYZ v2", "XYZ SyncAgent v2", |
| sync_pb::SyncEnums_DeviceType_TYPE_LINUX); |
| |
| std::vector<DeviceInfo*> devices; |
| devices.push_back(CreateDeviceInfo(device_info1)); |
| devices.push_back(CreateDeviceInfo(device_info2)); |
| |
| EXPECT_CALL(*pss_mock, GetAllSignedinDevicesMock()). |
| WillOnce(Return(&devices)); |
| |
| EXPECT_CALL(*pss_mock, Shutdown()); |
| |
| scoped_ptr<base::ListValue> result(RunFunctionAndReturnList( |
| new SignedinDevicesGetFunction(), "[null]")); |
| |
| // Ensure dictionary matches device info. |
| VerifyDictionaryWithDeviceInfo(GetDictionaryFromList(0, result.get()), |
| &device_info1); |
| VerifyDictionaryWithDeviceInfo(GetDictionaryFromList(1, result.get()), |
| &device_info2); |
| |
| // Ensure public ids are set and unique. |
| std::string public_id1 = GetPublicId(GetDictionaryFromList(0, result.get())); |
| std::string public_id2 = GetPublicId(GetDictionaryFromList(1, result.get())); |
| |
| EXPECT_FALSE(public_id1.empty()); |
| EXPECT_FALSE(public_id2.empty()); |
| EXPECT_NE(public_id1, public_id2); |
| } |
| |
| } // namespace extensions |