summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-17 17:48:24 +0000
committersanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-17 17:48:24 +0000
commit58310639ddc719c51bcd152966a01723ca16e4c5 (patch)
tree9960980d149c59317d177fb0f5032ab363025b4a
parent685dffb92f13c973310f36800384701122812e7b (diff)
downloadchromium_src-58310639ddc719c51bcd152966a01723ca16e4c5.zip
chromium_src-58310639ddc719c51bcd152966a01723ca16e4c5.tar.gz
chromium_src-58310639ddc719c51bcd152966a01723ca16e4c5.tar.bz2
Added support to the Windows cloud print proxy to print XPS documents directly without any conversion (only works on Windows 7). The proxy uses the Accept: header to specify what data types it can accept.
BUG=None. TEST=When the cloud print service supports this, submitting an XPS document should go through to the Win 7 proxy without any conversions. Review URL: http://codereview.chromium.org/6523040 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75286 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/service/cloud_print/cloud_print_proxy_backend.cc27
-rw-r--r--chrome/service/cloud_print/cloud_print_url_fetcher.cc24
-rw-r--r--chrome/service/cloud_print/cloud_print_url_fetcher.h9
-rw-r--r--chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc4
-rw-r--r--chrome/service/cloud_print/job_status_updater.cc5
-rw-r--r--chrome/service/cloud_print/print_system.h5
-rw-r--r--chrome/service/cloud_print/print_system_cups.cc9
-rw-r--r--chrome/service/cloud_print/print_system_win.cc199
-rw-r--r--chrome/service/cloud_print/printer_job_handler.cc28
-rw-r--r--printing/backend/win_helper.cc53
-rw-r--r--printing/backend/win_helper.h25
11 files changed, 320 insertions, 68 deletions
diff --git a/chrome/service/cloud_print/cloud_print_proxy_backend.cc b/chrome/service/cloud_print/cloud_print_proxy_backend.cc
index 7890fee..e9d05c3 100644
--- a/chrome/service/cloud_print/cloud_print_proxy_backend.cc
+++ b/chrome/service/cloud_print/cloud_print_proxy_backend.cc
@@ -475,8 +475,11 @@ void CloudPrintProxyBackend::Core::GetRegisteredPrinters() {
next_response_handler_ =
&CloudPrintProxyBackend::Core::HandlePrinterListResponse;
request_ = new CloudPrintURLFetcher;
- request_->StartGetRequest(printer_list_url, this, auth_token_,
- kCloudPrintAPIMaxRetryCount);
+ request_->StartGetRequest(printer_list_url,
+ this,
+ auth_token_,
+ kCloudPrintAPIMaxRetryCount,
+ std::string());
}
void CloudPrintProxyBackend::Core::RegisterNextPrinter() {
@@ -565,9 +568,13 @@ void CloudPrintProxyBackend::Core::OnReceivePrinterCaps(
std::string mime_type("multipart/form-data; boundary=");
mime_type += mime_boundary;
request_ = new CloudPrintURLFetcher;
- request_->StartPostRequest(post_url, this, auth_token_,
- kCloudPrintAPIMaxRetryCount, mime_type,
- post_data);
+ request_->StartPostRequest(post_url,
+ this,
+ auth_token_,
+ kCloudPrintAPIMaxRetryCount,
+ mime_type,
+ post_data,
+ std::string());
} else {
LOG(ERROR) << "CP_PROXY: Failed to get printer info for: " <<
printer_name;
@@ -774,9 +781,13 @@ void CloudPrintProxyBackend::Core::ReportUserMessage(
std::string mime_type("multipart/form-data; boundary=");
mime_type += mime_boundary;
request_ = new CloudPrintURLFetcher;
- request_->StartPostRequest(post_url, this, auth_token_,
- kCloudPrintAPIMaxRetryCount, mime_type,
- post_data);
+ request_->StartPostRequest(post_url,
+ this,
+ auth_token_,
+ kCloudPrintAPIMaxRetryCount,
+ mime_type,
+ post_data,
+ std::string());
}
CloudPrintURLFetcher::ResponseAction
diff --git a/chrome/service/cloud_print/cloud_print_url_fetcher.cc b/chrome/service/cloud_print/cloud_print_url_fetcher.cc
index 9840e14..0d81e17 100644
--- a/chrome/service/cloud_print/cloud_print_url_fetcher.cc
+++ b/chrome/service/cloud_print/cloud_print_url_fetcher.cc
@@ -18,12 +18,14 @@ CloudPrintURLFetcher::CloudPrintURLFetcher()
num_retries_(0) {
}
-void CloudPrintURLFetcher::StartGetRequest(const GURL& url,
- Delegate* delegate,
- const std::string& auth_token,
- int max_retries) {
+void CloudPrintURLFetcher::StartGetRequest(
+ const GURL& url,
+ Delegate* delegate,
+ const std::string& auth_token,
+ int max_retries,
+ const std::string& additional_headers) {
StartRequestHelper(url, URLFetcher::GET, delegate, auth_token, max_retries,
- std::string(), std::string());
+ std::string(), std::string(), additional_headers);
}
void CloudPrintURLFetcher::StartPostRequest(
@@ -32,9 +34,10 @@ void CloudPrintURLFetcher::StartPostRequest(
const std::string& auth_token,
int max_retries,
const std::string& post_data_mime_type,
- const std::string& post_data) {
+ const std::string& post_data,
+ const std::string& additional_headers) {
StartRequestHelper(url, URLFetcher::POST, delegate, auth_token, max_retries,
- post_data_mime_type, post_data);
+ post_data_mime_type, post_data, additional_headers);
}
// URLFetcher::Delegate implementation.
@@ -113,7 +116,8 @@ void CloudPrintURLFetcher::StartRequestHelper(
const std::string& auth_token,
int max_retries,
const std::string& post_data_mime_type,
- const std::string& post_data) {
+ const std::string& post_data,
+ const std::string& additional_headers) {
DCHECK(delegate);
request_.reset(new URLFetcher(url, request_type, this));
request_->set_request_context(GetRequestContextGetter());
@@ -125,6 +129,10 @@ void CloudPrintURLFetcher::StartRequestHelper(
headers += auth_token;
headers += "\r\n";
headers += kChromeCloudPrintProxyHeader;
+ if (!additional_headers.empty()) {
+ headers += "\r\n";
+ headers += additional_headers;
+ }
request_->set_extra_request_headers(headers);
if (request_type == URLFetcher::POST) {
request_->set_upload_data(post_data_mime_type, post_data);
diff --git a/chrome/service/cloud_print/cloud_print_url_fetcher.h b/chrome/service/cloud_print/cloud_print_url_fetcher.h
index 850265e..12e97b7 100644
--- a/chrome/service/cloud_print/cloud_print_url_fetcher.h
+++ b/chrome/service/cloud_print/cloud_print_url_fetcher.h
@@ -81,13 +81,15 @@ class CloudPrintURLFetcher
void StartGetRequest(const GURL& url,
Delegate* delegate,
const std::string& auth_token,
- int max_retries);
+ int max_retries,
+ const std::string& additional_headers);
void StartPostRequest(const GURL& url,
Delegate* delegate,
const std::string& auth_token,
int max_retries,
const std::string& post_data_mime_type,
- const std::string& post_data);
+ const std::string& post_data,
+ const std::string& additional_headers);
// URLFetcher::Delegate implementation.
virtual void OnURLFetchComplete(const URLFetcher* source, const GURL& url,
@@ -109,7 +111,8 @@ class CloudPrintURLFetcher
const std::string& auth_token,
int max_retries,
const std::string& post_data_mime_type,
- const std::string& post_data);
+ const std::string& post_data,
+ const std::string& additional_headers);
scoped_ptr<URLFetcher> request_;
Delegate* delegate_;
diff --git a/chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc b/chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc
index 6d399b0..7a8e233 100644
--- a/chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc
+++ b/chrome/service/cloud_print/cloud_print_url_fetcher_unittest.cc
@@ -192,7 +192,7 @@ void CloudPrintURLFetcherTest::CreateFetcher(const GURL& url, int max_retries) {
fetcher_ = new TestCloudPrintURLFetcher(io_message_loop_proxy());
max_retries_ = max_retries;
start_time_ = Time::Now();
- fetcher_->StartGetRequest(url, this, "", max_retries_);
+ fetcher_->StartGetRequest(url, this, "", max_retries_, std::string());
}
CloudPrintURLFetcher::ResponseAction
@@ -264,7 +264,7 @@ CloudPrintURLFetcherOverloadTest::HandleRawData(const URLFetcher* source,
const TimeDelta one_second = TimeDelta::FromMilliseconds(1000);
response_count_++;
if (response_count_ < 20) {
- fetcher_->StartGetRequest(url, this, "", max_retries_);
+ fetcher_->StartGetRequest(url, this, "", max_retries_, std::string());
} else {
// We have already sent 20 requests continuously. And we expect that
// it takes more than 1 second due to the overload protection settings.
diff --git a/chrome/service/cloud_print/job_status_updater.cc b/chrome/service/cloud_print/job_status_updater.cc
index f717f29..56632b1 100644
--- a/chrome/service/cloud_print/job_status_updater.cc
+++ b/chrome/service/cloud_print/job_status_updater.cc
@@ -62,7 +62,10 @@ void JobStatusUpdater::UpdateStatus() {
request_->StartGetRequest(
CloudPrintHelpers::GetUrlForJobStatusUpdate(
cloud_print_server_url_, job_id_, last_job_details_),
- this, auth_token_, kCloudPrintAPIMaxRetryCount);
+ this,
+ auth_token_,
+ kCloudPrintAPIMaxRetryCount,
+ std::string());
}
}
}
diff --git a/chrome/service/cloud_print/print_system.h b/chrome/service/cloud_print/print_system.h
index d3de6bc9..d744826 100644
--- a/chrome/service/cloud_print/print_system.h
+++ b/chrome/service/cloud_print/print_system.h
@@ -185,6 +185,11 @@ class PrintSystem : public base::RefCountedThreadSafe<PrintSystem> {
const std::string& printer_name) = 0;
virtual JobSpooler* CreateJobSpooler() = 0;
+ // Returns a comma separated list of mimetypes for print data that are
+ // supported by this print system. The format of this string is the same as
+ // that used for the HTTP Accept: header.
+ virtual std::string GetSupportedMimeTypes() = 0;
+
// Generate unique for proxy.
static std::string GenerateProxyId();
diff --git a/chrome/service/cloud_print/print_system_cups.cc b/chrome/service/cloud_print/print_system_cups.cc
index 6cb26e1..7d51908 100644
--- a/chrome/service/cloud_print/print_system_cups.cc
+++ b/chrome/service/cloud_print/print_system_cups.cc
@@ -95,6 +95,7 @@ class PrintSystemCUPS : public PrintSystem {
virtual PrintSystem::PrinterWatcher* CreatePrinterWatcher(
const std::string& printer_name);
virtual PrintSystem::JobSpooler* CreateJobSpooler();
+ virtual std::string GetSupportedMimeTypes();
// Helper functions.
PlatformJobId SpoolPrintJob(const std::string& print_ticket,
@@ -644,6 +645,14 @@ PrintSystem::JobSpooler* PrintSystemCUPS::CreateJobSpooler() {
return new JobSpoolerCUPS(this);
}
+std::string PrintSystemCUPS::GetSupportedMimeTypes() {
+ // Since we hand off the document to the CUPS server directly, list some types
+ // that we know CUPS supports (http://www.cups.org/articles.php?L205+TFAQ+Q)
+ // TODO(sanjeevr): Determine this dynamically (http://crbug.com/73240).
+ return
+ "application/pdf,application/postscript,image/jpeg,image/png,image/gif";
+}
+
std::string PrintSystem::GenerateProxyId() {
// TODO(gene): This code should generate a unique id for proxy. ID should be
// unique for this user. Rand may return the same number. We'll need to change
diff --git a/chrome/service/cloud_print/print_system_win.cc b/chrome/service/cloud_print/print_system_win.cc
index 62f4ddf..4a09ff5 100644
--- a/chrome/service/cloud_print/print_system_win.cc
+++ b/chrome/service/cloud_print/print_system_win.cc
@@ -6,8 +6,14 @@
#include <objidl.h>
#include <winspool.h>
+#if defined(_WIN32_WINNT)
+#undef _WIN32_WINNT
+#endif // defined(_WIN32_WINNT)
+#define _WIN32_WINNT _WIN32_WINNT_WIN7
+#include <xpsprint.h>
#include "base/file_path.h"
+#include "base/file_util.h"
#include "base/scoped_ptr.h"
#include "base/utf_string_conversions.h"
#include "base/win/object_watcher.h"
@@ -366,10 +372,15 @@ class PrintSystemWin : public PrintSystem {
private:
// We use a Core class because we want a separate RefCountedThreadSafe
// implementation for ServiceUtilityProcessHost::Client.
- class Core : public ServiceUtilityProcessHost::Client {
+ class Core : public ServiceUtilityProcessHost::Client,
+ public base::win::ObjectWatcher::Delegate {
public:
Core()
- : last_page_printed_(-1), job_id_(-1), delegate_(NULL), saved_dc_(0) {
+ : last_page_printed_(-1),
+ job_id_(-1),
+ delegate_(NULL),
+ saved_dc_(0),
+ should_couninit_(false) {
}
~Core() {
}
@@ -385,47 +396,54 @@ class PrintSystemWin : public PrintSystem {
return false;
}
last_page_printed_ = -1;
- // We only support PDFs for now.
- if (print_data_mime_type != "application/pdf") {
- NOTREACHED();
- return false;
- }
-
- DevMode pt_dev_mode;
- HRESULT hr = PrintTicketToDevMode(printer_name, print_ticket,
- &pt_dev_mode);
- if (FAILED(hr)) {
- NOTREACHED();
- return false;
- }
-
- HDC dc = CreateDC(L"WINSPOOL", UTF8ToWide(printer_name).c_str(),
- NULL, pt_dev_mode.dm_);
- if (!dc) {
+ // We only support PDF and XPS documents for now.
+ if (print_data_mime_type == "application/pdf") {
+ DevMode pt_dev_mode;
+ HRESULT hr = PrintTicketToDevMode(printer_name, print_ticket,
+ &pt_dev_mode);
+ if (FAILED(hr)) {
+ NOTREACHED();
+ return false;
+ }
+
+ HDC dc = CreateDC(L"WINSPOOL", UTF8ToWide(printer_name).c_str(),
+ NULL, pt_dev_mode.dm_);
+ if (!dc) {
+ NOTREACHED();
+ return false;
+ }
+ hr = E_FAIL;
+ DOCINFO di = {0};
+ di.cbSize = sizeof(DOCINFO);
+ std::wstring doc_name = UTF8ToWide(job_title);
+ di.lpszDocName = doc_name.c_str();
+ job_id_ = StartDoc(dc, &di);
+ if (job_id_ <= 0)
+ return false;
+
+ printer_dc_.Set(dc);
+ int printer_dpi = ::GetDeviceCaps(printer_dc_.Get(), LOGPIXELSX);
+ saved_dc_ = SaveDC(printer_dc_.Get());
+ SetGraphicsMode(printer_dc_.Get(), GM_ADVANCED);
+ XFORM xform = {0};
+ xform.eM11 = xform.eM22 = static_cast<float>(printer_dpi) /
+ static_cast<float>(GetDeviceCaps(GetDC(NULL), LOGPIXELSX));
+ ModifyWorldTransform(printer_dc_.Get(), &xform, MWT_LEFTMULTIPLY);
+ print_data_file_path_ = print_data_file_path;
+ delegate_ = delegate;
+ RenderNextPDFPages();
+ } else if (print_data_mime_type == "application/vnd.ms-xpsdocument") {
+ bool ret = PrintXPSDocument(printer_name,
+ job_title,
+ print_data_file_path,
+ print_ticket);
+ if (ret)
+ delegate_ = delegate;
+ return ret;
+ } else {
NOTREACHED();
return false;
}
- hr = E_FAIL;
- DOCINFO di = {0};
- di.cbSize = sizeof(DOCINFO);
- std::wstring doc_name = UTF8ToWide(job_title);
- di.lpszDocName = doc_name.c_str();
- job_id_ = StartDoc(dc, &di);
- if (job_id_ <= 0)
- return false;
-
- printer_dc_.Set(dc);
-
- int printer_dpi = ::GetDeviceCaps(printer_dc_.Get(), LOGPIXELSX);
- saved_dc_ = SaveDC(printer_dc_.Get());
- SetGraphicsMode(printer_dc_.Get(), GM_ADVANCED);
- XFORM xform = {0};
- xform.eM11 = xform.eM22 = static_cast<float>(printer_dpi) /
- static_cast<float>(GetDeviceCaps(GetDC(NULL), LOGPIXELSX));
- ModifyWorldTransform(printer_dc_.Get(), &xform, MWT_LEFTMULTIPLY);
- print_data_file_path_ = print_data_file_path;
- delegate_ = delegate;
- RenderNextPDFPages();
return true;
}
@@ -442,6 +460,33 @@ class PrintSystemWin : public PrintSystem {
else
RenderNextPDFPages();
}
+
+ // base::win::ObjectWatcher::Delegate inplementation.
+ virtual void OnObjectSignaled(HANDLE object) {
+ DCHECK(xps_print_job_);
+ if (!delegate_)
+ return;
+ XPS_JOB_STATUS job_status = {0};
+ xps_print_job_->GetJobStatus(&job_status);
+ bool done = false;
+ if ((job_status.completion == XPS_JOB_CANCELLED) ||
+ (job_status.completion == XPS_JOB_FAILED)) {
+ delegate_->OnJobSpoolFailed();
+ done = true;
+ } else if (job_status.jobId) {
+ delegate_->OnJobSpoolSucceeded(job_status.jobId);
+ done = true;
+ } else {
+ ResetEvent(job_progress_event_.Get());
+ job_progress_watcher_.StopWatching();
+ job_progress_watcher_.StartWatching(job_progress_event_.Get(), this);
+ }
+ if (done && should_couninit_) {
+ CoUninitialize();
+ should_couninit_ = false;
+ }
+ }
+
virtual void OnRenderPDFPagesToMetafileFailed() {
PrintJobDone();
}
@@ -503,6 +548,67 @@ class PrintSystemWin : public PrintSystem {
utility_host.release();
}
}
+ bool PrintXPSDocument(const std::string& printer_name,
+ const std::string& job_title,
+ const FilePath& print_data_file_path,
+ const std::string& print_ticket) {
+ if (!printing::XPSPrintModule::Init())
+ return false;
+ job_progress_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL));
+ if (!job_progress_event_.Get())
+ return false;
+ should_couninit_ = SUCCEEDED(CoInitializeEx(NULL,
+ COINIT_MULTITHREADED));
+ ScopedComPtr<IXpsPrintJobStream> doc_stream;
+ ScopedComPtr<IXpsPrintJobStream> print_ticket_stream;
+ bool ret = false;
+ // Use nested SUCCEEDED checks because we want a common return point.
+ if (SUCCEEDED(printing::XPSPrintModule::StartXpsPrintJob(
+ UTF8ToWide(printer_name).c_str(),
+ UTF8ToWide(job_title).c_str(),
+ NULL,
+ job_progress_event_.Get(),
+ NULL,
+ NULL,
+ NULL,
+ xps_print_job_.Receive(),
+ doc_stream.Receive(),
+ print_ticket_stream.Receive()))) {
+ ULONG bytes_written = 0;
+ if (SUCCEEDED(print_ticket_stream->Write(print_ticket.c_str(),
+ print_ticket.length(),
+ &bytes_written))) {
+ DCHECK(bytes_written == print_ticket.length());
+ if (SUCCEEDED(print_ticket_stream->Close())) {
+ std::string document_data;
+ file_util::ReadFileToString(print_data_file_path, &document_data);
+ bytes_written = 0;
+ if (SUCCEEDED(doc_stream->Write(document_data.c_str(),
+ document_data.length(),
+ &bytes_written))) {
+ DCHECK(bytes_written == document_data.length());
+ if (SUCCEEDED(doc_stream->Close())) {
+ job_progress_watcher_.StartWatching(job_progress_event_.Get(),
+ this);
+ ret = true;
+ }
+ }
+ }
+ }
+ }
+ if (!ret) {
+ if (xps_print_job_) {
+ xps_print_job_->Cancel();
+ xps_print_job_.Release();
+ }
+ if (should_couninit_) {
+ CoUninitialize();
+ should_couninit_ = false;
+ }
+ }
+ return ret;
+ }
+
// Some Cairo-generated PDFs from Chrome OS result in huge metafiles.
// So the PageCountPerBatch is set to 1 for now.
// TODO(sanjeevr): Figure out a smarter way to determine the pages per
@@ -515,6 +621,10 @@ class PrintSystemWin : public PrintSystem {
int saved_dc_;
base::win::ScopedHDC printer_dc_;
FilePath print_data_file_path_;
+ base::win::ScopedHandle job_progress_event_;
+ base::win::ObjectWatcher job_progress_watcher_;
+ ScopedComPtr<IXpsPrintJob> xps_print_job_;
+ bool should_couninit_;
DISALLOW_COPY_AND_ASSIGN(JobSpoolerWin::Core);
};
scoped_refptr<Core> core_;
@@ -588,6 +698,8 @@ class PrintSystemWin : public PrintSystem {
virtual PrintSystem::PrinterWatcher* CreatePrinterWatcher(
const std::string& printer_name);
virtual PrintSystem::JobSpooler* CreateJobSpooler();
+ virtual std::string GetSupportedMimeTypes();
+
private:
scoped_refptr<printing::PrintBackend> print_backend_;
@@ -728,6 +840,13 @@ PrintSystemWin::CreateJobSpooler() {
return new JobSpoolerWin();
}
+std::string PrintSystemWin::GetSupportedMimeTypes() {
+ if (printing::XPSPrintModule::Init())
+ return "application/vnd.ms-xpsdocument,application/pdf";
+ return "application/pdf";
+}
+
+
std::string PrintSystem::GenerateProxyId() {
GUID proxy_id = {0};
HRESULT hr = UuidCreate(&proxy_id);
diff --git a/chrome/service/cloud_print/printer_job_handler.cc b/chrome/service/cloud_print/printer_job_handler.cc
index c99d1b6..572accc 100644
--- a/chrome/service/cloud_print/printer_job_handler.cc
+++ b/chrome/service/cloud_print/printer_job_handler.cc
@@ -109,7 +109,10 @@ void PrinterJobHandler::Start() {
request_->StartGetRequest(
CloudPrintHelpers::GetUrlForPrinterDelete(
cloud_print_server_url_, printer_info_cloud_.printer_id),
- this, auth_token_, kCloudPrintAPIMaxRetryCount);
+ this,
+ auth_token_,
+ kCloudPrintAPIMaxRetryCount,
+ std::string());
}
if (!task_in_progress_ && printer_update_pending_) {
printer_update_pending_ = false;
@@ -125,7 +128,10 @@ void PrinterJobHandler::Start() {
CloudPrintHelpers::GetUrlForJobFetch(
cloud_print_server_url_, printer_info_cloud_.printer_id,
job_fetch_reason_),
- this, auth_token_, kCloudPrintAPIMaxRetryCount);
+ this,
+ auth_token_,
+ kCloudPrintAPIMaxRetryCount,
+ std::string());
last_job_fetch_time_ = base::TimeTicks::Now();
VLOG(1) << "Last job fetch time for printer "
<< printer_info_.printer_name.c_str() << " is "
@@ -254,7 +260,12 @@ void PrinterJobHandler::OnReceivePrinterCaps(
request_->StartPostRequest(
CloudPrintHelpers::GetUrlForPrinterUpdate(
cloud_print_server_url_, printer_info_cloud_.printer_id),
- this, auth_token_, kCloudPrintAPIMaxRetryCount, mime_type, post_data);
+ this,
+ auth_token_,
+ kCloudPrintAPIMaxRetryCount,
+ mime_type,
+ post_data,
+ std::string());
} else {
// We are done here. Go to the Stop state
MessageLoop::current()->PostTask(
@@ -408,7 +419,8 @@ PrinterJobHandler::HandleJobMetadataResponse(
request_->StartGetRequest(GURL(print_ticket_url.c_str()),
this,
auth_token_,
- kCloudPrintAPIMaxRetryCount);
+ kCloudPrintAPIMaxRetryCount,
+ std::string());
}
}
}
@@ -429,10 +441,13 @@ PrinterJobHandler::HandlePrintTicketResponse(const URLFetcher* source,
job_details_.print_ticket_ = data;
SetNextDataHandler(&PrinterJobHandler::HandlePrintDataResponse);
request_ = new CloudPrintURLFetcher;
+ std::string accept_headers = "Accept: ";
+ accept_headers += print_system_->GetSupportedMimeTypes();
request_->StartGetRequest(GURL(print_data_url_.c_str()),
this,
auth_token_,
- kJobDataMaxRetryCount);
+ kJobDataMaxRetryCount,
+ accept_headers);
} else {
// The print ticket was not valid. We are done here.
FailedFetchingJobData();
@@ -580,7 +595,8 @@ void PrinterJobHandler::UpdateJobStatus(cloud_print::PrintJobStatus status,
status),
this,
auth_token_,
- kCloudPrintAPIMaxRetryCount);
+ kCloudPrintAPIMaxRetryCount,
+ std::string());
}
}
}
diff --git a/printing/backend/win_helper.cc b/printing/backend/win_helper.cc
index e63b45f..b163a65 100644
--- a/printing/backend/win_helper.cc
+++ b/printing/backend/win_helper.cc
@@ -37,6 +37,17 @@ typedef HRESULT (WINAPI *PTMergeAndValidatePrintTicketProc)(
BSTR* error_message);
typedef HRESULT (WINAPI *PTReleaseMemoryProc)(PVOID buffer);
typedef HRESULT (WINAPI *PTCloseProviderProc)(HPTPROVIDER provider);
+typedef HRESULT (WINAPI *StartXpsPrintJobProc)(
+ const LPCWSTR printer_name,
+ const LPCWSTR job_name,
+ const LPCWSTR output_file_name,
+ HANDLE progress_event,
+ HANDLE completion_event,
+ UINT8 *printable_pages_on,
+ UINT32 printable_pages_on_count,
+ IXpsPrintJob **xps_print_job,
+ IXpsPrintJobStream **document_stream,
+ IXpsPrintJobStream **print_ticket_stream);
PTOpenProviderProc g_open_provider_proc = NULL;
PTGetPrintCapabilitiesProc g_get_print_capabilities_proc = NULL;
@@ -45,6 +56,7 @@ PTConvertPrintTicketToDevModeProc g_convert_print_ticket_to_devmode_proc = NULL;
PTMergeAndValidatePrintTicketProc g_merge_and_validate_print_ticket_proc = NULL;
PTReleaseMemoryProc g_release_memory_proc = NULL;
PTCloseProviderProc g_close_provider_proc = NULL;
+StartXpsPrintJobProc g_start_xps_print_job_proc = NULL;
}
namespace printing {
@@ -207,4 +219,45 @@ ScopedXPSInitializer::~ScopedXPSInitializer() {
initialized_ = false;
}
+bool XPSPrintModule::Init() {
+ static bool initialized = InitImpl();
+ return initialized;
+}
+
+bool XPSPrintModule::InitImpl() {
+ HMODULE xpsprint_module = LoadLibrary(L"xpsprint.dll");
+ if (xpsprint_module == NULL)
+ return false;
+ g_start_xps_print_job_proc = reinterpret_cast<StartXpsPrintJobProc>(
+ GetProcAddress(xpsprint_module, "StartXpsPrintJob"));
+ if (!g_start_xps_print_job_proc) {
+ NOTREACHED();
+ return false;
+ }
+ return true;
+}
+
+HRESULT XPSPrintModule::StartXpsPrintJob(
+ const LPCWSTR printer_name,
+ const LPCWSTR job_name,
+ const LPCWSTR output_file_name,
+ HANDLE progress_event,
+ HANDLE completion_event,
+ UINT8 *printable_pages_on,
+ UINT32 printable_pages_on_count,
+ IXpsPrintJob **xps_print_job,
+ IXpsPrintJobStream **document_stream,
+ IXpsPrintJobStream **print_ticket_stream) {
+ return g_start_xps_print_job_proc(printer_name,
+ job_name,
+ output_file_name,
+ progress_event,
+ completion_event,
+ printable_pages_on,
+ printable_pages_on_count,
+ xps_print_job,
+ document_stream,
+ print_ticket_stream);
+}
+
} // namespace printing
diff --git a/printing/backend/win_helper.h b/printing/backend/win_helper.h
index 891f833..28e57f7 100644
--- a/printing/backend/win_helper.h
+++ b/printing/backend/win_helper.h
@@ -9,6 +9,7 @@
#include <objidl.h>
#include <winspool.h>
#include <prntvpt.h>
+#include <xpsprint.h>
#include "base/string16.h"
@@ -70,6 +71,30 @@ class ScopedXPSInitializer {
bool initialized_;
};
+// Wrapper class to wrap the XPS Print APIs (these are different from the PTxxx
+// which deal with the XML Print Schema). This is needed because these
+// APIs are only available on Windows 7 and higher.
+class XPSPrintModule {
+ public:
+ // All the other methods can ONLY be called after a successful call to Init.
+ // Init can be called many times and by multiple threads.
+ static bool Init();
+ static HRESULT StartXpsPrintJob(
+ const LPCWSTR printer_name,
+ const LPCWSTR job_name,
+ const LPCWSTR output_file_name,
+ HANDLE progress_event,
+ HANDLE completion_event,
+ UINT8 *printable_pages_on,
+ UINT32 printable_pages_on_count,
+ IXpsPrintJob **xps_print_job,
+ IXpsPrintJobStream **document_stream,
+ IXpsPrintJobStream **print_ticket_stream);
+ private:
+ XPSPrintModule() { }
+ static bool InitImpl();
+};
+
} // namespace printing
#endif // PRINTING_BACKEND_WIN_HELPER_H_