1 // Copyright (c) 2012 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 "chrome/browser/chromeos/printer_detector/printer_detector.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/run_loop.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
12 #include "chrome/browser/chromeos/printer_detector/printer_detector_factory.h"
13 #include "chrome/browser/chromeos/profiles/profile_helper.h"
14 #include "chrome/browser/extensions/test_extension_system.h"
15 #include "chrome/browser/notifications/notification.h"
16 #include "chrome/browser/notifications/notification_test_util.h"
17 #include "chrome/browser/notifications/notification_ui_manager.h"
18 #include "chrome/test/base/testing_profile.h"
19 #include "components/user_manager/fake_user_manager.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "device/core/device_client.h"
22 #include "device/usb/mock_usb_service.h"
23 #include "device/usb/usb_descriptors.h"
24 #include "device/usb/usb_device.h"
25 #include "device/usb/usb_service.h"
26 #include "extensions/browser/extension_registry.h"
27 #include "extensions/common/extension_builder.h"
28 #include "extensions/common/value_builder.h"
29 #include "testing/gtest/include/gtest/gtest.h"
31 using extensions::DictionaryBuilder
;
32 using extensions::ListBuilder
;
38 const uint8 kPrinterInterfaceClass
= 7;
40 const char kTestUserId
[] = "test_user";
42 const char kPrinterAppExistsDelegateIDTemplate
[] =
43 "system.printer.printer_provider_exists/%s:%s";
45 const char kPrinterAppNotFoundDelegateIDTemplate
[] =
46 "system.printer.no_printer_provider_found/%s:%s";
48 class FakeUsbDevice
: public device::UsbDevice
{
50 FakeUsbDevice(uint16 vendor_id
, uint16 product_id
, uint8 interface_class
)
51 : device::UsbDevice(vendor_id
,
53 base::ASCIIToUTF16("Google"),
54 base::ASCIIToUTF16("A product"),
55 base::ASCIIToUTF16("")) {
56 config_
.reset(new device::UsbConfigDescriptor
);
57 device::UsbInterfaceDescriptor interface
;
58 interface
.interface_number
= 1;
59 interface
.interface_class
= interface_class
;
60 config_
->interfaces
.push_back(interface
);
64 ~FakeUsbDevice() override
{}
66 // device::UsbDevice overrides:
67 void Open(const OpenCallback
& callback
) override
{
68 ADD_FAILURE() << "Not reached";
71 bool Close(scoped_refptr
<device::UsbDeviceHandle
> handle
) override
{
72 ADD_FAILURE() << "Not reached";
76 const device::UsbConfigDescriptor
* GetActiveConfiguration() override
{
80 scoped_ptr
<device::UsbConfigDescriptor
> config_
;
82 DISALLOW_COPY_AND_ASSIGN(FakeUsbDevice
);
85 class FakeDeviceClient
: public device::DeviceClient
{
87 FakeDeviceClient() : usb_service_(nullptr) {}
89 ~FakeDeviceClient() override
{}
91 // device::DeviceClient implementation:
92 device::UsbService
* GetUsbService() override
{
93 EXPECT_TRUE(usb_service_
);
97 void set_usb_service(device::UsbService
* service
) { usb_service_
= service
; }
100 device::UsbService
* usb_service_
;
102 DISALLOW_COPY_AND_ASSIGN(FakeDeviceClient
);
105 scoped_ptr
<KeyedService
> CreatePrinterDetector(
106 content::BrowserContext
* context
) {
107 return scoped_ptr
<KeyedService
>(
108 new chromeos::PrinterDetector(Profile::FromBrowserContext(context
)));
113 // TODO(tbarzic): Rename this test.
114 class PrinterDetectorAppSearchEnabledTest
: public testing::Test
{
116 PrinterDetectorAppSearchEnabledTest()
117 : user_manager_(new user_manager::FakeUserManager()),
118 user_manager_enabler_(user_manager_
) {}
120 ~PrinterDetectorAppSearchEnabledTest() override
= default;
122 void SetUp() override
{
123 device_client_
.set_usb_service(&usb_service_
);
124 // Make sure the profile is created after adding the switch and setting up
126 profile_
.reset(new TestingProfile());
127 chromeos::PrinterDetectorFactory::GetInstance()->SetTestingFactoryAndUse(
128 profile_
.get(), &CreatePrinterDetector
);
130 SetExtensionSystemReady(profile_
.get());
134 void SetExtensionSystemReady(TestingProfile
* profile
) {
135 extensions::TestExtensionSystem
* test_extension_system
=
136 static_cast<extensions::TestExtensionSystem
*>(
137 extensions::ExtensionSystem::Get(profile
));
138 test_extension_system
->SetReady();
139 base::RunLoop().RunUntilIdle();
143 const user_manager::User
* user
= user_manager_
->AddUser(kTestUserId
);
144 profile_
->set_profile_name(kTestUserId
);
145 chromeos::ProfileHelper::Get()->SetUserToProfileMappingForTesting(
146 user
, profile_
.get());
147 chromeos::PrinterDetectorFactory::GetInstance()
148 ->Get(profile_
.get())
149 ->SetNotificationUIManagerForTesting(¬ification_ui_manager_
);
152 void InvokeUsbAdded(uint16 vendor_id
,
154 uint8 interface_class
) {
155 usb_service_
.AddDevice(
156 new FakeUsbDevice(vendor_id
, product_id
, interface_class
));
159 // Creates a test extension with the provided permissions.
160 scoped_refptr
<extensions::Extension
> CreateTestExtension(
161 ListBuilder
& permissions_builder
,
162 DictionaryBuilder
& usb_printers_builder
) {
163 return extensions::ExtensionBuilder()
164 .SetID("fake_extension_id")
167 .Set("name", "Printer provider extension")
168 .Set("manifest_version", 2)
169 .Set("version", "1.0")
170 // Needed to enable usb API.
171 .Set("app", DictionaryBuilder().Set(
173 DictionaryBuilder().Set(
174 "scripts", ListBuilder().Append("bg.js"))))
175 .Set("permissions", permissions_builder
)
176 .Set("usb_printers", usb_printers_builder
))
180 content::TestBrowserThreadBundle thread_bundle_
;
181 StubNotificationUIManager notification_ui_manager_
;
182 user_manager::FakeUserManager
* user_manager_
;
183 chromeos::ScopedUserManagerEnabler user_manager_enabler_
;
184 device::MockUsbService usb_service_
;
185 scoped_ptr
<TestingProfile
> profile_
;
186 FakeDeviceClient device_client_
;
188 DISALLOW_COPY_AND_ASSIGN(PrinterDetectorAppSearchEnabledTest
);
191 TEST_F(PrinterDetectorAppSearchEnabledTest
, ShowFindAppNotification
) {
192 InvokeUsbAdded(123, 456, kPrinterInterfaceClass
);
194 ASSERT_EQ(1u, notification_ui_manager_
.GetNotificationCount());
195 const Notification
& notification
=
196 notification_ui_manager_
.GetNotificationAt(0);
197 EXPECT_EQ("123:456", notification
.tag());
199 base::StringPrintf(kPrinterAppNotFoundDelegateIDTemplate
, "123", "456"),
200 notification
.delegate_id());
203 TEST_F(PrinterDetectorAppSearchEnabledTest
, ShowAppFoundNotification
) {
204 scoped_refptr
<extensions::Extension
> extension
= CreateTestExtension(
207 .Append("printerProvider")
208 .Append(DictionaryBuilder().Set(
209 "usbDevices", ListBuilder().Append(DictionaryBuilder()
210 .Set("vendorId", 123)
211 .Set("productId", 456))))
213 DictionaryBuilder().Set("filters", ListBuilder().Pass()).Pass());
214 ASSERT_TRUE(extensions::ExtensionRegistry::Get(profile_
.get())
215 ->AddEnabled(extension
));
217 InvokeUsbAdded(123, 456, kPrinterInterfaceClass
);
219 ASSERT_EQ(1u, notification_ui_manager_
.GetNotificationCount());
220 const Notification
& notification
=
221 notification_ui_manager_
.GetNotificationAt(0);
222 EXPECT_EQ("123:456", notification
.tag());
224 base::StringPrintf(kPrinterAppExistsDelegateIDTemplate
, "123", "456"),
225 notification
.delegate_id());
228 TEST_F(PrinterDetectorAppSearchEnabledTest
,
229 UsbHandlerExists_NotPrinterProvider
) {
230 scoped_refptr
<extensions::Extension
> extension
= CreateTestExtension(
233 .Append(DictionaryBuilder().Set(
234 "usbDevices", ListBuilder().Append(DictionaryBuilder()
235 .Set("vendorId", 123)
236 .Set("productId", 756))))
238 DictionaryBuilder().Set("filters", ListBuilder().Pass()).Pass());
239 ASSERT_TRUE(extensions::ExtensionRegistry::Get(profile_
.get())
240 ->AddEnabled(extension
));
242 InvokeUsbAdded(123, 756, kPrinterInterfaceClass
);
244 ASSERT_EQ(1u, notification_ui_manager_
.GetNotificationCount());
245 const Notification
& notification
=
246 notification_ui_manager_
.GetNotificationAt(0);
247 EXPECT_EQ("123:756", notification
.tag());
249 base::StringPrintf(kPrinterAppNotFoundDelegateIDTemplate
, "123", "756"),
250 notification
.delegate_id());
253 TEST_F(PrinterDetectorAppSearchEnabledTest
,
254 PrinterProvider_DifferentUsbProductId
) {
255 scoped_refptr
<extensions::Extension
> extension
= CreateTestExtension(
258 .Append("printerProvider")
259 .Append(DictionaryBuilder().Set(
260 "usbDevices", ListBuilder().Append(DictionaryBuilder()
261 .Set("vendorId", 123)
262 .Set("productId", 001))))
264 DictionaryBuilder().Set("filters", ListBuilder().Pass()).Pass());
265 ASSERT_TRUE(extensions::ExtensionRegistry::Get(profile_
.get())
266 ->AddEnabled(extension
));
268 InvokeUsbAdded(123, 456, kPrinterInterfaceClass
);
270 ASSERT_EQ(1u, notification_ui_manager_
.GetNotificationCount());
271 const Notification
& notification
=
272 notification_ui_manager_
.GetNotificationAt(0);
273 EXPECT_EQ("123:456", notification
.tag());
275 base::StringPrintf(kPrinterAppNotFoundDelegateIDTemplate
, "123", "456"),
276 notification
.delegate_id());
279 TEST_F(PrinterDetectorAppSearchEnabledTest
,
280 PrinterProvider_UsbPrinters_NotFound
) {
281 scoped_refptr
<extensions::Extension
> extension
=
283 ListBuilder().Append("usb").Append("printerProvider").Pass(),
284 DictionaryBuilder().Set(
285 "filters", ListBuilder().Append(DictionaryBuilder()
286 .Set("vendorId", 123)
287 .Set("productId", 001))))
289 ASSERT_TRUE(extensions::ExtensionRegistry::Get(profile_
.get())
290 ->AddEnabled(extension
));
292 InvokeUsbAdded(123, 456, kPrinterInterfaceClass
);
294 ASSERT_EQ(1u, notification_ui_manager_
.GetNotificationCount());
295 const Notification
& notification
=
296 notification_ui_manager_
.GetNotificationAt(0);
297 EXPECT_EQ("123:456", notification
.tag());
299 base::StringPrintf(kPrinterAppNotFoundDelegateIDTemplate
, "123", "456"),
300 notification
.delegate_id());
303 TEST_F(PrinterDetectorAppSearchEnabledTest
,
304 PrinterProvider_UsbPrinters_WithProductId
) {
305 scoped_refptr
<extensions::Extension
> extension
=
307 ListBuilder().Append("usb").Append("printerProvider").Pass(),
308 DictionaryBuilder().Set(
309 "filters", ListBuilder().Append(DictionaryBuilder()
310 .Set("vendorId", 123)
311 .Set("productId", 456))))
313 ASSERT_TRUE(extensions::ExtensionRegistry::Get(profile_
.get())
314 ->AddEnabled(extension
));
316 InvokeUsbAdded(123, 456, kPrinterInterfaceClass
);
318 ASSERT_EQ(1u, notification_ui_manager_
.GetNotificationCount());
319 const Notification
& notification
=
320 notification_ui_manager_
.GetNotificationAt(0);
321 EXPECT_EQ("123:456", notification
.tag());
323 base::StringPrintf(kPrinterAppExistsDelegateIDTemplate
, "123", "456"),
324 notification
.delegate_id());
327 TEST_F(PrinterDetectorAppSearchEnabledTest
,
328 PrinterProvider_UsbPrinters_WithInterfaceClass
) {
329 scoped_refptr
<extensions::Extension
> extension
=
331 ListBuilder().Append("usb").Append("printerProvider").Pass(),
332 DictionaryBuilder().Set(
334 ListBuilder().Append(
336 .Set("vendorId", 123)
337 .Set("interfaceClass", kPrinterInterfaceClass
)))).Pass();
338 ASSERT_TRUE(extensions::ExtensionRegistry::Get(profile_
.get())
339 ->AddEnabled(extension
));
341 InvokeUsbAdded(123, 456, kPrinterInterfaceClass
);
343 ASSERT_EQ(1u, notification_ui_manager_
.GetNotificationCount());
344 const Notification
& notification
=
345 notification_ui_manager_
.GetNotificationAt(0);
346 EXPECT_EQ("123:456", notification
.tag());
348 base::StringPrintf(kPrinterAppExistsDelegateIDTemplate
, "123", "456"),
349 notification
.delegate_id());
352 TEST_F(PrinterDetectorAppSearchEnabledTest
, IgnoreNonPrinters
) {
353 scoped_refptr
<extensions::Extension
> extension
=
355 ListBuilder().Append("usb").Append("printerProvider").Pass(),
356 DictionaryBuilder().Set(
358 ListBuilder().Append(
360 .Set("vendorId", 123)
361 .Set("interfaceClass", kPrinterInterfaceClass
)))).Pass();
362 ASSERT_TRUE(extensions::ExtensionRegistry::Get(profile_
.get())
363 ->AddEnabled(extension
));
365 InvokeUsbAdded(123, 456, 1);
367 ASSERT_EQ(0u, notification_ui_manager_
.GetNotificationCount());
370 } // namespace chromeos