[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

dglazkov at chromium.org dglazkov at chromium.org
Wed Dec 22 15:48:39 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 22000f6d5445bbf2d2e0efa6d071ebcc9a72209e
Author: dglazkov at chromium.org <dglazkov at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Nov 12 19:49:40 2010 +0000

    2010-11-05  Dimitri Glazkov  <dglazkov at chromium.org>
    
            Reviewed by Darin Adler.
    
            Implement shadow DOM-aware event targeting and introduce EventContext to track the context of each event dispatch.
            https://bugs.webkit.org/show_bug.cgi?id=46015
    
            Added more test coverage around events crossing shadow DOM boundaries and tweaked existing tests.
    
            * fast/events/shadow-boundary-crossing-2-expected.txt: Added.
            * fast/events/shadow-boundary-crossing-2.html: Added.
            * fast/events/shadow-boundary-crossing.html: Tuned to better reflect its point:
                the event should indeed fire (it used to be swallowed), but its target
                should be a non-shadow node.
            * media/audio-delete-while-slider-thumb-clicked.html :  Tweaked to actually click on
                the scrubber thumb (it was off by 2 pixels).
    2010-11-05  Dimitri Glazkov  <dglazkov at chromium.org>
    
            Reviewed by Darin Adler.
    
            Implement shadow DOM-aware event targeting and introduce EventContext to track the context of each event dispatch.
            https://bugs.webkit.org/show_bug.cgi?id=46015
    
            Test: fast/events/shadow-boundary-crossing-2.html
    
            This patch adds the notion of EventContext (and a very similar-acting WindowEventContext, specifically
            for DOMWindow), an abstraction that carries information around dispatching an event for any given Node.
    
            This abstraction is necessary to ensure that events, fired from shadow DOM nodes are properly retargeted to
            appear as if they are coming from their host, thus never exposing the shadow DOM nodes to the world outside.
    
            * Android.mk: Added EventContext, WindowEventContext files.
            * CMakeLists.txt: Ditto.
            * GNUmakefile.am: Ditto.
            * WebCore.gypi: Ditto.
            * WebCore.pro: Ditto.
            * WebCore.xcodeproj/project.pbxproj: Ditto.
            * WebCore.vcproj/WebCore.vcproj: Ditto.
            * dom/ContainerNode.cpp:
            (WebCore::notifyChildInserted): Changed to be shadow DOM-aware.
            * dom/EventContext.cpp: Added.
            * dom/EventContext.h: Added.
            * dom/Node.cpp:
            (WebCore::Node::markAncestorsWithChildNeedsStyleRecalc): Changed to be shadow DOM-aware.
            (WebCore::Node::createRendererIfNeeded): Ditto.
            (WebCore::Node::parentOrHostNode): Added new helper method.
            (WebCore::Node::enclosingLinkEventParentOrSelf): Changed to be shadow DOM-aware.
            (WebCore::eventTargetRespectingSVGTargetRules): Collapsed two helper methods into one.
            (WebCore::Node::getEventAncestors): Renamed and refactored to collect a vector of EventContexts.
            (WebCore::Node::topEventContext): Added.
            (WebCore::eventHasListeners): Changed to use EventContexts.
            (WebCore::Node::dispatchGenericEvent): Ditto.
            * dom/Node.h: Removed eventParentNode that's no longer needed, added parentOrHostNode decl,
                and changed signature of eventAncestors to use EventContexts.
            * dom/Text.cpp:
            (WebCore::Text::createRenderer): Changed to be shadow DOM-aware.
            * dom/WindowEventContext.cpp: Added.
            * dom/WindowEventContext.h: Added.
            * inspector/InspectorDOMAgent.cpp:
            (WebCore::InspectorDOMAgent::getEventListenersForNode): Changed to use EventContexts.
            * page/EventHandler.cpp:
            (WebCore::EventHandler::updateMouseEventTargetNode): Removed code that's no longer necessary.
            * rendering/RenderTextControlMultiLine.cpp:
            (WebCore::RenderTextControlMultiLine::subtreeHasChanged): Removed event invocation that's
                no longer necessary.
            * rendering/ShadowElement.h: Made m_shadowParent a RefPtr to avoid stale references when parent
            is deleted.
            * rendering/TextControlInnerElements.cpp:
            (WebCore::TextControlInnerTextElement::defaultEventHandler): Flipped the condition back
                from where it was prior to r60418.
            * svg/SVGElement.cpp: Removed eventParentNode that's no longer needed.
            * svg/SVGElement.h: Ditto.
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@71934 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 4997500..9e4560c 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,20 @@
+2010-11-05  Dimitri Glazkov  <dglazkov at chromium.org>
+
+        Reviewed by Darin Adler.
+
+        Implement shadow DOM-aware event targeting and introduce EventContext to track the context of each event dispatch.
+        https://bugs.webkit.org/show_bug.cgi?id=46015
+
+        Added more test coverage around events crossing shadow DOM boundaries and tweaked existing tests.
+
+        * fast/events/shadow-boundary-crossing-2-expected.txt: Added.
+        * fast/events/shadow-boundary-crossing-2.html: Added.
+        * fast/events/shadow-boundary-crossing.html: Tuned to better reflect its point:
+            the event should indeed fire (it used to be swallowed), but its target
+            should be a non-shadow node.
+        * media/audio-delete-while-slider-thumb-clicked.html :  Tweaked to actually click on
+            the scrubber thumb (it was off by 2 pixels).
+
 2010-11-12  Mihai Parparita  <mihaip at chromium.org>
 
         Unreviewed Chromium expectations update.
diff --git a/LayoutTests/fast/events/shadow-boundary-crossing-2-expected.txt b/LayoutTests/fast/events/shadow-boundary-crossing-2-expected.txt
new file mode 100644
index 0000000..23d620b
--- /dev/null
+++ b/LayoutTests/fast/events/shadow-boundary-crossing-2-expected.txt
@@ -0,0 +1,7 @@
+Tests to ensure that shadow DOM boundary is not crossed during event propagation. Can only run within DRT.
+
+See bug 46015 for details.
+
+Mutation events should not propagate out of the shadow DOM: PASS
+Other events should be retargeted: PASS
+After event dispatch, the event object should not reveal shadow DOM: PASS
diff --git a/LayoutTests/fast/events/shadow-boundary-crossing-2.html b/LayoutTests/fast/events/shadow-boundary-crossing-2.html
new file mode 100644
index 0000000..3cf88b0
--- /dev/null
+++ b/LayoutTests/fast/events/shadow-boundary-crossing-2.html
@@ -0,0 +1,81 @@
+<html>
+<head>
+<script>
+
+var logDiv;
+
+function log(msg, success)
+{
+    logDiv.appendChild(document.createElement('div')).textContent = msg + ': ' + (success ? 'PASS' : 'FAIL');
+}
+
+function clickOn(element)
+{
+    if (!window.eventSender)
+        return;
+
+    var x = element.offsetLeft + element.offsetWidth / 2;
+    var y = element.offsetTop + element.offsetHeight / 2;
+    eventSender.mouseMoveTo(x, y);
+    eventSender.mouseDown();
+    eventSender.mouseUp();
+}
+
+var tests = {
+    mutationEventPropagation: function()
+    {
+        var textarea = document.body.appendChild(document.createElement('textarea'));
+        var mutationEventFired;
+        textarea.addEventListener('DOMSubtreeModified', function(e)
+        {
+            mutationEventFired = true;
+        }, false);
+        textarea.value = 'test';
+        // Trigger style recalc and sadly, the actual mutation of the textarea shadow DOM.
+        textarea.offsetHeight;
+        log('Mutation events should not propagate out of the shadow DOM', !mutationEventFired);
+        textarea.parentNode.removeChild(textarea);
+    },
+    eventInProgress: function()
+    {
+        var textInput = document.body.appendChild(document.createElement('input'));
+        textInput.addEventListener('click', function(e)
+        {
+            log('Other events should be retargeted', e.target == textInput);
+        }, false);
+        clickOn(textInput);
+        textInput.parentNode.removeChild(textInput);
+    },
+    finalEventObject: function()
+    {
+        var textInput = document.body.appendChild(document.createElement('input'));
+        var storedEvent;
+        textInput.addEventListener('click', function(e)
+        {
+            storedEvent = e;
+        }, false);
+        clickOn(textInput);
+        log('After event dispatch, the event object should not reveal shadow DOM', storedEvent && storedEvent.target == textInput);
+        textInput.parentNode.removeChild(textInput);
+    }
+};
+
+function runTest()
+{
+    if (window.layoutTestController)
+        layoutTestController.dumpAsText();
+
+    logDiv = document.getElementById('log');
+    for(var testName in tests) {
+        tests[testName]();
+    }
+}
+
+</script>
+</head>
+<body onload="runTest()">
+    <p>Tests to ensure that shadow DOM boundary is not crossed during event propagation. Can only run within DRT.
+    <p>See <a href="https://bugs.webkit.org/show_bug.cgi?id=46015">bug 46015</a> for details.
+    <div id="log"></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/fast/events/shadow-boundary-crossing.html b/LayoutTests/fast/events/shadow-boundary-crossing.html
index 623e067..e002333 100644
--- a/LayoutTests/fast/events/shadow-boundary-crossing.html
+++ b/LayoutTests/fast/events/shadow-boundary-crossing.html
@@ -2,11 +2,12 @@
 <head>
     <title></title>
     <script type="text/javascript">
-        var fired = false;
+        var success;
+        var target;
 
         function selectStart(event)
         {
-            fired = true;
+            success = event.target == target;
         }
 
         function test()
@@ -15,7 +16,7 @@
                 return;
             layoutTestController.dumpAsText();
 
-            var target = document.getElementById("target");
+            target = document.getElementById("target");
             var x = target.offsetLeft + target.offsetWidth / 2;
             var y = target.offsetTop + target.offsetHeight / 2;
 
@@ -23,7 +24,7 @@
             eventSender.mouseDown();
             eventSender.mouseUp();
 
-            document.getElementById("result").innerText = fired ? "FAIL" : "PASS";
+            document.getElementById("result").innerText = !success ? "FAIL" : "PASS";
         }
 
         addEventListener("selectstart", selectStart, true);
