Title: [159048] releases/WebKitGTK/webkit-2.2/Source/WebKit2
Revision
159048
Author
carlo...@webkit.org
Date
2013-11-11 02:13:26 -0800 (Mon, 11 Nov 2013)

Log Message

Merge r159042 - [GTK] Crash when printing via _javascript_ in WebKit2
https://bugs.webkit.org/show_bug.cgi?id=124043

Reviewed by Martin Robinson.

It happens because the print operation when started by the
WebProcess due to a DOM operation is supposed to be synchronous
and our print operation is always asynchronous. This is currently
handled only in the UI process because other ports print
synchronously in the WebProcess. In the GTK+ port we need to
notify the WebProcess that the print operation should run
synchronously when request by a DOM operation. Together with the
print settings and page setup we now send a print mode that can be
sync or async. When printing in sync mode we run a nested main loop
for the print operation, making sure that print sources have a
higher priority.

* Shared/PrintInfo.cpp:
(WebKit::PrintInfo::encode): Encode the print mode.
(WebKit::PrintInfo::decode): Decode the print mode.
* Shared/PrintInfo.h: Add PrintMode enum.
* Shared/gtk/PrintInfoGtk.cpp:
(WebKit::PrintInfo::PrintInfo): Initialize print mode.
* UIProcess/API/gtk/WebKitPrintOperation.cpp:
(drawPagesForPrintingCompleted): Do not call endPrinting() when
printing synchronously because WebPageProxy already calls it right
after sending the message to the WebProcess.
(webkitPrintOperationPrintPagesForFrame): Create the PrintInfo
struct with a print mode.
(webkitPrintOperationSetPrintMode): Helper private function to set
the print mode of the print operation.
* UIProcess/API/gtk/WebKitPrintOperationPrivate.h:
* UIProcess/API/gtk/WebKitWebView.cpp:
(webkitWebViewPrintFrame): Set sync print mode when printing due
to a UIClient request.
* WebProcess/WebPage/gtk/WebPrintOperationGtk.cpp:
(WebKit::PrintPagesData::PrintPagesData): Create a main loop when
printing synchronously.
(WebKit::WebPrintOperationGtk::WebPrintOperationGtk): Initialize
print mode.
(WebKit::WebPrintOperationGtk::printPagesIdleDone): Finish the
nested main loop when printing synchronously.
(WebKit::WebPrintOperationGtk::print): Run a nested main loop when
printing synchronously.
* WebProcess/WebPage/gtk/WebPrintOperationGtk.h:
(WebKit::WebPrintOperationGtk::printMode): Return the print mode.

Modified Paths

Diff

Modified: releases/WebKitGTK/webkit-2.2/Source/WebKit2/ChangeLog (159047 => 159048)


--- releases/WebKitGTK/webkit-2.2/Source/WebKit2/ChangeLog	2013-11-11 10:10:02 UTC (rev 159047)
+++ releases/WebKitGTK/webkit-2.2/Source/WebKit2/ChangeLog	2013-11-11 10:13:26 UTC (rev 159048)
@@ -1,3 +1,52 @@
+2013-11-11  Carlos Garcia Campos  <cgar...@igalia.com>
+
+        [GTK] Crash when printing via _javascript_ in WebKit2
+        https://bugs.webkit.org/show_bug.cgi?id=124043
+
+        Reviewed by Martin Robinson.
+
+        It happens because the print operation when started by the
+        WebProcess due to a DOM operation is supposed to be synchronous
+        and our print operation is always asynchronous. This is currently
+        handled only in the UI process because other ports print
+        synchronously in the WebProcess. In the GTK+ port we need to
+        notify the WebProcess that the print operation should run
+        synchronously when request by a DOM operation. Together with the
+        print settings and page setup we now send a print mode that can be
+        sync or async. When printing in sync mode we run a nested main loop
+        for the print operation, making sure that print sources have a
+        higher priority.
+
+        * Shared/PrintInfo.cpp:
+        (WebKit::PrintInfo::encode): Encode the print mode.
+        (WebKit::PrintInfo::decode): Decode the print mode.
+        * Shared/PrintInfo.h: Add PrintMode enum.
+        * Shared/gtk/PrintInfoGtk.cpp:
+        (WebKit::PrintInfo::PrintInfo): Initialize print mode.
+        * UIProcess/API/gtk/WebKitPrintOperation.cpp:
+        (drawPagesForPrintingCompleted): Do not call endPrinting() when
+        printing synchronously because WebPageProxy already calls it right
+        after sending the message to the WebProcess.
+        (webkitPrintOperationPrintPagesForFrame): Create the PrintInfo
+        struct with a print mode.
+        (webkitPrintOperationSetPrintMode): Helper private function to set
+        the print mode of the print operation.
+        * UIProcess/API/gtk/WebKitPrintOperationPrivate.h:
+        * UIProcess/API/gtk/WebKitWebView.cpp:
+        (webkitWebViewPrintFrame): Set sync print mode when printing due
+        to a UIClient request.
+        * WebProcess/WebPage/gtk/WebPrintOperationGtk.cpp:
+        (WebKit::PrintPagesData::PrintPagesData): Create a main loop when
+        printing synchronously.
+        (WebKit::WebPrintOperationGtk::WebPrintOperationGtk): Initialize
+        print mode.
+        (WebKit::WebPrintOperationGtk::printPagesIdleDone): Finish the
+        nested main loop when printing synchronously.
+        (WebKit::WebPrintOperationGtk::print): Run a nested main loop when
+        printing synchronously.
+        * WebProcess/WebPage/gtk/WebPrintOperationGtk.h:
+        (WebKit::WebPrintOperationGtk::printMode): Return the print mode.
+
 2013-11-10  Carlos Garcia Campos  <cgar...@igalia.com>
 
         [GTK] [WebKit2] Crash when printing to a file via _javascript_

