blob: 8936680f06ba7bfeaccf8e3a298a21b901525f81 [file] [log] [blame]
// 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