diff --git a/LayoutTests/media/audio-delete-while-slider-thumb-clicked.html b/LayoutTests/media/audio-delete-while-slider-thumb-clicked.html
index c5a16a8..8d25e8a 100644
--- a/LayoutTests/media/audio-delete-while-slider-thumb-clicked.html
+++ b/LayoutTests/media/audio-delete-while-slider-thumb-clicked.html
@@ -50,11 +50,11 @@
 
                 var audio = document.getElementById('audio');
 
-                var middle = audio.offsetLeft + (audio.offsetWidth / 2);
-                var bottom = audio.offsetTop + audio.offsetHeight;
+                var center = audio.offsetLeft + (audio.offsetWidth / 2);
+                var middle = audio.offsetTop + (audio.offsetHeight / 2);
                 
-                var x = middle + 16 + 16 + 8;
-                var y = bottom - 8;
+                var x = center + 16 + 16 + 8;
+                var y = middle;
 
                 // drag slider, leave the mouse down
                 log("clicking in controller");
diff --git a/WebCore/Android.mk b/WebCore/Android.mk
index 1421b63..923fdef 100644
--- a/WebCore/Android.mk
+++ b/WebCore/Android.mk
@@ -132,6 +132,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
 	dom/EntityReference.cpp \
 	dom/ErrorEvent.cpp \
 	dom/Event.cpp \
+	dom/EventContext.cpp \
 	dom/EventNames.cpp \
 	dom/EventTarget.cpp \
 	dom/ExceptionBase.cpp \
@@ -192,6 +193,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
 	dom/WebKitAnimationEvent.cpp \
 	dom/WebKitTransitionEvent.cpp \
 	dom/WheelEvent.cpp \
+	dom/WindowEventContext.cpp \
 	dom/XMLDocumentParser.cpp \
 	dom/XMLDocumentParserLibxml2.cpp \
 	dom/XMLDocumentParserScope.cpp \
