changeset 11018:94d23e05b3de

8208622: [WebView] IllegalStateException when invoking print API with html form controls Reviewed-by: kcr, mbilla
author arajkumar
date Tue, 07 Aug 2018 12:25:41 +0530
parents 328f6b32bf0c
children 15326b4db607
files modules/javafx.web/src/main/native/Source/WebCore/platform/graphics/java/PlatformContextJava.h modules/javafx.web/src/main/native/Source/WebCore/platform/java/RenderThemeJava.cpp modules/javafx.web/src/main/native/Source/WebCore/platform/java/WebPage.cpp modules/javafx.web/src/main/native/Source/WebCore/platform/java/WebPage.h modules/javafx.web/src/shims/java/com/sun/webkit/WebPageShim.java modules/javafx.web/src/test/java/test/javafx/scene/web/FormControlsTest.java
diffstat 6 files changed, 212 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/modules/javafx.web/src/main/native/Source/WebCore/platform/graphics/java/PlatformContextJava.h	Mon Aug 06 11:47:14 2018 -0700
+++ b/modules/javafx.web/src/main/native/Source/WebCore/platform/graphics/java/PlatformContextJava.h	Tue Aug 07 12:25:41 2018 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,12 +39,14 @@
     class PlatformContextJava {
         WTF_MAKE_NONCOPYABLE(PlatformContextJava);
     public:
-        PlatformContextJava(const JLObject &jRQ, bool autoFlush = false) {
-            m_rq = RenderingQueue::create(
-                jRQ,
-                com_sun_webkit_graphics_WCRenderQueue_MAX_QUEUE_SIZE / RenderingQueue::MAX_BUFFER_COUNT,
-                autoFlush);
-        }
+        PlatformContextJava(const JLObject& jRQ, RefPtr<RQRef> jTheme, bool autoFlush = false)
+            : m_rq(RenderingQueue::create(jRQ, com_sun_webkit_graphics_WCRenderQueue_MAX_QUEUE_SIZE / RenderingQueue::MAX_BUFFER_COUNT, autoFlush))
+            , m_jRenderTheme(jTheme)
+        {}
+
+        PlatformContextJava(const JLObject& jRQ, bool autoFlush = false)
+            : PlatformContextJava(jRQ, nullptr, autoFlush)
+        {}
 
         RenderingQueue& rq() const {
             return *m_rq;
@@ -54,6 +56,10 @@
             return m_rq;
         }
 
+        RefPtr<RQRef> jRenderTheme() const {
+            return m_jRenderTheme;
+        }
+
         void beginPath() {
             m_path.clear();
         }
@@ -75,6 +81,7 @@
 
     private:
         RefPtr<RenderingQueue> m_rq;
+        RefPtr<RQRef> m_jRenderTheme;
         Path m_path;
     };
 }
--- a/modules/javafx.web/src/main/native/Source/WebCore/platform/java/RenderThemeJava.cpp	Mon Aug 06 11:47:14 2018 -0700
+++ b/modules/javafx.web/src/main/native/Source/WebCore/platform/java/RenderThemeJava.cpp	Tue Aug 07 12:25:41 2018 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -67,9 +67,6 @@
 
 namespace WebCore {
 
-static RefPtr<RQRef> s_jTheme;
-
-
 RenderTheme& RenderTheme::singleton()
 {
     static RenderTheme& sm_defaultInstance = *new RenderThemeJava();
@@ -121,19 +118,8 @@
     return RQRef::create(getJRenderTheme(page));
 }
 
-void RenderThemeJava::setTheme(RefPtr<RQRef> theme)
-{
-    if (theme) {
-        s_jTheme = theme;
-    } else {
-        static auto jTheme = themeForPage(nullptr);
-        s_jTheme = jTheme;
-    }
-}
-
 RenderThemeJava::RenderThemeJava()
 {
-    setTheme(nullptr);
 }
 
 int RenderThemeJava::createWidgetState(const RenderObject& o)
@@ -176,7 +162,11 @@
         return false;
     }
 
