Title: [95471] trunk
Revision
95471
Author
dim...@chromium.org
Date
2011-09-19 14:05:28 -0700 (Mon, 19 Sep 2011)

Log Message

[Chromium] Crash after magic iframe transfer for Pepper/NaCl plugins.
https://bugs.webkit.org/show_bug.cgi?id=68267
Make adoptNode() to not enable live iframe transfer when the iframe's subtree contains plugins.

Reviewed by Adam Barth.

Source/WebCore:

Test: fast/frames/iframe-reparenting-embed-elements.html

* dom/Document.cpp:
(WebCore::Document::adoptNode):
* html/HTMLFrameElementBase.cpp:
(WebCore::hasPluginElements):
(WebCore::HTMLFrameElementBase::canRemainAliveOnRemovalFromTree):
* html/HTMLFrameElementBase.h:

LayoutTests:

* fast/frames/iframe-reparenting-embed-elements-expected.txt: Added.
* fast/frames/iframe-reparenting-embed-elements.html: Added.
* fast/frames/resources/iframe-reparenting-embed-frame1.html: Added.
* fast/frames/resources/iframe-reparenting-embed-iframe.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (95470 => 95471)


--- trunk/LayoutTests/ChangeLog	2011-09-19 20:55:48 UTC (rev 95470)
+++ trunk/LayoutTests/ChangeLog	2011-09-19 21:05:28 UTC (rev 95471)
@@ -1,3 +1,16 @@
+2011-09-19  Dmitry Titov  <dim...@chromium.org>
+
+        [Chromium] Crash after magic iframe transfer for Pepper/NaCl plugins.
+        https://bugs.webkit.org/show_bug.cgi?id=68267
+        Make adoptNode() to not enable live iframe transfer when the iframe's subtree contains plugins.
+
+        Reviewed by Adam Barth.
+
+        * fast/frames/iframe-reparenting-embed-elements-expected.txt: Added.
+        * fast/frames/iframe-reparenting-embed-elements.html: Added.
+        * fast/frames/resources/iframe-reparenting-embed-frame1.html: Added.
+        * fast/frames/resources/iframe-reparenting-embed-iframe.html: Added.
+
 2011-09-19  Abhishek Arya  <infe...@chromium.org>
 
         Issues with merging ruby bases.

Added: trunk/LayoutTests/fast/frames/iframe-reparenting-embed-elements-expected.txt (0 => 95471)


--- trunk/LayoutTests/fast/frames/iframe-reparenting-embed-elements-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/frames/iframe-reparenting-embed-elements-expected.txt	2011-09-19 21:05:28 UTC (rev 95471)
@@ -0,0 +1,12 @@
+This test moves an iframe between two documents 3 times: without plugins, with <embed> tag and then with <object> tag.
+
+Only the attempt without plugin elements should succeed. The presence of plugin elements should prevent the document.adoptNode() method from triggering live transfer - in which case the iframe will be reloaded.
+
+Test succeeds if there are 'PASS' messages below and no 'FAIL' messages.
+
+ 
+PASS: Test without plugins
+PASS: Test with <embed>
+PASS: Test with <object>
+Test Finished.
+
Property changes on: trunk/LayoutTests/fast/frames/iframe-reparenting-embed-elements-expected.txt
___________________________________________________________________

Added: svn:eol-style

Added: trunk/LayoutTests/fast/frames/iframe-reparenting-embed-elements.html (0 => 95471)