diff --git a/WebCore/CMakeLists.txt b/WebCore/CMakeLists.txt
index 70c9cb0..7a2f98b 100644
--- a/WebCore/CMakeLists.txt
+++ b/WebCore/CMakeLists.txt
@@ -825,6 +825,7 @@ SET(WebCore_SOURCES
     dom/EntityReference.cpp
     dom/ErrorEvent.cpp
     dom/Event.cpp
+    dom/EventContext.cpp
     dom/EventNames.cpp
     dom/EventTarget.cpp
     dom/ExceptionBase.cpp
@@ -882,6 +883,7 @@ SET(WebCore_SOURCES
     dom/WebKitAnimationEvent.cpp
     dom/WebKitTransitionEvent.cpp
     dom/WheelEvent.cpp
+    dom/WindowEventContext.cpp
     dom/XMLDocumentParser.cpp
     dom/XMLDocumentParserLibxml2.cpp
     dom/XMLDocumentParserScope.cpp
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index a6beaf7..5ea291f 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,60 @@
+2010-11-05  Dimitri Glazkov  <dglazkov at chromium.org>
+
+        Reviewed by Darin Adler.
+
+        Implement shadow DOM-aware event targeting and introduce EventContext to track the context of each event dispatch.
+        https://bugs.webkit.org/show_bug.cgi?id=46015
+
+        Test: fast/events/shadow-boundary-crossing-2.html
+
+        This patch adds the notion of EventContext (and a very similar-acting WindowEventContext, specifically
+        for DOMWindow), an abstraction that carries information around dispatching an event for any given Node.
+
+        This abstraction is necessary to ensure that events, fired from shadow DOM nodes are properly retargeted to
+        appear as if they are coming from their host, thus never exposing the shadow DOM nodes to the world outside.
+
+        * Android.mk: Added EventContext, WindowEventContext files.
+        * CMakeLists.txt: Ditto.
+        * GNUmakefile.am: Ditto.
+        * WebCore.gypi: Ditto.
+        * WebCore.pro: Ditto.
+        * WebCore.xcodeproj/project.pbxproj: Ditto.
+        * WebCore.vcproj/WebCore.vcproj: Ditto.
+        * dom/ContainerNode.cpp:
+        (WebCore::notifyChildInserted): Changed to be shadow DOM-aware.
+        * dom/EventContext.cpp: Added.
+        * dom/EventContext.h: Added.
+        * dom/Node.cpp:
+        (WebCore::Node::markAncestorsWithChildNeedsStyleRecalc): Changed to be shadow DOM-aware.
+        (WebCore::Node::createRendererIfNeeded): Ditto.
+        (WebCore::Node::parentOrHostNode): Added new helper method.
+        (WebCore::Node::enclosingLinkEventParentOrSelf): Changed to be shadow DOM-aware.
+        (WebCore::eventTargetRespectingSVGTargetRules): Collapsed two helper methods into one.
+        (WebCore::Node::getEventAncestors): Renamed and refactored to collect a vector of EventContexts.
+        (WebCore::Node::topEventContext): Added.
+        (WebCore::eventHasListeners): Changed to use EventContexts.
+        (WebCore::Node::dispatchGenericEvent): Ditto.
+        * dom/Node.h: Removed eventParentNode that's no longer needed, added parentOrHostNode decl,
+            and changed signature of eventAncestors to use EventContexts.
+        * dom/Text.cpp:
+        (WebCore::Text::createRenderer): Changed to be shadow DOM-aware.
+        * dom/WindowEventContext.cpp: Added.
+        * dom/WindowEventContext.h: Added.
+        * inspector/InspectorDOMAgent.cpp:
+        (WebCore::InspectorDOMAgent::getEventListenersForNode): Changed to use EventContexts.
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::updateMouseEventTargetNode): Removed code that's no longer necessary.
+        * rendering/RenderTextControlMultiLine.cpp:
+        (WebCore::RenderTextControlMultiLine::subtreeHasChanged): Removed event invocation that's
+            no longer necessary.
+        * rendering/ShadowElement.h: Made m_shadowParent a RefPtr to avoid stale references when parent
+        is deleted.
+        * rendering/TextControlInnerElements.cpp:
+        (WebCore::TextControlInnerTextElement::defaultEventHandler): Flipped the condition back
+            from where it was prior to r60418.
+        * svg/SVGElement.cpp: Removed eventParentNode that's no longer needed.
+        * svg/SVGElement.h: Ditto.
+
 2010-11-12  Ryuan Choi  <ryuan.choi at samsung.com>
 
         Reviewed by Martin Robinson.
diff --git a/WebCore/GNUmakefile.am b/WebCore/GNUmakefile.am
index 7ab6259..a5ec07c 100644
--- a/WebCore/GNUmakefile.am
+++ b/WebCore/GNUmakefile.am
@@ -1135,8 +1135,10 @@ webcore_sources += \
 	WebCore/dom/ErrorEvent.cpp \
 	WebCore/dom/ErrorEvent.h \
 	WebCore/dom/Event.cpp \
-	WebCore/dom/EventException.h \
 	WebCore/dom/Event.h \
+	WebCore/dom/EventContext.cpp \
+	WebCore/dom/EventContext.h \
+	WebCore/dom/EventException.h \
 	WebCore/dom/EventListener.h \
 	WebCore/dom/EventNames.cpp \
 	WebCore/dom/EventNames.h \
@@ -1264,6 +1266,8 @@ webcore_sources += \
 	WebCore/dom/WebKitTransitionEvent.h \
 	WebCore/dom/WheelEvent.cpp \
 	WebCore/dom/WheelEvent.h \
+	WebCore/dom/WindowEventContext.cpp \
+	WebCore/dom/WindowEventContext.h \
 	WebCore/dom/XMLDocumentParser.cpp \
 	WebCore/dom/XMLDocumentParser.h \
 	WebCore/dom/XMLDocumentParserLibxml2.cpp \
diff --git a/WebCore/WebCore.gypi b/WebCore/WebCore.gypi
index eeaf9b2..6e414ec 100644
--- a/WebCore/WebCore.gypi
+++ b/WebCore/WebCore.gypi
@@ -1202,6 +1202,8 @@
             'dom/ErrorEvent.h',
             'dom/Event.cpp',
             'dom/Event.h',
+            'dom/EventContext.cpp',
+            'dom/EventContext.h',
             'dom/EventException.h',
             'dom/EventListener.h',
             'dom/EventNames.cpp',
@@ -1337,6 +1339,8 @@
             'dom/WebKitTransitionEvent.h',
             'dom/WheelEvent.cpp',
             'dom/WheelEvent.h',
+            'dom/WindowEventContext.cpp',
+            'dom/WindowEventContext.h',
             'dom/XMLDocumentParser.cpp',
             'dom/XMLDocumentParser.h',
             'dom/XMLDocumentParserLibxml2.cpp',
diff --git a/WebCore/WebCore.pro b/WebCore/WebCore.pro
index e1cd5a1..23128d2 100644
--- a/WebCore/WebCore.pro
+++ b/WebCore/WebCore.pro
@@ -713,6 +713,7 @@ SOURCES += \
     dom/EntityReference.cpp \
     dom/ErrorEvent.cpp \
     dom/Event.cpp \
+    dom/EventContext.cpp \
     dom/EventNames.cpp \
     dom/EventTarget.cpp \
     dom/ExceptionBase.cpp \
@@ -773,6 +774,7 @@ SOURCES += \
     dom/WebKitAnimationEvent.cpp \
     dom/WebKitTransitionEvent.cpp \
     dom/WheelEvent.cpp \
+    dom/WindowEventContext.cpp \
     dom/XMLDocumentParser.cpp \
     dom/XMLDocumentParserQt.cpp \
     dom/default/PlatformMessagePortChannel.cpp \
diff --git a/WebCore/WebCore.vcproj/WebCore.vcproj b/WebCore/WebCore.vcproj/WebCore.vcproj
index 1f18b40..7af4af8 100644
--- a/WebCore/WebCore.vcproj/WebCore.vcproj
+++ b/WebCore/WebCore.vcproj/WebCore.vcproj
@@ -42388,6 +42388,62 @@
 				>
 			</File>
 			<File
+				RelativePath="..\dom\EventContext.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug_Internal|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug_Cairo|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release_Cairo|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug_All|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\dom\EventContext.h"
+				>
+			</File>
+			<File
 				RelativePath="..\dom\EventException.h"
 				>
 			</File>
@@ -45476,6 +45532,62 @@
 				>
 			</File>
 			<File
+				RelativePath="..\dom\WindowEventContext.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug_Internal|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug_Cairo|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release_Cairo|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug_All|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\dom\WindowEventContext.h"
+				>
+			</File>
+			<File
 				RelativePath="..\dom\XMLDocumentParser.cpp"
 				>
 				<FileConfiguration
diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj
index 775b333..76b4fc6 100644
--- a/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -902,7 +902,11 @@
 		410B7E721045FAB000D8224F /* JSMessageEventCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 410B7E711045FAB000D8224F /* JSMessageEventCustom.cpp */; };
 		411046410FA222A600BA436A /* ScriptEventListener.h in Headers */ = {isa = PBXBuildFile; fileRef = 4110463F0FA222A600BA436A /* ScriptEventListener.h */; };
 		411046420FA222A600BA436A /* ScriptEventListener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 411046400FA222A600BA436A /* ScriptEventListener.cpp */; };
+		4123E569127B3041000FEEA7 /* WindowEventContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 4123E567127B3041000FEEA7 /* WindowEventContext.h */; };
+		4123E56A127B3041000FEEA7 /* WindowEventContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4123E568127B3041000FEEA7 /* WindowEventContext.cpp */; };
 		4127D5370F8AAB1D00E424F5 /* ScriptState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4127D5360F8AAB1D00E424F5 /* ScriptState.cpp */; };