Modified: releases/WebKitGTK/webkit-2.2/Source/WebKit2/Shared/PrintInfo.cpp (159047 => 159048)


--- releases/WebKitGTK/webkit-2.2/Source/WebKit2/Shared/PrintInfo.cpp	2013-11-11 10:10:02 UTC (rev 159047)
+++ releases/WebKitGTK/webkit-2.2/Source/WebKit2/Shared/PrintInfo.cpp	2013-11-11 10:13:26 UTC (rev 159048)
@@ -52,6 +52,7 @@
 #if PLATFORM(GTK)
     CoreIPC::encode(encoder, printSettings.get());
     CoreIPC::encode(encoder, pageSetup.get());
+    encoder.encodeEnum(printMode);
 #endif
 }
 
@@ -69,6 +70,8 @@
         return false;
     if (!CoreIPC::decode(decoder, info.pageSetup))
         return false;
+    if (!decoder.decodeEnum(info.printMode))
+        return false;
 #endif
 
     return true;

Modified: releases/WebKitGTK/webkit-2.2/Source/WebKit2/Shared/PrintInfo.h (159047 => 159048)


--- releases/WebKitGTK/webkit-2.2/Source/WebKit2/Shared/PrintInfo.h	2013-11-11 10:10:02 UTC (rev 159047)
+++ releases/WebKitGTK/webkit-2.2/Source/WebKit2/Shared/PrintInfo.h	2013-11-11 10:13:26 UTC (rev 159048)
@@ -47,7 +47,12 @@
 struct PrintInfo {
     PrintInfo();
 #if PLATFORM(GTK)
-    explicit PrintInfo(GtkPrintSettings*, GtkPageSetup*);
+    enum PrintMode {
+        PrintModeAsync,
+        PrintModeSync
+    };
+
+    explicit PrintInfo(GtkPrintSettings*, GtkPageSetup*, PrintMode = PrintModeAsync);
 #else
     explicit PrintInfo(NSPrintInfo *);
 #endif
@@ -59,6 +64,7 @@
 #if PLATFORM(GTK)
     GRefPtr<GtkPrintSettings> printSettings;
     GRefPtr<GtkPageSetup> pageSetup;
+    PrintMode printMode;
 #endif
 
     void encode(CoreIPC::ArgumentEncoder&) const;

Modified: releases/WebKitGTK/webkit-2.2/Source/WebKit2/Shared/gtk/PrintInfoGtk.cpp (159047 => 159048)


--- releases/WebKitGTK/webkit-2.2/Source/WebKit2/Shared/gtk/PrintInfoGtk.cpp	2013-11-11 10:10:02 UTC (rev 159047)
+++ releases/WebKitGTK/webkit-2.2/Source/WebKit2/Shared/gtk/PrintInfoGtk.cpp	2013-11-11 10:13:26 UTC (rev 159048)
@@ -30,12 +30,13 @@
 
 namespace WebKit {
 
-PrintInfo::PrintInfo(GtkPrintSettings* settings, GtkPageSetup* pageSetup)
+PrintInfo::PrintInfo(GtkPrintSettings* settings, GtkPageSetup* pageSetup, PrintMode printMode)
     : pageSetupScaleFactor(gtk_print_settings_get_scale(settings) / 100.0)
     , availablePaperWidth(gtk_page_setup_get_paper_width(pageSetup, GTK_UNIT_POINTS) - gtk_page_setup_get_left_margin(pageSetup, GTK_UNIT_POINTS) - gtk_page_setup_get_right_margin(pageSetup, GTK_UNIT_POINTS))
     , availablePaperHeight(gtk_page_setup_get_paper_height(pageSetup, GTK_UNIT_POINTS) - gtk_page_setup_get_top_margin(pageSetup, GTK_UNIT_POINTS) - gtk_page_setup_get_bottom_margin(pageSetup, GTK_UNIT_POINTS))
     , printSettings(settings)
     , pageSetup(pageSetup)
+    , printMode(printMode)
 {
     ASSERT(settings);
     ASSERT(pageSetup);

Modified: releases/WebKitGTK/webkit-2.2/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp (159047 => 159048)


--- releases/WebKitGTK/webkit-2.2/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp	2013-11-11 10:10:02 UTC (rev 159047)
+++ releases/WebKitGTK/webkit-2.2/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp	2013-11-11 10:13:26 UTC (rev 159048)
@@ -20,7 +20,6 @@
 #include "config.h"
 #include "WebKitPrintOperation.h"
 
-#include "PrintInfo.h"
 #include "WebKitPrintOperationPrivate.h"
 #include "WebKitPrivate.h"
 #include "WebKitWebViewBasePrivate.h"
@@ -73,6 +72,7 @@
 
     WebKitWebView* webView;
     gulong webViewDestroyedId;
+    PrintInfo::PrintMode printMode;
 
     GRefPtr<GtkPrintSettings> printSettings;
     GRefPtr<GtkPageSetup> pageSetup;
@@ -264,8 +264,11 @@
 {
     GRefPtr<WebKitPrintOperation> printOperation = adoptGRef(WEBKIT_PRINT_OPERATION(context));
     WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(printOperation->priv->webView));
-    page->endPrinting();
 
+    // When running synchronously WebPageProxy::printFrame() calls endPrinting().
+    if (printOperation->priv->printMode == PrintInfo::PrintModeAsync)
+        page->endPrinting();
+
     const WebCore::ResourceError& resourceError = toImpl(wkPrintError)->platformError();
     if (!resourceError.isNull()) {
         GOwnPtr<GError> printError(g_error_new_literal(g_quark_from_string(resourceError.domain().utf8().data()),
@@ -278,7 +281,7 @@
 
 static void webkitPrintOperationPrintPagesForFrame(WebKitPrintOperation* printOperation, WebFrameProxy* webFrame, GtkPrintSettings* printSettings, GtkPageSetup* pageSetup)
 {
-    PrintInfo printInfo(printSettings, pageSetup);
+    PrintInfo printInfo(printSettings, pageSetup, printOperation->priv->printMode);
     WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(printOperation->priv->webView));
     page->drawPagesForPrinting(webFrame, printInfo, PrintFinishedCallback::create(g_object_ref(printOperation), &drawPagesForPrintingCompleted));
 }
@@ -300,6 +303,11 @@
     return response;
 }
 
+void webkitPrintOperationSetPrintMode(WebKitPrintOperation* printOperation, PrintInfo::PrintMode printMode)
+{
+    printOperation->priv->printMode = printMode;
+}
+
 /**
  * webkit_print_operation_new:
  * @web_view: a #WebKitWebView

Modified: releases/WebKitGTK/webkit-2.2/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperationPrivate.h (159047 => 159048)


--- releases/WebKitGTK/webkit-2.2/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperationPrivate.h	2013-11-11 10:10:02 UTC (rev 159047)
+++ releases/WebKitGTK/webkit-2.2/Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperationPrivate.h	2013-11-11 10:13:26 UTC (rev 159048)
@@ -20,9 +20,11 @@
 #ifndef WebKitPrintOperationPrivate_h
 #define WebKitPrintOperationPrivate_h
 
+#include "PrintInfo.h"
 #include "WebFrameProxy.h"
 #include "WebKitPrintOperation.h"
 
 WebKitPrintOperationResponse webkitPrintOperationRunDialogForFrame(WebKitPrintOperation*, GtkWindow* parent, WebKit::WebFrameProxy*);
+void webkitPrintOperationSetPrintMode(WebKitPrintOperation*, WebKit::PrintInfo::PrintMode);
 
 #endif // WebKitPrintOperationPrivate_h

Modified: releases/WebKitGTK/webkit-2.2/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp (159047 => 159048)


--- releases/WebKitGTK/webkit-2.2/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp	2013-11-11 10:10:02 UTC (rev 159047)
+++ releases/WebKitGTK/webkit-2.2/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp	2013-11-11 10:13:26 UTC (rev 159048)
@@ -1643,6 +1643,7 @@
     if (returnValue)
         return;
 
+    webkitPrintOperationSetPrintMode(printOperation.get(), PrintInfo::PrintModeSync);
     WebKitPrintOperationResponse response = webkitPrintOperationRunDialogForFrame(printOperation.get(), 0, frame);
     if (response == WEBKIT_PRINT_OPERATION_RESPONSE_CANCEL)
         return;

Modified: releases/WebKitGTK/webkit-2.2/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.cpp (159047 => 159048)


--- releases/WebKitGTK/webkit-2.2/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.cpp	2013-11-11 10:10:02 UTC (rev 159047)
+++ releases/WebKitGTK/webkit-2.2/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.cpp	2013-11-11 10:13:26 UTC (rev 159048)
@@ -109,7 +109,7 @@
         m_printContext = printContext;
         m_callbackID = callbackID;
         gtk_enumerate_printers(reinterpret_cast<GtkPrinterFunc>(enumeratePrintersFunction), this,
-                               reinterpret_cast<GDestroyNotify>(enumeratePrintersFinished), FALSE);
+            reinterpret_cast<GDestroyNotify>(enumeratePrintersFinished), m_printMode == PrintInfo::PrintModeSync);
     }
 
     void startPage(cairo_t* cr)
@@ -217,6 +217,9 @@
         , isDone(false)
         , isValid(true)
     {
+        if (printOperation->printMode() == PrintInfo::PrintModeSync)
+            mainLoop = adoptGRef(g_main_loop_new(0, FALSE));
+
         if (printOperation->collateCopies()) {
             collatedCopies = printOperation->copies();
             uncollatedCopies = 1;
@@ -358,6 +361,7 @@
     }
 
     RefPtr<WebPrintOperationGtk> printOperation;
+    GRefPtr<GMainLoop> mainLoop;
 
     int totalPrinted;
     size_t totalToPrint;
@@ -392,6 +396,7 @@
     : m_webPage(page)
     , m_printSettings(printInfo.printSettings.get())
     , m_pageSetup(printInfo.pageSetup.get())
+    , m_printMode(printInfo.printMode)
     , m_printContext(0)
     , m_callbackID(0)
     , m_xDPI(1)
@@ -669,6 +674,8 @@
 void WebPrintOperationGtk::printPagesIdleDone(gpointer userData)
 {
     PrintPagesData* data = ""
+    if (data->mainLoop)
+        g_main_loop_quit(data->mainLoop.get());
 
     data->printOperation->printPagesDone();
     delete data;
@@ -705,8 +712,17 @@
     m_xDPI = xDPI;
     m_yDPI = yDPI;
     m_cairoContext = adoptRef(cairo_create(surface));
-    m_printPagesIdleId = gdk_threads_add_idle_full(G_PRIORITY_DEFAULT_IDLE + 10, printPagesIdle,
-                                                   data.leakPtr(), printPagesIdleDone);
+
+    // Make sure the print pages idle has more priority than IPC messages comming from
+    // the IO thread, so that the EndPrinting message is always handled once the print
+    // operation has finished. See https://bugs.webkit.org/show_bug.cgi?id=122801.
+    unsigned idlePriority = m_printMode == PrintInfo::PrintModeSync ? G_PRIORITY_DEFAULT - 10 : G_PRIORITY_DEFAULT_IDLE + 10;
+    GMainLoop* mainLoop = data->mainLoop.get();
+    m_printPagesIdleId = gdk_threads_add_idle_full(idlePriority, printPagesIdle, data.leakPtr(), printPagesIdleDone);
+    if (m_printMode == PrintInfo::PrintModeSync) {
+        ASSERT(mainLoop);
+        g_main_loop_run(mainLoop);
+    }
 }
 
 }

Modified: releases/WebKitGTK/webkit-2.2/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.h (159047 => 159048)


--- releases/WebKitGTK/webkit-2.2/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.h	2013-11-11 10:10:02 UTC (rev 159047)
+++ releases/WebKitGTK/webkit-2.2/Source/WebKit2/WebProcess/WebPage/gtk/WebPrintOperationGtk.h	2013-11-11 10:13:26 UTC (rev 159048)
@@ -53,6 +53,7 @@
     WebCore::PrintContext* printContext() const { return m_printContext; }
     GtkPrintSettings* printSettings() const { return m_printSettings.get(); }
     GtkPageSetup* pageSetup() const { return m_pageSetup.get(); }
+    PrintInfo::PrintMode printMode() const { return m_printMode; }
     void setNumberOfPagesToPrint(size_t numberOfPages) { m_numberOfPagesToPrint = numberOfPages; }
     unsigned int pagesToPrint() const { return m_pagesToPrint; }
     int pageCount() const;
@@ -95,6 +96,7 @@
     WebPage* m_webPage;
     GRefPtr<GtkPrintSettings> m_printSettings;
     GRefPtr<GtkPageSetup> m_pageSetup;
+    PrintInfo::PrintMode m_printMode;
     WebCore::PrintContext* m_printContext;
     uint64_t m_callbackID;
     RefPtr<cairo_t> m_cairoContext;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to