2011-02-04 Adam Barth <abarth@webkit.org>
authorabarth@webkit.org <abarth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 5 Feb 2011 00:50:04 +0000 (00:50 +0000)
committerabarth@webkit.org <abarth@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 5 Feb 2011 00:50:04 +0000 (00:50 +0000)
        Reviewed by Eric Seidel.

        PluginDocuments don't create widgets for plugins on back/forward
        https://bugs.webkit.org/show_bug.cgi?id=53474

        Test that plugin loads when in a plugin document on back-forward.

        * plugins/plugin-document-back-forward-expected.txt: Added.
        * plugins/plugin-document-back-forward.html: Added.
2011-02-04  Adam Barth  <abarth@webkit.org>

        Reviewed by Eric Seidel.

        PluginDocuments don't create widgets for plugins on back/forward
        https://bugs.webkit.org/show_bug.cgi?id=53474

        Long ago, PluginDocument always caused the HTMLEmbedElement to create
        its widget synchronously during a post-layout task.  Recently, however,
        some changes to the HistroyController caused layout on back/forward to
        become slightly more complicated (and added an extra level of recursion
        to layout).  This extra level of recursion triggered the "I've recursed
        too many times" condition in the post-layout task queue, causing the
        FrameView to run the remainder of the tasks asynchronously.
        Unfortunately, that broke PluginDocument because it needs its the
        HTMLEmbedElement's updateWidget task to run synchronously.

        This patch adds a mechanism for "kicking off" the pending post-layout
        tasks synchronously (instead of waiting for the timer to fire).
        PluginDocument then uses that facility to ensure that the
        HTMLEmbedElement's updateWidget task happens.

        Test: plugins/plugin-document-back-forward.html

        * html/PluginDocument.cpp:
        (WebCore::PluginDocumentParser::appendBytes):
        * page/FrameView.cpp:
        (WebCore::FrameView::flushAnyPendingPostLayoutTasks):
        * page/FrameView.h:
2011-02-04  Adam Barth  <abarth@webkit.org>

        Reviewed by Eric Seidel.

        PluginDocuments don't create widgets for plugins on back/forward
        https://bugs.webkit.org/show_bug.cgi?id=53474

        Teach the test plugin how to call alert on load.

        * DumpRenderTree/TestNetscapePlugIn/main.cpp:
        (NPP_New):

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

LayoutTests/ChangeLog
LayoutTests/plugins/plugin-document-back-forward-expected.txt [new file with mode: 0644]
LayoutTests/plugins/plugin-document-back-forward.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/html/PluginDocument.cpp
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/FrameView.h
Tools/ChangeLog
Tools/DumpRenderTree/TestNetscapePlugIn/main.cpp

index 3ec749870cf7bc8dd945aa879eab448c73771dba..bcd2f20746ac66641a578728fa624dfcacab76b7 100644 (file)
@@ -1,3 +1,15 @@
+2011-02-04  Adam Barth  <abarth@webkit.org>
+
+        Reviewed by Eric Seidel.
+
+        PluginDocuments don't create widgets for plugins on back/forward
+        https://bugs.webkit.org/show_bug.cgi?id=53474
+
+        Test that plugin loads when in a plugin document on back-forward.
+
+        * plugins/plugin-document-back-forward-expected.txt: Added.
+        * plugins/plugin-document-back-forward.html: Added.
+
 2011-02-04  Charlie Reis  <creis@chromium.org>
 
         Reviewed by Mihai Parparita.
diff --git a/LayoutTests/plugins/plugin-document-back-forward-expected.txt b/LayoutTests/plugins/plugin-document-back-forward-expected.txt
new file mode 100644 (file)
index 0000000..641d6d0
--- /dev/null
@@ -0,0 +1,3 @@
+ALERT: Plugin Loaded!
+ALERT: Plugin Loaded!
+
diff --git a/LayoutTests/plugins/plugin-document-back-forward.html b/LayoutTests/plugins/plugin-document-back-forward.html
new file mode 100644 (file)
index 0000000..7e586cb
--- /dev/null
@@ -0,0 +1,44 @@
+<html>
+<script>
+if (window.layoutTestController) {
+    layoutTestController.waitUntilDone();
+    layoutTestController.dumpAsText();
+    layoutTestController.dumpChildFramesAsText();
+}
+
+state = "initial";
+
+function next() {
+    switch (state) {
+    case "initial":
+        state = "loading-plugin";
+        var frame = document.getElementsByTagName("iframe")[0]
+        frame.addEventListener("load", next, false);
+        frame.src = "data:application/x-webkit-test-netscape,alertwhenloaded";
+        break;
+    case "loading-plugin":
+        state = "moving-backward";
+        history.back();
+        break;
+    case "moving-backward":
+        state = "moving-forward";
+        history.forward();
+        break;
+    case "moving-forward":
+        state = "done";
+        layoutTestController.notifyDone();
+        break;
+    default:
+        alert('FAIL');
+        break;
+    }
+}
+
+window.onload = function() {
+    // We need to wait for after the load event so that we get a new history
+    // entry when navigating the frame.
+    setTimeout(next, 0);
+}
+</script>
+<iframe src="data:text/html,Waiting..."></iframe>
+</html>
index 1adcf89032fe45ac036b60b8c1889a0e7ffb38a4..ecab65ea104f9c6086cec13540409f3434ef217d 100644 (file)
@@ -1,3 +1,33 @@
+2011-02-04  Adam Barth  <abarth@webkit.org>
+
+        Reviewed by Eric Seidel.
+
+        PluginDocuments don't create widgets for plugins on back/forward
+        https://bugs.webkit.org/show_bug.cgi?id=53474
+
+        Long ago, PluginDocument always caused the HTMLEmbedElement to create
+        its widget synchronously during a post-layout task.  Recently, however,
+        some changes to the HistroyController caused layout on back/forward to
+        become slightly more complicated (and added an extra level of recursion
+        to layout).  This extra level of recursion triggered the "I've recursed
+        too many times" condition in the post-layout task queue, causing the
+        FrameView to run the remainder of the tasks asynchronously.
+        Unfortunately, that broke PluginDocument because it needs its the
+        HTMLEmbedElement's updateWidget task to run synchronously.
+
+        This patch adds a mechanism for "kicking off" the pending post-layout
+        tasks synchronously (instead of waiting for the timer to fire).
+        PluginDocument then uses that facility to ensure that the
+        HTMLEmbedElement's updateWidget task happens.
+
+        Test: plugins/plugin-document-back-forward.html
+
+        * html/PluginDocument.cpp:
+        (WebCore::PluginDocumentParser::appendBytes):
+        * page/FrameView.cpp:
+        (WebCore::FrameView::flushAnyPendingPostLayoutTasks):
+        * page/FrameView.h:
+
 2011-02-04  Charlie Reis  <creis@chromium.org>
 
         Reviewed by Mihai Parparita.
