Index: chrome/browser/printing/print_dialog_gtk.cc |
=================================================================== |
--- chrome/browser/printing/print_dialog_gtk.cc (revision 74844) |
+++ chrome/browser/printing/print_dialog_gtk.cc (working copy) |
@@ -4,117 +4,96 @@ |
#include "chrome/browser/printing/print_dialog_gtk.h" |
+#include <fcntl.h> |
+#include <gtk/gtkpagesetupunixdialog.h> |
#include <gtk/gtkprintjob.h> |
-#include <gtk/gtkprintunixdialog.h> |
-#include <gtk/gtkpagesetupunixdialog.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/utf_string_conversions.h" |
+#include "base/synchronization/waitable_event.h" |
+#include "base/string_util.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" |
+#include "printing/print_settings_initializer_gtk.h" |
-namespace { |
+// static |
+void* PrintDialogGtk::CreatePrintDialog( |
+ PrintingContextCairo::PrintSettingsCallback* callback, |
+ PrintingContextCairo* context) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
-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(); |
+ PrintDialogGtk* dialog = new PrintDialogGtk(callback, context); |
+ return dialog; |
} |
-// 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) { |
- } |
+// static |
+void PrintDialogGtk::PrintDocument(void* print_dialog, |
+ const NativeMetafile* metafile, |
+ const string16& document_name) { |
+ PrintDialogGtk* dialog = static_cast<PrintDialogGtk*>(print_dialog); |
- 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 |
- |
-// static |
-void PrintDialogGtk::CreatePrintDialogForPdf(const FilePath& path) { |
+ scoped_ptr<base::WaitableEvent> event; |
Evan Stade
2011/02/15 00:40:46
unite these
Lei Zhang
2011/02/15 01:20:26
O
|
+ event.reset(new base::WaitableEvent(false, false)); |
Evan Stade
2011/02/15 00:40:46
two lines
Lei Zhang
2011/02/15 01:20:26
K
|
+ dialog->set_save_document_event(event.get()); |
BrowserThread::PostTask( |
- BrowserThread::UI, FROM_HERE, |
- NewRunnableFunction(&PrintDialogGtk::CreateDialogImpl, path)); |
+ BrowserThread::FILE, FROM_HERE, |
+ NewRunnableMethod(dialog, |
+ &PrintDialogGtk::SaveDocumentToDisk, |
+ metafile, |
+ document_name)); |
+ event->Wait(); // Wait for SaveDocumentToDisk() to finish. |
Evan Stade
2011/02/15 00:40:46
can we at least be consistent between comment on l
Lei Zhang
2011/02/15 01:20:26
Yes.
|
} |
-// static |
-bool PrintDialogGtk::DialogShowing() { |
- base::AutoLock lock(DialogLock()); |
- return !!g_print_dialog; |
-} |
+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(); |
-// 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; |
- } |
+ GtkWindow* parent = BrowserList::GetLastActive()->window()->GetNativeHandle(); |
- g_print_dialog = new PrintDialogGtk(path); |
-} |
- |
-PrintDialogGtk::PrintDialogGtk(const FilePath& path_to_pdf) |
- : path_to_pdf_(path_to_pdf), |
- browser_(BrowserList::GetLastActive()) { |
- GtkWindow* parent = browser_->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); |
+ gtk_print_unix_dialog_set_embed_page_setup(GTK_PRINT_UNIX_DIALOG(dialog_), |
Evan Stade
2011/02/15 00:40:46
if this is 2.18+ then we need a workaround until A
Lei Zhang
2011/02/15 01:20:26
Done.
|
+ TRUE); |
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 +101,118 @@ |
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(); // Printing cancelled. |
+ 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( |
+ UTF16ToASCII(document_name).c_str(), |
Evan Stade
2011/02/15 00:40:46
is the document name guaranteed to be ascii? I sus
Lei Zhang
2011/02/15 01:20:26
Done.
|
+ 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, |
Evan Stade
2011/02/15 00:40:46
convert this to CHROMEGTK_SIGNAL macro style
Lei Zhang
2011/02/15 01:20:26
Can't. |user_data| is not the last parameter. All
|
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); |
+ Release(); // Printing finished. |
+} |
- delete this; |
+void PrintDialogGtk::set_save_document_event(base::WaitableEvent* event) { |
+ DCHECK(event); |
+ DCHECK(!save_document_event_); |
+ save_document_event_ = event; |
} |