[GTK] UI process crashes when the web process crashes while printing
authorcarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 15 Jan 2014 07:47:47 +0000 (07:47 +0000)
committercarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 15 Jan 2014 07:47:47 +0000 (07:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=126977

Reviewed by Gustavo Noronha Silva.

Source/WebKit2:

When the web process crashes, the printing callback is
invalidated, so the function is called with a NULL error.

* UIProcess/API/gtk/WebKitPrintOperation.cpp:
(drawPagesForPrintingCompleted): Check wkError is not NULL before
trying to use it.
* UIProcess/API/gtk/WebKitWebView.cpp:
(webkitWebViewPrintFrame): Set the print mode of the operation
before emitting the print signal.

Tools:

Add new test case to check that closing the window right after
printing works. It's skipped for now, because this patch only
fixes the UI process crash, but not the web process one.

* Scripts/run-gtk-tests:
(TestRunner): Skip
/webkit2/WebKitPrintOperation/close-after-print.
* TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp:
(testPrintOperationPrintPrinter):
(findPrintToFilePrinter):
(testPrintOperationPrint):
(testPrintOperationErrors):
(testPrintOperationCloseAfterPrint):
(beforeAll):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@162056 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/gtk/WebKitPrintOperation.cpp
Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp
Tools/ChangeLog
Tools/Scripts/run-gtk-tests
Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp

index c84a3f5..63e6e61 100644 (file)
@@ -1,3 +1,20 @@
+2014-01-14  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [GTK] UI process crashes when the web process crashes while printing
+        https://bugs.webkit.org/show_bug.cgi?id=126977
+
+        Reviewed by Gustavo Noronha Silva.
+
+        When the web process crashes, the printing callback is
+        invalidated, so the function is called with a NULL error.
+
+        * UIProcess/API/gtk/WebKitPrintOperation.cpp:
+        (drawPagesForPrintingCompleted): Check wkError is not NULL before
+        trying to use it.
+        * UIProcess/API/gtk/WebKitWebView.cpp:
+        (webkitWebViewPrintFrame): Set the print mode of the operation
+        before emitting the print signal.
+
 2014-01-14  Brady Eidson  <beidson@apple.com>
 
         IDB: create object store support
index 1c9378d..03f63c7 100644 (file)
@@ -269,7 +269,7 @@ static void drawPagesForPrintingCompleted(WKErrorRef wkPrintError, WKErrorRef, v
     if (printOperation->priv->printMode == PrintInfo::PrintModeAsync)
         page->endPrinting();
 
-    const WebCore::ResourceError& resourceError = toImpl(wkPrintError)->platformError();
+    const WebCore::ResourceError& resourceError = wkPrintError ? toImpl(wkPrintError)->platformError() : WebCore::ResourceError();
     if (!resourceError.isNull()) {
         GOwnPtr<GError> printError(g_error_new_literal(g_quark_from_string(resourceError.domain().utf8().data()),
                                                      resourceError.errorCode(),
index 6597b3b..2388614 100644 (file)
@@ -1678,12 +1678,12 @@ void webkitWebViewMouseTargetChanged(WebKitWebView* webView, WebHitTestResult* h
 void webkitWebViewPrintFrame(WebKitWebView* webView, WebFrameProxy* frame)
 {
     GRefPtr<WebKitPrintOperation> printOperation = adoptGRef(webkit_print_operation_new(webView));
+    webkitPrintOperationSetPrintMode(printOperation.get(), PrintInfo::PrintModeSync);
     gboolean returnValue;
     g_signal_emit(webView, signals[PRINT], 0, printOperation.get(), &returnValue);
     if (returnValue)
         return;
 
-    webkitPrintOperationSetPrintMode(printOperation.get(), PrintInfo::PrintModeSync);
     WebKitPrintOperationResponse response = webkitPrintOperationRunDialogForFrame(printOperation.get(), 0, frame);
     if (response == WEBKIT_PRINT_OPERATION_RESPONSE_CANCEL)
         return;
index 723ed7d..73df56b 100644 (file)
@@ -1,3 +1,25 @@
+2014-01-14  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [GTK] UI process crashes when the web process crashes while printing
+        https://bugs.webkit.org/show_bug.cgi?id=126977
+
+        Reviewed by Gustavo Noronha Silva.
+
+        Add new test case to check that closing the window right after
+        printing works. It's skipped for now, because this patch only
+        fixes the UI process crash, but not the web process one.
+
+        * Scripts/run-gtk-tests:
+        (TestRunner): Skip
+        /webkit2/WebKitPrintOperation/close-after-print.
+        * TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp:
+        (testPrintOperationPrintPrinter):
+        (findPrintToFilePrinter):
+        (testPrintOperationPrint):
+        (testPrintOperationErrors):
+        (testPrintOperationCloseAfterPrint):
+        (beforeAll):
+
 2014-01-14  Brent Fulgham  <bfulgham@apple.com>
 
         [WIN] Set MSBuild environment variable to avoid long-lived processes locking log files
index c0a91f5..51f71eb 100755 (executable)
@@ -69,6 +69,7 @@ class TestRunner:
         SkippedTest("WebKit2Gtk/TestUIClient", "/webkit2/WebKitWebView/mouse-target", "Test times out after r150890", 117689),
         SkippedTest("WebKit2Gtk/TestContextMenu", SkippedTest.ENTIRE_SUITE, "Test times out after r150890", 117689),
         SkippedTest("WebKit2Gtk/TestWebKitWebView", "/webkit2/WebKitWebView/snapshot", "Test fails", 120404),
+        SkippedTest("WebKit2Gtk/TestPrinting", "/webkit2/WebKitPrintOperation/close-after-print", "Test times out", 126979),
         SkippedTest("WebKit2/TestWebKit2", "WebKit2.MouseMoveAfterCrash", "Test is flaky", 85066),
         SkippedTest("WebKit2/TestWebKit2", "WebKit2.NewFirstVisuallyNonEmptyLayoutForImages", "Test is flaky", 85066),
         SkippedTest("WebKit2/TestWebKit2", "WebKit2.NewFirstVisuallyNonEmptyLayoutFrames", "Test fails", 85037),
index 408e2aa..0524072 100644 (file)
@@ -72,6 +72,23 @@ static void testWebViewPrint(WebViewTest* test, gconstpointer)
 }
 
 #ifdef HAVE_GTK_UNIX_PRINTING
+static gboolean testPrintOperationPrintPrinter(GtkPrinter* printer, gpointer userData)
+{
+    if (strcmp(gtk_printer_get_name(printer), "Print to File"))
+        return FALSE;
+
+    GtkPrinter** foundPrinter = static_cast<GtkPrinter**>(userData);
+    *foundPrinter = static_cast<GtkPrinter*>(g_object_ref(printer));
+    return TRUE;
+}
+
+static GtkPrinter* findPrintToFilePrinter()
+{
+    GtkPrinter* printer = 0;
+    gtk_enumerate_printers(testPrintOperationPrintPrinter, &printer, 0, TRUE);
+    return printer;
+}
+
 class PrintTest: public WebViewTest {
 public:
     MAKE_GLIB_TEST_FIXTURE(PrintTest);
@@ -97,23 +114,6 @@ public:
         g_signal_connect(m_printOperation.get(), "failed", G_CALLBACK(printFailedCallback), this);
     }
 
-    static gboolean testPrintOperationPrintPrinter(GtkPrinter* printer, gpointer userData)
-    {
-        if (strcmp(gtk_printer_get_name(printer), "Print to File"))
-            return FALSE;
-
-        GtkPrinter** foundPrinter = static_cast<GtkPrinter**>(userData);
-        *foundPrinter = static_cast<GtkPrinter*>(g_object_ref(printer));
-        return TRUE;
-    }
-
-    GtkPrinter* findPrintToFilePrinter()
-    {
-        GtkPrinter* printer = 0;
-        gtk_enumerate_printers(testPrintOperationPrintPrinter, &printer, 0, TRUE);
-        return printer;
-    }
-
     void waitUntilPrintFinished()
     {
         g_main_loop_run(m_mainLoop);
@@ -128,7 +128,7 @@ static void testPrintOperationPrint(PrintTest* test, gconstpointer)
     test->loadHtml("<html><body>WebKitGTK+ printing test</body></html>", 0);
     test->waitUntilLoadFinished();
 
-    GRefPtr<GtkPrinter> printer = adoptGRef(test->findPrintToFilePrinter());
+    GRefPtr<GtkPrinter> printer = adoptGRef(findPrintToFilePrinter());
     if (!printer) {
         g_message("%s", "Cannot test WebKitPrintOperation/print: no suitable printer found");
         return;
@@ -161,7 +161,7 @@ static void testPrintOperationErrors(PrintTest* test, gconstpointer)
     test->loadHtml("<html><body>WebKitGTK+ printing errors test</body></html>", 0);
     test->waitUntilLoadFinished();
 
-    GRefPtr<GtkPrinter> printer = adoptGRef(test->findPrintToFilePrinter());
+    GRefPtr<GtkPrinter> printer = adoptGRef(findPrintToFilePrinter());
     if (!printer) {
         g_message("%s", "Cannot test WebKitPrintOperation/print: no suitable printer found");
         return;
@@ -189,6 +189,105 @@ static void testPrintOperationErrors(PrintTest* test, gconstpointer)
     webkit_print_operation_print(test->m_printOperation.get());
     test->waitUntilPrintFinished();
 }
+
+class CloseAfterPrintTest: public WebViewTest {
+public:
+    MAKE_GLIB_TEST_FIXTURE(CloseAfterPrintTest);
+
+    static GtkWidget* webViewCreate(WebKitWebView* webView, CloseAfterPrintTest* test)
+    {
+        return test->createWebView();
+    }
+
+    static gboolean webViewPrint(WebKitWebView* webView, WebKitPrintOperation* printOperation, CloseAfterPrintTest* test)
+    {
+        test->print(printOperation);
+        return TRUE;
+    }
+
+    static void printOperationFinished(WebKitPrintOperation* printOperation, CloseAfterPrintTest* test)
+    {
+        test->printFinished();
+    }
+
+    static void webViewClosed(WebKitWebView* webView, CloseAfterPrintTest* test)
+    {
+        gtk_widget_destroy(GTK_WIDGET(webView));
+        test->m_webViewClosed = true;
+        if (test->m_printFinished)
+            g_main_loop_quit(test->m_mainLoop);
+    }
+
+    CloseAfterPrintTest()
+        : m_webViewClosed(false)
+        , m_printFinished(false)
+    {
+        webkit_settings_set_javascript_can_open_windows_automatically(webkit_web_view_get_settings(m_webView), TRUE);
+        g_signal_connect(m_webView, "create", G_CALLBACK(webViewCreate), this);
+    }
+
+    GtkWidget* createWebView()
+    {
+        GtkWidget* newWebView = webkit_web_view_new();
+        g_object_ref_sink(newWebView);
+
+        assertObjectIsDeletedWhenTestFinishes(G_OBJECT(newWebView));
+        g_signal_connect(newWebView, "print", G_CALLBACK(webViewPrint), this);
+        g_signal_connect(newWebView, "close", G_CALLBACK(webViewClosed), this);
+        return newWebView;
+    }
+
+    void print(WebKitPrintOperation* printOperation)
+    {
+        assertObjectIsDeletedWhenTestFinishes(G_OBJECT(printOperation));
+
+        GRefPtr<GtkPrinter> printer = adoptGRef(findPrintToFilePrinter());
+        if (!printer) {
+            g_message("%s", "Cannot test WebKitPrintOperation/print: no suitable printer found");
+            return;
+        }
+
+        GOwnPtr<char> outputFilename(g_build_filename(kTempDirectory, "webkit-close-after-print.pdf", NULL));
+        m_outputFile = adoptGRef(g_file_new_for_path(outputFilename.get()));
+        GOwnPtr<char> outputURI(g_file_get_uri(m_outputFile.get()));
+
+        GRefPtr<GtkPrintSettings> printSettings = adoptGRef(gtk_print_settings_new());
+        gtk_print_settings_set_printer(printSettings.get(), gtk_printer_get_name(printer.get()));
+        gtk_print_settings_set(printSettings.get(), GTK_PRINT_SETTINGS_OUTPUT_URI, outputURI.get());
+        webkit_print_operation_set_print_settings(printOperation, printSettings.get());
+
+        m_printOperation = printOperation;
+        g_signal_connect(m_printOperation.get(), "finished", G_CALLBACK(printOperationFinished), this);
+        webkit_print_operation_print(m_printOperation.get());
+    }
+
+    void printFinished()
+    {
+        m_printFinished = true;
+        m_printOperation = nullptr;
+        g_assert(m_outputFile);
+        g_file_delete(m_outputFile.get(), 0, 0);
+        m_outputFile = nullptr;
+        if (m_webViewClosed)
+            g_main_loop_quit(m_mainLoop);
+    }
+
+    void waitUntilPrintFinishedAndViewClosed()
+    {
+        g_main_loop_run(m_mainLoop);
+    }
+
+    GRefPtr<WebKitPrintOperation> m_printOperation;
+    GRefPtr<GFile> m_outputFile;
+    bool m_webViewClosed;
+    bool m_printFinished;
+};
+
+static void testPrintOperationCloseAfterPrint(CloseAfterPrintTest* test, gconstpointer)
+{
+    test->loadHtml("<html><body onLoad=\"w = window.open();w.print();w.close();\"></body></html>", 0);
+    test->waitUntilPrintFinishedAndViewClosed();
+}
 #endif // HAVE_GTK_UNIX_PRINTING
 
 void beforeAll()
@@ -201,6 +300,7 @@ void beforeAll()
 #ifdef HAVE_GTK_UNIX_PRINTING
     PrintTest::add("WebKitPrintOperation", "print", testPrintOperationPrint);
     PrintTest::add("WebKitPrintOperation", "print-errors", testPrintOperationErrors);
+    CloseAfterPrintTest::add("WebKitPrintOperation", "close-after-print", testPrintOperationCloseAfterPrint);
 #endif
 }