+		4138D3351244054800323D33 /* EventContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 4138D3331244054800323D33 /* EventContext.h */; };
+		4138D3361244054800323D33 /* EventContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4138D3341244054800323D33 /* EventContext.cpp */; };
 		4162A450101145AE00DFF3ED /* DedicatedWorkerContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4162A44D101145AE00DFF3ED /* DedicatedWorkerContext.cpp */; };
 		4162A451101145AE00DFF3ED /* DedicatedWorkerContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 4162A44E101145AE00DFF3ED /* DedicatedWorkerContext.h */; };
 		4162A454101145E300DFF3ED /* JSDedicatedWorkerContextCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4162A453101145E300DFF3ED /* JSDedicatedWorkerContextCustom.cpp */; };
@@ -6997,7 +7001,11 @@
 		410B7E711045FAB000D8224F /* JSMessageEventCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSMessageEventCustom.cpp; sourceTree = "<group>"; };
 		4110463F0FA222A600BA436A /* ScriptEventListener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptEventListener.h; sourceTree = "<group>"; };
 		411046400FA222A600BA436A /* ScriptEventListener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptEventListener.cpp; sourceTree = "<group>"; };
+		4123E567127B3041000FEEA7 /* WindowEventContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowEventContext.h; sourceTree = "<group>"; };
+		4123E568127B3041000FEEA7 /* WindowEventContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WindowEventContext.cpp; sourceTree = "<group>"; };
 		4127D5360F8AAB1D00E424F5 /* ScriptState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScriptState.cpp; sourceTree = "<group>"; };
+		4138D3331244054800323D33 /* EventContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventContext.h; sourceTree = "<group>"; };
+		4138D3341244054800323D33 /* EventContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventContext.cpp; sourceTree = "<group>"; };
 		4162A44D101145AE00DFF3ED /* DedicatedWorkerContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DedicatedWorkerContext.cpp; path = workers/DedicatedWorkerContext.cpp; sourceTree = "<group>"; };
 		4162A44E101145AE00DFF3ED /* DedicatedWorkerContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DedicatedWorkerContext.h; path = workers/DedicatedWorkerContext.h; sourceTree = "<group>"; };
 		4162A44F101145AE00DFF3ED /* DedicatedWorkerContext.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = DedicatedWorkerContext.idl; path = workers/DedicatedWorkerContext.idl; sourceTree = "<group>"; };
@@ -18268,6 +18276,8 @@
 				85031B2B0A44EFC700F992E0 /* Event.cpp */,
 				85031B2C0A44EFC700F992E0 /* Event.h */,
 				14E836D209F8512000B85AE4 /* Event.idl */,
+				4138D3341244054800323D33 /* EventContext.cpp */,
+				4138D3331244054800323D33 /* EventContext.h */,
 				BC60D9090D2A17CE00B9918F /* EventException.h */,
 				BC60D90A0D2A17CE00B9918F /* EventException.idl */,
 				935FBC4409BA00B900E230B1 /* EventListener.h */,
@@ -18428,6 +18438,8 @@
 				85031B3A0A44EFC700F992E0 /* WheelEvent.cpp */,
 				85031B3B0A44EFC700F992E0 /* WheelEvent.h */,
 				93EEC1F709C2877700C515D1 /* WheelEvent.idl */,
+				4123E568127B3041000FEEA7 /* WindowEventContext.cpp */,
+				4123E567127B3041000FEEA7 /* WindowEventContext.h */,
 				F523D30902DE4476018635CA /* XMLDocumentParser.cpp */,
 				F523D30A02DE4476018635CA /* XMLDocumentParser.h */,
 				54C50F7A0E801DF3009832A0 /* XMLDocumentParserLibxml2.cpp */,
@@ -19594,6 +19606,7 @@
 				89878560122CA064003AABDA /* ErrorCallback.h in Headers */,
 				2ECF7AE210162B5800427DE7 /* ErrorEvent.h in Headers */,
 				85031B420A44EFC700F992E0 /* Event.h in Headers */,
+				4138D3351244054800323D33 /* EventContext.h in Headers */,
 				BC60D90C0D2A17CE00B9918F /* EventException.h in Headers */,
 				93C09A530B064DB3005ABD4D /* EventHandler.h in Headers */,
 				935FBC4509BA00B900E230B1 /* EventListener.h in Headers */,
@@ -21274,6 +21287,7 @@
 				85031B510A44EFC700F992E0 /* WheelEvent.h in Headers */,
 				9380F47409A11AB4001FDB34 /* Widget.h in Headers */,
 				939B02EF0EA2DBC400C54570 /* WidthIterator.h in Headers */,
+				4123E569127B3041000FEEA7 /* WindowEventContext.h in Headers */,
 				BC8243E90D0CFD7500460C8F /* WindowFeatures.h in Headers */,
 				E1E1BF00115FF6FB006F52CA /* WindowsKeyboardCodes.h in Headers */,
 				08203AA00ED8C35300B8B61A /* WMLAccessElement.h in Headers */,
@@ -22246,6 +22260,7 @@
 				893C480C1248BD3A002B3D86 /* EntrySync.cpp in Sources */,
 				2ECF7AE110162B5800427DE7 /* ErrorEvent.cpp in Sources */,
 				85031B410A44EFC700F992E0 /* Event.cpp in Sources */,
+				4138D3361244054800323D33 /* EventContext.cpp in Sources */,
 				93C09A810B064F00005ABD4D /* EventHandler.cpp in Sources */,
 				93C09A7F0B064EEF005ABD4D /* EventHandlerMac.mm in Sources */,
 				1CA19E050DC255950065A994 /* EventLoopMac.mm in Sources */,
@@ -23853,6 +23868,7 @@
 				9380F47309A11AB4001FDB34 /* Widget.cpp in Sources */,
 				9380F47809A11ACC001FDB34 /* WidgetMac.mm in Sources */,
 				939B02EE0EA2DBC400C54570 /* WidthIterator.cpp in Sources */,
+				4123E56A127B3041000FEEA7 /* WindowEventContext.cpp in Sources */,
 				BC8243E80D0CFD7500460C8F /* WindowFeatures.cpp in Sources */,
 				08203A9F0ED8C35300B8B61A /* WMLAccessElement.cpp in Sources */,
 				088C97510ECB6E28000534BA /* WMLAElement.cpp in Sources */,
diff --git a/WebCore/dom/ContainerNode.cpp b/WebCore/dom/ContainerNode.cpp
index cd16e01..075a78b 100644
--- a/WebCore/dom/ContainerNode.cpp
+++ b/WebCore/dom/ContainerNode.cpp
@@ -1008,7 +1008,8 @@ static void notifyChildInserted(Node* child)
     RefPtr<Node> c = child;
     RefPtr<Document> document = child->document();
 
-    if (c->parentNode() && c->parentNode()->inDocument())
+    Node* parentOrHostNode = c->parentOrHostNode();
+    if (parentOrHostNode && parentOrHostNode->inDocument())
         c->insertedIntoDocument();
     else
         c->insertedIntoTree(true);
diff --git a/WebCore/dom/DOMAllInOne.cpp b/WebCore/dom/DOMAllInOne.cpp
index c1d536a..2f3510d 100644
--- a/WebCore/dom/DOMAllInOne.cpp
+++ b/WebCore/dom/DOMAllInOne.cpp
@@ -69,6 +69,7 @@
 #include "EntityReference.cpp"
 #include "ErrorEvent.cpp"
 #include "Event.cpp"
+#include "EventContext.cpp"
 #include "EventNames.cpp"
 #include "EventTarget.cpp"
 #include "ExceptionBase.cpp"