-    ASSERT(s_jTheme);
+    auto jRenderTheme = paintInfo.context().platformContext()->jRenderTheme();
+    if (!jRenderTheme) {
+        return false;
+    }
+
     int state = createWidgetState(object);
     RGBA32 bgColor = object.style().visitedDependentColor(
         widgetIndex == JNI_EXPAND(MENU_LIST_BUTTON)
@@ -258,7 +248,7 @@
     ASSERT(mid);
 
     RefPtr<RQRef> widgetRef = RQRef::create(
-        env->CallObjectMethod((jobject)*s_jTheme, mid,
+        env->CallObjectMethod(jobject(*jRenderTheme), mid,
             ptr_to_jlong(&object),
             (jint)widgetIndex,
             (jint)state,
@@ -279,7 +269,7 @@
     // widgetRef will go into rq's inner refs vector.
     paintInfo.context().platformContext()->rq().freeSpace(20)
     << (jint)com_sun_webkit_graphics_GraphicsDecoder_DRAWWIDGET
-    << (jint)*s_jTheme
+    << (jint)*jRenderTheme
     << widgetRef
     << (jint)rect.x() << (jint)rect.y();
 
@@ -347,14 +337,13 @@
         return;
     }
 
-    ASSERT(s_jTheme);
-
     JNIEnv* env = WebCore_GetJavaEnv();
 
     static jmethodID mid = env->GetMethodID(getJRenderThemeClass(), "getRadioButtonSize", "()I");
     ASSERT(mid);
 
-    int radioRadius = env->CallIntMethod((jobject)*s_jTheme, mid);
+    // Get from default theme object.
+    int radioRadius = env->CallIntMethod((jobject)getJRenderTheme(nullptr), mid);
     CheckAndClearException(env);
 
     if (style.width().isIntrinsicOrAuto()) {
@@ -606,12 +595,12 @@
 {
     JNIEnv* env = WebCore_GetJavaEnv();
     ASSERT(env);
-    ASSERT(s_jTheme);
 
     static jmethodID mid = env->GetMethodID(getJRenderThemeClass(), "getSelectionColor", "(I)I");
     ASSERT(mid);
 
-    jint c = env->CallIntMethod((jobject)*s_jTheme, mid, index);
+    // Get from default theme object.
+    jint c = env->CallIntMethod((jobject)getJRenderTheme(nullptr), mid, index);
     CheckAndClearException(env);
 
     return Color(c);
--- a/modules/javafx.web/src/main/native/Source/WebCore/platform/java/WebPage.cpp	Mon Aug 06 11:47:14 2018 -0700
+++ b/modules/javafx.web/src/main/native/Source/WebCore/platform/java/WebPage.cpp	Tue Aug 07 12:25:41 2018 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -174,7 +174,6 @@
 
 WebPage::~WebPage()
 {
-    RenderThemeJava::setTheme(nullptr);
     debugEnded();
 }
 
@@ -256,10 +255,6 @@
 #endif
 
 void WebPage::prePaint() {
-    if (!m_jTheme) {
-        m_jTheme = RenderThemeJava::themeForPage(jobjectFromPage(m_page.get()));
-    }
-    RenderThemeJava::setTheme(m_jTheme);
 #if USE(ACCELERATED_COMPOSITING)
     if (m_rootLayer) {
         if (m_syncLayers) {
@@ -278,6 +273,14 @@
     }
 }
 
+RefPtr<RQRef> WebPage::jRenderTheme()
+{
+    if (!m_jRenderTheme) {
+        m_jRenderTheme = RenderThemeJava::themeForPage(jobjectFromPage(m_page.get()));
+    }
+    return m_jRenderTheme;
+}
+
 void WebPage::paint(jobject rq, jint x, jint y, jint w, jint h)
 {
 #if USE(ACCELERATED_COMPOSITING)
@@ -295,7 +298,7 @@
     }
 
     // Will be deleted by GraphicsContext destructor
-    PlatformContextJava* ppgc = new PlatformContextJava(rq);
+    PlatformContextJava* ppgc = new PlatformContextJava(rq, jRenderTheme());
     GraphicsContext gc(ppgc);
 
     // TODO: Following JS synchronization is not necessary for single thread model
@@ -312,7 +315,6 @@
 
 void WebPage::postPaint(jobject rq, jint x, jint y, jint w, jint h)
 {
-    RenderThemeJava::setTheme(nullptr);
     if (!m_page->inspectorController().highlightedNode()
 #if USE(ACCELERATED_COMPOSITING)
             && !m_rootLayer
@@ -322,7 +324,7 @@
     }
 
     // Will be deleted by GraphicsContext destructor
-    PlatformContextJava* ppgc = new PlatformContextJava(rq);
+    PlatformContextJava* ppgc = new PlatformContextJava(rq, jRenderTheme());
     GraphicsContext gc(ppgc);
 
 #if USE(ACCELERATED_COMPOSITING)
@@ -1555,9 +1557,10 @@
 JNIEXPORT void JNICALL Java_com_sun_webkit_WebPage_twkPrint
     (JNIEnv* env, jobject self, jlong pPage, jobject rq, jint pageIndex, jfloat width)
 {
-    PlatformContextJava* ppgc = new PlatformContextJava(rq);
+    auto webPage = WebPage::webPageFromJLong(pPage);
+    PlatformContextJava* ppgc = new PlatformContextJava(rq, webPage->jRenderTheme());
     GraphicsContext gc(ppgc);
-    WebPage::webPageFromJLong(pPage)->print(gc, pageIndex, width);
+    webPage->print(gc, pageIndex, width);
 }
 
 JNIEXPORT jint JNICALL Java_com_sun_webkit_WebPage_twkGetFrameHeight
--- a/modules/javafx.web/src/main/native/Source/WebCore/platform/java/WebPage.h	Mon Aug 06 11:47:14 2018 -0700
+++ b/modules/javafx.web/src/main/native/Source/WebCore/platform/java/WebPage.h	Tue Aug 07 12:25:41 2018 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -107,6 +107,8 @@
     void enableWatchdog();
     void disableWatchdog();
 
+    RefPtr<RQRef> jRenderTheme();
+
 private:
     void requestJavaRepaint(const IntRect&);
 #if USE(ACCELERATED_COMPOSITING)
@@ -140,7 +142,7 @@
 
     std::unique_ptr<Page> m_page;
     std::unique_ptr<PrintContext> m_printContext;
-    RefPtr<RQRef> m_jTheme;
+    RefPtr<RQRef> m_jRenderTheme;
 
 #if USE(ACCELERATED_COMPOSITING)
     std::unique_ptr<GraphicsLayer> m_rootLayer;
--- a/modules/javafx.web/src/shims/java/com/sun/webkit/WebPageShim.java	Mon Aug 06 11:47:14 2018 -0700
+++ b/modules/javafx.web/src/shims/java/com/sun/webkit/WebPageShim.java	Tue Aug 07 12:25:41 2018 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,10 +26,38 @@
 package com.sun.webkit;
 
 import com.sun.webkit.WebPage;
+import com.sun.webkit.graphics.WCGraphicsContext;
+import com.sun.webkit.graphics.WCGraphicsManager;
+import com.sun.webkit.graphics.WCPageBackBuffer;
+import com.sun.webkit.graphics.WCRectangle;
 
 public class WebPageShim {
 
     public static int getFramesCount(WebPage page) {
         return page.test_getFramesCount();
     }
+
+    private static WCGraphicsContext setupPageWithGraphics(WebPage page, int x, int y, int w, int h) {
+        page.setBounds(x, y, w, h);
+        // forces layout and renders the page into RenderQueue.
+        page.updateContent(new WCRectangle(x, y, w, h));
+
+        final WCPageBackBuffer buffer = WCGraphicsManager.getGraphicsManager().createPageBackBuffer();
+        buffer.validate(w, h);
+        return buffer.createGraphics();
+    }
+
+    public static void mockPrint(WebPage page, int x, int y, int w, int h) {
+        final WCGraphicsContext gc = setupPageWithGraphics(page, x, y, w, h);
+        // almost equivalent to `PrinterJob.printPage(webview)`
+        page.print(gc, x, y, w, h);
+    }
+
+    public static void mockPrintByPage(WebPage page, int pageNo, int x, int y, int w, int h) {
+        final WCGraphicsContext gc = setupPageWithGraphics(page, x, y, w, h);
+        // almost equivalent to `WebEngine.print(printerJob) `
+        page.beginPrinting(w, h);
+        page.print(gc, pageNo, w);
+        page.endPrinting();
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/javafx.web/src/test/java/test/javafx/scene/web/FormControlsTest.java	Tue Aug 07 12:25:41 2018 +0530
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.javafx.scene.web;
+
+import com.sun.webkit.WebPage;
+import com.sun.webkit.WebPageShim;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Set;
+import javafx.scene.Node;
+import javafx.scene.web.WebEngineShim;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized.Parameters;
+import org.junit.runners.Parameterized;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(Parameterized.class)
+public final class FormControlsTest extends TestBase {
+
+    private static final PrintStream ERR = System.err;
+
+    // To arguments from junit data provider.
+    private final String element;
+    private final String selector;
+
+    // TODO: junit 4.11 provides an option to label arguments.
+    @Parameters
+    public static Collection<String[]> data() {
+        return Arrays.asList(new String[][] {
+            {"<input type='checkbox'/>", "check-box"},
+            {"<input type='radio'/>", "radio-button"},
+            {"<input type='button'/>", "button"},
+            {"<input type='text'/>", "text-field"},
+            {"<meter value='06'>60%</meter>", "progress-bar"},
+            {"<input type='range'/>", "slider"},
+            // TODO: Add other form controls once it is enabled
+            // from WebKit.
+        });
+    }
+
+    public FormControlsTest(final String element, final String selector) {
+        this.element = element;
+        this.selector = selector;
+    }
+
+    private void printWithFormControl(final Runnable testBody) {
+        final ByteArrayOutputStream errStream = new ByteArrayOutputStream();
+
+        System.setErr(new PrintStream(errStream));
+        loadContent(String.format("<body>%s</body>", element));
+        submit(testBody);
+        System.setErr(ERR);
+
+        final String exMessage = errStream.toString();
+        assertFalse(String.format("%s:Test failed with exception:\n%s", selector, exMessage),
+            exMessage.contains("Exception") || exMessage.contains("Error"));
+    }
+
+    @Test
+    public void testRendering() {
+        final Runnable testBody = () -> {
+            final WebPage page = WebEngineShim.getPage(getEngine());
+            assertNotNull(page);
+            WebPageShim.mockPrint(page, 0, 0, 800, 600);
+            final Set<Node> elements = getView().lookupAll("." + selector);
+            // Check whether control is added as a children of WebView.
+            assertEquals(
+                String.format("%s control doesn't exists as child of WebView", selector),
+                1,
+                elements.size());
+            final Node node = (Node) elements.toArray()[0];
+            // Check whether Node's styleClass contains given selector.
+            assertTrue(
+                String.format("%s styleClass=%s is incorrect", node.getTypeSelector(), selector),
+                node.getStyleClass().contains(selector));
+        };
+
+        printWithFormControl(testBody);
+    }
+
+    @Test
+    public void testPrint() {
+        final Runnable testBody = () -> {
+            final WebPage page = WebEngineShim.getPage(getEngine());
+            assertNotNull(page);
+            WebPageShim.mockPrint(page, 0, 0, 800, 600);
+        };
+
+        printWithFormControl(testBody);
+    }
+
+    @Test
+    public void testPrintByPageNumber() {
+        final Runnable testBody = () -> {
+            final WebPage page = WebEngineShim.getPage(getEngine());
+            assertNotNull(page);
+            WebPageShim.mockPrintByPage(page, 0, 0, 0, 800, 600);
+        };
+        printWithFormControl(testBody);
+    }
+
+    @After
+    public void teardown() {
+        System.setErr(ERR);
+    }
+}
+