diff options
author | tbarzic <tbarzic@chromium.org> | 2015-02-12 17:52:48 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-13 01:53:42 +0000 |
commit | 19e5d42cf476eae206fe698a306e3baeb6f9273a (patch) | |
tree | c1bd5f2c41c3a55ef97d5b721fa2f8e3c0428e63 /extensions | |
parent | 198f1cd771751f113641219e05d6ecf9f22b2bc2 (diff) | |
download | chromium_src-19e5d42cf476eae206fe698a306e3baeb6f9273a.zip chromium_src-19e5d42cf476eae206fe698a306e3baeb6f9273a.tar.gz chromium_src-19e5d42cf476eae206fe698a306e3baeb6f9273a.tar.bz2 |
Implement ExtensionPrinterHandler::StartPrint
This wires up print requests with PritnerProviderAPI, for now only for
PDF. The method will check printer capability and fail the request if
the printer did not declare support for PDF.
Also, PrinterProviderAPI interface is changed a bit:
Document bytes data type in PrintJob struct is changed from string to
base::RefCountedMemory and print request callback now returns string
instead of PrintError enum (to avoid extra type conversion before
sending the error to print preview webui).
Also, add some restrictions on document data size dispatched to
extension.
BUG=408772
TEST=Coming (very) soon
Review URL: https://codereview.chromium.org/905023006
Cr-Commit-Position: refs/heads/master@{#316125}
Diffstat (limited to 'extensions')
3 files changed, 86 insertions, 61 deletions
diff --git a/extensions/browser/api/printer_provider/printer_provider_api.cc b/extensions/browser/api/printer_provider/printer_provider_api.cc index 03e2c72..da66224 100644 --- a/extensions/browser/api/printer_provider/printer_provider_api.cc +++ b/extensions/browser/api/printer_provider/printer_provider_api.cc @@ -8,6 +8,7 @@ #include <vector> #include "base/bind.h" +#include "base/json/json_string_value_serializer.h" #include "base/lazy_instance.h" #include "base/values.h" #include "extensions/browser/api/printer_provider_internal/printer_provider_internal_api.h" @@ -54,24 +55,6 @@ bool ParsePrinterId(const std::string& printer_id, return true; } -PrinterProviderAPI::PrintError APIPrintErrorToInternalType( - core_api::printer_provider_internal::PrintError error) { - switch (error) { - case core_api::printer_provider_internal::PRINT_ERROR_NONE: - // The PrintError parameter is not set, which implies an error. - return PrinterProviderAPI::PRINT_ERROR_FAILED; - case core_api::printer_provider_internal::PRINT_ERROR_OK: - return PrinterProviderAPI::PRINT_ERROR_NONE; - case core_api::printer_provider_internal::PRINT_ERROR_FAILED: - return PrinterProviderAPI::PRINT_ERROR_FAILED; - case core_api::printer_provider_internal::PRINT_ERROR_INVALID_TICKET: - return PrinterProviderAPI::PRINT_ERROR_INVALID_TICKET; - case core_api::printer_provider_internal::PRINT_ERROR_INVALID_DATA: - return PrinterProviderAPI::PRINT_ERROR_INVALID_DATA; - } - return PrinterProviderAPI::PRINT_ERROR_FAILED; -} - } // namespace PrinterProviderAPI::PrintJob::PrintJob() { @@ -86,6 +69,12 @@ PrinterProviderAPI::GetFactoryInstance() { return g_api_factory.Pointer(); } +// static +std::string PrinterProviderAPI::GetDefaultPrintError() { + return core_api::printer_provider_internal::ToString( + core_api::printer_provider_internal::PRINT_ERROR_FAILED); +} + PrinterProviderAPI::PrinterProviderAPI(content::BrowserContext* browser_context) : browser_context_(browser_context), internal_api_observer_(this), @@ -169,7 +158,7 @@ void PrinterProviderAPI::DispatchPrintRequested( std::string extension_id; std::string internal_printer_id; if (!ParsePrinterId(job.printer_id, &extension_id, &internal_printer_id)) { - callback.Run(PRINT_ERROR_FAILED); + callback.Run(false, GetDefaultPrintError()); return; } @@ -177,15 +166,36 @@ void PrinterProviderAPI::DispatchPrintRequested( if (!event_router->ExtensionHasEventListener( extension_id, core_api::printer_provider::OnPrintRequested::kEventName)) { - callback.Run(PRINT_ERROR_FAILED); + callback.Run(false, GetDefaultPrintError()); return; } core_api::printer_provider::PrintJob print_job; print_job.printer_id = internal_printer_id; + + JSONStringValueSerializer serializer(job.ticket_json); + scoped_ptr<base::Value> ticket_value(serializer.Deserialize(NULL, NULL)); + if (!ticket_value || + !core_api::printer_provider::PrintJob::Ticket::Populate( + *ticket_value, &print_job.ticket)) { + callback.Run(false, + core_api::printer_provider::ToString( + core_api::printer_provider::PRINT_ERROR_INVALID_TICKET)); + return; + } + + // TODO(tbarzic): Figure out how to support huge documents. + if (job.document_bytes->size() > PrinterProviderAPI::kMaxDocumentSize) { + callback.Run(false, + core_api::printer_provider::ToString( + core_api::printer_provider::PRINT_ERROR_INVALID_DATA)); + return; + } + print_job.content_type = job.content_type; - print_job.document = - std::vector<char>(job.document_bytes.begin(), job.document_bytes.end()); + print_job.document = std::vector<char>( + job.document_bytes->front(), + job.document_bytes->front() + job.document_bytes->size()); int request_id = pending_print_requests_[extension_id].Add(callback); @@ -324,8 +334,10 @@ int PrinterProviderAPI::PendingPrintRequests::Add( return last_request_id_; } -bool PrinterProviderAPI::PendingPrintRequests::Complete(int request_id, - PrintError response) { +bool PrinterProviderAPI::PendingPrintRequests::Complete( + int request_id, + bool success, + const std::string& response) { auto it = pending_requests_.find(request_id); if (it == pending_requests_.end()) return false; @@ -333,13 +345,13 @@ bool PrinterProviderAPI::PendingPrintRequests::Complete(int request_id, PrintCallback callback = it->second; pending_requests_.erase(it); - callback.Run(response); + callback.Run(success, response); return true; } void PrinterProviderAPI::PendingPrintRequests::FailAll() { for (auto& request : pending_requests_) - request.second.Run(PRINT_ERROR_FAILED); + request.second.Run(false, GetDefaultPrintError()); pending_requests_.clear(); } @@ -376,8 +388,13 @@ void PrinterProviderAPI::OnPrintResult( const Extension* extension, int request_id, core_api::printer_provider_internal::PrintError error) { + const std::string error_str = + error == core_api::printer_provider_internal::PRINT_ERROR_NONE + ? GetDefaultPrintError() + : core_api::printer_provider_internal::ToString(error); pending_print_requests_[extension->id()].Complete( - request_id, APIPrintErrorToInternalType(error)); + request_id, error == core_api::printer_provider_internal::PRINT_ERROR_OK, + error_str); } void PrinterProviderAPI::OnExtensionUnloaded( diff --git a/extensions/browser/api/printer_provider/printer_provider_api.h b/extensions/browser/api/printer_provider/printer_provider_api.h index 2574d7bf..0bd3e4c 100644 --- a/extensions/browser/api/printer_provider/printer_provider_api.h +++ b/extensions/browser/api/printer_provider/printer_provider_api.h @@ -11,6 +11,7 @@ #include "base/callback.h" #include "base/macros.h" +#include "base/memory/ref_counted_memory.h" #include "base/scoped_observer.h" #include "extensions/browser/api/printer_provider_internal/printer_provider_internal_api_observer.h" #include "extensions/browser/browser_context_keyed_api_factory.h" @@ -38,14 +39,6 @@ class PrinterProviderAPI : public BrowserContextKeyedAPI, public PrinterProviderInternalAPIObserver, public ExtensionRegistryObserver { public: - // Status returned by chrome.printerProvider.onPrintRequested event. - enum PrintError { - PRINT_ERROR_NONE, - PRINT_ERROR_FAILED, - PRINT_ERROR_INVALID_TICKET, - PRINT_ERROR_INVALID_DATA - }; - // Struct describing print job that should be forwarded to an extension via // chrome.printerProvider.onPrintRequested event. struct PrintJob { @@ -66,18 +59,21 @@ class PrinterProviderAPI : public BrowserContextKeyedAPI, std::string content_type; // The document data that should be printed. - std::string document_bytes; + scoped_refptr<base::RefCountedMemory> document_bytes; }; using GetPrintersCallback = base::Callback<void(const base::ListValue& printers, bool done)>; using GetCapabilityCallback = - base::Callback<void(const base::DictionaryValue&)>; - using PrintCallback = base::Callback<void(PrintError)>; + base::Callback<void(const base::DictionaryValue& capability)>; + using PrintCallback = + base::Callback<void(bool success, const std::string& error)>; static BrowserContextKeyedAPIFactory<PrinterProviderAPI>* GetFactoryInstance(); + static std::string GetDefaultPrintError(); + explicit PrinterProviderAPI(content::BrowserContext* browser_context); ~PrinterProviderAPI() override; @@ -112,6 +108,11 @@ class PrinterProviderAPI : public BrowserContextKeyedAPI, void DispatchPrintRequested(const PrintJob& job, const PrintCallback& callback); + // The API currently cannot handle very large files, so the document size that + // may be sent to an extension is restricted. + // TODO(tbarzic): Fix the API to support huge documents. + static const int kMaxDocumentSize = 50 * 1000 * 1000; + private: friend class BrowserContextKeyedAPIFactory<PrinterProviderAPI>; @@ -215,7 +216,7 @@ class PrinterProviderAPI : public BrowserContextKeyedAPI, // Completes the request with the provided request id. It runs the request // callback and removes the request from the set. - bool Complete(int request_id, PrintError result); + bool Complete(int request_id, bool success, const std::string& result); // Runs all pending callbacks with ERROR_FAILED and clears the set of // pending requests. diff --git a/extensions/browser/api/printer_provider/printer_provider_apitest.cc b/extensions/browser/api/printer_provider/printer_provider_apitest.cc index 19b066f..59d5ebb 100644 --- a/extensions/browser/api/printer_provider/printer_provider_apitest.cc +++ b/extensions/browser/api/printer_provider/printer_provider_apitest.cc @@ -4,6 +4,7 @@ #include "base/bind.h" #include "base/json/json_string_value_serializer.h" +#include "base/memory/ref_counted_memory.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "extensions/browser/api/printer_provider/printer_provider_api.h" @@ -38,10 +39,13 @@ void AppendPrintersAndRunCallbackIfDone(base::ListValue* printers_out, // Callback for PrinterProviderAPI::DispatchPrintRequested calls. // It copies |value| to |*result| and runs |callback|. -void RecordPrintErrorAndRunCallback(PrinterProviderAPI::PrintError* result, - const base::Closure& callback, - PrinterProviderAPI::PrintError value) { - *result = value; +void RecordPrintResultAndRunCallback(bool* result_success, + std::string* result_status, + const base::Closure& callback, + bool success, + const std::string& status) { + *result_success = success; + *result_status = status; if (!callback.is_null()) callback.Run(); } @@ -76,7 +80,9 @@ class PrinterProviderApiTest : public extensions::ShellApiTest { job.printer_id = extension_id + ":printer_id"; job.ticket_json = "{}"; job.content_type = "content_type"; - job.document_bytes = "bytes"; + const unsigned char kDocumentBytes[] = {'b', 'y', 't', 'e', 's', 0}; + job.document_bytes = + new base::RefCountedBytes(kDocumentBytes, arraysize(kDocumentBytes)); PrinterProviderAPI::GetFactoryInstance() ->Get(browser_context()) @@ -127,7 +133,7 @@ class PrinterProviderApiTest : public extensions::ShellApiTest { // |test_param|: The test that should be run. // |expected_result|: The print result the app is expected to report. void RunPrintRequestTestApp(const std::string& test_param, - PrinterProviderAPI::PrintError expected_result) { + const std::string& expected_result) { extensions::ResultCatcher catcher; std::string extension_id; @@ -137,15 +143,17 @@ class PrinterProviderApiTest : public extensions::ShellApiTest { return; base::RunLoop run_loop; - PrinterProviderAPI::PrintError print_result; + bool success; + std::string print_status; StartPrintRequest(extension_id, - base::Bind(&RecordPrintErrorAndRunCallback, &print_result, - run_loop.QuitClosure())); + base::Bind(&RecordPrintResultAndRunCallback, &success, + &print_status, run_loop.QuitClosure())); ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); run_loop.Run(); - EXPECT_EQ(expected_result, print_result); + EXPECT_EQ(expected_result, print_status); + EXPECT_EQ(expected_result == "OK", success); } // Runs a test for chrome.printerProvider.onGetCapabilityRequested @@ -218,27 +226,24 @@ class PrinterProviderApiTest : public extensions::ShellApiTest { }; IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, PrintJobSuccess) { - RunPrintRequestTestApp("OK", PrinterProviderAPI::PRINT_ERROR_NONE); + RunPrintRequestTestApp("OK", "OK"); } IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, PrintJobAsyncSuccess) { - RunPrintRequestTestApp("ASYNC_RESPONSE", - PrinterProviderAPI::PRINT_ERROR_NONE); + RunPrintRequestTestApp("ASYNC_RESPONSE", "OK"); } IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, PrintJobFailed) { - RunPrintRequestTestApp("INVALID_TICKET", - PrinterProviderAPI::PRINT_ERROR_INVALID_TICKET); + RunPrintRequestTestApp("INVALID_TICKET", "INVALID_TICKET"); } IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, NoPrintEventListener) { - RunPrintRequestTestApp("NO_LISTENER", PrinterProviderAPI::PRINT_ERROR_FAILED); + RunPrintRequestTestApp("NO_LISTENER", "FAILED"); } IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, PrintRequestInvalidCallbackParam) { - RunPrintRequestTestApp("INVALID_VALUE", - PrinterProviderAPI::PRINT_ERROR_FAILED); + RunPrintRequestTestApp("INVALID_VALUE", "FAILED"); } IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, PrintRequestAppUnloaded) { @@ -250,17 +255,19 @@ IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, PrintRequestAppUnloaded) { ASSERT_FALSE(extension_id.empty()); base::RunLoop run_loop; - PrinterProviderAPI::PrintError print_result; + bool success = false; + std::string status; StartPrintRequest(extension_id, - base::Bind(&RecordPrintErrorAndRunCallback, &print_result, - run_loop.QuitClosure())); + base::Bind(&RecordPrintResultAndRunCallback, &success, + &status, run_loop.QuitClosure())); ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); ASSERT_TRUE(SimulateExtensionUnload(extension_id)); run_loop.Run(); - EXPECT_EQ(PrinterProviderAPI::PRINT_ERROR_FAILED, print_result); + EXPECT_FALSE(success); + EXPECT_EQ("FAILED", status); } IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest, GetCapabilitySuccess) { |