diff options
author | tbarzic <tbarzic@chromium.org> | 2015-02-26 19:17:34 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-27 03:19:05 +0000 |
commit | 089e28561693b3287409b96048d0c3c02cd0b740 (patch) | |
tree | 2bce2686e9fed63a3b521bb40e681f6d161c0ab2 | |
parent | 715d4a3869c5fe16fa45a15a15e9583de4581527 (diff) | |
download | chromium_src-089e28561693b3287409b96048d0c3c02cd0b740.zip chromium_src-089e28561693b3287409b96048d0c3c02cd0b740.tar.gz chromium_src-089e28561693b3287409b96048d0c3c02cd0b740.tar.bz2 |
Add tests for ExtensionPrinterHandler
In process, changed ExtensionPrinterHandler construction so
pwg_raster_converter and task runner for reading converted PWG file
can be injected through constructor.
BUG=461114
TEST=unit_tests --gtest_filter=ExtensionPrinterHandler*
Review URL: https://codereview.chromium.org/954283003
Cr-Commit-Position: refs/heads/master@{#318390}
5 files changed, 809 insertions, 17 deletions
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc index aaeb3ff..e47a228 100644 --- a/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc +++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc @@ -14,7 +14,6 @@ #include "base/memory/ref_counted.h" #include "base/memory/ref_counted_memory.h" #include "base/task_runner_util.h" -#include "base/threading/worker_pool.h" #include "chrome/browser/local_discovery/pwg_raster_converter.h" #include "components/cloud_devices/common/cloud_device_description.h" #include "components/cloud_devices/common/printer_description.h" @@ -33,6 +32,7 @@ const char kContentTypePWGRaster[] = "image/pwg-raster"; const char kContentTypeAll[] = "*/*"; const char kInvalidDataPrintError[] = "INVALID_DATA"; +const char kInvalidTicketPrintError[] = "INVALID_TICKET"; // Reads raster data from file path |raster_path| and returns it as // RefCountedMemory. Returns NULL on error. @@ -57,6 +57,7 @@ scoped_refptr<base::RefCountedMemory> ReadConvertedPWGRasterFileOnWorkerThread( // Posts a task to read a file containing converted PWG raster data to the // worker pool. void ReadConvertedPWGRasterFile( + const scoped_refptr<base::TaskRunner>& slow_task_runner, const ExtensionPrinterHandler::RefCountedMemoryCallback& callback, bool success, const base::FilePath& pwg_file_path) { @@ -66,7 +67,7 @@ void ReadConvertedPWGRasterFile( } base::PostTaskAndReplyWithResult( - base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE, + slow_task_runner.get(), FROM_HERE, base::Bind(&ReadConvertedPWGRasterFileOnWorkerThread, pwg_file_path), callback); } @@ -74,8 +75,11 @@ void ReadConvertedPWGRasterFile( } // namespace ExtensionPrinterHandler::ExtensionPrinterHandler( - content::BrowserContext* browser_context) - : browser_context_(browser_context), weak_ptr_factory_(this) { + content::BrowserContext* browser_context, + const scoped_refptr<base::TaskRunner>& slow_task_runner) + : browser_context_(browser_context), + slow_task_runner_(slow_task_runner), + weak_ptr_factory_(this) { } ExtensionPrinterHandler::~ExtensionPrinterHandler() { @@ -134,25 +138,30 @@ void ExtensionPrinterHandler::StartPrint( return; } + cloud_devices::CloudDeviceDescription ticket; + if (!ticket.InitFromString(ticket_json)) { + WrapPrintCallback(callback, false, kInvalidTicketPrintError); + return; + } + print_job->content_type = kContentTypePWGRaster; - ConvertToPWGRaster(print_data, printer_description, ticket_json, page_size, + ConvertToPWGRaster(print_data, printer_description, ticket, page_size, base::Bind(&ExtensionPrinterHandler::DispatchPrintJob, weak_ptr_factory_.GetWeakPtr(), callback, base::Passed(&print_job))); } +void ExtensionPrinterHandler::SetPwgRasterConverterForTesting( + scoped_ptr<local_discovery::PWGRasterConverter> pwg_raster_converter) { + pwg_raster_converter_ = pwg_raster_converter.Pass(); +} + void ExtensionPrinterHandler::ConvertToPWGRaster( const scoped_refptr<base::RefCountedMemory>& data, const cloud_devices::CloudDeviceDescription& printer_description, - const std::string& ticket_json, + const cloud_devices::CloudDeviceDescription& ticket, const gfx::Size& page_size, const ExtensionPrinterHandler::RefCountedMemoryCallback& callback) { - cloud_devices::CloudDeviceDescription ticket; - if (!ticket.InitFromString(ticket_json)) { - callback.Run(scoped_refptr<base::RefCountedMemory>()); - return; - } - if (!pwg_raster_converter_) { pwg_raster_converter_ = PWGRasterConverter::CreateDefault(); } @@ -160,7 +169,7 @@ void ExtensionPrinterHandler::ConvertToPWGRaster( data.get(), PWGRasterConverter::GetConversionSettings(printer_description, page_size), PWGRasterConverter::GetBitmapSettings(printer_description, ticket), - base::Bind(&ReadConvertedPWGRasterFile, callback)); + base::Bind(&ReadConvertedPWGRasterFile, slow_task_runner_, callback)); } void ExtensionPrinterHandler::DispatchPrintJob( diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler.h b/chrome/browser/ui/webui/print_preview/extension_printer_handler.h index 89238e2..408c4bc 100644 --- a/chrome/browser/ui/webui/print_preview/extension_printer_handler.h +++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler.h @@ -17,6 +17,7 @@ namespace base { class DictionaryValue; class ListValue; class RefCountedMemory; +class TaskRunner; } namespace content { @@ -42,7 +43,9 @@ class ExtensionPrinterHandler : public PrinterHandler { using RefCountedMemoryCallback = base::Callback<void(const scoped_refptr<base::RefCountedMemory>&)>; - explicit ExtensionPrinterHandler(content::BrowserContext* browser_context); + ExtensionPrinterHandler( + content::BrowserContext* browser_context, + const scoped_refptr<base::TaskRunner>& slow_task_runner); ~ExtensionPrinterHandler() override; @@ -62,13 +65,18 @@ class ExtensionPrinterHandler : public PrinterHandler { const PrinterHandler::PrintCallback& callback) override; private: + friend class ExtensionPrinterHandlerTest; + + void SetPwgRasterConverterForTesting( + scoped_ptr<local_discovery::PWGRasterConverter> pwg_raster_converter); + // Converts |data| to PWG raster format (from PDF) for a printer described // by |printer_description|. // |callback| is called with the converted data. void ConvertToPWGRaster( const scoped_refptr<base::RefCountedMemory>& data, const cloud_devices::CloudDeviceDescription& printer_description, - const std::string& ticket, + const cloud_devices::CloudDeviceDescription& ticket, const gfx::Size& page_size, const RefCountedMemoryCallback& callback); @@ -97,6 +105,8 @@ class ExtensionPrinterHandler : public PrinterHandler { scoped_ptr<local_discovery::PWGRasterConverter> pwg_raster_converter_; + scoped_refptr<base::TaskRunner> slow_task_runner_; + base::WeakPtrFactory<ExtensionPrinterHandler> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(ExtensionPrinterHandler); diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc new file mode 100644 index 0000000..7fb2c96 --- /dev/null +++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc @@ -0,0 +1,771 @@ +// Copyright 2015 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/bind.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/json/json_string_value_serializer.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/run_loop.h" +#include "base/values.h" +#include "chrome/browser/local_discovery/pwg_raster_converter.h" +#include "chrome/browser/ui/webui/print_preview/extension_printer_handler.h" +#include "chrome/test/base/testing_profile.h" +#include "extensions/browser/api/printer_provider/printer_provider_api.h" +#include "extensions/browser/api/printer_provider/printer_provider_api_factory.h" +#include "extensions/browser/api/printer_provider/printer_provider_print_job.h" +#include "printing/pdf_render_settings.h" +#include "printing/pwg_raster_settings.h" +#include "printing/units.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/size.h" + +using extensions::PrinterProviderAPI; +using extensions::PrinterProviderPrintJob; +using local_discovery::PWGRasterConverter; + +namespace { + +// Printer id used for requests in tests. +const char kPrinterId[] = "printer_id"; + +// Printer list used a result for getPrinters. +const char kPrinterDescriptionList[] = + "[{" + " \"id\": \"printer1\"," + " \"name\": \"Printer 1\"" + "}, {" + " \"id\": \"printer2\"," + " \"name\": \"Printer 2\"," + " \"description\": \"Test printer 2\"" + "}]"; + +// Printer capability for printer that supports all content types. +const char kAllContentTypesSupportedPrinter[] = + "{" + " \"version\": \"1.0\"," + " \"printer\": {" + " \"supported_content_type\": [" + " {\"content_type\": \"*/*\"}" + " ]" + " }" + "}"; + +// Printer capability for a printer that supports PDF. +const char kPdfSupportedPrinter[] = + "{" + " \"version\": \"1.0\"," + " \"printer\": {" + " \"supported_content_type\": [" + " {\"content_type\": \"application/pdf\"}," + " {\"content_type\": \"image/pwg-raster\"}" + " ]" + " }" + "}"; + +// Printer capability for a printer that supportd only PWG raster. +const char kPWGRasterOnlyPrinterSimpleDescription[] = + "{" + " \"version\": \"1.0\"," + " \"printer\": {" + " \"supported_content_type\": [" + " {\"content_type\": \"image/pwg-raster\"}" + " ]" + " }" + "}"; + +// Printer capability for a printer that supportd only PWG raster that has +// options other that supported_content_type set. +const char kPWGRasterOnlyPrinter[] = + "{" + " \"version\": \"1.0\"," + " \"printer\": {" + " \"supported_content_type\": [" + " {\"content_type\": \"image/pwg-raster\"}" + " ]," + " \"pwg_raster_config\": {" + " \"document_sheet_back\": \"FLIPPED\"," + " \"reverse_order_streaming\": true," + " \"rotate_all_pages\": true" + " }," + " \"dpi\": {" + " \"option\": [{" + " \"horizontal_dpi\": 100," + " \"vertical_dpi\": 200," + " \"is_default\": true" + " }]" + " }" + " }" + "}"; + +// Print ticket with no parameters set. +const char kEmptyPrintTicket[] = "{\"version\": \"1.0\"}"; + +// Print ticket that has duplex parameter set. +const char kPrintTicketWithDuplex[] = + "{" + " \"version\": \"1.0\"," + " \"print\": {" + " \"duplex\": {\"type\": \"LONG_EDGE\"}" + " }" + "}"; + +// Suffix appended to document data by fake PWGRasterConverter. +const char kPWGConversionSuffix[] = "_converted"; + +const char kContentTypePDF[] = "application/pdf"; +const char kContentTypePWG[] = "image/pwg-raster"; + +// Print request status considered to be successful by fake PrinterProviderAPI. +const char kPrintRequestSuccess[] = "OK"; + +// Used as a callback to StartGetPrinters in tests. +// Increases |*call_count| and records values returned by StartGetPrinters. +void RecordPrinterList(size_t* call_count, + scoped_ptr<base::ListValue>* printers_out, + bool* is_done_out, + const base::ListValue& printers, + bool is_done) { + ++(*call_count); + printers_out->reset(printers.DeepCopy()); + *is_done_out = is_done; +} + +// Used as a callback to StartGetCapability in tests. +// Increases |*call_count| and records values returned by StartGetCapability. +void RecordCapability(size_t* call_count, + std::string* destination_id_out, + scoped_ptr<base::DictionaryValue>* capability_out, + const std::string& destination_id, + const base::DictionaryValue& capability) { + ++(*call_count); + *destination_id_out = destination_id; + capability_out->reset(capability.DeepCopy()); +} + +// Used as a callback to StartPrint in tests. +// Increases |*call_count| and records values returned by StartPrint. +void RecordPrintResult(size_t* call_count, + bool* success_out, + std::string* status_out, + bool success, + const std::string& status) { + ++(*call_count); + *success_out = success; + *status_out = status; +} + +// Converts JSON string to base::ListValue object. +// On failure, returns NULL and fills |*error| string. +scoped_ptr<base::ListValue> GetJSONAsListValue(const std::string& json, + std::string* error) { + scoped_ptr<base::Value> deserialized( + JSONStringValueSerializer(json).Deserialize(NULL, error)); + if (!deserialized) + return scoped_ptr<base::ListValue>(); + base::ListValue* list = nullptr; + if (!deserialized->GetAsList(&list)) { + *error = "Value is not a list."; + return scoped_ptr<base::ListValue>(); + } + return scoped_ptr<base::ListValue>(list->DeepCopy()); +} + +// Converts JSON string to base::DictionaryValue object. +// On failure, returns NULL and fills |*error| string. +scoped_ptr<base::DictionaryValue> GetJSONAsDictionaryValue( + const std::string& json, + std::string* error) { + scoped_ptr<base::Value> deserialized( + JSONStringValueSerializer(json).Deserialize(NULL, error)); + if (!deserialized) + return scoped_ptr<base::DictionaryValue>(); + base::DictionaryValue* dictionary; + if (!deserialized->GetAsDictionary(&dictionary)) { + *error = "Value is not a dictionary."; + return scoped_ptr<base::DictionaryValue>(); + } + return scoped_ptr<base::DictionaryValue>(dictionary->DeepCopy()); +} + +// Fake PWGRasterconverter used in the tests. +class FakePWGRasterConverter : public PWGRasterConverter { + public: + FakePWGRasterConverter() : fail_conversion_(false), initialized_(false) {} + ~FakePWGRasterConverter() override = default; + + // PWGRasterConverter implementation. + // It writes |data| to a temp file, appending it |kPWGConversionSuffix|. + // Also, remembers conversion and bitmap settings passed into the method. + void Start(base::RefCountedMemory* data, + const printing::PdfRenderSettings& conversion_settings, + const printing::PwgRasterSettings& bitmap_settings, + const ResultCallback& callback) override { + if (fail_conversion_) { + callback.Run(false, base::FilePath()); + return; + } + + if (!initialized_ && !temp_dir_.CreateUniqueTempDir()) { + ADD_FAILURE() << "Unable to create target dir for cenverter"; + callback.Run(false, base::FilePath()); + return; + } + + initialized_ = true; + + std::string data_str(data->front_as<char>(), data->size()); + data_str.append(kPWGConversionSuffix); + base::FilePath target_path = temp_dir_.path().AppendASCII("output.pwg"); + int written = WriteFile(target_path, data_str.c_str(), data_str.size()); + if (written != static_cast<int>(data_str.size())) { + ADD_FAILURE() << "Failed to write pwg raster file."; + callback.Run(false, base::FilePath()); + return; + } + + conversion_settings_ = conversion_settings; + bitmap_settings_ = bitmap_settings; + + callback.Run(true, target_path); + } + + // Makes |Start| method always return an error. + void FailConversion() { fail_conversion_ = true; } + + const printing::PdfRenderSettings& conversion_settings() const { + return conversion_settings_; + } + + const printing::PwgRasterSettings& bitmap_settings() const { + return bitmap_settings_; + } + + private: + base::ScopedTempDir temp_dir_; + + printing::PdfRenderSettings conversion_settings_; + printing::PwgRasterSettings bitmap_settings_; + bool fail_conversion_; + bool initialized_; + + DISALLOW_COPY_AND_ASSIGN(FakePWGRasterConverter); +}; + +// Copy of data contained in print job passed to |DispatchPrintRequested|. +struct PrintJobParams { + std::string printer_id; + std::string ticket; + std::string content_type; + std::string document; +}; + +// Information about received print requests. +struct PrintRequestInfo { + PrinterProviderAPI::PrintCallback callback; + PrintJobParams params; +}; + +// Fake PrinterProviderAPI used in tests. +// It caches requests issued to API and exposes methods to trigger their +// callbacks. +class FakePrinterProviderAPI : public PrinterProviderAPI { + public: + FakePrinterProviderAPI() = default; + ~FakePrinterProviderAPI() override = default; + + void DispatchGetPrintersRequested( + const PrinterProviderAPI::GetPrintersCallback& callback) override { + pending_printers_callbacks_.push_back(callback); + } + + void DispatchGetCapabilityRequested( + const std::string& destination_id, + const PrinterProviderAPI::GetCapabilityCallback& callback) override { + pending_capability_callbacks_.push_back(base::Bind(callback)); + } + + void DispatchPrintRequested( + const PrinterProviderPrintJob& job, + const PrinterProviderAPI::PrintCallback& callback) override { + PrintRequestInfo request_info; + request_info.callback = callback; + + request_info.params.printer_id = job.printer_id; + request_info.params.ticket = job.ticket_json; + request_info.params.content_type = job.content_type; + request_info.params.document = std::string( + job.document_bytes->front_as<char>(), job.document_bytes->size()); + + pending_print_requests_.push_back(request_info); + } + + size_t pending_get_printers_count() const { + return pending_printers_callbacks_.size(); + } + + void TriggerNextGetPrintersCallback(const base::ListValue& printers, + bool done) { + ASSERT_GT(pending_get_printers_count(), 0u); + pending_printers_callbacks_[0].Run(printers, done); + pending_printers_callbacks_.erase(pending_printers_callbacks_.begin()); + } + + size_t pending_get_capability_count() const { + return pending_capability_callbacks_.size(); + } + + void TriggerNextGetCapabilityCallback( + const base::DictionaryValue& description) { + ASSERT_GT(pending_get_capability_count(), 0u); + pending_capability_callbacks_[0].Run(description); + pending_capability_callbacks_.erase(pending_capability_callbacks_.begin()); + } + + size_t pending_print_count() const { return pending_print_requests_.size(); } + + const PrintJobParams* GetNextPendingPrintJob() const { + EXPECT_GT(pending_print_count(), 0u); + if (pending_print_count() == 0) + return NULL; + return &pending_print_requests_[0].params; + } + + void TriggerNextPrintCallback(const std::string& result) { + ASSERT_GT(pending_print_count(), 0u); + pending_print_requests_[0].callback.Run(result == kPrintRequestSuccess, + result); + pending_print_requests_.erase(pending_print_requests_.begin()); + } + + private: + std::vector<PrinterProviderAPI::GetPrintersCallback> + pending_printers_callbacks_; + std::vector<PrinterProviderAPI::GetCapabilityCallback> + pending_capability_callbacks_; + std::vector<PrintRequestInfo> pending_print_requests_; + + DISALLOW_COPY_AND_ASSIGN(FakePrinterProviderAPI); +}; + +KeyedService* BuildTestingPrinterProviderAPI(content::BrowserContext* context) { + return new FakePrinterProviderAPI(); +} + +} // namespace + +class ExtensionPrinterHandlerTest : public testing::Test { + public: + ExtensionPrinterHandlerTest() : pwg_raster_converter_(NULL) {} + ~ExtensionPrinterHandlerTest() override = default; + + void SetUp() override { + TestingProfile::Builder profile_builder; + profile_builder.AddTestingFactory( + extensions::PrinterProviderAPIFactory::GetInstance(), + &BuildTestingPrinterProviderAPI); + profile_ = profile_builder.Build(); + + extension_printer_handler_.reset(new ExtensionPrinterHandler( + profile_.get(), message_loop_.task_runner())); + + pwg_raster_converter_ = new FakePWGRasterConverter(); + extension_printer_handler_->SetPwgRasterConverterForTesting( + scoped_ptr<PWGRasterConverter>(pwg_raster_converter_)); + } + + protected: + FakePrinterProviderAPI* GetPrinterProviderAPI() { + return static_cast<FakePrinterProviderAPI*>( + extensions::PrinterProviderAPIFactory::GetInstance() + ->GetForBrowserContext(profile_.get())); + } + + scoped_ptr<ExtensionPrinterHandler> extension_printer_handler_; + + FakePWGRasterConverter* pwg_raster_converter_; + + private: + base::MessageLoop message_loop_; + + scoped_ptr<TestingProfile> profile_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionPrinterHandlerTest); +}; + +TEST_F(ExtensionPrinterHandlerTest, GetPrinters) { + size_t call_count = 0; + scoped_ptr<base::ListValue> printers; + bool is_done = false; + + extension_printer_handler_->StartGetPrinters( + base::Bind(&RecordPrinterList, &call_count, &printers, &is_done)); + + EXPECT_FALSE(printers.get()); + FakePrinterProviderAPI* fake_api = GetPrinterProviderAPI(); + ASSERT_TRUE(fake_api); + ASSERT_EQ(1u, fake_api->pending_get_printers_count()); + + std::string error; + scoped_ptr<base::ListValue> original_printers( + GetJSONAsListValue(kPrinterDescriptionList, &error)); + ASSERT_TRUE(original_printers) << "Failed to deserialize printers: " << error; + + fake_api->TriggerNextGetPrintersCallback(*original_printers, true); + + EXPECT_EQ(1u, call_count); + EXPECT_TRUE(is_done); + ASSERT_TRUE(printers.get()); + EXPECT_TRUE(printers->Equals(original_printers.get())) + << *printers << ", expected: " << *original_printers; +} + +TEST_F(ExtensionPrinterHandlerTest, GetPrinters_Reset) { + size_t call_count = 0; + scoped_ptr<base::ListValue> printers; + bool is_done = false; + + extension_printer_handler_->StartGetPrinters( + base::Bind(&RecordPrinterList, &call_count, &printers, &is_done)); + + EXPECT_FALSE(printers.get()); + FakePrinterProviderAPI* fake_api = GetPrinterProviderAPI(); + ASSERT_TRUE(fake_api); + ASSERT_EQ(1u, fake_api->pending_get_printers_count()); + + extension_printer_handler_->Reset(); + + std::string error; + scoped_ptr<base::ListValue> original_printers( + GetJSONAsListValue(kPrinterDescriptionList, &error)); + ASSERT_TRUE(original_printers) << "Error deserializing printers: " << error; + + fake_api->TriggerNextGetPrintersCallback(*original_printers, true); + + EXPECT_EQ(0u, call_count); +} + +TEST_F(ExtensionPrinterHandlerTest, GetCapability) { + size_t call_count = 0; + std::string destination_id; + scoped_ptr<base::DictionaryValue> capability; + + extension_printer_handler_->StartGetCapability( + kPrinterId, + base::Bind(&RecordCapability, &call_count, &destination_id, &capability)); + + EXPECT_EQ(0u, call_count); + + FakePrinterProviderAPI* fake_api = GetPrinterProviderAPI(); + ASSERT_TRUE(fake_api); + ASSERT_EQ(1u, fake_api->pending_get_capability_count()); + + std::string error; + scoped_ptr<base::DictionaryValue> original_capability( + GetJSONAsDictionaryValue(kPWGRasterOnlyPrinterSimpleDescription, &error)); + ASSERT_TRUE(original_capability) + << "Error deserializing capability: " << error; + + fake_api->TriggerNextGetCapabilityCallback(*original_capability); + + EXPECT_EQ(1u, call_count); + EXPECT_EQ(kPrinterId, destination_id); + ASSERT_TRUE(capability.get()); + EXPECT_TRUE(capability->Equals(original_capability.get())) + << *capability << ", expected: " << *original_capability; +} + +TEST_F(ExtensionPrinterHandlerTest, GetCapability_Reset) { + size_t call_count = 0; + std::string destination_id; + scoped_ptr<base::DictionaryValue> capability; + + extension_printer_handler_->StartGetCapability( + kPrinterId, + base::Bind(&RecordCapability, &call_count, &destination_id, &capability)); + + EXPECT_EQ(0u, call_count); + + FakePrinterProviderAPI* fake_api = GetPrinterProviderAPI(); + ASSERT_TRUE(fake_api); + ASSERT_EQ(1u, fake_api->pending_get_capability_count()); + + extension_printer_handler_->Reset(); + + std::string error; + scoped_ptr<base::DictionaryValue> original_capability( + GetJSONAsDictionaryValue(kPWGRasterOnlyPrinterSimpleDescription, &error)); + ASSERT_TRUE(original_capability) + << "Error deserializing capability: " << error; + + fake_api->TriggerNextGetCapabilityCallback(*original_capability); + + EXPECT_EQ(0u, call_count); +} + +TEST_F(ExtensionPrinterHandlerTest, Print_Pdf) { + size_t call_count = 0; + bool success = false; + std::string status; + + scoped_refptr<base::RefCountedString> print_data( + new base::RefCountedString()); + print_data->data() = "print data, PDF"; + + extension_printer_handler_->StartPrint( + kPrinterId, kPdfSupportedPrinter, kEmptyPrintTicket, gfx::Size(100, 100), + print_data, + base::Bind(&RecordPrintResult, &call_count, &success, &status)); + + EXPECT_EQ(0u, call_count); + FakePrinterProviderAPI* fake_api = GetPrinterProviderAPI(); + ASSERT_TRUE(fake_api); + ASSERT_EQ(1u, fake_api->pending_print_count()); + + const PrintJobParams* print_job = fake_api->GetNextPendingPrintJob(); + ASSERT_TRUE(print_job); + + EXPECT_EQ(kPrinterId, print_job->printer_id); + EXPECT_EQ(kEmptyPrintTicket, print_job->ticket); + EXPECT_EQ(kContentTypePDF, print_job->content_type); + EXPECT_EQ(print_data->data(), print_job->document); + + fake_api->TriggerNextPrintCallback(kPrintRequestSuccess); + + EXPECT_EQ(1u, call_count); + EXPECT_TRUE(success); + EXPECT_EQ(kPrintRequestSuccess, status); +} + +TEST_F(ExtensionPrinterHandlerTest, Print_Pdf_Reset) { + size_t call_count = 0; + bool success = false; + std::string status; + + scoped_refptr<base::RefCountedString> print_data( + new base::RefCountedString()); + print_data->data() = "print data, PDF"; + + extension_printer_handler_->StartPrint( + kPrinterId, kPdfSupportedPrinter, kEmptyPrintTicket, gfx::Size(100, 100), + print_data, + base::Bind(&RecordPrintResult, &call_count, &success, &status)); + + EXPECT_EQ(0u, call_count); + FakePrinterProviderAPI* fake_api = GetPrinterProviderAPI(); + ASSERT_TRUE(fake_api); + ASSERT_EQ(1u, fake_api->pending_print_count()); + + extension_printer_handler_->Reset(); + + fake_api->TriggerNextPrintCallback(kPrintRequestSuccess); + + EXPECT_EQ(0u, call_count); +} + +TEST_F(ExtensionPrinterHandlerTest, Print_All) { + size_t call_count = 0; + bool success = false; + std::string status; + + scoped_refptr<base::RefCountedString> print_data( + new base::RefCountedString()); + print_data->data() = "print data, PDF"; + + extension_printer_handler_->StartPrint( + kPrinterId, kAllContentTypesSupportedPrinter, kEmptyPrintTicket, + gfx::Size(100, 100), print_data, + base::Bind(&RecordPrintResult, &call_count, &success, &status)); + + EXPECT_EQ(0u, call_count); + + FakePrinterProviderAPI* fake_api = GetPrinterProviderAPI(); + ASSERT_TRUE(fake_api); + ASSERT_EQ(1u, fake_api->pending_print_count()); + + const PrintJobParams* print_job = fake_api->GetNextPendingPrintJob(); + ASSERT_TRUE(print_job); + + EXPECT_EQ(kPrinterId, print_job->printer_id); + EXPECT_EQ(kEmptyPrintTicket, print_job->ticket); + EXPECT_EQ(kContentTypePDF, print_job->content_type); + EXPECT_EQ(print_data->data(), print_job->document); + + fake_api->TriggerNextPrintCallback(kPrintRequestSuccess); + + EXPECT_EQ(1u, call_count); + EXPECT_TRUE(success); + EXPECT_EQ(kPrintRequestSuccess, status); +} + +TEST_F(ExtensionPrinterHandlerTest, Print_Pwg) { + size_t call_count = 0; + bool success = false; + std::string status; + + scoped_refptr<base::RefCountedString> print_data( + new base::RefCountedString()); + print_data->data() = "print data, PDF"; + + extension_printer_handler_->StartPrint( + kPrinterId, kPWGRasterOnlyPrinterSimpleDescription, kEmptyPrintTicket, + gfx::Size(100, 50), print_data, + base::Bind(&RecordPrintResult, &call_count, &success, &status)); + + EXPECT_EQ(0u, call_count); + + base::RunLoop().RunUntilIdle(); + + FakePrinterProviderAPI* fake_api = GetPrinterProviderAPI(); + ASSERT_TRUE(fake_api); + ASSERT_EQ(1u, fake_api->pending_print_count()); + + EXPECT_EQ(printing::TRANSFORM_NORMAL, + pwg_raster_converter_->bitmap_settings().odd_page_transform); + EXPECT_FALSE(pwg_raster_converter_->bitmap_settings().rotate_all_pages); + EXPECT_FALSE(pwg_raster_converter_->bitmap_settings().reverse_page_order); + + EXPECT_EQ(printing::kDefaultPdfDpi, + pwg_raster_converter_->conversion_settings().dpi()); + EXPECT_TRUE(pwg_raster_converter_->conversion_settings().autorotate()); + EXPECT_EQ("0,0 208x416", // vertically_oriented_size * dpi / points_per_inch + pwg_raster_converter_->conversion_settings().area().ToString()); + + const PrintJobParams* print_job = fake_api->GetNextPendingPrintJob(); + ASSERT_TRUE(print_job); + + EXPECT_EQ(kPrinterId, print_job->printer_id); + EXPECT_EQ(kEmptyPrintTicket, print_job->ticket); + EXPECT_EQ(kContentTypePWG, print_job->content_type); + EXPECT_EQ(print_data->data() + kPWGConversionSuffix, print_job->document); + + fake_api->TriggerNextPrintCallback(kPrintRequestSuccess); + + EXPECT_EQ(1u, call_count); + EXPECT_TRUE(success); + EXPECT_EQ(kPrintRequestSuccess, status); +} + +TEST_F(ExtensionPrinterHandlerTest, Print_Pwg_NonDefaultSettings) { + size_t call_count = 0; + bool success = false; + std::string status; + + scoped_refptr<base::RefCountedString> print_data( + new base::RefCountedString()); + print_data->data() = "print data, PDF"; + + extension_printer_handler_->StartPrint( + kPrinterId, kPWGRasterOnlyPrinter, kPrintTicketWithDuplex, + gfx::Size(100, 50), print_data, + base::Bind(&RecordPrintResult, &call_count, &success, &status)); + + EXPECT_EQ(0u, call_count); + + base::RunLoop().RunUntilIdle(); + + FakePrinterProviderAPI* fake_api = GetPrinterProviderAPI(); + ASSERT_TRUE(fake_api); + ASSERT_EQ(1u, fake_api->pending_print_count()); + + EXPECT_EQ(printing::TRANSFORM_FLIP_VERTICAL, + pwg_raster_converter_->bitmap_settings().odd_page_transform); + EXPECT_TRUE(pwg_raster_converter_->bitmap_settings().rotate_all_pages); + EXPECT_TRUE(pwg_raster_converter_->bitmap_settings().reverse_page_order); + + EXPECT_EQ(200, // max(vertical_dpi, horizontal_dpi) + pwg_raster_converter_->conversion_settings().dpi()); + EXPECT_TRUE(pwg_raster_converter_->conversion_settings().autorotate()); + EXPECT_EQ("0,0 138x277", // vertically_oriented_size * dpi / points_per_inch + pwg_raster_converter_->conversion_settings().area().ToString()); + + const PrintJobParams* print_job = fake_api->GetNextPendingPrintJob(); + ASSERT_TRUE(print_job); + + EXPECT_EQ(kPrinterId, print_job->printer_id); + EXPECT_EQ(kPrintTicketWithDuplex, print_job->ticket); + EXPECT_EQ(kContentTypePWG, print_job->content_type); + EXPECT_EQ(print_data->data() + kPWGConversionSuffix, print_job->document); + + fake_api->TriggerNextPrintCallback(kPrintRequestSuccess); + + EXPECT_EQ(1u, call_count); + EXPECT_TRUE(success); + EXPECT_EQ(kPrintRequestSuccess, status); +} + +TEST_F(ExtensionPrinterHandlerTest, Print_Pwg_Reset) { + size_t call_count = 0; + bool success = false; + std::string status; + + scoped_refptr<base::RefCountedString> print_data( + new base::RefCountedString()); + print_data->data() = "print data, PDF"; + + extension_printer_handler_->StartPrint( + kPrinterId, kPWGRasterOnlyPrinterSimpleDescription, kEmptyPrintTicket, + gfx::Size(100, 50), print_data, + base::Bind(&RecordPrintResult, &call_count, &success, &status)); + + EXPECT_EQ(0u, call_count); + + base::RunLoop().RunUntilIdle(); + + FakePrinterProviderAPI* fake_api = GetPrinterProviderAPI(); + ASSERT_TRUE(fake_api); + ASSERT_EQ(1u, fake_api->pending_print_count()); + + extension_printer_handler_->Reset(); + + fake_api->TriggerNextPrintCallback(kPrintRequestSuccess); + + EXPECT_EQ(0u, call_count); +} + +TEST_F(ExtensionPrinterHandlerTest, Print_Pwg_InvalidTicket) { + size_t call_count = 0; + bool success = false; + std::string status; + + scoped_refptr<base::RefCountedString> print_data( + new base::RefCountedString()); + print_data->data() = "print data, PDF"; + + extension_printer_handler_->StartPrint( + kPrinterId, kPWGRasterOnlyPrinterSimpleDescription, "{}" /* ticket */, + gfx::Size(100, 100), print_data, + base::Bind(&RecordPrintResult, &call_count, &success, &status)); + + EXPECT_EQ(1u, call_count); + + EXPECT_FALSE(success); + EXPECT_EQ("INVALID_TICKET", status); +} + +TEST_F(ExtensionPrinterHandlerTest, Print_Pwg_FailedConversion) { + size_t call_count = 0; + bool success = false; + std::string status; + + pwg_raster_converter_->FailConversion(); + + scoped_refptr<base::RefCountedString> print_data( + new base::RefCountedString()); + print_data->data() = "print data, PDF"; + + extension_printer_handler_->StartPrint( + kPrinterId, kPWGRasterOnlyPrinterSimpleDescription, kEmptyPrintTicket, + gfx::Size(100, 100), print_data, + base::Bind(&RecordPrintResult, &call_count, &success, &status)); + + EXPECT_EQ(1u, call_count); + + EXPECT_FALSE(success); + EXPECT_EQ("INVALID_DATA", status); +} diff --git a/chrome/browser/ui/webui/print_preview/printer_handler.cc b/chrome/browser/ui/webui/print_preview/printer_handler.cc index a38f46b..edc85d1 100644 --- a/chrome/browser/ui/webui/print_preview/printer_handler.cc +++ b/chrome/browser/ui/webui/print_preview/printer_handler.cc @@ -4,11 +4,12 @@ #include "chrome/browser/ui/webui/print_preview/printer_handler.h" +#include "base/threading/worker_pool.h" #include "chrome/browser/ui/webui/print_preview/extension_printer_handler.h" // static scoped_ptr<PrinterHandler> PrinterHandler::CreateForExtensionPrinters( content::BrowserContext* browser_context) { - return scoped_ptr<ExtensionPrinterHandler>( - new ExtensionPrinterHandler(browser_context)); + return scoped_ptr<ExtensionPrinterHandler>(new ExtensionPrinterHandler( + browser_context, base::WorkerPool::GetTaskRunner(true))); } diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 5f96c31..4df53f5 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -1073,6 +1073,7 @@ 'browser/printing/print_preview_dialog_controller_unittest.cc', 'browser/printing/print_preview_test.cc', 'browser/printing/print_preview_test.h', + 'browser/ui/webui/print_preview/extension_printer_handler_unittest.cc', 'browser/ui/webui/print_preview/print_preview_ui_unittest.cc', 'common/service_process_util_unittest.cc', 'service/cloud_print/cloud_print_service_helpers_unittest.cc', |