Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1695)

Unified Diff: chrome/browser/printing/print_dialog_gtk.cc

Issue 6516022: Linux: Refactor printing to be more like Windows/Mac.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Address PrintDialogGtk comments Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/printing/print_dialog_gtk.h ('k') | chrome/browser/printing/print_job_worker.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
}
« no previous file with comments | « chrome/browser/printing/print_dialog_gtk.h ('k') | chrome/browser/printing/print_job_worker.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698