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