913ae1871161342137b517bd07c47df72eef73ce
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / frame / LocalDOMWindow.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "core/frame/LocalDOMWindow.h"
29
30 #include "bindings/core/v8/Dictionary.h"
31 #include "bindings/core/v8/ExceptionMessages.h"
32 #include "bindings/core/v8/ExceptionState.h"
33 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
34 #include "bindings/core/v8/ScriptCallStackFactory.h"
35 #include "bindings/core/v8/ScriptController.h"
36 #include "bindings/core/v8/SerializedScriptValue.h"
37 #include "bindings/core/v8/V8DOMActivityLogger.h"
38 #include "core/css/CSSComputedStyleDeclaration.h"
39 #include "core/css/CSSRuleList.h"
40 #include "core/css/DOMWindowCSS.h"
41 #include "core/css/MediaQueryList.h"
42 #include "core/css/MediaQueryMatcher.h"
43 #include "core/css/StyleMedia.h"
44 #include "core/css/resolver/StyleResolver.h"
45 #include "core/dom/ContextFeatures.h"
46 #include "core/dom/DOMImplementation.h"
47 #include "core/dom/Document.h"
48 #include "core/dom/Element.h"
49 #include "core/dom/ExceptionCode.h"
50 #include "core/dom/ExecutionContext.h"
51 #include "core/dom/RequestAnimationFrameCallback.h"
52 #include "core/editing/Editor.h"
53 #include "core/events/DOMWindowEventQueue.h"
54 #include "core/events/EventListener.h"
55 #include "core/events/HashChangeEvent.h"
56 #include "core/events/MessageEvent.h"
57 #include "core/events/PageTransitionEvent.h"
58 #include "core/events/PopStateEvent.h"
59 #include "core/frame/BarProp.h"
60 #include "core/frame/Console.h"
61 #include "core/frame/DOMWindowLifecycleNotifier.h"
62 #include "core/frame/EventHandlerRegistry.h"
63 #include "core/frame/FrameConsole.h"
64 #include "core/frame/FrameHost.h"
65 #include "core/frame/FrameView.h"
66 #include "core/frame/History.h"
67 #include "core/frame/LocalFrame.h"
68 #include "core/frame/Location.h"
69 #include "core/frame/Navigator.h"
70 #include "core/frame/Screen.h"
71 #include "core/frame/Settings.h"
72 #include "core/html/HTMLFrameOwnerElement.h"
73 #include "core/inspector/ConsoleMessage.h"
74 #include "core/inspector/InspectorInstrumentation.h"
75 #include "core/inspector/InspectorTraceEvents.h"
76 #include "core/inspector/ScriptCallStack.h"
77 #include "core/loader/DocumentLoader.h"
78 #include "core/loader/FrameLoadRequest.h"
79 #include "core/loader/FrameLoader.h"
80 #include "core/loader/FrameLoaderClient.h"
81 #include "core/loader/MixedContentChecker.h"
82 #include "core/loader/SinkDocument.h"
83 #include "core/loader/appcache/ApplicationCache.h"
84 #include "core/page/BackForwardClient.h"
85 #include "core/page/Chrome.h"
86 #include "core/page/ChromeClient.h"
87 #include "core/page/CreateWindow.h"
88 #include "core/page/EventHandler.h"
89 #include "core/page/FrameTree.h"
90 #include "core/page/Page.h"
91 #include "core/page/WindowFeatures.h"
92 #include "core/page/WindowFocusAllowedIndicator.h"
93 #include "core/page/scrolling/ScrollingCoordinator.h"
94 #include "core/storage/Storage.h"
95 #include "core/storage/StorageArea.h"
96 #include "core/storage/StorageNamespace.h"
97 #include "core/timing/Performance.h"
98 #include "platform/EventDispatchForbiddenScope.h"
99 #include "platform/PlatformScreen.h"
100 #include "platform/RuntimeEnabledFeatures.h"
101 #include "platform/UserGestureIndicator.h"
102 #include "platform/geometry/FloatRect.h"
103 #include "platform/graphics/media/MediaPlayer.h"
104 #include "platform/weborigin/KURL.h"
105 #include "platform/weborigin/SecurityOrigin.h"
106 #include "platform/weborigin/SecurityPolicy.h"
107 #include "public/platform/Platform.h"
108 #include "wtf/MainThread.h"
109 #include "wtf/MathExtras.h"
110 #include "wtf/text/WTFString.h"
111 #include <algorithm>
112
113 using std::min;
114 using std::max;
115
116 namespace blink {
117
118 class PostMessageTimer FINAL : public SuspendableTimer {
119 public:
120     PostMessageTimer(LocalDOMWindow& window, PassRefPtr<SerializedScriptValue> message, const String& sourceOrigin, PassRefPtrWillBeRawPtr<LocalDOMWindow> source, PassOwnPtr<MessagePortChannelArray> channels, SecurityOrigin* targetOrigin, PassRefPtrWillBeRawPtr<ScriptCallStack> stackTrace, UserGestureToken* userGestureToken)
121         : SuspendableTimer(window.document())
122         , m_window(&window)
123         , m_message(message)
124         , m_origin(sourceOrigin)
125         , m_source(source)
126         , m_channels(channels)
127         , m_targetOrigin(targetOrigin)
128         , m_stackTrace(stackTrace)
129         , m_userGestureToken(userGestureToken)
130     {
131         m_asyncOperationId = InspectorInstrumentation::traceAsyncOperationStarting(executionContext(), "postMessage");
132     }
133
134     PassRefPtrWillBeRawPtr<MessageEvent> event()
135     {
136         return MessageEvent::create(m_channels.release(), m_message, m_origin, String(), m_source.get());
137
138     }
139     SecurityOrigin* targetOrigin() const { return m_targetOrigin.get(); }
140     ScriptCallStack* stackTrace() const { return m_stackTrace.get(); }
141     UserGestureToken* userGestureToken() const { return m_userGestureToken.get(); }
142
143 private:
144     virtual void fired() OVERRIDE
145     {
146         InspectorInstrumentationCookie cookie = InspectorInstrumentation::traceAsyncOperationCompletedCallbackStarting(executionContext(), m_asyncOperationId);
147         m_window->postMessageTimerFired(this);
148         // This object is deleted now.
149         InspectorInstrumentation::traceAsyncCallbackCompleted(cookie);
150     }
151
152     // FIXME: Oilpan: This raw pointer is safe because the PostMessageTimer is
153     // owned by the LocalDOMWindow. Ideally PostMessageTimer should be moved to
154     // the heap and use Member<LocalDOMWindow>.
155     LocalDOMWindow* m_window;
156     RefPtr<SerializedScriptValue> m_message;
157     String m_origin;
158     RefPtrWillBePersistent<LocalDOMWindow> m_source;
159     OwnPtr<MessagePortChannelArray> m_channels;
160     RefPtr<SecurityOrigin> m_targetOrigin;
161     RefPtrWillBePersistent<ScriptCallStack> m_stackTrace;
162     RefPtr<UserGestureToken> m_userGestureToken;
163     int m_asyncOperationId;
164 };
165
166 static void disableSuddenTermination()
167 {
168     blink::Platform::current()->suddenTerminationChanged(false);
169 }
170
171 static void enableSuddenTermination()
172 {
173     blink::Platform::current()->suddenTerminationChanged(true);
174 }
175
176 typedef HashCountedSet<LocalDOMWindow*> DOMWindowSet;
177
178 static DOMWindowSet& windowsWithUnloadEventListeners()
179 {
180     DEFINE_STATIC_LOCAL(DOMWindowSet, windowsWithUnloadEventListeners, ());
181     return windowsWithUnloadEventListeners;
182 }
183
184 static DOMWindowSet& windowsWithBeforeUnloadEventListeners()
185 {
186     DEFINE_STATIC_LOCAL(DOMWindowSet, windowsWithBeforeUnloadEventListeners, ());
187     return windowsWithBeforeUnloadEventListeners;
188 }
189
190 static void addUnloadEventListener(LocalDOMWindow* domWindow)
191 {
192     DOMWindowSet& set = windowsWithUnloadEventListeners();
193     if (set.isEmpty())
194         disableSuddenTermination();
195     set.add(domWindow);
196 }
197
198 static void removeUnloadEventListener(LocalDOMWindow* domWindow)
199 {
200     DOMWindowSet& set = windowsWithUnloadEventListeners();
201     DOMWindowSet::iterator it = set.find(domWindow);
202     if (it == set.end())
203         return;
204     set.remove(it);
205     if (set.isEmpty())
206         enableSuddenTermination();
207 }
208
209 static void removeAllUnloadEventListeners(LocalDOMWindow* domWindow)
210 {
211     DOMWindowSet& set = windowsWithUnloadEventListeners();
212     DOMWindowSet::iterator it = set.find(domWindow);
213     if (it == set.end())
214         return;
215     set.removeAll(it);
216     if (set.isEmpty())
217         enableSuddenTermination();
218 }
219
220 static void addBeforeUnloadEventListener(LocalDOMWindow* domWindow)
221 {
222     DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
223     if (set.isEmpty())
224         disableSuddenTermination();
225     set.add(domWindow);
226 }
227
228 static void removeBeforeUnloadEventListener(LocalDOMWindow* domWindow)
229 {
230     DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
231     DOMWindowSet::iterator it = set.find(domWindow);
232     if (it == set.end())
233         return;
234     set.remove(it);
235     if (set.isEmpty())
236         enableSuddenTermination();
237 }
238
239 static void removeAllBeforeUnloadEventListeners(LocalDOMWindow* domWindow)
240 {
241     DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
242     DOMWindowSet::iterator it = set.find(domWindow);
243     if (it == set.end())
244         return;
245     set.removeAll(it);
246     if (set.isEmpty())
247         enableSuddenTermination();
248 }
249
250 static bool allowsBeforeUnloadListeners(LocalDOMWindow* window)
251 {
252     ASSERT_ARG(window, window);
253     LocalFrame* frame = window->frame();
254     if (!frame)
255         return false;
256     return frame->isMainFrame();
257 }
258
259 unsigned LocalDOMWindow::pendingUnloadEventListeners() const
260 {
261     return windowsWithUnloadEventListeners().count(const_cast<LocalDOMWindow*>(this));
262 }
263
264 // This function:
265 // 1) Validates the pending changes are not changing any value to NaN; in that case keep original value.
266 // 2) Constrains the window rect to the minimum window size and no bigger than the float rect's dimensions.
267 // 3) Constrains the window rect to within the top and left boundaries of the available screen rect.
268 // 4) Constrains the window rect to within the bottom and right boundaries of the available screen rect.
269 // 5) Translate the window rect coordinates to be within the coordinate space of the screen.
270 FloatRect LocalDOMWindow::adjustWindowRect(LocalFrame& frame, const FloatRect& pendingChanges)
271 {
272     FrameHost* host = frame.host();
273     ASSERT(host);
274
275     FloatRect screen = screenAvailableRect(frame.view());
276     FloatRect window = host->chrome().windowRect();
277
278     // Make sure we're in a valid state before adjusting dimensions.
279     ASSERT(std::isfinite(screen.x()));
280     ASSERT(std::isfinite(screen.y()));
281     ASSERT(std::isfinite(screen.width()));
282     ASSERT(std::isfinite(screen.height()));
283     ASSERT(std::isfinite(window.x()));
284     ASSERT(std::isfinite(window.y()));
285     ASSERT(std::isfinite(window.width()));
286     ASSERT(std::isfinite(window.height()));
287
288     // Update window values if new requested values are not NaN.
289     if (!std::isnan(pendingChanges.x()))
290         window.setX(pendingChanges.x());
291     if (!std::isnan(pendingChanges.y()))
292         window.setY(pendingChanges.y());
293     if (!std::isnan(pendingChanges.width()))
294         window.setWidth(pendingChanges.width());
295     if (!std::isnan(pendingChanges.height()))
296         window.setHeight(pendingChanges.height());
297
298     FloatSize minimumSize = host->chrome().client().minimumWindowSize();
299     // Let size 0 pass through, since that indicates default size, not minimum size.
300     if (window.width())
301         window.setWidth(min(max(minimumSize.width(), window.width()), screen.width()));
302     if (window.height())
303         window.setHeight(min(max(minimumSize.height(), window.height()), screen.height()));
304
305     // Constrain the window position within the valid screen area.
306     window.setX(max(screen.x(), min(window.x(), screen.maxX() - window.width())));
307     window.setY(max(screen.y(), min(window.y(), screen.maxY() - window.height())));
308
309     return window;
310 }
311
312 bool LocalDOMWindow::allowPopUp(LocalFrame& firstFrame)
313 {
314     if (UserGestureIndicator::processingUserGesture())
315         return true;
316
317     Settings* settings = firstFrame.settings();
318     return settings && settings->javaScriptCanOpenWindowsAutomatically();
319 }
320
321 bool LocalDOMWindow::allowPopUp()
322 {
323     return m_frame && allowPopUp(*m_frame);
324 }
325
326 bool LocalDOMWindow::canShowModalDialogNow(const LocalFrame* frame)
327 {
328     if (!frame)
329         return false;
330     FrameHost* host = frame->host();
331     if (!host)
332         return false;
333     return host->chrome().canRunModalNow();
334 }
335
336 LocalDOMWindow::LocalDOMWindow(LocalFrame& frame)
337     : FrameDestructionObserver(&frame)
338     , m_shouldPrintWhenFinishedLoading(false)
339 #if ENABLE(ASSERT)
340     , m_hasBeenReset(false)
341 #endif
342 {
343     ScriptWrappable::init(this);
344 }
345
346 void LocalDOMWindow::clearDocument()
347 {
348     if (!m_document)
349         return;
350
351     if (m_document->isActive()) {
352         // FIXME: We don't call willRemove here. Why is that OK?
353         // This detach() call is also mostly redundant. Most of the calls to
354         // this function come via DocumentLoader::createWriterFor, which
355         // always detaches the previous Document first. Only XSLTProcessor
356         // depends on this detach() call, so it seems like there's some room
357         // for cleanup.
358         m_document->detach();
359     }
360
361     // FIXME: This should be part of ActiveDOMObject shutdown
362     clearEventQueue();
363
364     m_document->clearDOMWindow();
365     m_document = nullptr;
366 }
367
368 void LocalDOMWindow::clearEventQueue()
369 {
370     if (!m_eventQueue)
371         return;
372     m_eventQueue->close();
373     m_eventQueue.clear();
374 }
375
376 void LocalDOMWindow::acceptLanguagesChanged()
377 {
378     if (m_navigator)
379         m_navigator->setLanguagesChanged();
380
381     dispatchEvent(Event::create(EventTypeNames::languagechange));
382 }
383
384 PassRefPtrWillBeRawPtr<Document> LocalDOMWindow::createDocument(const String& mimeType, const DocumentInit& init, bool forceXHTML)
385 {
386     RefPtrWillBeRawPtr<Document> document = nullptr;
387     if (forceXHTML) {
388         // This is a hack for XSLTProcessor. See XSLTProcessor::createDocumentFromSource().
389         document = Document::create(init);
390     } else {
391         document = DOMImplementation::createDocument(mimeType, init, init.frame() ? init.frame()->inViewSourceMode() : false);
392         if (document->isPluginDocument() && document->isSandboxed(SandboxPlugins))
393             document = SinkDocument::create(init);
394     }
395
396     return document.release();
397 }
398
399 PassRefPtrWillBeRawPtr<Document> LocalDOMWindow::installNewDocument(const String& mimeType, const DocumentInit& init, bool forceXHTML)
400 {
401     ASSERT(init.frame() == m_frame);
402
403     clearDocument();
404
405     m_document = createDocument(mimeType, init, forceXHTML);
406     m_eventQueue = DOMWindowEventQueue::create(m_document.get());
407     m_document->attach();
408
409     if (!m_frame)
410         return m_document;
411
412     m_frame->script().updateDocument();
413     m_document->updateViewportDescription();
414
415     if (m_frame->page() && m_frame->view()) {
416         if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scrollingCoordinator()) {
417             scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_frame->view(), HorizontalScrollbar);
418             scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_frame->view(), VerticalScrollbar);
419             scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_frame->view());
420         }
421     }
422
423     m_frame->selection().updateSecureKeyboardEntryIfActive();
424     return m_document;
425 }
426
427 EventQueue* LocalDOMWindow::eventQueue() const
428 {
429     return m_eventQueue.get();
430 }
431
432 void LocalDOMWindow::enqueueWindowEvent(PassRefPtrWillBeRawPtr<Event> event)
433 {
434     if (!m_eventQueue)
435         return;
436     event->setTarget(this);
437     m_eventQueue->enqueueEvent(event);
438 }
439
440 void LocalDOMWindow::enqueueDocumentEvent(PassRefPtrWillBeRawPtr<Event> event)
441 {
442     if (!m_eventQueue)
443         return;
444     event->setTarget(m_document.get());
445     m_eventQueue->enqueueEvent(event);
446 }
447
448 void LocalDOMWindow::dispatchWindowLoadEvent()
449 {
450     ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden());
451     dispatchLoadEvent();
452 }
453
454 void LocalDOMWindow::documentWasClosed()
455 {
456     dispatchWindowLoadEvent();
457     enqueuePageshowEvent(PageshowEventNotPersisted);
458     if (m_pendingStateObject)
459         enqueuePopstateEvent(m_pendingStateObject.release());
460 }
461
462 void LocalDOMWindow::enqueuePageshowEvent(PageshowEventPersistence persisted)
463 {
464     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36334 Pageshow event needs to fire asynchronously.
465     // As per spec pageshow must be triggered asynchronously.
466     // However to be compatible with other browsers blink fires pageshow synchronously.
467     dispatchEvent(PageTransitionEvent::create(EventTypeNames::pageshow, persisted), m_document.get());
468 }
469
470 void LocalDOMWindow::enqueueHashchangeEvent(const String& oldURL, const String& newURL)
471 {
472     enqueueWindowEvent(HashChangeEvent::create(oldURL, newURL));
473 }
474
475 void LocalDOMWindow::enqueuePopstateEvent(PassRefPtr<SerializedScriptValue> stateObject)
476 {
477     if (!ContextFeatures::pushStateEnabled(document()))
478         return;
479
480     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36202 Popstate event needs to fire asynchronously
481     dispatchEvent(PopStateEvent::create(stateObject, &history()));
482 }
483
484 void LocalDOMWindow::statePopped(PassRefPtr<SerializedScriptValue> stateObject)
485 {
486     if (!frame())
487         return;
488
489     // Per step 11 of section 6.5.9 (history traversal) of the HTML5 spec, we
490     // defer firing of popstate until we're in the complete state.
491     if (document()->isLoadCompleted())
492         enqueuePopstateEvent(stateObject);
493     else
494         m_pendingStateObject = stateObject;
495 }
496
497 LocalDOMWindow::~LocalDOMWindow()
498 {
499     ASSERT(m_hasBeenReset);
500     reset();
501
502 #if ENABLE(OILPAN)
503     // Oilpan: the frame host and document objects are
504     // also garbage collected; cannot notify these
505     // when removing event listeners.
506     removeAllEventListenersInternal(DoNotBroadcastListenerRemoval);
507
508     // Cleared when detaching document.
509     ASSERT(!m_eventQueue);
510 #else
511     removeAllEventListenersInternal(DoBroadcastListenerRemoval);
512
513     ASSERT(m_document->isStopped());
514     clearDocument();
515 #endif
516 }
517
518 const AtomicString& LocalDOMWindow::interfaceName() const
519 {
520     return EventTargetNames::LocalDOMWindow;
521 }
522
523 ExecutionContext* LocalDOMWindow::executionContext() const
524 {
525     return m_document.get();
526 }
527
528 LocalDOMWindow* LocalDOMWindow::toDOMWindow()
529 {
530     return this;
531 }
532
533 PassRefPtrWillBeRawPtr<MediaQueryList> LocalDOMWindow::matchMedia(const String& media)
534 {
535     return document() ? document()->mediaQueryMatcher().matchMedia(media) : nullptr;
536 }
537
538 Page* LocalDOMWindow::page()
539 {
540     return frame() ? frame()->page() : 0;
541 }
542
543 void LocalDOMWindow::frameDestroyed()
544 {
545     FrameDestructionObserver::frameDestroyed();
546     reset();
547 }
548
549 void LocalDOMWindow::willDetachFrameHost()
550 {
551     m_frame->host()->eventHandlerRegistry().didRemoveAllEventHandlers(*this);
552     InspectorInstrumentation::frameWindowDiscarded(m_frame, this);
553 }
554
555 void LocalDOMWindow::willDestroyDocumentInFrame()
556 {
557     // It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may
558     // unregister themselves from the LocalDOMWindow as a result of the call to willDestroyGlobalObjectInFrame.
559     Vector<DOMWindowProperty*> properties;
560     copyToVector(m_properties, properties);
561     for (size_t i = 0; i < properties.size(); ++i)
562         properties[i]->willDestroyGlobalObjectInFrame();
563 }
564
565 void LocalDOMWindow::willDetachDocumentFromFrame()
566 {
567     // It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may
568     // unregister themselves from the LocalDOMWindow as a result of the call to willDetachGlobalObjectFromFrame.
569     Vector<DOMWindowProperty*> properties;
570     copyToVector(m_properties, properties);
571     for (size_t i = 0; i < properties.size(); ++i)
572         properties[i]->willDetachGlobalObjectFromFrame();
573 }
574
575 void LocalDOMWindow::registerProperty(DOMWindowProperty* property)
576 {
577     m_properties.add(property);
578 }
579
580 void LocalDOMWindow::unregisterProperty(DOMWindowProperty* property)
581 {
582     m_properties.remove(property);
583 }
584
585 void LocalDOMWindow::reset()
586 {
587     willDestroyDocumentInFrame();
588     resetDOMWindowProperties();
589 }
590
591 void LocalDOMWindow::resetDOMWindowProperties()
592 {
593     m_properties.clear();
594
595     m_screen = nullptr;
596     m_history = nullptr;
597     m_locationbar = nullptr;
598     m_menubar = nullptr;
599     m_personalbar = nullptr;
600     m_scrollbars = nullptr;
601     m_statusbar = nullptr;
602     m_toolbar = nullptr;
603     m_console = nullptr;
604     m_navigator = nullptr;
605     m_performance = nullptr;
606     m_location = nullptr;
607     m_media = nullptr;
608     m_sessionStorage = nullptr;
609     m_localStorage = nullptr;
610     m_applicationCache = nullptr;
611 #if ENABLE(ASSERT)
612     m_hasBeenReset = true;
613 #endif
614 }
615
616 bool LocalDOMWindow::isCurrentlyDisplayedInFrame() const
617 {
618     return m_frame && m_frame->domWindow() == this && m_frame->host();
619 }
620
621 int LocalDOMWindow::orientation() const
622 {
623     ASSERT(RuntimeEnabledFeatures::orientationEventEnabled());
624
625     if (!m_frame)
626         return 0;
627
628     int orientation = screenOrientationAngle(m_frame->view());
629     // For backward compatibility, we want to return a value in the range of
630     // [-90; 180] instead of [0; 360[ because window.orientation used to behave
631     // like that in WebKit (this is a WebKit proprietary API).
632     if (orientation == 270)
633         return -90;
634     return orientation;
635 }
636
637 Screen& LocalDOMWindow::screen() const
638 {
639     if (!m_screen)
640         m_screen = Screen::create(m_frame);
641     return *m_screen;
642 }
643
644 History& LocalDOMWindow::history() const
645 {
646     if (!m_history)
647         m_history = History::create(m_frame);
648     return *m_history;
649 }
650
651 BarProp& LocalDOMWindow::locationbar() const
652 {
653     if (!m_locationbar)
654         m_locationbar = BarProp::create(m_frame, BarProp::Locationbar);
655     return *m_locationbar;
656 }
657
658 BarProp& LocalDOMWindow::menubar() const
659 {
660     if (!m_menubar)
661         m_menubar = BarProp::create(m_frame, BarProp::Menubar);
662     return *m_menubar;
663 }
664
665 BarProp& LocalDOMWindow::personalbar() const
666 {
667     if (!m_personalbar)
668         m_personalbar = BarProp::create(m_frame, BarProp::Personalbar);
669     return *m_personalbar;
670 }
671
672 BarProp& LocalDOMWindow::scrollbars() const
673 {
674     if (!m_scrollbars)
675         m_scrollbars = BarProp::create(m_frame, BarProp::Scrollbars);
676     return *m_scrollbars;
677 }
678
679 BarProp& LocalDOMWindow::statusbar() const
680 {
681     if (!m_statusbar)
682         m_statusbar = BarProp::create(m_frame, BarProp::Statusbar);
683     return *m_statusbar;
684 }
685
686 BarProp& LocalDOMWindow::toolbar() const
687 {
688     if (!m_toolbar)
689         m_toolbar = BarProp::create(m_frame, BarProp::Toolbar);
690     return *m_toolbar;
691 }
692
693 Console& LocalDOMWindow::console() const
694 {
695     if (!m_console)
696         m_console = Console::create(m_frame);
697     return *m_console;
698 }
699
700 FrameConsole* LocalDOMWindow::frameConsole() const
701 {
702     if (!isCurrentlyDisplayedInFrame())
703         return 0;
704     return &m_frame->console();
705 }
706
707 ApplicationCache* LocalDOMWindow::applicationCache() const
708 {
709     if (!isCurrentlyDisplayedInFrame())
710         return 0;
711     if (!m_applicationCache)
712         m_applicationCache = ApplicationCache::create(m_frame);
713     return m_applicationCache.get();
714 }
715
716 Navigator& LocalDOMWindow::navigator() const
717 {
718     if (!m_navigator)
719         m_navigator = Navigator::create(m_frame);
720     return *m_navigator;
721 }
722
723 Performance& LocalDOMWindow::performance() const
724 {
725     if (!m_performance)
726         m_performance = Performance::create(m_frame);
727     return *m_performance;
728 }
729
730 Location& LocalDOMWindow::location() const
731 {
732     if (!m_location)
733         m_location = Location::create(m_frame);
734     return *m_location;
735 }
736
737 Storage* LocalDOMWindow::sessionStorage(ExceptionState& exceptionState) const
738 {
739     if (!isCurrentlyDisplayedInFrame())
740         return 0;
741
742     Document* document = this->document();
743     if (!document)
744         return 0;
745
746     String accessDeniedMessage = "Access is denied for this document.";
747     if (!document->securityOrigin()->canAccessLocalStorage()) {
748         if (document->isSandboxed(SandboxOrigin))
749             exceptionState.throwSecurityError("The document is sandboxed and lacks the 'allow-same-origin' flag.");
750         else if (document->url().protocolIs("data"))
751             exceptionState.throwSecurityError("Storage is disabled inside 'data:' URLs.");
752         else
753             exceptionState.throwSecurityError(accessDeniedMessage);
754         return 0;
755     }
756
757     if (m_sessionStorage) {
758         if (!m_sessionStorage->area()->canAccessStorage(m_frame)) {
759             exceptionState.throwSecurityError(accessDeniedMessage);
760             return 0;
761         }
762         return m_sessionStorage.get();
763     }
764
765     Page* page = document->page();
766     if (!page)
767         return 0;
768
769     OwnPtrWillBeRawPtr<StorageArea> storageArea = page->sessionStorage()->storageArea(document->securityOrigin());
770     if (!storageArea->canAccessStorage(m_frame)) {
771         exceptionState.throwSecurityError(accessDeniedMessage);
772         return 0;
773     }
774
775     m_sessionStorage = Storage::create(m_frame, storageArea.release());
776     return m_sessionStorage.get();
777 }
778
779 Storage* LocalDOMWindow::localStorage(ExceptionState& exceptionState) const
780 {
781     if (!isCurrentlyDisplayedInFrame())
782         return 0;
783
784     Document* document = this->document();
785     if (!document)
786         return 0;
787
788     String accessDeniedMessage = "Access is denied for this document.";
789     if (!document->securityOrigin()->canAccessLocalStorage()) {
790         if (document->isSandboxed(SandboxOrigin))
791             exceptionState.throwSecurityError("The document is sandboxed and lacks the 'allow-same-origin' flag.");
792         else if (document->url().protocolIs("data"))
793             exceptionState.throwSecurityError("Storage is disabled inside 'data:' URLs.");
794         else
795             exceptionState.throwSecurityError(accessDeniedMessage);
796         return 0;
797     }
798
799     if (m_localStorage) {
800         if (!m_localStorage->area()->canAccessStorage(m_frame)) {
801             exceptionState.throwSecurityError(accessDeniedMessage);
802             return 0;
803         }
804         return m_localStorage.get();
805     }
806
807     // FIXME: Seems this check should be much higher?
808     FrameHost* host = document->frameHost();
809     if (!host || !host->settings().localStorageEnabled())
810         return 0;
811
812     OwnPtrWillBeRawPtr<StorageArea> storageArea = StorageNamespace::localStorageArea(document->securityOrigin());
813     if (!storageArea->canAccessStorage(m_frame)) {
814         exceptionState.throwSecurityError(accessDeniedMessage);
815         return 0;
816     }
817
818     m_localStorage = Storage::create(m_frame, storageArea.release());
819     return m_localStorage.get();
820 }
821
822 void LocalDOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, const String& targetOrigin, LocalDOMWindow* source, ExceptionState& exceptionState)
823 {
824     if (!isCurrentlyDisplayedInFrame())
825         return;
826
827     Document* sourceDocument = source->document();
828
829     // Compute the target origin.  We need to do this synchronously in order
830     // to generate the SyntaxError exception correctly.
831     RefPtr<SecurityOrigin> target;
832     if (targetOrigin == "/") {
833         if (!sourceDocument)
834             return;
835         target = sourceDocument->securityOrigin();
836     } else if (targetOrigin != "*") {
837         target = SecurityOrigin::createFromString(targetOrigin);
838         // It doesn't make sense target a postMessage at a unique origin
839         // because there's no way to represent a unique origin in a string.
840         if (target->isUnique()) {
841             exceptionState.throwDOMException(SyntaxError, "Invalid target origin '" + targetOrigin + "' in a call to 'postMessage'.");
842             return;
843         }
844     }
845
846     OwnPtr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(ports, exceptionState);
847     if (exceptionState.hadException())
848         return;
849
850     // Capture the source of the message.  We need to do this synchronously
851     // in order to capture the source of the message correctly.
852     if (!sourceDocument)
853         return;
854     String sourceOrigin = sourceDocument->securityOrigin()->toString();
855
856     if (MixedContentChecker::isMixedContent(sourceDocument->securityOrigin(), document()->url()))
857         UseCounter::count(document(), UseCounter::PostMessageFromSecureToInsecure);
858     else if (MixedContentChecker::isMixedContent(document()->securityOrigin(), sourceDocument->url()))
859         UseCounter::count(document(), UseCounter::PostMessageFromInsecureToSecure);
860
861     // Capture stack trace only when inspector front-end is loaded as it may be time consuming.
862     RefPtrWillBeRawPtr<ScriptCallStack> stackTrace = nullptr;
863     if (InspectorInstrumentation::consoleAgentEnabled(sourceDocument))
864         stackTrace = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true);
865
866     // Schedule the message.
867     OwnPtr<PostMessageTimer> timer = adoptPtr(new PostMessageTimer(*this, message, sourceOrigin, source, channels.release(), target.get(), stackTrace.release(), UserGestureIndicator::currentToken()));
868     timer->startOneShot(0, FROM_HERE);
869     timer->suspendIfNeeded();
870     m_postMessageTimers.add(timer.release());
871 }
872
873 void LocalDOMWindow::postMessageTimerFired(PostMessageTimer* timer)
874 {
875     if (!isCurrentlyDisplayedInFrame()) {
876         m_postMessageTimers.remove(timer);
877         return;
878     }
879
880     RefPtrWillBeRawPtr<MessageEvent> event = timer->event();
881
882     // Give the embedder a chance to intercept this postMessage because this
883     // LocalDOMWindow might be a proxy for another in browsers that support
884     // postMessage calls across WebKit instances.
885     if (m_frame->loader().client()->willCheckAndDispatchMessageEvent(timer->targetOrigin(), event.get())) {
886         m_postMessageTimers.remove(timer);
887         return;
888     }
889
890     UserGestureIndicator gestureIndicator(timer->userGestureToken());
891
892     event->entangleMessagePorts(document());
893     dispatchMessageEventWithOriginCheck(timer->targetOrigin(), event, timer->stackTrace());
894     m_postMessageTimers.remove(timer);
895 }
896
897 void LocalDOMWindow::dispatchMessageEventWithOriginCheck(SecurityOrigin* intendedTargetOrigin, PassRefPtrWillBeRawPtr<Event> event, PassRefPtrWillBeRawPtr<ScriptCallStack> stackTrace)
898 {
899     if (intendedTargetOrigin) {
900         // Check target origin now since the target document may have changed since the timer was scheduled.
901         if (!intendedTargetOrigin->isSameSchemeHostPort(document()->securityOrigin())) {
902             String message = ExceptionMessages::failedToExecute("postMessage", "DOMWindow", "The target origin provided ('" + intendedTargetOrigin->toString() + "') does not match the recipient window's origin ('" + document()->securityOrigin()->toString() + "').");
903             RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, message);
904             consoleMessage->setCallStack(stackTrace);
905             frameConsole()->addMessage(consoleMessage.release());
906             return;
907         }
908     }
909
910     dispatchEvent(event);
911 }
912
913 DOMSelection* LocalDOMWindow::getSelection()
914 {
915     if (!isCurrentlyDisplayedInFrame() || !m_frame)
916         return 0;
917
918     return m_frame->document()->getSelection();
919 }
920
921 Element* LocalDOMWindow::frameElement() const
922 {
923     if (!m_frame)
924         return 0;
925
926     // The bindings security check should ensure we're same origin...
927     ASSERT(!m_frame->owner() || m_frame->owner()->isLocal());
928     return m_frame->deprecatedLocalOwner();
929 }
930
931 void LocalDOMWindow::focus(ExecutionContext* context)
932 {
933     if (!m_frame)
934         return;
935
936     FrameHost* host = m_frame->host();
937     if (!host)
938         return;
939
940     bool allowFocus = WindowFocusAllowedIndicator::windowFocusAllowed();
941     if (context) {
942         ASSERT(isMainThread());
943         Document* activeDocument = toDocument(context);
944         if (opener() && opener() != this && activeDocument->domWindow() == opener())
945             allowFocus = true;
946     }
947
948     // If we're a top level window, bring the window to the front.
949     if (m_frame->isMainFrame() && allowFocus)
950         host->chrome().focus();
951
952     if (!m_frame)
953         return;
954
955     m_frame->eventHandler().focusDocumentView();
956 }
957
958 void LocalDOMWindow::blur()
959 {
960 }
961
962 void LocalDOMWindow::close(ExecutionContext* context)
963 {
964     if (!m_frame || !m_frame->isMainFrame())
965         return;
966
967     Page* page = m_frame->page();
968     if (!page)
969         return;
970
971     if (context) {
972         ASSERT(isMainThread());
973         Document* activeDocument = toDocument(context);
974         if (!activeDocument)
975             return;
976
977         if (!activeDocument->canNavigate(*m_frame))
978             return;
979     }
980
981     Settings* settings = m_frame->settings();
982     bool allowScriptsToCloseWindows = settings && settings->allowScriptsToCloseWindows();
983
984     if (!(page->openedByDOM() || page->backForward().backForwardListCount() <= 1 || allowScriptsToCloseWindows)) {
985         frameConsole()->addMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, "Scripts may close only the windows that were opened by it."));
986         return;
987     }
988
989     if (!m_frame->loader().shouldClose())
990         return;
991
992     InspectorInstrumentation::willCloseWindow(context);
993
994     page->chrome().closeWindowSoon();
995 }
996
997 void LocalDOMWindow::print()
998 {
999     if (!m_frame)
1000         return;
1001
1002     FrameHost* host = m_frame->host();
1003     if (!host)
1004         return;
1005
1006     if (m_frame->loader().state() != FrameStateComplete) {
1007         m_shouldPrintWhenFinishedLoading = true;
1008         return;
1009     }
1010     m_shouldPrintWhenFinishedLoading = false;
1011     host->chrome().print(m_frame);
1012 }
1013
1014 void LocalDOMWindow::stop()
1015 {
1016     if (!m_frame)
1017         return;
1018     m_frame->loader().stopAllLoaders();
1019 }
1020
1021 void LocalDOMWindow::alert(const String& message)
1022 {
1023     if (!m_frame)
1024         return;
1025
1026     m_frame->document()->updateRenderTreeIfNeeded();
1027
1028     FrameHost* host = m_frame->host();
1029     if (!host)
1030         return;
1031
1032     host->chrome().runJavaScriptAlert(m_frame, message);
1033 }
1034
1035 bool LocalDOMWindow::confirm(const String& message)
1036 {
1037     if (!m_frame)
1038         return false;
1039
1040     m_frame->document()->updateRenderTreeIfNeeded();
1041
1042     FrameHost* host = m_frame->host();
1043     if (!host)
1044         return false;
1045
1046     return host->chrome().runJavaScriptConfirm(m_frame, message);
1047 }
1048
1049 String LocalDOMWindow::prompt(const String& message, const String& defaultValue)
1050 {
1051     if (!m_frame)
1052         return String();
1053
1054     m_frame->document()->updateRenderTreeIfNeeded();
1055
1056     FrameHost* host = m_frame->host();
1057     if (!host)
1058         return String();
1059
1060     String returnValue;
1061     if (host->chrome().runJavaScriptPrompt(m_frame, message, defaultValue, returnValue))
1062         return returnValue;
1063
1064     return String();
1065 }
1066
1067 bool LocalDOMWindow::find(const String& string, bool caseSensitive, bool backwards, bool wrap, bool /*wholeWord*/, bool /*searchInFrames*/, bool /*showDialog*/) const
1068 {
1069     if (!isCurrentlyDisplayedInFrame())
1070         return false;
1071
1072     // |m_frame| can be destructed during |Editor::findString()| via
1073     // |Document::updateLayou()|, e.g. event handler removes a frame.
1074     RefPtr<LocalFrame> protectFrame(m_frame);
1075
1076     // FIXME (13016): Support wholeWord, searchInFrames and showDialog
1077     return m_frame->editor().findString(string, !backwards, caseSensitive, wrap, false);
1078 }
1079
1080 bool LocalDOMWindow::offscreenBuffering() const
1081 {
1082     return true;
1083 }
1084
1085 int LocalDOMWindow::outerHeight() const
1086 {
1087     if (!m_frame)
1088         return 0;
1089
1090     FrameHost* host = m_frame->host();
1091     if (!host)
1092         return 0;
1093
1094     if (host->settings().reportScreenSizeInPhysicalPixelsQuirk())
1095         return lroundf(host->chrome().windowRect().height() * host->deviceScaleFactor());
1096     return static_cast<int>(host->chrome().windowRect().height());
1097 }
1098
1099 int LocalDOMWindow::outerWidth() const
1100 {
1101     if (!m_frame)
1102         return 0;
1103
1104     FrameHost* host = m_frame->host();
1105     if (!host)
1106         return 0;
1107
1108     if (host->settings().reportScreenSizeInPhysicalPixelsQuirk())
1109         return lroundf(host->chrome().windowRect().width() * host->deviceScaleFactor());
1110     return static_cast<int>(host->chrome().windowRect().width());
1111 }
1112
1113 int LocalDOMWindow::innerHeight() const
1114 {
1115     if (!m_frame)
1116         return 0;
1117
1118     FrameView* view = m_frame->view();
1119     if (!view)
1120         return 0;
1121
1122     // FIXME: This is potentially too much work. We really only need to know the dimensions of the parent frame's renderer.
1123     if (Frame* parent = m_frame->tree().parent()) {
1124         if (parent && parent->isLocalFrame())
1125             toLocalFrame(parent)->document()->updateLayoutIgnorePendingStylesheets();
1126     }
1127
1128     return adjustForAbsoluteZoom(view->visibleContentRect(IncludeScrollbars).height(), m_frame->pageZoomFactor());
1129 }
1130
1131 int LocalDOMWindow::innerWidth() const
1132 {
1133     if (!m_frame)
1134         return 0;
1135
1136     FrameView* view = m_frame->view();
1137     if (!view)
1138         return 0;
1139
1140     // FIXME: This is potentially too much work. We really only need to know the dimensions of the parent frame's renderer.
1141     if (Frame* parent = m_frame->tree().parent()) {
1142         if (parent && parent->isLocalFrame())
1143             toLocalFrame(parent)->document()->updateLayoutIgnorePendingStylesheets();
1144     }
1145
1146     return adjustForAbsoluteZoom(view->visibleContentRect(IncludeScrollbars).width(), m_frame->pageZoomFactor());
1147 }
1148
1149 int LocalDOMWindow::screenX() const
1150 {
1151     if (!m_frame)
1152         return 0;
1153
1154     FrameHost* host = m_frame->host();
1155     if (!host)
1156         return 0;
1157
1158     if (host->settings().reportScreenSizeInPhysicalPixelsQuirk())
1159         return lroundf(host->chrome().windowRect().x() * host->deviceScaleFactor());
1160     return static_cast<int>(host->chrome().windowRect().x());
1161 }
1162
1163 int LocalDOMWindow::screenY() const
1164 {
1165     if (!m_frame)
1166         return 0;
1167
1168     FrameHost* host = m_frame->host();
1169     if (!host)
1170         return 0;
1171
1172     if (host->settings().reportScreenSizeInPhysicalPixelsQuirk())
1173         return lroundf(host->chrome().windowRect().y() * host->deviceScaleFactor());
1174     return static_cast<int>(host->chrome().windowRect().y());
1175 }
1176
1177 int LocalDOMWindow::scrollX() const
1178 {
1179     if (!m_frame)
1180         return 0;
1181
1182     FrameView* view = m_frame->view();
1183     if (!view)
1184         return 0;
1185
1186     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1187
1188     return adjustForAbsoluteZoom(view->scrollX(), m_frame->pageZoomFactor());
1189 }
1190
1191 int LocalDOMWindow::scrollY() const
1192 {
1193     if (!m_frame)
1194         return 0;
1195
1196     FrameView* view = m_frame->view();
1197     if (!view)
1198         return 0;
1199
1200     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1201
1202     return adjustForAbsoluteZoom(view->scrollY(), m_frame->pageZoomFactor());
1203 }
1204
1205 bool LocalDOMWindow::closed() const
1206 {
1207     return !m_frame;
1208 }
1209
1210 unsigned LocalDOMWindow::length() const
1211 {
1212     if (!isCurrentlyDisplayedInFrame())
1213         return 0;
1214
1215     return m_frame->tree().scopedChildCount();
1216 }
1217
1218 const AtomicString& LocalDOMWindow::name() const
1219 {
1220     if (!isCurrentlyDisplayedInFrame())
1221         return nullAtom;
1222
1223     return m_frame->tree().name();
1224 }
1225
1226 void LocalDOMWindow::setName(const AtomicString& name)
1227 {
1228     if (!isCurrentlyDisplayedInFrame())
1229         return;
1230
1231     m_frame->tree().setName(name);
1232     ASSERT(m_frame->loader().client());
1233     m_frame->loader().client()->didChangeName(name);
1234 }
1235
1236 void LocalDOMWindow::setStatus(const String& string)
1237 {
1238     m_status = string;
1239
1240     if (!m_frame)
1241         return;
1242
1243     FrameHost* host = m_frame->host();
1244     if (!host)
1245         return;
1246
1247     ASSERT(m_frame->document()); // Client calls shouldn't be made when the frame is in inconsistent state.
1248     host->chrome().setStatusbarText(m_frame, m_status);
1249 }
1250
1251 void LocalDOMWindow::setDefaultStatus(const String& string)
1252 {
1253     m_defaultStatus = string;
1254
1255     if (!m_frame)
1256         return;
1257
1258     FrameHost* host = m_frame->host();
1259     if (!host)
1260         return;
1261
1262     ASSERT(m_frame->document()); // Client calls shouldn't be made when the frame is in inconsistent state.
1263     host->chrome().setStatusbarText(m_frame, m_defaultStatus);
1264 }
1265
1266 LocalDOMWindow* LocalDOMWindow::self() const
1267 {
1268     if (!m_frame)
1269         return 0;
1270
1271     return m_frame->domWindow();
1272 }
1273
1274 LocalDOMWindow* LocalDOMWindow::opener() const
1275 {
1276     if (!m_frame)
1277         return 0;
1278
1279     LocalFrame* opener = m_frame->loader().opener();
1280     if (!opener)
1281         return 0;
1282
1283     return opener->domWindow();
1284 }
1285
1286 LocalDOMWindow* LocalDOMWindow::parent() const
1287 {
1288     if (!m_frame)
1289         return 0;
1290
1291     Frame* parent = m_frame->tree().parent();
1292     if (parent)
1293         return parent->domWindow();
1294
1295     return m_frame->domWindow();
1296 }
1297
1298 LocalDOMWindow* LocalDOMWindow::top() const
1299 {
1300     if (!m_frame)
1301         return 0;
1302
1303     return m_frame->tree().top()->domWindow();
1304 }
1305
1306 Document* LocalDOMWindow::document() const
1307 {
1308     return m_document.get();
1309 }
1310
1311 StyleMedia& LocalDOMWindow::styleMedia() const
1312 {
1313     if (!m_media)
1314         m_media = StyleMedia::create(m_frame);
1315     return *m_media;
1316 }
1317
1318 PassRefPtrWillBeRawPtr<CSSStyleDeclaration> LocalDOMWindow::getComputedStyle(Element* elt, const String& pseudoElt) const
1319 {
1320     if (!elt)
1321         return nullptr;
1322
1323     return CSSComputedStyleDeclaration::create(elt, false, pseudoElt);
1324 }
1325
1326 PassRefPtrWillBeRawPtr<CSSRuleList> LocalDOMWindow::getMatchedCSSRules(Element* element, const String& pseudoElement) const
1327 {
1328     if (!element)
1329         return nullptr;
1330
1331     if (!isCurrentlyDisplayedInFrame())
1332         return nullptr;
1333
1334     unsigned colonStart = pseudoElement[0] == ':' ? (pseudoElement[1] == ':' ? 2 : 1) : 0;
1335     CSSSelector::PseudoType pseudoType = CSSSelector::parsePseudoType(AtomicString(pseudoElement.substring(colonStart)));
1336     if (pseudoType == CSSSelector::PseudoUnknown && !pseudoElement.isEmpty())
1337         return nullptr;
1338
1339     unsigned rulesToInclude = StyleResolver::AuthorCSSRules;
1340     PseudoId pseudoId = CSSSelector::pseudoId(pseudoType);
1341     return m_frame->document()->ensureStyleResolver().pseudoCSSRulesForElement(element, pseudoId, rulesToInclude);
1342 }
1343
1344 double LocalDOMWindow::devicePixelRatio() const
1345 {
1346     if (!m_frame)
1347         return 0.0;
1348
1349     return m_frame->devicePixelRatio();
1350 }
1351
1352 static bool scrollBehaviorFromScrollOptions(const Dictionary& scrollOptions, ScrollBehavior& scrollBehavior, ExceptionState& exceptionState)
1353 {
1354     String scrollBehaviorString;
1355     if (!DictionaryHelper::get(scrollOptions, "behavior", scrollBehaviorString)) {
1356         scrollBehavior = ScrollBehaviorAuto;
1357         return true;
1358     }
1359
1360     if (ScrollableArea::scrollBehaviorFromString(scrollBehaviorString, scrollBehavior))
1361         return true;
1362
1363     exceptionState.throwTypeError("The ScrollBehavior provided is invalid.");
1364     return false;
1365 }
1366
1367 void LocalDOMWindow::scrollBy(int x, int y, ScrollBehavior scrollBehavior) const
1368 {
1369     if (!isCurrentlyDisplayedInFrame())
1370         return;
1371
1372     document()->updateLayoutIgnorePendingStylesheets();
1373
1374     FrameView* view = m_frame->view();
1375     if (!view)
1376         return;
1377
1378     IntSize scaledOffset(x * m_frame->pageZoomFactor(), y * m_frame->pageZoomFactor());
1379     view->scrollBy(scaledOffset, scrollBehavior);
1380 }
1381
1382 void LocalDOMWindow::scrollBy(int x, int y, const Dictionary& scrollOptions, ExceptionState &exceptionState) const
1383 {
1384     ScrollBehavior scrollBehavior = ScrollBehaviorAuto;
1385     if (!scrollBehaviorFromScrollOptions(scrollOptions, scrollBehavior, exceptionState))
1386         return;
1387     scrollBy(x, y, scrollBehavior);
1388 }
1389
1390 void LocalDOMWindow::scrollTo(int x, int y, ScrollBehavior scrollBehavior) const
1391 {
1392     if (!isCurrentlyDisplayedInFrame())
1393         return;
1394
1395     document()->updateLayoutIgnorePendingStylesheets();
1396
1397     RefPtr<FrameView> view = m_frame->view();
1398     if (!view)
1399         return;
1400
1401     IntPoint layoutPos(x * m_frame->pageZoomFactor(), y * m_frame->pageZoomFactor());
1402     view->setScrollPosition(layoutPos, scrollBehavior);
1403 }
1404
1405 void LocalDOMWindow::scrollTo(int x, int y, const Dictionary& scrollOptions, ExceptionState& exceptionState) const
1406 {
1407     ScrollBehavior scrollBehavior = ScrollBehaviorAuto;
1408     if (!scrollBehaviorFromScrollOptions(scrollOptions, scrollBehavior, exceptionState))
1409         return;
1410     scrollTo(x, y, scrollBehavior);
1411 }
1412
1413 void LocalDOMWindow::moveBy(float x, float y) const
1414 {
1415     if (!m_frame || !m_frame->isMainFrame())
1416         return;
1417
1418     FrameHost* host = m_frame->host();
1419     if (!host)
1420         return;
1421
1422     FloatRect windowRect = host->chrome().windowRect();
1423     windowRect.move(x, y);
1424     // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
1425     host->chrome().setWindowRect(adjustWindowRect(*m_frame, windowRect));
1426 }
1427
1428 void LocalDOMWindow::moveTo(float x, float y) const
1429 {
1430     if (!m_frame || !m_frame->isMainFrame())
1431         return;
1432
1433     FrameHost* host = m_frame->host();
1434     if (!host)
1435         return;
1436
1437     FloatRect windowRect = host->chrome().windowRect();
1438     windowRect.setLocation(FloatPoint(x, y));
1439     // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
1440     host->chrome().setWindowRect(adjustWindowRect(*m_frame, windowRect));
1441 }
1442
1443 void LocalDOMWindow::resizeBy(float x, float y) const
1444 {
1445     if (!m_frame || !m_frame->isMainFrame())
1446         return;
1447
1448     FrameHost* host = m_frame->host();
1449     if (!host)
1450         return;
1451
1452     FloatRect fr = host->chrome().windowRect();
1453     FloatSize dest = fr.size() + FloatSize(x, y);
1454     FloatRect update(fr.location(), dest);
1455     host->chrome().setWindowRect(adjustWindowRect(*m_frame, update));
1456 }
1457
1458 void LocalDOMWindow::resizeTo(float width, float height) const
1459 {
1460     if (!m_frame || !m_frame->isMainFrame())
1461         return;
1462
1463     FrameHost* host = m_frame->host();
1464     if (!host)
1465         return;
1466
1467     FloatRect fr = host->chrome().windowRect();
1468     FloatSize dest = FloatSize(width, height);
1469     FloatRect update(fr.location(), dest);
1470     host->chrome().setWindowRect(adjustWindowRect(*m_frame, update));
1471 }
1472
1473 int LocalDOMWindow::requestAnimationFrame(PassOwnPtr<RequestAnimationFrameCallback> callback)
1474 {
1475     callback->m_useLegacyTimeBase = false;
1476     if (Document* d = document())
1477         return d->requestAnimationFrame(callback);
1478     return 0;
1479 }
1480
1481 int LocalDOMWindow::webkitRequestAnimationFrame(PassOwnPtr<RequestAnimationFrameCallback> callback)
1482 {
1483     callback->m_useLegacyTimeBase = true;
1484     if (Document* d = document())
1485         return d->requestAnimationFrame(callback);
1486     return 0;
1487 }
1488
1489 void LocalDOMWindow::cancelAnimationFrame(int id)
1490 {
1491     if (Document* d = document())
1492         d->cancelAnimationFrame(id);
1493 }
1494
1495 DOMWindowCSS& LocalDOMWindow::css() const
1496 {
1497     if (!m_css)
1498         m_css = DOMWindowCSS::create();
1499     return *m_css;
1500 }
1501
1502 static void didAddStorageEventListener(LocalDOMWindow* window)
1503 {
1504     // Creating these blink::Storage objects informs the system that we'd like to receive
1505     // notifications about storage events that might be triggered in other processes. Rather
1506     // than subscribe to these notifications explicitly, we subscribe to them implicitly to
1507     // simplify the work done by the system.
1508     window->localStorage(IGNORE_EXCEPTION);
1509     window->sessionStorage(IGNORE_EXCEPTION);
1510 }
1511
1512 bool LocalDOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
1513 {
1514     if (!EventTarget::addEventListener(eventType, listener, useCapture))
1515         return false;
1516
1517     if (m_frame && m_frame->host())
1518         m_frame->host()->eventHandlerRegistry().didAddEventHandler(*this, eventType);
1519
1520     if (Document* document = this->document()) {
1521         document->addListenerTypeIfNeeded(eventType);
1522         if (eventType == EventTypeNames::storage)
1523             didAddStorageEventListener(this);
1524     }
1525
1526     lifecycleNotifier().notifyAddEventListener(this, eventType);
1527
1528     if (eventType == EventTypeNames::unload) {
1529         UseCounter::count(document(), UseCounter::DocumentUnloadRegistered);
1530         addUnloadEventListener(this);
1531     } else if (eventType == EventTypeNames::beforeunload) {
1532         UseCounter::count(document(), UseCounter::DocumentBeforeUnloadRegistered);
1533         if (allowsBeforeUnloadListeners(this)) {
1534             // This is confusingly named. It doesn't actually add the listener. It just increments a count
1535             // so that we know we have listeners registered for the purposes of determining if we can
1536             // fast terminate the renderer process.
1537             addBeforeUnloadEventListener(this);
1538         } else {
1539             // Subframes return false from allowsBeforeUnloadListeners.
1540             UseCounter::count(document(), UseCounter::SubFrameBeforeUnloadRegistered);
1541         }
1542     }
1543
1544     return true;
1545 }
1546
1547 bool LocalDOMWindow::removeEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
1548 {
1549     if (!EventTarget::removeEventListener(eventType, listener, useCapture))
1550         return false;
1551
1552     if (m_frame && m_frame->host())
1553         m_frame->host()->eventHandlerRegistry().didRemoveEventHandler(*this, eventType);
1554
1555     lifecycleNotifier().notifyRemoveEventListener(this, eventType);
1556
1557     if (eventType == EventTypeNames::unload) {
1558         removeUnloadEventListener(this);
1559     } else if (eventType == EventTypeNames::beforeunload && allowsBeforeUnloadListeners(this)) {
1560         removeBeforeUnloadEventListener(this);
1561     }
1562
1563     return true;
1564 }
1565
1566 void LocalDOMWindow::dispatchLoadEvent()
1567 {
1568     RefPtrWillBeRawPtr<Event> loadEvent(Event::create(EventTypeNames::load));
1569     if (m_frame && m_frame->loader().documentLoader() && !m_frame->loader().documentLoader()->timing()->loadEventStart()) {
1570         // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed while dispatching
1571         // the event, so protect it to prevent writing the end time into freed memory.
1572         RefPtr<DocumentLoader> documentLoader = m_frame->loader().documentLoader();
1573         DocumentLoadTiming* timing = documentLoader->timing();
1574         timing->markLoadEventStart();
1575         dispatchEvent(loadEvent, document());
1576         timing->markLoadEventEnd();
1577     } else
1578         dispatchEvent(loadEvent, document());
1579
1580     // For load events, send a separate load event to the enclosing frame only.
1581     // This is a DOM extension and is independent of bubbling/capturing rules of
1582     // the DOM.
1583     FrameOwner* owner = m_frame ? m_frame->owner() : 0;
1584     if (owner)
1585         owner->dispatchLoad();
1586
1587     TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "MarkLoad", "data", InspectorMarkLoadEvent::data(frame()));
1588     // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
1589     InspectorInstrumentation::loadEventFired(frame());
1590 }
1591
1592 bool LocalDOMWindow::dispatchEvent(PassRefPtrWillBeRawPtr<Event> prpEvent, PassRefPtrWillBeRawPtr<EventTarget> prpTarget)
1593 {
1594     ASSERT(!EventDispatchForbiddenScope::isEventDispatchForbidden());
1595
1596     RefPtrWillBeRawPtr<EventTarget> protect(this);
1597     RefPtrWillBeRawPtr<Event> event = prpEvent;
1598
1599     event->setTarget(prpTarget ? prpTarget : this);
1600     event->setCurrentTarget(this);
1601     event->setEventPhase(Event::AT_TARGET);
1602
1603     TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "EventDispatch", "data", InspectorEventDispatchEvent::data(*event));
1604     // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing.
1605     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEventOnWindow(frame(), *event, this);
1606
1607     bool result = fireEventListeners(event.get());
1608
1609     InspectorInstrumentation::didDispatchEventOnWindow(cookie);
1610
1611     return result;
1612 }
1613
1614 void LocalDOMWindow::removeAllEventListenersInternal(BroadcastListenerRemoval mode)
1615 {
1616     EventTarget::removeAllEventListeners();
1617
1618     lifecycleNotifier().notifyRemoveAllEventListeners(this);
1619
1620     if (mode == DoBroadcastListenerRemoval) {
1621         if (m_frame && m_frame->host())
1622             m_frame->host()->eventHandlerRegistry().didRemoveAllEventHandlers(*this);
1623     }
1624
1625     removeAllUnloadEventListeners(this);
1626     removeAllBeforeUnloadEventListeners(this);
1627 }
1628
1629 void LocalDOMWindow::removeAllEventListeners()
1630 {
1631     removeAllEventListenersInternal(DoBroadcastListenerRemoval);
1632 }
1633
1634 void LocalDOMWindow::finishedLoading()
1635 {
1636     if (m_shouldPrintWhenFinishedLoading) {
1637         m_shouldPrintWhenFinishedLoading = false;
1638         print();
1639     }
1640 }
1641
1642 void LocalDOMWindow::setLocation(const String& urlString, LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, SetLocationLocking locking)
1643 {
1644     if (!isCurrentlyDisplayedInFrame())
1645         return;
1646
1647     Document* activeDocument = callingWindow->document();
1648     if (!activeDocument)
1649         return;
1650
1651     ASSERT(m_frame);
1652     if (!activeDocument->canNavigate(*m_frame))
1653         return;
1654
1655     LocalFrame* firstFrame = enteredWindow->frame();
1656     if (!firstFrame)
1657         return;
1658
1659     KURL completedURL = firstFrame->document()->completeURL(urlString);
1660     if (completedURL.isNull())
1661         return;
1662
1663     if (isInsecureScriptAccess(*callingWindow, completedURL))
1664         return;
1665
1666     V8DOMActivityLogger* activityLogger = V8DOMActivityLogger::currentActivityLoggerIfIsolatedWorld();
1667     if (activityLogger) {
1668         Vector<String> argv;
1669         argv.append("LocalDOMWindow");
1670         argv.append("url");
1671         argv.append(firstFrame->document()->url());
1672         argv.append(completedURL);
1673         activityLogger->logEvent("blinkSetAttribute", argv.size(), argv.data());
1674     }
1675
1676     // We want a new history item if we are processing a user gesture.
1677     m_frame->navigationScheduler().scheduleLocationChange(activeDocument,
1678         // FIXME: What if activeDocument()->frame() is 0?
1679         completedURL, Referrer(activeDocument->outgoingReferrer(), activeDocument->referrerPolicy()),
1680         locking != LockHistoryBasedOnGestureState);
1681 }
1682
1683 void LocalDOMWindow::printErrorMessage(const String& message)
1684 {
1685     if (!isCurrentlyDisplayedInFrame())
1686         return;
1687
1688     if (message.isEmpty())
1689         return;
1690
1691     frameConsole()->addMessage(ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, message));
1692 }
1693
1694 // FIXME: Once we're throwing exceptions for cross-origin access violations, we will always sanitize the target
1695 // frame details, so we can safely combine 'crossDomainAccessErrorMessage' with this method after considering
1696 // exactly which details may be exposed to JavaScript.
1697 //
1698 // http://crbug.com/17325
1699 String LocalDOMWindow::sanitizedCrossDomainAccessErrorMessage(LocalDOMWindow* callingWindow)
1700 {
1701     if (!callingWindow || !callingWindow->document())
1702         return String();
1703
1704     const KURL& callingWindowURL = callingWindow->document()->url();
1705     if (callingWindowURL.isNull())
1706         return String();
1707
1708     ASSERT(!callingWindow->document()->securityOrigin()->canAccess(document()->securityOrigin()));
1709
1710     SecurityOrigin* activeOrigin = callingWindow->document()->securityOrigin();
1711     String message = "Blocked a frame with origin \"" + activeOrigin->toString() + "\" from accessing a cross-origin frame.";
1712
1713     // FIXME: Evaluate which details from 'crossDomainAccessErrorMessage' may safely be reported to JavaScript.
1714
1715     return message;
1716 }
1717
1718 String LocalDOMWindow::crossDomainAccessErrorMessage(LocalDOMWindow* callingWindow)
1719 {
1720     if (!callingWindow || !callingWindow->document())
1721         return String();
1722
1723     const KURL& callingWindowURL = callingWindow->document()->url();
1724     if (callingWindowURL.isNull())
1725         return String();
1726
1727     ASSERT(!callingWindow->document()->securityOrigin()->canAccess(document()->securityOrigin()));
1728
1729     // FIXME: This message, and other console messages, have extra newlines. Should remove them.
1730     SecurityOrigin* activeOrigin = callingWindow->document()->securityOrigin();
1731     SecurityOrigin* targetOrigin = document()->securityOrigin();
1732     String message = "Blocked a frame with origin \"" + activeOrigin->toString() + "\" from accessing a frame with origin \"" + targetOrigin->toString() + "\". ";
1733
1734     // Sandbox errors: Use the origin of the frames' location, rather than their actual origin (since we know that at least one will be "null").
1735     KURL activeURL = callingWindow->document()->url();
1736     KURL targetURL = document()->url();
1737     if (document()->isSandboxed(SandboxOrigin) || callingWindow->document()->isSandboxed(SandboxOrigin)) {
1738         message = "Blocked a frame at \"" + SecurityOrigin::create(activeURL)->toString() + "\" from accessing a frame at \"" + SecurityOrigin::create(targetURL)->toString() + "\". ";
1739         if (document()->isSandboxed(SandboxOrigin) && callingWindow->document()->isSandboxed(SandboxOrigin))
1740             return "Sandbox access violation: " + message + " Both frames are sandboxed and lack the \"allow-same-origin\" flag.";
1741         if (document()->isSandboxed(SandboxOrigin))
1742             return "Sandbox access violation: " + message + " The frame being accessed is sandboxed and lacks the \"allow-same-origin\" flag.";
1743         return "Sandbox access violation: " + message + " The frame requesting access is sandboxed and lacks the \"allow-same-origin\" flag.";
1744     }
1745
1746     // Protocol errors: Use the URL's protocol rather than the origin's protocol so that we get a useful message for non-heirarchal URLs like 'data:'.
1747     if (targetOrigin->protocol() != activeOrigin->protocol())
1748         return message + " The frame requesting access has a protocol of \"" + activeURL.protocol() + "\", the frame being accessed has a protocol of \"" + targetURL.protocol() + "\". Protocols must match.\n";
1749
1750     // 'document.domain' errors.
1751     if (targetOrigin->domainWasSetInDOM() && activeOrigin->domainWasSetInDOM())
1752         return message + "The frame requesting access set \"document.domain\" to \"" + activeOrigin->domain() + "\", the frame being accessed set it to \"" + targetOrigin->domain() + "\". Both must set \"document.domain\" to the same value to allow access.";
1753     if (activeOrigin->domainWasSetInDOM())
1754         return message + "The frame requesting access set \"document.domain\" to \"" + activeOrigin->domain() + "\", but the frame being accessed did not. Both must set \"document.domain\" to the same value to allow access.";
1755     if (targetOrigin->domainWasSetInDOM())
1756         return message + "The frame being accessed set \"document.domain\" to \"" + targetOrigin->domain() + "\", but the frame requesting access did not. Both must set \"document.domain\" to the same value to allow access.";
1757
1758     // Default.
1759     return message + "Protocols, domains, and ports must match.";
1760 }
1761
1762 bool LocalDOMWindow::isInsecureScriptAccess(LocalDOMWindow& callingWindow, const String& urlString)
1763 {
1764     if (!protocolIsJavaScript(urlString))
1765         return false;
1766
1767     // If this LocalDOMWindow isn't currently active in the LocalFrame, then there's no
1768     // way we should allow the access.
1769     // FIXME: Remove this check if we're able to disconnect LocalDOMWindow from
1770     // LocalFrame on navigation: https://bugs.webkit.org/show_bug.cgi?id=62054
1771     if (isCurrentlyDisplayedInFrame()) {
1772         // FIXME: Is there some way to eliminate the need for a separate "callingWindow == this" check?
1773         if (&callingWindow == this)
1774             return false;
1775
1776         // FIXME: The name canAccess seems to be a roundabout way to ask "can execute script".
1777         // Can we name the SecurityOrigin function better to make this more clear?
1778         if (callingWindow.document()->securityOrigin()->canAccess(document()->securityOrigin()))
1779             return false;
1780     }
1781
1782     printErrorMessage(crossDomainAccessErrorMessage(&callingWindow));
1783     return true;
1784 }
1785
1786 PassRefPtrWillBeRawPtr<LocalDOMWindow> LocalDOMWindow::open(const String& urlString, const AtomicString& frameName, const String& windowFeaturesString,
1787     LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow)
1788 {
1789     if (!isCurrentlyDisplayedInFrame())
1790         return nullptr;
1791     Document* activeDocument = callingWindow->document();
1792     if (!activeDocument)
1793         return nullptr;
1794     LocalFrame* firstFrame = enteredWindow->frame();
1795     if (!firstFrame)
1796         return nullptr;
1797
1798     UseCounter::count(*activeDocument, UseCounter::DOMWindowOpen);
1799     if (!windowFeaturesString.isEmpty())
1800         UseCounter::count(*activeDocument, UseCounter::DOMWindowOpenFeatures);
1801
1802     if (!enteredWindow->allowPopUp()) {
1803         // Because FrameTree::find() returns true for empty strings, we must check for empty frame names.
1804         // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker.
1805         if (frameName.isEmpty() || !m_frame->tree().find(frameName))
1806             return nullptr;
1807     }
1808
1809     // Get the target frame for the special cases of _top and _parent.
1810     // In those cases, we schedule a location change right now and return early.
1811     Frame* targetFrame = 0;
1812     if (frameName == "_top")
1813         targetFrame = m_frame->tree().top();
1814     else if (frameName == "_parent") {
1815         if (Frame* parent = m_frame->tree().parent())
1816             targetFrame = parent;
1817         else
1818             targetFrame = m_frame;
1819     }
1820     // FIXME: Navigating RemoteFrames is not yet supported.
1821     if (targetFrame && targetFrame->isLocalFrame()) {
1822         if (!activeDocument->canNavigate(*targetFrame))
1823             return nullptr;
1824
1825         KURL completedURL = firstFrame->document()->completeURL(urlString);
1826
1827         if (targetFrame->domWindow()->isInsecureScriptAccess(*callingWindow, completedURL))
1828             return targetFrame->domWindow();
1829
1830         if (urlString.isEmpty())
1831             return targetFrame->domWindow();
1832
1833         // For whatever reason, Firefox uses the first window rather than the active window to
1834         // determine the outgoing referrer. We replicate that behavior here.
1835         toLocalFrame(targetFrame)->navigationScheduler().scheduleLocationChange(
1836             activeDocument,
1837             completedURL,
1838             Referrer(firstFrame->document()->outgoingReferrer(), firstFrame->document()->referrerPolicy()),
1839             false);
1840         return targetFrame->domWindow();
1841     }
1842
1843     WindowFeatures windowFeatures(windowFeaturesString);
1844     LocalFrame* result = createWindow(urlString, frameName, windowFeatures, *callingWindow, *firstFrame, *m_frame);
1845     return result ? result->domWindow() : 0;
1846 }
1847
1848 void LocalDOMWindow::showModalDialog(const String& urlString, const String& dialogFeaturesString,
1849     LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, PrepareDialogFunction function, void* functionContext)
1850 {
1851     if (!isCurrentlyDisplayedInFrame())
1852         return;
1853     LocalFrame* activeFrame = callingWindow->frame();
1854     if (!activeFrame)
1855         return;
1856     LocalFrame* firstFrame = enteredWindow->frame();
1857     if (!firstFrame)
1858         return;
1859
1860     if (!canShowModalDialogNow(m_frame) || !enteredWindow->allowPopUp())
1861         return;
1862
1863     UseCounter::countDeprecation(this, UseCounter::ShowModalDialog);
1864
1865     WindowFeatures windowFeatures(dialogFeaturesString, screenAvailableRect(m_frame->view()));
1866     LocalFrame* dialogFrame = createWindow(urlString, emptyAtom, windowFeatures,
1867         *callingWindow, *firstFrame, *m_frame, function, functionContext);
1868     if (!dialogFrame)
1869         return;
1870     UserGestureIndicatorDisabler disabler;
1871     dialogFrame->host()->chrome().runModal();
1872 }
1873
1874 LocalDOMWindow* LocalDOMWindow::anonymousIndexedGetter(uint32_t index)
1875 {
1876     LocalFrame* frame = this->frame();
1877     if (!frame)
1878         return 0;
1879
1880     Frame* child = frame->tree().scopedChild(index);
1881     if (child)
1882         return child->domWindow();
1883
1884     return 0;
1885 }
1886
1887 DOMWindowLifecycleNotifier& LocalDOMWindow::lifecycleNotifier()
1888 {
1889     return static_cast<DOMWindowLifecycleNotifier&>(LifecycleContext<LocalDOMWindow>::lifecycleNotifier());
1890 }
1891
1892 PassOwnPtr<LifecycleNotifier<LocalDOMWindow> > LocalDOMWindow::createLifecycleNotifier()
1893 {
1894     return DOMWindowLifecycleNotifier::create(this);
1895 }
1896
1897 void LocalDOMWindow::trace(Visitor* visitor)
1898 {
1899     visitor->trace(m_document);
1900     visitor->trace(m_screen);
1901     visitor->trace(m_history);
1902     visitor->trace(m_locationbar);
1903     visitor->trace(m_menubar);
1904     visitor->trace(m_personalbar);
1905     visitor->trace(m_scrollbars);
1906     visitor->trace(m_statusbar);
1907     visitor->trace(m_toolbar);
1908     visitor->trace(m_console);
1909     visitor->trace(m_navigator);
1910     visitor->trace(m_location);
1911     visitor->trace(m_media);
1912     visitor->trace(m_sessionStorage);
1913     visitor->trace(m_localStorage);
1914     visitor->trace(m_applicationCache);
1915     visitor->trace(m_performance);
1916     visitor->trace(m_css);
1917     visitor->trace(m_eventQueue);
1918     WillBeHeapSupplementable<LocalDOMWindow>::trace(visitor);
1919     EventTargetWithInlineData::trace(visitor);
1920     LifecycleContext<LocalDOMWindow>::trace(visitor);
1921 }
1922
1923 } // namespace blink