Add ENABLE_MEDIA_ROUTER define to builds other than Android and iOS.
[chromium-blink-merge.git] / chrome / browser / extensions / api / device_permissions_manager_unittest.cc
blob0140bf611a6ed48822d4c84fda1e4b7584608e65
1 // Copyright 2014 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.
5 #include "base/run_loop.h"
6 #include "base/strings/utf_string_conversions.h"
7 #include "base/test/values_test_util.h"
8 #include "chrome/browser/extensions/test_extension_environment.h"
9 #include "chrome/test/base/testing_profile.h"
10 #include "device/core/device_client.h"
11 #include "device/usb/usb_device.h"
12 #include "device/usb/usb_device_handle.h"
13 #include "extensions/browser/api/device_permissions_manager.h"
14 #include "extensions/browser/extension_prefs.h"
15 #include "extensions/common/extension.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 namespace extensions {
21 namespace {
23 using device::UsbDevice;
24 using device::UsbDeviceHandle;
25 using device::UsbService;
26 using testing::_;
27 using testing::DoAll;
28 using testing::Return;
29 using testing::SetArgPointee;
31 int next_id;
33 class MockUsbService : public UsbService {
34 public:
35 MockUsbService() : mock_device_client(this) {}
37 MOCK_METHOD1(GetDeviceById, scoped_refptr<UsbDevice>(uint32));
38 MOCK_METHOD1(GetDevices, void(std::vector<scoped_refptr<UsbDevice>>*));
40 // Public wrapper for the protected NotifyDeviceRemove function.
41 void NotifyDeviceRemoved(scoped_refptr<UsbDevice> device) {
42 UsbService::NotifyDeviceRemoved(device);
45 private:
46 class MockDeviceClient : device::DeviceClient {
47 public:
48 explicit MockDeviceClient(UsbService* usb_service)
49 : usb_service_(usb_service) {}
51 UsbService* GetUsbService() override { return usb_service_; }
53 private:
54 UsbService* usb_service_;
57 MockDeviceClient mock_device_client;
60 class MockUsbDevice : public UsbDevice {
61 public:
62 explicit MockUsbDevice(const std::string& serial_number)
63 : UsbDevice(0, 0, next_id++) {
64 if (serial_number.empty()) {
65 EXPECT_CALL(*this, GetSerialNumber(_)).WillRepeatedly(Return(false));
66 } else {
67 EXPECT_CALL(*this, GetSerialNumber(_))
68 .WillRepeatedly(
69 DoAll(SetArgPointee<0>(base::ASCIIToUTF16(serial_number)),
70 Return(true)));
73 EXPECT_CALL(*this, GetProduct(_))
74 .WillRepeatedly(
75 DoAll(SetArgPointee<0>(base::ASCIIToUTF16("Test Product")),
76 Return(true)));
77 EXPECT_CALL(*this, GetManufacturer(_))
78 .WillRepeatedly(
79 DoAll(SetArgPointee<0>(base::ASCIIToUTF16("Test Manufacturer")),
80 Return(true)));
83 MOCK_METHOD0(Open, scoped_refptr<UsbDeviceHandle>());
84 MOCK_METHOD1(Close, bool(scoped_refptr<UsbDeviceHandle>));
85 MOCK_METHOD0(GetConfiguration, const device::UsbConfigDescriptor*());
86 MOCK_METHOD1(GetManufacturer, bool(base::string16*));
87 MOCK_METHOD1(GetProduct, bool(base::string16*));
88 MOCK_METHOD1(GetSerialNumber, bool(base::string16*));
90 private:
91 virtual ~MockUsbDevice() {}
94 void AllowUsbDevice(DevicePermissionsManager* manager,
95 const Extension* extension,
96 scoped_refptr<UsbDevice> device) {
97 // If the device cannot provide any of these strings they will simply by
98 // empty.
99 base::string16 product;
100 device->GetProduct(&product);
101 base::string16 manufacturer;
102 device->GetManufacturer(&manufacturer);
103 base::string16 serial_number;
104 device->GetSerialNumber(&serial_number);
106 manager->AllowUsbDevice(
107 extension->id(), device, product, manufacturer, serial_number);
110 scoped_refptr<DevicePermissionEntry> FindEntry(
111 DevicePermissions* device_permissions,
112 scoped_refptr<UsbDevice> device) {
113 base::string16 serial_number;
114 device->GetSerialNumber(&serial_number);
116 return device_permissions->FindEntry(device, serial_number);
119 } // namespace
121 class DevicePermissionsManagerTest : public testing::Test {
122 protected:
123 void SetUp() override {
124 testing::Test::SetUp();
125 env_.GetExtensionPrefs(); // Force creation before adding extensions.
126 extension_ = env_.MakeExtension(*base::test::ParseJson(
128 " \"app\": {"
129 " \"background\": {"
130 " \"scripts\": [\"background.js\"]"
131 " }"
132 " },"
133 " \"permissions\": ["
134 " \"usb\""
135 " ]"
136 "}"));
137 device0_ = new MockUsbDevice("ABCDE");
138 device1_ = new MockUsbDevice("");
139 device2_ = new MockUsbDevice("12345");
140 device3_ = new MockUsbDevice("");
141 usb_service_ = new MockUsbService();
142 UsbService::SetInstanceForTest(usb_service_);
145 extensions::TestExtensionEnvironment env_;
146 const extensions::Extension* extension_;
147 MockUsbService* usb_service_;
148 scoped_refptr<MockUsbDevice> device0_;
149 scoped_refptr<MockUsbDevice> device1_;
150 scoped_refptr<MockUsbDevice> device2_;
151 scoped_refptr<MockUsbDevice> device3_;
154 TEST_F(DevicePermissionsManagerTest, AllowAndClearDevices) {
155 DevicePermissionsManager* manager =
156 DevicePermissionsManager::Get(env_.profile());
157 AllowUsbDevice(manager, extension_, device0_);
158 AllowUsbDevice(manager, extension_, device1_);
160 scoped_ptr<DevicePermissions> device_permissions =
161 manager->GetForExtension(extension_->id());
162 scoped_refptr<DevicePermissionEntry> device0_entry =
163 FindEntry(device_permissions.get(), device0_);
164 ASSERT_TRUE(device0_entry.get());
165 scoped_refptr<DevicePermissionEntry> device1_entry =
166 FindEntry(device_permissions.get(), device1_);
167 ASSERT_TRUE(device1_entry.get());
168 ASSERT_FALSE(FindEntry(device_permissions.get(), device2_).get());
169 ASSERT_FALSE(FindEntry(device_permissions.get(), device3_).get());
170 ASSERT_EQ(2U, device_permissions->entries().size());
172 ASSERT_EQ(base::ASCIIToUTF16(
173 "Test Product from Test Manufacturer (serial number ABCDE)"),
174 device0_entry->GetPermissionMessageString());
175 ASSERT_EQ(base::ASCIIToUTF16("Test Product from Test Manufacturer"),
176 device1_entry->GetPermissionMessageString());
178 manager->Clear(extension_->id());
180 device_permissions = manager->GetForExtension(extension_->id());
181 ASSERT_FALSE(FindEntry(device_permissions.get(), device0_).get());
182 ASSERT_FALSE(FindEntry(device_permissions.get(), device1_).get());
183 ASSERT_FALSE(FindEntry(device_permissions.get(), device2_).get());
184 ASSERT_FALSE(FindEntry(device_permissions.get(), device3_).get());
185 ASSERT_EQ(0U, device_permissions->entries().size());
187 // After clearing device it should be possible to grant permission again.
188 AllowUsbDevice(manager, extension_, device0_);
189 AllowUsbDevice(manager, extension_, device1_);
191 device_permissions = manager->GetForExtension(extension_->id());
192 ASSERT_TRUE(FindEntry(device_permissions.get(), device0_).get());
193 ASSERT_TRUE(FindEntry(device_permissions.get(), device1_).get());
194 ASSERT_FALSE(FindEntry(device_permissions.get(), device2_).get());
195 ASSERT_FALSE(FindEntry(device_permissions.get(), device3_).get());
198 TEST_F(DevicePermissionsManagerTest, SuspendExtension) {
199 DevicePermissionsManager* manager =
200 DevicePermissionsManager::Get(env_.profile());
201 AllowUsbDevice(manager, extension_, device0_);
202 AllowUsbDevice(manager, extension_, device1_);
204 scoped_ptr<DevicePermissions> device_permissions =
205 manager->GetForExtension(extension_->id());
206 ASSERT_TRUE(FindEntry(device_permissions.get(), device0_).get());
207 ASSERT_TRUE(FindEntry(device_permissions.get(), device1_).get());
208 ASSERT_FALSE(FindEntry(device_permissions.get(), device2_).get());
209 ASSERT_FALSE(FindEntry(device_permissions.get(), device3_).get());
211 manager->OnBackgroundHostClose(extension_->id());
213 device_permissions = manager->GetForExtension(extension_->id());
214 // Device 0 is still registered because its serial number has been stored in
215 // ExtensionPrefs, it is "persistent".
216 ASSERT_TRUE(FindEntry(device_permissions.get(), device0_).get());
217 // Device 1 does not have uniquely identifying traits and so permission to
218 // open it has been dropped when the app's windows have closed and the
219 // background page has been suspended.
220 ASSERT_FALSE(FindEntry(device_permissions.get(), device1_).get());
221 ASSERT_FALSE(FindEntry(device_permissions.get(), device2_).get());
222 ASSERT_FALSE(FindEntry(device_permissions.get(), device3_).get());
225 // TODO(reillyg): Until crbug.com/427985 is resolved device removal
226 // notifications are delivered asynchronously and so this test must be disabled.
227 TEST_F(DevicePermissionsManagerTest, DISABLED_DisconnectDevice) {
228 DevicePermissionsManager* manager =
229 DevicePermissionsManager::Get(env_.profile());
230 AllowUsbDevice(manager, extension_, device0_);
231 AllowUsbDevice(manager, extension_, device1_);
233 scoped_ptr<DevicePermissions> device_permissions =
234 manager->GetForExtension(extension_->id());
235 ASSERT_TRUE(FindEntry(device_permissions.get(), device0_).get());
236 ASSERT_TRUE(FindEntry(device_permissions.get(), device1_).get());
237 ASSERT_FALSE(FindEntry(device_permissions.get(), device2_).get());
238 ASSERT_FALSE(FindEntry(device_permissions.get(), device3_).get());
240 usb_service_->NotifyDeviceRemoved(device0_);
241 usb_service_->NotifyDeviceRemoved(device1_);
243 device_permissions = manager->GetForExtension(extension_->id());
244 // Device 0 will be accessible when it is reconnected because it can be
245 // recognized by its serial number.
246 ASSERT_TRUE(FindEntry(device_permissions.get(), device0_).get());
247 // Device 1 does not have a serial number and cannot be distinguished from
248 // any other device of the same model so the app must request permission again
249 // when it is reconnected.
250 ASSERT_FALSE(FindEntry(device_permissions.get(), device1_).get());
251 ASSERT_FALSE(FindEntry(device_permissions.get(), device2_).get());
252 ASSERT_FALSE(FindEntry(device_permissions.get(), device3_).get());
255 TEST_F(DevicePermissionsManagerTest, RevokeAndRegrantAccess) {
256 DevicePermissionsManager* manager =
257 DevicePermissionsManager::Get(env_.profile());
258 AllowUsbDevice(manager, extension_, device0_);
259 AllowUsbDevice(manager, extension_, device1_);
261 scoped_ptr<DevicePermissions> device_permissions =
262 manager->GetForExtension(extension_->id());
263 scoped_refptr<DevicePermissionEntry> device0_entry =
264 FindEntry(device_permissions.get(), device0_);
265 ASSERT_TRUE(device0_entry.get());
266 scoped_refptr<DevicePermissionEntry> device1_entry =
267 FindEntry(device_permissions.get(), device1_);
268 ASSERT_TRUE(device1_entry.get());
270 manager->RemoveEntry(extension_->id(), device0_entry);
271 device_permissions = manager->GetForExtension(extension_->id());
272 ASSERT_FALSE(FindEntry(device_permissions.get(), device0_).get());
273 ASSERT_TRUE(FindEntry(device_permissions.get(), device1_).get());
275 AllowUsbDevice(manager, extension_, device0_);
276 device_permissions = manager->GetForExtension(extension_->id());
277 ASSERT_TRUE(FindEntry(device_permissions.get(), device0_).get());
278 ASSERT_TRUE(FindEntry(device_permissions.get(), device1_).get());
280 manager->RemoveEntry(extension_->id(), device1_entry);
281 device_permissions = manager->GetForExtension(extension_->id());
282 ASSERT_TRUE(FindEntry(device_permissions.get(), device0_).get());
283 ASSERT_FALSE(FindEntry(device_permissions.get(), device1_).get());
285 AllowUsbDevice(manager, extension_, device1_);
286 device_permissions = manager->GetForExtension(extension_->id());
287 ASSERT_TRUE(FindEntry(device_permissions.get(), device0_).get());
288 ASSERT_TRUE(FindEntry(device_permissions.get(), device1_).get());
291 TEST_F(DevicePermissionsManagerTest, UpdateLastUsed) {
292 DevicePermissionsManager* manager =
293 DevicePermissionsManager::Get(env_.profile());
294 AllowUsbDevice(manager, extension_, device0_);
296 scoped_ptr<DevicePermissions> device_permissions =
297 manager->GetForExtension(extension_->id());
298 scoped_refptr<DevicePermissionEntry> device0_entry =
299 FindEntry(device_permissions.get(), device0_);
300 ASSERT_TRUE(device0_entry->last_used().is_null());
302 manager->UpdateLastUsed(extension_->id(), device0_entry);
303 device_permissions = manager->GetForExtension(extension_->id());
304 device0_entry = FindEntry(device_permissions.get(), device0_);
305 ASSERT_FALSE(device0_entry->last_used().is_null());
308 TEST_F(DevicePermissionsManagerTest, LoadPrefs) {
309 scoped_ptr<base::Value> prefs_value = base::test::ParseJson(
311 " {"
312 " \"product_id\": 0,"
313 " \"serial_number\": \"ABCDE\","
314 " \"type\": \"usb\","
315 " \"vendor_id\": 0"
316 " }"
317 "]");
318 env_.GetExtensionPrefs()->UpdateExtensionPref(extension_->id(), "devices",
319 prefs_value.release());
321 DevicePermissionsManager* manager =
322 DevicePermissionsManager::Get(env_.profile());
323 scoped_ptr<DevicePermissions> device_permissions =
324 manager->GetForExtension(extension_->id());
325 ASSERT_TRUE(FindEntry(device_permissions.get(), device0_).get());
326 ASSERT_FALSE(FindEntry(device_permissions.get(), device1_).get());
327 ASSERT_FALSE(FindEntry(device_permissions.get(), device2_).get());
328 ASSERT_FALSE(FindEntry(device_permissions.get(), device3_).get());
331 } // namespace extensions