Home | History | Annotate | Download | only in signed_in_devices
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <string>
      6 
      7 #include <vector>
      8 
      9 #include "base/guid.h"
     10 #include "base/message_loop/message_loop.h"
     11 #include "base/prefs/pref_service.h"
     12 #include "base/values.h"
     13 #include "chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h"
     14 #include "chrome/browser/extensions/extension_api_unittest.h"
     15 #include "chrome/browser/extensions/test_extension_prefs.h"
     16 #include "chrome/browser/profiles/profile.h"
     17 #include "chrome/browser/sync/profile_sync_service_factory.h"
     18 #include "chrome/browser/sync/profile_sync_service_mock.h"
     19 #include "chrome/common/pref_names.h"
     20 #include "components/sync_driver/device_info.h"
     21 #include "extensions/common/extension.h"
     22 #include "testing/gmock/include/gmock/gmock.h"
     23 #include "testing/gtest/include/gtest/gtest.h"
     24 
     25 using sync_driver::DeviceInfo;
     26 using sync_driver::DeviceInfoTracker;
     27 using testing::Return;
     28 
     29 namespace extensions {
     30 
     31 class MockDeviceInfoTracker : public DeviceInfoTracker {
     32  public:
     33   virtual ~MockDeviceInfoTracker() {}
     34 
     35   virtual scoped_ptr<DeviceInfo> GetDeviceInfo(
     36       const std::string& client_id) const OVERRIDE {
     37     NOTREACHED();
     38     return scoped_ptr<DeviceInfo>();
     39   }
     40 
     41   static DeviceInfo* CloneDeviceInfo(const DeviceInfo* device_info) {
     42     return new DeviceInfo(device_info->guid(),
     43                           device_info->client_name(),
     44                           device_info->chrome_version(),
     45                           device_info->sync_user_agent(),
     46                           device_info->device_type(),
     47                           device_info->signin_scoped_device_id());
     48   }
     49 
     50   virtual ScopedVector<DeviceInfo> GetAllDeviceInfo() const OVERRIDE {
     51     ScopedVector<DeviceInfo> list;
     52 
     53     for (std::vector<const DeviceInfo*>::const_iterator iter = devices_.begin();
     54          iter != devices_.end();
     55          ++iter) {
     56       list.push_back(CloneDeviceInfo(*iter));
     57     }
     58 
     59     return list.Pass();
     60   }
     61 
     62   virtual void AddObserver(Observer* observer) OVERRIDE { NOTREACHED(); }
     63 
     64   virtual void RemoveObserver(Observer* observer) OVERRIDE { NOTREACHED(); }
     65 
     66   void Add(const DeviceInfo* device) { devices_.push_back(device); }
     67 
     68  private:
     69   // DeviceInfo stored here are not owned.
     70   std::vector<const DeviceInfo*> devices_;
     71 };
     72 
     73 TEST(SignedInDevicesAPITest, GetSignedInDevices) {
     74   TestingProfile profile;
     75   MockDeviceInfoTracker device_tracker;
     76   base::MessageLoop message_loop_;
     77   TestExtensionPrefs extension_prefs(
     78       message_loop_.message_loop_proxy().get());
     79 
     80   // Add a couple of devices and make sure we get back public ids for them.
     81   std::string extension_name = "test";
     82   scoped_refptr<Extension> extension_test =
     83       extension_prefs.AddExtension(extension_name);
     84 
     85   DeviceInfo device_info1(base::GenerateGUID(),
     86                           "abc Device",
     87                           "XYZ v1",
     88                           "XYZ SyncAgent v1",
     89                           sync_pb::SyncEnums_DeviceType_TYPE_LINUX,
     90                           "device_id");
     91 
     92   DeviceInfo device_info2(base::GenerateGUID(),
     93                           "def Device",
     94                           "XYZ v2",
     95                           "XYZ SyncAgent v2",
     96                           sync_pb::SyncEnums_DeviceType_TYPE_LINUX,
     97                           "device_id");
     98 
     99   device_tracker.Add(&device_info1);
    100   device_tracker.Add(&device_info2);
    101 
    102   ScopedVector<DeviceInfo> output1 = GetAllSignedInDevices(
    103       extension_test.get()->id(), &device_tracker, extension_prefs.prefs());
    104 
    105   std::string public_id1 = output1[0]->public_id();
    106   std::string public_id2 = output1[1]->public_id();
    107 
    108   EXPECT_FALSE(public_id1.empty());
    109   EXPECT_FALSE(public_id2.empty());
    110   EXPECT_NE(public_id1, public_id2);
    111 
    112   // Add a third device and make sure the first 2 ids are retained and a new
    113   // id is generated for the third device.
    114   DeviceInfo device_info3(base::GenerateGUID(),
    115                           "def Device",
    116                           "jkl v2",
    117                           "XYZ SyncAgent v2",
    118                           sync_pb::SyncEnums_DeviceType_TYPE_LINUX,
    119                           "device_id");
    120 
    121   device_tracker.Add(&device_info3);
    122 
    123   ScopedVector<DeviceInfo> output2 = GetAllSignedInDevices(
    124       extension_test.get()->id(), &device_tracker, extension_prefs.prefs());
    125 
    126   EXPECT_EQ(output2[0]->public_id(), public_id1);
    127   EXPECT_EQ(output2[1]->public_id(), public_id2);
    128 
    129   std::string public_id3 = output2[2]->public_id();
    130   EXPECT_FALSE(public_id3.empty());
    131   EXPECT_NE(public_id3, public_id1);
    132   EXPECT_NE(public_id3, public_id2);
    133 }
    134 
    135 class ProfileSyncServiceMockForExtensionTests:
    136     public ProfileSyncServiceMock {
    137  public:
    138   explicit ProfileSyncServiceMockForExtensionTests(Profile* p)
    139       : ProfileSyncServiceMock(p) {}
    140   ~ProfileSyncServiceMockForExtensionTests() {}
    141 
    142   MOCK_METHOD0(Shutdown, void());
    143   MOCK_CONST_METHOD0(GetDeviceInfoTracker, DeviceInfoTracker*());
    144 };
    145 
    146 KeyedService* CreateProfileSyncServiceMock(content::BrowserContext* profile) {
    147   return new ProfileSyncServiceMockForExtensionTests(
    148       Profile::FromBrowserContext(profile));
    149 }
    150 
    151 class ExtensionSignedInDevicesTest : public ExtensionApiUnittest {
    152  public:
    153   virtual void SetUp() {
    154     ExtensionApiUnittest::SetUp();
    155 
    156     ProfileSyncServiceFactory::GetInstance()->SetTestingFactory(
    157         profile(), CreateProfileSyncServiceMock);
    158   }
    159 };
    160 
    161 std::string GetPublicId(const base::DictionaryValue* dictionary) {
    162   std::string public_id;
    163   if (!dictionary->GetString("id", &public_id)) {
    164     ADD_FAILURE() << "Not able to find public id in the dictionary";
    165   }
    166 
    167   return public_id;
    168 }
    169 
    170 void VerifyDictionaryWithDeviceInfo(const base::DictionaryValue* actual_value,
    171                                     DeviceInfo* device_info) {
    172   std::string public_id = GetPublicId(actual_value);
    173   device_info->set_public_id(public_id);
    174 
    175   scoped_ptr<base::DictionaryValue> expected_value(device_info->ToValue());
    176   EXPECT_TRUE(expected_value->Equals(actual_value));
    177 }
    178 
    179 base::DictionaryValue* GetDictionaryFromList(int index,
    180                                              base::ListValue* value) {
    181   base::DictionaryValue* dictionary;
    182   if (!value->GetDictionary(index, &dictionary)) {
    183     ADD_FAILURE() << "Expected a list of dictionaries";
    184     return NULL;
    185   }
    186   return dictionary;
    187 }
    188 
    189 TEST_F(ExtensionSignedInDevicesTest, GetAll) {
    190   ProfileSyncServiceMockForExtensionTests* pss_mock =
    191       static_cast<ProfileSyncServiceMockForExtensionTests*>(
    192           ProfileSyncServiceFactory::GetForProfile(profile()));
    193   MockDeviceInfoTracker device_tracker;
    194 
    195   DeviceInfo device_info1(base::GenerateGUID(),
    196                           "abc Device",
    197                           "XYZ v1",
    198                           "XYZ SyncAgent v1",
    199                           sync_pb::SyncEnums_DeviceType_TYPE_LINUX,
    200                           "device_id");
    201 
    202   DeviceInfo device_info2(base::GenerateGUID(),
    203                           "def Device",
    204                           "XYZ v2",
    205                           "XYZ SyncAgent v2",
    206                           sync_pb::SyncEnums_DeviceType_TYPE_LINUX,
    207                           "device_id");
    208 
    209   device_tracker.Add(&device_info1);
    210   device_tracker.Add(&device_info2);
    211 
    212   EXPECT_CALL(*pss_mock, GetDeviceInfoTracker())
    213       .WillOnce(Return(&device_tracker));
    214 
    215   EXPECT_CALL(*pss_mock, Shutdown());
    216 
    217   scoped_ptr<base::ListValue> result(RunFunctionAndReturnList(
    218       new SignedInDevicesGetFunction(), "[null]"));
    219 
    220   // Ensure dictionary matches device info.
    221   VerifyDictionaryWithDeviceInfo(GetDictionaryFromList(0, result.get()),
    222                                  &device_info1);
    223   VerifyDictionaryWithDeviceInfo(GetDictionaryFromList(1, result.get()),
    224                                  &device_info2);
    225 
    226   // Ensure public ids are set and unique.
    227   std::string public_id1 = GetPublicId(GetDictionaryFromList(0, result.get()));
    228   std::string public_id2 = GetPublicId(GetDictionaryFromList(1, result.get()));
    229 
    230   EXPECT_FALSE(public_id1.empty());
    231   EXPECT_FALSE(public_id2.empty());
    232   EXPECT_NE(public_id1, public_id2);
    233 }
    234 
    235 TEST_F(ExtensionSignedInDevicesTest, DeviceInfoTrackerNotInitialized) {
    236   ProfileSyncServiceMockForExtensionTests* pss_mock =
    237       static_cast<ProfileSyncServiceMockForExtensionTests*>(
    238           ProfileSyncServiceFactory::GetForProfile(profile()));
    239 
    240   EXPECT_CALL(*pss_mock, GetDeviceInfoTracker())
    241     .WillOnce(Return((DeviceInfoTracker*)NULL));
    242   EXPECT_CALL(*pss_mock, Shutdown());
    243 
    244   ScopedVector<DeviceInfo> output = GetAllSignedInDevices(
    245       extension()->id(), profile());
    246 
    247   EXPECT_TRUE(output.empty());
    248 }
    249 
    250 }  // namespace extensions
    251