--- trunk/LayoutTests/fast/frames/iframe-reparenting-embed-elements.html	                        (rev 0)
+++ trunk/LayoutTests/fast/frames/iframe-reparenting-embed-elements.html	2011-09-19 21:05:28 UTC (rev 95471)
@@ -0,0 +1,69 @@
+<html>
+<script>
+function log(message) {
+  document.getElementById("log").innerText += message + "\n";
+}
+
+function verifyResult(message, actualToken, expectedToReload) {
+  var success = (expectedToReload != (actualToken == "modified"));
+  log((success ? "PASS" : "FAIL") + ": " + message);
+}
+
+function transferIframe(testStepDescription, expectedToReload, nextTest)
+{
+  var iframe = frame1.contentDocument.getElementsByTagName("iframe")[0];
+  if (iframe.contentWindow.token != "loaded")
+    log("FAIL: invalid initial state of test iframe");
+
+  iframe.contentWindow.token = "modified";
+
+  frame1.contentDocument.adoptNode(iframe);
+  frame2.contentDocument.body.appendChild(iframe);
+  verifyResult(testStepDescription, iframe.contentWindow.token, expectedToReload);
+
+  frame1._onload_ = nextTest;
+  frame1.contentWindow.location.reload();
+}
+
+function finish()
+{
+  log("Test Finished.");
+  if (window.layoutTestController)
+      layoutTestController.notifyDone();
+}
+
+function test() {
+  if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.waitUntilDone();
+  }
+
+  frame1 = document.getElementById("frame1");
+  frame2 = document.getElementById("frame2");
+
+  transferIframe("Test without plugins", false, test1);
+}
+
+function test1() {
+  var iframe = frame1.contentDocument.getElementsByTagName("iframe")[0];
+  iframe.contentDocument.body.appendChild(iframe.contentDocument.createElement("embed"));
+  transferIframe("Test with <embed>", true, test2);
+}
+
+function test2() {
+  var iframe = frame1.contentDocument.getElementsByTagName("iframe")[0];
+  iframe.contentDocument.body.appendChild(iframe.contentDocument.createElement("object"));
+  transferIframe("Test with <object>", true, finish);
+}
+
+</script>
+<body _onload_=test()>
+<p>This test moves an iframe between two documents 3 times: without plugins, with &lt;embed&gt; tag and then with &lt;object&gt; tag.</p>
+<p>Only the attempt without plugin elements should succeed. The presence of plugin elements should prevent the document.adoptNode() method from 
+triggering live transfer - in which case the iframe will be reloaded.</p>
+<p>Test succeeds if there are 'PASS' messages below and no 'FAIL' messages.</p>
+<iframe id=frame1 src=""
+<iframe id=frame2 src=""
+<pre id=log></pre>
+</body>
+</html>
Property changes on: trunk/LayoutTests/fast/frames/iframe-reparenting-embed-elements.html
___________________________________________________________________

Added: svn:eol-style

Added: trunk/LayoutTests/fast/frames/resources/iframe-reparenting-embed-frame1.html (0 => 95471)


--- trunk/LayoutTests/fast/frames/resources/iframe-reparenting-embed-frame1.html	                        (rev 0)
+++ trunk/LayoutTests/fast/frames/resources/iframe-reparenting-embed-frame1.html	2011-09-19 21:05:28 UTC (rev 95471)
@@ -0,0 +1,2 @@
+<body>
+<iframe src=""
Property changes on: trunk/LayoutTests/fast/frames/resources/iframe-reparenting-embed-frame1.html
___________________________________________________________________

Added: svn:eol-style

Added: trunk/LayoutTests/fast/frames/resources/iframe-reparenting-embed-iframe.html (0 => 95471)


--- trunk/LayoutTests/fast/frames/resources/iframe-reparenting-embed-iframe.html	                        (rev 0)
+++ trunk/LayoutTests/fast/frames/resources/iframe-reparenting-embed-iframe.html	2011-09-19 21:05:28 UTC (rev 95471)
@@ -0,0 +1,10 @@
+<script>
+token = "loading";
+
+function init()
+{
+    token = "loaded";
+}
+
+</script>
+<body _onload_=init()>
Property changes on: trunk/LayoutTests/fast/frames/resources/iframe-reparenting-embed-iframe.html
___________________________________________________________________

Added: svn:eol-style

Modified: trunk/Source/WebCore/ChangeLog (95470 => 95471)


--- trunk/Source/WebCore/ChangeLog	2011-09-19 20:55:48 UTC (rev 95470)
+++ trunk/Source/WebCore/ChangeLog	2011-09-19 21:05:28 UTC (rev 95471)
@@ -1,3 +1,20 @@
+2011-09-19  Dmitry Titov  <dim...@chromium.org>
+
+        [Chromium] Crash after magic iframe transfer for Pepper/NaCl plugins.
+        https://bugs.webkit.org/show_bug.cgi?id=68267
+        Make adoptNode() to not enable live iframe transfer when the iframe's subtree contains plugins.
+
+        Reviewed by Adam Barth.
+
+        Test: fast/frames/iframe-reparenting-embed-elements.html
+
+        * dom/Document.cpp:
+        (WebCore::Document::adoptNode):
+        * html/HTMLFrameElementBase.cpp:
+        (WebCore::hasPluginElements):
+        (WebCore::HTMLFrameElementBase::canRemainAliveOnRemovalFromTree):
+        * html/HTMLFrameElementBase.h:
+
 2011-09-19  Abhishek Arya  <infe...@chromium.org>
 
         Issues with merging ruby bases.