@@ -126,5 +127,6 @@
 #include "WebKitAnimationEvent.cpp"
 #include "WebKitTransitionEvent.cpp"
 #include "WheelEvent.cpp"
+#include "WindowEventContext.cpp"
 #include "XMLDocumentParser.cpp"
 #include "XMLDocumentParserScope.cpp"
diff --git a/WebCore/dom/EventContext.cpp b/WebCore/dom/EventContext.cpp
new file mode 100644
index 0000000..2a5c521
--- /dev/null
+++ b/WebCore/dom/EventContext.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#include "config.h"
+#include "EventContext.h"
+
+#include "DOMWindow.h"
+#include "Document.h"
+#include "Event.h"
+#include "Node.h"
+
+namespace WebCore {
+
+EventContext::EventContext(PassRefPtr<Node> node, PassRefPtr<EventTarget> currentTarget, PassRefPtr<EventTarget> target)
+    : m_node(node)
+    , m_currentTarget(currentTarget)
+    , m_target(target)
+{
+}
+
+void EventContext::handleLocalEvents(Event* event) const
+{
+    event->setTarget(m_target.get());
+    event->setCurrentTarget(m_currentTarget.get());
+    m_node->handleLocalEvents(event);
+}
+
+}
diff --git a/WebCore/dom/EventContext.h b/WebCore/dom/EventContext.h
new file mode 100644
index 0000000..9bab9d4
--- /dev/null
+++ b/WebCore/dom/EventContext.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef EventContext_h
+#define EventContext_h
+
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class EventTarget;
+class Event;
+class Node;
+
+class EventContext {
+public:
+    // FIXME: Use ContainerNode instead of Node.
+    EventContext(PassRefPtr<Node>, PassRefPtr<EventTarget> currentTarget, PassRefPtr<EventTarget> target);
+
+    Node* node() const;
+    EventTarget* target() const;
+    void handleLocalEvents(Event*) const;
+
+private:
+    RefPtr<Node> m_node;
+    RefPtr<EventTarget> m_currentTarget;
+    RefPtr<EventTarget> m_target;
+};
+
+inline Node* EventContext::node() const
+{
+    return m_node.get();
+}
+
+inline EventTarget* EventContext::target() const
+{
+    return m_target.get();
+}
+
+}
+
+#endif // EventContext_h
diff --git a/WebCore/dom/Node.cpp b/WebCore/dom/Node.cpp
index e45baa4..e71c4bd 100644
--- a/WebCore/dom/Node.cpp
+++ b/WebCore/dom/Node.cpp
@@ -45,6 +45,7 @@
 #include "DynamicNodeList.h"
 #include "Element.h"
 #include "Event.h"
+#include "EventContext.h"
 #include "EventException.h"
 #include "EventHandler.h"
 #include "EventListener.h"
@@ -80,6 +81,7 @@
 #include "WebKitAnimationEvent.h"
 #include "WebKitTransitionEvent.h"
 #include "WheelEvent.h"
+#include "WindowEventContext.h"
 #include "XMLNames.h"
 #include "htmlediting.h"
 #include <wtf/HashSet.h>
@@ -734,9 +736,9 @@ inline void Node::setStyleChange(StyleChangeType changeType)
 
 inline void Node::markAncestorsWithChildNeedsStyleRecalc()
 {
-    for (ContainerNode* p = parentNode(); p && !p->childNeedsStyleRecalc(); p = p->parentNode())
+    for (ContainerNode* p = parentOrHostNode(); p && !p->childNeedsStyleRecalc(); p = p->parentOrHostNode())
         p->setChildNeedsStyleRecalc();
-    
+
     if (document()->childNeedsStyleRecalc())
         document()->scheduleStyleRecalc();
 }
@@ -1321,7 +1323,7 @@ void Node::createRendererIfNeeded()
 
     ASSERT(!renderer());
     
-    ContainerNode* parent = parentNode();    
+    ContainerNode* parent = parentOrHostNode();
     ASSERT(parent);
     
     RenderObject* parentRenderer = parent->renderer();
@@ -2239,14 +2241,9 @@ void Node::getSubresourceURLs(ListHashSet<KURL>& urls) const
     addSubresourceAttributeURLs(urls);
 }
 
-ContainerNode* Node::eventParentNode()
-{
-    return parentNode();
-}
-
 Node* Node::enclosingLinkEventParentOrSelf()
 {
-    for (Node* node = this; node; node = node->eventParentNode()) {
+    for (Node* node = this; node; node = node->parentOrHostNode()) {
         // For imagemaps, the enclosing link node is the associated area element not the image itself.
         // So we don't let images be the enclosingLinkNode, even though isLink sometimes returns true
         // for them.
@@ -2484,12 +2481,13 @@ void Node::handleLocalEvents(Event* event)
     fireEventListeners(event);
 }
 
-#if ENABLE(SVG)
-static inline SVGElementInstance* eventTargetAsSVGElementInstance(Node* referenceNode)
+static inline EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNode)
 {
     ASSERT(referenceNode);
+
+#if ENABLE(SVG)
     if (!referenceNode->isSVGElement())
-        return 0;
+        return referenceNode;
 
     // Spec: The event handling for the non-exposed tree works as if the referenced element had been textually included
     // as a deeply cloned child of the 'use' element, except that events are dispatched to the SVGElementInstance objects
@@ -2503,36 +2501,41 @@ static inline SVGElementInstance* eventTargetAsSVGElementInstance(Node* referenc
         if (SVGElementInstance* instance = static_cast<SVGUseElement*>(shadowTreeParentElement)->instanceForShadowTreeElement(referenceNode))
             return instance;
     }
+#endif
 
-    return 0;
+    return referenceNode;
 }
-#endif
 
-static inline EventTarget* eventTargetRespectingSVGTargetRules(Node* referenceNode)
+void Node::getEventAncestors(Vector<EventContext>& ancestors, EventTarget* originalTarget, EventDispatchBehavior behavior)
 {
-    ASSERT(referenceNode);
+    if (!inDocument())
+        return;
 
-#if ENABLE(SVG)
-    if (SVGElementInstance* instance = eventTargetAsSVGElementInstance(referenceNode)) {
-        ASSERT(instance->shadowTreeElement() == referenceNode);
-        return instance;
-    }
-#endif
+    EventTarget* target = originalTarget;
+    Node* ancestor = this;
+    bool shouldSkipNextAncestor = false;
+    while (true) {
+        if (ancestor->isShadowNode()) {
+            if (behavior == StayInsideShadowDOM)
+                return;
+            ancestor = ancestor->shadowParentNode();
+            if (!shouldSkipNextAncestor)
+                target = ancestor;
+        } else
+            ancestor = ancestor->parentNode();
 
-    return referenceNode;
-}
+        if (!ancestor)
+            return;
 
-void Node::eventAncestors(Vector<RefPtr<ContainerNode> > &ancestors)
-{
-    if (inDocument()) {
-        for (ContainerNode* ancestor = eventParentNode(); ancestor; ancestor = ancestor->eventParentNode()) {
 #if ENABLE(SVG)
-            // Skip <use> shadow tree elements.
-            if (ancestor->isSVGElement() && ancestor->isShadowNode())
-                continue;
+        // Skip SVGShadowTreeRootElement.
+        shouldSkipNextAncestor = ancestor->isSVGElement() && ancestor->isShadowNode();
+        if (shouldSkipNextAncestor)
+            continue;
 #endif
-            ancestors.append(ancestor);
-        }
+        // FIXME: Unroll the extra loop inside eventTargetRespectingSVGTargetRules into this loop.
+        ancestors.append(EventContext(ancestor, eventTargetRespectingSVGTargetRules(ancestor), target));
+
     }
 }
 
@@ -2547,6 +2550,11 @@ bool Node::dispatchEvent(PassRefPtr<Event> prpEvent)
     return dispatchGenericEvent(event.release());
 }
 
+static const EventContext* topEventContext(const Vector<EventContext>& ancestors)
+{
+    return ancestors.isEmpty() ? 0 : &ancestors.last();
+}
+
 bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent)
 {
     RefPtr<Event> event(prpEvent);
@@ -2559,20 +2567,13 @@ bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent)
     // If the node is not in a document just send the event to it.
     // Be sure to ref all of nodes since event handlers could result in the last reference going away.
     RefPtr<Node> thisNode(this);
