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

Side by Side Diff: Source/core/frame/LocalDOMWindow.cpp

Issue 1017043002: Remove all event listeners during window's frame destruction step. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: minor tidying Created 5 years, 9 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
« no previous file with comments | « Source/core/frame/LocalDOMWindow.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. 2 * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) 3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 RefPtr<SerializedScriptValue> m_message; 196 RefPtr<SerializedScriptValue> m_message;
197 String m_origin; 197 String m_origin;
198 RefPtrWillBeMember<LocalDOMWindow> m_source; 198 RefPtrWillBeMember<LocalDOMWindow> m_source;
199 OwnPtr<MessagePortChannelArray> m_channels; 199 OwnPtr<MessagePortChannelArray> m_channels;
200 RefPtr<SecurityOrigin> m_targetOrigin; 200 RefPtr<SecurityOrigin> m_targetOrigin;
201 RefPtrWillBeMember<ScriptCallStack> m_stackTrace; 201 RefPtrWillBeMember<ScriptCallStack> m_stackTrace;
202 RefPtr<UserGestureToken> m_userGestureToken; 202 RefPtr<UserGestureToken> m_userGestureToken;
203 int m_asyncOperationId; 203 int m_asyncOperationId;
204 }; 204 };
205 205
206 static void disableSuddenTermination() 206 static void updateSuddenTerminationStatus(LocalDOMWindow* domWindow, bool addedL istener, FrameLoaderClient::SuddenTerminationDisablerType disablerType)
207 { 207 {
208 blink::Platform::current()->suddenTerminationChanged(false); 208 blink::Platform::current()->suddenTerminationChanged(!addedListener);
209 } 209 if (domWindow->frame() && domWindow->frame()->loader().client())
210 210 domWindow->frame()->loader().client()->suddenTerminationDisablerChanged( addedListener, disablerType);
211 static void enableSuddenTermination()
212 {
213 blink::Platform::current()->suddenTerminationChanged(true);
214 } 211 }
215 212
216 typedef HashCountedSet<LocalDOMWindow*> DOMWindowSet; 213 typedef HashCountedSet<LocalDOMWindow*> DOMWindowSet;
217 214
218 static DOMWindowSet& windowsWithUnloadEventListeners() 215 static DOMWindowSet& windowsWithUnloadEventListeners()
219 { 216 {
220 DEFINE_STATIC_LOCAL(DOMWindowSet, windowsWithUnloadEventListeners, ()); 217 DEFINE_STATIC_LOCAL(DOMWindowSet, windowsWithUnloadEventListeners, ());
221 return windowsWithUnloadEventListeners; 218 return windowsWithUnloadEventListeners;
222 } 219 }
223 220
224 static DOMWindowSet& windowsWithBeforeUnloadEventListeners() 221 static DOMWindowSet& windowsWithBeforeUnloadEventListeners()
225 { 222 {
226 DEFINE_STATIC_LOCAL(DOMWindowSet, windowsWithBeforeUnloadEventListeners, ()) ; 223 DEFINE_STATIC_LOCAL(DOMWindowSet, windowsWithBeforeUnloadEventListeners, ()) ;
227 return windowsWithBeforeUnloadEventListeners; 224 return windowsWithBeforeUnloadEventListeners;
228 } 225 }
229 226
230 static void addUnloadEventListener(LocalDOMWindow* domWindow) 227 static void addUnloadEventListener(LocalDOMWindow* domWindow)
231 { 228 {
232 DOMWindowSet& set = windowsWithUnloadEventListeners(); 229 DOMWindowSet& set = windowsWithUnloadEventListeners();
233 if (set.isEmpty()) { 230 if (set.isEmpty())
234 disableSuddenTermination(); 231 updateSuddenTerminationStatus(domWindow, true, FrameLoaderClient::Unload Handler);
235 if (domWindow->frame()) { 232
236 domWindow->frame()->loader().client()->suddenTerminationDisablerChan ged(
237 true, FrameLoaderClient::UnloadHandler);
238 }
239 }
240 set.add(domWindow); 233 set.add(domWindow);
241 } 234 }
242 235
243 static void removeUnloadEventListener(LocalDOMWindow* domWindow) 236 static void removeUnloadEventListener(LocalDOMWindow* domWindow)
244 { 237 {
245 DOMWindowSet& set = windowsWithUnloadEventListeners(); 238 DOMWindowSet& set = windowsWithUnloadEventListeners();
246 DOMWindowSet::iterator it = set.find(domWindow); 239 DOMWindowSet::iterator it = set.find(domWindow);
247 if (it == set.end()) 240 if (it == set.end())
248 return; 241 return;
249 set.remove(it); 242 set.remove(it);
250 if (set.isEmpty()) { 243 if (set.isEmpty())
251 enableSuddenTermination(); 244 updateSuddenTerminationStatus(domWindow, false, FrameLoaderClient::Unloa dHandler);
252 if (domWindow->frame()) {
253 domWindow->frame()->loader().client()->suddenTerminationDisablerChan ged(
254 false, FrameLoaderClient::UnloadHandler);
255 }
256 }
257 } 245 }
258 246
259 static void removeAllUnloadEventListeners(LocalDOMWindow* domWindow) 247 static void removeAllUnloadEventListeners(LocalDOMWindow* domWindow)
260 { 248 {
261 DOMWindowSet& set = windowsWithUnloadEventListeners(); 249 DOMWindowSet& set = windowsWithUnloadEventListeners();
262 DOMWindowSet::iterator it = set.find(domWindow); 250 DOMWindowSet::iterator it = set.find(domWindow);
263 if (it == set.end()) 251 if (it == set.end())
264 return; 252 return;
265 set.removeAll(it); 253 set.removeAll(it);
266 if (set.isEmpty()) { 254 if (set.isEmpty())
267 enableSuddenTermination(); 255 updateSuddenTerminationStatus(domWindow, false, FrameLoaderClient::Unloa dHandler);
268 if (domWindow->frame()) {
269 domWindow->frame()->loader().client()->suddenTerminationDisablerChan ged(
270 false, FrameLoaderClient::UnloadHandler);
271 }
272 }
273 } 256 }
274 257
275 static void addBeforeUnloadEventListener(LocalDOMWindow* domWindow) 258 static void addBeforeUnloadEventListener(LocalDOMWindow* domWindow)
276 { 259 {
277 DOMWindowSet& set = windowsWithBeforeUnloadEventListeners(); 260 DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
278 if (set.isEmpty()) { 261 if (set.isEmpty())
279 disableSuddenTermination(); 262 updateSuddenTerminationStatus(domWindow, true, FrameLoaderClient::Before UnloadHandler);
280 if (domWindow->frame()) { 263
281 domWindow->frame()->loader().client()->suddenTerminationDisablerChan ged(
282 true, FrameLoaderClient::BeforeUnloadHandler);
283 }
284 }
285 set.add(domWindow); 264 set.add(domWindow);
286 } 265 }
287 266
288 static void removeBeforeUnloadEventListener(LocalDOMWindow* domWindow) 267 static void removeBeforeUnloadEventListener(LocalDOMWindow* domWindow)
289 { 268 {
290 DOMWindowSet& set = windowsWithBeforeUnloadEventListeners(); 269 DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
291 DOMWindowSet::iterator it = set.find(domWindow); 270 DOMWindowSet::iterator it = set.find(domWindow);
292 if (it == set.end()) 271 if (it == set.end())
293 return; 272 return;
294 set.remove(it); 273 set.remove(it);
295 if (set.isEmpty()) { 274 if (set.isEmpty())
296 enableSuddenTermination(); 275 updateSuddenTerminationStatus(domWindow, false, FrameLoaderClient::Befor eUnloadHandler);
297 if (domWindow->frame()) {
298 domWindow->frame()->loader().client()->suddenTerminationDisablerChan ged(
299 false, FrameLoaderClient::BeforeUnloadHandler);
300 }
301 }
302 } 276 }
303 277
304 static void removeAllBeforeUnloadEventListeners(LocalDOMWindow* domWindow) 278 static void removeAllBeforeUnloadEventListeners(LocalDOMWindow* domWindow)
305 { 279 {
306 DOMWindowSet& set = windowsWithBeforeUnloadEventListeners(); 280 DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
307 DOMWindowSet::iterator it = set.find(domWindow); 281 DOMWindowSet::iterator it = set.find(domWindow);
308 if (it == set.end()) 282 if (it == set.end())
309 return; 283 return;
310 set.removeAll(it); 284 set.removeAll(it);
311 if (set.isEmpty()) { 285 if (set.isEmpty())
312 enableSuddenTermination(); 286 updateSuddenTerminationStatus(domWindow, false, FrameLoaderClient::Befor eUnloadHandler);
313 if (domWindow->frame()) {
314 domWindow->frame()->loader().client()->suddenTerminationDisablerChan ged(
315 false, FrameLoaderClient::BeforeUnloadHandler);
316 }
317 }
318 } 287 }
319 288
320 static bool allowsBeforeUnloadListeners(LocalDOMWindow* window) 289 static bool allowsBeforeUnloadListeners(LocalDOMWindow* window)
321 { 290 {
322 ASSERT_ARG(window, window); 291 ASSERT_ARG(window, window);
323 LocalFrame* frame = window->frame(); 292 LocalFrame* frame = window->frame();
324 if (!frame) 293 if (!frame)
325 return false; 294 return false;
326 return frame->isMainFrame(); 295 return frame->isMainFrame();
327 } 296 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 return frame() && allowPopUp(*frame()); 341 return frame() && allowPopUp(*frame());
373 } 342 }
374 343
375 LocalDOMWindow::LocalDOMWindow(LocalFrame& frame) 344 LocalDOMWindow::LocalDOMWindow(LocalFrame& frame)
376 : m_frameObserver(WindowFrameObserver::create(this, frame)) 345 : m_frameObserver(WindowFrameObserver::create(this, frame))
377 , m_shouldPrintWhenFinishedLoading(false) 346 , m_shouldPrintWhenFinishedLoading(false)
378 #if ENABLE(ASSERT) 347 #if ENABLE(ASSERT)
379 , m_hasBeenReset(false) 348 , m_hasBeenReset(false)
380 #endif 349 #endif
381 { 350 {
351 #if ENABLE(OILPAN)
352 ThreadState::current()->registerPreFinalizer(*this);
353 #endif
382 } 354 }
383 355
384 void LocalDOMWindow::clearDocument() 356 void LocalDOMWindow::clearDocument()
385 { 357 {
386 if (!m_document) 358 if (!m_document)
387 return; 359 return;
388 360
389 if (m_document->isActive()) { 361 if (m_document->isActive()) {
390 // FIXME: We don't call willRemove here. Why is that OK? 362 // FIXME: We don't call willRemove here. Why is that OK?
391 // This detach() call is also mostly redundant. Most of the calls to 363 // This detach() call is also mostly redundant. Most of the calls to
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 // Per step 11 of section 6.5.9 (history traversal) of the HTML5 spec, we 496 // Per step 11 of section 6.5.9 (history traversal) of the HTML5 spec, we
525 // defer firing of popstate until we're in the complete state. 497 // defer firing of popstate until we're in the complete state.
526 if (document()->isLoadCompleted()) 498 if (document()->isLoadCompleted())
527 enqueuePopstateEvent(stateObject); 499 enqueuePopstateEvent(stateObject);
528 else 500 else
529 m_pendingStateObject = stateObject; 501 m_pendingStateObject = stateObject;
530 } 502 }
531 503
532 LocalDOMWindow::~LocalDOMWindow() 504 LocalDOMWindow::~LocalDOMWindow()
533 { 505 {
534 #if ENABLE(OILPAN) 506 #if ENABLE(OILPAN)
haraken 2015/03/18 23:38:45 Not related to your CL, I'm wondering if we could
sof 2015/03/19 06:27:36 It would be nice to empty this dtor entirely of an
535 // Oilpan: the frame host and document objects are
536 // also garbage collected; cannot notify these
537 // when removing event listeners.
538 removeAllEventListenersInternal(DoNotBroadcastListenerRemoval);
539
540 // Cleared when detaching document. 507 // Cleared when detaching document.
541 ASSERT(!m_eventQueue); 508 ASSERT(!m_eventQueue);
542 #else 509 #else
543 ASSERT(m_hasBeenReset); 510 ASSERT(m_hasBeenReset);
544 reset();
545
546 removeAllEventListenersInternal(DoBroadcastListenerRemoval);
547
548 ASSERT(m_document->isStopped()); 511 ASSERT(m_document->isStopped());
549 clearDocument(); 512 clearDocument();
550 #endif 513 #endif
551 } 514 }
552 515
516 void LocalDOMWindow::dispose()
517 {
518 // Oilpan: should the LocalDOMWindow be GCed along with its LocalFrame, the frame
519 // may not have explicitly detached itself first. In that case, handle the c learing
520 // of event listeners in a prefinalizing action.
521 //
522 // (Non-Oilpan, LocalDOMWindow::reset() will always be invoked which takes c are of this step.)
haraken 2015/03/18 23:38:45 Help me understand: The LocalDOMWindow::reset() is
sof 2015/03/19 06:27:36 Yes, if the frame is detached, reset() will be cal
haraken 2015/03/19 06:54:45 Thanks for the clarification; makes sense!
523 if (!frame())
524 return;
525
526 removeAllEventListeners();
527 }
528
553 const AtomicString& LocalDOMWindow::interfaceName() const 529 const AtomicString& LocalDOMWindow::interfaceName() const
554 { 530 {
555 return EventTargetNames::LocalDOMWindow; 531 return EventTargetNames::LocalDOMWindow;
556 } 532 }
557 533
558 ExecutionContext* LocalDOMWindow::executionContext() const 534 ExecutionContext* LocalDOMWindow::executionContext() const
559 { 535 {
560 return m_document.get(); 536 return m_document.get();
561 } 537 }
562 538
(...skipping 17 matching lines...) Expand all
580 frame()->host()->eventHandlerRegistry().didRemoveAllEventHandlers(*this); 556 frame()->host()->eventHandlerRegistry().didRemoveAllEventHandlers(*this);
581 frame()->host()->consoleMessageStorage().frameWindowDiscarded(this); 557 frame()->host()->consoleMessageStorage().frameWindowDiscarded(this);
582 LocalDOMWindow::notifyContextDestroyed(); 558 LocalDOMWindow::notifyContextDestroyed();
583 } 559 }
584 560
585 void LocalDOMWindow::frameDestroyed() 561 void LocalDOMWindow::frameDestroyed()
586 { 562 {
587 willDestroyDocumentInFrame(); 563 willDestroyDocumentInFrame();
588 resetLocation(); 564 resetLocation();
589 m_properties.clear(); 565 m_properties.clear();
566 removeAllEventListeners();
590 } 567 }
591 568
592 void LocalDOMWindow::willDestroyDocumentInFrame() 569 void LocalDOMWindow::willDestroyDocumentInFrame()
593 { 570 {
594 for (const auto& domWindowProperty : m_properties) 571 for (const auto& domWindowProperty : m_properties)
595 domWindowProperty->willDestroyGlobalObjectInFrame(); 572 domWindowProperty->willDestroyGlobalObjectInFrame();
596 } 573 }
597 574
598 void LocalDOMWindow::willDetachDocumentFromFrame() 575 void LocalDOMWindow::willDetachDocumentFromFrame()
599 { 576 {
(...skipping 970 matching lines...) Expand 10 before | Expand all | Expand 10 after
1570 RefPtrWillBeRawPtr<Event> event = prpEvent; 1547 RefPtrWillBeRawPtr<Event> event = prpEvent;
1571 1548
1572 event->setTarget(prpTarget ? prpTarget : this); 1549 event->setTarget(prpTarget ? prpTarget : this);
1573 event->setCurrentTarget(this); 1550 event->setCurrentTarget(this);
1574 event->setEventPhase(Event::AT_TARGET); 1551 event->setEventPhase(Event::AT_TARGET);
1575 1552
1576 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "EventDispatch" , "data", InspectorEventDispatchEvent::data(*event)); 1553 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "EventDispatch" , "data", InspectorEventDispatchEvent::data(*event));
1577 return fireEventListeners(event.get()); 1554 return fireEventListeners(event.get());
1578 } 1555 }
1579 1556
1580 void LocalDOMWindow::removeAllEventListenersInternal(BroadcastListenerRemoval mo de) 1557 void LocalDOMWindow::removeAllEventListeners()
1581 { 1558 {
1582 EventTarget::removeAllEventListeners(); 1559 EventTarget::removeAllEventListeners();
1583 1560
1584 if (mode == DoBroadcastListenerRemoval) { 1561 notifyRemoveAllEventListeners(this);
1585 notifyRemoveAllEventListeners(this); 1562 if (frame() && frame()->host())
1586 if (frame() && frame()->host()) 1563 frame()->host()->eventHandlerRegistry().didRemoveAllEventHandlers(*this) ;
1587 frame()->host()->eventHandlerRegistry().didRemoveAllEventHandlers(*t his);
1588 }
1589 1564
1590 removeAllUnloadEventListeners(this); 1565 removeAllUnloadEventListeners(this);
1591 removeAllBeforeUnloadEventListeners(this); 1566 removeAllBeforeUnloadEventListeners(this);
1592 } 1567 }
1593 1568
1594 void LocalDOMWindow::removeAllEventListeners()
1595 {
1596 removeAllEventListenersInternal(DoBroadcastListenerRemoval);
1597 }
1598
1599 void LocalDOMWindow::finishedLoading() 1569 void LocalDOMWindow::finishedLoading()
1600 { 1570 {
1601 if (m_shouldPrintWhenFinishedLoading) { 1571 if (m_shouldPrintWhenFinishedLoading) {
1602 m_shouldPrintWhenFinishedLoading = false; 1572 m_shouldPrintWhenFinishedLoading = false;
1603 print(); 1573 print();
1604 } 1574 }
1605 } 1575 }
1606 1576
1607 void LocalDOMWindow::printErrorMessage(const String& message) 1577 void LocalDOMWindow::printErrorMessage(const String& message)
1608 { 1578 {
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1781 return m_frameObserver->frame(); 1751 return m_frameObserver->frame();
1782 } 1752 }
1783 1753
1784 v8::Handle<v8::Object> LocalDOMWindow::wrap(v8::Handle<v8::Object> creationConte xt, v8::Isolate* isolate) 1754 v8::Handle<v8::Object> LocalDOMWindow::wrap(v8::Handle<v8::Object> creationConte xt, v8::Isolate* isolate)
1785 { 1755 {
1786 ASSERT_NOT_REACHED(); // LocalDOMWindow has [Custom=ToV8]. 1756 ASSERT_NOT_REACHED(); // LocalDOMWindow has [Custom=ToV8].
1787 return v8::Handle<v8::Object>(); 1757 return v8::Handle<v8::Object>();
1788 } 1758 }
1789 1759
1790 } // namespace blink 1760 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/frame/LocalDOMWindow.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698