Modified: trunk/Source/WebCore/dom/Document.cpp (95470 => 95471)


--- trunk/Source/WebCore/dom/Document.cpp	2011-09-19 20:55:48 UTC (rev 95470)
+++ trunk/Source/WebCore/dom/Document.cpp	2011-09-19 21:05:28 UTC (rev 95471)
@@ -944,7 +944,7 @@
                 ec = HIERARCHY_REQUEST_ERR;
                 return 0;
             }
-            iframe->setRemainsAliveOnRemovalFromTree(attached() && source->attached());
+            iframe->setRemainsAliveOnRemovalFromTree(attached() && source->attached() && iframe->canRemainAliveOnRemovalFromTree());
         }
 
         if (source->parentNode())

Modified: trunk/Source/WebCore/html/HTMLFrameElementBase.cpp (95470 => 95471)


--- trunk/Source/WebCore/html/HTMLFrameElementBase.cpp	2011-09-19 20:55:48 UTC (rev 95470)
+++ trunk/Source/WebCore/html/HTMLFrameElementBase.cpp	2011-09-19 21:05:28 UTC (rev 95471)
@@ -44,6 +44,33 @@
 
 using namespace HTMLNames;
 
+// Helper to check if the Frame's document contains elements that can instantiate plugins.
+// Does a recursive check for nested Frames too.
+static bool hasPluginElements(Frame* frame)
+{
+    if (!frame)
+        return false;
+
+    // Search for a plugin element in this document.
+    Document* document = frame->document();
+    for (Node* node = document->firstChild(); node; node = node->traverseNextNode(document)) {
+        if (!node->isElementNode())
+            continue;
+
+        Element* element = static_cast<Element*>(node);
+        if (element->hasLocalName(embedTag) || element->hasLocalName(objectTag))
+            return true;
+    }
+
+    // Do the same for the nested frames.
+    for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
+        if (hasPluginElements(child))
+            return true;
+    }
+
+    return false;
+}
+
 HTMLFrameElementBase::HTMLFrameElementBase(const QualifiedName& tagName, Document* document)
     : HTMLFrameOwnerElement(tagName, document)
     , m_scrolling(ScrollbarAuto)
@@ -251,8 +278,18 @@
     return renderBox()->height();
 }
 
+// Some types of content can restrict the ability to move the iframes between pages.
+// For example, the plugin infrastructure of an embedder may associate the plugin instances
+// with the top-level Frame for tracking various resources and failure to transfer those
+// resources correctly may lead to crashes and other ill effects (https://bugs.webkit.org/show_bug.cgi?id=68267)
+bool HTMLFrameElementBase::canRemainAliveOnRemovalFromTree()
+{
+    return !hasPluginElements(contentFrame());
+}
+
 void HTMLFrameElementBase::setRemainsAliveOnRemovalFromTree(bool value)
 {
+    ASSERT(!value || canRemainAliveOnRemovalFromTree());
     m_remainsAliveOnRemovalFromTree = value;
 
     // There is a possibility that JS will do document.adoptNode() on this element but will not insert it into the tree.

Modified: trunk/Source/WebCore/html/HTMLFrameElementBase.h (95470 => 95471)


--- trunk/Source/WebCore/html/HTMLFrameElementBase.h	2011-09-19 20:55:48 UTC (rev 95470)
+++ trunk/Source/WebCore/html/HTMLFrameElementBase.h	2011-09-19 21:05:28 UTC (rev 95471)
@@ -42,6 +42,7 @@
     int width();
     int height();
 
+    bool canRemainAliveOnRemovalFromTree();
     void setRemainsAliveOnRemovalFromTree(bool);
 #if ENABLE(FULLSCREEN_API)
     virtual bool allowFullScreen() const;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to