-    Vector<RefPtr<ContainerNode> > ancestors;
-    eventAncestors(ancestors);
+    RefPtr<EventTarget> originalTarget = event->target();
+    Vector<EventContext> ancestors;
+    getEventAncestors(ancestors, originalTarget.get(), event->isMutationEvent() ? StayInsideShadowDOM : RetargetEvent);
 
-    // Set up a pointer to indicate whether / where to dispatch window events.
-    // We don't dispatch load events to the window. That quirk was originally
-    // added because Mozilla doesn't propagate load events to the window object.
-    DOMWindow* targetForWindowEvents = 0;
-    if (event->type() != eventNames().loadEvent) {
-        Node* topLevelContainer = ancestors.isEmpty() ? this : ancestors.last().get();
-        if (topLevelContainer->isDocumentNode())
-            targetForWindowEvents = static_cast<Document*>(topLevelContainer)->domWindow();
-    }
+    WindowEventContext windowContext(event.get(), this, topEventContext(ancestors));
 
-    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(document(), *event, targetForWindowEvents, this, ancestors);
+    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(document(), *event, windowContext.window(), this, ancestors);
 
     // Give the target node a chance to do some work before DOM event handlers get a crack.
     void* data = preDispatchEventHandler(event.get());
@@ -2582,22 +2583,17 @@ bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent)
     // Trigger capturing event handlers, starting at the top and working our way down.
     event->setEventPhase(Event::CAPTURING_PHASE);
 
-    if (targetForWindowEvents) {
-        event->setCurrentTarget(targetForWindowEvents);
-        targetForWindowEvents->fireEventListeners(event.get());
-        if (event->propagationStopped())
-            goto doneDispatching;
-    }
+    if (windowContext.handleLocalEvents(event.get()) && event->propagationStopped())
+        goto doneDispatching;
+
     for (size_t i = ancestors.size(); i; --i) {
-        ContainerNode* ancestor = ancestors[i - 1].get();
-        event->setCurrentTarget(eventTargetRespectingSVGTargetRules(ancestor));
-        ancestor->handleLocalEvents(event.get());
+        ancestors[i - 1].handleLocalEvents(event.get());
         if (event->propagationStopped())
             goto doneDispatching;
     }
 
     event->setEventPhase(Event::AT_TARGET);
-
+    event->setTarget(originalTarget.get());
     event->setCurrentTarget(eventTargetRespectingSVGTargetRules(this));
     handleLocalEvents(event.get());
     if (event->propagationStopped())
@@ -2609,21 +2605,15 @@ bool Node::dispatchGenericEvent(PassRefPtr<Event> prpEvent)
 
         size_t size = ancestors.size();
         for (size_t i = 0; i < size; ++i) {
-            ContainerNode* ancestor = ancestors[i].get();
-            event->setCurrentTarget(eventTargetRespectingSVGTargetRules(ancestor));
-            ancestor->handleLocalEvents(event.get());
-            if (event->propagationStopped() || event->cancelBubble())
-                goto doneDispatching;
-        }
-        if (targetForWindowEvents) {
-            event->setCurrentTarget(targetForWindowEvents);
-            targetForWindowEvents->fireEventListeners(event.get());
+            ancestors[i].handleLocalEvents(event.get());
             if (event->propagationStopped() || event->cancelBubble())
                 goto doneDispatching;
         }
+        windowContext.handleLocalEvents(event.get());
     }
 
 doneDispatching:
+    event->setTarget(originalTarget.get());
     event->setCurrentTarget(0);
     event->setEventPhase(0);
 
