diff --git a/include/capi/cef_print_handler_capi.h b/include/capi/cef_print_handler_capi.h index 72ce14871..497595435 100644 --- a/include/capi/cef_print_handler_capi.h +++ b/include/capi/cef_print_handler_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=e8f6bdc822cf4f5c32b22ba8b5cacb25823d8971$ +// $hash=ed78ca41d62dfc0cdb52828dcf795617c4e231a7$ // #ifndef CEF_INCLUDE_CAPI_CEF_PRINT_HANDLER_CAPI_H_ @@ -85,8 +85,9 @@ typedef struct _cef_print_job_callback_t { } cef_print_job_callback_t; /// -// Implement this structure to handle printing on Linux. The functions of this -// structure will be called on the browser process UI thread. +// Implement this structure to handle printing on Linux. Each browser will have +// only one print job in progress at a time. The functions of this structure +// will be called on the browser process UI thread. /// typedef struct _cef_print_handler_t { /// @@ -109,6 +110,7 @@ typedef struct _cef_print_handler_t { // reference to |settings| outside of this callback. /// void(CEF_CALLBACK* on_print_settings)(struct _cef_print_handler_t* self, + struct _cef_browser_t* browser, struct _cef_print_settings_t* settings, int get_defaults); @@ -119,6 +121,7 @@ typedef struct _cef_print_handler_t { /// int(CEF_CALLBACK* on_print_dialog)( struct _cef_print_handler_t* self, + struct _cef_browser_t* browser, int has_selection, struct _cef_print_dialog_callback_t* callback); @@ -128,6 +131,7 @@ typedef struct _cef_print_handler_t { // the job immediately. /// int(CEF_CALLBACK* on_print_job)(struct _cef_print_handler_t* self, + struct _cef_browser_t* browser, const cef_string_t* document_name, const cef_string_t* pdf_file_path, struct _cef_print_job_callback_t* callback); @@ -135,7 +139,8 @@ typedef struct _cef_print_handler_t { /// // Reset client state related to printing. /// - void(CEF_CALLBACK* on_print_reset)(struct _cef_print_handler_t* self); + void(CEF_CALLBACK* on_print_reset)(struct _cef_print_handler_t* self, + struct _cef_browser_t* browser); /// // Return the PDF paper size in device units. Used in combination with @@ -143,6 +148,7 @@ typedef struct _cef_print_handler_t { /// cef_size_t(CEF_CALLBACK* get_pdf_paper_size)( struct _cef_print_handler_t* self, + struct _cef_browser_t* browser, int device_units_per_inch); } cef_print_handler_t; diff --git a/include/cef_print_handler.h b/include/cef_print_handler.h index 4e8b2fa39..950764acd 100644 --- a/include/cef_print_handler.h +++ b/include/cef_print_handler.h @@ -75,8 +75,9 @@ class CefPrintJobCallback : public virtual CefBaseRefCounted { }; /// -// Implement this interface to handle printing on Linux. The methods of this -// class will be called on the browser process UI thread. +// Implement this interface to handle printing on Linux. Each browser will have +// only one print job in progress at a time. The methods of this class will be +// called on the browser process UI thread. /// /*--cef(source=client)--*/ class CefPrintHandler : public virtual CefBaseRefCounted { @@ -96,7 +97,8 @@ class CefPrintHandler : public virtual CefBaseRefCounted { // reference to |settings| outside of this callback. /// /*--cef()--*/ - virtual void OnPrintSettings(CefRefPtr settings, + virtual void OnPrintSettings(CefRefPtr browser, + CefRefPtr settings, bool get_defaults) = 0; /// @@ -105,7 +107,8 @@ class CefPrintHandler : public virtual CefBaseRefCounted { // printing immediately. /// /*--cef()--*/ - virtual bool OnPrintDialog(bool has_selection, + virtual bool OnPrintDialog(CefRefPtr browser, + bool has_selection, CefRefPtr callback) = 0; /// @@ -114,7 +117,8 @@ class CefPrintHandler : public virtual CefBaseRefCounted { // immediately. /// /*--cef()--*/ - virtual bool OnPrintJob(const CefString& document_name, + virtual bool OnPrintJob(CefRefPtr browser, + const CefString& document_name, const CefString& pdf_file_path, CefRefPtr callback) = 0; @@ -122,14 +126,15 @@ class CefPrintHandler : public virtual CefBaseRefCounted { // Reset client state related to printing. /// /*--cef()--*/ - virtual void OnPrintReset() = 0; + virtual void OnPrintReset(CefRefPtr browser) = 0; /// // Return the PDF paper size in device units. Used in combination with // CefBrowserHost::PrintToPDF(). /// /*--cef()--*/ - virtual CefSize GetPdfPaperSize(int device_units_per_inch) { + virtual CefSize GetPdfPaperSize(CefRefPtr browser, + int device_units_per_inch) { return CefSize(); } }; diff --git a/libcef/browser/printing/print_dialog_linux.cc b/libcef/browser/printing/print_dialog_linux.cc index c45980fb8..a9b44fe79 100644 --- a/libcef/browser/printing/print_dialog_linux.cc +++ b/libcef/browser/printing/print_dialog_linux.cc @@ -113,9 +113,12 @@ gfx::Size CefPrintDialogLinux::GetPdfPaperSize( if (browser_handler.get()) { CefRefPtr handler = browser_handler->GetPrintHandler(); if (handler.get()) { + CefRefPtr browser = + extensions::GetOwnerBrowserForFrame( + context->render_process_id(), context->render_frame_id(), NULL); const printing::PrintSettings& settings = context->settings(); - CefSize cef_size = - handler->GetPdfPaperSize(settings.device_units_per_inch()); + CefSize cef_size = handler->GetPdfPaperSize( + browser.get(), settings.device_units_per_inch()); size.SetSize(cef_size.width, cef_size.height); } } @@ -187,10 +190,14 @@ void CefPrintDialogLinux::ShowDialog( callback_ = callback; + CefRefPtr browser = extensions::GetOwnerBrowserForFrame( + context_->render_process_id(), context_->render_frame_id(), NULL); + CefRefPtr callback_impl( new CefPrintDialogCallbackImpl(this)); - if (!handler_->OnPrintDialog(has_selection, callback_impl.get())) { + if (!handler_->OnPrintDialog(browser.get(), has_selection, + callback_impl.get())) { callback_impl->Disconnect(); OnPrintCancel(); } @@ -253,7 +260,10 @@ void CefPrintDialogLinux::SetHandler() { void CefPrintDialogLinux::ReleaseHandler() { if (handler_.get()) { - handler_->OnPrintReset(); + CefRefPtr browser = extensions::GetOwnerBrowserForFrame( + context_->render_process_id(), context_->render_frame_id(), NULL); + + handler_->OnPrintReset(browser.get()); handler_ = NULL; } } @@ -266,9 +276,12 @@ bool CefPrintDialogLinux::UpdateSettings(printing::PrintSettings* settings, if (!handler_.get()) return false; + CefRefPtr browser = extensions::GetOwnerBrowserForFrame( + context_->render_process_id(), context_->render_frame_id(), NULL); + CefRefPtr settings_impl( new CefPrintSettingsImpl(settings, false, false)); - handler_->OnPrintSettings(settings_impl.get(), get_defaults); + handler_->OnPrintSettings(browser.get(), settings_impl.get(), get_defaults); settings_impl->Detach(NULL); context_->InitWithSettings(*settings); @@ -284,10 +297,13 @@ void CefPrintDialogLinux::SendDocumentToPrinter( return; } + CefRefPtr browser = extensions::GetOwnerBrowserForFrame( + context_->render_process_id(), context_->render_frame_id(), NULL); + CefRefPtr callback_impl( new CefPrintJobCallbackImpl(this)); - if (!handler_->OnPrintJob(document_name, path_to_pdf_.value(), + if (!handler_->OnPrintJob(browser.get(), document_name, path_to_pdf_.value(), callback_impl.get())) { callback_impl->Disconnect(); OnJobCompleted(); diff --git a/libcef_dll/cpptoc/print_handler_cpptoc.cc b/libcef_dll/cpptoc/print_handler_cpptoc.cc index 48ecd71e2..f82a03a09 100644 --- a/libcef_dll/cpptoc/print_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/print_handler_cpptoc.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=e2a9910119dcf81b74624588d222c7781e3fdc9a$ +// $hash=80fc869800987a74f4c6e4eb202f0f5201126a76$ // #include "libcef_dll/cpptoc/print_handler_cpptoc.h" @@ -42,6 +42,7 @@ print_handler_on_print_start(struct _cef_print_handler_t* self, void CEF_CALLBACK print_handler_on_print_settings(struct _cef_print_handler_t* self, + cef_browser_t* browser, struct _cef_print_settings_t* settings, int get_defaults) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING @@ -49,6 +50,10 @@ print_handler_on_print_settings(struct _cef_print_handler_t* self, DCHECK(self); if (!self) return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; // Verify param: settings; type: refptr_diff DCHECK(settings); if (!settings) @@ -56,11 +61,13 @@ print_handler_on_print_settings(struct _cef_print_handler_t* self, // Execute CefPrintHandlerCppToC::Get(self)->OnPrintSettings( - CefPrintSettingsCToCpp::Wrap(settings), get_defaults ? true : false); + CefBrowserCToCpp::Wrap(browser), CefPrintSettingsCToCpp::Wrap(settings), + get_defaults ? true : false); } int CEF_CALLBACK print_handler_on_print_dialog(struct _cef_print_handler_t* self, + cef_browser_t* browser, int has_selection, cef_print_dialog_callback_t* callback) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING @@ -68,6 +75,10 @@ print_handler_on_print_dialog(struct _cef_print_handler_t* self, DCHECK(self); if (!self) return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; // Verify param: callback; type: refptr_diff DCHECK(callback); if (!callback) @@ -75,7 +86,7 @@ print_handler_on_print_dialog(struct _cef_print_handler_t* self, // Execute bool _retval = CefPrintHandlerCppToC::Get(self)->OnPrintDialog( - has_selection ? true : false, + CefBrowserCToCpp::Wrap(browser), has_selection ? true : false, CefPrintDialogCallbackCToCpp::Wrap(callback)); // Return type: bool @@ -84,6 +95,7 @@ print_handler_on_print_dialog(struct _cef_print_handler_t* self, int CEF_CALLBACK print_handler_on_print_job(struct _cef_print_handler_t* self, + cef_browser_t* browser, const cef_string_t* document_name, const cef_string_t* pdf_file_path, cef_print_job_callback_t* callback) { @@ -92,6 +104,10 @@ print_handler_on_print_job(struct _cef_print_handler_t* self, DCHECK(self); if (!self) return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; // Verify param: document_name; type: string_byref_const DCHECK(document_name); if (!document_name) @@ -107,37 +123,48 @@ print_handler_on_print_job(struct _cef_print_handler_t* self, // Execute bool _retval = CefPrintHandlerCppToC::Get(self)->OnPrintJob( - CefString(document_name), CefString(pdf_file_path), - CefPrintJobCallbackCToCpp::Wrap(callback)); + CefBrowserCToCpp::Wrap(browser), CefString(document_name), + CefString(pdf_file_path), CefPrintJobCallbackCToCpp::Wrap(callback)); // Return type: bool return _retval; } void CEF_CALLBACK -print_handler_on_print_reset(struct _cef_print_handler_t* self) { +print_handler_on_print_reset(struct _cef_print_handler_t* self, + cef_browser_t* browser) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING DCHECK(self); if (!self) return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; // Execute - CefPrintHandlerCppToC::Get(self)->OnPrintReset(); + CefPrintHandlerCppToC::Get(self)->OnPrintReset( + CefBrowserCToCpp::Wrap(browser)); } cef_size_t CEF_CALLBACK print_handler_get_pdf_paper_size(struct _cef_print_handler_t* self, + cef_browser_t* browser, int device_units_per_inch) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING DCHECK(self); if (!self) return CefSize(); + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return CefSize(); // Execute - cef_size_t _retval = - CefPrintHandlerCppToC::Get(self)->GetPdfPaperSize(device_units_per_inch); + cef_size_t _retval = CefPrintHandlerCppToC::Get(self)->GetPdfPaperSize( + CefBrowserCToCpp::Wrap(browser), device_units_per_inch); // Return type: simple return _retval; diff --git a/libcef_dll/ctocpp/print_handler_ctocpp.cc b/libcef_dll/ctocpp/print_handler_ctocpp.cc index c8b1ee132..9e89d542a 100644 --- a/libcef_dll/ctocpp/print_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/print_handler_ctocpp.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=0749b78aaf8f69cd706962477d4d0241c93cf333$ +// $hash=80679bfc067e7564eadb691876081c4176b04c4f$ // #include "libcef_dll/ctocpp/print_handler_ctocpp.h" @@ -37,6 +37,7 @@ void CefPrintHandlerCToCpp::OnPrintStart(CefRefPtr browser) { } void CefPrintHandlerCToCpp::OnPrintSettings( + CefRefPtr browser, CefRefPtr settings, bool get_defaults) { cef_print_handler_t* _struct = GetStruct(); @@ -45,17 +46,23 @@ void CefPrintHandlerCToCpp::OnPrintSettings( // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; // Verify param: settings; type: refptr_diff DCHECK(settings.get()); if (!settings.get()) return; // Execute - _struct->on_print_settings(_struct, CefPrintSettingsCppToC::Wrap(settings), + _struct->on_print_settings(_struct, CefBrowserCppToC::Wrap(browser), + CefPrintSettingsCppToC::Wrap(settings), get_defaults); } bool CefPrintHandlerCToCpp::OnPrintDialog( + CefRefPtr browser, bool has_selection, CefRefPtr callback) { cef_print_handler_t* _struct = GetStruct(); @@ -64,6 +71,10 @@ bool CefPrintHandlerCToCpp::OnPrintDialog( // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; // Verify param: callback; type: refptr_diff DCHECK(callback.get()); if (!callback.get()) @@ -71,13 +82,15 @@ bool CefPrintHandlerCToCpp::OnPrintDialog( // Execute int _retval = _struct->on_print_dialog( - _struct, has_selection, CefPrintDialogCallbackCppToC::Wrap(callback)); + _struct, CefBrowserCppToC::Wrap(browser), has_selection, + CefPrintDialogCallbackCppToC::Wrap(callback)); // Return type: bool return _retval ? true : false; } bool CefPrintHandlerCToCpp::OnPrintJob( + CefRefPtr browser, const CefString& document_name, const CefString& pdf_file_path, CefRefPtr callback) { @@ -87,6 +100,10 @@ bool CefPrintHandlerCToCpp::OnPrintJob( // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; // Verify param: document_name; type: string_byref_const DCHECK(!document_name.empty()); if (document_name.empty()) @@ -102,34 +119,45 @@ bool CefPrintHandlerCToCpp::OnPrintJob( // Execute int _retval = _struct->on_print_job( - _struct, document_name.GetStruct(), pdf_file_path.GetStruct(), - CefPrintJobCallbackCppToC::Wrap(callback)); + _struct, CefBrowserCppToC::Wrap(browser), document_name.GetStruct(), + pdf_file_path.GetStruct(), CefPrintJobCallbackCppToC::Wrap(callback)); // Return type: bool return _retval ? true : false; } -void CefPrintHandlerCToCpp::OnPrintReset() { +void CefPrintHandlerCToCpp::OnPrintReset(CefRefPtr browser) { cef_print_handler_t* _struct = GetStruct(); if (CEF_MEMBER_MISSING(_struct, on_print_reset)) return; // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + // Execute - _struct->on_print_reset(_struct); + _struct->on_print_reset(_struct, CefBrowserCppToC::Wrap(browser)); } -CefSize CefPrintHandlerCToCpp::GetPdfPaperSize(int device_units_per_inch) { +CefSize CefPrintHandlerCToCpp::GetPdfPaperSize(CefRefPtr browser, + int device_units_per_inch) { cef_print_handler_t* _struct = GetStruct(); if (CEF_MEMBER_MISSING(_struct, get_pdf_paper_size)) return CefSize(); // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return CefSize(); + // Execute - cef_size_t _retval = - _struct->get_pdf_paper_size(_struct, device_units_per_inch); + cef_size_t _retval = _struct->get_pdf_paper_size( + _struct, CefBrowserCppToC::Wrap(browser), device_units_per_inch); // Return type: simple return _retval; diff --git a/libcef_dll/ctocpp/print_handler_ctocpp.h b/libcef_dll/ctocpp/print_handler_ctocpp.h index 767acf72a..de792ec04 100644 --- a/libcef_dll/ctocpp/print_handler_ctocpp.h +++ b/libcef_dll/ctocpp/print_handler_ctocpp.h @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=104e754c5019270e7bd700c6b979891f1275f9a7$ +// $hash=1a2adb6e9cbbe96253cc997312e60ca330dc4de6$ // #ifndef CEF_LIBCEF_DLL_CTOCPP_PRINT_HANDLER_CTOCPP_H_ @@ -34,15 +34,19 @@ class CefPrintHandlerCToCpp : public CefCToCppRefCounted browser) override; - void OnPrintSettings(CefRefPtr settings, + void OnPrintSettings(CefRefPtr browser, + CefRefPtr settings, bool get_defaults) override; - bool OnPrintDialog(bool has_selection, + bool OnPrintDialog(CefRefPtr browser, + bool has_selection, CefRefPtr callback) override; - bool OnPrintJob(const CefString& document_name, + bool OnPrintJob(CefRefPtr browser, + const CefString& document_name, const CefString& pdf_file_path, CefRefPtr callback) override; - void OnPrintReset() override; - CefSize GetPdfPaperSize(int device_units_per_inch) override; + void OnPrintReset(CefRefPtr browser) override; + CefSize GetPdfPaperSize(CefRefPtr browser, + int device_units_per_inch) override; }; #endif // CEF_LIBCEF_DLL_CTOCPP_PRINT_HANDLER_CTOCPP_H_ diff --git a/patch/patch.cfg b/patch/patch.cfg index e0b89445b..c661c56b2 100644 --- a/patch/patch.cfg +++ b/patch/patch.cfg @@ -324,4 +324,9 @@ patches = [ 'name': 'swiftshader_729532', 'path': 'third_party/swiftshader/', }, + { + # Linux: Attach routing IDs to PrintingContext. + # https://bitbucket.org/chromiumembedded/cef/issues/2196 + 'name': 'printing_context_2196', + }, ] diff --git a/patch/patches/printing_context_2196.patch b/patch/patches/printing_context_2196.patch new file mode 100644 index 000000000..93e202930 --- /dev/null +++ b/patch/patches/printing_context_2196.patch @@ -0,0 +1,41 @@ +diff --git chrome/browser/printing/print_job_worker.cc chrome/browser/printing/print_job_worker.cc +index d06b61a..f41f848 100644 +--- chrome/browser/printing/print_job_worker.cc ++++ chrome/browser/printing/print_job_worker.cc +@@ -121,6 +121,7 @@ PrintJobWorker::PrintJobWorker(int render_process_id, + printing_context_delegate_ = base::MakeUnique( + render_process_id, render_frame_id); + printing_context_ = PrintingContext::Create(printing_context_delegate_.get()); ++ printing_context_->set_render_ids(render_process_id, render_frame_id); + } + + PrintJobWorker::~PrintJobWorker() { +diff --git printing/printing_context.h printing/printing_context.h +index 7054654..ed5b664 100644 +--- printing/printing_context.h ++++ printing/printing_context.h +@@ -127,6 +127,13 @@ class PRINTING_EXPORT PrintingContext { + + int job_id() const { return job_id_; } + ++ void set_render_ids(int render_process_id, int render_frame_id) { ++ render_process_id_ = render_process_id; ++ render_frame_id_ = render_frame_id; ++ } ++ int render_process_id() const { return render_process_id_; } ++ int render_frame_id() const { return render_frame_id_; } ++ + protected: + explicit PrintingContext(Delegate* delegate); + +@@ -151,6 +158,10 @@ class PRINTING_EXPORT PrintingContext { + // The job id for the current job. The value is 0 if no jobs are active. + int job_id_; + ++ // Routing IDs for the frame that owns this object. ++ int render_process_id_ = 0; ++ int render_frame_id_ = 0; ++ + private: + DISALLOW_COPY_AND_ASSIGN(PrintingContext); + }; diff --git a/tests/cefclient/browser/print_handler_gtk.cc b/tests/cefclient/browser/print_handler_gtk.cc index 7288a7d46..263e4546a 100644 --- a/tests/cefclient/browser/print_handler_gtk.cc +++ b/tests/cefclient/browser/print_handler_gtk.cc @@ -7,10 +7,15 @@ #include +#include +#include + #include "include/base/cef_logging.h" #include "include/base/cef_macros.h" #include "include/wrapper/cef_helpers.h" +#include "tests/cefclient/browser/root_window.h" + namespace client { namespace { @@ -267,161 +272,328 @@ void InitPrintSettings(GtkPrintSettings* settings, } // namespace -ClientPrintHandlerGtk::ClientPrintHandlerGtk() - : dialog_(NULL), gtk_settings_(NULL), page_setup_(NULL), printer_(NULL) {} +struct ClientPrintHandlerGtk::PrintHandler { + PrintHandler(CefRefPtr browser) + : browser_(browser), + dialog_(NULL), + gtk_settings_(NULL), + page_setup_(NULL), + printer_(NULL) {} -void ClientPrintHandlerGtk::OnPrintStart(CefRefPtr browser) {} - -void ClientPrintHandlerGtk::OnPrintSettings( - CefRefPtr settings, - bool get_defaults) { - if (get_defaults) { - DCHECK(!page_setup_); - DCHECK(!printer_); - - // |gtk_settings_| is a new copy. - gtk_settings_ = gtk_print_settings_copy(GetLastUsedSettings()->settings()); - page_setup_ = gtk_page_setup_new(); - } else { - if (!gtk_settings_) { - gtk_settings_ = - gtk_print_settings_copy(GetLastUsedSettings()->settings()); + ~PrintHandler() { + if (dialog_) { + gtk_widget_destroy(dialog_); + dialog_ = NULL; + } + if (gtk_settings_) { + g_object_unref(gtk_settings_); + gtk_settings_ = NULL; + } + if (page_setup_) { + g_object_unref(page_setup_); + page_setup_ = NULL; } - - GtkPrinterList* printer_list = new GtkPrinterList; - printer_ = printer_list->GetPrinterWithName(settings->GetDeviceName()); if (printer_) { - g_object_ref(printer_); - gtk_print_settings_set_printer(gtk_settings_, - gtk_printer_get_name(printer_)); - if (!page_setup_) { - page_setup_ = gtk_printer_get_default_page_size(printer_); - } + g_object_unref(printer_); + printer_ = NULL; } - - gtk_print_settings_set_n_copies(gtk_settings_, settings->GetCopies()); - gtk_print_settings_set_collate(gtk_settings_, settings->WillCollate()); - - std::string color_value; - std::string color_setting_name; - GetColorModelForMode(settings->GetColorModel(), &color_setting_name, - &color_value); - gtk_print_settings_set(gtk_settings_, color_setting_name.c_str(), - color_value.c_str()); - - if (settings->GetDuplexMode() != DUPLEX_MODE_UNKNOWN) { - const char* cups_duplex_mode = NULL; - switch (settings->GetDuplexMode()) { - case DUPLEX_MODE_LONG_EDGE: - cups_duplex_mode = kDuplexNoTumble; - break; - case DUPLEX_MODE_SHORT_EDGE: - cups_duplex_mode = kDuplexTumble; - break; - case DUPLEX_MODE_SIMPLEX: - cups_duplex_mode = kDuplexNone; - break; - default: // UNKNOWN_DUPLEX_MODE - NOTREACHED(); - break; - } - gtk_print_settings_set(gtk_settings_, kCUPSDuplex, cups_duplex_mode); - } - - if (!page_setup_) - page_setup_ = gtk_page_setup_new(); - - gtk_print_settings_set_orientation( - gtk_settings_, settings->IsLandscape() ? GTK_PAGE_ORIENTATION_LANDSCAPE - : GTK_PAGE_ORIENTATION_PORTRAIT); - - delete printer_list; } - InitPrintSettings(gtk_settings_, page_setup_, settings); + void OnPrintSettings(CefRefPtr settings, + bool get_defaults) { + if (get_defaults) { + DCHECK(!page_setup_); + DCHECK(!printer_); + + // |gtk_settings_| is a new copy. + gtk_settings_ = + gtk_print_settings_copy(GetLastUsedSettings()->settings()); + page_setup_ = gtk_page_setup_new(); + } else { + if (!gtk_settings_) { + gtk_settings_ = + gtk_print_settings_copy(GetLastUsedSettings()->settings()); + } + + GtkPrinterList* printer_list = new GtkPrinterList; + printer_ = printer_list->GetPrinterWithName(settings->GetDeviceName()); + if (printer_) { + g_object_ref(printer_); + gtk_print_settings_set_printer(gtk_settings_, + gtk_printer_get_name(printer_)); + if (!page_setup_) { + page_setup_ = gtk_printer_get_default_page_size(printer_); + } + } + + gtk_print_settings_set_n_copies(gtk_settings_, settings->GetCopies()); + gtk_print_settings_set_collate(gtk_settings_, settings->WillCollate()); + + std::string color_value; + std::string color_setting_name; + GetColorModelForMode(settings->GetColorModel(), &color_setting_name, + &color_value); + gtk_print_settings_set(gtk_settings_, color_setting_name.c_str(), + color_value.c_str()); + + if (settings->GetDuplexMode() != DUPLEX_MODE_UNKNOWN) { + const char* cups_duplex_mode = NULL; + switch (settings->GetDuplexMode()) { + case DUPLEX_MODE_LONG_EDGE: + cups_duplex_mode = kDuplexNoTumble; + break; + case DUPLEX_MODE_SHORT_EDGE: + cups_duplex_mode = kDuplexTumble; + break; + case DUPLEX_MODE_SIMPLEX: + cups_duplex_mode = kDuplexNone; + break; + default: // UNKNOWN_DUPLEX_MODE + NOTREACHED(); + break; + } + gtk_print_settings_set(gtk_settings_, kCUPSDuplex, cups_duplex_mode); + } + + if (!page_setup_) + page_setup_ = gtk_page_setup_new(); + + gtk_print_settings_set_orientation(gtk_settings_, + settings->IsLandscape() + ? GTK_PAGE_ORIENTATION_LANDSCAPE + : GTK_PAGE_ORIENTATION_PORTRAIT); + + delete printer_list; + } + + InitPrintSettings(gtk_settings_, page_setup_, settings); + } + + bool OnPrintDialog(bool has_selection, + CefRefPtr callback) { + dialog_callback_ = callback; + + GtkWindow* parent = GetWindow(); + // TODO(estade): We need a window title here. + dialog_ = gtk_print_unix_dialog_new(NULL, parent); + g_signal_connect(dialog_, "delete-event", + G_CALLBACK(gtk_widget_hide_on_delete), NULL); + + // 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( + 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_), + TRUE); + gtk_print_unix_dialog_set_support_selection(GTK_PRINT_UNIX_DIALOG(dialog_), + TRUE); + gtk_print_unix_dialog_set_has_selection(GTK_PRINT_UNIX_DIALOG(dialog_), + has_selection); + gtk_print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(dialog_), + gtk_settings_); + g_signal_connect(dialog_, "response", G_CALLBACK(OnDialogResponseThunk), + this); + gtk_widget_show(dialog_); + + return true; + } + + bool OnPrintJob(const CefString& document_name, + const CefString& pdf_file_path, + CefRefPtr callback) { + // If |printer_| is NULL then somehow the GTK printer list changed out under + // us. In which case, just bail out. + if (!printer_) + return false; + + job_callback_ = callback; + + // Save the settings for next time. + GetLastUsedSettings()->SetLastUsedSettings(gtk_settings_); + + GtkPrintJob* print_job = gtk_print_job_new( + document_name.ToString().c_str(), printer_, gtk_settings_, page_setup_); + gtk_print_job_set_source_file(print_job, pdf_file_path.ToString().c_str(), + NULL); + gtk_print_job_send(print_job, OnJobCompletedThunk, this, NULL); + + return true; + } + + private: + // Returns the GtkWindow* for the browser. Will return NULL when using the + // Views framework. + GtkWindow* GetWindow() { + scoped_refptr root_window = + RootWindow::GetForBrowser(browser_->GetIdentifier()); + if (root_window) + return GTK_WINDOW(root_window->GetWindowHandle()); + return NULL; + } + + void OnDialogResponse(GtkDialog* dialog, gint response_id) { + int num_matched_handlers = g_signal_handlers_disconnect_by_func( + dialog_, reinterpret_cast(&OnDialogResponseThunk), this); + DCHECK_EQ(1, num_matched_handlers); + + gtk_widget_hide(dialog_); + + switch (response_id) { + case GTK_RESPONSE_OK: { + if (gtk_settings_) + g_object_unref(gtk_settings_); + gtk_settings_ = + gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog_)); + + if (printer_) + g_object_unref(printer_); + printer_ = gtk_print_unix_dialog_get_selected_printer( + GTK_PRINT_UNIX_DIALOG(dialog_)); + g_object_ref(printer_); + + if (page_setup_) + g_object_unref(page_setup_); + page_setup_ = gtk_print_unix_dialog_get_page_setup( + GTK_PRINT_UNIX_DIALOG(dialog_)); + g_object_ref(page_setup_); + + // Handle page ranges. + CefPrintSettings::PageRangeList ranges_vector; + gint num_ranges; + bool print_selection_only = false; + switch (gtk_print_settings_get_print_pages(gtk_settings_)) { + case GTK_PRINT_PAGES_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) { + ranges_vector.push_back( + CefRange(gtk_range[i].start, gtk_range[i].end)); + } + g_free(gtk_range); + } + break; + } + case GTK_PRINT_PAGES_SELECTION: + print_selection_only = true; + break; + case GTK_PRINT_PAGES_ALL: + // Leave |ranges_vector| empty to indicate print all pages. + break; + case GTK_PRINT_PAGES_CURRENT: + default: + NOTREACHED(); + break; + } + + CefRefPtr settings = CefPrintSettings::Create(); + settings->SetPageRanges(ranges_vector); + settings->SetSelectionOnly(print_selection_only); + InitPrintSettings(gtk_settings_, page_setup_, settings); + dialog_callback_->Continue(settings); + dialog_callback_ = NULL; + return; + } + case GTK_RESPONSE_DELETE_EVENT: // Fall through. + case GTK_RESPONSE_CANCEL: { + dialog_callback_->Cancel(); + dialog_callback_ = NULL; + return; + } + case GTK_RESPONSE_APPLY: + default: { NOTREACHED(); } + } + } + + void OnJobCompleted(GtkPrintJob* print_job, GError* error) { + job_callback_->Continue(); + job_callback_ = NULL; + } + + static void OnDialogResponseThunk(GtkDialog* dialog, + gint response_id, + PrintHandler* handler) { + handler->OnDialogResponse(dialog, response_id); + } + + static void OnJobCompletedThunk(GtkPrintJob* print_job, + void* handler, + GError* error) { + static_cast(handler)->OnJobCompleted(print_job, error); + } + + CefRefPtr browser_; + + GtkWidget* dialog_; // Owned. + GtkPrintSettings* gtk_settings_; // Referenced. + GtkPageSetup* page_setup_; // Referenced. + GtkPrinter* printer_; // Referenced. + + CefRefPtr dialog_callback_; + CefRefPtr job_callback_; +}; + +ClientPrintHandlerGtk::ClientPrintHandlerGtk() {} + +ClientPrintHandlerGtk::~ClientPrintHandlerGtk() { + DCHECK(print_handler_map_.empty()); +} + +void ClientPrintHandlerGtk::OnPrintStart(CefRefPtr browser) { + const int browser_id = browser->GetIdentifier(); + +#ifndef _NDEBUG + // Print handler should not already exist for the browser. + PrintHandlerMap::const_iterator it = print_handler_map_.find(browser_id); + DCHECK(it == print_handler_map_.end()); +#endif + + // Create a new print handler. + PrintHandler* ph = new PrintHandler(browser); + print_handler_map_.insert(std::make_pair(browser_id, ph)); +} + +void ClientPrintHandlerGtk::OnPrintSettings( + CefRefPtr browser, + CefRefPtr settings, + bool get_defaults) { + GetPrintHandler(browser)->OnPrintSettings(settings, get_defaults); } bool ClientPrintHandlerGtk::OnPrintDialog( + CefRefPtr browser, bool has_selection, CefRefPtr callback) { - dialog_callback_ = callback; - - // TODO(cef): Identify the correct parent window. - GtkWindow* parent = NULL; - // TODO(estade): We need a window title here. - dialog_ = gtk_print_unix_dialog_new(NULL, parent); - g_signal_connect(dialog_, "delete-event", - G_CALLBACK(gtk_widget_hide_on_delete), NULL); - - // 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( - 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_), - TRUE); - gtk_print_unix_dialog_set_support_selection(GTK_PRINT_UNIX_DIALOG(dialog_), - TRUE); - gtk_print_unix_dialog_set_has_selection(GTK_PRINT_UNIX_DIALOG(dialog_), - has_selection); - gtk_print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(dialog_), - gtk_settings_); - g_signal_connect(dialog_, "response", G_CALLBACK(OnDialogResponseThunk), - this); - gtk_widget_show(dialog_); - - return true; + return GetPrintHandler(browser)->OnPrintDialog(has_selection, callback); } bool ClientPrintHandlerGtk::OnPrintJob( + CefRefPtr browser, const CefString& document_name, const CefString& pdf_file_path, CefRefPtr callback) { - // If |printer_| is NULL then somehow the GTK printer list changed out under - // us. In which case, just bail out. - if (!printer_) - return false; - - job_callback_ = callback; - - // Save the settings for next time. - GetLastUsedSettings()->SetLastUsedSettings(gtk_settings_); - - GtkPrintJob* print_job = gtk_print_job_new( - document_name.ToString().c_str(), printer_, gtk_settings_, page_setup_); - gtk_print_job_set_source_file(print_job, pdf_file_path.ToString().c_str(), - NULL); - gtk_print_job_send(print_job, OnJobCompletedThunk, this, NULL); - - return true; + return GetPrintHandler(browser)->OnPrintJob(document_name, pdf_file_path, + callback); } -void ClientPrintHandlerGtk::OnPrintReset() { - if (dialog_) { - gtk_widget_destroy(dialog_); - dialog_ = NULL; - } - if (gtk_settings_) { - g_object_unref(gtk_settings_); - gtk_settings_ = NULL; - } - if (page_setup_) { - g_object_unref(page_setup_); - page_setup_ = NULL; - } - if (printer_) { - g_object_unref(printer_); - printer_ = NULL; - } +void ClientPrintHandlerGtk::OnPrintReset(CefRefPtr browser) { + // Delete the print handler. + PrintHandlerMap::iterator it = + print_handler_map_.find(browser->GetIdentifier()); + DCHECK(it != print_handler_map_.end()); + delete it->second; + print_handler_map_.erase(it); } -CefSize ClientPrintHandlerGtk::GetPdfPaperSize(int device_units_per_inch) { +CefSize ClientPrintHandlerGtk::GetPdfPaperSize(CefRefPtr browser, + int device_units_per_inch) { GtkPageSetup* page_setup = gtk_page_setup_new(); float width = gtk_page_setup_get_paper_width(page_setup, GTK_UNIT_INCH); @@ -432,85 +604,12 @@ CefSize ClientPrintHandlerGtk::GetPdfPaperSize(int device_units_per_inch) { return CefSize(width * device_units_per_inch, height * device_units_per_inch); } -void ClientPrintHandlerGtk::OnDialogResponse(GtkDialog* dialog, - gint response_id) { - int num_matched_handlers = g_signal_handlers_disconnect_by_func( - dialog_, reinterpret_cast(&OnDialogResponseThunk), this); - DCHECK_EQ(1, num_matched_handlers); - - gtk_widget_hide(dialog_); - - switch (response_id) { - case GTK_RESPONSE_OK: { - if (gtk_settings_) - g_object_unref(gtk_settings_); - gtk_settings_ = - gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog_)); - - if (printer_) - g_object_unref(printer_); - printer_ = gtk_print_unix_dialog_get_selected_printer( - GTK_PRINT_UNIX_DIALOG(dialog_)); - g_object_ref(printer_); - - if (page_setup_) - g_object_unref(page_setup_); - page_setup_ = - gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(dialog_)); - g_object_ref(page_setup_); - - // Handle page ranges. - CefPrintSettings::PageRangeList ranges_vector; - gint num_ranges; - bool print_selection_only = false; - switch (gtk_print_settings_get_print_pages(gtk_settings_)) { - case GTK_PRINT_PAGES_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) { - ranges_vector.push_back( - CefRange(gtk_range[i].start, gtk_range[i].end)); - } - g_free(gtk_range); - } - break; - } - case GTK_PRINT_PAGES_SELECTION: - print_selection_only = true; - break; - case GTK_PRINT_PAGES_ALL: - // Leave |ranges_vector| empty to indicate print all pages. - break; - case GTK_PRINT_PAGES_CURRENT: - default: - NOTREACHED(); - break; - } - - CefRefPtr settings = CefPrintSettings::Create(); - settings->SetPageRanges(ranges_vector); - settings->SetSelectionOnly(print_selection_only); - InitPrintSettings(gtk_settings_, page_setup_, settings); - dialog_callback_->Continue(settings); - dialog_callback_ = NULL; - return; - } - case GTK_RESPONSE_DELETE_EVENT: // Fall through. - case GTK_RESPONSE_CANCEL: { - dialog_callback_->Cancel(); - dialog_callback_ = NULL; - return; - } - case GTK_RESPONSE_APPLY: - default: { NOTREACHED(); } - } -} - -void ClientPrintHandlerGtk::OnJobCompleted(GtkPrintJob* print_job, - GError* error) { - job_callback_->Continue(); - job_callback_ = NULL; +ClientPrintHandlerGtk::PrintHandler* ClientPrintHandlerGtk::GetPrintHandler( + CefRefPtr browser) { + PrintHandlerMap::const_iterator it = + print_handler_map_.find(browser->GetIdentifier()); + DCHECK(it != print_handler_map_.end()); + return it->second; } } // namespace client diff --git a/tests/cefclient/browser/print_handler_gtk.h b/tests/cefclient/browser/print_handler_gtk.h index 53046612c..0aa8f85a2 100644 --- a/tests/cefclient/browser/print_handler_gtk.h +++ b/tests/cefclient/browser/print_handler_gtk.h @@ -7,8 +7,7 @@ #define CEF_TESTS_CEFCLIENT_BROWSER_PRINT_HANDLER_GTK_H_ #pragma once -#include -#include +#include #include "include/cef_print_handler.h" @@ -17,44 +16,32 @@ namespace client { class ClientPrintHandlerGtk : public CefPrintHandler { public: ClientPrintHandlerGtk(); + virtual ~ClientPrintHandlerGtk(); // CefPrintHandler methods. void OnPrintStart(CefRefPtr browser) OVERRIDE; - void OnPrintSettings(CefRefPtr settings, + void OnPrintSettings(CefRefPtr browser, + CefRefPtr settings, bool get_defaults) OVERRIDE; - bool OnPrintDialog(bool has_selection, + bool OnPrintDialog(CefRefPtr browser, + bool has_selection, CefRefPtr callback) OVERRIDE; - bool OnPrintJob(const CefString& document_name, + bool OnPrintJob(CefRefPtr browser, + const CefString& document_name, const CefString& pdf_file_path, CefRefPtr callback) OVERRIDE; - void OnPrintReset() OVERRIDE; - CefSize GetPdfPaperSize(int device_units_per_inch) OVERRIDE; + void OnPrintReset(CefRefPtr browser) OVERRIDE; + CefSize GetPdfPaperSize(CefRefPtr browser, + int device_units_per_inch) OVERRIDE; private: - void OnDialogResponse(GtkDialog* dialog, gint response_id); - void OnJobCompleted(GtkPrintJob* print_job, GError* error); + // Print handler. + struct PrintHandler; + PrintHandler* GetPrintHandler(CefRefPtr browser); - static void OnDialogResponseThunk(GtkDialog* dialog, - gint response_id, - ClientPrintHandlerGtk* handler) { - handler->OnDialogResponse(dialog, response_id); - } - static void OnJobCompletedThunk(GtkPrintJob* print_job, - void* handler, - GError* error) { - static_cast(handler)->OnJobCompleted(print_job, - error); - } - - // Print dialog settings. ClientPrintHandlerGtk owns |dialog_| and holds - // references to the other objects. - GtkWidget* dialog_; - GtkPrintSettings* gtk_settings_; - GtkPageSetup* page_setup_; - GtkPrinter* printer_; - - CefRefPtr dialog_callback_; - CefRefPtr job_callback_; + // Map of browser ID to print handler. + typedef std::map PrintHandlerMap; + PrintHandlerMap print_handler_map_; IMPLEMENT_REFCOUNTING(ClientPrintHandlerGtk); DISALLOW_COPY_AND_ASSIGN(ClientPrintHandlerGtk);