index cebb949a547538b2d5097fb3f11e8c430cb47928..c28224bfd4077bf313edbc9ce839a8fca90d6154 100644 (file)
@@ -28,6 +28,7 @@
 #include "DocumentLoader.h"
 #include "Frame.h"
 #include "FrameLoaderClient.h"
+#include "FrameView.h"
 #include "HTMLEmbedElement.h"
 #include "HTMLHtmlElement.h"
 #include "HTMLNames.h"
@@ -115,6 +116,13 @@ void PluginDocumentParser::appendBytes(DocumentWriter*, const char*, int, bool)
 
     document()->updateLayout();
 
+    // Below we assume that renderer->widget() to have been created by
+    // document()->updateLayout(). However, in some cases, updateLayout() will 
+    // recurse too many times and delay its post-layout tasks (such as creating
+    // the widget). Here we kick off the pending post-layout tasks so that we
+    // can synchronously redirect data to the plugin.
+    frame->view()->flushAnyPendingPostLayoutTasks();
+
     if (RenderPart* renderer = m_embedElement->renderPart()) {
         if (Widget* widget = renderer->widget()) {
             frame->loader()->client()->redirectDataToPlugin(widget);
index d5fc75201d56daccb623894963fc47d385e42544..3b0289d6c89a62efff45deefae88de13bb2b2815 100644 (file)
@@ -1835,7 +1835,16 @@ bool FrameView::updateWidgets()
     
     return m_widgetUpdateSet->isEmpty();
 }
-    
+
+void FrameView::flushAnyPendingPostLayoutTasks()
+{
+    if (!m_hasPendingPostLayoutTasks)
+        return;
+
+    m_postLayoutTasksTimer.stop();
+    performPostLayoutTasks();
+}
+
 void FrameView::performPostLayoutTasks()
 {
     m_hasPendingPostLayoutTasks = false;
index 334bafc28789b2d132564c4c06ab214b6e77bed5..4959d8e0a457988a874e4005163c49e18611543b 100644 (file)
@@ -258,6 +258,9 @@ public:
 
     virtual IntPoint currentMousePosition() const;
 
+    // FIXME: Remove this method once plugin loading is decoupled from layout.
+    void flushAnyPendingPostLayoutTasks();
+
 protected:
     virtual bool scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect);
     virtual void scrollContentsSlowPath(const IntRect& updateRect);
index 8918613e9ec89eda80e99e3da14d67782a821a9e..1342a9c0d0cfae982f4d3a0d025d7f1833ce69a1 100644 (file)
@@ -1,3 +1,15 @@
+2011-02-04  Adam Barth  <abarth@webkit.org>
+
+        Reviewed by Eric Seidel.
+
+        PluginDocuments don't create widgets for plugins on back/forward
+        https://bugs.webkit.org/show_bug.cgi?id=53474
+
+        Teach the test plugin how to call alert on load.
+
+        * DumpRenderTree/TestNetscapePlugIn/main.cpp:
+        (NPP_New):
+
 2011-02-04  Adam Roben  <aroben@apple.com>
 
         Add a test case for encode/decode of FormData/FormDataElement
index b4b7fa38a08f8ad41f4e8eea1a759ecbafeddf7a..1d960db8e579673261385a192edcb0e047154f75 100644 (file)
@@ -200,6 +200,9 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc
         else if (strcasecmp(argn[i], "src") == 0 &&
                  strcasecmp(argv[i], "data:application/x-webkit-test-netscape,returnerrorfromnewstream") == 0)
             obj->returnErrorFromNewStream = TRUE;
+        else if (strcasecmp(argn[i], "src") == 0 &&
+                 strcasecmp(argv[i], "data:application/x-webkit-test-netscape,alertwhenloaded") == 0)
+            executeScript(obj, "alert('Plugin Loaded!')");
         else if (strcasecmp(argn[i], "onSetWindow") == 0 && !obj->onSetWindow)
             obj->onSetWindow = strdup(argv[i]);
         else if (strcasecmp(argn[i], "onNew") == 0 && !onNewScript)