summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/browser.cc4
-rw-r--r--chrome/browser/browser_process_impl.cc4
-rw-r--r--chrome/browser/printing/print_job.cc7
-rw-r--r--chrome/browser/printing/print_job_worker.cc50
-rw-r--r--chrome/browser/printing/print_job_worker.h14
-rw-r--r--chrome/browser/printing/print_view_manager.cc8
-rw-r--r--chrome/browser/printing/printer_query.cc6
-rw-r--r--chrome/browser/printing/printer_query.h3
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc38
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h8
-rw-r--r--chrome/browser/tab_contents/tab_contents.h4
-rwxr-xr-xchrome/chrome.gyp11
-rw-r--r--chrome/common/render_messages_internal.h12
-rw-r--r--chrome/common/temp_scaffolding_stubs.h2
-rw-r--r--chrome/renderer/mock_render_thread.cc25
-rw-r--r--chrome/renderer/mock_render_thread.h7
-rw-r--r--chrome/renderer/print_web_view_helper_mac.cc28
-rw-r--r--chrome/renderer/print_web_view_helper_mac.mm238
-rw-r--r--chrome/renderer/render_view_unittest.cc4
19 files changed, 406 insertions, 67 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index f1ece51..cb8feee 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -960,11 +960,7 @@ void Browser::ClosePopups() {
void Browser::Print() {
UserMetrics::RecordAction(L"PrintPreview", profile_);
-#if defined(OS_WIN) || defined(OS_LINUX)
GetSelectedTabContents()->PrintPreview();
-#else
- NOTIMPLEMENTED();
-#endif
}
void Browser::ToggleEncodingAutoDetect() {
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index fca8950..1102d4a 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -38,7 +38,9 @@
#include "chrome/browser/automation/automation_provider_list.h"
#include "chrome/browser/printing/print_job_manager.h"
#include "views/focus/view_storage.h"
-#elif defined(OS_POSIX)
+#elif defined(OS_MACOSX)
+#include "chrome/browser/printing/print_job_manager.h"
+#elif defined(OS_LINUX)
// TODO(port): Remove the temporary scaffolding as we port the above headers.
#include "chrome/common/temp_scaffolding_stubs.h"
#endif
diff --git a/chrome/browser/printing/print_job.cc b/chrome/browser/printing/print_job.cc
index d65b7bf..8a1a5e2 100644
--- a/chrome/browser/printing/print_job.cc
+++ b/chrome/browser/printing/print_job.cc
@@ -21,8 +21,8 @@ namespace printing {
PrintJob::PrintJob()
: ui_message_loop_(MessageLoop::current()),
- worker_(),
source_(NULL),
+ worker_(),
settings_(),
is_job_pending_(false),
is_print_dialog_box_shown_(false),
@@ -284,6 +284,10 @@ void PrintJob::OnDocumentDone() {
void PrintJob::ControlledWorkerShutdown() {
DCHECK_EQ(ui_message_loop_, MessageLoop::current());
+
+ // The deadlock this code works around is specific to window messaging on
+ // Windows, so we aren't likely to need it on any other platforms.
+#if defined(OS_WIN)
// We could easily get into a deadlock case if worker_->Stop() is used; the
// printer driver created a window as a child of the browser window. By
// canceling the job, the printer driver initiated dialog box is destroyed,
@@ -323,6 +327,7 @@ void PrintJob::ControlledWorkerShutdown() {
break;
}
}
+#endif
// Now make sure the thread object is cleaned up.
worker_->Stop();
diff --git a/chrome/browser/printing/print_job_worker.cc b/chrome/browser/printing/print_job_worker.cc
index 375c2407..27a553d 100644
--- a/chrome/browser/printing/print_job_worker.cc
+++ b/chrome/browser/printing/print_job_worker.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/printing/print_job_worker.h"
#include "base/message_loop.h"
+#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/printing/print_job.h"
#include "chrome/common/notification_service.h"
#include "printing/printed_document.h"
@@ -64,7 +65,7 @@ void PrintJobWorker::SetNewOwner(PrintJobWorkerOwner* new_owner) {
}
void PrintJobWorker::GetSettings(bool ask_user_for_settings,
- HWND parent_window,
+ gfx::NativeWindow parent_window,
int document_page_count,
bool has_selection) {
DCHECK_EQ(message_loop(), MessageLoop::current());
@@ -74,15 +75,24 @@ void PrintJobWorker::GetSettings(bool ask_user_for_settings,
// destroyed by a task.
MessageLoop::current()->SetNestableTasksAllowed(true);
- PrintingContext::Result result;
if (ask_user_for_settings) {
- result = printing_context_.AskUserForSettings(parent_window,
- document_page_count,
- has_selection);
+#if defined(OS_MACOSX)
+ ChromeThread::GetMessageLoop(ChromeThread::UI)->PostTask(
+ FROM_HERE, NewRunnableMethod(this, &PrintJobWorker::GetSettingsWithUI,
+ parent_window, document_page_count,
+ has_selection));
+#else
+ PrintingContext::Result result = printing_context_.AskUserForSettings(
+ parent_window, document_page_count, has_selection);
+ GetSettingsDone(result);
+#endif
} else {
- result = printing_context_.UseDefaultSettings();
+ PrintingContext::Result result = printing_context_.UseDefaultSettings();
+ GetSettingsDone(result);
}
+}
+void PrintJobWorker::GetSettingsDone(PrintingContext::Result result) {
// Most PrintingContext functions may start a message loop and process
// message recursively, so disable recursive task processing.
MessageLoop::current()->SetNestableTasksAllowed(false);
@@ -97,13 +107,29 @@ void PrintJobWorker::GetSettings(bool ask_user_for_settings,
result));
}
+#if defined(OS_MACOSX)
+void PrintJobWorker::GetSettingsWithUI(gfx::NativeWindow parent_window,
+ int document_page_count,
+ bool has_selection) {
+ DCHECK_EQ(ChromeThread::GetMessageLoop(ChromeThread::UI),
+ MessageLoop::current());
+
+ PrintingContext::Result result = printing_context_.AskUserForSettings(
+ parent_window, document_page_count, has_selection);
+ message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &PrintJobWorker::GetSettingsDone, result));
+}
+#endif
+
void PrintJobWorker::StartPrinting(PrintedDocument* new_document) {
DCHECK_EQ(message_loop(), MessageLoop::current());
DCHECK_EQ(page_number_, PageNumber::npos());
DCHECK_EQ(document_, new_document);
DCHECK(document_.get());
DCHECK(new_document->settings().Equals(printing_context_.settings()));
+#if !defined(OS_MACOSX)
DCHECK(printing_context_.context());
+#endif
if (!document_.get() || page_number_ != PageNumber::npos() ||
document_ != new_document) {
return;
@@ -130,7 +156,9 @@ void PrintJobWorker::OnDocumentChanged(PrintedDocument* new_document) {
DCHECK_EQ(page_number_, PageNumber::npos());
DCHECK(!new_document ||
new_document->settings().Equals(printing_context_.settings()));
+#if !defined(OS_MACOSX)
DCHECK(printing_context_.context());
+#endif
if (page_number_ != PageNumber::npos())
return;
@@ -144,9 +172,11 @@ void PrintJobWorker::OnNewPage() {
}
// message_loop() could return NULL when the print job is cancelled.
DCHECK_EQ(message_loop(), MessageLoop::current());
+#if !defined(OS_MACOSX)
DCHECK(printing_context_.context());
if (!printing_context_.context())
return;
+#endif
if (page_number_ == PageNumber::npos()) {
// Find first page to print.
@@ -199,7 +229,9 @@ void PrintJobWorker::OnDocumentDone() {
DCHECK_EQ(message_loop(), MessageLoop::current());
DCHECK_EQ(page_number_, PageNumber::npos());
DCHECK(document_.get());
+#if !defined(OS_MACOSX)
DCHECK(printing_context_.context());
+#endif
if (printing_context_.DocumentDone() != PrintingContext::OK) {
OnFailure();
@@ -221,7 +253,9 @@ void PrintJobWorker::OnDocumentDone() {
void PrintJobWorker::SpoolPage(PrintedPage& page) {
DCHECK_EQ(message_loop(), MessageLoop::current());
DCHECK_NE(page_number_, PageNumber::npos());
+#if !defined(OS_MACOSX)
DCHECK(printing_context_.context());
+#endif
// Signal everyone that the page is about to be printed.
NotificationTask* task = new NotificationTask();
task->Init(owner_,
@@ -236,6 +270,10 @@ void PrintJobWorker::SpoolPage(PrintedPage& page) {
return;
}
+#if defined(OS_MACOSX)
+ // Context is only valid between NewPage and PageDone, so we only check here.
+ DCHECK(printing_context_.context());
+#endif
// Actual printing.
document_->RenderPrintedPage(page, printing_context_.context());
diff --git a/chrome/browser/printing/print_job_worker.h b/chrome/browser/printing/print_job_worker.h
index fce8912..56e7893 100644
--- a/chrome/browser/printing/print_job_worker.h
+++ b/chrome/browser/printing/print_job_worker.h
@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_PRINTING_PRINT_JOB_WORKER_H__
#define CHROME_BROWSER_PRINTING_PRINT_JOB_WORKER_H__
+#include "app/gfx/native_widget_types.h"
#include "base/task.h"
#include "base/thread.h"
#include "printing/page_number.h"
@@ -33,7 +34,7 @@ class PrintJobWorker : public base::Thread {
// Initializes the print settings. If |ask_user_for_settings| is true, a
// Print... dialog box will be shown to ask the user his preference.
void GetSettings(bool ask_user_for_settings,
- HWND parent_window,
+ gfx::NativeWindow parent_window,
int document_page_count,
bool has_selection);
@@ -78,6 +79,17 @@ class PrintJobWorker : public base::Thread {
// context.
void OnFailure();
+#if defined(OS_MACOSX)
+ // Asks the user for print settings. Must be called on the UI thread.
+ // Mac-only since Windows can display UI from non-main threads.
+ void GetSettingsWithUI(gfx::NativeWindow parent_window,
+ int document_page_count,
+ bool has_selection);
+#endif
+
+ // Reports settings back to owner_.
+ void GetSettingsDone(PrintingContext::Result result);
+
// Information about the printer setting.
PrintingContext printing_context_;
diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc
index 22f3abe..4f6e73a 100644
--- a/chrome/browser/printing/print_view_manager.cc
+++ b/chrome/browser/printing/print_view_manager.cc
@@ -24,10 +24,10 @@ using base::TimeDelta;
namespace printing {
PrintViewManager::PrintViewManager(TabContents& owner)
- : owner_(owner),
- waiting_to_print_(false),
+ : waiting_to_print_(false),
printing_succeeded_(false),
- inside_inner_message_loop_(false) {
+ inside_inner_message_loop_(false),
+ owner_(owner) {
}
PrintViewManager::~PrintViewManager() {
@@ -101,6 +101,7 @@ void PrintViewManager::DidPrintPage(
return;
}
+#if defined(OS_WIN)
// http://msdn2.microsoft.com/en-us/library/ms535522.aspx
// Windows 2000/XP: When a page in a spooled file exceeds approximately 350
// MB, it can fail to print and not send an error message.
@@ -110,6 +111,7 @@ void PrintViewManager::DidPrintPage(
owner_.Stop();
return;
}
+#endif
base::SharedMemory shared_buf(params.metafile_data_handle, true);
if (!shared_buf.Map(params.data_size)) {
diff --git a/chrome/browser/printing/printer_query.cc b/chrome/browser/printing/printer_query.cc
index 3bcee7a..4fdadbe 100644
--- a/chrome/browser/printing/printer_query.cc
+++ b/chrome/browser/printing/printer_query.cc
@@ -17,8 +17,8 @@ PrinterQuery::PrinterQuery()
: ui_message_loop_(MessageLoop::current()),
worker_(new PrintJobWorker(this)),
is_print_dialog_box_shown_(false),
- last_status_(PrintingContext::FAILED),
- cookie_(PrintSettings::NewCookie()) {
+ cookie_(PrintSettings::NewCookie()),
+ last_status_(PrintingContext::FAILED) {
}
PrinterQuery::~PrinterQuery() {
@@ -62,7 +62,7 @@ PrintJobWorker* PrinterQuery::DetachWorker(PrintJobWorkerOwner* new_owner) {
}
void PrinterQuery::GetSettings(GetSettingsAskParam ask_user_for_settings,
- HWND parent_window,
+ gfx::NativeWindow parent_window,
int expected_page_count,
bool has_selection,
CancelableTask* callback) {
diff --git a/chrome/browser/printing/printer_query.h b/chrome/browser/printing/printer_query.h
index b0502c8..b4826ec 100644
--- a/chrome/browser/printing/printer_query.h
+++ b/chrome/browser/printing/printer_query.h
@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_PRINTING_PRINTER_QUERY_H_
#define CHROME_BROWSER_PRINTING_PRINTER_QUERY_H_
+#include "app/gfx/native_widget_types.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/printing/print_job_worker_owner.h"
@@ -47,7 +48,7 @@ class PrinterQuery : public PrintJobWorkerOwner {
// owner of the print setting dialog box. It is unused when
// |ask_for_user_settings| is DEFAULTS.
void GetSettings(GetSettingsAskParam ask_user_for_settings,
- HWND parent_window,
+ gfx::NativeWindow parent_window,
int expected_page_count,
bool has_selection,
CancelableTask* callback);
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index 5912750..cecdeaf 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -55,10 +55,10 @@
#include "webkit/glue/webkit_glue.h"
#include "webkit/glue/webplugin.h"
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_MACOSX)
#include "chrome/browser/printing/print_job_manager.h"
#include "chrome/browser/printing/printer_query.h"
-#elif defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_FREEBSD)
+#elif defined(OS_LINUX) || defined(OS_FREEBSD)
// TODO(port) remove this.
#include "chrome/common/temp_scaffolding_stubs.h"
#endif
@@ -118,7 +118,7 @@ class WriteClipboardTask : public Task {
void RenderParamsFromPrintSettings(const printing::PrintSettings& settings,
ViewMsg_Print_Params* params) {
DCHECK(params);
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_MACOSX)
params->printable_size.SetSize(
settings.page_setup_pixels().content_area().width(),
settings.page_setup_pixels().content_area().height());
@@ -358,11 +358,15 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_TempFileForPrintingWritten,
OnTempFileForPrintingWritten)
#endif
+#if defined(OS_MACOSX)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_AllocatePDFTransport,
+ OnAllocatePDFTransport)
+#endif
IPC_MESSAGE_HANDLER(ViewHostMsg_ResourceTypeStats, OnResourceTypeStats)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ResolveProxy, OnResolveProxy)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetDefaultPrintSettings,
OnGetDefaultPrintSettings)
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_MACOSX)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_ScriptedPrint,
OnScriptedPrint)
#endif
@@ -738,6 +742,21 @@ void ResourceMessageFilter::OnDuplicateSection(
}
#endif
+#if defined(OS_MACOSX)
+void ResourceMessageFilter::OnAllocatePDFTransport(
+ size_t buffer_size,
+ base::SharedMemoryHandle* handle) {
+ base::SharedMemory shared_buf;
+ shared_buf.Create(L"", false, false, buffer_size);
+ if (!shared_buf.Map(buffer_size)) {
+ *handle = base::SharedMemory::NULLHandle();
+ NOTREACHED() << "Cannot map PDF transport buffer";
+ return;
+ }
+ shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), handle);
+}
+#endif
+
void ResourceMessageFilter::OnResourceTypeStats(
const WebCache::ResourceTypeStats& stats) {
HISTOGRAM_COUNTS("WebCoreCache.ImagesSizeKB",
@@ -820,12 +839,17 @@ void ResourceMessageFilter::OnGetDefaultPrintSettingsReply(
}
}
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_MACOSX)
void ResourceMessageFilter::OnScriptedPrint(
const ViewHostMsg_ScriptedPrint_Params& params,
IPC::Message* reply_msg) {
+#if defined(OS_WIN)
HWND host_window = gfx::NativeViewFromId(params.host_window_id);
+#elif defined(OS_MACOSX)
+ gfx::NativeWindow host_window = NULL;
+ // TODO: Get an actual window ref here, to allow a sheet-based print dialog.
+#endif
scoped_refptr<printing::PrinterQuery> printer_query;
print_job_manager_->PopPrinterQuery(params.cookie, &printer_query);
@@ -839,6 +863,7 @@ void ResourceMessageFilter::OnScriptedPrint(
printer_query,
params.routing_id,
reply_msg);
+#if defined(OS_WIN)
// Shows the Print... dialog box. This is asynchronous, only the IPC message
// sender will hang until the Print dialog is dismissed.
if (!host_window || !IsWindow(host_window)) {
@@ -848,6 +873,7 @@ void ResourceMessageFilter::OnScriptedPrint(
host_window = GetAncestor(host_window, GA_ROOTOWNER);
}
DCHECK(host_window);
+#endif
printer_query->GetSettings(printing::PrinterQuery::ASK_USER,
host_window,
@@ -879,7 +905,7 @@ void ResourceMessageFilter::OnScriptedPrintReply(
}
}
-#endif // OS_WIN
+#endif // OS_WIN || OS_MACOSX
// static
Clipboard* ResourceMessageFilter::GetClipboard() {
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index 8821ac6..6a12d14 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -219,6 +219,12 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
void OnAllocateTempFileForPrinting(IPC::Message* reply_msg);
void OnTempFileForPrintingWritten(int fd_in_browser);
#endif
+#if defined(OS_MACOSX)
+ // Used to ask the browser to allocate a block of shared memory for the
+ // renderer to send PDF across in.
+ void OnAllocatePDFTransport(size_t buffer_size,
+ base::SharedMemoryHandle* handle);
+#endif
void OnResourceTypeStats(const WebKit::WebCache::ResourceTypeStats& stats);
static void OnResourceTypeStatsOnUIThread(WebKit::WebCache::ResourceTypeStats,
@@ -238,7 +244,7 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
void OnGetDefaultPrintSettingsReply(
scoped_refptr<printing::PrinterQuery> printer_query,
IPC::Message* reply_msg);
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_MACOSX)
// A javascript code requested to print the current page. The renderer host
// have to show to the user the print dialog and returns the selected print
// settings.
diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h
index b90d68b..6e8c8d0 100644
--- a/chrome/browser/tab_contents/tab_contents.h
+++ b/chrome/browser/tab_contents/tab_contents.h
@@ -40,10 +40,10 @@
#include "webkit/glue/password_form.h"
#include "webkit/glue/webpreferences.h"
-#if defined(OS_MACOSX) || defined(OS_LINUX)
+#if defined(OS_LINUX)
// Remove when we've finished porting the supporting classes.
#include "chrome/common/temp_scaffolding_stubs.h"
-#elif defined(OS_WIN)
+#elif defined(OS_WIN) || defined(OS_MACOSX)
#include "chrome/browser/printing/print_view_manager.h"
#endif
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 43588d5..a34abd7 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -2393,6 +2393,11 @@
'sources': [
'browser/net/ssl_config_service_manager_pref.cc',
],
+ 'sources/': [
+ # Exclude most of printing.
+ ['exclude', '^browser/printing/'],
+ ['include', '^browser/printing/page_(number|range|setup)\\.cc$'],
+ ],
'conditions': [
['linux_breakpad==1', {
'sources': [
@@ -2602,10 +2607,6 @@
# Exclude parts of password_manager.
['exclude', '^browser/password_manager/ie7_password\\.cc$'],
- # Exclude most of printing.
- ['exclude', '^browser/printing/'],
- ['include', '^browser/printing/page_(number|range|setup)\\.cc$'],
-
# Exclude all of rlz.
['exclude', '^browser/rlz/'],
@@ -3144,7 +3145,7 @@
'renderer/print_web_view_helper.cc',
'renderer/print_web_view_helper.h',
'renderer/print_web_view_helper_linux.cc',
- 'renderer/print_web_view_helper_mac.cc',
+ 'renderer/print_web_view_helper_mac.mm',
'renderer/print_web_view_helper_win.cc',
'renderer/render_process.cc',
'renderer/render_process.h',
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index d29d41d..8a48182 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -1341,7 +1341,7 @@ IPC_BEGIN_MESSAGES(ViewHost)
IPC_SYNC_MESSAGE_ROUTED0_1(ViewHostMsg_GetDefaultPrintSettings,
ViewMsg_Print_Params /* default_settings */)
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_MACOSX)
// It's the renderer that controls the printing process when it is generated
// by javascript. This step is about showing UI to the user to select the
// final print settings. The output parameter is the same as
@@ -1350,7 +1350,7 @@ IPC_BEGIN_MESSAGES(ViewHost)
ViewHostMsg_ScriptedPrint_Params,
ViewMsg_PrintPages_Params /* settings choosen by
the user*/)
-#endif // defined(OS_WIN)
+#endif // defined(OS_WIN) || defined(OS_MACOSX)
// WebKit and JavaScript error messages to log to the console
// or debugger UI.
@@ -1526,6 +1526,14 @@ IPC_BEGIN_MESSAGES(ViewHost)
int /* fd in browser */)
#endif
+#if defined(OS_MACOSX)
+ // Asks the browser create a block of shared memory for the renderer to pass
+ // NativeMetafile data to the browser.
+ IPC_SYNC_MESSAGE_ROUTED1_1(ViewHostMsg_AllocatePDFTransport,
+ size_t /* buffer size */,
+ base::SharedMemoryHandle /* browser handle */)
+#endif
+
// Provide the browser process with information about the WebCore resource
// cache.
IPC_MESSAGE_CONTROL1(ViewHostMsg_ResourceTypeStats,
diff --git a/chrome/common/temp_scaffolding_stubs.h b/chrome/common/temp_scaffolding_stubs.h
index 2971ddd..d4097b8 100644
--- a/chrome/common/temp_scaffolding_stubs.h
+++ b/chrome/common/temp_scaffolding_stubs.h
@@ -46,6 +46,7 @@ void InstallJankometer(const CommandLine&);
//---------------------------------------------------------------------------
// These stubs are for BrowserProcessImpl
+#if !defined(OS_MACOSX)
class ViewMsg_Print_Params;
// Printing is all (obviously) not implemented.
@@ -117,6 +118,7 @@ class PrintJobManager {
};
} // namespace printing
+#endif // !OS_MACOSX
//---------------------------------------------------------------------------
// These stubs are for Browser
diff --git a/chrome/renderer/mock_render_thread.cc b/chrome/renderer/mock_render_thread.cc
index 6445dce..bcb1517 100644
--- a/chrome/renderer/mock_render_thread.cc
+++ b/chrome/renderer/mock_render_thread.cc
@@ -4,6 +4,7 @@
#include "chrome/renderer/mock_render_thread.h"
+#include "base/process_util.h"
#include "chrome/common/render_messages.h"
#include "ipc/ipc_message_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -74,7 +75,7 @@ void MockRenderThread::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnMsgCreateWidget);
IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToExtension,
OnMsgOpenChannelToExtension);
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetDefaultPrintSettings,
OnGetDefaultPrintSettings);
IPC_MESSAGE_HANDLER(ViewHostMsg_ScriptedPrint,
@@ -82,8 +83,14 @@ void MockRenderThread::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_DidGetPrintedPagesCount,
OnDidGetPrintedPagesCount)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidPrintPage, OnDidPrintPage)
+#endif
+#if defined(OS_WIN)
IPC_MESSAGE_HANDLER(ViewHostMsg_DuplicateSection, OnDuplicateSection)
#endif
+#if defined(OS_MACOSX)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_AllocatePDFTransport,
+ OnAllocatePDFTransport)
+#endif
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP_EX()
}
@@ -103,6 +110,7 @@ void MockRenderThread::OnMsgOpenChannelToExtension(
*port_id = 0;
}
+#if defined(OS_WIN)
void MockRenderThread::OnDuplicateSection(
base::SharedMemoryHandle renderer_handle,
base::SharedMemoryHandle* browser_handle) {
@@ -110,6 +118,21 @@ void MockRenderThread::OnDuplicateSection(
// separate a browser process from a renderer process.
*browser_handle = renderer_handle;
}
+#endif
+
+#if defined(OS_MACOSX)
+void MockRenderThread::OnAllocatePDFTransport(
+ size_t buffer_size, base::SharedMemoryHandle* handle) {
+ base::SharedMemory shared_buf;
+ shared_buf.Create(L"", false, false, buffer_size);
+ if (!shared_buf.Map(buffer_size)) {
+ *handle = base::SharedMemory::NULLHandle();
+ NOTREACHED() << "Cannot map PDF transport buffer";
+ return;
+ }
+ shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), handle);
+}
+#endif
void MockRenderThread::OnGetDefaultPrintSettings(ViewMsg_Print_Params* params) {
if (printer_.get())
diff --git a/chrome/renderer/mock_render_thread.h b/chrome/renderer/mock_render_thread.h
index eb1a458..d4ed9f7 100644
--- a/chrome/renderer/mock_render_thread.h
+++ b/chrome/renderer/mock_render_thread.h
@@ -87,8 +87,15 @@ class MockRenderThread : public RenderThreadBase {
const std::string& source_extension_id,
const std::string& target_extension_id, int* port_id);
+#if defined(OS_WIN)
void OnDuplicateSection(base::SharedMemoryHandle renderer_handle,
base::SharedMemoryHandle* browser_handle);
+#endif
+
+#if defined(OS_MACOSX)
+ void OnAllocatePDFTransport(size_t buffer_size,
+ base::SharedMemoryHandle* handle);
+#endif
// The RenderView expects default print settings.
void OnGetDefaultPrintSettings(ViewMsg_Print_Params* setting);
diff --git a/chrome/renderer/print_web_view_helper_mac.cc b/chrome/renderer/print_web_view_helper_mac.cc
deleted file mode 100644
index fdb61419e..0000000
--- a/chrome/renderer/print_web_view_helper_mac.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/renderer/print_web_view_helper.h"
-
-#include "base/logging.h"
-
-using WebKit::WebFrame;
-
-void PrintWebViewHelper::Print(WebFrame* frame, bool script_initiated) {
- // TODO(port): print not implemented
- NOTIMPLEMENTED();
-}
-
-void PrintWebViewHelper::PrintPages(const ViewMsg_PrintPages_Params& params,
- WebKit::WebFrame* frame) {
- // TODO(port) implement printing
- NOTIMPLEMENTED();
-}
-
-void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params,
- const gfx::Size& canvas_size,
- WebFrame* frame) {
- // TODO(port) implement printing
- NOTIMPLEMENTED();
-}
-
diff --git a/chrome/renderer/print_web_view_helper_mac.mm b/chrome/renderer/print_web_view_helper_mac.mm
new file mode 100644
index 0000000..4ac3a47
--- /dev/null
+++ b/chrome/renderer/print_web_view_helper_mac.mm
@@ -0,0 +1,238 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/print_web_view_helper.h"
+
+#import <AppKit/AppKit.h>
+
+#include "app/l10n_util.h"
+#include "base/logging.h"
+#include "base/process_util.h"
+#include "base/scoped_cftyperef.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/renderer/render_view.h"
+#include "grit/generated_resources.h"
+#include "printing/native_metafile.h"
+#include "webkit/api/public/WebFrame.h"
+#include "webkit/api/public/WebCanvas.h"
+#include "webkit/api/public/WebConsoleMessage.h"
+
+using WebKit::WebFrame;
+using WebKit::WebCanvas;
+using WebKit::WebConsoleMessage;
+using WebKit::WebString;
+
+// TODO(stuartmorgan): There's a fair amount of code here that is duplicated
+// from _win that should instead be shared. Once Linux has a real print settings
+// implementation, it's likely that this whole method can just be moved to the
+// cross-platform file, and the slight divergences resolved/ifdef'd.
+void PrintWebViewHelper::Print(WebFrame* frame, bool script_initiated) {
+ const int kMinSecondsToIgnoreJavascriptInitiatedPrint = 2;
+ const int kMaxSecondsToIgnoreJavascriptInitiatedPrint = 2 * 60; // 2 Minutes.
+
+ // If still not finished with earlier print request simply ignore.
+ if (IsPrinting())
+ return;
+
+ // TODO(maruel): Move this out of platform specific code.
+ // Check if there is script repeatedly trying to print and ignore it if too
+ // frequent. We use exponential wait time so for a page that calls print() in
+ // a loop the user will need to cancel the print dialog after 2 seconds, 4
+ // seconds, 8, ... up to the maximum of 2 minutes.
+ // This gives the user time to navigate from the page.
+ if (script_initiated && (user_cancelled_scripted_print_count_ > 0)) {
+ base::TimeDelta diff = base::Time::Now() - last_cancelled_script_print_;
+ int min_wait_seconds = std::min(
+ kMinSecondsToIgnoreJavascriptInitiatedPrint <<
+ (user_cancelled_scripted_print_count_ - 1),
+ kMaxSecondsToIgnoreJavascriptInitiatedPrint);
+ if (diff.InSeconds() < min_wait_seconds) {
+ WebString message(WebString::fromUTF8(
+ "Ignoring too frequent calls to print()."));
+ frame->addMessageToConsole(WebConsoleMessage(
+ WebConsoleMessage::LevelWarning,
+ message));
+ return;
+ }
+ }
+
+ // Retrieve the default print settings to calculate the expected number of
+ // pages.
+ ViewMsg_Print_Params default_settings;
+ bool user_cancelled_print = false;
+
+ IPC::SyncMessage* msg =
+ new ViewHostMsg_GetDefaultPrintSettings(routing_id(), &default_settings);
+ if (Send(msg)) {
+ msg = NULL;
+ if (default_settings.IsEmpty()) {
+ NOTREACHED() << "Couldn't get default print settings";
+ return;
+ }
+
+ // Continue only if the settings are valid.
+ if (default_settings.dpi && default_settings.document_cookie) {
+ int expected_pages_count = 0;
+
+ // Prepare once to calculate the estimated page count. This must be in
+ // a scope for itself (see comments on PrepareFrameAndViewForPrint).
+ {
+ PrepareFrameAndViewForPrint prep_frame_view(default_settings,
+ frame,
+ frame->view());
+ expected_pages_count = prep_frame_view.GetExpectedPageCount();
+ DCHECK(expected_pages_count);
+ }
+
+ // Ask the browser to show UI to retrieve the final print settings.
+ ViewMsg_PrintPages_Params print_settings;
+
+ ViewHostMsg_ScriptedPrint_Params params;
+
+ // The routing id is sent across as it is needed to look up the
+ // corresponding RenderViewHost instance to signal and reset the
+ // pump messages event.
+ params.routing_id = routing_id();
+ // host_window_ may be NULL at this point if the current window is a popup
+ // and the print() command has been issued from the parent. The receiver
+ // of this message has to deal with this.
+ params.host_window_id = render_view_->host_window();
+ params.cookie = default_settings.document_cookie;
+ params.has_selection = frame->hasSelection();
+ params.expected_pages_count = expected_pages_count;
+
+ msg = new ViewHostMsg_ScriptedPrint(params, &print_settings);
+ // TODO(stuartmorgan): This should use SendAndRunNestedMessageLoop, as on
+ // Windows, to prevent getting a "hung renderer" dialog, but if we do we
+ // never actually break out of the nested loop and continue with printing.
+ // Once that's fixed, switch back to SendAndRunNestedMessageLoop.
+ //if (render_view_->SendAndRunNestedMessageLoop(msg)) {
+ if (render_view_->Send(msg)) {
+ msg = NULL;
+
+ // If the settings are invalid, early quit.
+ if (print_settings.params.dpi &&
+ print_settings.params.document_cookie) {
+ if (print_settings.params.selection_only) {
+ CopyAndPrint(print_settings, frame);
+ } else {
+ // TODO: Always copy before printing.
+ PrintPages(print_settings, frame);
+ }
+
+ // Reset cancel counter on first successful print.
+ user_cancelled_scripted_print_count_ = 0;
+ return; // All went well.
+ } else {
+ user_cancelled_print = true;
+ }
+ } else {
+ // Send() failed.
+ NOTREACHED();
+ }
+ } else {
+ // Failed to get default settings.
+ NOTREACHED();
+ }
+ } else {
+ // Send() failed.
+ NOTREACHED();
+ }
+ if (script_initiated && user_cancelled_print) {
+ ++user_cancelled_scripted_print_count_;
+ last_cancelled_script_print_ = base::Time::Now();
+ }
+ // When |user_cancelled_print| is true, we treat it as success so that
+ // DidFinishPrinting() won't show any error alert.
+ // If |user_cancelled_print| is false and we reach here, there must be
+ // something wrong and hence is not success, DidFinishPrinting() should show
+ // an error alert.
+ // In both cases, we have to call DidFinishPrinting() here to release
+ // printing resources, since we don't need them anymore.
+ DidFinishPrinting(user_cancelled_print);
+}
+
+void PrintWebViewHelper::PrintPages(const ViewMsg_PrintPages_Params& params,
+ WebKit::WebFrame* frame) {
+ PrepareFrameAndViewForPrint prep_frame_view(params.params,
+ frame,
+ frame->view());
+ int page_count = prep_frame_view.GetExpectedPageCount();
+
+ Send(new ViewHostMsg_DidGetPrintedPagesCount(routing_id(),
+ params.params.document_cookie,
+ page_count));
+ if (!page_count)
+ return;
+
+ const gfx::Size& canvas_size = prep_frame_view.GetPrintCanvasSize();
+ ViewMsg_PrintPage_Params page_params;
+ page_params.params = params.params;
+ if (params.pages.empty()) {
+ for (int i = 0; i < page_count; ++i) {
+ page_params.page_number = i;
+ PrintPage(page_params, canvas_size, frame);
+ }
+ } else {
+ for (size_t i = 0; i < params.pages.size(); ++i) {
+ if (params.pages[i] >= page_count)
+ break;
+ page_params.page_number = params.pages[i];
+ PrintPage(page_params, canvas_size, frame);
+ }
+ }
+}
+
+void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params,
+ const gfx::Size& canvas_size,
+ WebFrame* frame) {
+ printing::NativeMetafile metafile;
+ CGContextRef context = metafile.Init();
+
+ float scale_factor = frame->getPrintPageShrink(params.page_number);
+ metafile.StartPage(canvas_size.width(), canvas_size.height(), scale_factor);
+
+ // printPage can create autoreleased references to |canvas|. PDF contexts
+ // don't write all their data until they are destroyed, so we need to make
+ // certain that there are no lingering references.
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ frame->printPage(params.page_number, context);
+ [pool release];
+
+ metafile.FinishPage();
+ metafile.Close();
+
+ // Get the size of the compiled metafile.
+ ViewHostMsg_DidPrintPage_Params page_params;
+ page_params.data_size = 0;
+ page_params.page_number = params.page_number;
+ page_params.document_cookie = params.params.document_cookie;
+ page_params.actual_shrink = scale_factor;
+ base::SharedMemory shared_buf;
+
+ // Ask the browser to create the shared memory for us.
+ unsigned int buf_size = metafile.GetDataSize();
+ base::SharedMemoryHandle shared_mem_handle;
+ if (Send(new ViewHostMsg_AllocatePDFTransport(routing_id(), buf_size,
+ &shared_mem_handle))) {
+ if (base::SharedMemory::IsHandleValid(shared_mem_handle)) {
+ base::SharedMemory shared_buf(shared_mem_handle, false);
+ if (shared_buf.Map(buf_size)) {
+ metafile.GetData(shared_buf.memory(), buf_size);
+ page_params.data_size = buf_size;
+ shared_buf.GiveToProcess(base::GetCurrentProcessHandle(),
+ &(page_params.metafile_data_handle));
+ } else {
+ NOTREACHED() << "Map failed";
+ }
+ } else {
+ NOTREACHED() << "Browser failed to allocate shared memory";
+ }
+ } else {
+ NOTREACHED() << "Browser allocation request message failed";
+ }
+
+ Send(new ViewHostMsg_DidPrintPage(routing_id(), page_params));
+}
+
diff --git a/chrome/renderer/render_view_unittest.cc b/chrome/renderer/render_view_unittest.cc
index 3bdb362..980ba38 100644
--- a/chrome/renderer/render_view_unittest.cc
+++ b/chrome/renderer/render_view_unittest.cc
@@ -310,7 +310,7 @@ TEST_F(RenderViewTest, OnSetTextDirection) {
// Tests that printing pages work and sending and receiving messages through
// that channel all works.
TEST_F(RenderViewTest, OnPrintPages) {
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_MACOSX)
// Lets simulate a print pages with Hello world.
LoadHTML("<body><p>Hello World!</p></body>");
view_->OnPrintPages();
@@ -342,7 +342,7 @@ TEST_F(RenderViewTest, OnPrintPages) {
// Duplicate of OnPrintPagesTest only using javascript to print.
TEST_F(RenderViewTest, PrintWithJavascript) {
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_MACOSX)
// HTML contains a call to window.print()
LoadHTML("<body>Hello<script>window.print()</script>World</body>");