diff options
author | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-19 00:09:22 +0000 |
---|---|---|
committer | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-19 00:09:22 +0000 |
commit | 5cc4c42d46ac837b79333091b110391c2ca1c996 (patch) | |
tree | 02764336dcbc316b1725fc614f658f391de8326c | |
parent | 38a0a14f438057e1c8c0ddcf1e903c8d53620141 (diff) | |
download | chromium_src-5cc4c42d46ac837b79333091b110391c2ca1c996.zip chromium_src-5cc4c42d46ac837b79333091b110391c2ca1c996.tar.gz chromium_src-5cc4c42d46ac837b79333091b110391c2ca1c996.tar.bz2 |
Linux: Refactor printing to be more linux Windows/Mac.
BUG=41543,59732
TEST=Printing works on Linux and CrOS, Linux printing respect print dialog settings.
Review URL: http://codereview.chromium.org/6516022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75475 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/browser_main_posix.cc | 14 | ||||
-rw-r--r-- | chrome/browser/printing/print_dialog_gtk.cc | 271 | ||||
-rw-r--r-- | chrome/browser/printing/print_dialog_gtk.h | 66 | ||||
-rw-r--r-- | chrome/browser/printing/print_job_worker.cc | 6 | ||||
-rw-r--r-- | chrome/browser/printing/print_view_manager.cc | 32 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_message_filter.cc | 2 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_message_filter.h | 2 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_message_filter_gtk.cc | 30 | ||||
-rw-r--r-- | chrome/renderer/mock_render_thread.cc | 8 | ||||
-rw-r--r-- | chrome/renderer/mock_render_thread.h | 4 | ||||
-rw-r--r-- | chrome/renderer/print_web_view_helper_linux.cc | 63 | ||||
-rw-r--r-- | chrome/test/render_view_test.cc | 28 | ||||
-rw-r--r-- | printing/printed_document.cc | 14 | ||||
-rw-r--r-- | printing/printed_document.h | 8 | ||||
-rw-r--r-- | printing/printed_document_cairo.cc | 14 | ||||
-rw-r--r-- | printing/printing_context_cairo.cc | 93 | ||||
-rw-r--r-- | printing/printing_context_cairo.h | 25 |
17 files changed, 452 insertions, 228 deletions
diff --git a/chrome/browser/browser_main_posix.cc b/chrome/browser/browser_main_posix.cc index 02319c7..1a9b8d2 100644 --- a/chrome/browser/browser_main_posix.cc +++ b/chrome/browser/browser_main_posix.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -8,6 +8,8 @@ #include <signal.h> #include <sys/resource.h> +#include <string> + #include "base/command_line.h" #include "base/eintr_wrapper.h" #include "base/logging.h" @@ -17,6 +19,10 @@ #include "chrome/browser/browser_thread.h" #include "chrome/common/chrome_switches.h" +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) +#include "chrome/browser/printing/print_dialog_gtk.h" +#endif + namespace { // See comment in |PreEarlyInitialization()|, where sigaction is called. @@ -218,4 +224,10 @@ void BrowserMainPartsPosix::PostMainMessageLoopStart() { LOG(DFATAL) << "Failed to create shutdown detector task."; } } + +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + printing::PrintingContextCairo::SetPrintingFunctions( + &PrintDialogGtk::CreatePrintDialog, + &PrintDialogGtk::PrintDocument); +#endif // defined(OS_LINUX) && !defined(OS_CHROMEOS) } diff --git a/chrome/browser/printing/print_dialog_gtk.cc b/chrome/browser/printing/print_dialog_gtk.cc index b51056a..747571b 100644 --- a/chrome/browser/printing/print_dialog_gtk.cc +++ b/chrome/browser/printing/print_dialog_gtk.cc @@ -4,117 +4,98 @@ #include "chrome/browser/printing/print_dialog_gtk.h" -#include <gtk/gtkprintjob.h> -#include <gtk/gtkprintunixdialog.h> +#include <fcntl.h> #include <gtk/gtkpagesetupunixdialog.h> +#include <gtk/gtkprintjob.h> +#include <sys/stat.h> +#include <sys/types.h> #include "base/file_util.h" #include "base/file_util_proxy.h" -#include "base/lazy_instance.h" #include "base/logging.h" -#include "base/synchronization/lock.h" -#include "base/threading/thread_restrictions.h" +#include "base/synchronization/waitable_event.h" #include "base/utf_string_conversions.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/browser_window.h" -#include "chrome/browser/tab_contents/infobar_delegate.h" -#include "chrome/browser/tab_contents/tab_contents.h" - -namespace { - -PrintDialogGtk* g_print_dialog = NULL; - -// Used to make accesses to the above thread safe. -base::Lock& DialogLock() { - static base::LazyInstance<base::Lock> dialog_lock(base::LINKER_INITIALIZED); - return dialog_lock.Get(); -} - -// This is a temporary infobar designed to help gauge how many users are trying -// to print to printers that don't support PDF. -class PdfUnsupportedInfoBarDelegate : public LinkInfoBarDelegate { - public: - explicit PdfUnsupportedInfoBarDelegate(Browser* browser) - : LinkInfoBarDelegate(NULL), - browser_(browser) { - } - - virtual ~PdfUnsupportedInfoBarDelegate() {} - - virtual string16 GetMessageTextWithOffset(size_t* link_offset) const { - string16 message = UTF8ToUTF16("Oops! Your printer does not support PDF. " - "Please report this to us."); - *link_offset = message.length() - 1; - return message; - } - - virtual string16 GetLinkText() const { - return UTF8ToUTF16("here"); - } - - virtual Type GetInfoBarType() const { return WARNING_TYPE; } - - virtual bool LinkClicked(WindowOpenDisposition disposition) { - browser_->OpenURL( - GURL("http://code.google.com/p/chromium/issues/detail?id=22027"), - GURL(), NEW_FOREGROUND_TAB, PageTransition::TYPED); - return true; - } - - private: - Browser* browser_; -}; - -} // namespace +#include "printing/print_settings_initializer_gtk.h" // static -void PrintDialogGtk::CreatePrintDialogForPdf(const FilePath& path) { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - NewRunnableFunction(&PrintDialogGtk::CreateDialogImpl, path)); -} +void* PrintDialogGtk::CreatePrintDialog( + PrintingContextCairo::PrintSettingsCallback* callback, + PrintingContextCairo* context) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); -// static -bool PrintDialogGtk::DialogShowing() { - base::AutoLock lock(DialogLock()); - return !!g_print_dialog; + PrintDialogGtk* dialog = new PrintDialogGtk(callback, context); + return dialog; } // static -void PrintDialogGtk::CreateDialogImpl(const FilePath& path) { - // Only show one print dialog at once. This is to prevent a page from - // locking up the system with - // - // while(true){print();} - base::AutoLock lock(DialogLock()); - if (g_print_dialog) { - // Clean up the temporary file. - base::FileUtilProxy::Delete( - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), - path, false, NULL); - return; - } +void PrintDialogGtk::PrintDocument(void* print_dialog, + const NativeMetafile* metafile, + const string16& document_name) { + PrintDialogGtk* dialog = static_cast<PrintDialogGtk*>(print_dialog); - g_print_dialog = new PrintDialogGtk(path); + scoped_ptr<base::WaitableEvent> event(new base::WaitableEvent(false, false)); + dialog->set_save_document_event(event.get()); + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + NewRunnableMethod(dialog, + &PrintDialogGtk::SaveDocumentToDisk, + metafile, + document_name)); + // Wait for SaveDocumentToDisk() to finish. + event->Wait(); } -PrintDialogGtk::PrintDialogGtk(const FilePath& path_to_pdf) - : path_to_pdf_(path_to_pdf), - browser_(BrowserList::GetLastActive()) { - GtkWindow* parent = browser_->window()->GetNativeHandle(); +PrintDialogGtk::PrintDialogGtk( + PrintingContextCairo::PrintSettingsCallback* callback, + PrintingContextCairo* context) + : callback_(callback), + context_(context), + dialog_(NULL), + page_setup_(NULL), + printer_(NULL), + gtk_settings_(NULL), + save_document_event_(NULL) { + // Manual AddRef since PrintDialogGtk manages its own lifetime. + AddRef(); + + GtkWindow* parent = BrowserList::GetLastActive()->window()->GetNativeHandle(); // TODO(estade): We need a window title here. dialog_ = gtk_print_unix_dialog_new(NULL, parent); + // Set modal so user cannot focus the same tab and press print again. + gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE); + + // Since we only generate PDF, only show printers that support PDF. + // TODO(thestig) Add more capabilities to support? + GtkPrintCapabilities cap = static_cast<GtkPrintCapabilities>( + GTK_PRINT_CAPABILITY_GENERATE_PDF | + GTK_PRINT_CAPABILITY_PAGE_SET | + GTK_PRINT_CAPABILITY_COPIES | + GTK_PRINT_CAPABILITY_COLLATE | + GTK_PRINT_CAPABILITY_REVERSE); + gtk_print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(dialog_), + cap); +#if GTK_CHECK_VERSION(2, 18, 0) + gtk_print_unix_dialog_set_embed_page_setup(GTK_PRINT_UNIX_DIALOG(dialog_), + TRUE); +#endif g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this); gtk_widget_show(dialog_); } PrintDialogGtk::~PrintDialogGtk() { - base::AutoLock lock(DialogLock()); - DCHECK_EQ(this, g_print_dialog); - g_print_dialog = NULL; + gtk_widget_destroy(dialog_); + dialog_ = NULL; + page_setup_ = NULL; + printer_ = NULL; + if (gtk_settings_) { + g_object_unref(gtk_settings_); + gtk_settings_ = NULL; + } } void PrintDialogGtk::OnResponse(GtkWidget* dialog, gint response_id) { @@ -122,67 +103,119 @@ void PrintDialogGtk::OnResponse(GtkWidget* dialog, gint response_id) { switch (response_id) { case GTK_RESPONSE_OK: { - GtkPrinter* printer = - gtk_print_unix_dialog_get_selected_printer( - GTK_PRINT_UNIX_DIALOG(dialog_)); - // Attempt to track down bug 70166. - CHECK(printer != NULL); - if (!gtk_printer_accepts_pdf(printer)) { - browser_->GetSelectedTabContents()->AddInfoBar( - new PdfUnsupportedInfoBarDelegate(browser_)); - break; + // |gtk_settings_| is a new object. + gtk_settings_ = gtk_print_unix_dialog_get_settings( + GTK_PRINT_UNIX_DIALOG(dialog_)); + // |printer_| and |page_setup_| are owned by |dialog_|. + page_setup_ = gtk_print_unix_dialog_get_page_setup( + GTK_PRINT_UNIX_DIALOG(dialog_)); + printer_ = gtk_print_unix_dialog_get_selected_printer( + GTK_PRINT_UNIX_DIALOG(dialog_)); + + printing::PageRanges ranges_vector; + gint num_ranges; + GtkPageRange* gtk_range = + gtk_print_settings_get_page_ranges(gtk_settings_, &num_ranges); + if (gtk_range) { + for (int i = 0; i < num_ranges; ++i) { + printing::PageRange* range = new printing::PageRange; + range->from = gtk_range[i].start; + range->to = gtk_range[i].end; + ranges_vector.push_back(*range); + } + g_free(gtk_range); } - GtkPrintSettings* settings = - gtk_print_unix_dialog_get_settings( - GTK_PRINT_UNIX_DIALOG(dialog_)); - GtkPageSetup* setup = gtk_print_unix_dialog_get_page_setup( - GTK_PRINT_UNIX_DIALOG(dialog_)); - - GtkPrintJob* job = - gtk_print_job_new(path_to_pdf_.value().c_str(), printer, - settings, setup); - gtk_print_job_set_source_file(job, path_to_pdf_.value().c_str(), NULL); - gtk_print_job_send(job, OnJobCompletedThunk, this, NULL); - g_object_unref(settings); - // Success; return early. + printing::PrintSettings settings; + printing::PrintSettingsInitializerGtk::InitPrintSettings( + gtk_settings_, page_setup_, ranges_vector, false, &settings); + context_->InitWithSettings(settings); + callback_->Run(PrintingContextCairo::OK); return; } case GTK_RESPONSE_DELETE_EVENT: // Fall through. case GTK_RESPONSE_CANCEL: { - break; + callback_->Run(PrintingContextCairo::CANCEL); + Release(); + return; } case GTK_RESPONSE_APPLY: default: { NOTREACHED(); } } +} - // Delete this dialog. - OnJobCompleted(NULL, NULL); +void PrintDialogGtk::SaveDocumentToDisk(const NativeMetafile* metafile, + const string16& document_name) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + + bool error = false; + if (!file_util::CreateTemporaryFile(&path_to_pdf_)) { + LOG(ERROR) << "Creating temporary file failed"; + error = true; + } + + if (!error) { + base::FileDescriptor temp_file_fd; + temp_file_fd.fd = open(path_to_pdf_.value().c_str(), O_WRONLY); + temp_file_fd.auto_close = true; + if (!metafile->SaveTo(temp_file_fd)) { + LOG(ERROR) << "Saving metafile failed"; + file_util::Delete(path_to_pdf_, false); + error = true; + } + } + + // Done saving, let PrintDialogGtk::PrintDocument() continue. + save_document_event_->Signal(); + + if (error) { + Release(); + } else { + // No errors, continue printing. + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + NewRunnableMethod(this, + &PrintDialogGtk::SendDocumentToPrinter, + document_name)); + } } +void PrintDialogGtk::SendDocumentToPrinter(const string16& document_name) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + GtkPrintJob* print_job = gtk_print_job_new( + UTF16ToUTF8(document_name).c_str(), + printer_, + gtk_settings_, + page_setup_); + gtk_print_job_set_source_file(print_job, path_to_pdf_.value().c_str(), NULL); + gtk_print_job_send(print_job, OnJobCompletedThunk, this, NULL); +} + +// static void PrintDialogGtk::OnJobCompletedThunk(GtkPrintJob* print_job, gpointer user_data, GError* error) { - reinterpret_cast<PrintDialogGtk*>(user_data)->OnJobCompleted(print_job, - error); + static_cast<PrintDialogGtk*>(user_data)->OnJobCompleted(print_job, error); } -void PrintDialogGtk::OnJobCompleted(GtkPrintJob* job, GError* error) { - gtk_widget_destroy(dialog_); - +void PrintDialogGtk::OnJobCompleted(GtkPrintJob* print_job, GError* error) { if (error) LOG(ERROR) << "Printing failed: " << error->message; - - if (job) - g_object_unref(job); - + if (print_job) + g_object_unref(print_job); base::FileUtilProxy::Delete( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), path_to_pdf_, false, NULL); + // Printing finished. + Release(); +} - delete this; +void PrintDialogGtk::set_save_document_event(base::WaitableEvent* event) { + DCHECK(event); + DCHECK(!save_document_event_); + save_document_event_ = event; } diff --git a/chrome/browser/printing/print_dialog_gtk.h b/chrome/browser/printing/print_dialog_gtk.h index 4e610b3..e499809 100644 --- a/chrome/browser/printing/print_dialog_gtk.h +++ b/chrome/browser/printing/print_dialog_gtk.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -7,41 +7,75 @@ #pragma once #include <gtk/gtk.h> +#include <gtk/gtkprintunixdialog.h> -#include "base/basictypes.h" #include "base/file_path.h" +#include "base/ref_counted.h" +#include "printing/native_metafile.h" +#include "printing/printing_context_cairo.h" #include "ui/base/gtk/gtk_signal.h" -class Browser; +namespace base { +class WaitableEvent; +} -typedef struct _GtkPrintJob GtkPrintJob; +using printing::NativeMetafile; +using printing::PrintingContextCairo; -// Currently this dialog only allows the user to choose a printer. -class PrintDialogGtk { +class PrintDialogGtk : public base::RefCountedThreadSafe<PrintDialogGtk> { public: - static bool DialogShowing(); - - // Called on the IO thread. - static void CreatePrintDialogForPdf(const FilePath& path); + // Creates and returns a print dialog. The dialog will initialize the settings + // for |context| and call |callback| to inform the print workflow of the + // dialog results. + static void* CreatePrintDialog( + PrintingContextCairo::PrintSettingsCallback* callback, + PrintingContextCairo* context); + + // Prints a document named |document_name| based on the settings in + // |print_dialog|, with data from |metafile|. + // Called from the print worker thread. + static void PrintDocument(void* print_dialog, + const NativeMetafile* metafile, + const string16& document_name); private: - explicit PrintDialogGtk(const FilePath& path_to_pdf); - ~PrintDialogGtk(); + friend class base::RefCountedThreadSafe<PrintDialogGtk>; - static void CreateDialogImpl(const FilePath& path); + PrintDialogGtk(PrintingContextCairo::PrintSettingsCallback* callback, + PrintingContextCairo* context); + ~PrintDialogGtk(); + // Handles dialog response. CHROMEGTK_CALLBACK_1(PrintDialogGtk, void, OnResponse, gint); + // Saves data in |metafile| to disk for document named |document_name|. + void SaveDocumentToDisk(const NativeMetafile* metafile, + const string16& document_name); + + // Prints document named |document_name|. + void SendDocumentToPrinter(const string16& document_name); + + // Handles print job response. static void OnJobCompletedThunk(GtkPrintJob* print_job, gpointer user_data, GError* error); - void OnJobCompleted(GtkPrintJob* job, GError* error); + void OnJobCompleted(GtkPrintJob* print_job, GError* error); - FilePath path_to_pdf_; + void set_save_document_event(base::WaitableEvent* event); + // Printing dialog callback. + PrintingContextCairo::PrintSettingsCallback* callback_; + PrintingContextCairo* context_; + + // Print dialog settings. GtkWidget* dialog_; + GtkPageSetup* page_setup_; + GtkPrinter* printer_; + GtkPrintSettings* gtk_settings_; - Browser* browser_; + // Event to signal when save document finishes. + base::WaitableEvent* save_document_event_; + FilePath path_to_pdf_; DISALLOW_COPY_AND_ASSIGN(PrintDialogGtk); }; diff --git a/chrome/browser/printing/print_job_worker.cc b/chrome/browser/printing/print_job_worker.cc index 2c16cba..77ca7df 100644 --- a/chrome/browser/printing/print_job_worker.cc +++ b/chrome/browser/printing/print_job_worker.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -270,7 +270,11 @@ void PrintJobWorker::SpoolPage(PrintedPage& page) { } // Actual printing. +#if defined(OS_WIN) || defined(OS_MACOSX) document_->RenderPrintedPage(page, printing_context_->context()); +#elif defined(OS_POSIX) + document_->RenderPrintedPage(page, printing_context_.get()); +#endif // Postprocess. if (printing_context_->PageDone() != PrintingContext::OK) { diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc index 15cef0a..8eeba7d 100644 --- a/chrome/browser/printing/print_view_manager.cc +++ b/chrome/browser/printing/print_view_manager.cc @@ -114,21 +114,29 @@ void PrintViewManager::OnDidPrintPage( } #endif + const bool metafile_must_be_valid = +#if defined(OS_WIN) || defined(OS_MACOSX) + true; +#elif defined(OS_POSIX) + (params.page_number == 0); +#endif + base::SharedMemory shared_buf(params.metafile_data_handle, true); - if (!shared_buf.Map(params.data_size)) { - NOTREACHED() << "couldn't map"; - tab_contents()->Stop(); - return; + if (metafile_must_be_valid) { + if (!shared_buf.Map(params.data_size)) { + NOTREACHED() << "couldn't map"; + tab_contents()->Stop(); + return; + } } -#if defined(OS_POSIX) && !defined(OS_MACOSX) - NOTIMPLEMENTED() << " this printing code doesn't quite work yet."; -#else scoped_ptr<NativeMetafile> metafile(new NativeMetafile()); - if (!metafile->Init(shared_buf.memory(), params.data_size)) { - NOTREACHED() << "Invalid metafile header"; - tab_contents()->Stop(); - return; + if (metafile_must_be_valid) { + if (!metafile->Init(shared_buf.memory(), params.data_size)) { + NOTREACHED() << "Invalid metafile header"; + tab_contents()->Stop(); + return; + } } // Update the rendered document. It will send notifications to the listener. @@ -138,7 +146,7 @@ void PrintViewManager::OnDidPrintPage( params.page_size, params.content_area, params.has_visible_overlays); -#endif + ShouldQuitFromInnerMessageLoop(); } diff --git a/chrome/browser/renderer_host/render_message_filter.cc b/chrome/browser/renderer_host/render_message_filter.cc index 4ae24e0..0ca1002 100644 --- a/chrome/browser/renderer_host/render_message_filter.cc +++ b/chrome/browser/renderer_host/render_message_filter.cc @@ -450,7 +450,7 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message, IPC_MESSAGE_HANDLER(ViewHostMsg_AllocateSharedMemoryBuffer, OnAllocateSharedMemoryBuffer) #endif -#if defined(OS_POSIX) && !defined(OS_MACOSX) +#if defined(OS_CHROMEOS) IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_AllocateTempFileForPrinting, OnAllocateTempFileForPrinting) IPC_MESSAGE_HANDLER(ViewHostMsg_TempFileForPrintingWritten, diff --git a/chrome/browser/renderer_host/render_message_filter.h b/chrome/browser/renderer_host/render_message_filter.h index ff50fab..de80fa2 100644 --- a/chrome/browser/renderer_host/render_message_filter.h +++ b/chrome/browser/renderer_host/render_message_filter.h @@ -222,7 +222,7 @@ class RenderMessageFilter : public BrowserMessageFilter, base::SharedMemoryHandle* browser_handle); #endif -#if defined(OS_POSIX) && !defined(OS_MACOSX) +#if defined(OS_CHROMEOS) // Used to ask the browser allocate a temporary file for the renderer // to fill in resulting PDF in renderer. void OnAllocateTempFileForPrinting(IPC::Message* reply_msg); diff --git a/chrome/browser/renderer_host/render_message_filter_gtk.cc b/chrome/browser/renderer_host/render_message_filter_gtk.cc index 8e66dfb..d3e11e7 100644 --- a/chrome/browser/renderer_host/render_message_filter_gtk.cc +++ b/chrome/browser/renderer_host/render_message_filter_gtk.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -11,11 +11,6 @@ #include "base/lazy_instance.h" #include "base/path_service.h" #include "chrome/browser/browser_thread.h" -#if defined(TOOLKIT_GTK) -#include "chrome/browser/printing/print_dialog_gtk.h" -#else -#include "chrome/browser/printing/print_dialog_cloud.h" -#endif #include "chrome/common/chrome_paths.h" #include "chrome/common/render_messages.h" #include "grit/generated_resources.h" @@ -25,6 +20,10 @@ #include "ui/base/x/x11_util.h" #include "ui/gfx/gtk_native_view_id_manager.h" +#if defined(OS_CHROMEOS) +#include "chrome/browser/printing/print_dialog_cloud.h" +#endif + using WebKit::WebScreenInfo; using WebKit::WebScreenInfoFactory; @@ -177,22 +176,16 @@ void RenderMessageFilter::DoOnClipboardReadFilenames( Send(reply_msg); } +#if defined(OS_CHROMEOS) void RenderMessageFilter::DoOnAllocateTempFileForPrinting( IPC::Message* reply_msg) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); base::FileDescriptor temp_file_fd(-1, false); - bool allow_print = -#if defined(TOOLKIT_GTK) - !PrintDialogGtk::DialogShowing(); -#else - true; -#endif - FilePath path; SequenceToPathMap* map = &g_printing_file_descriptor_map.Get().map; const int sequence_number = g_printing_file_descriptor_map.Get().sequence++; - if (allow_print && - file_util::CreateTemporaryFile(&path)) { + FilePath path; + if (file_util::CreateTemporaryFile(&path)) { int fd = open(path.value().c_str(), O_WRONLY); if (fd >= 0) { SequenceToPathMap::iterator it = map->find(sequence_number); @@ -222,18 +215,15 @@ void RenderMessageFilter::DoOnTempFileForPrintingWritten(int sequence_number) { return; } -#if defined(TOOLKIT_GTK) - PrintDialogGtk::CreatePrintDialogForPdf(it->second); -#else if (cloud_print_enabled_) PrintDialogCloud::CreatePrintDialogForPdf(it->second, string16(), true); else NOTIMPLEMENTED(); -#endif // Erase the entry in the map. map->erase(it); } +#endif // defined(OS_CHROMEOS) void RenderMessageFilter::OnGetScreenInfo(gfx::NativeViewId view, IPC::Message* reply_msg) { @@ -334,6 +324,7 @@ void RenderMessageFilter::OnClipboardReadFilenames( reply_msg)); } +#if defined(OS_CHROMEOS) void RenderMessageFilter::OnAllocateTempFileForPrinting( IPC::Message* reply_msg) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); @@ -352,3 +343,4 @@ void RenderMessageFilter::OnTempFileForPrintingWritten(int sequence_number) { this, &RenderMessageFilter::DoOnTempFileForPrintingWritten, sequence_number)); } +#endif // defined(OS_CHROMEOS) diff --git a/chrome/renderer/mock_render_thread.cc b/chrome/renderer/mock_render_thread.cc index f6a26b7..846d2d8 100644 --- a/chrome/renderer/mock_render_thread.cc +++ b/chrome/renderer/mock_render_thread.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -120,7 +120,7 @@ bool MockRenderThread::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(ViewHostMsg_AllocateSharedMemoryBuffer, OnAllocateSharedMemoryBuffer) #endif -#if defined(OS_LINUX) +#if defined(OS_CHROMEOS) IPC_MESSAGE_HANDLER(ViewHostMsg_AllocateTempFileForPrinting, OnAllocateTempFileForPrinting) IPC_MESSAGE_HANDLER(ViewHostMsg_TempFileForPrintingWritten, @@ -169,7 +169,7 @@ void MockRenderThread::OnAllocateSharedMemoryBuffer( } #endif -#if defined(OS_LINUX) +#if defined(OS_CHROMEOS) void MockRenderThread::OnAllocateTempFileForPrinting( base::FileDescriptor* renderer_fd, int* browser_fd) { @@ -187,7 +187,7 @@ void MockRenderThread::OnAllocateTempFileForPrinting( void MockRenderThread::OnTempFileForPrintingWritten(int browser_fd) { close(browser_fd); } -#endif +#endif // defined(OS_CHROMEOS) 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 130480a..0d8e313 100644 --- a/chrome/renderer/mock_render_thread.h +++ b/chrome/renderer/mock_render_thread.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -108,7 +108,7 @@ class MockRenderThread : public RenderThreadBase { base::SharedMemoryHandle* handle); #endif -#if defined(OS_LINUX) +#if defined(OS_CHROMEOS) void OnAllocateTempFileForPrinting(base::FileDescriptor* renderer_fd, int* browser_fd); void OnTempFileForPrintingWritten(int browser_fd); diff --git a/chrome/renderer/print_web_view_helper_linux.cc b/chrome/renderer/print_web_view_helper_linux.cc index 8488073..c7c9ce7 100644 --- a/chrome/renderer/print_web_view_helper_linux.cc +++ b/chrome/renderer/print_web_view_helper_linux.cc @@ -13,6 +13,10 @@ #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h" +#if !defined(OS_CHROMEOS) +#include "base/process_util.h" +#endif // !defined(OS_CHROMEOS) + using printing::NativeMetafile; using WebKit::WebFrame; using WebKit::WebNode; @@ -39,10 +43,13 @@ void PrintWebViewHelper::PrintPages(const ViewMsg_PrintPages_Params& params, node, frame->view()); page_count = prep_frame_view.GetExpectedPageCount(); +#if !defined(OS_CHROMEOS) + Send(new ViewHostMsg_DidGetPrintedPagesCount(routing_id(), + printParams.document_cookie, + page_count)); +#endif // !defined(OS_CHROMEOS) - // TODO(myhuang): Send ViewHostMsg_DidGetPrintedPagesCount. - - if (page_count == 0) + if (!page_count) return; metafile.Init(); @@ -68,11 +75,12 @@ void PrintWebViewHelper::PrintPages(const ViewMsg_PrintPages_Params& params, delete canvas; metafile.Close(); - int sequence_number = -1; // Get the size of the resulting metafile. uint32 buf_size = metafile.GetDataSize(); DCHECK_GT(buf_size, 0u); +#if defined(OS_CHROMEOS) + int sequence_number = -1; base::FileDescriptor fd; // Ask the browser to open a file for us. @@ -80,12 +88,57 @@ void PrintWebViewHelper::PrintPages(const ViewMsg_PrintPages_Params& params, &sequence_number))) { return; } - if (!metafile.SaveTo(fd)) return; // Tell the browser we've finished writing the file. Send(new ViewHostMsg_TempFileForPrintingWritten(sequence_number)); +#else + ViewHostMsg_DidPrintPage_Params printed_page_params; + printed_page_params.data_size = 0; + printed_page_params.document_cookie = params.params.document_cookie; + + base::SharedMemoryHandle shared_mem_handle; + if (!Send(new ViewHostMsg_AllocateSharedMemoryBuffer(buf_size, + &shared_mem_handle))) { + NOTREACHED() << "AllocateSharedMemoryBuffer failed"; + return; + } + if (!base::SharedMemory::IsHandleValid(shared_mem_handle)) { + NOTREACHED() << "AllocateSharedMemoryBuffer returned bad handle"; + return; + } + + { + base::SharedMemory shared_buf(shared_mem_handle, false); + if (!shared_buf.Map(buf_size)) { + NOTREACHED() << "Map failed"; + return; + } + metafile.GetData(shared_buf.memory(), buf_size); + printed_page_params.data_size = buf_size; + shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), + &(printed_page_params.metafile_data_handle)); + } + + // Send the first page with a valid handle. + printed_page_params.page_number = 0; + Send(new ViewHostMsg_DidPrintPage(routing_id(), printed_page_params)); + + // Send the rest of the pages with an invalid metafile handle. + printed_page_params.metafile_data_handle.fd = -1; + if (params.pages.empty()) { + for (int i = 1; i < page_count; ++i) { + printed_page_params.page_number = i; + Send(new ViewHostMsg_DidPrintPage(routing_id(), printed_page_params)); + } + } else { + for (size_t i = 1; i < params.pages.size(); ++i) { + printed_page_params.page_number = params.pages[i]; + Send(new ViewHostMsg_DidPrintPage(routing_id(), printed_page_params)); + } + } +#endif // defined(OS_CHROMEOS) } void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params, diff --git a/chrome/test/render_view_test.cc b/chrome/test/render_view_test.cc index 0af56dd..1cba1c9 100644 --- a/chrome/test/render_view_test.cc +++ b/chrome/test/render_view_test.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -259,7 +259,11 @@ void RenderViewTest::SendNativeKeyEvent( } void RenderViewTest::VerifyPageCount(int count) { -#if defined(OS_WIN) || defined(OS_MACOSX) +#if defined(OS_CHROMEOS) + // The DidGetPrintedPagesCount message isn't sent on ChromeOS. Right now we + // always print all pages, and there are checks to that effect built into + // the print code. +#else const IPC::Message* page_cnt_msg = render_thread_.sink().GetUniqueMessageMatching( ViewHostMsg_DidGetPrintedPagesCount::ID); @@ -268,15 +272,16 @@ void RenderViewTest::VerifyPageCount(int count) { ViewHostMsg_DidGetPrintedPagesCount::Read(page_cnt_msg, &post_page_count_param); EXPECT_EQ(count, post_page_count_param.b); -#elif defined(OS_LINUX) - // The DidGetPrintedPagesCount message isn't sent on Linux. Right now we - // always print all pages, and there are checks to that effect built into - // the print code. -#endif +#endif // defined(OS_CHROMEOS) } void RenderViewTest::VerifyPagesPrinted() { -#if defined(OS_WIN) || defined(OS_MACOSX) +#if defined(OS_CHROMEOS) + const IPC::Message* did_print_msg = + render_thread_.sink().GetUniqueMessageMatching( + ViewHostMsg_TempFileForPrintingWritten::ID); + ASSERT_TRUE(did_print_msg); +#else const IPC::Message* did_print_msg = render_thread_.sink().GetUniqueMessageMatching( ViewHostMsg_DidPrintPage::ID); @@ -284,12 +289,7 @@ void RenderViewTest::VerifyPagesPrinted() { ViewHostMsg_DidPrintPage::Param post_did_print_page_param; ViewHostMsg_DidPrintPage::Read(did_print_msg, &post_did_print_page_param); EXPECT_EQ(0, post_did_print_page_param.a.page_number); -#elif defined(OS_LINUX) - const IPC::Message* did_print_msg = - render_thread_.sink().GetUniqueMessageMatching( - ViewHostMsg_TempFileForPrintingWritten::ID); - ASSERT_TRUE(did_print_msg); -#endif +#endif // defined(OS_CHROMEOS) } const char* const kGetCoordinatesScript = diff --git a/printing/printed_document.cc b/printing/printed_document.cc index d33751c..3d8f156 100644 --- a/printing/printed_document.cc +++ b/printing/printed_document.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -109,10 +109,18 @@ bool PrintedDocument::IsComplete() const { PageNumber page(immutable_.settings_, mutable_.page_count_); if (page == PageNumber::npos()) return false; + for (; page != PageNumber::npos(); ++page) { + bool metafile_must_be_valid = +#if defined(OS_WIN) || defined(OS_MAC) + true; +#elif defined(OS_POSIX) + (page.ToInt() == 0); +#endif PrintedPages::const_iterator itr = mutable_.pages_.find(page.ToInt()); - if (itr == mutable_.pages_.end() || !itr->second.get() || - !itr->second->native_metafile()) + if (itr == mutable_.pages_.end() || !itr->second.get()) + return false; + if (metafile_must_be_valid && !itr->second->native_metafile()) return false; } return true; diff --git a/printing/printed_document.h b/printing/printed_document.h index e71f431..f95ddcf 100644 --- a/printing/printed_document.h +++ b/printing/printed_document.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -27,6 +27,7 @@ namespace printing { class PrintedPage; class PrintedPagesSource; +class PrintingContext; // A collection of rendered pages. The settings are immutable. If the print // settings are changed, a new PrintedDocument must be created. @@ -55,8 +56,13 @@ class PrintedDocument : public base::RefCountedThreadSafe<PrintedDocument> { // Draws the page in the context. // Note: locks for a short amount of time in debug only. +#if defined(OS_WIN) || defined(OS_MACOSX) void RenderPrintedPage(const PrintedPage& page, gfx::NativeDrawingContext context) const; +#elif defined(OS_POSIX) + void RenderPrintedPage(const PrintedPage& page, + PrintingContext* context) const; +#endif // Returns true if all the necessary pages for the settings are already // rendered. diff --git a/printing/printed_document_cairo.cc b/printing/printed_document_cairo.cc index d24fef9..9992bc6 100644 --- a/printing/printed_document_cairo.cc +++ b/printing/printed_document_cairo.cc @@ -1,19 +1,18 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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 "printing/printed_document.h" -#include "base/file_util.h" #include "base/logging.h" -#include "base/message_loop.h" #include "printing/page_number.h" #include "printing/printed_page.h" +#include "printing/printing_context_cairo.h" namespace printing { void PrintedDocument::RenderPrintedPage( - const PrintedPage& page, gfx::NativeDrawingContext context) const { + const PrintedPage& page, PrintingContext* context) const { #ifndef NDEBUG { // Make sure the page is from our list. @@ -24,7 +23,12 @@ void PrintedDocument::RenderPrintedPage( DCHECK(context); - NOTIMPLEMENTED(); +#if !defined(OS_CHROMEOS) + if (page.page_number() == 1) { + reinterpret_cast<PrintingContextCairo*>(context)->PrintDocument( + page.native_metafile()); + } +#endif // !defined(OS_CHROMEOS) } void PrintedDocument::DrawHeaderFooter(gfx::NativeDrawingContext context, diff --git a/printing/printing_context_cairo.cc b/printing/printing_context_cairo.cc index 5976878..d0110b1 100644 --- a/printing/printing_context_cairo.cc +++ b/printing/printing_context_cairo.cc @@ -1,17 +1,35 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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 "printing/printing_context_cairo.h" +#include "base/logging.h" +#include "printing/units.h" + +#if defined(OS_CHROMEOS) +#include <unicode/ulocdata.h> +#include <printing/native_metafile.h> +#else #include <gtk/gtk.h> #include <gtk/gtkprintunixdialog.h> -#include <unicode/ulocdata.h> -#include "base/logging.h" -#include "printing/native_metafile.h" #include "printing/print_settings_initializer_gtk.h" -#include "printing/units.h" +#endif // defined(OS_CHROMEOS) + +#if !defined(OS_CHROMEOS) +namespace { + // Function pointer for creating print dialogs. + static void* (*create_dialog_func_)( + printing::PrintingContext::PrintSettingsCallback* callback, + printing::PrintingContextCairo* context) = NULL; + // Function pointer for printing documents. + static void (*print_document_func_)( + void* print_dialog, + const printing::NativeMetafile* metafile, + const string16& document_name) = NULL; +} // namespace +#endif // !defined(OS_CHROMEOS) namespace printing { @@ -20,21 +38,52 @@ namespace printing { return static_cast<PrintingContext*>(new PrintingContextCairo(app_locale)); } - PrintingContextCairo::PrintingContextCairo(const std::string& app_locale) - : PrintingContext(app_locale) { +PrintingContextCairo::PrintingContextCairo(const std::string& app_locale) +#if defined(OS_CHROMEOS) + : PrintingContext(app_locale) { +#else + : PrintingContext(app_locale), + print_dialog_(NULL) { +#endif } PrintingContextCairo::~PrintingContextCairo() { ReleaseContext(); } +#if !defined(OS_CHROMEOS) +// static +void PrintingContextCairo::SetPrintingFunctions( + void* (*create_dialog_func)(PrintSettingsCallback* callback, + PrintingContextCairo* context), + void (*print_document_func)(void* print_dialog, + const NativeMetafile* metafile, + const string16& document_name)) { + DCHECK(create_dialog_func); + DCHECK(print_document_func); + DCHECK(!create_dialog_func_); + DCHECK(!print_document_func_); + create_dialog_func_ = create_dialog_func; + print_document_func_ = print_document_func; +} + +void PrintingContextCairo::PrintDocument(const NativeMetafile* metafile) { + DCHECK(print_dialog_); + DCHECK(metafile); + print_document_func_(print_dialog_, metafile, document_name_); +} +#endif // !defined(OS_CHROMEOS) + void PrintingContextCairo::AskUserForSettings( gfx::NativeView parent_view, int max_pages, bool has_selection, PrintSettingsCallback* callback) { - NOTIMPLEMENTED(); +#if defined(OS_CHROMEOS) callback->Run(OK); +#else + print_dialog_ = create_dialog_func_(callback, this); +#endif // defined(OS_CHROMEOS) } PrintingContext::Result PrintingContextCairo::UseDefaultSettings() { @@ -106,18 +155,19 @@ PrintingContext::Result PrintingContextCairo::InitWithSettings( settings_ = settings; - NOTIMPLEMENTED(); - - return FAILED; + return OK; } PrintingContext::Result PrintingContextCairo::NewDocument( const string16& document_name) { DCHECK(!in_print_job_); + in_print_job_ = true; - NOTIMPLEMENTED(); +#if !defined(OS_CHROMEOS) + document_name_ = document_name; +#endif // !defined(OS_CHROMEOS) - return FAILED; + return OK; } PrintingContext::Result PrintingContextCairo::NewPage() { @@ -125,9 +175,9 @@ PrintingContext::Result PrintingContextCairo::NewPage() { return CANCEL; DCHECK(in_print_job_); - NOTIMPLEMENTED(); + // Intentional No-op. - return FAILED; + return OK; } PrintingContext::Result PrintingContextCairo::PageDone() { @@ -135,9 +185,9 @@ PrintingContext::Result PrintingContextCairo::PageDone() { return CANCEL; DCHECK(in_print_job_); - NOTIMPLEMENTED(); + // Intentional No-op. - return FAILED; + return OK; } PrintingContext::Result PrintingContextCairo::DocumentDone() { @@ -145,24 +195,21 @@ PrintingContext::Result PrintingContextCairo::DocumentDone() { return CANCEL; DCHECK(in_print_job_); - NOTIMPLEMENTED(); - ResetSettings(); - return FAILED; + return OK; } void PrintingContextCairo::Cancel() { abort_printing_ = true; in_print_job_ = false; - - NOTIMPLEMENTED(); } void PrintingContextCairo::ReleaseContext() { - // Nothing to do yet. + // Intentional No-op. } gfx::NativeDrawingContext PrintingContextCairo::context() const { + // Intentional No-op. return NULL; } diff --git a/printing/printing_context_cairo.h b/printing/printing_context_cairo.h index ac42239..9a88eae 100644 --- a/printing/printing_context_cairo.h +++ b/printing/printing_context_cairo.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -9,6 +9,10 @@ #include "printing/printing_context.h" +#if !defined(OS_CHROMEOS) +#include "printing/native_metafile.h" +#endif + namespace printing { class PrintingContextCairo : public PrintingContext { @@ -16,6 +20,20 @@ class PrintingContextCairo : public PrintingContext { explicit PrintingContextCairo(const std::string& app_locale); ~PrintingContextCairo(); +#if !defined(OS_CHROMEOS) + // Sets the function that creates the print dialog, and the function that + // prints the document. + static void SetPrintingFunctions( + void* (*create_dialog_func)(PrintSettingsCallback* callback, + PrintingContextCairo* context), + void (*print_document_func)(void* print_dialog, + const NativeMetafile* metafile, + const string16& document_name)); + + // Prints the document contained in |metafile|. + void PrintDocument(const NativeMetafile* metafile); +#endif + // PrintingContext implementation. virtual void AskUserForSettings(gfx::NativeView parent_view, int max_pages, @@ -32,6 +50,11 @@ class PrintingContextCairo : public PrintingContext { virtual gfx::NativeDrawingContext context() const; private: +#if !defined(OS_CHROMEOS) + string16 document_name_; + void* print_dialog_; +#endif + DISALLOW_COPY_AND_ASSIGN(PrintingContextCairo); }; |