summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/printing/print_preview_data_service.cc86
-rw-r--r--chrome/browser/printing/print_preview_data_service.h38
-rw-r--r--chrome/browser/printing/print_preview_message_handler.cc78
-rw-r--r--chrome/browser/printing/print_preview_message_handler.h7
-rw-r--r--chrome/browser/resources/print_preview/layout_settings.js6
-rw-r--r--chrome/browser/resources/print_preview/page_settings.js13
-rw-r--r--chrome/browser/resources/print_preview/print_preview.js91
-rw-r--r--chrome/browser/resources/print_preview/print_preview_utils.js10
-rw-r--r--chrome/browser/ui/webui/print_preview_data_source.cc23
-rw-r--r--chrome/browser/ui/webui/print_preview_data_source.h7
-rw-r--r--chrome/browser/ui/webui/print_preview_handler.cc12
-rw-r--r--chrome/browser/ui/webui/print_preview_ui.cc40
-rw-r--r--chrome/browser/ui/webui/print_preview_ui.h29
-rw-r--r--chrome/browser/ui/webui/print_preview_ui_unittest.cc94
-rw-r--r--chrome/common/print_messages.h35
-rw-r--r--chrome/renderer/mock_render_thread.cc8
-rw-r--r--chrome/renderer/mock_render_thread.h6
-rw-r--r--chrome/renderer/print_web_view_helper.cc89
-rw-r--r--chrome/renderer/print_web_view_helper.h28
-rw-r--r--chrome/renderer/print_web_view_helper_browsertest.cc6
-rw-r--r--chrome/renderer/print_web_view_helper_linux.cc14
-rw-r--r--chrome/renderer/print_web_view_helper_mac.mm48
-rw-r--r--chrome/renderer/print_web_view_helper_win.cc24
-rw-r--r--printing/print_job_constants.cc6
-rw-r--r--printing/print_job_constants.h4
25 files changed, 627 insertions, 175 deletions
diff --git a/chrome/browser/printing/print_preview_data_service.cc b/chrome/browser/printing/print_preview_data_service.cc
index 2199e73..53ba36f 100644
--- a/chrome/browser/printing/print_preview_data_service.cc
+++ b/chrome/browser/printing/print_preview_data_service.cc
@@ -4,7 +4,67 @@
#include "chrome/browser/printing/print_preview_data_service.h"
+#include "base/memory/ref_counted_memory.h"
#include "base/memory/singleton.h"
+#include "printing/print_job_constants.h"
+
+// PrintPreviewDataStore stores data for preview workflow and preview printing
+// workflow.
+//
+// NOTE:
+// This class stores a list of PDFs. The list |index| is zero-based and can
+// be |printing::COMPLETE_PREVIEW_DOCUMENT_INDEX| to represent complete preview
+// document. The PDF stored at |printing::COMPLETE_PREVIEW_DOCUMENT_INDEX| is
+// optimized with font subsetting, compression, etc. PDF's stored at all other
+// indices are unoptimized.
+//
+// PrintPreviewDataStore owns the data and is responsible for freeing it when
+// either:
+// a) There is a new data.
+// b) When PrintPreviewDataStore is destroyed.
+//
+class PrintPreviewDataStore : public base::RefCounted<PrintPreviewDataStore> {
+ public:
+ PrintPreviewDataStore() {}
+
+ // Get the preview page for the specified |index|.
+ void GetPreviewDataForIndex(int index, scoped_refptr<RefCountedBytes>* data) {
+ if (index != printing::COMPLETE_PREVIEW_DOCUMENT_INDEX &&
+ index < printing::FIRST_PAGE_INDEX) {
+ return;
+ }
+
+ PreviewPageDataMap::iterator it = page_data_map_.find(index);
+ if (it != page_data_map_.end())
+ *data = it->second.get();
+ }
+
+ // Set/Update the preview data entry for the specified |index|.
+ void SetPreviewDataForIndex(int index, const RefCountedBytes* data) {
+ if (index != printing::COMPLETE_PREVIEW_DOCUMENT_INDEX &&
+ index < printing::FIRST_PAGE_INDEX) {
+ return;
+ }
+
+ page_data_map_[index] = const_cast<RefCountedBytes*>(data);
+ }
+
+ private:
+ friend class base::RefCounted<PrintPreviewDataStore>;
+
+ // 1:1 relationship between page index and its associated preview data.
+ // Key: Page index is zero-based and can be
+ // |printing::COMPLETE_PREVIEW_DOCUMENT_INDEX| to represent complete preview
+ // document.
+ // Value: Preview data.
+ typedef std::map<int, scoped_refptr<RefCountedBytes> > PreviewPageDataMap;
+
+ ~PrintPreviewDataStore() {}
+
+ PreviewPageDataMap page_data_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrintPreviewDataStore);
+};
// static
PrintPreviewDataService* PrintPreviewDataService::GetInstance() {
@@ -19,21 +79,29 @@ PrintPreviewDataService::~PrintPreviewDataService() {
void PrintPreviewDataService::GetDataEntry(
const std::string& preview_ui_addr_str,
+ int index,
scoped_refptr<RefCountedBytes>* data_bytes) {
- PreviewDataSourceMap::iterator it = data_src_map_.find(preview_ui_addr_str);
- if (it != data_src_map_.end())
- *data_bytes = it->second.get();
+ *data_bytes = NULL;
+ PreviewDataStoreMap::iterator it = data_store_map_.find(preview_ui_addr_str);
+ if (it != data_store_map_.end())
+ it->second->GetPreviewDataForIndex(index, data_bytes);
}
void PrintPreviewDataService::SetDataEntry(
- const std::string& preview_ui_addr_str, const RefCountedBytes* data_bytes) {
- RemoveEntry(preview_ui_addr_str);
- data_src_map_[preview_ui_addr_str] = const_cast<RefCountedBytes*>(data_bytes);
+ const std::string& preview_ui_addr_str,
+ int index,
+ const RefCountedBytes* data_bytes) {
+ PreviewDataStoreMap::iterator it = data_store_map_.find(preview_ui_addr_str);
+ if (it == data_store_map_.end())
+ data_store_map_[preview_ui_addr_str] = new PrintPreviewDataStore();
+
+ data_store_map_[preview_ui_addr_str]->SetPreviewDataForIndex(index,
+ data_bytes);
}
void PrintPreviewDataService::RemoveEntry(
const std::string& preview_ui_addr_str) {
- PreviewDataSourceMap::iterator it = data_src_map_.find(preview_ui_addr_str);
- if (it != data_src_map_.end())
- data_src_map_.erase(it);
+ PreviewDataStoreMap::iterator it = data_store_map_.find(preview_ui_addr_str);
+ if (it != data_store_map_.end())
+ data_store_map_.erase(it);
}
diff --git a/chrome/browser/printing/print_preview_data_service.h b/chrome/browser/printing/print_preview_data_service.h
index 63618ac..2e94393 100644
--- a/chrome/browser/printing/print_preview_data_service.h
+++ b/chrome/browser/printing/print_preview_data_service.h
@@ -10,27 +10,31 @@
#include <string>
#include "base/memory/ref_counted.h"
-#include "base/memory/ref_counted_memory.h"
template<typename T> struct DefaultSingletonTraits;
-// PrintPreviewDataService manages data for chrome://print requests.
-//
-// PrintPreviewDataService owns the data and is responsible for freeing it when
-// either:
-// a) There is a new data.
-// b) When PrintPreviewDataService is destroyed.
-//
+class PrintPreviewDataStore;
+class RefCountedBytes;
+
+// PrintPreviewDataService manages data stores for chrome://print requests.
+// It owns the data store object and is responsible for freeing it.
class PrintPreviewDataService {
public:
static PrintPreviewDataService* GetInstance();
- // Get the data entry from PreviewDataSourceMap.
- void GetDataEntry(const std::string& preview_ui_addr_str,
+ // Get the data entry from PrintPreviewDataStore. |index| is zero-based or
+ // |printing::COMPLETE_PREVIEW_DOCUMENT_INDEX| to represent complete preview
+ // data. Use |index| to retrieve a specific preview page data. |data| is set
+ // to NULL if the requested page is not yet available.
+ void GetDataEntry(const std::string& preview_ui_addr_str, int index,
scoped_refptr<RefCountedBytes>* data);
- // Set/Update the data entry in PreviewDataSourceMap.
- void SetDataEntry(const std::string& preview_ui_addr_str,
+ // Set/Update the data entry in PrintPreviewDataStore. |index| is zero-based
+ // or |printing::COMPLETE_PREVIEW_DOCUMENT_INDEX| to represent complete
+ // preview data. Use |index| to set/update a specific preview page data.
+ // NOTE: PrintPreviewDataStore owns the data. Do not refcount |data| before
+ // calling this function. It will be refcounted in PrintPreviewDataStore.
+ void SetDataEntry(const std::string& preview_ui_addr_str, int index,
const RefCountedBytes* data);
// Remove the corresponding PrintPreviewUI entry from the map.
@@ -39,16 +43,16 @@ class PrintPreviewDataService {
private:
friend struct DefaultSingletonTraits<PrintPreviewDataService>;
- // 1:1 relationship between PrintPreviewUI and preview data.
+ // 1:1 relationship between PrintPreviewUI and data store object.
// Key: Print preview UI address string.
- // Value: Preview data.
- typedef std::map<std::string, scoped_refptr<RefCountedBytes> >
- PreviewDataSourceMap;
+ // Value: Print preview data store object.
+ typedef std::map<std::string, scoped_refptr<PrintPreviewDataStore> >
+ PreviewDataStoreMap;
PrintPreviewDataService();
virtual ~PrintPreviewDataService();
- PreviewDataSourceMap data_src_map_;
+ PreviewDataStoreMap data_store_map_;
DISALLOW_COPY_AND_ASSIGN(PrintPreviewDataService);
};
diff --git a/chrome/browser/printing/print_preview_message_handler.cc b/chrome/browser/printing/print_preview_message_handler.cc
index 75aa54c..d2b1181 100644
--- a/chrome/browser/printing/print_preview_message_handler.cc
+++ b/chrome/browser/printing/print_preview_message_handler.cc
@@ -7,6 +7,8 @@
#include <vector>
#include "base/memory/ref_counted.h"
+#include "base/memory/ref_counted_memory.h"
+#include "base/shared_memory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/printing/background_printing_manager.h"
#include "chrome/browser/printing/print_job_manager.h"
@@ -21,6 +23,7 @@
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/common/content_restriction.h"
+#include "printing/print_job_constants.h"
namespace {
@@ -37,6 +40,20 @@ void StopWorker(int document_cookie) {
}
}
+RefCountedBytes* GetDataFromHandle(base::SharedMemoryHandle handle,
+ uint32 data_size) {
+ scoped_ptr<base::SharedMemory> shared_buf(
+ new base::SharedMemory(handle, true));
+ if (!shared_buf->Map(data_size)) {
+ NOTREACHED();
+ return NULL;
+ }
+ char* preview_data = static_cast<char*>(shared_buf->memory());
+ std::vector<unsigned char> data(data_size);
+ memcpy(&data[0], preview_data, data_size);
+ return RefCountedBytes::TakeVector(&data);
+}
+
} // namespace
namespace printing {
@@ -64,7 +81,8 @@ void PrintPreviewMessageHandler::OnRequestPrintPreview() {
}
void PrintPreviewMessageHandler::OnDidGetPreviewPageCount(int document_cookie,
- int page_count) {
+ int page_count,
+ bool is_modifiable) {
if (page_count <= 0)
return;
TabContents* print_preview_tab = GetPrintPreviewTab();
@@ -73,10 +91,12 @@ void PrintPreviewMessageHandler::OnDidGetPreviewPageCount(int document_cookie,
PrintPreviewUI* print_preview_ui =
static_cast<PrintPreviewUI*>(print_preview_tab->web_ui());
- print_preview_ui->OnDidGetPreviewPageCount(document_cookie, page_count);
+ print_preview_ui->OnDidGetPreviewPageCount(
+ document_cookie, page_count, is_modifiable);
}
-void PrintPreviewMessageHandler::OnDidPreviewPage(int page_number) {
+void PrintPreviewMessageHandler::OnDidPreviewPage(
+ const PrintHostMsg_DidPreviewPage_Params& params) {
RenderViewHost* rvh = tab_contents()->render_view_host();
TabContents* print_preview_tab = GetPrintPreviewTab();
if (!(print_preview_tab && print_preview_tab->web_ui())) {
@@ -96,10 +116,25 @@ void PrintPreviewMessageHandler::OnDidPreviewPage(int page_number) {
return;
}
- // Continue
- if (page_number >= 0)
+ int requested_preview_page_index = INVALID_PAGE_INDEX;
+ int page_number = params.page_number;
+
+ if (page_number == FIRST_PAGE_INDEX)
+ print_preview_ui->ClearAllPreviewData();
+
+ if (page_number >= FIRST_PAGE_INDEX && params.data_size) {
+ RefCountedBytes* data_bytes =
+ GetDataFromHandle(params.metafile_data_handle, params.data_size);
+ DCHECK(data_bytes);
+
+ print_preview_ui->SetPrintPreviewDataForIndex(page_number, data_bytes);
print_preview_ui->OnDidPreviewPage(page_number);
- rvh->Send(new PrintMsg_ContinuePreview(rvh->routing_id()));
+ // TODO(kmadhusu): Query |PrintPreviewUI| and update
+ // |requested_preview_page_index| accordingly.
+ }
+
+ rvh->Send(new PrintMsg_ContinuePreview(rvh->routing_id(),
+ requested_preview_page_index));
}
void PrintPreviewMessageHandler::OnPagesReadyForPreview(
@@ -121,41 +156,28 @@ void PrintPreviewMessageHandler::OnPagesReadyForPreview(
if (params.reuse_existing_data) {
// Need to match normal rendering where we are expected to send this.
print_preview_ui->OnDidGetPreviewPageCount(params.document_cookie,
- params.expected_pages_count);
-
- print_preview_ui->OnPreviewDataIsAvailable(
- params.expected_pages_count,
- wrapper->print_view_manager()->RenderSourceName(),
- params.modifiable,
- params.preview_request_id);
- return;
- }
+ params.expected_pages_count,
+ params.modifiable);
- base::SharedMemory* shared_buf =
- new base::SharedMemory(params.metafile_data_handle, true);
- if (!shared_buf->Map(params.data_size)) {
- NOTREACHED();
- delete shared_buf;
+ print_preview_ui->OnReusePreviewData(params.preview_request_id);
return;
}
wrapper->print_view_manager()->OverrideTitle(tab_contents());
- const unsigned char* preview_data =
- static_cast<unsigned char*>(shared_buf->memory());
- uint32 preview_data_size = params.data_size;
-
// TODO(joth): This seems like a good match for using RefCountedStaticMemory
// to avoid the memory copy, but the SetPrintPreviewData call chain below
// needs updating to accept the RefCountedMemory* base class.
- scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
- html_bytes->data().assign(preview_data, preview_data + preview_data_size);
+ RefCountedBytes* data_bytes =
+ GetDataFromHandle(params.metafile_data_handle, params.data_size);
+ if (!data_bytes)
+ return;
- print_preview_ui->SetPrintPreviewData(html_bytes.get());
+ print_preview_ui->SetPrintPreviewDataForIndex(COMPLETE_PREVIEW_DOCUMENT_INDEX,
+ data_bytes);
print_preview_ui->OnPreviewDataIsAvailable(
params.expected_pages_count,
wrapper->print_view_manager()->RenderSourceName(),
- params.modifiable,
params.preview_request_id);
}
diff --git a/chrome/browser/printing/print_preview_message_handler.h b/chrome/browser/printing/print_preview_message_handler.h
index 9d049d0..ff56b01 100644
--- a/chrome/browser/printing/print_preview_message_handler.h
+++ b/chrome/browser/printing/print_preview_message_handler.h
@@ -9,6 +9,7 @@
#include "content/browser/tab_contents/tab_contents_observer.h"
struct PrintHostMsg_DidPreviewDocument_Params;
+struct PrintHostMsg_DidPreviewPage_Params;
namespace printing {
@@ -30,9 +31,11 @@ class PrintPreviewMessageHandler : public TabContentsObserver {
// Message handlers.
void OnRequestPrintPreview();
- void OnDidGetPreviewPageCount(int document_cookie, int page_count);
+ void OnDidGetPreviewPageCount(int document_cookie,
+ int page_count,
+ bool is_modifiable);
// |page_number| is 0-based.
- void OnDidPreviewPage(int page_number);
+ void OnDidPreviewPage(const PrintHostMsg_DidPreviewPage_Params& params);
void OnPagesReadyForPreview(
const PrintHostMsg_DidPreviewDocument_Params& params);
void OnPrintPreviewFailed(int document_cookie);
diff --git a/chrome/browser/resources/print_preview/layout_settings.js b/chrome/browser/resources/print_preview/layout_settings.js
index 2f74381..0932e21 100644
--- a/chrome/browser/resources/print_preview/layout_settings.js
+++ b/chrome/browser/resources/print_preview/layout_settings.js
@@ -66,7 +66,8 @@ cr.define('print_preview', function() {
* @private
*/
onPrinterCapabilitiesUpdated_: function(e) {
- this.fadeInOut(e.printerCapabilities.disableLandscapeOption);
+ if (e.printerCapabilities.disableLandscapeOption)
+ this.fadeInOut_(e.printerCapabilities.disableLandscapeOption);
},
/**
@@ -93,8 +94,9 @@ cr.define('print_preview', function() {
/**
* @param {boolean} fadeOut True if |this.layoutOption_| should be faded
* out, false if it should be faded in.
+ * @private
*/
- fadeInOut: function(fadeOut) {
+ fadeInOut_: function(fadeOut) {
fadeOut ? fadeOutElement(this.layoutOption_) :
fadeInElement(this.layoutOption_);
}
diff --git a/chrome/browser/resources/print_preview/page_settings.js b/chrome/browser/resources/print_preview/page_settings.js
index 5d8656b..48210c6 100644
--- a/chrome/browser/resources/print_preview/page_settings.js
+++ b/chrome/browser/resources/print_preview/page_settings.js
@@ -20,7 +20,8 @@ cr.define('print_preview', function() {
// whenever needed.
this.timerId_;
- // Contains the previously selected pages. It is used in
+ // Contains the previously selected pages (pages requested by last
+ // preview request). It is used in
// |this.onSelectedPagesMayHaveChanged_()| to make sure that a new preview
// is not requested more often than necessary.
this.previouslySelectedPages_ = [];
@@ -108,6 +109,16 @@ cr.define('print_preview', function() {
},
/**
+ * Returns the previously selected pages in ascending order without any
+ * duplicates.
+ *
+ * @return {Array}
+ */
+ get previouslySelectedPages() {
+ return this.previouslySelectedPages_;
+ },
+
+ /**
* Returns an array of objects describing the selected page ranges. See
* documentation of pageSetToPageRanges() for more details.
* @return {Array}
diff --git a/chrome/browser/resources/print_preview/print_preview.js b/chrome/browser/resources/print_preview/print_preview.js
index 17bdbcf..4f2aa94 100644
--- a/chrome/browser/resources/print_preview/print_preview.js
+++ b/chrome/browser/resources/print_preview/print_preview.js
@@ -71,6 +71,7 @@ var addedCloudPrinters = {};
// The maximum number of cloud printers to allow in the dropdown.
const maxCloudPrinters = 10;
+var isPipeliningSupported = false;
/**
* Window onload handler, sets up the page and starts print preview by getting
@@ -79,6 +80,8 @@ const maxCloudPrinters = 10;
function onLoad() {
cr.enablePlatformSpecificCSSRules();
+ isPipeliningSupported = !cr.isWindows;
+
if (!checkCompatiblePluginExists()) {
disableInputElementsInSidebar();
displayErrorMessageWithButton(localStrings.getString('noPlugin'),
@@ -365,6 +368,16 @@ function hasRequestedPreview() {
}
/**
+ * Checks if |previewResponseId| matches |lastPreviewRequestId|. Used to ignore
+ * obsolete preview data responses.
+ * @param {number} previewResponseId The id to check.
+ * @return {boolean} True if previewResponseId reffers to the expected response.
+ */
+function isExpectedPreviewResponse(previewResponseId) {
+ return lastPreviewRequestID == previewResponseId;
+}
+
+/**
* Returns the name of the selected printer or the empty string if no
* printer is selected.
* @return {string} The name of the currently selected printer.
@@ -790,6 +803,10 @@ function printPreviewFailed() {
* Called when the PDF plugin loads its document.
*/
function onPDFLoad() {
+ if (previewModifiable && isPipeliningSupported) {
+ setPluginPreviewPageCount();
+ cr.dispatchSimpleEvent(document, 'updateSummary');
+ }
$('pdf-viewer').fitToHeight();
setColor($('color').checked);
hideLoadingAnimation();
@@ -797,13 +814,41 @@ function onPDFLoad() {
cr.dispatchSimpleEvent(document, 'PDFLoaded');
}
+function setPluginPreviewPageCount() {
+ $('pdf-viewer').printPreviewPageCount(
+ pageSettings.previouslySelectedPages.length);
+}
+
/**
* Update the page count and check the page range.
* Called from PrintPreviewUI::OnDidGetPreviewPageCount().
* @param {number} pageCount The number of pages.
+ * @param {boolean} isModifiable Indicates whether the previewed document can be
+ * modified.
*/
-function onDidGetPreviewPageCount(pageCount) {
+function onDidGetPreviewPageCount(pageCount, isModifiable) {
pageSettings.updateState(pageCount);
+ previewModifiable = isModifiable;
+}
+
+/**
+ * Called when no pipelining previewed pages.
+ */
+function reloadPreviewPages(previewUid, previewResponseId) {
+ if (!isExpectedPreviewResponse(previewResponseId))
+ return;
+ hasPendingPreviewRequest = false;
+
+ if (checkIfSettingsChangedAndRegeneratePreview())
+ return;
+ cr.dispatchSimpleEvent(document, 'updateSummary');
+ cr.dispatchSimpleEvent(document, 'updatePrintButton');
+ addEventListeners();
+ hideLoadingAnimation();
+ var pageSet = pageSettings.previouslySelectedPages;
+ for (var i = 0; i < pageSet.length; i++)
+ $('pdf-viewer').loadPreviewPage(getPageSrcURL(previewUid, pageSet[i]-1), i);
+ // TODO(dpapad): handle pending print file requests.
}
/**
@@ -812,10 +857,20 @@ function onDidGetPreviewPageCount(pageCount) {
* Called from PrintPreviewUI::OnDidPreviewPage().
* @param {number} pageNumber The page number, 0-based.
*/
-function onDidPreviewPage(pageNumber) {
+function onDidPreviewPage(pageNumber, previewUid) {
+ // Refactor
+ if (!previewModifiable || !isPipeliningSupported)
+ return;
+
+ var pageIndex = pageSettings.previouslySelectedPages.indexOf(pageNumber + 1);
+
if (checkIfSettingsChangedAndRegeneratePreview())
return;
- // TODO(thestig) Make use of |pageNumber| for pipelined preview generation.
+ if (pageIndex == 0)
+ createPDFPlugin(previewUid);
+
+ $('pdf-viewer').loadPreviewPage(
+ getPageSrcURL(previewUid, pageNumber), pageIndex);
}
/**
@@ -825,24 +880,26 @@ function onDidPreviewPage(pageNumber) {
* @param {string} jobTitle The print job title.
* @param {boolean} modifiable If the preview is modifiable.
* @param {string} previewUid Preview unique identifier.
- * @param {number} previewRequestId The preview request id that resulted in this
- * response.
+ * @param {number} previewResponseId The preview request id that resulted in
+ * this response.
*/
function updatePrintPreview(jobTitle,
- modifiable,
previewUid,
- previewRequestId) {
- if (lastPreviewRequestID != previewRequestId)
+ previewResponseId) {
+ if (!isExpectedPreviewResponse(previewResponseId))
return;
hasPendingPreviewRequest = false;
if (checkIfSettingsChangedAndRegeneratePreview())
return;
- previewModifiable = modifiable;
document.title = localStrings.getStringF('printPreviewTitleFormat', jobTitle);
- createPDFPlugin(previewUid);
+ if (!previewModifiable || !isPipeliningSupported) {
+ // If the preview is not modifiable the plugin has not been created yet.
+ createPDFPlugin(previewUid);
+ }
+
cr.dispatchSimpleEvent(document, 'updateSummary');
cr.dispatchSimpleEvent(document, 'updatePrintButton');
addEventListeners();
@@ -883,17 +940,19 @@ function createPDFPlugin(previewUid) {
// Need to call this before the reload(), where the plugin resets its
// internal page count.
pdfViewer.goToPage('0');
-
pdfViewer.reload();
pdfViewer.grayscale(!isColor());
return;
}
+ // Get the complete preview document.
+ var dataIndex = previewModifiable && isPipeliningSupported ? '0' : '-1';
+
pdfViewer = document.createElement('embed');
pdfViewer.setAttribute('id', 'pdf-viewer');
pdfViewer.setAttribute('type',
'application/x-google-chrome-print-preview-pdf');
- pdfViewer.setAttribute('src', 'chrome://print/' + previewUid + '/print.pdf');
+ pdfViewer.setAttribute('src', getPageSrcURL(previewUid, dataIndex));
pdfViewer.setAttribute('aria-live', 'polite');
pdfViewer.setAttribute('aria-atomic', 'true');
$('mainview').appendChild(pdfViewer);
@@ -907,9 +966,11 @@ function createPDFPlugin(previewUid) {
*/
function checkCompatiblePluginExists() {
var dummyPlugin = $('dummy-viewer')
- return (dummyPlugin.onload &&
- dummyPlugin.goToPage &&
- dummyPlugin.removePrintButton);
+ return !!(dummyPlugin.onload &&
+ dummyPlugin.goToPage &&
+ dummyPlugin.removePrintButton &&
+ dummyPlugin.loadPreviewPage &&
+ dummyPlugin.printPreviewPageCount);
}
window.addEventListener('DOMContentLoaded', onLoad);
diff --git a/chrome/browser/resources/print_preview/print_preview_utils.js b/chrome/browser/resources/print_preview/print_preview_utils.js
index 26a3760..68e5224 100644
--- a/chrome/browser/resources/print_preview/print_preview_utils.js
+++ b/chrome/browser/resources/print_preview/print_preview_utils.js
@@ -179,3 +179,13 @@ function pageSetToPageRanges(pageSet) {
}
return pageRanges;
}
+
+/**
+ * Constructs a url for getting a specific page.
+ * @param {string} id The id of the preview data.
+ * @param {number} pageNumber The number of the desired page.
+ * @return {string} The constructed URL.
+ */
+function getPageSrcURL(id, pageNumber) {
+ return 'chrome://print/' + id + '/' + pageNumber + '/print.pdf';
+}
diff --git a/chrome/browser/ui/webui/print_preview_data_source.cc b/chrome/browser/ui/webui/print_preview_data_source.cc
index 04399b2..5cda03d 100644
--- a/chrome/browser/ui/webui/print_preview_data_source.cc
+++ b/chrome/browser/ui/webui/print_preview_data_source.cc
@@ -7,7 +7,9 @@
#include <algorithm>
#include "base/message_loop.h"
+#include "base/string_number_conversions.h"
#include "base/string_piece.h"
+#include "base/string_split.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
@@ -140,13 +142,18 @@ PrintPreviewDataSource::~PrintPreviewDataSource() {
void PrintPreviewDataSource::StartDataRequest(const std::string& path,
bool is_incognito,
int request_id) {
- scoped_refptr<RefCountedBytes> data(new RefCountedBytes);
+ scoped_refptr<RefCountedBytes> data;
bool preview_data_requested = EndsWith(path, "/print.pdf", true);
if (preview_data_requested) {
- size_t index = path.rfind("/print.pdf");
- PrintPreviewDataService::GetInstance()->GetDataEntry(path.substr(0, index),
- &data);
+ std::vector<std::string> url_substr;
+ base::SplitString(path, '/', &url_substr);
+ int page_index = 0;
+ if (url_substr.size() == 3 && base::StringToInt(url_substr[1],
+ &page_index)) {
+ PrintPreviewDataService::GetInstance()->GetDataEntry(url_substr[0],
+ page_index, &data);
+ }
}
if (path.empty()) {
@@ -163,11 +170,11 @@ void PrintPreviewDataSource::StartDataRequest(const std::string& path,
SendResponse(request_id, base::RefCountedString::TakeString(&full_html));
return;
- } else if (preview_data_requested && data->front()) {
+ } else if (preview_data_requested && data.get()) {
// Print Preview data.
SendResponse(request_id, data);
return;
- } else {
+ } else {
// Invalid request.
scoped_refptr<RefCountedBytes> empty_bytes(new RefCountedBytes);
SendResponse(request_id, empty_bytes);
@@ -176,7 +183,5 @@ void PrintPreviewDataSource::StartDataRequest(const std::string& path,
}
std::string PrintPreviewDataSource::GetMimeType(const std::string& path) const {
- if (path.empty())
- return "text/html"; // Print Preview Index Page.
- return "application/pdf"; // Print Preview data
+ return path.empty() ? "text/html" : "application/pdf";
}
diff --git a/chrome/browser/ui/webui/print_preview_data_source.h b/chrome/browser/ui/webui/print_preview_data_source.h
index a6b02a1..7f82d00 100644
--- a/chrome/browser/ui/webui/print_preview_data_source.h
+++ b/chrome/browser/ui/webui/print_preview_data_source.h
@@ -14,13 +14,16 @@
// PrintPreviewDataSource serves data for chrome://print requests.
//
// The format for requesting data is as follows:
-// chrome://print/<PrintPreviewUIAddrStr>/print.pdf
+// chrome://print/<PrintPreviewUIAddrStr>/<PageIndex>/print.pdf
//
// Parameters (< > required):
// <PrintPreviewUIAddrStr> = Print preview UI identifier.
+// <PageIndex> = Page index is zero-based or
+// |printing::COMPLETE_PREVIEW_DOCUMENT_INDEX| to represent
+// a print ready PDF.
//
// Example:
-// chrome://print/0xab0123ef/print.pdf
+// chrome://print/0xab0123ef/10/print.pdf
class PrintPreviewDataSource : public ChromeURLDataManager::DataSource {
public:
diff --git a/chrome/browser/ui/webui/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview_handler.cc
index 0096840..22be5a7 100644
--- a/chrome/browser/ui/webui/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview_handler.cc
@@ -713,8 +713,9 @@ void PrintPreviewHandler::SendCloudPrintJob(const DictionaryValue& settings,
std::string print_ticket) {
scoped_refptr<RefCountedBytes> data;
PrintPreviewUI* print_preview_ui = static_cast<PrintPreviewUI*>(web_ui_);
- print_preview_ui->GetPrintPreviewData(&data);
- CHECK(data->front());
+ print_preview_ui->GetPrintPreviewDataForIndex(
+ printing::COMPLETE_PREVIEW_DOCUMENT_INDEX, &data);
+ CHECK(data.get());
DCHECK_GT(data->size(), 0U);
TabContentsWrapper* wrapper =
@@ -846,9 +847,10 @@ void PrintPreviewHandler::OnNavigation() {
void PrintPreviewHandler::FileSelected(const FilePath& path,
int index, void* params) {
PrintPreviewUI* print_preview_ui = static_cast<PrintPreviewUI*>(web_ui_);
- scoped_refptr<RefCountedBytes> data(new RefCountedBytes());
- print_preview_ui->GetPrintPreviewData(&data);
- if (!data->front()) {
+ scoped_refptr<RefCountedBytes> data;
+ print_preview_ui->GetPrintPreviewDataForIndex(
+ printing::COMPLETE_PREVIEW_DOCUMENT_INDEX, &data);
+ if (!data.get()) {
NOTREACHED();
return;
}
diff --git a/chrome/browser/ui/webui/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview_ui.cc
index 6fe75d5..bb3c037 100644
--- a/chrome/browser/ui/webui/print_preview_ui.cc
+++ b/chrome/browser/ui/webui/print_preview_ui.cc
@@ -37,12 +37,19 @@ PrintPreviewUI::~PrintPreviewUI() {
print_preview_data_service()->RemoveEntry(preview_ui_addr_str_);
}
-void PrintPreviewUI::GetPrintPreviewData(scoped_refptr<RefCountedBytes>* data) {
- print_preview_data_service()->GetDataEntry(preview_ui_addr_str_, data);
+void PrintPreviewUI::GetPrintPreviewDataForIndex(
+ int index,
+ scoped_refptr<RefCountedBytes>* data) {
+ print_preview_data_service()->GetDataEntry(preview_ui_addr_str_, index, data);
}
-void PrintPreviewUI::SetPrintPreviewData(const RefCountedBytes* data) {
- print_preview_data_service()->SetDataEntry(preview_ui_addr_str_, data);
+void PrintPreviewUI::SetPrintPreviewDataForIndex(int index,
+ const RefCountedBytes* data) {
+ print_preview_data_service()->SetDataEntry(preview_ui_addr_str_, index, data);
+}
+
+void PrintPreviewUI::ClearAllPreviewData() {
+ print_preview_data_service()->RemoveEntry(preview_ui_addr_str_);
}
void PrintPreviewUI::OnInitiatorTabClosed(
@@ -56,22 +63,33 @@ void PrintPreviewUI::OnPrintPreviewRequest() {
}
void PrintPreviewUI::OnDidGetPreviewPageCount(int document_cookie,
- int page_count) {
+ int page_count,
+ bool is_modifiable) {
DCHECK_GT(page_count, 0);
document_cookie_ = document_cookie;
FundamentalValue count(page_count);
- CallJavascriptFunction("onDidGetPreviewPageCount", count);
+ FundamentalValue modifiable(is_modifiable);
+ CallJavascriptFunction("onDidGetPreviewPageCount", count, modifiable);
}
void PrintPreviewUI::OnDidPreviewPage(int page_number) {
DCHECK_GE(page_number, 0);
FundamentalValue number(page_number);
- CallJavascriptFunction("onDidPreviewPage", number);
+ StringValue ui_identifier(preview_ui_addr_str_);
+ CallJavascriptFunction("onDidPreviewPage", number, ui_identifier);
+}
+
+void PrintPreviewUI::OnReusePreviewData(int preview_request_id) {
+ DecrementRequestCount();
+
+ StringValue ui_identifier(preview_ui_addr_str_);
+ FundamentalValue ui_preview_request_id(preview_request_id);
+ CallJavascriptFunction("reloadPreviewPages", ui_identifier,
+ ui_preview_request_id);
}
void PrintPreviewUI::OnPreviewDataIsAvailable(int expected_pages_count,
const string16& job_title,
- bool modifiable,
int preview_request_id) {
VLOG(1) << "Print preview request finished with "
<< expected_pages_count << " pages";
@@ -84,13 +102,11 @@ void PrintPreviewUI::OnPreviewDataIsAvailable(int expected_pages_count,
expected_pages_count);
initial_preview_start_time_ = base::TimeTicks();
}
- FundamentalValue pages_count(expected_pages_count);
StringValue title(job_title);
- FundamentalValue is_preview_modifiable(modifiable);
StringValue ui_identifier(preview_ui_addr_str_);
FundamentalValue ui_preview_request_id(preview_request_id);
- CallJavascriptFunction("updatePrintPreview", title, is_preview_modifiable,
- ui_identifier, ui_preview_request_id);
+ CallJavascriptFunction("updatePrintPreview", title, ui_identifier,
+ ui_preview_request_id);
}
void PrintPreviewUI::OnNavigation() {
diff --git a/chrome/browser/ui/webui/print_preview_ui.h b/chrome/browser/ui/webui/print_preview_ui.h
index 13b4aff..192611b 100644
--- a/chrome/browser/ui/webui/print_preview_ui.h
+++ b/chrome/browser/ui/webui/print_preview_ui.h
@@ -22,13 +22,19 @@ class PrintPreviewUI : public ChromeWebUI {
explicit PrintPreviewUI(TabContents* contents);
virtual ~PrintPreviewUI();
- // Gets the print preview |data|. The data is valid as long as the
- // PrintPreviewDataService is valid and SetPrintPreviewData() does not get
- // called.
- void GetPrintPreviewData(scoped_refptr<RefCountedBytes>* data);
+ // Gets the print preview |data|. |index| is zero-based, and can be
+ // |printing::COMPLETE_PREVIEW_DOCUMENT_INDEX| to get the entire preview
+ // document.
+ void GetPrintPreviewDataForIndex(int index,
+ scoped_refptr<RefCountedBytes>* data);
- // Sets the print preview |data|.
- void SetPrintPreviewData(const RefCountedBytes* data);
+ // Sets the print preview |data|. |index| is zero-based, and can be
+ // |printing::COMPLETE_PREVIEW_DOCUMENT_INDEX| to set the entire preview
+ // document.
+ void SetPrintPreviewDataForIndex(int index, const RefCountedBytes* data);
+
+ // Clear the existing print preview data.
+ void ClearAllPreviewData();
// Notify the Web UI that there is a print preview request.
// There should be a matching call to OnPreviewDataIsAvailable() or
@@ -36,7 +42,11 @@ class PrintPreviewUI : public ChromeWebUI {
void OnPrintPreviewRequest();
// Notify the Web UI that the print preview will have |page_count| pages.
- void OnDidGetPreviewPageCount(int document_cookie_, int page_count);
+ // |is_modifiable| indicates if the preview can be rerendered with different
+ // print settings.
+ void OnDidGetPreviewPageCount(int document_cookie_,
+ int page_count,
+ bool is_modifiable);
// Notify the Web UI that the 0-based page |page_number| has been rendered.
void OnDidPreviewPage(int page_number);
@@ -44,14 +54,13 @@ class PrintPreviewUI : public ChromeWebUI {
// Notify the Web UI renderer that preview data is available.
// |expected_pages_count| specifies the total number of pages.
// |job_title| is the title of the page being previewed.
- // |modifiable| indicates if the preview can be rerendered with different
- // print settings.
// |preview_request_id| indicates wich request resulted in this response.
void OnPreviewDataIsAvailable(int expected_pages_count,
const string16& job_title,
- bool modifiable,
int preview_request_id);
+ void OnReusePreviewData(int preview_request_id);
+
// Notify the Web UI that a navigation has occurred in this tab. This is the
// last chance to communicate with the source tab before the assocation is
// erased.
diff --git a/chrome/browser/ui/webui/print_preview_ui_unittest.cc b/chrome/browser/ui/webui/print_preview_ui_unittest.cc
index 65613d3..53a09c1 100644
--- a/chrome/browser/ui/webui/print_preview_ui_unittest.cc
+++ b/chrome/browser/ui/webui/print_preview_ui_unittest.cc
@@ -11,6 +11,7 @@
#include "chrome/test/browser_with_test_window_test.h"
#include "chrome/test/testing_profile.h"
#include "content/browser/tab_contents/tab_contents.h"
+#include "printing/print_job_constants.h"
namespace {
@@ -47,20 +48,99 @@ TEST_F(PrintPreviewUITest, PrintPreviewData) {
reinterpret_cast<PrintPreviewUI*>(preview_tab->web_ui());
ASSERT_TRUE(preview_ui != NULL);
- scoped_refptr<RefCountedBytes> data(new RefCountedBytes);
- preview_ui->GetPrintPreviewData(&data);
- EXPECT_EQ(NULL, data->front());
- EXPECT_EQ(0U, data->size());
+ scoped_refptr<RefCountedBytes> data;
+ preview_ui->GetPrintPreviewDataForIndex(
+ printing::COMPLETE_PREVIEW_DOCUMENT_INDEX,
+ &data);
+ EXPECT_EQ(NULL, data.get());
std::vector<unsigned char> preview_data(blob1, blob1 + sizeof(blob1));
scoped_refptr<RefCountedBytes> dummy_data(new RefCountedBytes(preview_data));
- preview_ui->SetPrintPreviewData(dummy_data.get());
- preview_ui->GetPrintPreviewData(&data);
+ preview_ui->SetPrintPreviewDataForIndex(
+ printing::COMPLETE_PREVIEW_DOCUMENT_INDEX,
+ dummy_data.get());
+ preview_ui->GetPrintPreviewDataForIndex(
+ printing::COMPLETE_PREVIEW_DOCUMENT_INDEX,
+ &data);
EXPECT_EQ(dummy_data->size(), data->size());
EXPECT_EQ(dummy_data.get(), data.get());
// This should not cause any memory leaks.
dummy_data = new RefCountedBytes();
- preview_ui->SetPrintPreviewData(dummy_data);
+ preview_ui->SetPrintPreviewDataForIndex(printing::FIRST_PAGE_INDEX,
+ dummy_data);
+
+ // Clear the preview data.
+ preview_ui->ClearAllPreviewData();
+
+ preview_ui->GetPrintPreviewDataForIndex(
+ printing::COMPLETE_PREVIEW_DOCUMENT_INDEX,
+ &data);
+ EXPECT_EQ(NULL, data.get());
+}
+
+// Set and get the individual draft pages.
+TEST_F(PrintPreviewUITest, PrintPreviewDraftPages) {
+#if !defined(GOOGLE_CHROME_BUILD) || defined(OS_CHROMEOS)
+ CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnablePrintPreview);
+#endif
+ ASSERT_TRUE(browser());
+ BrowserList::SetLastActive(browser());
+ ASSERT_TRUE(BrowserList::GetLastActive());
+
+ browser()->NewTab();
+ TabContents* initiator_tab = browser()->GetSelectedTabContents();
+ ASSERT_TRUE(initiator_tab);
+
+ scoped_refptr<printing::PrintPreviewTabController>
+ controller(new printing::PrintPreviewTabController());
+ ASSERT_TRUE(controller);
+
+ TabContents* preview_tab = controller->GetOrCreatePreviewTab(initiator_tab);
+
+ EXPECT_NE(initiator_tab, preview_tab);
+ EXPECT_EQ(2, browser()->tab_count());
+
+ PrintPreviewUI* preview_ui =
+ reinterpret_cast<PrintPreviewUI*>(preview_tab->web_ui());
+ ASSERT_TRUE(preview_ui != NULL);
+
+ scoped_refptr<RefCountedBytes> data;
+ preview_ui->GetPrintPreviewDataForIndex(printing::FIRST_PAGE_INDEX, &data);
+ EXPECT_EQ(NULL, data.get());
+
+ std::vector<unsigned char> preview_data(blob1, blob1 + sizeof(blob1));
+ scoped_refptr<RefCountedBytes> dummy_data(new RefCountedBytes(preview_data));
+
+ preview_ui->SetPrintPreviewDataForIndex(printing::FIRST_PAGE_INDEX,
+ dummy_data.get());
+ preview_ui->GetPrintPreviewDataForIndex(printing::FIRST_PAGE_INDEX, &data);
+ EXPECT_EQ(dummy_data->size(), data->size());
+ EXPECT_EQ(dummy_data.get(), data.get());
+
+ // Set and get the third page data.
+ preview_ui->SetPrintPreviewDataForIndex(printing::FIRST_PAGE_INDEX + 2,
+ dummy_data.get());
+ preview_ui->GetPrintPreviewDataForIndex(printing::FIRST_PAGE_INDEX + 2,
+ &data);
+ EXPECT_EQ(dummy_data->size(), data->size());
+ EXPECT_EQ(dummy_data.get(), data.get());
+
+ // Get the second page data.
+ preview_ui->GetPrintPreviewDataForIndex(printing::FIRST_PAGE_INDEX + 1,
+ &data);
+ EXPECT_EQ(NULL, data.get());
+
+ preview_ui->SetPrintPreviewDataForIndex(printing::FIRST_PAGE_INDEX + 1,
+ dummy_data.get());
+ preview_ui->GetPrintPreviewDataForIndex(printing::FIRST_PAGE_INDEX + 1,
+ &data);
+ EXPECT_EQ(dummy_data->size(), data->size());
+ EXPECT_EQ(dummy_data.get(), data.get());
+
+ // Clear the preview data.
+ preview_ui->ClearAllPreviewData();
+ preview_ui->GetPrintPreviewDataForIndex(printing::FIRST_PAGE_INDEX, &data);
+ EXPECT_EQ(NULL, data.get());
}
diff --git a/chrome/common/print_messages.h b/chrome/common/print_messages.h
index 8773bae..ee5bf44 100644
--- a/chrome/common/print_messages.h
+++ b/chrome/common/print_messages.h
@@ -60,6 +60,11 @@ IPC_STRUCT_BEGIN(PrintMsg_PrintPage_Params)
// The page number is the indicator of the square that should be rendered
// according to the layout specified in PrintMsg_Print_Params.
IPC_STRUCT_MEMBER(int, page_number)
+
+ // The page number in the resulting document. If the user is only printing
+ // page 2, |page_number| above will 1, but |page_slot| will be 0, as it's the
+ // first page in the final document.
+ IPC_STRUCT_MEMBER(int, page_slot)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(PrintMsg_PrintPages_Params)
@@ -96,6 +101,19 @@ IPC_STRUCT_BEGIN(PrintHostMsg_DidPreviewDocument_Params)
IPC_STRUCT_MEMBER(int, preview_request_id)
IPC_STRUCT_END()
+// Parameters to describe a rendered preview page.
+IPC_STRUCT_BEGIN(PrintHostMsg_DidPreviewPage_Params)
+ // A shared memory handle to metafile data for a draft document of the page.
+ IPC_STRUCT_MEMBER(base::SharedMemoryHandle, metafile_data_handle)
+
+ // Size of metafile data.
+ IPC_STRUCT_MEMBER(uint32, data_size)
+
+ // |page_number| is zero-based and can be |printing::INVALID_PAGE_INDEX| if it
+ // is just a check.
+ IPC_STRUCT_MEMBER(int, page_number)
+IPC_STRUCT_END()
+
// Parameters to describe a rendered page.
IPC_STRUCT_BEGIN(PrintHostMsg_DidPrintPage_Params)
// A shared memory handle to the EMF data. This data can be quite large so a
@@ -174,7 +192,11 @@ IPC_MESSAGE_ROUTED0(PrintMsg_PrintForSystemDialog)
IPC_MESSAGE_ROUTED0(PrintMsg_ResetScriptedPrintCount)
// Tells a renderer to continue generating the print preview.
-IPC_MESSAGE_ROUTED0(PrintMsg_ContinuePreview)
+// Use |requested_preview_page_index| to request a specific preview page data.
+// |requested_preview_page_index| is 1-based or |printing::INVALID_PAGE_INDEX|
+// to render the next page.
+IPC_MESSAGE_ROUTED1(PrintMsg_ContinuePreview,
+ int /* requested_preview_page_index */)
// Tells a renderer to abort the print preview and reset all state.
IPC_MESSAGE_ROUTED0(PrintMsg_AbortPreview)
@@ -242,15 +264,14 @@ IPC_MESSAGE_CONTROL1(PrintHostMsg_TempFileForPrintingWritten,
IPC_MESSAGE_ROUTED0(PrintHostMsg_RequestPrintPreview)
// Notify the browser the number of pages in the print preview document.
-IPC_MESSAGE_ROUTED2(PrintHostMsg_DidGetPreviewPageCount,
+IPC_MESSAGE_ROUTED3(PrintHostMsg_DidGetPreviewPageCount,
int /* document cookie */,
- int /* page count */)
+ int /* page count */,
+ bool /* is modifiable */)
-// Notify the browser a print preview page has been rendered. Give the browser
-// a chance to cancel the print preview as needed. Page number is zero-based,
-// and can be -1 if it is just a check.
+// Notify the browser a print preview page has been rendered.
IPC_MESSAGE_ROUTED1(PrintHostMsg_DidPreviewPage,
- int /* page number */)
+ PrintHostMsg_DidPreviewPage_Params /* params */)
// Sends back to the browser the complete rendered document for print preview
// that was requested by a PrintMsg_PrintPreview message. The memory handle in
diff --git a/chrome/renderer/mock_render_thread.cc b/chrome/renderer/mock_render_thread.cc
index ab0654d..aac7156 100644
--- a/chrome/renderer/mock_render_thread.cc
+++ b/chrome/renderer/mock_render_thread.cc
@@ -212,12 +212,14 @@ void MockRenderThread::OnDidPrintPage(
}
void MockRenderThread::OnDidGetPreviewPageCount(int document_cookie,
- int number_pages) {
+ int number_pages,
+ bool is_modifiable) {
print_preview_pages_remaining_ = number_pages;
}
-void MockRenderThread::OnDidPreviewPage(int page_number) {
- if (page_number < 0)
+void MockRenderThread::OnDidPreviewPage(
+ const PrintHostMsg_DidPreviewPage_Params& params) {
+ if (params.page_number < printing::FIRST_PAGE_INDEX)
return;
print_preview_pages_remaining_--;
}
diff --git a/chrome/renderer/mock_render_thread.h b/chrome/renderer/mock_render_thread.h
index 1d2036b..5eb7ad3 100644
--- a/chrome/renderer/mock_render_thread.h
+++ b/chrome/renderer/mock_render_thread.h
@@ -20,6 +20,7 @@ class MessageReplyDeserializer;
struct PrintMsg_Print_Params;
struct PrintMsg_PrintPages_Params;
+struct PrintHostMsg_DidPreviewPage_Params;
struct PrintHostMsg_ScriptedPrint_Params;
// This class is very simple mock of RenderThread. It simulates an IPC channel
@@ -124,8 +125,9 @@ class MockRenderThread : public RenderThreadBase {
void OnDidGetPrintedPagesCount(int cookie, int number_pages);
void OnDidPrintPage(const PrintHostMsg_DidPrintPage_Params& params);
- void OnDidGetPreviewPageCount(int document_cookie, int number_pages);
- void OnDidPreviewPage(int page_number);
+ void OnDidGetPreviewPageCount(int document_cookie, int number_pages,
+ bool is_modifiable);
+ void OnDidPreviewPage(const PrintHostMsg_DidPreviewPage_Params& params);
// For print preview, PrintWebViewHelper will update settings.
void OnUpdatePrintSettings(int document_cookie,
diff --git a/chrome/renderer/print_web_view_helper.cc b/chrome/renderer/print_web_view_helper.cc
index 8430356..028fe2d 100644
--- a/chrome/renderer/print_web_view_helper.cc
+++ b/chrome/renderer/print_web_view_helper.cc
@@ -337,6 +337,8 @@ void PrintWebViewHelper::OnPrintPreview(const DictionaryValue& settings) {
Send(new PrintHostMsg_PagesReadyForPreview(routing_id(), preview_params));
return;
}
+ // Always clear |old_print_pages_params_| before rendering the pages.
+ old_print_pages_params_.reset();
// PDF printer device supports alpha blending.
print_pages_params_->params.supports_alpha_blend = true;
@@ -350,20 +352,29 @@ bool PrintWebViewHelper::CreatePreviewDocument() {
if (!print_preview_context_.CreatePreviewDocument(&print_params, pages))
return false;
int page_count = print_preview_context_.total_page_count();
+ bool is_modifiable = print_preview_context_.IsModifiable();
int document_cookie = print_pages_params_->params.document_cookie;
Send(new PrintHostMsg_DidGetPreviewPageCount(routing_id(), document_cookie,
- page_count));
- PreviewPageRendered(-1);
+ page_count, is_modifiable));
+ PreviewPageRendered(printing::INVALID_PAGE_INDEX, NULL);
return true;
}
-void PrintWebViewHelper::OnContinuePreview() {
+void PrintWebViewHelper::OnContinuePreview(int requested_preview_page_index) {
// Spurious message. We already finished/cancelled/aborted the print preview.
if (!print_preview_context_.IsBusy())
return;
+ int page_number;
+#if defined(USE_SKIA)
+ if (requested_preview_page_index >= printing::FIRST_PAGE_INDEX) {
+ page_number = requested_preview_page_index;
+ } else
+#endif
+ {
+ page_number = print_preview_context_.GetNextPageNumber();
+ }
- int page_number = print_preview_context_.GetNextPageNumber();
- if (page_number >= 0) {
+ if (page_number >= printing::FIRST_PAGE_INDEX) {
// Continue generating the print preview.
RenderPreviewPage(page_number);
return;
@@ -576,6 +587,7 @@ bool PrintWebViewHelper::PrintPages(const PrintMsg_PrintPages_Params& params,
if (params.pages.empty()) {
for (int i = 0; i < page_count; ++i) {
page_params.page_number = i;
+ page_params.page_slot = i;
PrintPageInternal(page_params, canvas_size, frame);
}
} else {
@@ -583,6 +595,7 @@ bool PrintWebViewHelper::PrintPages(const PrintMsg_PrintPages_Params& params,
if (params.pages[i] >= page_count)
break;
page_params.page_number = params.pages[i];
+ page_params.page_slot = i;
PrintPageInternal(page_params, canvas_size, frame);
}
}
@@ -901,8 +914,33 @@ void PrintWebViewHelper::RequestPrintPreview() {
Send(new PrintHostMsg_RequestPrintPreview(routing_id()));
}
-void PrintWebViewHelper::PreviewPageRendered(int page_number) {
- Send(new PrintHostMsg_DidPreviewPage(routing_id(), page_number));
+void PrintWebViewHelper::PreviewPageRendered(int page_number,
+ printing::Metafile* metafile) {
+#if !defined(OS_WIN)
+ if ((page_number == printing::INVALID_PAGE_INDEX && metafile) ||
+ (page_number >= printing::FIRST_PAGE_INDEX && !metafile &&
+ print_preview_context_.IsModifiable())) {
+ NOTREACHED();
+ DidFinishPrinting(FAIL_PREVIEW);
+ return;
+ }
+#endif
+
+ uint32 buf_size = 0;
+ PrintHostMsg_DidPreviewPage_Params preview_page_params;
+ // Get the size of the resulting metafile.
+ if (metafile) {
+ buf_size = metafile->GetDataSize();
+ DCHECK_GT(buf_size, 0u);
+ if (!CopyMetafileDataToSharedMem(
+ metafile, &(preview_page_params.metafile_data_handle))) {
+ DidFinishPrinting(FAIL_PREVIEW);
+ return;
+ }
+ }
+ preview_page_params.data_size = buf_size;
+ preview_page_params.page_number = page_number;
+ Send(new PrintHostMsg_DidPreviewPage(routing_id(), preview_page_params));
}
PrintWebViewHelper::PrintPreviewContext::PrintPreviewContext()
@@ -966,15 +1004,20 @@ bool PrintWebViewHelper::PrintPreviewContext::CreatePreviewDocument(
current_page_number_ = 0;
if (pages.empty()) {
actual_page_count_ = total_page_count_;
- rendered_pages_ = std::vector<bool>(total_page_count_, false);
+ rendered_pages_ = std::vector<PreviewPageInfo>(total_page_count_,
+ std::make_pair(false, -1));
} else {
actual_page_count_ = pages.size();
- rendered_pages_ = std::vector<bool>(total_page_count_, true);
+ rendered_pages_ = std::vector<PreviewPageInfo>(total_page_count_,
+ std::make_pair(true, -1));
for (int i = 0; i < actual_page_count_; ++i) {
int page_number = pages[i];
- if (page_number < 0 || page_number >= total_page_count_)
+ if (page_number < printing::FIRST_PAGE_INDEX ||
+ page_number >= total_page_count_) {
return false;
- rendered_pages_[page_number] = false;
+ }
+ rendered_pages_[page_number].first = false;
+ rendered_pages_[page_number].second = i;
}
}
@@ -1029,14 +1072,15 @@ void PrintWebViewHelper::PrintPreviewContext::Abort() {
int PrintWebViewHelper::PrintPreviewContext::GetNextPageNumber() {
DCHECK_EQ(RENDERING, state_);
- while (current_page_number_ < total_page_count_ &&
- rendered_pages_[current_page_number_]) {
- ++current_page_number_;
+ for (int i = 0; i < total_page_count_; i++) {
+ if (!rendered_pages_[current_page_number_].first)
+ break;
+ current_page_number_ = (current_page_number_ + 1) % total_page_count_;
}
- if (current_page_number_ == total_page_count_)
- return -1;
- rendered_pages_[current_page_number_] = true;
- return current_page_number_++;
+ if (rendered_pages_[current_page_number_].first)
+ return printing::INVALID_PAGE_INDEX;
+ rendered_pages_[current_page_number_].first = true;
+ return current_page_number_;
}
bool PrintWebViewHelper::PrintPreviewContext::IsReadyToRender() const {
@@ -1048,12 +1092,21 @@ bool PrintWebViewHelper::PrintPreviewContext::IsBusy() const {
}
bool PrintWebViewHelper::PrintPreviewContext::IsModifiable() const {
+ // TODO(vandebo) I think this should only return false if the content is a
+ // PDF, just because we are printing a particular node does not mean it's
+ // a PDF (right?), we should check the mime type of the node.
if (node())
return false;
std::string mime(frame()->dataSource()->response().mimeType().utf8());
return mime != "application/pdf";
}
+int PrintWebViewHelper::PrintPreviewContext::GetPageSlotForPage(
+ int page_number) const {
+ int page_slot = rendered_pages_[page_number].second;
+ return page_slot == -1 ? page_number : page_slot;
+}
+
WebKit::WebFrame* PrintWebViewHelper::PrintPreviewContext::frame() const {
return frame_;
}
diff --git a/chrome/renderer/print_web_view_helper.h b/chrome/renderer/print_web_view_helper.h
index fa555fe..14fc465 100644
--- a/chrome/renderer/print_web_view_helper.h
+++ b/chrome/renderer/print_web_view_helper.h
@@ -6,6 +6,7 @@
#define CHROME_RENDERER_PRINT_WEB_VIEW_HELPER_H_
#pragma once
+#include <utility>
#include <vector>
#include "base/memory/scoped_ptr.h"
@@ -134,8 +135,10 @@ class PrintWebViewHelper : public RenderViewObserver,
// Initialize the print preview document.
bool CreatePreviewDocument();
- // Continue generating the print preview.
- void OnContinuePreview();
+ // Continue generating the print preview. |requested_preview_page_index|
+ // specifies the browser requested preview page index. It is 1-based or
+ // |printing::INVALID_PAGE_INDEX| to continue with next page.
+ void OnContinuePreview(int requested_preview_page_index);
// Renders a print preview page. |page_number| is 0-based.
void RenderPreviewPage(int page_number);
// Finalize the print preview document.
@@ -225,11 +228,12 @@ class PrintWebViewHelper : public RenderViewObserver,
// Platform specific helper function for rendering page(s) to |metafile|.
#if defined(OS_WIN)
void RenderPage(const PrintMsg_Print_Params& params, float* scale_factor,
- int page_number, bool is_preview, WebKit::WebFrame* frame,
+ int page_number, int page_slot, bool is_preview,
+ WebKit::WebFrame* frame,
scoped_ptr<printing::Metafile>* metafile);
#elif defined(OS_MACOSX)
void RenderPage(const gfx::Size& page_size, const gfx::Rect& content_area,
- const float& scale_factor, int page_number,
+ const float& scale_factor, int page_number, int page_slot,
WebKit::WebFrame* frame, printing::Metafile* metafile);
#elif defined(OS_POSIX)
bool RenderPages(const PrintMsg_PrintPages_Params& params,
@@ -281,8 +285,9 @@ class PrintWebViewHelper : public RenderViewObserver,
void RequestPrintPreview();
// Notify the browser a print preview page has been rendered.
- // |page_number| is 0-based.
- void PreviewPageRendered(int page_number);
+ // |page_number| is 0-based or |printing::INVALID_PAGE_INDEX| to check
+ // for pending preview requests.
+ void PreviewPageRendered(int page_number, printing::Metafile* metafile);
WebKit::WebView* print_web_view_;
@@ -336,6 +341,11 @@ class PrintWebViewHelper : public RenderViewObserver,
bool IsBusy() const;
bool IsModifiable() const;
+ // Return the page slot in the final document for |page_number|. i.e. if
+ // the user selected just page 3, the page slot would be 0, since it is
+ // the first page in the resulting document.
+ int GetPageSlotForPage(int page_number) const;
+
// Getters
WebKit::WebFrame* frame() const;
WebKit::WebNode* node() const;
@@ -372,8 +382,10 @@ class PrintWebViewHelper : public RenderViewObserver,
// The current page to render.
int current_page_number_;
- // Array to keep track of which pages have been printed.
- std::vector<bool> rendered_pages_;
+ // |rendered_pages_| tracks which pages need to be printed as well as
+ // the page slot it should be printed in. See GetPageSlotForPage.
+ typedef std::pair<bool, int> PreviewPageInfo;
+ std::vector<PreviewPageInfo> rendered_pages_;
base::TimeDelta document_render_time_;
base::TimeTicks begin_time_;
diff --git a/chrome/renderer/print_web_view_helper_browsertest.cc b/chrome/renderer/print_web_view_helper_browsertest.cc
index 86aec37..06246d4 100644
--- a/chrome/renderer/print_web_view_helper_browsertest.cc
+++ b/chrome/renderer/print_web_view_helper_browsertest.cc
@@ -354,8 +354,10 @@ TEST_F(PrintWebViewHelperPreviewTest, OnPrintPreview) {
// Need to finish simulating print preview.
// Generate the page and finalize it.
- PrintWebViewHelper::Get(view_)->OnContinuePreview();
- PrintWebViewHelper::Get(view_)->OnContinuePreview();
+ PrintWebViewHelper::Get(view_)->OnContinuePreview(
+ printing::INVALID_PAGE_INDEX);
+ PrintWebViewHelper::Get(view_)->OnContinuePreview(
+ printing::INVALID_PAGE_INDEX);
EXPECT_EQ(0, render_thread_.print_preview_pages_remaining());
VerifyPrintPreviewFailed(false);
diff --git a/chrome/renderer/print_web_view_helper_linux.cc b/chrome/renderer/print_web_view_helper_linux.cc
index 6620693..27667d6 100644
--- a/chrome/renderer/print_web_view_helper_linux.cc
+++ b/chrome/renderer/print_web_view_helper_linux.cc
@@ -29,15 +29,23 @@ void PrintWebViewHelper::RenderPreviewPage(int page_number) {
PrintMsg_PrintPage_Params page_params;
page_params.params = print_preview_context_.print_params();
page_params.page_number = page_number;
+ page_params.page_slot =
+ print_preview_context_.GetPageSlotForPage(page_number);
base::TimeTicks begin_time = base::TimeTicks::Now();
PrintPageInternal(page_params,
print_preview_context_.GetPrintCanvasSize(),
print_preview_context_.frame(),
print_preview_context_.metafile());
+
print_preview_context_.RenderedPreviewPage(
base::TimeTicks::Now() - begin_time);
- PreviewPageRendered(page_number);
+ printing::Metafile* page_metafile = NULL;
+ if (print_preview_context_.IsModifiable()) {
+ page_metafile = reinterpret_cast<printing::PreviewMetafile*>(
+ print_preview_context_.metafile())->GetMetafileForCurrentPage();
+ }
+ PreviewPageRendered(page_number, page_metafile);
}
bool PrintWebViewHelper::PrintPages(const PrintMsg_PrintPages_Params& params,
@@ -154,11 +162,13 @@ bool PrintWebViewHelper::RenderPages(const PrintMsg_PrintPages_Params& params,
if (params.pages.empty()) {
for (int i = 0; i < *page_count; ++i) {
page_params.page_number = i;
+ page_params.page_slot = i;
PrintPageInternal(page_params, canvas_size, frame, metafile);
}
} else {
for (size_t i = 0; i < params.pages.size(); ++i) {
page_params.page_number = params.pages[i];
+ page_params.page_slot = i;
PrintPageInternal(page_params, canvas_size, frame, metafile);
}
}
@@ -192,7 +202,7 @@ void PrintWebViewHelper::PrintPageInternal(
page_layout_in_points.content_height);
SkDevice* device = metafile->StartPageForVectorCanvas(
- params.page_number, page_size, content_area, 1.0f);
+ params.page_slot, page_size, content_area, 1.0f);
if (!device)
return;
diff --git a/chrome/renderer/print_web_view_helper_mac.mm b/chrome/renderer/print_web_view_helper_mac.mm
index f5ded39..3ceeb5d 100644
--- a/chrome/renderer/print_web_view_helper_mac.mm
+++ b/chrome/renderer/print_web_view_helper_mac.mm
@@ -32,11 +32,12 @@ void PrintWebViewHelper::PrintPageInternal(
float scale_factor = frame->getPrintPageShrink(params.page_number);
int page_number = params.page_number;
+ int page_slot = params.page_slot;
// Render page for printing.
gfx::Rect content_area(params.params.printable_size);
RenderPage(params.params.printable_size, content_area, scale_factor,
- page_number, frame, &metafile);
+ page_number, page_slot, frame, &metafile);
metafile.FinishDocument();
PrintHostMsg_DidPrintPage_Params page_params;
@@ -66,23 +67,60 @@ void PrintWebViewHelper::RenderPreviewPage(int page_number) {
printParams.printable_size.width(),
printParams.printable_size.height());
+ printing::Metafile* initial_render_metafile =
+ print_preview_context_.metafile();
+#if !defined(USE_SKIA)
+ if (print_preview_context_.IsModifiable()) {
+ initial_render_metafile = new printing::PreviewMetafile();
+ if (!initial_render_metafile->Init()) {
+ DidFinishPrinting(FAIL_PREVIEW);
+ return;
+ }
+ }
+#endif
+
base::TimeTicks begin_time = base::TimeTicks::Now();
RenderPage(printParams.page_size, content_area, scale_factor, page_number,
- print_preview_context_.frame(), print_preview_context_.metafile());
+ print_preview_context_.GetPageSlotForPage(page_number),
+ print_preview_context_.frame(), initial_render_metafile);
print_preview_context_.RenderedPreviewPage(
base::TimeTicks::Now() - begin_time);
- PreviewPageRendered(page_number);
+
+ printing::Metafile* draft_metafile = NULL;
+ if (print_preview_context_.IsModifiable()) {
+#if defined(USE_SKIA)
+ draft_metafile = reinterpret_cast<printing::PreviewMetafile*>(
+ print_preview_context_.metafile())->GetMetafileForCurrentPage();
+#else
+ draft_metafile = initial_render_metafile;
+ draft_metafile->FinishDocument();
+
+ // With CG, we rendered into a new metafile so we could get it as a draft
+ // document. Now we need to add it to complete document.
+ draft_metafile->RenderPage(1,
+ print_preview_context_.metafile()->context(),
+ CGRectMake(content_area.x(), content_area.y(),
+ content_area.width(),
+ content_area.height()),
+ false /*shrunk_to_fit*/,
+ false /*stretch_to_fit*/,
+ true /*center_horizontally*/,
+ true /*center_vertically*/);
+#endif
+ }
+
+ PreviewPageRendered(page_number, draft_metafile);
}
void PrintWebViewHelper::RenderPage(
const gfx::Size& page_size, const gfx::Rect& content_area,
- const float& scale_factor, int page_number, WebFrame* frame,
+ const float& scale_factor, int page_number, int page_slot, WebFrame* frame,
printing::Metafile* metafile) {
{
#if defined(USE_SKIA)
SkDevice* device = metafile->StartPageForVectorCanvas(
- page_number, page_size, content_area, scale_factor);
+ page_slot, page_size, content_area, scale_factor);
if (!device)
return;
diff --git a/chrome/renderer/print_web_view_helper_win.cc b/chrome/renderer/print_web_view_helper_win.cc
index d627fff..7f74acf 100644
--- a/chrome/renderer/print_web_view_helper_win.cc
+++ b/chrome/renderer/print_web_view_helper_win.cc
@@ -84,13 +84,14 @@ void PrintWebViewHelper::PrintPageInternal(
skia::InitializeDC(metafile->context());
int page_number = params.page_number;
+ int page_slot = params.page_slot;
// Calculate the dpi adjustment.
float scale_factor = static_cast<float>(params.params.desired_dpi /
params.params.dpi);
// Render page for printing.
- RenderPage(params.params, &scale_factor, page_number, false, frame,
+ RenderPage(params.params, &scale_factor, page_number, page_slot, false, frame,
&metafile);
// Close the device context to retrieve the compiled metafile.
@@ -128,23 +129,28 @@ void PrintWebViewHelper::RenderPreviewPage(int page_number) {
// Calculate the dpi adjustment.
float scale_factor = static_cast<float>(print_params.desired_dpi /
print_params.dpi);
- // Needed for RenderPage() below.
- // Not taking ownership with intent to reset().
+
+ // |metafile| is needed for RenderPage() below. |metafile| will not take the
+ // ownership of |print_preview_context_| metafile.
scoped_ptr<Metafile> metafile(print_preview_context_.metafile());
base::TimeTicks begin_time = base::TimeTicks::Now();
- RenderPage(print_params, &scale_factor, page_number, true,
+ RenderPage(print_params, &scale_factor, page_number,
+ print_preview_context_.GetPageSlotForPage(page_number), true,
print_preview_context_.frame(), &metafile);
- // Release since |print_preview_context_| is the real owner.
- metafile.release();
+
print_preview_context_.RenderedPreviewPage(
base::TimeTicks::Now() - begin_time);
- PreviewPageRendered(page_number);
+
+ // Release since |print_preview_context_| is the real owner.
+ metafile.release();
+ PreviewPageRendered(page_number, NULL);
}
void PrintWebViewHelper::RenderPage(
const PrintMsg_Print_Params& params, float* scale_factor, int page_number,
- bool is_preview, WebFrame* frame, scoped_ptr<Metafile>* metafile) {
+ int page_slot, bool is_preview, WebFrame* frame,
+ scoped_ptr<Metafile>* metafile) {
PageSizeMargins page_layout_in_points;
GetPageSizeAndMarginsInPoints(frame, page_number, params,
&page_layout_in_points);
@@ -173,7 +179,7 @@ void PrintWebViewHelper::RenderPage(
static_cast<int>(page_layout_in_points.content_width),
static_cast<int>(page_layout_in_points.content_height));
SkDevice* device = (*metafile)->StartPageForVectorCanvas(
- page_number, page_size, content_area,
+ page_slot, page_size, content_area,
frame->getPrintPageShrink(page_number));
DCHECK(device);
// The printPage method may take a reference to the canvas we pass down, so it
diff --git a/printing/print_job_constants.cc b/printing/print_job_constants.cc
index f0e5e77..0c50b44 100644
--- a/printing/print_job_constants.cc
+++ b/printing/print_job_constants.cc
@@ -45,4 +45,10 @@ const char kSettingPrinterName[] = "printerName";
// Print to PDF option: true if selected, false if not.
const char kSettingPrintToPDF[] = "printToPDF";
+// Indices used to represent first page, invalid page and complete
+// preview document.
+const int FIRST_PAGE_INDEX = 0;
+const int COMPLETE_PREVIEW_DOCUMENT_INDEX = -1;
+const int INVALID_PAGE_INDEX = -2;
+
} // namespace printing
diff --git a/printing/print_job_constants.h b/printing/print_job_constants.h
index e877a01..8c6103b 100644
--- a/printing/print_job_constants.h
+++ b/printing/print_job_constants.h
@@ -21,6 +21,10 @@ extern const char kSettingPageRangeTo[];
extern const char kSettingPrinterName[];
extern const char kSettingPrintToPDF[];
+extern const int FIRST_PAGE_INDEX;
+extern const int COMPLETE_PREVIEW_DOCUMENT_INDEX;
+extern const int INVALID_PAGE_INDEX;
+
// Print job duplex mode values.
enum DuplexMode {
SIMPLEX,