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