chromiumembedded / cef

Chromium Embedded Framework (CEF). A simple framework for embedding Chromium-based browsers in other applications.
https://bitbucket.org/chromiumembedded/cef/
Other
3.38k stars 467 forks source link

Support CefPrintHandler on Chrome-Runtime Linux #3729

Closed edgardogho closed 1 month ago

edgardogho commented 4 months ago

Is your feature request related to a problem? Please describe. Using chrome runtime on Linux with Alloy Style, CefPrintHandler does not capture print events when calling GetHost()->Print() or a print is initiated on HTML side. If chrome runtime is not enabled CefPrintHandler works fine.

Describe the solution you'd like It would be good to support CefPrintHandler on linux with chrome runtime so we can capture print events before they reach the OS print dialog

Describe alternatives you've considered The GetHost()->PrintToPDF(...) works fine using chrome-runtime (linux) and it provides a callback to inform when PDF is created, but when a print starts on HTML side this is not called by default.

magreenblatt commented 4 months ago

Running cefclient --use-client-dialogs --use-alloy-style --use-native at M127 I can confirm no calls to ClientPrintHandlerGtk::OnPrintStart.

magreenblatt commented 4 months ago

The below change at current master/M127 adds the call to CefPrintHandler, however the actual printing on Ubuntu 22 (using the above cefclient command-line) is failing for me with the following errors:

4879:4879:0705/142903.490653:ERROR:print_backend_service_impl.cc(286)] Failure rendering document 5, error: kFailed
[4750:4750:0705/142903.491246:ERROR:device_event_log_impl.cc(196)] [14:29:03.490] Printer: print_job_worker_oop.cc:191 Error rendering printed document via service for document 5: kFailed
[4750:4750:0705/142903.708746:ERROR:device_event_log_impl.cc(196)] [14:29:03.708] Printer: print_error_dialog.cc:61 Something went wrong when trying to print.  Please check your printer and try again.

Printing succeeds when using the default print dialog. I'm going to hold off on merging this change until someone has time to debug and fix the printing issue in cefclient (contributions welcome!).

diff --git libcef/browser/chrome/chrome_browser_main_extra_parts_cef.cc libcef/browser/chrome/chrome_browser_main_extra_parts_cef.cc
index f04ee109c..b85ef8a3a 100644
--- libcef/browser/chrome/chrome_browser_main_extra_parts_cef.cc
+++ libcef/browser/chrome/chrome_browser_main_extra_parts_cef.cc
@@ -17,6 +17,7 @@

 #if BUILDFLAG(IS_LINUX)
 #include "base/linux_util.h"
+#include "cef/libcef/browser/printing/print_dialog_linux.h"
 #endif

 #if BUILDFLAG(IS_WIN)
@@ -83,4 +84,11 @@ void ChromeBrowserMainExtraPartsCef::ToolkitInitialized() {
   // Override the default Chrome client.
   SetConstrainedWindowViewsClient(CreateAlloyConstrainedWindowViewsClient(
       CreateChromeConstrainedWindowViewsClient()));
+
+#if BUILDFLAG(IS_LINUX)
+  auto printing_delegate = new CefPrintingContextLinuxDelegate();
+  auto default_delegate =
+      ui::PrintingContextLinuxDelegate::SetInstance(printing_delegate);
+  printing_delegate->SetDefaultDelegate(default_delegate);
+#endif  // BUILDFLAG(IS_LINUX)
 }
edgardogho commented 2 months ago

Using this patch on branch 6668 I was able to print triggering the print event from the HTML side. This is on ubuntu 20 and ubuntu 22 running cefclient --use-alloy-style. It also worked on my c++ app using cef.

shagkur commented 1 month ago

Seems this issue is kind of releated to enable_oop_printing=true (which, for 6668, is the default). Building CEF/chromium with this flag disabled, and the above patch applied, makes the printhandler work as expected. Not sure if this can be "fixed" at all. As with this flag enabled the printing is delegated (as it says out-of-process). Finally it ends up in /chrome/services/printing/print_backend_service_impl.cc:EstablishPrintingContext. And constructs there fresh PrintingContextDelegate(s) and PrintingContext(s).

shagkur commented 1 month ago

More detailed analysis: In /chrome/services/printing/print_backend_service_impl.cc:Init the following code is creating a new instance of the LinuxUi (other process). No PrintContextLinuxDelegate is previously set (nil). Using the implementation (in this case of print_dialog_gtk.cc) of CreatePrintDialog.

#if BUILDFLAG(IS_LINUX)
  // Test framework already initializes the UI, so this should not go in
  // `InitCommon()`.  Additionally, low-level Linux UI is not needed when tests
  // are using `TestPrintingContext`.
  InstantiateLinuxUiDelegate();
  ui::LinuxUi::SetInstance(ui::GetDefaultLinuxUi());
#endif  // BUILDFLAG(IS_LINUX)

Not sure how this can be solved to set the CefPrintingContextLinuxDelegate in the printing process. @magreenblatt

magreenblatt commented 1 month ago

Thanks for the analysis.

Seems this issue is kind of releated to enable_oop_printing=true (which, for 6668, is the default). Building CEF/chromium with this flag disabled, and the above patch applied, makes the printhandler work as expected.

Adding --disable-features=EnableOopPrintDrivers on the command-line might also work.

Not sure how this can be solved to set the CefPrintingContextLinuxDelegate in the printing process.

I don't think implementing CefPrintingContextLinuxDelegate in the printing process is a viable option currently, as we would need to implement a new Mojo interface for communicating the callbacks to/from the browser process. Applying the patch and building/running with the above setting is probably the best option for now.

magreenblatt commented 1 month ago

Running cefclient --use-client-dialogs --use-alloy-style --use-native --ozone-platform=x11 --disable-features=EnableOopPrintDrivers works for me after applying the patch (tested at M130).

edgardogho commented 3 weeks ago

Can confirm CefPrintHandler works as expected on latest M130 (gfc42567) on linux with alloy-style.