Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(449)

Side by Side Diff: third_party/WebKit/Source/core/events/EventTarget.cpp

Issue 1949793002: Emit a console warning when blocking event listener is delayed for too long (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: removed forward decls & includes that are not in use now Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 5 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
6 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) 6 * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
7 * (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> 7 * (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
(...skipping 14 matching lines...) Expand all
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * 29 *
30 */ 30 */
31 31
32 #include "core/events/EventTarget.h" 32 #include "core/events/EventTarget.h"
33 33
34 #include "bindings/core/v8/ExceptionState.h" 34 #include "bindings/core/v8/ExceptionState.h"
35 #include "bindings/core/v8/ScriptEventListener.h"
35 #include "bindings/core/v8/V8DOMActivityLogger.h" 36 #include "bindings/core/v8/V8DOMActivityLogger.h"
36 #include "core/dom/ExceptionCode.h" 37 #include "core/dom/ExceptionCode.h"
37 #include "core/editing/Editor.h" 38 #include "core/editing/Editor.h"
38 #include "core/events/Event.h" 39 #include "core/events/Event.h"
40 #include "core/frame/FrameHost.h"
41 #include "core/frame/LocalDOMWindow.h"
42 #include "core/frame/Settings.h"
43 #include "core/frame/UseCounter.h"
44 #include "core/inspector/ConsoleMessage.h"
39 #include "core/inspector/InspectorInstrumentation.h" 45 #include "core/inspector/InspectorInstrumentation.h"
40 #include "core/frame/LocalDOMWindow.h"
41 #include "core/frame/UseCounter.h"
42 #include "platform/EventDispatchForbiddenScope.h" 46 #include "platform/EventDispatchForbiddenScope.h"
43 #include "wtf/StdLibExtras.h" 47 #include "wtf/StdLibExtras.h"
44 #include "wtf/Threading.h" 48 #include "wtf/Threading.h"
45 #include "wtf/Vector.h" 49 #include "wtf/Vector.h"
46 50
47 using namespace WTF; 51 using namespace WTF;
48 52
49 namespace blink { 53 namespace blink {
50 namespace { 54 namespace {
51 55
52 void setDefaultEventListenerOptionsLegacy(EventListenerOptions& options, bool us eCapture) 56 void setDefaultEventListenerOptionsLegacy(EventListenerOptions& options, bool us eCapture)
53 { 57 {
54 options.setCapture(useCapture); 58 options.setCapture(useCapture);
55 } 59 }
56 60
57 void setDefaultAddEventListenerOptionsLegacy(AddEventListenerOptions& options, b ool useCapture) 61 void setDefaultAddEventListenerOptionsLegacy(AddEventListenerOptions& options, b ool useCapture)
58 { 62 {
59 setDefaultEventListenerOptionsLegacy(options, useCapture); 63 setDefaultEventListenerOptionsLegacy(options, useCapture);
60 options.setPassive(false); 64 options.setPassive(false);
61 } 65 }
62 66
63 void setDefaultAddEventListenerOptions(AddEventListenerOptions& options) 67 void setDefaultAddEventListenerOptions(AddEventListenerOptions& options)
64 { 68 {
65 if (!options.hasPassive()) 69 if (!options.hasPassive())
66 options.setPassive(false); 70 options.setPassive(false);
67 } 71 }
68 72
73 double blockedEventsWarningThreshold(const ExecutionContext* context, const Even t* event)
74 {
75 if (!event->cancelable())
76 return 0.0;
77 const AtomicString& eventType = event->type();
78 if (eventType != EventTypeNames::touchstart
79 && eventType != EventTypeNames::touchmove
80 && eventType != EventTypeNames::touchend
81 && eventType != EventTypeNames::mousewheel
82 && eventType != EventTypeNames::wheel) {
83 return 0.0;
84 }
85
86 if (!context->isDocument())
87 return 0.0;
88 FrameHost* frameHost = toDocument(context)->frameHost();
89 if (!frameHost)
90 return 0.0;
91 return frameHost->settings().blockedMainThreadEventsWarningThreshold();
92 }
93
94 void reportBlockedEvent(ExecutionContext* context, const Event* event, Registere dEventListener* registeredListener, double delayedSeconds)
95 {
96 if (registeredListener->listener()->type() != EventListener::JSEventListener Type)
97 return;
98
99 V8AbstractEventListener* v8Listener = V8AbstractEventListener::cast(register edListener->listener());
100 v8::HandleScope handles(v8Listener->isolate());
101 v8::Local<v8::Object> handler = v8Listener->getListenerObject(context);
102
103 String messageText = String::format(
104 "Handling of %s input event was delayed for %ld ms. due to main thread b eing busy. "
pfeldman 2016/05/10 20:01:23 '%s'
pfeldman 2016/05/10 20:01:23 No need for . after ms
105 "Consider marking event handler as passive to make the page appear more responive.",
pfeldman 2016/05/10 20:01:23 s/appear//
pfeldman 2016/05/10 20:01:23 'passive'
106 event->type().characters8(), lround(delayedSeconds * 1000));
107 ConsoleMessage* message = ConsoleMessage::create(JSMessageSource, WarningMes sageLevel, messageText);
108
109 v8::Local<v8::Function> function = eventListenerEffectiveFunction(v8Listener ->isolate(), handler);
110 if (!function.IsEmpty()) {
111 message->setLineNumber(function->GetScriptLineNumber() + 1);
112 message->setColumnNumber(function->GetScriptColumnNumber());
113 message->setScriptId(function->ScriptId());
114 }
115 context->addConsoleMessage(message);
116 registeredListener->setBlockedEventWarningEmitted();
117 }
118
119
69 } // namespace 120 } // namespace
70 121
71 EventTargetData::EventTargetData() 122 EventTargetData::EventTargetData()
72 { 123 {
73 } 124 }
74 125
75 EventTargetData::~EventTargetData() 126 EventTargetData::~EventTargetData()
76 { 127 {
77 } 128 }
78 129
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 if (LocalDOMWindow* executingWindow = this->executingWindow()) 470 if (LocalDOMWindow* executingWindow = this->executingWindow())
420 UseCounter::count(executingWindow->document(), UseCounter::DOMFocusI nOutEvent); 471 UseCounter::count(executingWindow->document(), UseCounter::DOMFocusI nOutEvent);
421 } else if (event->type() == EventTypeNames::focusin || event->type() == Even tTypeNames::focusout) { 472 } else if (event->type() == EventTypeNames::focusin || event->type() == Even tTypeNames::focusout) {
422 if (LocalDOMWindow* executingWindow = this->executingWindow()) 473 if (LocalDOMWindow* executingWindow = this->executingWindow())
423 UseCounter::count(executingWindow->document(), UseCounter::FocusInOu tEvent); 474 UseCounter::count(executingWindow->document(), UseCounter::FocusInOu tEvent);
424 } else if (event->type() == EventTypeNames::textInput) { 475 } else if (event->type() == EventTypeNames::textInput) {
425 if (LocalDOMWindow* executingWindow = this->executingWindow()) 476 if (LocalDOMWindow* executingWindow = this->executingWindow())
426 UseCounter::count(executingWindow->document(), UseCounter::TextInput Fired); 477 UseCounter::count(executingWindow->document(), UseCounter::TextInput Fired);
427 } 478 }
428 479
480 ExecutionContext* context = getExecutionContext();
481 if (!context)
482 return;
483
429 size_t i = 0; 484 size_t i = 0;
430 size_t size = entry.size(); 485 size_t size = entry.size();
431 if (!d->firingEventIterators) 486 if (!d->firingEventIterators)
432 d->firingEventIterators = adoptPtr(new FiringEventIteratorVector); 487 d->firingEventIterators = adoptPtr(new FiringEventIteratorVector);
433 d->firingEventIterators->append(FiringEventIterator(event->type(), i, size)) ; 488 d->firingEventIterators->append(FiringEventIterator(event->type(), i, size)) ;
489
490 double blockedEventThreshold = blockedEventsWarningThreshold(context, event) ;
491 double now = 0.0;
492 bool shouldReportBlockedEvent = false;
493 if (blockedEventThreshold) {
494 now = WTF::monotonicallyIncreasingTime();
495 shouldReportBlockedEvent = now - event->platformTimeStamp() > blockedEve ntThreshold;
496 }
497
434 while (i < size) { 498 while (i < size) {
435 RegisteredEventListener& registeredListener = entry[i]; 499 RegisteredEventListener& registeredListener = entry[i];
436 500
437 // Move the iterator past this event listener. This must match 501 // Move the iterator past this event listener. This must match
438 // the handling of the FiringEventIterator::iterator in 502 // the handling of the FiringEventIterator::iterator in
439 // EventTarget::removeEventListener. 503 // EventTarget::removeEventListener.
440 ++i; 504 ++i;
441 505
442 if (event->eventPhase() == Event::CAPTURING_PHASE && !registeredListener .capture()) 506 if (event->eventPhase() == Event::CAPTURING_PHASE && !registeredListener .capture())
443 continue; 507 continue;
444 if (event->eventPhase() == Event::BUBBLING_PHASE && registeredListener.c apture()) 508 if (event->eventPhase() == Event::BUBBLING_PHASE && registeredListener.c apture())
445 continue; 509 continue;
446 510
447 // If stopImmediatePropagation has been called, we just break out immedi ately, without 511 // If stopImmediatePropagation has been called, we just break out immedi ately, without
448 // handling any more events on this target. 512 // handling any more events on this target.
449 if (event->immediatePropagationStopped()) 513 if (event->immediatePropagationStopped())
450 break; 514 break;
451 515
452 ExecutionContext* context = getExecutionContext();
453 if (!context)
454 break;
455
456 event->setHandlingPassive(registeredListener.passive()); 516 event->setHandlingPassive(registeredListener.passive());
457 517
458 InspectorInstrumentation::NativeBreakpoint nativeBreakpoint(context, thi s, event); 518 InspectorInstrumentation::NativeBreakpoint nativeBreakpoint(context, thi s, event);
459 519
460 // To match Mozilla, the AT_TARGET phase fires both capturing and bubbli ng 520 // To match Mozilla, the AT_TARGET phase fires both capturing and bubbli ng
461 // event listeners, even though that violates some versions of the DOM s pec. 521 // event listeners, even though that violates some versions of the DOM s pec.
462 registeredListener.listener()->handleEvent(context, event); 522 registeredListener.listener()->handleEvent(context, event);
523
524 if (shouldReportBlockedEvent && !registeredListener.passive() && !regist eredListener.blockedEventWarningEmitted() && !event->defaultPrevented())
525 reportBlockedEvent(context, event, &registeredListener, now - event- >platformTimeStamp());
526
463 event->setHandlingPassive(false); 527 event->setHandlingPassive(false);
464 528
465 RELEASE_ASSERT(i <= size); 529 RELEASE_ASSERT(i <= size);
466 } 530 }
467 d->firingEventIterators->removeLast(); 531 d->firingEventIterators->removeLast();
468 } 532 }
469 533
470 DispatchEventResult EventTarget::dispatchEventResult(const Event& event) 534 DispatchEventResult EventTarget::dispatchEventResult(const Event& event)
471 { 535 {
472 if (event.defaultPrevented()) 536 if (event.defaultPrevented())
(...skipping 28 matching lines...) Expand all
501 // they have one less listener to invoke. 565 // they have one less listener to invoke.
502 if (d->firingEventIterators) { 566 if (d->firingEventIterators) {
503 for (size_t i = 0; i < d->firingEventIterators->size(); ++i) { 567 for (size_t i = 0; i < d->firingEventIterators->size(); ++i) {
504 d->firingEventIterators->at(i).iterator = 0; 568 d->firingEventIterators->at(i).iterator = 0;
505 d->firingEventIterators->at(i).end = 0; 569 d->firingEventIterators->at(i).end = 0;
506 } 570 }
507 } 571 }
508 } 572 }
509 573
510 } // namespace blink 574 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698