1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All
6  * rights reserved.
7  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
8  * Copyright (C) 2009 Torch Mobile Inc. All rights reserved.
9  * (http://www.torchmobile.com/)
10  * Copyright (C) 2011 Google Inc. All rights reserved.
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public License
23  * along with this library; see the file COPYING.LIB.  If not, write to
24  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25  * Boston, MA 02110-1301, USA.
26  */
27 
28 #include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
29 
30 #include "base/memory/scoped_refptr.h"
31 #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
32 #include "third_party/blink/renderer/core/dom/container_node.h"
33 #include "third_party/blink/renderer/core/dom/document.h"
34 #include "third_party/blink/renderer/core/dom/element.h"
35 #include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
36 #include "third_party/blink/renderer/core/dom/events/event_path.h"
37 #include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
38 #include "third_party/blink/renderer/core/dom/events/window_event_context.h"
39 #include "third_party/blink/renderer/core/events/keyboard_event.h"
40 #include "third_party/blink/renderer/core/events/mouse_event.h"
41 #include "third_party/blink/renderer/core/frame/ad_tracker.h"
42 #include "third_party/blink/renderer/core/frame/deprecation.h"
43 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
44 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
45 #include "third_party/blink/renderer/core/frame/settings.h"
46 #include "third_party/blink/renderer/core/html/html_element.h"
47 #include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
48 #include "third_party/blink/renderer/core/page/page.h"
49 #include "third_party/blink/renderer/core/page/spatial_navigation_controller.h"
50 #include "third_party/blink/renderer/core/timing/event_timing.h"
51 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
52 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
53 
54 namespace blink {
55 
DispatchEvent(Node & node,Event & event)56 DispatchEventResult EventDispatcher::DispatchEvent(Node& node, Event& event) {
57   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("blink.debug"),
58                "EventDispatcher::dispatchEvent");
59 #if DCHECK_IS_ON()
60   DCHECK(!EventDispatchForbiddenScope::IsEventDispatchForbidden());
61 #endif
62   EventDispatcher dispatcher(node, event);
63   return event.DispatchEvent(dispatcher);
64 }
65 
EventDispatcher(Node & node,Event & event)66 EventDispatcher::EventDispatcher(Node& node, Event& event)
67     : node_(&node), event_(&event) {
68   view_ = node.GetDocument().View();
69   event_->InitEventPath(*node_);
70 }
71 
DispatchScopedEvent(Node & node,Event & event)72 void EventDispatcher::DispatchScopedEvent(Node& node, Event& event) {
73   // We need to set the target here because it can go away by the time we
74   // actually fire the event.
75   event.SetTarget(&EventPath::EventTargetRespectingTargetRules(node));
76   ScopedEventQueue::Instance()->EnqueueEvent(event);
77 }
78 
DispatchSimulatedClick(Node & node,const Event * underlying_event,SimulatedClickMouseEventOptions mouse_event_options,SimulatedClickCreationScope creation_scope)79 void EventDispatcher::DispatchSimulatedClick(
80     Node& node,
81     const Event* underlying_event,
82     SimulatedClickMouseEventOptions mouse_event_options,
83     SimulatedClickCreationScope creation_scope) {
84   // This persistent vector doesn't cause leaks, because added Nodes are removed
85   // before dispatchSimulatedClick() returns. This vector is here just to
86   // prevent the code from running into an infinite recursion of
87   // dispatchSimulatedClick().
88   DEFINE_STATIC_LOCAL(Persistent<HeapHashSet<Member<Node>>>,
89                       nodes_dispatching_simulated_clicks,
90                       (MakeGarbageCollected<HeapHashSet<Member<Node>>>()));
91 
92   if (IsDisabledFormControl(&node))
93     return;
94 
95   if (nodes_dispatching_simulated_clicks->Contains(&node))
96     return;
97 
98   nodes_dispatching_simulated_clicks->insert(&node);
99 
100   if (mouse_event_options == kSendMouseOverUpDownEvents)
101     EventDispatcher(node, *MouseEvent::Create(event_type_names::kMouseover,
102                                               node.GetDocument().domWindow(),
103                                               underlying_event, creation_scope))
104         .Dispatch();
105 
106   Element* element = DynamicTo<Element>(node);
107   if (mouse_event_options != kSendNoEvents) {
108     EventDispatcher(node, *MouseEvent::Create(event_type_names::kMousedown,
109                                               node.GetDocument().domWindow(),
110                                               underlying_event, creation_scope))
111         .Dispatch();
112     if (element)
113       element->SetActive(true);
114     EventDispatcher(node, *MouseEvent::Create(event_type_names::kMouseup,
115                                               node.GetDocument().domWindow(),
116                                               underlying_event, creation_scope))
117         .Dispatch();
118   }
119   // Some elements (e.g. the color picker) may set active state to true before
120   // calling this method and expect the state to be reset during the call.
121   if (element)
122     element->SetActive(false);
123 
124   // always send click
125   EventDispatcher(node, *MouseEvent::Create(event_type_names::kClick,
126                                             node.GetDocument().domWindow(),
127                                             underlying_event, creation_scope))
128       .Dispatch();
129 
130   nodes_dispatching_simulated_clicks->erase(&node);
131 }
132 
133 // https://dom.spec.whatwg.org/#dispatching-events
Dispatch()134 DispatchEventResult EventDispatcher::Dispatch() {
135   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("blink.debug"),
136                "EventDispatcher::dispatch");
137 
138 #if DCHECK_IS_ON()
139   DCHECK(!event_dispatched_);
140   event_dispatched_ = true;
141 #endif
142   if (GetEvent().GetEventPath().IsEmpty()) {
143     // eventPath() can be empty if relatedTarget retargeting has shrunk the
144     // path.
145     return DispatchEventResult::kNotCanceled;
146   }
147   std::unique_ptr<EventTiming> eventTiming;
148   LocalFrame* frame = node_->GetDocument().GetFrame();
149   if (frame && frame->DomWindow())
150     eventTiming = EventTiming::Create(frame->DomWindow(), *event_);
151   event_->GetEventPath().EnsureWindowEventContext();
152 
153   const bool is_click =
154       event_->IsMouseEvent() && event_->type() == event_type_names::kClick;
155 
156   if (is_click && event_->isTrusted()) {
157     Document& document = node_->GetDocument();
158     if (frame) {
159       // A genuine mouse click cannot be triggered by script so we don't expect
160       // there are any script in the stack.
161       DCHECK(!frame->GetAdTracker() ||
162              !frame->GetAdTracker()->IsAdScriptInStack(
163                  AdTracker::StackType::kBottomAndTop));
164       if (frame->IsAdSubframe()) {
165         UseCounter::Count(document, WebFeature::kAdClick);
166       }
167     }
168   }
169 
170   // 6. Let isActivationEvent be true, if event is a MouseEvent object and
171   // event's type attribute is "click", and false otherwise.
172   //
173   // We need to include non-standard textInput event for HTMLInputElement.
174   const bool is_activation_event =
175       is_click || event_->type() == event_type_names::kTextInput;
176 
177   // 7. Let activationTarget be target, if isActivationEvent is true and target
178   // has activation behavior, and null otherwise.
179   Node* activation_target =
180       is_activation_event && node_->HasActivationBehavior() ? node_ : nullptr;
181 
182   // A part of step 9 loop.
183   if (is_activation_event && !activation_target && event_->bubbles()) {
184     wtf_size_t size = event_->GetEventPath().size();
185     for (wtf_size_t i = 1; i < size; ++i) {
186       Node& target = event_->GetEventPath()[i].GetNode();
187       if (target.HasActivationBehavior()) {
188         activation_target = &target;
189         break;
190       }
191     }
192   }
193 
194   event_->SetTarget(&EventPath::EventTargetRespectingTargetRules(*node_));
195 #if DCHECK_IS_ON()
196   DCHECK(!EventDispatchForbiddenScope::IsEventDispatchForbidden());
197 #endif
198   DCHECK(event_->target());
199   TRACE_EVENT1("devtools.timeline", "EventDispatch", "data",
200                inspector_event_dispatch_event::Data(*event_));
201   EventDispatchHandlingState* pre_dispatch_event_handler_result = nullptr;
202   if (DispatchEventPreProcess(activation_target,
203                               pre_dispatch_event_handler_result) ==
204       kContinueDispatching) {
205     if (DispatchEventAtCapturing() == kContinueDispatching) {
206       if (DispatchEventAtTarget() == kContinueDispatching)
207         DispatchEventAtBubbling();
208     }
209   }
210   DispatchEventPostProcess(activation_target,
211                            pre_dispatch_event_handler_result);
212   if (eventTiming)
213     eventTiming->DidDispatchEvent(*event_, node_->GetDocument());
214 
215   return EventTarget::GetDispatchEventResult(*event_);
216 }
217 
DispatchEventPreProcess(Node * activation_target,EventDispatchHandlingState * & pre_dispatch_event_handler_result)218 inline EventDispatchContinuation EventDispatcher::DispatchEventPreProcess(
219     Node* activation_target,
220     EventDispatchHandlingState*& pre_dispatch_event_handler_result) {
221   // 11. If activationTarget is non-null and activationTarget has
222   // legacy-pre-activation behavior, then run activationTarget's
223   // legacy-pre-activation behavior.
224   if (activation_target) {
225     pre_dispatch_event_handler_result =
226         activation_target->PreDispatchEventHandler(*event_);
227   }
228 
229   return (event_->GetEventPath().IsEmpty() || event_->PropagationStopped())
230              ? kDoneDispatching
231              : kContinueDispatching;
232 }
233 
DispatchEventAtCapturing()234 inline EventDispatchContinuation EventDispatcher::DispatchEventAtCapturing() {
235   // Trigger capturing event handlers, starting at the top and working our way
236   // down.
237   event_->SetEventPhase(Event::kCapturingPhase);
238 
239   if (event_->GetEventPath().GetWindowEventContext().HandleLocalEvents(
240           *event_) &&
241       event_->PropagationStopped())
242     return kDoneDispatching;
243 
244   for (wtf_size_t i = event_->GetEventPath().size() - 1; i > 0; --i) {
245     const NodeEventContext& event_context = event_->GetEventPath()[i];
246     if (event_context.CurrentTargetSameAsTarget()) {
247       event_->SetEventPhase(Event::kAtTarget);
248       event_->SetFireOnlyCaptureListenersAtTarget(true);
249       event_context.HandleLocalEvents(*event_);
250       event_->SetFireOnlyCaptureListenersAtTarget(false);
251     } else {
252       event_->SetEventPhase(Event::kCapturingPhase);
253       event_context.HandleLocalEvents(*event_);
254     }
255     if (event_->PropagationStopped())
256       return kDoneDispatching;
257   }
258 
259   return kContinueDispatching;
260 }
261 
DispatchEventAtTarget()262 inline EventDispatchContinuation EventDispatcher::DispatchEventAtTarget() {
263   event_->SetEventPhase(Event::kAtTarget);
264   event_->GetEventPath()[0].HandleLocalEvents(*event_);
265   return event_->PropagationStopped() ? kDoneDispatching : kContinueDispatching;
266 }
267 
DispatchEventAtBubbling()268 inline void EventDispatcher::DispatchEventAtBubbling() {
269   // Trigger bubbling event handlers, starting at the bottom and working our way
270   // up.
271   wtf_size_t size = event_->GetEventPath().size();
272   for (wtf_size_t i = 1; i < size; ++i) {
273     const NodeEventContext& event_context = event_->GetEventPath()[i];
274     if (event_context.CurrentTargetSameAsTarget()) {
275       // TODO(hayato): Need to check cancelBubble() also here?
276       event_->SetEventPhase(Event::kAtTarget);
277       event_->SetFireOnlyNonCaptureListenersAtTarget(true);
278       event_context.HandleLocalEvents(*event_);
279       event_->SetFireOnlyNonCaptureListenersAtTarget(false);
280     } else if (event_->bubbles() && !event_->cancelBubble()) {
281       event_->SetEventPhase(Event::kBubblingPhase);
282       event_context.HandleLocalEvents(*event_);
283     } else {
284       continue;
285     }
286     if (event_->PropagationStopped())
287       return;
288   }
289   if (event_->bubbles() && !event_->cancelBubble()) {
290     event_->SetEventPhase(Event::kBubblingPhase);
291     event_->GetEventPath().GetWindowEventContext().HandleLocalEvents(*event_);
292   }
293 }
294 
DispatchEventPostProcess(Node * activation_target,EventDispatchHandlingState * pre_dispatch_event_handler_result)295 inline void EventDispatcher::DispatchEventPostProcess(
296     Node* activation_target,
297     EventDispatchHandlingState* pre_dispatch_event_handler_result) {
298   event_->SetTarget(&EventPath::EventTargetRespectingTargetRules(*node_));
299   // https://dom.spec.whatwg.org/#concept-event-dispatch
300   // 14. Unset event’s dispatch flag, stop propagation flag, and stop immediate
301   // propagation flag.
302   event_->SetStopPropagation(false);
303   event_->SetStopImmediatePropagation(false);
304   // 15. Set event’s eventPhase attribute to NONE.
305   event_->SetEventPhase(0);
306   // TODO(rakina): investigate this and move it to the bottom of step 16
307   // 17. Set event’s currentTarget attribute to null.
308   event_->SetCurrentTarget(nullptr);
309 
310   auto* mouse_event = DynamicTo<MouseEvent>(event_);
311   bool is_click =
312       mouse_event && mouse_event->type() == event_type_names::kClick;
313   if (is_click) {
314     // Fire an accessibility event indicating a node was clicked on.  This is
315     // safe if event_->target()->ToNode() returns null.
316     if (AXObjectCache* cache = node_->GetDocument().ExistingAXObjectCache())
317       cache->HandleClicked(event_->target()->ToNode());
318 
319     // Pass the data from the PreDispatchEventHandler to the
320     // PostDispatchEventHandler.
321     // This may dispatch an event, and node_ and event_ might be altered.
322     if (activation_target) {
323       activation_target->PostDispatchEventHandler(
324           *event_, pre_dispatch_event_handler_result);
325     }
326     // TODO(tkent): Is it safe to kick DefaultEventHandler() with such altered
327     // event_?
328   }
329 
330   // The DOM Events spec says that events dispatched by JS (other than "click")
331   // should not have their default handlers invoked.
332   bool is_trusted_or_click = event_->isTrusted() || is_click;
333 
334   // For Android WebView (distinguished by wideViewportQuirkEnabled)
335   // enable untrusted events for mouse down on select elements because
336   // fastclick.js seems to generate these. crbug.com/642698
337   // TODO(dtapuska): Change this to a target SDK quirk crbug.com/643705
338   if (!is_trusted_or_click && event_->IsMouseEvent() &&
339       event_->type() == event_type_names::kMousedown &&
340       IsA<HTMLSelectElement>(*node_)) {
341     if (Settings* settings = node_->GetDocument().GetSettings()) {
342       is_trusted_or_click = settings->GetWideViewportQuirkEnabled();
343     }
344   }
345 
346   // Call default event handlers. While the DOM does have a concept of
347   // preventing default handling, the detail of which handlers are called is an
348   // internal implementation detail and not part of the DOM.
349   if (!event_->defaultPrevented() && !event_->DefaultHandled() &&
350       is_trusted_or_click) {
351     // Non-bubbling events call only one default event handler, the one for the
352     // target.
353     node_->DefaultEventHandler(*event_);
354     DCHECK(!event_->defaultPrevented());
355     // For bubbling events, call default event handlers on the same targets in
356     // the same order as the bubbling phase.
357     if (!event_->DefaultHandled() && event_->bubbles()) {
358       wtf_size_t size = event_->GetEventPath().size();
359       for (wtf_size_t i = 1; i < size; ++i) {
360         event_->GetEventPath()[i].GetNode().DefaultEventHandler(*event_);
361         DCHECK(!event_->defaultPrevented());
362         if (event_->DefaultHandled())
363           break;
364       }
365     }
366   }
367 
368   auto* keyboard_event = DynamicTo<KeyboardEvent>(event_);
369   if (Page* page = node_->GetDocument().GetPage()) {
370     if (page->GetSettings().GetSpatialNavigationEnabled() &&
371         is_trusted_or_click && keyboard_event &&
372         keyboard_event->key() == "Enter" &&
373         event_->type() == event_type_names::kKeyup) {
374       page->GetSpatialNavigationController().ResetEnterKeyState();
375     }
376   }
377 
378   // Track the usage of sending a mousedown event to a select element to force
379   // it to open. This measures a possible breakage of not allowing untrusted
380   // events to open select boxes.
381   if (!event_->isTrusted() && event_->IsMouseEvent() &&
382       event_->type() == event_type_names::kMousedown &&
383       IsA<HTMLSelectElement>(*node_)) {
384     UseCounter::Count(node_->GetDocument(),
385                       WebFeature::kUntrustedMouseDownEventDispatchedToSelect);
386   }
387   // 16. If target's root is a shadow root, then set event's target attribute
388   // and event's relatedTarget to null.
389   event_->SetTarget(event_->GetEventPath().GetWindowEventContext().Target());
390   if (!event_->target())
391     event_->SetRelatedTargetIfExists(nullptr);
392 }
393 
394 }  // namespace blink
395