Modified: trunk/LayoutTests/ChangeLog (88417 => 88418)
--- trunk/LayoutTests/ChangeLog 2011-06-09 03:42:40 UTC (rev 88417)
+++ trunk/LayoutTests/ChangeLog 2011-06-09 03:55:17 UTC (rev 88418)
@@ -1,3 +1,14 @@
+2011-06-08 Hayato Ito <hay...@chromium.org>
+
+ Reviewed by Hajime Morita.
+
+ Makes sure that document.activeElement won't be an element in shadow root.
+
+ https://bugs.webkit.org/show_bug.cgi?id=61413
+
+ * fast/dom/shadow/activeelement-should-be-shadowhost-expected.txt: Added.
+ * fast/dom/shadow/activeelement-should-be-shadowhost.html: Added.
+
2011-06-08 Kent Tamura <tk...@chromium.org>
[Mac][GTK][Qt] Rebaseline for r88415, and remove old images.
Added: trunk/LayoutTests/fast/dom/shadow/activeelement-should-be-shadowhost.html (0 => 88418)
--- trunk/LayoutTests/fast/dom/shadow/activeelement-should-be-shadowhost.html (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/activeelement-should-be-shadowhost.html 2011-06-09 03:55:17 UTC (rev 88418)
@@ -0,0 +1,145 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>
+Makes sure that document.activeElement returns a shadow host when a element in the correspoinding shadow tree is focused.
+</p>
+<pre id="console"></pre>
+<script>
+function describe(obj) {
+ if (obj === document)
+ return 'top';
+ if (obj.defaultView && obj.defaultView.frameElement)
+ return describe(obj.defaultView.frameElement);
+ return describe(obj.ownerDocument) + '/' + obj.id;
+}
+
+function print(s) {
+ document.getElementById('console').textContent += s + '\n';
+}
+
+function assertActiveElement(doc, expected) {
+ if (doc.activeElement === expected)
+ print('PASS: ' + describe(doc) + ' document.activeElement is ' + describe(doc.activeElement));
+ else
+ print('FAIL: ' + describe(doc) + ' document.activeElement is ' + describe(doc.activeElement) + ' but expected ' + describe(expected));
+}
+
+if (window.layoutTestController) {
+ layoutTestController.dumpAsText();
+
+ function shadowRoot(shadowHost) {
+ return layoutTestController.ensureShadowRoot(shadowHost);
+ }
+
+ function appendChildToShadow(shadowHost, child) {
+ return shadowRoot(shadowHost).appendChild(child)
+ }
+
+ function appendShadowHost(doc, parent) {
+ var shadowHost = doc.createElement('p');
+ shadowHost.tabIndex = 1; // Makes sure that the shadow host is focusable.
+ parent = parent || doc.body;
+ return parent.appendChild(shadowHost);
+ }
+
+ // For readability, I noted a DOM tree which is under the test here.
+ //
+ // - document (doc0)
+ // - shadow0
+ // - input0
+ // - iframe1 (doc1)
+ // - shadow1
+ // - input1
+ // - shadow2
+ // - shadow2_1
+ // - input2
+ // - shadow3
+ // - iframe3 (doc3)
+ // - input3
+ // - iframe4 (doc4)
+ // - iframe4_1 (doc4_1)
+ // - input4
+ var doc0 = document;
+ var shadow0 = appendShadowHost(doc0);
+ var input0 = appendChildToShadow(shadow0, doc0.createElement('input'));
+
+ var iframe1 = doc0.body.appendChild(doc0.createElement('iframe'));
+ var doc1 = iframe1.contentDocument;
+ var shadow1 = appendShadowHost(doc1);
+ var input1 = appendChildToShadow(shadow1, doc1.createElement('input'));
+
+ var shadow2 = appendShadowHost(doc0);
+ var shadow2_1 = appendShadowHost(doc0, shadowRoot(shadow2));
+ var input2 = appendChildToShadow(shadow2_1, doc0.createElement('input'));
+
+ var shadow3 = appendShadowHost(doc0);
+ var iframe3 = appendChildToShadow(shadow3, doc0.createElement('iframe'))
+ var doc3 = iframe3.contentDocument;
+ var input3 = doc3.body.appendChild(doc3.createElement('input'))
+
+ // Althought this subtree (iframe4) doesn't contain any explicit shadow hosts,
+ // this might be useful as a reference.
+ var iframe4 = doc0.body.appendChild(doc0.createElement('iframe'));
+ var doc4 = iframe4.contentDocument;
+ var iframe4_1 = doc4.body.appendChild(doc4.createElement('iframe'));
+ var doc4_1 = iframe4_1.contentDocument;
+ var input4 = doc4_1.body.appendChild(doc4_1.createElement('input'));
+
+ // Set up IDs for logging.
+ var elements = ['shadow0','shadow1', 'shadow2', 'shadow2_1', 'shadow3',
+ 'input0', 'input1', 'input2', 'input3', 'input4',
+ 'iframe1', 'iframe3', 'iframe4', 'iframe4_1'];
+ for (var i = 0; i < elements.length; i++) {
+ var id = elements[i];
+ window[id].id = id;
+ }
+ var docs = ['doc0', 'doc1', 'doc3', 'doc4', 'doc4_1'];
+ for (var i = 0; i < docs.length; i++) {
+ var id = docs[i];
+ window[id].body.id = id + '_body';
+ }
+
+ print('\nFocusing ' + describe(input0));
+ input0.focus();
+ assertActiveElement(doc0, shadow0);
+ assertActiveElement(doc1, doc1.body);
+ assertActiveElement(doc3, doc3.body);
+ assertActiveElement(doc4, doc4.body);
+ assertActiveElement(doc4_1, doc4_1.body);
+
+ print('\nFocusing ' + describe(input1));
+ input1.focus();
+ assertActiveElement(doc0, iframe1);
+ assertActiveElement(doc1, shadow1);
+ assertActiveElement(doc3, doc3.body);
+ assertActiveElement(doc4, doc4.body);
+ assertActiveElement(doc4_1, doc4_1.body);
+
+ print('\nFocusing ' + describe(input2));
+ input2.focus();
+ assertActiveElement(doc0, shadow2);
+ assertActiveElement(doc1, doc1.body);
+ assertActiveElement(doc3, doc3.body);
+ assertActiveElement(doc4, doc4.body);
+ assertActiveElement(doc4_1, doc4_1.body);
+
+ print('\nFocusing ' + describe(input3));
+ input3.focus();
+ assertActiveElement(doc0, shadow3);
+ assertActiveElement(doc1, doc1.body);
+ assertActiveElement(doc3, input3);
+ assertActiveElement(doc4, doc4.body);
+ assertActiveElement(doc4_1, doc4_1.body);
+
+ print('\nFocusing ' + describe(input4));
+ input4.focus();
+ assertActiveElement(doc0, iframe4);
+ assertActiveElement(doc1, doc1.body);
+ assertActiveElement(doc3, doc3.body);
+ assertActiveElement(doc4, iframe4_1);
+ assertActiveElement(doc4_1, input4);
+}
+</script>
+</body>
+</html>
Modified: trunk/Source/WebCore/html/HTMLDocument.cpp (88417 => 88418)
--- trunk/Source/WebCore/html/HTMLDocument.cpp 2011-06-09 03:42:40 UTC (rev 88417)
+++ trunk/Source/WebCore/html/HTMLDocument.cpp 2011-06-09 03:55:17 UTC (rev 88418)
@@ -136,17 +136,29 @@
Document::setDesignMode(mode);
}
+static Node* focusedFrameOwnerElement(Frame* focusedFrame, Frame* currentFrame)
+{
+ for (; focusedFrame; focusedFrame = focusedFrame->tree()->parent()) {
+ if (focusedFrame->tree()->parent() == currentFrame)
+ return focusedFrame->ownerElement();
+ }
+ return 0;
+}
+
Element* HTMLDocument::activeElement()
{
- if (Node* node = focusedNode()) {
- if (node->isElementNode())
- return static_cast<Element*>(node);
- } else if (Page* page = this->page()) {
- for (Frame* focusedFrame = page->focusController()->focusedFrame(); focusedFrame; focusedFrame = focusedFrame->tree()->parent()) {
- if (focusedFrame->tree()->parent() == frame())
- return focusedFrame->ownerElement();
- }
+ Node* node = focusedNode();
+ if (!node && page())
+ node = focusedFrameOwnerElement(page()->focusController()->focusedFrame(), frame());
+ if (!node)
+ return body();
+ ASSERT(node->document() == this);
+ while (node->treeScope() != this) {
+ node = node->parentOrHostNode();
+ ASSERT(node);
}
+ if (node->isElementNode())
+ return toElement(node);
return body();
}