1 // Copyright 2015 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.
6 #include "base/json/json_string_value_serializer.h"
7 #include "base/run_loop.h"
8 #include "base/strings/stringprintf.h"
9 #include "extensions/browser/api/printer_provider/printer_provider_api.h"
10 #include "extensions/browser/extension_registry.h"
11 #include "extensions/common/extension.h"
12 #include "extensions/shell/test/shell_apitest.h"
13 #include "extensions/test/extension_test_message_listener.h"
14 #include "extensions/test/result_catcher.h"
15 #include "testing/gtest/include/gtest/gtest.h"
19 using extensions::PrinterProviderAPI
;
21 // Callback for PrinterProviderAPI::DispatchGetPrintersRequested calls.
22 // It appends items in |printers| to |*printers_out|. If |done| is set, it runs
24 void AppendPrintersAndRunCallbackIfDone(base::ListValue
* printers_out
,
25 const base::Closure
& callback
,
26 const base::ListValue
& printers
,
28 for (size_t i
= 0; i
< printers
.GetSize(); ++i
) {
29 const base::DictionaryValue
* printer
= NULL
;
30 EXPECT_TRUE(printers
.GetDictionary(i
, &printer
))
31 << "Found invalid printer value at index " << i
<< ": " << printers
;
33 printers_out
->Append(printer
->DeepCopy());
35 if (done
&& !callback
.is_null())
39 // Callback for PrinterProviderAPI::DispatchPrintRequested calls.
40 // It copies |value| to |*result| and runs |callback|.
41 void RecordPrintErrorAndRunCallback(PrinterProviderAPI::PrintError
* result
,
42 const base::Closure
& callback
,
43 PrinterProviderAPI::PrintError value
) {
45 if (!callback
.is_null())
49 // Callback for PrinterProviderAPI::DispatchGetCapabilityRequested calls.
50 // It saves reported |value| as JSON string to |*result| and runs |callback|.
51 void RecordDictAndRunCallback(std::string
* result
,
52 const base::Closure
& callback
,
53 const base::DictionaryValue
& value
) {
54 JSONStringValueSerializer
serializer(result
);
55 EXPECT_TRUE(serializer
.Serialize(value
));
56 if (!callback
.is_null())
60 // Tests for chrome.printerProvider API.
61 class PrinterProviderApiTest
: public extensions::ShellApiTest
{
63 PrinterProviderApiTest() {}
64 ~PrinterProviderApiTest() override
{}
66 void StartGetPrintersRequest(
67 const PrinterProviderAPI::GetPrintersCallback
& callback
) {
68 PrinterProviderAPI::GetFactoryInstance()
69 ->Get(browser_context())
70 ->DispatchGetPrintersRequested(callback
);
73 void StartPrintRequest(const std::string
& extension_id
,
74 const PrinterProviderAPI::PrintCallback
& callback
) {
75 PrinterProviderAPI::PrintJob job
;
76 job
.printer_id
= extension_id
+ ":printer_id";
77 job
.ticket_json
= "{}";
78 job
.content_type
= "content_type";
79 job
.document_bytes
= "bytes";
81 PrinterProviderAPI::GetFactoryInstance()
82 ->Get(browser_context())
83 ->DispatchPrintRequested(job
, callback
);
86 void StartCapabilityRequest(
87 const std::string
& extension_id
,
88 const PrinterProviderAPI::GetCapabilityCallback
& callback
) {
89 PrinterProviderAPI::GetFactoryInstance()
90 ->Get(browser_context())
91 ->DispatchGetCapabilityRequested(extension_id
+ ":printer_id",
95 // Loads chrome.printerProvider test app and initializes is for test
97 // When the app's background page is loaded, the app will send 'loaded'
98 // message. As a response to the message it will expect string message
99 // specifying the test that should be run. When the app initializes its state
100 // (e.g. registers listener for a chrome.printerProvider event) it will send
101 // message 'ready', at which point the test may be started.
102 // If the app is successfully initialized, |*extension_id_out| will be set to
103 // the loaded extension's id, otherwise it will remain unchanged.
104 void InitializePrinterProviderTestApp(const std::string
& app_path
,
105 const std::string
& test_param
,
106 std::string
* extension_id_out
) {
107 ExtensionTestMessageListener
loaded_listener("loaded", true);
108 ExtensionTestMessageListener
ready_listener("ready", false);
110 const extensions::Extension
* extension
= LoadApp(app_path
);
111 ASSERT_TRUE(extension
);
112 const std::string extension_id
= extension
->id();
114 loaded_listener
.set_extension_id(extension_id
);
115 ready_listener
.set_extension_id(extension_id
);
117 ASSERT_TRUE(loaded_listener
.WaitUntilSatisfied());
119 loaded_listener
.Reply(test_param
);
121 ASSERT_TRUE(ready_listener
.WaitUntilSatisfied());
123 *extension_id_out
= extension_id
;
126 // Runs a test for chrome.printerProvider.onPrintRequested event.
127 // |test_param|: The test that should be run.
128 // |expected_result|: The print result the app is expected to report.
129 void RunPrintRequestTestApp(const std::string
& test_param
,
130 PrinterProviderAPI::PrintError expected_result
) {
131 extensions::ResultCatcher catcher
;
133 std::string extension_id
;
134 InitializePrinterProviderTestApp("api_test/printer_provider/request_print",
135 test_param
, &extension_id
);
136 if (extension_id
.empty())
139 base::RunLoop run_loop
;
140 PrinterProviderAPI::PrintError print_result
;
141 StartPrintRequest(extension_id
,
142 base::Bind(&RecordPrintErrorAndRunCallback
, &print_result
,
143 run_loop
.QuitClosure()));
145 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
148 EXPECT_EQ(expected_result
, print_result
);
151 // Runs a test for chrome.printerProvider.onGetCapabilityRequested
153 // |test_param|: The test that should be run.
154 // |expected_result|: The printer capability the app is expected to report.
155 void RunPrinterCapabilitiesRequestTest(const std::string
& test_param
,
156 const std::string
& expected_result
) {
157 extensions::ResultCatcher catcher
;
159 std::string extension_id
;
160 InitializePrinterProviderTestApp(
161 "api_test/printer_provider/request_capability", test_param
,
163 if (extension_id
.empty())
166 base::RunLoop run_loop
;
168 StartCapabilityRequest(
170 base::Bind(&RecordDictAndRunCallback
, &result
, run_loop
.QuitClosure()));
172 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
175 EXPECT_EQ(expected_result
, result
);
178 bool SimulateExtensionUnload(const std::string
& extension_id
) {
179 extensions::ExtensionRegistry
* extension_registry
=
180 extensions::ExtensionRegistry::Get(browser_context());
182 const extensions::Extension
* extension
=
183 extension_registry
->GetExtensionById(
184 extension_id
, extensions::ExtensionRegistry::ENABLED
);
188 extension_registry
->RemoveEnabled(extension_id
);
189 extension_registry
->TriggerOnUnloaded(
190 extension
, extensions::UnloadedExtensionInfo::REASON_TERMINATE
);
194 // Validates that set of printers reported by test apps via
195 // chrome.printerProvider.onGetPritersRequested is the same as the set of
196 // printers in |expected_printers|. |expected_printers| contains list of
197 // printer objects formatted as a JSON string. It is assumed that the values
198 // in |expoected_printers| are unique.
199 void ValidatePrinterListValue(
200 const base::ListValue
& printers
,
201 const std::vector
<std::string
>& expected_printers
) {
202 ASSERT_EQ(expected_printers
.size(), printers
.GetSize());
203 for (size_t i
= 0; i
< expected_printers
.size(); ++i
) {
204 JSONStringValueSerializer
serializer(expected_printers
[i
]);
206 scoped_ptr
<base::Value
> printer_value(
207 serializer
.Deserialize(&error_code
, NULL
));
208 ASSERT_TRUE(printer_value
) << "Failed to deserialize "
209 << expected_printers
[i
] << ": "
210 << "error code " << error_code
;
211 EXPECT_TRUE(printers
.Find(*printer_value
) != printers
.end())
212 << "Unabe to find " << *printer_value
<< " in " << printers
;
217 DISALLOW_COPY_AND_ASSIGN(PrinterProviderApiTest
);
220 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, PrintJobSuccess
) {
221 RunPrintRequestTestApp("OK", PrinterProviderAPI::PRINT_ERROR_NONE
);
224 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, PrintJobAsyncSuccess
) {
225 RunPrintRequestTestApp("ASYNC_RESPONSE",
226 PrinterProviderAPI::PRINT_ERROR_NONE
);
229 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, PrintJobFailed
) {
230 RunPrintRequestTestApp("INVALID_TICKET",
231 PrinterProviderAPI::PRINT_ERROR_INVALID_TICKET
);
234 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, NoPrintEventListener
) {
235 RunPrintRequestTestApp("NO_LISTENER", PrinterProviderAPI::PRINT_ERROR_FAILED
);
238 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
,
239 PrintRequestInvalidCallbackParam
) {
240 RunPrintRequestTestApp("INVALID_VALUE",
241 PrinterProviderAPI::PRINT_ERROR_FAILED
);
244 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, PrintRequestAppUnloaded
) {
245 extensions::ResultCatcher catcher
;
247 std::string extension_id
;
248 InitializePrinterProviderTestApp("api_test/printer_provider/request_print",
249 "IGNORE_CALLBACK", &extension_id
);
250 ASSERT_FALSE(extension_id
.empty());
252 base::RunLoop run_loop
;
253 PrinterProviderAPI::PrintError print_result
;
254 StartPrintRequest(extension_id
,
255 base::Bind(&RecordPrintErrorAndRunCallback
, &print_result
,
256 run_loop
.QuitClosure()));
258 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
260 ASSERT_TRUE(SimulateExtensionUnload(extension_id
));
263 EXPECT_EQ(PrinterProviderAPI::PRINT_ERROR_FAILED
, print_result
);
266 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetCapabilitySuccess
) {
267 RunPrinterCapabilitiesRequestTest("OK", "{\"capability\":\"value\"}");
270 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetCapabilityAsyncSuccess
) {
271 RunPrinterCapabilitiesRequestTest("ASYNC_RESPONSE",
272 "{\"capability\":\"value\"}");
275 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, EmptyCapability
) {
276 RunPrinterCapabilitiesRequestTest("EMPTY", "{}");
279 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, NoCapabilityEventListener
) {
280 RunPrinterCapabilitiesRequestTest("NO_LISTENER", "{}");
283 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, CapabilityInvalidValue
) {
284 RunPrinterCapabilitiesRequestTest("INVALID_VALUE", "{}");
287 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetCapabilityAppUnloaded
) {
288 extensions::ResultCatcher catcher
;
290 std::string extension_id
;
291 InitializePrinterProviderTestApp(
292 "api_test/printer_provider/request_capability", "IGNORE_CALLBACK",
294 ASSERT_FALSE(extension_id
.empty());
296 base::RunLoop run_loop
;
298 StartCapabilityRequest(
300 base::Bind(&RecordDictAndRunCallback
, &result
, run_loop
.QuitClosure()));
302 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
304 ASSERT_TRUE(SimulateExtensionUnload(extension_id
));
306 EXPECT_EQ("{}", result
);
309 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetPrintersSuccess
) {
310 extensions::ResultCatcher catcher
;
312 std::string extension_id
;
313 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
314 "OK", &extension_id
);
315 ASSERT_FALSE(extension_id
.empty());
317 base::RunLoop run_loop
;
318 base::ListValue printers
;
320 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
321 &printers
, run_loop
.QuitClosure()));
323 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
327 std::vector
<std::string
> expected_printers
;
328 expected_printers
.push_back(base::StringPrintf(
330 "\"description\":\"Test printer\","
331 "\"extensionId\":\"%s\","
332 "\"id\":\"%s:printer1\","
333 "\"name\":\"Printer 1\""
335 extension_id
.c_str(), extension_id
.c_str()));
336 expected_printers
.push_back(base::StringPrintf(
338 "\"extensionId\":\"%s\","
339 "\"id\":\"%s:printerNoDesc\","
340 "\"name\":\"Printer 2\""
342 extension_id
.c_str(), extension_id
.c_str()));
344 ValidatePrinterListValue(printers
, expected_printers
);
347 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetPrintersAsyncSuccess
) {
348 extensions::ResultCatcher catcher
;
350 std::string extension_id
;
351 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
352 "ASYNC_RESPONSE", &extension_id
);
353 ASSERT_FALSE(extension_id
.empty());
355 base::RunLoop run_loop
;
356 base::ListValue printers
;
358 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
359 &printers
, run_loop
.QuitClosure()));
361 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
365 std::vector
<std::string
> expected_printers
;
366 expected_printers
.push_back(base::StringPrintf(
368 "\"description\":\"Test printer\","
369 "\"extensionId\":\"%s\","
370 "\"id\":\"%s:printer1\","
371 "\"name\":\"Printer 1\""
373 extension_id
.c_str(), extension_id
.c_str()));
375 ValidatePrinterListValue(printers
, expected_printers
);
378 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetPrintersTwoExtensions
) {
379 extensions::ResultCatcher catcher
;
381 std::string extension_id_1
;
382 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
383 "OK", &extension_id_1
);
384 ASSERT_FALSE(extension_id_1
.empty());
386 std::string extension_id_2
;
387 InitializePrinterProviderTestApp(
388 "api_test/printer_provider/request_printers_second", "OK",
390 ASSERT_FALSE(extension_id_2
.empty());
392 base::RunLoop run_loop
;
393 base::ListValue printers
;
395 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
396 &printers
, run_loop
.QuitClosure()));
398 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
399 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
403 std::vector
<std::string
> expected_printers
;
404 expected_printers
.push_back(base::StringPrintf(
406 "\"description\":\"Test printer\","
407 "\"extensionId\":\"%s\","
408 "\"id\":\"%s:printer1\","
409 "\"name\":\"Printer 1\""
411 extension_id_1
.c_str(), extension_id_1
.c_str()));
412 expected_printers
.push_back(base::StringPrintf(
414 "\"extensionId\":\"%s\","
415 "\"id\":\"%s:printerNoDesc\","
416 "\"name\":\"Printer 2\""
418 extension_id_1
.c_str(), extension_id_1
.c_str()));
419 expected_printers
.push_back(base::StringPrintf(
421 "\"description\":\"Test printer\","
422 "\"extensionId\":\"%s\","
423 "\"id\":\"%s:printer1\","
424 "\"name\":\"Printer 1\""
426 extension_id_2
.c_str(), extension_id_2
.c_str()));
427 expected_printers
.push_back(base::StringPrintf(
429 "\"extensionId\":\"%s\","
430 "\"id\":\"%s:printerNoDesc\","
431 "\"name\":\"Printer 2\""
433 extension_id_2
.c_str(), extension_id_2
.c_str()));
435 ValidatePrinterListValue(printers
, expected_printers
);
438 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
,
439 GetPrintersTwoExtensionsBothUnloaded
) {
440 extensions::ResultCatcher catcher
;
442 std::string extension_id_1
;
443 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
444 "IGNORE_CALLBACK", &extension_id_1
);
445 ASSERT_FALSE(extension_id_1
.empty());
447 std::string extension_id_2
;
448 InitializePrinterProviderTestApp(
449 "api_test/printer_provider/request_printers_second", "IGNORE_CALLBACK",
451 ASSERT_FALSE(extension_id_2
.empty());
453 base::RunLoop run_loop
;
454 base::ListValue printers
;
456 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
457 &printers
, run_loop
.QuitClosure()));
459 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
460 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
462 ASSERT_TRUE(SimulateExtensionUnload(extension_id_1
));
463 ASSERT_TRUE(SimulateExtensionUnload(extension_id_2
));
467 EXPECT_TRUE(printers
.empty());
470 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
,
471 GetPrintersTwoExtensionsOneFails
) {
472 extensions::ResultCatcher catcher
;
474 std::string extension_id_1
;
475 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
476 "NOT_ARRAY", &extension_id_1
);
477 ASSERT_FALSE(extension_id_1
.empty());
479 std::string extension_id_2
;
480 InitializePrinterProviderTestApp(
481 "api_test/printer_provider/request_printers_second", "OK",
483 ASSERT_FALSE(extension_id_2
.empty());
485 base::RunLoop run_loop
;
486 base::ListValue printers
;
488 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
489 &printers
, run_loop
.QuitClosure()));
491 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
492 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
496 std::vector
<std::string
> expected_printers
;
497 expected_printers
.push_back(base::StringPrintf(
499 "\"description\":\"Test printer\","
500 "\"extensionId\":\"%s\","
501 "\"id\":\"%s:printer1\","
502 "\"name\":\"Printer 1\""
504 extension_id_2
.c_str(), extension_id_2
.c_str()));
505 expected_printers
.push_back(base::StringPrintf(
507 "\"extensionId\":\"%s\","
508 "\"id\":\"%s:printerNoDesc\","
509 "\"name\":\"Printer 2\""
511 extension_id_2
.c_str(), extension_id_2
.c_str()));
513 ValidatePrinterListValue(printers
, expected_printers
);
516 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
,
517 GetPrintersTwoExtensionsOneWithNoListener
) {
518 extensions::ResultCatcher catcher
;
520 std::string extension_id_1
;
521 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
522 "NO_LISTENER", &extension_id_1
);
523 ASSERT_FALSE(extension_id_1
.empty());
525 std::string extension_id_2
;
526 InitializePrinterProviderTestApp(
527 "api_test/printer_provider/request_printers_second", "OK",
529 ASSERT_FALSE(extension_id_2
.empty());
531 base::RunLoop run_loop
;
532 base::ListValue printers
;
534 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
535 &printers
, run_loop
.QuitClosure()));
537 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
538 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
542 std::vector
<std::string
> expected_printers
;
543 expected_printers
.push_back(base::StringPrintf(
545 "\"description\":\"Test printer\","
546 "\"extensionId\":\"%s\","
547 "\"id\":\"%s:printer1\","
548 "\"name\":\"Printer 1\""
550 extension_id_2
.c_str(), extension_id_2
.c_str()));
551 expected_printers
.push_back(base::StringPrintf(
553 "\"extensionId\":\"%s\","
554 "\"id\":\"%s:printerNoDesc\","
555 "\"name\":\"Printer 2\""
557 extension_id_2
.c_str(), extension_id_2
.c_str()));
559 ValidatePrinterListValue(printers
, expected_printers
);
562 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetPrintersNoListener
) {
563 extensions::ResultCatcher catcher
;
565 std::string extension_id
;
566 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
567 "NO_LISTENER", &extension_id
);
568 ASSERT_FALSE(extension_id
.empty());
570 base::RunLoop run_loop
;
571 base::ListValue printers
;
573 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
574 &printers
, run_loop
.QuitClosure()));
576 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
580 EXPECT_TRUE(printers
.empty());
583 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetPrintersNotArray
) {
584 extensions::ResultCatcher catcher
;
586 std::string extension_id
;
587 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
588 "NOT_ARRAY", &extension_id
);
589 ASSERT_FALSE(extension_id
.empty());
591 base::RunLoop run_loop
;
592 base::ListValue printers
;
594 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
595 &printers
, run_loop
.QuitClosure()));
597 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
601 EXPECT_TRUE(printers
.empty());
604 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
,
605 GetPrintersInvalidPrinterValueType
) {
606 extensions::ResultCatcher catcher
;
608 std::string extension_id
;
609 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
610 "INVALID_PRINTER_TYPE", &extension_id
);
611 ASSERT_FALSE(extension_id
.empty());
613 base::RunLoop run_loop
;
614 base::ListValue printers
;
616 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
617 &printers
, run_loop
.QuitClosure()));
619 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
623 EXPECT_TRUE(printers
.empty());
626 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetPrintersInvalidPrinterValue
) {
627 extensions::ResultCatcher catcher
;
629 std::string extension_id
;
630 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
631 "INVALID_PRINTER", &extension_id
);
632 ASSERT_FALSE(extension_id
.empty());
634 base::RunLoop run_loop
;
635 base::ListValue printers
;
637 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
638 &printers
, run_loop
.QuitClosure()));
640 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
644 EXPECT_TRUE(printers
.empty());