@@ -2644,8 +2634,7 @@ doneDispatching:
         if (event->bubbles()) {
             size_t size = ancestors.size();
             for (size_t i = 0; i < size; ++i) {
-                ContainerNode* ancestor = ancestors[i].get();
-                ancestor->defaultEventHandler(event.get());
+                ancestors[i].node()->defaultEventHandler(event.get());
                 ASSERT(!event->defaultPrevented());
                 if (event->defaultHandled())
                     goto doneWithDefault;
@@ -2655,6 +2644,10 @@ doneDispatching:
 
 doneWithDefault:
 
+    // Ensure that after event dispatch, the event's target object is the
+    // outermost shadow DOM boundary.
+    event->setTarget(windowContext.target());
+    event->setCurrentTarget(0);
     InspectorInstrumentation::didDispatchEvent(cookie);
 
     return !event->defaultPrevented();
diff --git a/WebCore/dom/Node.h b/WebCore/dom/Node.h
index 3c6c199..675de04 100644
--- a/WebCore/dom/Node.h
+++ b/WebCore/dom/Node.h
@@ -49,6 +49,7 @@ class Document;
 class DynamicNodeList;
 class Element;
 class Event;
+class EventContext;
 class EventListener;
 class FloatPoint;
 class Frame;
@@ -85,6 +86,11 @@ enum StyleChangeType {
     SyntheticStyleChange = 3 << nodeStyleChangeShift
 };
 
+enum EventDispatchBehavior {
+    RetargetEvent,
+    StayInsideShadowDOM
+};
+
 class Node : public EventTarget, public TreeShared<ContainerNode>, public ScriptWrappable {
     friend class Document;
 public:
@@ -204,16 +210,14 @@ public:
     Node* shadowAncestorNode();
     Node* shadowTreeRootNode();
     bool isInShadowTree();
-
-    // The node's parent for the purpose of event capture and bubbling.
-    virtual ContainerNode* eventParentNode();
+    // Node's parent or shadow tree host.
+    ContainerNode* parentOrHostNode();
 
     // Returns the enclosing event parent node (or self) that, when clicked, would trigger a navigation.
     Node* enclosingLinkEventParentOrSelf();
 
     // Node ancestors when concerned about event flow.
-    // FIXME: Should be named getEventAncestors.
-    void eventAncestors(Vector<RefPtr<ContainerNode> > &ancestors);
+    void getEventAncestors(Vector<EventContext>& ancestors, EventTarget*, EventDispatchBehavior = RetargetEvent);
 
     bool isBlockFlow() const;
     bool isBlockFlowOrBlockTable() const;
@@ -693,6 +697,13 @@ inline void addSubresourceURL(ListHashSet<KURL>& urls, const KURL& url)
         urls.add(url);
 }
 
+inline ContainerNode* Node::parentOrHostNode()
+{
+    if (ContainerNode* parent = parentNode())
+        return parent;
+    return shadowParentNode();
+}
+
 } //namespace
 
 #ifndef NDEBUG
diff --git a/WebCore/dom/Text.cpp b/WebCore/dom/Text.cpp
index 6271f11..47c532e 100644
--- a/WebCore/dom/Text.cpp
+++ b/WebCore/dom/Text.cpp
@@ -240,9 +240,10 @@ bool Text::rendererIsNeeded(RenderStyle *style)
 RenderObject* Text::createRenderer(RenderArena* arena, RenderStyle*)
 {
 #if ENABLE(SVG)
-    if (parentNode()->isSVGElement()
+    Node* parentOrHost = parentOrHostNode();
+    if (parentOrHost->isSVGElement()
 #if ENABLE(SVG_FOREIGN_OBJECT)
-        && !parentNode()->hasTagName(SVGNames::foreignObjectTag)
+        && !parentOrHost->hasTagName(SVGNames::foreignObjectTag)
 #endif
     )
         return new (arena) RenderSVGInlineText(this, dataImpl());
diff --git a/WebCore/dom/WindowEventContext.cpp b/WebCore/dom/WindowEventContext.cpp
new file mode 100644
index 0000000..0709330
--- /dev/null
+++ b/WebCore/dom/WindowEventContext.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#include "config.h"
+#include "WindowEventContext.h"
+
+#include "DOMWindow.h"
+#include "Document.h"
+#include "Event.h"
+#include "EventContext.h"
+#include "Node.h"
+
+namespace WebCore {
+
+WindowEventContext::WindowEventContext(Event* event, PassRefPtr<Node> node, const EventContext* topEventContext)
+{
+    // We don't dispatch load events to the window. This quirk was originally
+    // added because Mozilla doesn't propagate load events to the window object.
+    if (event->type() == eventNames().loadEvent)
+        return;
+
+    Node* topLevelContainer = topEventContext ? topEventContext->node() : node.get();
+    if (!topLevelContainer->isDocumentNode())
+        return;
+
+    m_window = static_cast<Document*>(topLevelContainer)->domWindow();
+    m_target = topEventContext ? topEventContext->target() : node.get();
+}
+
+bool WindowEventContext::handleLocalEvents(Event* event)
+{
+    if (!m_window)
+        return false;
+
+    event->setTarget(target());
+    event->setCurrentTarget(window());
+    m_window->fireEventListeners(event);
+    return true;
+}
+
+}
diff --git a/WebCore/dom/WindowEventContext.h b/WebCore/dom/WindowEventContext.h
new file mode 100644
index 0000000..a19e04d
--- /dev/null
+++ b/WebCore/dom/WindowEventContext.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ *
+ */
+
+#ifndef WindowEventContext_h
+#define WindowEventContext_h
+
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class DOMWindow;
+class EventTarget;
+class EventContext;
+class Event;
+class Node;
+
+class WindowEventContext {
+public:
+    WindowEventContext(Event*, PassRefPtr<Node>, const EventContext*);
+
+    DOMWindow* window() const;
+    EventTarget* target() const;
+    bool handleLocalEvents(Event* event);
+
+private:
+    RefPtr<DOMWindow> m_window;
+    RefPtr<EventTarget> m_target;
+};
+
+inline DOMWindow* WindowEventContext::window() const
+{
+    return m_window.get();
+}
+
+inline EventTarget* WindowEventContext::target() const
+{
+    return m_target.get();
+}
+
+}
+
+#endif // WindowEventContext_h
diff --git a/WebCore/inspector/InspectorDOMAgent.cpp b/WebCore/inspector/InspectorDOMAgent.cpp
index 39aecf1..894e4b2 100644
--- a/WebCore/inspector/InspectorDOMAgent.cpp
+++ b/WebCore/inspector/InspectorDOMAgent.cpp
@@ -51,6 +51,7 @@
 #include "Document.h"
 #include "DocumentType.h"
 #include "Event.h"
+#include "EventContext.h"
 #include "EventListener.h"
 #include "EventNames.h"
 #include "EventTarget.h"
@@ -613,13 +614,13 @@ void InspectorDOMAgent::getEventListenersForNode(long nodeId, long* outNodeId, R
         return;
 
     // The Node's Event Ancestors (not including self)
-    Vector<RefPtr<ContainerNode> > ancestors;
-    node->eventAncestors(ancestors);
+    Vector<EventContext> ancestors;
+    node->getEventAncestors(ancestors, node);
 
     // Nodes and their Listeners for the concerned event types (order is top to bottom)
     Vector<EventListenerInfo> eventInformation;
     for (size_t i = ancestors.size(); i; --i) {
-        ContainerNode* ancestor = ancestors[i - 1].get();
+        Node* ancestor = ancestors[i - 1].node();
         for (size_t j = 0; j < eventTypesLength; ++j) {
             AtomicString& type = eventTypes[j];
             if (ancestor->hasEventListeners(type))
diff --git a/WebCore/inspector/InspectorInstrumentation.cpp b/WebCore/inspector/InspectorInstrumentation.cpp
index 94202c1..cf41527 100644
--- a/WebCore/inspector/InspectorInstrumentation.cpp
+++ b/WebCore/inspector/InspectorInstrumentation.cpp
@@ -35,6 +35,7 @@
 
 #include "DOMWindow.h"
 #include "Event.h"
+#include "EventContext.h"
 #include "InspectorController.h"
 #include "InspectorDOMAgent.h"
 #include "InspectorDebuggerAgent.h"
@@ -53,7 +54,7 @@ static const char* const timerFiredEventName = "timerFired";
 
 int InspectorInstrumentation::s_frontendCounter = 0;
 
-static bool eventHasListeners(const AtomicString& eventType, DOMWindow* window, Node* node, const Vector<RefPtr<ContainerNode> >& ancestors)
+static bool eventHasListeners(const AtomicString& eventType, DOMWindow* window, Node* node, const Vector<EventContext>& ancestors)
 {
     if (window && window->hasEventListeners(eventType))
         return true;
@@ -62,7 +63,7 @@ static bool eventHasListeners(const AtomicString& eventType, DOMWindow* window,
         return true;
 
     for (size_t i = 0; i < ancestors.size(); i++) {
-        ContainerNode* ancestor = ancestors[i].get();
+        Node* ancestor = ancestors[i].node();
         if (ancestor->hasEventListeners(eventType))
             return true;
     }
@@ -139,7 +140,6 @@ void InspectorInstrumentation::characterDataModifiedImpl(InspectorController* in
         domAgent->characterDataModified(characterData);
 }
 
-
 void InspectorInstrumentation::willSendXMLHttpRequestImpl(InspectorController* inspectorController, const String& url)
 {
 #if ENABLE(JAVASCRIPT_DEBUGGER)
@@ -213,7 +213,7 @@ void InspectorInstrumentation::didChangeXHRReadyStateImpl(const InspectorInstrum
         timelineAgent->didChangeXHRReadyState();
 }
 
-InspectorInstrumentationCookie InspectorInstrumentation::willDispatchEventImpl(InspectorController* inspectorController, const Event& event, DOMWindow* window, Node* node, const Vector<RefPtr<ContainerNode> >& ancestors)
+InspectorInstrumentationCookie InspectorInstrumentation::willDispatchEventImpl(InspectorController* inspectorController, const Event& event, DOMWindow* window, Node* node, const Vector<EventContext>& ancestors)
 {
     pauseOnNativeEventIfNeeded(inspectorController, listenerEventCategoryType, event.type(), false);
 
diff --git a/WebCore/inspector/InspectorInstrumentation.h b/WebCore/inspector/InspectorInstrumentation.h
index 1b62ecb..7f241c4 100644
--- a/WebCore/inspector/InspectorInstrumentation.h
+++ b/WebCore/inspector/InspectorInstrumentation.h
@@ -40,6 +40,7 @@ namespace WebCore {
 
 class CharacterData;
 class Element;
+class EventContext;
 class InspectorController;
 class InspectorTimelineAgent;
 class KURL;
@@ -73,7 +74,7 @@ public:
     static void didCallFunction(const InspectorInstrumentationCookie&);
     static InspectorInstrumentationCookie willChangeXHRReadyState(ScriptExecutionContext*, XMLHttpRequest* request);
     static void didChangeXHRReadyState(const InspectorInstrumentationCookie&);
-    static InspectorInstrumentationCookie willDispatchEvent(Document*, const Event& event, DOMWindow* window, Node* node, const Vector<RefPtr<ContainerNode> >& ancestors);
+    static InspectorInstrumentationCookie willDispatchEvent(Document*, const Event& event, DOMWindow* window, Node* node, const Vector<EventContext>& ancestors);
     static void didDispatchEvent(const InspectorInstrumentationCookie&);
     static InspectorInstrumentationCookie willDispatchEventOnWindow(Frame*, const Event& event, DOMWindow* window);
     static void didDispatchEventOnWindow(const InspectorInstrumentationCookie&);
@@ -130,7 +131,7 @@ private:
     static void didCallFunctionImpl(const InspectorInstrumentationCookie&);
     static InspectorInstrumentationCookie willChangeXHRReadyStateImpl(InspectorController*, XMLHttpRequest* request);
     static void didChangeXHRReadyStateImpl(const InspectorInstrumentationCookie&);
-    static InspectorInstrumentationCookie willDispatchEventImpl(InspectorController*, const Event& event, DOMWindow* window, Node* node, const Vector<RefPtr<ContainerNode> >& ancestors);
+    static InspectorInstrumentationCookie willDispatchEventImpl(InspectorController*, const Event& event, DOMWindow* window, Node* node, const Vector<EventContext>& ancestors);
     static void didDispatchEventImpl(const InspectorInstrumentationCookie&);
     static InspectorInstrumentationCookie willDispatchEventOnWindowImpl(InspectorController*, const Event& event, DOMWindow* window);
     static void didDispatchEventOnWindowImpl(const InspectorInstrumentationCookie&);
@@ -225,7 +226,6 @@ inline void InspectorInstrumentation::characterDataModified(Document* document,
 #endif
 }
 
-
 inline void InspectorInstrumentation::willSendXMLHttpRequest(ScriptExecutionContext* context, const String& url)
 {
 #if ENABLE(INSPECTOR)
@@ -293,7 +293,7 @@ inline void InspectorInstrumentation::didChangeXHRReadyState(const InspectorInst
 #endif
 }
 
-inline InspectorInstrumentationCookie InspectorInstrumentation::willDispatchEvent(Document* document, const Event& event, DOMWindow* window, Node* node, const Vector<RefPtr<ContainerNode> >& ancestors)
+inline InspectorInstrumentationCookie InspectorInstrumentation::willDispatchEvent(Document* document, const Event& event, DOMWindow* window, Node* node, const Vector<EventContext>& ancestors)
 {
 #if ENABLE(INSPECTOR)
     if (InspectorController* inspectorController = inspectorControllerForDocument(document))
diff --git a/WebCore/page/EventHandler.cpp b/WebCore/page/EventHandler.cpp
index faf0b78..208d897 100644
--- a/WebCore/page/EventHandler.cpp
+++ b/WebCore/page/EventHandler.cpp
@@ -1766,8 +1766,6 @@ void EventHandler::updateMouseEventTargetNode(Node* targetNode, const PlatformMo
         // If the target node is a text node, dispatch on the parent node - rdar://4196646
         if (result && result->isTextNode())
             result = result->parentNode();
-        if (result)
-            result = result->shadowAncestorNode();
     }
     m_nodeUnderMouse = result;
 #if ENABLE(SVG)
diff --git a/WebCore/rendering/RenderTextControlMultiLine.cpp b/WebCore/rendering/RenderTextControlMultiLine.cpp
index 64293fe..e26d478 100644
--- a/WebCore/rendering/RenderTextControlMultiLine.cpp
+++ b/WebCore/rendering/RenderTextControlMultiLine.cpp
@@ -52,8 +52,6 @@ void RenderTextControlMultiLine::subtreeHasChanged()
     if (!node()->focused())
         return;
 
-    node()->dispatchEvent(Event::create(eventNames().inputEvent, true, false));
-
     if (Frame* frame = this->frame())
         frame->editor()->textDidChangeInTextArea(textArea);
 }
diff --git a/WebCore/rendering/ShadowElement.h b/WebCore/rendering/ShadowElement.h
index 04db62b..f5668ef 100644
--- a/WebCore/rendering/ShadowElement.h
+++ b/WebCore/rendering/ShadowElement.h
@@ -43,13 +43,13 @@ protected:
     {
     }
 
-    HTMLElement* shadowParent() const { return m_shadowParent; }
+    HTMLElement* shadowParent() const { return m_shadowParent.get(); }
 
 private:
     virtual bool isShadowNode() const { return true; }
-    virtual ContainerNode* shadowParentNode() { return m_shadowParent; }
+    virtual ContainerNode* shadowParentNode() { return m_shadowParent.get(); }
 
-    HTMLElement* m_shadowParent;
+    RefPtr<HTMLElement> m_shadowParent;
 };
 
 class ShadowBlockElement : public ShadowElement<HTMLDivElement> {
diff --git a/WebCore/rendering/TextControlInnerElements.cpp b/WebCore/rendering/TextControlInnerElements.cpp
index 6495d04..73560fd 100644
--- a/WebCore/rendering/TextControlInnerElements.cpp
+++ b/WebCore/rendering/TextControlInnerElements.cpp
@@ -154,7 +154,7 @@ void TextControlInnerTextElement::defaultEventHandler(Event* event)
         if (shadowAncestor && shadowAncestor != this)
             shadowAncestor->defaultEventHandler(event);
     }
-    if (event->defaultHandled())
+    if (!event->defaultHandled())
         HTMLDivElement::defaultEventHandler(event);
 }
 
diff --git a/WebCore/svg/SVGElement.cpp b/WebCore/svg/SVGElement.cpp
index 6c2c4a2..3e9bda0 100644
--- a/WebCore/svg/SVGElement.cpp
+++ b/WebCore/svg/SVGElement.cpp
@@ -347,13 +347,6 @@ void SVGElement::updateAnimatedSVGAttribute(const QualifiedName& name) const
     clearIsSynchronizingSVGAttributes();
 }
 
-ContainerNode* SVGElement::eventParentNode()
-{
-    if (ContainerNode* shadowParent = shadowParentNode())
-        return shadowParent;
-    return StyledElement::eventParentNode();
-}
-
 }
 
 #endif // ENABLE(SVG)
diff --git a/WebCore/svg/SVGElement.h b/WebCore/svg/SVGElement.h
index 517515f..96e7fd7 100644
--- a/WebCore/svg/SVGElement.h
+++ b/WebCore/svg/SVGElement.h
@@ -99,8 +99,6 @@ namespace WebCore {
 
         virtual bool isSupported(StringImpl* feature, StringImpl* version) const;
 
-        virtual ContainerNode* eventParentNode();
-
         virtual bool needsPendingResourceHandling() const { return true; }
         virtual void buildPendingResource() { }
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list