summaryrefslogtreecommitdiff
path: root/Source/WebCore/page/DOMWindow.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/page/DOMWindow.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/page/DOMWindow.cpp')
-rw-r--r--Source/WebCore/page/DOMWindow.cpp1319
1 files changed, 747 insertions, 572 deletions
diff --git a/Source/WebCore/page/DOMWindow.cpp b/Source/WebCore/page/DOMWindow.cpp
index 7533b009a..6aedb09c8 100644
--- a/Source/WebCore/page/DOMWindow.cpp
+++ b/Source/WebCore/page/DOMWindow.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008, 2010, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
*
* Redistribution and use in source and binary forms, with or without
@@ -11,17 +11,17 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
@@ -29,22 +29,22 @@
#include "BackForwardController.h"
#include "BarProp.h"
-#include "BeforeUnloadEvent.h"
#include "CSSComputedStyleDeclaration.h"
#include "CSSRule.h"
#include "CSSRuleList.h"
#include "Chrome.h"
#include "ChromeClient.h"
-#include "Console.h"
+#include "ComposedTreeIterator.h"
+#include "ContentExtensionActions.h"
+#include "ContentExtensionRule.h"
#include "Crypto.h"
+#include "CustomElementRegistry.h"
#include "DOMApplicationCache.h"
#include "DOMSelection.h"
-#include "DOMSettableTokenList.h"
#include "DOMStringList.h"
#include "DOMTimer.h"
#include "DOMTokenList.h"
#include "DOMURL.h"
-#include "DOMWindowCSS.h"
#include "DOMWindowExtension.h"
#include "DOMWindowNotifications.h"
#include "DeviceMotionController.h"
@@ -53,12 +53,10 @@
#include "DocumentLoader.h"
#include "Editor.h"
#include "Element.h"
-#include "EventException.h"
#include "EventHandler.h"
#include "EventListener.h"
#include "EventNames.h"
#include "ExceptionCode.h"
-#include "ExceptionCodePlaceholder.h"
#include "FloatRect.h"
#include "FocusController.h"
#include "FrameLoadRequest.h"
@@ -69,7 +67,8 @@
#include "HTMLFrameOwnerElement.h"
#include "History.h"
#include "InspectorInstrumentation.h"
-#include "URL.h"
+#include "JSMainThreadExecState.h"
+#include "Language.h"
#include "Location.h"
#include "MainFrame.h"
#include "MediaQueryList.h"
@@ -77,103 +76,132 @@
#include "MessageEvent.h"
#include "Navigator.h"
#include "Page.h"
-#include "PageConsole.h"
-#include "PageGroup.h"
+#include "PageConsoleClient.h"
#include "PageTransitionEvent.h"
#include "Performance.h"
-#include "PlatformScreen.h"
+#include "RequestAnimationFrameCallback.h"
+#include "ResourceLoadInfo.h"
+#include "RuntimeApplicationChecks.h"
#include "RuntimeEnabledFeatures.h"
#include "ScheduledAction.h"
#include "Screen.h"
-#include "ScriptCallStack.h"
-#include "ScriptCallStackFactory.h"
#include "ScriptController.h"
#include "SecurityOrigin.h"
+#include "SecurityOriginData.h"
#include "SecurityPolicy.h"
+#include "SelectorQuery.h"
#include "SerializedScriptValue.h"
#include "Settings.h"
+#include "StaticNodeList.h"
#include "Storage.h"
#include "StorageArea.h"
#include "StorageNamespace.h"
+#include "StorageNamespaceProvider.h"
#include "StyleMedia.h"
#include "StyleResolver.h"
+#include "StyleScope.h"
#include "SuddenTermination.h"
+#include "URL.h"
+#include "UserGestureIndicator.h"
#include "WebKitPoint.h"
#include "WindowFeatures.h"
#include "WindowFocusAllowedIndicator.h"
#include <algorithm>
+#include <inspector/ScriptCallStack.h>
+#include <inspector/ScriptCallStackFactory.h>
+#include <memory>
#include <wtf/CurrentTime.h>
#include <wtf/MainThread.h>
#include <wtf/MathExtras.h>
+#include <wtf/NeverDestroyed.h>
#include <wtf/Ref.h>
-#include <wtf/text/Base64.h>
+#include <wtf/Variant.h>
#include <wtf/text/WTFString.h>
-#if ENABLE(PROXIMITY_EVENTS)
-#include "DeviceProximityController.h"
+#if ENABLE(USER_MESSAGE_HANDLERS)
+#include "UserContentController.h"
+#include "UserMessageHandlerDescriptor.h"
+#include "WebKitNamespace.h"
#endif
-#if ENABLE(REQUEST_ANIMATION_FRAME)
-#include "RequestAnimationFrameCallback.h"
+#if ENABLE(GAMEPAD)
+#include "GamepadManager.h"
#endif
-#if PLATFORM(IOS)
#if ENABLE(GEOLOCATION)
#include "NavigatorGeolocation.h"
#endif
+
+#if ENABLE(POINTER_LOCK)
+#include "PointerLockController.h"
+#endif
+
+#if ENABLE(PROXIMITY_EVENTS)
+#include "DeviceProximityController.h"
+#endif
+
+#if PLATFORM(IOS)
#include "WKContentObservation.h"
+#include "WKContentObservationInternal.h"
#endif
+using namespace Inspector;
+
namespace WebCore {
class PostMessageTimer : public TimerBase {
public:
- PostMessageTimer(DOMWindow* window, PassRefPtr<SerializedScriptValue> message, const String& sourceOrigin, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortChannelArray> channels, SecurityOrigin* targetOrigin, PassRefPtr<ScriptCallStack> stackTrace)
+ PostMessageTimer(DOMWindow& window, Ref<SerializedScriptValue>&& message, const String& sourceOrigin, DOMWindow& source, std::unique_ptr<MessagePortChannelArray> channels, RefPtr<SecurityOrigin>&& targetOrigin, RefPtr<ScriptCallStack>&& stackTrace)
: m_window(window)
- , m_message(message)
+ , m_message(WTFMove(message))
, m_origin(sourceOrigin)
, m_source(source)
- , m_channels(channels)
- , m_targetOrigin(targetOrigin)
+ , m_channels(WTFMove(channels))
+ , m_targetOrigin(WTFMove(targetOrigin))
, m_stackTrace(stackTrace)
+ , m_userGestureToForward(UserGestureIndicator::currentUserGesture())
{
}
- PassRefPtr<MessageEvent> event(ScriptExecutionContext* context)
+ Ref<MessageEvent> event(ScriptExecutionContext& context)
{
- OwnPtr<MessagePortArray> messagePorts = MessagePort::entanglePorts(*context, m_channels.release());
- return MessageEvent::create(messagePorts.release(), m_message, m_origin, String(), m_source);
+ return MessageEvent::create(MessagePort::entanglePorts(context, WTFMove(m_channels)), WTFMove(m_message), m_origin, { }, MessageEventSource(RefPtr<DOMWindow>(WTFMove(m_source))));
}
+
SecurityOrigin* targetOrigin() const { return m_targetOrigin.get(); }
ScriptCallStack* stackTrace() const { return m_stackTrace.get(); }
private:
- virtual void fired()
+ void fired() override
{
- m_window->postMessageTimerFired(adoptPtr(this));
- // This object is deleted now.
+ // This object gets deleted when std::unique_ptr falls out of scope..
+ std::unique_ptr<PostMessageTimer> timer(this);
+
+ UserGestureIndicator userGestureIndicator(m_userGestureToForward);
+ m_window->postMessageTimerFired(*timer);
}
- RefPtr<DOMWindow> m_window;
- RefPtr<SerializedScriptValue> m_message;
+ Ref<DOMWindow> m_window;
+ Ref<SerializedScriptValue> m_message;
String m_origin;
- RefPtr<DOMWindow> m_source;
- OwnPtr<MessagePortChannelArray> m_channels;
+ Ref<DOMWindow> m_source;
+ std::unique_ptr<MessagePortChannelArray> m_channels;
RefPtr<SecurityOrigin> m_targetOrigin;
RefPtr<ScriptCallStack> m_stackTrace;
+ RefPtr<UserGestureToken> m_userGestureToForward;
};
typedef HashCountedSet<DOMWindow*> DOMWindowSet;
static DOMWindowSet& windowsWithUnloadEventListeners()
{
- DEFINE_STATIC_LOCAL(DOMWindowSet, windowsWithUnloadEventListeners, ());
+ static NeverDestroyed<DOMWindowSet> windowsWithUnloadEventListeners;
return windowsWithUnloadEventListeners;
}
static DOMWindowSet& windowsWithBeforeUnloadEventListeners()
{
- DEFINE_STATIC_LOCAL(DOMWindowSet, windowsWithBeforeUnloadEventListeners, ());
+ static NeverDestroyed<DOMWindowSet> windowsWithBeforeUnloadEventListeners;
return windowsWithBeforeUnloadEventListeners;
}
@@ -237,22 +265,21 @@ bool DOMWindow::dispatchAllPendingBeforeUnloadEvents()
Vector<Ref<DOMWindow>> windows;
windows.reserveInitialCapacity(set.size());
- for (auto it = set.begin(), end = set.end(); it != end; ++it)
- windows.uncheckedAppend(*it->key);
+ for (auto& window : set)
+ windows.uncheckedAppend(*window.key);
- for (unsigned i = 0; i < windows.size(); ++i) {
- DOMWindow& window = windows[i].get();
- if (!set.contains(&window))
+ for (auto& window : windows) {
+ if (!set.contains(window.ptr()))
continue;
- Frame* frame = window.frame();
+ Frame* frame = window->frame();
if (!frame)
continue;
if (!frame->loader().shouldClose())
return false;
- window.enableSuddenTermination();
+ window->enableSuddenTermination();
}
alreadyDispatched = true;
@@ -277,18 +304,17 @@ void DOMWindow::dispatchAllPendingUnloadEvents()
Vector<Ref<DOMWindow>> windows;
windows.reserveInitialCapacity(set.size());
- for (auto it = set.begin(), end = set.end(); it != end; ++it)
- windows.uncheckedAppend(*it->key);
+ for (auto& keyValue : set)
+ windows.uncheckedAppend(*keyValue.key);
- for (unsigned i = 0; i < windows.size(); ++i) {
- DOMWindow& window = windows[i].get();
- if (!set.contains(&window))
+ for (auto& window : windows) {
+ if (!set.contains(window.ptr()))
continue;
- window.dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, false), window.document());
- window.dispatchEvent(Event::create(eventNames().unloadEvent, false, false), window.document());
+ window->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, false), window->document());
+ window->dispatchEvent(Event::create(eventNames().unloadEvent, false, false), window->document());
- window.enableSuddenTermination();
+ window->enableSuddenTermination();
}
alreadyDispatched = true;
@@ -300,12 +326,10 @@ void DOMWindow::dispatchAllPendingUnloadEvents()
// 3) Constrains the window rect to within the top and left boundaries of the available screen rect.
// 4) Constrains the window rect to within the bottom and right boundaries of the available screen rect.
// 5) Translate the window rect coordinates to be within the coordinate space of the screen.
-FloatRect DOMWindow::adjustWindowRect(Page* page, const FloatRect& pendingChanges)
+FloatRect DOMWindow::adjustWindowRect(Page& page, const FloatRect& pendingChanges)
{
- ASSERT(page);
-
- FloatRect screen = screenAvailableRect(page->mainFrame().view());
- FloatRect window = page->chrome().windowRect();
+ FloatRect screen = screenAvailableRect(page.mainFrame().view());
+ FloatRect window = page.chrome().windowRect();
// Make sure we're in a valid state before adjusting dimensions.
ASSERT(std::isfinite(screen.x()));
@@ -327,7 +351,7 @@ FloatRect DOMWindow::adjustWindowRect(Page* page, const FloatRect& pendingChange
if (!std::isnan(pendingChanges.height()))
window.setHeight(pendingChanges.height());
- FloatSize minimumSize = page->chrome().client().minimumWindowSize();
+ FloatSize minimumSize = page.chrome().client().minimumWindowSize();
window.setWidth(std::min(std::max(minimumSize.width(), window.width()), screen.width()));
window.setHeight(std::min(std::max(minimumSize.height(), window.height()), screen.height()));
@@ -338,67 +362,59 @@ FloatRect DOMWindow::adjustWindowRect(Page* page, const FloatRect& pendingChange
return window;
}
-bool DOMWindow::allowPopUp(Frame* firstFrame)
+bool DOMWindow::allowPopUp(Frame& firstFrame)
{
- ASSERT(firstFrame);
-
- if (ScriptController::processingUserGesture())
- return true;
-
- return firstFrame->settings().javaScriptCanOpenWindowsAutomatically();
+ return ScriptController::processingUserGesture()
+ || firstFrame.settings().javaScriptCanOpenWindowsAutomatically();
}
bool DOMWindow::allowPopUp()
{
- return m_frame && allowPopUp(m_frame);
+ return m_frame && allowPopUp(*m_frame);
}
-bool DOMWindow::canShowModalDialog(const Frame* frame)
+bool DOMWindow::canShowModalDialog(const Frame& frame)
{
- if (!frame)
- return false;
- Page* page = frame->page();
- if (!page)
- return false;
- return page->chrome().canRunModal();
+ // Override support for layout testing purposes.
+ if (auto* document = frame.document()) {
+ if (auto* window = document->domWindow()) {
+ if (window->m_canShowModalDialogOverride)
+ return window->m_canShowModalDialogOverride.value();
+ }
+ }
+
+ auto* page = frame.page();
+ return page && page->chrome().canRunModal();
}
-bool DOMWindow::canShowModalDialogNow(const Frame* frame)
+static void languagesChangedCallback(void* context)
{
- if (!frame)
- return false;
- Page* page = frame->page();
- if (!page)
- return false;
- return page->chrome().canRunModalNow();
+ static_cast<DOMWindow*>(context)->languagesChanged();
}
-DOMWindow::DOMWindow(Document* document)
- : ContextDestructionObserver(document)
- , FrameDestructionObserver(document->frame())
- , m_shouldPrintWhenFinishedLoading(false)
- , m_suspendedForPageCache(false)
- , m_lastPageStatus(PageStatusNone)
-#if PLATFORM(IOS)
- , m_scrollEventListenerCount(0)
-#endif
-#if ENABLE(IOS_TOUCH_EVENTS) || ENABLE(IOS_GESTURE_EVENTS)
- , m_touchEventListenerCount(0)
-#endif
+void DOMWindow::setCanShowModalDialogOverride(bool allow)
+{
+ m_canShowModalDialogOverride = allow;
+}
+
+DOMWindow::DOMWindow(Document& document)
+ : ContextDestructionObserver(&document)
+ , FrameDestructionObserver(document.frame())
+ , m_weakPtrFactory(this)
{
ASSERT(frame());
- ASSERT(DOMWindow::document());
+ addLanguageChangeObserver(this, &languagesChangedCallback);
}
-void DOMWindow::didSecureTransitionTo(Document* document)
+void DOMWindow::didSecureTransitionTo(Document& document)
{
- observeContext(document);
+ observeContext(&document);
}
DOMWindow::~DOMWindow()
{
#ifndef NDEBUG
- if (!m_suspendedForPageCache) {
+ if (!m_suspendedForDocumentSuspension) {
ASSERT(!m_screen);
ASSERT(!m_history);
ASSERT(!m_crypto);
@@ -408,7 +424,6 @@ DOMWindow::~DOMWindow()
ASSERT(!m_scrollbars);
ASSERT(!m_statusbar);
ASSERT(!m_toolbar);
- ASSERT(!m_console);
ASSERT(!m_navigator);
#if ENABLE(WEB_TIMING)
ASSERT(!m_performance);
@@ -421,7 +436,7 @@ DOMWindow::~DOMWindow()
}
#endif
- if (m_suspendedForPageCache)
+ if (m_suspendedForDocumentSuspension)
willDestroyCachedFrame();
else
willDestroyDocumentInFrame();
@@ -432,6 +447,13 @@ DOMWindow::~DOMWindow()
removeAllUnloadEventListeners(this);
removeAllBeforeUnloadEventListeners(this);
+
+#if ENABLE(GAMEPAD)
+ if (m_gamepadEventListenerCount)
+ GamepadManager::singleton().unregisterDOMWindow(this);
+#endif
+
+ removeLanguageChangeObserver(this);
}
DOMWindow* DOMWindow::toDOMWindow()
@@ -439,26 +461,30 @@ DOMWindow* DOMWindow::toDOMWindow()
return this;
}
-PassRefPtr<MediaQueryList> DOMWindow::matchMedia(const String& media)
+RefPtr<MediaQueryList> DOMWindow::matchMedia(const String& media)
{
- return document() ? document()->mediaQueryMatcher().matchMedia(media) : 0;
+ return document() ? document()->mediaQueryMatcher().matchMedia(media) : nullptr;
}
Page* DOMWindow::page()
{
- return frame() ? frame()->page() : 0;
+ return frame() ? frame()->page() : nullptr;
}
void DOMWindow::frameDestroyed()
{
+ Ref<DOMWindow> protectedThis(*this);
+
willDestroyDocumentInFrame();
FrameDestructionObserver::frameDestroyed();
resetDOMWindowProperties();
+ JSDOMWindowBase::fireFrameClearedWatchpointsForWindow(this);
}
void DOMWindow::willDetachPage()
{
- InspectorInstrumentation::frameWindowDiscarded(m_frame, this);
+ if (m_frame)
+ InspectorInstrumentation::frameWindowDiscarded(*m_frame, this);
}
void DOMWindow::willDestroyCachedFrame()
@@ -467,8 +493,8 @@ void DOMWindow::willDestroyCachedFrame()
// unregister themselves from the DOMWindow as a result of the call to willDestroyGlobalObjectInCachedFrame.
Vector<DOMWindowProperty*> properties;
copyToVector(m_properties, properties);
- for (size_t i = 0; i < properties.size(); ++i)
- properties[i]->willDestroyGlobalObjectInCachedFrame();
+ for (auto& property : properties)
+ property->willDestroyGlobalObjectInCachedFrame();
}
void DOMWindow::willDestroyDocumentInFrame()
@@ -477,8 +503,8 @@ void DOMWindow::willDestroyDocumentInFrame()
// unregister themselves from the DOMWindow as a result of the call to willDestroyGlobalObjectInFrame.
Vector<DOMWindowProperty*> properties;
copyToVector(m_properties, properties);
- for (size_t i = 0; i < properties.size(); ++i)
- properties[i]->willDestroyGlobalObjectInFrame();
+ for (auto& property : properties)
+ property->willDestroyGlobalObjectInFrame();
}
void DOMWindow::willDetachDocumentFromFrame()
@@ -487,84 +513,103 @@ void DOMWindow::willDetachDocumentFromFrame()
// unregister themselves from the DOMWindow as a result of the call to willDetachGlobalObjectFromFrame.
Vector<DOMWindowProperty*> properties;
copyToVector(m_properties, properties);
- for (size_t i = 0; i < properties.size(); ++i)
- properties[i]->willDetachGlobalObjectFromFrame();
+ for (auto& property : properties)
+ property->willDetachGlobalObjectFromFrame();
}
-void DOMWindow::registerProperty(DOMWindowProperty* property)
+#if ENABLE(GAMEPAD)
+
+void DOMWindow::incrementGamepadEventListenerCount()
{
- m_properties.add(property);
+ if (++m_gamepadEventListenerCount == 1)
+ GamepadManager::singleton().registerDOMWindow(this);
}
-void DOMWindow::unregisterProperty(DOMWindowProperty* property)
+void DOMWindow::decrementGamepadEventListenerCount()
{
- m_properties.remove(property);
+ ASSERT(m_gamepadEventListenerCount);
+
+ if (!--m_gamepadEventListenerCount)
+ GamepadManager::singleton().unregisterDOMWindow(this);
}
-void DOMWindow::resetUnlessSuspendedForPageCache()
+#endif
+
+void DOMWindow::registerProperty(DOMWindowProperty& property)
+{
+ m_properties.add(&property);
+}
+
+void DOMWindow::unregisterProperty(DOMWindowProperty& property)
{
- if (m_suspendedForPageCache)
+ m_properties.remove(&property);
+}
+
+void DOMWindow::resetUnlessSuspendedForDocumentSuspension()
+{
+ if (m_suspendedForDocumentSuspension)
return;
willDestroyDocumentInFrame();
resetDOMWindowProperties();
}
-void DOMWindow::suspendForPageCache()
+void DOMWindow::suspendForDocumentSuspension()
{
disconnectDOMWindowProperties();
- m_suspendedForPageCache = true;
+ m_suspendedForDocumentSuspension = true;
}
-void DOMWindow::resumeFromPageCache()
+void DOMWindow::resumeFromDocumentSuspension()
{
reconnectDOMWindowProperties();
- m_suspendedForPageCache = false;
+ m_suspendedForDocumentSuspension = false;
}
void DOMWindow::disconnectDOMWindowProperties()
{
// It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may
- // unregister themselves from the DOMWindow as a result of the call to disconnectFrameForPageCache.
+ // unregister themselves from the DOMWindow as a result of the call to disconnectFrameForDocumentSuspension.
Vector<DOMWindowProperty*> properties;
copyToVector(m_properties, properties);
- for (size_t i = 0; i < properties.size(); ++i)
- properties[i]->disconnectFrameForPageCache();
+ for (auto& property : properties)
+ property->disconnectFrameForDocumentSuspension();
}
void DOMWindow::reconnectDOMWindowProperties()
{
- ASSERT(m_suspendedForPageCache);
+ ASSERT(m_suspendedForDocumentSuspension);
// It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may
// unregister themselves from the DOMWindow as a result of the call to reconnectFromPageCache.
Vector<DOMWindowProperty*> properties;
copyToVector(m_properties, properties);
- for (size_t i = 0; i < properties.size(); ++i)
- properties[i]->reconnectFrameFromPageCache(m_frame);
+ for (auto& property : properties)
+ property->reconnectFrameFromDocumentSuspension(m_frame);
}
void DOMWindow::resetDOMWindowProperties()
{
m_properties.clear();
- m_screen = 0;
- m_history = 0;
- m_crypto = 0;
- m_locationbar = 0;
- m_menubar = 0;
- m_personalbar = 0;
- m_scrollbars = 0;
- m_statusbar = 0;
- m_toolbar = 0;
- m_console = 0;
- m_navigator = 0;
+ m_applicationCache = nullptr;
+ m_crypto = nullptr;
+ m_history = nullptr;
+ m_localStorage = nullptr;
+ m_location = nullptr;
+ m_locationbar = nullptr;
+ m_media = nullptr;
+ m_menubar = nullptr;
+ m_navigator = nullptr;
+ m_personalbar = nullptr;
+ m_screen = nullptr;
+ m_scrollbars = nullptr;
+ m_selection = nullptr;
+ m_sessionStorage = nullptr;
+ m_statusbar = nullptr;
+ m_toolbar = nullptr;
+
#if ENABLE(WEB_TIMING)
- m_performance = 0;
+ m_performance = nullptr;
#endif
- m_location = 0;
- m_media = 0;
- m_sessionStorage = 0;
- m_localStorage = 0;
- m_applicationCache = 0;
}
bool DOMWindow::isCurrentlyDisplayedInFrame() const
@@ -572,7 +617,66 @@ bool DOMWindow::isCurrentlyDisplayedInFrame() const
return m_frame && m_frame->document()->domWindow() == this;
}
+CustomElementRegistry& DOMWindow::ensureCustomElementRegistry()
+{
+ if (!m_customElementRegistry)
+ m_customElementRegistry = CustomElementRegistry::create(*this);
+ return *m_customElementRegistry;
+}
+
+static ExceptionOr<SelectorQuery&> selectorQueryInFrame(Frame* frame, const String& selectors)
+{
+ if (!frame)
+ return Exception { NOT_SUPPORTED_ERR };
+
+ Document* document = frame->document();
+ if (!document)
+ return Exception { NOT_SUPPORTED_ERR };
+
+ return document->selectorQueryForString(selectors);
+}
+
+ExceptionOr<Ref<NodeList>> DOMWindow::collectMatchingElementsInFlatTree(Node& scope, const String& selectors)
+{
+ auto queryOrException = selectorQueryInFrame(m_frame, selectors);
+ if (queryOrException.hasException())
+ return queryOrException.releaseException();
+
+ if (!is<ContainerNode>(scope))
+ return Ref<NodeList> { StaticElementList::create() };
+
+ SelectorQuery& query = queryOrException.releaseReturnValue();
+
+ Vector<Ref<Element>> result;
+ for (auto& node : composedTreeDescendants(downcast<ContainerNode>(scope))) {
+ if (is<Element>(node) && query.matches(downcast<Element>(node)) && !node.isInUserAgentShadowTree())
+ result.append(downcast<Element>(node));
+ }
+
+ return Ref<NodeList> { StaticElementList::create(WTFMove(result)) };
+}
+
+ExceptionOr<RefPtr<Element>> DOMWindow::matchingElementInFlatTree(Node& scope, const String& selectors)
+{
+ auto queryOrException = selectorQueryInFrame(m_frame, selectors);
+ if (queryOrException.hasException())
+ return queryOrException.releaseException();
+
+ if (!is<ContainerNode>(scope))
+ return RefPtr<Element> { nullptr };
+
+ SelectorQuery& query = queryOrException.releaseReturnValue();
+
+ for (auto& node : composedTreeDescendants(downcast<ContainerNode>(scope))) {
+ if (is<Element>(node) && query.matches(downcast<Element>(node)) && !node.isInUserAgentShadowTree())
+ return &downcast<Element>(node);
+ }
+
+ return RefPtr<Element> { nullptr };
+}
+
#if ENABLE(ORIENTATION_EVENTS)
+
int DOMWindow::orientation() const
{
if (!m_frame)
@@ -580,12 +684,13 @@ int DOMWindow::orientation() const
return m_frame->orientation();
}
+
#endif
Screen* DOMWindow::screen() const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
+ return nullptr;
if (!m_screen)
m_screen = Screen::create(m_frame);
return m_screen.get();
@@ -594,9 +699,9 @@ Screen* DOMWindow::screen() const
History* DOMWindow::history() const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
+ return nullptr;
if (!m_history)
- m_history = History::create(m_frame);
+ m_history = History::create(*m_frame);
return m_history.get();
}
@@ -604,7 +709,7 @@ Crypto* DOMWindow::crypto() const
{
// FIXME: Why is crypto not available when the window is not currently displayed in a frame?
if (!isCurrentlyDisplayedInFrame())
- return 0;
+ return nullptr;
if (!m_crypto)
m_crypto = Crypto::create(*document());
return m_crypto.get();
@@ -613,7 +718,7 @@ Crypto* DOMWindow::crypto() const
BarProp* DOMWindow::locationbar() const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
+ return nullptr;
if (!m_locationbar)
m_locationbar = BarProp::create(m_frame, BarProp::Locationbar);
return m_locationbar.get();
@@ -622,7 +727,7 @@ BarProp* DOMWindow::locationbar() const
BarProp* DOMWindow::menubar() const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
+ return nullptr;
if (!m_menubar)
m_menubar = BarProp::create(m_frame, BarProp::Menubar);
return m_menubar.get();
@@ -631,7 +736,7 @@ BarProp* DOMWindow::menubar() const
BarProp* DOMWindow::personalbar() const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
+ return nullptr;
if (!m_personalbar)
m_personalbar = BarProp::create(m_frame, BarProp::Personalbar);
return m_personalbar.get();
@@ -640,7 +745,7 @@ BarProp* DOMWindow::personalbar() const
BarProp* DOMWindow::scrollbars() const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
+ return nullptr;
if (!m_scrollbars)
m_scrollbars = BarProp::create(m_frame, BarProp::Scrollbars);
return m_scrollbars.get();
@@ -649,7 +754,7 @@ BarProp* DOMWindow::scrollbars() const
BarProp* DOMWindow::statusbar() const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
+ return nullptr;
if (!m_statusbar)
m_statusbar = BarProp::create(m_frame, BarProp::Statusbar);
return m_statusbar.get();
@@ -658,240 +763,271 @@ BarProp* DOMWindow::statusbar() const
BarProp* DOMWindow::toolbar() const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
+ return nullptr;
if (!m_toolbar)
m_toolbar = BarProp::create(m_frame, BarProp::Toolbar);
return m_toolbar.get();
}
-Console* DOMWindow::console() const
-{
- if (!isCurrentlyDisplayedInFrame())
- return 0;
- if (!m_console)
- m_console = Console::create(m_frame);
- return m_console.get();
-}
-
-PageConsole* DOMWindow::pageConsole() const
+PageConsoleClient* DOMWindow::console() const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
- return m_frame->page() ? &m_frame->page()->console() : 0;
+ return nullptr;
+ return m_frame->page() ? &m_frame->page()->console() : nullptr;
}
DOMApplicationCache* DOMWindow::applicationCache() const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
+ return nullptr;
if (!m_applicationCache)
- m_applicationCache = DOMApplicationCache::create(m_frame);
+ m_applicationCache = DOMApplicationCache::create(*m_frame);
return m_applicationCache.get();
}
Navigator* DOMWindow::navigator() const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
+ return nullptr;
if (!m_navigator)
- m_navigator = Navigator::create(m_frame);
+ m_navigator = Navigator::create(*m_frame);
return m_navigator.get();
}
#if ENABLE(WEB_TIMING)
+
Performance* DOMWindow::performance() const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
- if (!m_performance)
- m_performance = Performance::create(m_frame);
+ return nullptr;
+ if (!m_performance) {
+ MonotonicTime timeOrigin = document()->loader() ? document()->loader()->timing().referenceMonotonicTime() : MonotonicTime::now();
+ m_performance = Performance::create(*document(), timeOrigin);
+ }
return m_performance.get();
}
+
#endif
+double DOMWindow::nowTimestamp() const
+{
+#if ENABLE(WEB_TIMING)
+ return performance() ? performance()->now() / 1000 : 0;
+#else
+ return document() ? document()->monotonicTimestamp() : 0;
+#endif
+}
+
Location* DOMWindow::location() const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
+ return nullptr;
if (!m_location)
m_location = Location::create(m_frame);
return m_location.get();
}
-Storage* DOMWindow::sessionStorage(ExceptionCode& ec) const
+#if ENABLE(USER_MESSAGE_HANDLERS)
+
+bool DOMWindow::shouldHaveWebKitNamespaceForWorld(DOMWrapperWorld& world)
+{
+ if (!m_frame)
+ return false;
+
+ auto* page = m_frame->page();
+ if (!page)
+ return false;
+
+ bool hasUserMessageHandler = false;
+ page->userContentProvider().forEachUserMessageHandler([&](const UserMessageHandlerDescriptor& descriptor) {
+ if (&descriptor.world() == &world) {
+ hasUserMessageHandler = true;
+ return;
+ }
+ });
+
+ return hasUserMessageHandler;
+}
+
+WebKitNamespace* DOMWindow::webkitNamespace() const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
+ return nullptr;
+ auto* page = m_frame->page();
+ if (!page)
+ return nullptr;
+ if (!m_webkitNamespace)
+ m_webkitNamespace = WebKitNamespace::create(*m_frame, page->userContentProvider());
+ return m_webkitNamespace.get();
+}
- Document* document = this->document();
+#endif
+
+ExceptionOr<Storage*> DOMWindow::sessionStorage() const
+{
+ if (!isCurrentlyDisplayedInFrame())
+ return nullptr;
+
+ auto* document = this->document();
if (!document)
- return 0;
+ return nullptr;
- if (!document->securityOrigin()->canAccessSessionStorage(document->topOrigin())) {
- ec = SECURITY_ERR;
- return 0;
- }
+ if (!document->securityOrigin().canAccessSessionStorage(document->topOrigin()))
+ return Exception { SECURITY_ERR };
if (m_sessionStorage) {
- if (!m_sessionStorage->area().canAccessStorage(m_frame)) {
- ec = SECURITY_ERR;
- return 0;
- }
+ if (!m_sessionStorage->area().canAccessStorage(m_frame))
+ return Exception { SECURITY_ERR };
return m_sessionStorage.get();
}
- Page* page = document->page();
+ auto* page = document->page();
if (!page)
- return 0;
+ return nullptr;
- RefPtr<StorageArea> storageArea = page->sessionStorage()->storageArea(document->securityOrigin());
- if (!storageArea->canAccessStorage(m_frame)) {
- ec = SECURITY_ERR;
- return 0;
- }
+ auto storageArea = page->sessionStorage()->storageArea(SecurityOriginData::fromSecurityOrigin(document->securityOrigin()));
+ if (!storageArea->canAccessStorage(m_frame))
+ return Exception { SECURITY_ERR };
- m_sessionStorage = Storage::create(m_frame, storageArea.release());
+ m_sessionStorage = Storage::create(m_frame, WTFMove(storageArea));
return m_sessionStorage.get();
}
-Storage* DOMWindow::localStorage(ExceptionCode& ec) const
+ExceptionOr<Storage*> DOMWindow::localStorage() const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
+ return nullptr;
- Document* document = this->document();
+ auto* document = this->document();
if (!document)
- return 0;
-
- if (!document->securityOrigin()->canAccessLocalStorage(0)) {
- ec = SECURITY_ERR;
- return 0;
- }
-
- if (m_localStorage) {
- if (!m_localStorage->area().canAccessStorage(m_frame)) {
- ec = SECURITY_ERR;
- return 0;
+ return nullptr;
+
+ if (!document->securityOrigin().canAccessLocalStorage(nullptr))
+ return Exception { SECURITY_ERR };
+
+ auto* page = document->page();
+ // FIXME: We should consider supporting access/modification to local storage
+ // after calling window.close(). See <https://bugs.webkit.org/show_bug.cgi?id=135330>.
+ if (!page || !page->isClosing()) {
+ if (m_localStorage) {
+ if (!m_localStorage->area().canAccessStorage(m_frame))
+ return Exception { SECURITY_ERR };
+ return m_localStorage.get();
}
- return m_localStorage.get();
}
- Page* page = document->page();
if (!page)
- return 0;
+ return nullptr;
+
+ if (page->isClosing())
+ return nullptr;
if (!page->settings().localStorageEnabled())
- return 0;
+ return nullptr;
- RefPtr<StorageArea> storageArea;
- if (!document->securityOrigin()->canAccessLocalStorage(document->topOrigin()))
- storageArea = page->group().transientLocalStorage(document->topOrigin())->storageArea(document->securityOrigin());
- else
- storageArea = page->group().localStorage()->storageArea(document->securityOrigin());
+ auto storageArea = page->storageNamespaceProvider().localStorageArea(*document);
- if (!storageArea->canAccessStorage(m_frame)) {
- ec = SECURITY_ERR;
- return 0;
- }
+ if (!storageArea->canAccessStorage(m_frame))
+ return Exception { SECURITY_ERR };
- m_localStorage = Storage::create(m_frame, storageArea.release());
+ m_localStorage = Storage::create(m_frame, WTFMove(storageArea));
return m_localStorage.get();
}
-void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort* port, const String& targetOrigin, DOMWindow& source, ExceptionCode& ec)
-{
- MessagePortArray ports;
- if (port)
- ports.append(port);
- postMessage(message, &ports, targetOrigin, source, ec);
-}
-
-void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, const String& targetOrigin, DOMWindow& source, ExceptionCode& ec)
+ExceptionOr<void> DOMWindow::postMessage(JSC::ExecState& state, DOMWindow& callerWindow, JSC::JSValue messageValue, const String& targetOrigin, Vector<JSC::Strong<JSC::JSObject>>&& transfer)
{
if (!isCurrentlyDisplayedInFrame())
- return;
+ return { };
- Document* sourceDocument = source.document();
+ Document* sourceDocument = callerWindow.document();
// Compute the target origin. We need to do this synchronously in order
// to generate the SYNTAX_ERR exception correctly.
RefPtr<SecurityOrigin> target;
if (targetOrigin == "/") {
if (!sourceDocument)
- return;
- target = sourceDocument->securityOrigin();
+ return { };
+ target = &sourceDocument->securityOrigin();
} else if (targetOrigin != "*") {
target = SecurityOrigin::createFromString(targetOrigin);
// It doesn't make sense target a postMessage at a unique origin
// because there's no way to represent a unique origin in a string.
- if (target->isUnique()) {
- ec = SYNTAX_ERR;
- return;
- }
+ if (target->isUnique())
+ return Exception { SYNTAX_ERR };
}
- OwnPtr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(ports, ec);
- if (ec)
- return;
+ Vector<RefPtr<MessagePort>> ports;
+ auto message = SerializedScriptValue::create(state, messageValue, WTFMove(transfer), ports);
+ if (message.hasException())
+ return message.releaseException();
+
+ auto channels = MessagePort::disentanglePorts(WTFMove(ports));
+ if (channels.hasException())
+ return channels.releaseException();
// Capture the source of the message. We need to do this synchronously
// in order to capture the source of the message correctly.
if (!sourceDocument)
- return;
- String sourceOrigin = sourceDocument->securityOrigin()->toString();
+ return { };
+ auto sourceOrigin = sourceDocument->securityOrigin().toString();
// Capture stack trace only when inspector front-end is loaded as it may be time consuming.
RefPtr<ScriptCallStack> stackTrace;
if (InspectorInstrumentation::consoleAgentEnabled(sourceDocument))
- stackTrace = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true);
+ stackTrace = createScriptCallStack(JSMainThreadExecState::currentState(), ScriptCallStack::maxCallStackSizeToCapture);
// Schedule the message.
- PostMessageTimer* timer = new PostMessageTimer(this, message, sourceOrigin, &source, channels.release(), target.get(), stackTrace.release());
+ auto* timer = new PostMessageTimer(*this, message.releaseReturnValue(), sourceOrigin, callerWindow, channels.releaseReturnValue(), WTFMove(target), WTFMove(stackTrace));
timer->startOneShot(0);
+
+ return { };
}
-void DOMWindow::postMessageTimerFired(PassOwnPtr<PostMessageTimer> t)
+void DOMWindow::postMessageTimerFired(PostMessageTimer& timer)
{
- OwnPtr<PostMessageTimer> timer(t);
-
if (!document() || !isCurrentlyDisplayedInFrame())
return;
- dispatchMessageEventWithOriginCheck(timer->targetOrigin(), timer->event(document()), timer->stackTrace());
-}
-
-void DOMWindow::dispatchMessageEventWithOriginCheck(SecurityOrigin* intendedTargetOrigin, PassRefPtr<Event> event, PassRefPtr<ScriptCallStack> stackTrace)
-{
- if (intendedTargetOrigin) {
+ if (auto* intendedTargetOrigin = timer.targetOrigin()) {
// Check target origin now since the target document may have changed since the timer was scheduled.
if (!intendedTargetOrigin->isSameSchemeHostPort(document()->securityOrigin())) {
- String message = "Unable to post message to " + intendedTargetOrigin->toString() +
- ". Recipient has origin " + document()->securityOrigin()->toString() + ".\n";
- pageConsole()->addMessage(SecurityMessageSource, ErrorMessageLevel, message, stackTrace);
+ if (auto* pageConsole = console()) {
+ String message = makeString("Unable to post message to ", intendedTargetOrigin->toString(), ". Recipient has origin ", document()->securityOrigin().toString(), ".\n");
+ if (timer.stackTrace())
+ pageConsole->addMessage(MessageSource::Security, MessageLevel::Error, message, *timer.stackTrace());
+ else
+ pageConsole->addMessage(MessageSource::Security, MessageLevel::Error, message);
+ }
return;
}
}
- dispatchEvent(event);
+ dispatchEvent(timer.event(*document()));
}
DOMSelection* DOMWindow::getSelection()
{
- if (!isCurrentlyDisplayedInFrame() || !m_frame)
- return 0;
-
- return m_frame->document()->getSelection();
+ if (!isCurrentlyDisplayedInFrame())
+ return nullptr;
+ if (!m_selection)
+ m_selection = DOMSelection::create(*m_frame);
+ return m_selection.get();
}
Element* DOMWindow::frameElement() const
{
if (!m_frame)
- return 0;
+ return nullptr;
return m_frame->ownerElement();
}
-void DOMWindow::focus(ScriptExecutionContext* context)
+void DOMWindow::focus(DOMWindow& callerWindow)
+{
+ focus(opener() && opener() != this && &callerWindow == opener());
+}
+
+void DOMWindow::focus(bool allowFocus)
{
if (!m_frame)
return;
@@ -900,13 +1036,7 @@ void DOMWindow::focus(ScriptExecutionContext* context)
if (!page)
return;
- bool allowFocus = WindowFocusAllowedIndicator::windowFocusAllowed() || !m_frame->settings().windowFocusRestricted();
- if (context) {
- ASSERT(isMainThread());
- Document* activeDocument = toDocument(context);
- if (opener() && opener() != this && activeDocument->domWindow() == opener())
- allowFocus = true;
- }
+ allowFocus = allowFocus || WindowFocusAllowedIndicator::windowFocusAllowed() || !m_frame->settings().windowFocusRestricted();
// If we're a top level window, bring the window to the front.
if (m_frame->isMainFrame() && allowFocus)
@@ -918,9 +1048,11 @@ void DOMWindow::focus(ScriptExecutionContext* context)
// Clear the current frame's focused node if a new frame is about to be focused.
Frame* focusedFrame = page->focusController().focusedFrame();
if (focusedFrame && focusedFrame != m_frame)
- focusedFrame->document()->setFocusedElement(0);
+ focusedFrame->document()->setFocusedElement(nullptr);
- m_frame->eventHandler().focusDocumentView();
+ // setFocusedElement may clear m_frame, so recheck before using it.
+ if (m_frame)
+ m_frame->eventHandler().focusDocumentView();
}
void DOMWindow::blur()
@@ -941,7 +1073,14 @@ void DOMWindow::blur()
page->chrome().unfocus();
}
-void DOMWindow::close(ScriptExecutionContext* context)
+void DOMWindow::close(Document& document)
+{
+ if (!document.canNavigate(m_frame))
+ return;
+ close();
+}
+
+void DOMWindow::close()
{
if (!m_frame)
return;
@@ -953,26 +1092,17 @@ void DOMWindow::close(ScriptExecutionContext* context)
if (!m_frame->isMainFrame())
return;
- if (context) {
- ASSERT(isMainThread());
- Document* activeDocument = toDocument(context);
- if (!activeDocument)
- return;
-
- if (!activeDocument->canNavigate(m_frame))
- return;
- }
-
bool allowScriptsToCloseWindows = m_frame->settings().allowScriptsToCloseWindows();
if (!(page->openedByDOM() || page->backForward().count() <= 1 || allowScriptsToCloseWindows)) {
- pageConsole()->addMessage(JSMessageSource, WarningMessageLevel, ASCIILiteral("Can't close the window since it was not opened by JavaScript"));
+ console()->addMessage(MessageSource::JS, MessageLevel::Warning, ASCIILiteral("Can't close the window since it was not opened by JavaScript"));
return;
}
if (!m_frame->loader().shouldClose())
return;
+ page->setIsClosing();
page->chrome().closeWindowSoon();
}
@@ -981,13 +1111,12 @@ void DOMWindow::print()
if (!m_frame)
return;
- Page* page = m_frame->page();
+ auto* page = m_frame->page();
if (!page)
return;
- // Pages are not allowed to bring up a modal print dialog during BeforeUnload dispatch.
- if (page->isAnyFrameHandlingBeforeUnloadEvent()) {
- printErrorMessage("Use of window.print is not allowed during beforeunload event dispatch.");
+ if (!page->arePromptsAllowed()) {
+ printErrorMessage("Use of window.print is not allowed while unloading a page.");
return;
}
@@ -996,7 +1125,7 @@ void DOMWindow::print()
return;
}
m_shouldPrintWhenFinishedLoading = false;
- page->chrome().print(m_frame);
+ page->chrome().print(*m_frame);
}
void DOMWindow::stop()
@@ -1014,19 +1143,21 @@ void DOMWindow::alert(const String& message)
if (!m_frame)
return;
- // Pages are not allowed to cause modal alerts during BeforeUnload dispatch.
- if (page() && page()->isAnyFrameHandlingBeforeUnloadEvent()) {
- printErrorMessage("Use of window.alert is not allowed during beforeunload event dispatch.");
+ auto* page = m_frame->page();
+ if (!page)
+ return;
+
+ if (!page->arePromptsAllowed()) {
+ printErrorMessage("Use of window.alert is not allowed while unloading a page.");
return;
}
m_frame->document()->updateStyleIfNeeded();
+#if ENABLE(POINTER_LOCK)
+ page->pointerLockController().requestPointerUnlock();
+#endif
- Page* page = m_frame->page();
- if (!page)
- return;
-
- page->chrome().runJavaScriptAlert(m_frame, message);
+ page->chrome().runJavaScriptAlert(*m_frame, message);
}
bool DOMWindow::confirm(const String& message)
@@ -1034,19 +1165,21 @@ bool DOMWindow::confirm(const String& message)
if (!m_frame)
return false;
- // Pages are not allowed to cause modal alerts during BeforeUnload dispatch.
- if (page() && page()->isAnyFrameHandlingBeforeUnloadEvent()) {
- printErrorMessage("Use of window.confirm is not allowed during beforeunload event dispatch.");
+ auto* page = m_frame->page();
+ if (!page)
+ return false;
+
+ if (!page->arePromptsAllowed()) {
+ printErrorMessage("Use of window.confirm is not allowed while unloading a page.");
return false;
}
m_frame->document()->updateStyleIfNeeded();
+#if ENABLE(POINTER_LOCK)
+ page->pointerLockController().requestPointerUnlock();
+#endif
- Page* page = m_frame->page();
- if (!page)
- return false;
-
- return page->chrome().runJavaScriptConfirm(m_frame, message);
+ return page->chrome().runJavaScriptConfirm(*m_frame, message);
}
String DOMWindow::prompt(const String& message, const String& defaultValue)
@@ -1054,57 +1187,27 @@ String DOMWindow::prompt(const String& message, const String& defaultValue)
if (!m_frame)
return String();
- // Pages are not allowed to cause modal alerts during BeforeUnload dispatch.
- if (page() && page()->isAnyFrameHandlingBeforeUnloadEvent()) {
- printErrorMessage("Use of window.prompt is not allowed during beforeunload event dispatch.");
+ auto* page = m_frame->page();
+ if (!page)
+ return String();
+
+ if (!page->arePromptsAllowed()) {
+ printErrorMessage("Use of window.prompt is not allowed while unloading a page.");
return String();
}
m_frame->document()->updateStyleIfNeeded();
-
- Page* page = m_frame->page();
- if (!page)
- return String();
+#if ENABLE(POINTER_LOCK)
+ page->pointerLockController().requestPointerUnlock();
+#endif
String returnValue;
- if (page->chrome().runJavaScriptPrompt(m_frame, message, defaultValue, returnValue))
+ if (page->chrome().runJavaScriptPrompt(*m_frame, message, defaultValue, returnValue))
return returnValue;
return String();
}
-String DOMWindow::btoa(const String& stringToEncode, ExceptionCode& ec)
-{
- if (stringToEncode.isNull())
- return String();
-
- if (!stringToEncode.containsOnlyLatin1()) {
- ec = INVALID_CHARACTER_ERR;
- return String();
- }
-
- return base64Encode(stringToEncode.latin1());
-}
-
-String DOMWindow::atob(const String& encodedString, ExceptionCode& ec)
-{
- if (encodedString.isNull())
- return String();
-
- if (!encodedString.containsOnlyLatin1()) {
- ec = INVALID_CHARACTER_ERR;
- return String();
- }
-
- Vector<char> out;
- if (!base64Decode(encodedString, out, Base64FailOnInvalidCharacterOrExcessPadding)) {
- ec = INVALID_CHARACTER_ERR;
- return String();
- }
-
- return String(out.data(), out.size());
-}
-
bool DOMWindow::find(const String& string, bool caseSensitive, bool backwards, bool wrap, bool /*wholeWord*/, bool /*searchInFrames*/, bool /*showDialog*/) const
{
if (!isCurrentlyDisplayedInFrame())
@@ -1112,7 +1215,7 @@ bool DOMWindow::find(const String& string, bool caseSensitive, bool backwards, b
// FIXME (13016): Support wholeWord, searchInFrames and showDialog.
FindOptions options = (backwards ? Backwards : 0) | (caseSensitive ? 0 : CaseInsensitive) | (wrap ? WrapAround : 0);
- return m_frame->editor().findString(string, options);
+ return m_frame->editor().findString(string, options | DoNotTraverseFlatTree);
}
bool DOMWindow::offscreenBuffering() const
@@ -1122,6 +1225,9 @@ bool DOMWindow::offscreenBuffering() const
int DOMWindow::outerHeight() const
{
+#if PLATFORM(IOS)
+ return 0;
+#else
if (!m_frame)
return 0;
@@ -1130,10 +1236,14 @@ int DOMWindow::outerHeight() const
return 0;
return static_cast<int>(page->chrome().windowRect().height());
+#endif
}
int DOMWindow::outerWidth() const
{
+#if PLATFORM(IOS)
+ return 0;
+#else
if (!m_frame)
return 0;
@@ -1142,6 +1252,7 @@ int DOMWindow::outerWidth() const
return 0;
return static_cast<int>(page->chrome().windowRect().width());
+#endif
}
int DOMWindow::innerHeight() const
@@ -1153,7 +1264,7 @@ int DOMWindow::innerHeight() const
if (!view)
return 0;
- return view->mapFromLayoutToCSSUnits(static_cast<int>(view->visibleContentRectIncludingScrollbars().height()));
+ return view->mapFromLayoutToCSSUnits(static_cast<int>(view->unobscuredContentRectIncludingScrollbars().height()));
}
int DOMWindow::innerWidth() const
@@ -1165,7 +1276,7 @@ int DOMWindow::innerWidth() const
if (!view)
return 0;
- return view->mapFromLayoutToCSSUnits(static_cast<int>(view->visibleContentRectIncludingScrollbars().width()));
+ return view->mapFromLayoutToCSSUnits(static_cast<int>(view->unobscuredContentRectIncludingScrollbars().width()));
}
int DOMWindow::screenX() const
@@ -1201,16 +1312,13 @@ int DOMWindow::scrollX() const
if (!view)
return 0;
- if (!view->scrollX())
+ int scrollX = view->contentsScrollPosition().x();
+ if (!scrollX)
return 0;
m_frame->document()->updateLayoutIgnorePendingStylesheets();
-#if PLATFORM(IOS)
- return static_cast<int>(view->actualScrollX() / (m_frame->pageZoomFactor() * m_frame->frameScaleFactor()));
-#else
- return view->mapFromLayoutToCSSUnits(view->scrollX());
-#endif
+ return view->mapFromLayoutToCSSUnits(view->contentsScrollPosition().x());
}
int DOMWindow::scrollY() const
@@ -1222,16 +1330,13 @@ int DOMWindow::scrollY() const
if (!view)
return 0;
- if (!view->scrollY())
+ int scrollY = view->contentsScrollPosition().y();
+ if (!scrollY)
return 0;
m_frame->document()->updateLayoutIgnorePendingStylesheets();
-#if PLATFORM(IOS)
- return static_cast<int>(view->actualScrollY() / (m_frame->pageZoomFactor() * m_frame->frameScaleFactor()));
-#else
- return view->mapFromLayoutToCSSUnits(view->scrollY());
-#endif
+ return view->mapFromLayoutToCSSUnits(view->contentsScrollPosition().y());
}
bool DOMWindow::closed() const
@@ -1275,7 +1380,7 @@ void DOMWindow::setStatus(const String& string)
return;
ASSERT(m_frame->document()); // Client calls shouldn't be made when the frame is in inconsistent state.
- page->chrome().setStatusbarText(m_frame, m_status);
+ page->chrome().setStatusbarText(*m_frame, m_status);
}
void DOMWindow::setDefaultStatus(const String& string)
@@ -1290,13 +1395,13 @@ void DOMWindow::setDefaultStatus(const String& string)
return;
ASSERT(m_frame->document()); // Client calls shouldn't be made when the frame is in inconsistent state.
- page->chrome().setStatusbarText(m_frame, m_defaultStatus);
+ page->chrome().setStatusbarText(*m_frame, m_defaultStatus);
}
DOMWindow* DOMWindow::self() const
{
if (!m_frame)
- return 0;
+ return nullptr;
return m_frame->document()->domWindow();
}
@@ -1304,11 +1409,11 @@ DOMWindow* DOMWindow::self() const
DOMWindow* DOMWindow::opener() const
{
if (!m_frame)
- return 0;
+ return nullptr;
Frame* opener = m_frame->loader().opener();
if (!opener)
- return 0;
+ return nullptr;
return opener->document()->domWindow();
}
@@ -1316,7 +1421,7 @@ DOMWindow* DOMWindow::opener() const
DOMWindow* DOMWindow::parent() const
{
if (!m_frame)
- return 0;
+ return nullptr;
Frame* parent = m_frame->tree().parent();
if (parent)
@@ -1328,47 +1433,45 @@ DOMWindow* DOMWindow::parent() const
DOMWindow* DOMWindow::top() const
{
if (!m_frame)
- return 0;
+ return nullptr;
Page* page = m_frame->page();
if (!page)
- return 0;
+ return nullptr;
return m_frame->tree().top().document()->domWindow();
}
Document* DOMWindow::document() const
{
- ScriptExecutionContext* context = ContextDestructionObserver::scriptExecutionContext();
- return toDocument(context);
+ return downcast<Document>(ContextDestructionObserver::scriptExecutionContext());
}
-PassRefPtr<StyleMedia> DOMWindow::styleMedia() const
+RefPtr<StyleMedia> DOMWindow::styleMedia() const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
+ return nullptr;
if (!m_media)
m_media = StyleMedia::create(m_frame);
- return m_media.get();
+ return m_media;
}
-PassRefPtr<CSSStyleDeclaration> DOMWindow::getComputedStyle(Element* elt, const String& pseudoElt) const
+Ref<CSSStyleDeclaration> DOMWindow::getComputedStyle(Element& element, const String& pseudoElt) const
{
- if (!elt)
- return 0;
-
- return CSSComputedStyleDeclaration::create(elt, false, pseudoElt);
+ return CSSComputedStyleDeclaration::create(element, false, pseudoElt);
}
-PassRefPtr<CSSRuleList> DOMWindow::getMatchedCSSRules(Element* element, const String& pseudoElement, bool authorOnly) const
+RefPtr<CSSRuleList> DOMWindow::getMatchedCSSRules(Element* element, const String& pseudoElement, bool authorOnly) const
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
+ return nullptr;
unsigned colonStart = pseudoElement[0] == ':' ? (pseudoElement[1] == ':' ? 2 : 1) : 0;
- CSSSelector::PseudoType pseudoType = CSSSelector::parsePseudoType(AtomicString(pseudoElement.substring(colonStart)));
- if (pseudoType == CSSSelector::PseudoUnknown && !pseudoElement.isEmpty())
- return 0;
+ CSSSelector::PseudoElementType pseudoType = CSSSelector::parsePseudoElementType(pseudoElement.substringSharingImpl(colonStart));
+ if (pseudoType == CSSSelector::PseudoElementUnknown && !pseudoElement.isEmpty())
+ return nullptr;
+
+ m_frame->document()->styleScope().flushPendingUpdate();
unsigned rulesToInclude = StyleResolver::AuthorCSSRules;
if (!authorOnly)
@@ -1378,24 +1481,24 @@ PassRefPtr<CSSRuleList> DOMWindow::getMatchedCSSRules(Element* element, const St
PseudoId pseudoId = CSSSelector::pseudoId(pseudoType);
- Vector<RefPtr<StyleRuleBase>> matchedRules = m_frame->document()->ensureStyleResolver().pseudoStyleRulesForElement(element, pseudoId, rulesToInclude);
+ auto matchedRules = m_frame->document()->styleScope().resolver().pseudoStyleRulesForElement(element, pseudoId, rulesToInclude);
if (matchedRules.isEmpty())
- return 0;
+ return nullptr;
RefPtr<StaticCSSRuleList> ruleList = StaticCSSRuleList::create();
- for (unsigned i = 0; i < matchedRules.size(); ++i)
- ruleList->rules().append(matchedRules[i]->createCSSOMWrapper());
+ for (auto& rule : matchedRules)
+ ruleList->rules().append(rule->createCSSOMWrapper());
- return ruleList.release();
+ return ruleList;
}
-PassRefPtr<WebKitPoint> DOMWindow::webkitConvertPointFromNodeToPage(Node* node, const WebKitPoint* p) const
+RefPtr<WebKitPoint> DOMWindow::webkitConvertPointFromNodeToPage(Node* node, const WebKitPoint* p) const
{
if (!node || !p)
- return 0;
+ return nullptr;
if (!document())
- return 0;
+ return nullptr;
document()->updateLayoutIgnorePendingStylesheets();
@@ -1404,13 +1507,13 @@ PassRefPtr<WebKitPoint> DOMWindow::webkitConvertPointFromNodeToPage(Node* node,
return WebKitPoint::create(pagePoint.x(), pagePoint.y());
}
-PassRefPtr<WebKitPoint> DOMWindow::webkitConvertPointFromPageToNode(Node* node, const WebKitPoint* p) const
+RefPtr<WebKitPoint> DOMWindow::webkitConvertPointFromPageToNode(Node* node, const WebKitPoint* p) const
{
if (!node || !p)
- return 0;
+ return nullptr;
if (!document())
- return 0;
+ return nullptr;
document()->updateLayoutIgnorePendingStylesheets();
@@ -1431,7 +1534,12 @@ double DOMWindow::devicePixelRatio() const
return page->deviceScaleFactor();
}
-void DOMWindow::scrollBy(int x, int y) const
+void DOMWindow::scrollBy(const ScrollToOptions& options) const
+{
+ return scrollBy(options.left.value_or(0), options.top.value_or(0));
+}
+
+void DOMWindow::scrollBy(double x, double y) const
{
if (!isCurrentlyDisplayedInFrame())
return;
@@ -1442,34 +1550,48 @@ void DOMWindow::scrollBy(int x, int y) const
if (!view)
return;
+ // Normalize non-finite values (https://drafts.csswg.org/cssom-view/#normalize-non-finite-values).
+ x = std::isfinite(x) ? x : 0;
+ y = std::isfinite(y) ? y : 0;
+
IntSize scaledOffset(view->mapFromCSSToLayoutUnits(x), view->mapFromCSSToLayoutUnits(y));
-#if PLATFORM(IOS)
- view->setActualScrollPosition(view->actualScrollPosition() + scaledOffset);
-#else
- view->scrollBy(scaledOffset);
-#endif
+ view->setContentsScrollPosition(view->contentsScrollPosition() + scaledOffset);
}
-void DOMWindow::scrollTo(int x, int y) const
+void DOMWindow::scrollTo(const ScrollToOptions& options) const
{
if (!isCurrentlyDisplayedInFrame())
return;
- document()->updateLayoutIgnorePendingStylesheets();
+ RefPtr<FrameView> view = m_frame->view();
+ if (!view)
+ return;
+
+ double x = options.left ? options.left.value() : view->contentsScrollPosition().x();
+ double y = options.top ? options.top.value() : view->contentsScrollPosition().y();
+ return scrollTo(x, y);
+}
+
+void DOMWindow::scrollTo(double x, double y) const
+{
+ if (!isCurrentlyDisplayedInFrame())
+ return;
RefPtr<FrameView> view = m_frame->view();
if (!view)
return;
+ // Normalize non-finite values (https://drafts.csswg.org/cssom-view/#normalize-non-finite-values).
+ x = std::isfinite(x) ? x : 0;
+ y = std::isfinite(y) ? y : 0;
+
+ if (!x && !y && view->contentsScrollPosition() == IntPoint(0, 0))
+ return;
+
+ document()->updateLayoutIgnorePendingStylesheets();
-#if PLATFORM(IOS)
- int zoomedX = static_cast<int>(x * m_frame->pageZoomFactor() * m_frame->frameScaleFactor());
- int zoomedY = static_cast<int>(y * m_frame->pageZoomFactor() * m_frame->frameScaleFactor());
- view->setActualScrollPosition(IntPoint(zoomedX, zoomedY));
-#else
IntPoint layoutPos(view->mapFromCSSToLayoutUnits(x), view->mapFromCSSToLayoutUnits(y));
- view->setScrollPosition(layoutPos);
-#endif
+ view->setContentsScrollPosition(layoutPos);
}
bool DOMWindow::allowedToChangeWindowGeometry() const
@@ -1495,8 +1617,7 @@ void DOMWindow::moveBy(float x, float y) const
FloatRect fr = page->chrome().windowRect();
FloatRect update = fr;
update.move(x, y);
- // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
- page->chrome().setWindowRect(adjustWindowRect(page, update));
+ page->chrome().setWindowRect(adjustWindowRect(*page, update));
}
void DOMWindow::moveTo(float x, float y) const
@@ -1510,8 +1631,7 @@ void DOMWindow::moveTo(float x, float y) const
fr.setLocation(sr.location());
FloatRect update = fr;
update.move(x, y);
- // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
- page->chrome().setWindowRect(adjustWindowRect(page, update));
+ page->chrome().setWindowRect(adjustWindowRect(*page, update));
}
void DOMWindow::resizeBy(float x, float y) const
@@ -1523,7 +1643,7 @@ void DOMWindow::resizeBy(float x, float y) const
FloatRect fr = page->chrome().windowRect();
FloatSize dest = fr.size() + FloatSize(x, y);
FloatRect update(fr.location(), dest);
- page->chrome().setWindowRect(adjustWindowRect(page, update));
+ page->chrome().setWindowRect(adjustWindowRect(*page, update));
}
void DOMWindow::resizeTo(float width, float height) const
@@ -1535,17 +1655,15 @@ void DOMWindow::resizeTo(float width, float height) const
FloatRect fr = page->chrome().windowRect();
FloatSize dest = FloatSize(width, height);
FloatRect update(fr.location(), dest);
- page->chrome().setWindowRect(adjustWindowRect(page, update));
+ page->chrome().setWindowRect(adjustWindowRect(*page, update));
}
-int DOMWindow::setTimeout(PassOwnPtr<ScheduledAction> action, int timeout, ExceptionCode& ec)
+ExceptionOr<int> DOMWindow::setTimeout(std::unique_ptr<ScheduledAction> action, int timeout)
{
- ScriptExecutionContext* context = scriptExecutionContext();
- if (!context) {
- ec = INVALID_ACCESS_ERR;
- return -1;
- }
- return DOMTimer::install(context, action, timeout, true);
+ auto* context = scriptExecutionContext();
+ if (!context)
+ return Exception { INVALID_ACCESS_ERR };
+ return DOMTimer::install(*context, WTFMove(action), std::chrono::milliseconds(timeout), true);
}
void DOMWindow::clearTimeout(int timeoutId)
@@ -1560,7 +1678,7 @@ void DOMWindow::clearTimeout(int timeoutId)
if (!WebThreadCountOfObservedContentModifiers()) {
if (Page* page = m_frame->page())
- page->chrome().client().observedContentChange(m_frame);
+ page->chrome().client().observedContentChange(*m_frame);
}
}
}
@@ -1569,17 +1687,15 @@ void DOMWindow::clearTimeout(int timeoutId)
ScriptExecutionContext* context = scriptExecutionContext();
if (!context)
return;
- DOMTimer::removeById(context, timeoutId);
+ DOMTimer::removeById(*context, timeoutId);
}
-int DOMWindow::setInterval(PassOwnPtr<ScheduledAction> action, int timeout, ExceptionCode& ec)
+ExceptionOr<int> DOMWindow::setInterval(std::unique_ptr<ScheduledAction> action, int timeout)
{
- ScriptExecutionContext* context = scriptExecutionContext();
- if (!context) {
- ec = INVALID_ACCESS_ERR;
- return -1;
- }
- return DOMTimer::install(context, action, timeout, false);
+ auto* context = scriptExecutionContext();
+ if (!context)
+ return Exception { INVALID_ACCESS_ERR };
+ return DOMTimer::install(*context, WTFMove(action), std::chrono::milliseconds(timeout), false);
}
void DOMWindow::clearInterval(int timeoutId)
@@ -1587,65 +1703,74 @@ void DOMWindow::clearInterval(int timeoutId)
ScriptExecutionContext* context = scriptExecutionContext();
if (!context)
return;
- DOMTimer::removeById(context, timeoutId);
+ DOMTimer::removeById(*context, timeoutId);
}
-#if ENABLE(REQUEST_ANIMATION_FRAME)
-int DOMWindow::requestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback> callback)
+int DOMWindow::requestAnimationFrame(Ref<RequestAnimationFrameCallback>&& callback)
{
callback->m_useLegacyTimeBase = false;
- if (Document* d = document())
- return d->requestAnimationFrame(callback);
- return 0;
+ auto* document = this->document();
+ if (!document)
+ return 0;
+ return document->requestAnimationFrame(WTFMove(callback));
}
-int DOMWindow::webkitRequestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback> callback)
+int DOMWindow::webkitRequestAnimationFrame(Ref<RequestAnimationFrameCallback>&& callback)
{
callback->m_useLegacyTimeBase = true;
- if (Document* d = document())
- return d->requestAnimationFrame(callback);
- return 0;
+ auto* document = this->document();
+ if (!document)
+ return 0;
+ return document->requestAnimationFrame(WTFMove(callback));
}
void DOMWindow::cancelAnimationFrame(int id)
{
- if (Document* d = document())
- d->cancelAnimationFrame(id);
-}
-#endif
-
-#if ENABLE(CSS3_CONDITIONAL_RULES)
-DOMWindowCSS* DOMWindow::css()
-{
- if (!m_css)
- m_css = DOMWindowCSS::create();
- return m_css.get();
+ auto* document = this->document();
+ if (!document)
+ return;
+ document->cancelAnimationFrame(id);
}
-#endif
-static void didAddStorageEventListener(DOMWindow* window)
+static void didAddStorageEventListener(DOMWindow& window)
{
// Creating these WebCore::Storage objects informs the system that we'd like to receive
// notifications about storage events that might be triggered in other processes. Rather
// than subscribe to these notifications explicitly, we subscribe to them implicitly to
// simplify the work done by the system.
- window->localStorage(IGNORE_EXCEPTION);
- window->sessionStorage(IGNORE_EXCEPTION);
+ window.localStorage();
+ window.sessionStorage();
}
-bool DOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
+bool DOMWindow::isSameSecurityOriginAsMainFrame() const
{
- if (!EventTarget::addEventListener(eventType, listener, useCapture))
+ if (!m_frame || !m_frame->page() || !document())
+ return false;
+
+ if (m_frame->isMainFrame())
+ return true;
+
+ Document* mainFrameDocument = m_frame->mainFrame().document();
+
+ if (mainFrameDocument && document()->securityOrigin().canAccess(mainFrameDocument->securityOrigin()))
+ return true;
+
+ return false;
+}
+
+bool DOMWindow::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
+{
+ if (!EventTarget::addEventListener(eventType, WTFMove(listener), options))
return false;
if (Document* document = this->document()) {
document->addListenerTypeIfNeeded(eventType);
- if (eventType == eventNames().wheelEvent || eventType == eventNames().mousewheelEvent)
- document->didAddWheelEventHandler();
+ if (eventNames().isWheelEventType(eventType))
+ document->didAddWheelEventHandler(*document);
else if (eventNames().isTouchEventType(eventType))
- document->didAddTouchEventHandler(document);
+ document->didAddTouchEventHandler(*document);
else if (eventType == eventNames().storageEvent)
- didAddStorageEventListener(this);
+ didAddStorageEventListener(*this);
}
if (eventType == eventNames().unloadEvent)
@@ -1654,17 +1779,28 @@ bool DOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<Event
addBeforeUnloadEventListener(this);
#if ENABLE(DEVICE_ORIENTATION)
#if PLATFORM(IOS)
- else if (eventType == eventNames().devicemotionEvent && document())
- document()->deviceMotionController()->addDeviceEventListener(this);
- else if (eventType == eventNames().deviceorientationEvent && document())
- document()->deviceOrientationController()->addDeviceEventListener(this);
+ else if ((eventType == eventNames().devicemotionEvent || eventType == eventNames().deviceorientationEvent) && document()) {
+ if (isSameSecurityOriginAsMainFrame()) {
+ if (eventType == eventNames().deviceorientationEvent)
+ document()->deviceOrientationController()->addDeviceEventListener(this);
+ else
+ document()->deviceMotionController()->addDeviceEventListener(this);
+ } else if (document())
+ document()->addConsoleMessage(MessageSource::JS, MessageLevel::Warning, ASCIILiteral("Blocked attempt add device motion or orientation listener from child frame that wasn't the same security origin as the main page."));
+ }
#else
- else if (eventType == eventNames().devicemotionEvent && RuntimeEnabledFeatures::sharedFeatures().deviceMotionEnabled()) {
- if (DeviceMotionController* controller = DeviceMotionController::from(page()))
- controller->addDeviceEventListener(this);
- } else if (eventType == eventNames().deviceorientationEvent && RuntimeEnabledFeatures::sharedFeatures().deviceOrientationEnabled()) {
- if (DeviceOrientationController* controller = DeviceOrientationController::from(page()))
- controller->addDeviceEventListener(this);
+ else if (eventType == eventNames().devicemotionEvent) {
+ if (isSameSecurityOriginAsMainFrame()) {
+ if (DeviceMotionController* controller = DeviceMotionController::from(page()))
+ controller->addDeviceEventListener(this);
+ } else if (document())
+ document()->addConsoleMessage(MessageSource::JS, MessageLevel::Warning, ASCIILiteral("Blocked attempt add device motion listener from child frame that wasn't the same security origin as the main page."));
+ } else if (eventType == eventNames().deviceorientationEvent) {
+ if (isSameSecurityOriginAsMainFrame()) {
+ if (DeviceOrientationController* controller = DeviceOrientationController::from(page()))
+ controller->addDeviceEventListener(this);
+ } else if (document())
+ document()->addConsoleMessage(MessageSource::JS, MessageLevel::Warning, ASCIILiteral("Blocked attempt add device orientation listener from child frame that wasn't the same security origin as the main page."));
}
#endif // PLATFORM(IOS)
#endif // ENABLE(DEVICE_ORIENTATION)
@@ -1680,7 +1816,10 @@ bool DOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<Event
else if (eventNames().isGestureEventType(eventType))
++m_touchEventListenerCount;
#endif
-
+#if ENABLE(GAMEPAD)
+ else if (eventNames().isGamepadEventType(eventType))
+ incrementGamepadEventListenerCount();
+#endif
#if ENABLE(PROXIMITY_EVENTS)
else if (eventType == eventNames().webkitdeviceproximityEvent) {
if (DeviceProximityController* controller = DeviceProximityController::from(page()))
@@ -1692,13 +1831,14 @@ bool DOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<Event
}
#if PLATFORM(IOS)
+
void DOMWindow::incrementScrollEventListenersCount()
{
Document* document = this->document();
if (++m_scrollEventListenerCount == 1 && document == &document->topDocument()) {
Frame* frame = this->frame();
if (frame && frame->page())
- frame->page()->chrome().client().setNeedsScrollNotifications(frame, true);
+ frame->page()->chrome().client().setNeedsScrollNotifications(*frame, true);
}
}
@@ -1707,31 +1847,32 @@ void DOMWindow::decrementScrollEventListenersCount()
Document* document = this->document();
if (!--m_scrollEventListenerCount && document == &document->topDocument()) {
Frame* frame = this->frame();
- if (frame && frame->page() && !document->inPageCache())
- frame->page()->chrome().client().setNeedsScrollNotifications(frame, false);
+ if (frame && frame->page() && document->pageCacheState() == Document::NotInPageCache)
+ frame->page()->chrome().client().setNeedsScrollNotifications(*frame, false);
}
}
+
#endif
void DOMWindow::resetAllGeolocationPermission()
{
- // FIXME: Remove PLATFORM(IOS)-guard once we upstream the iOS changes to Geolocation.cpp.
+ // FIXME: Can we remove the PLATFORM(IOS)-guard?
#if ENABLE(GEOLOCATION) && PLATFORM(IOS)
if (m_navigator)
NavigatorGeolocation::from(m_navigator.get())->resetAllGeolocationPermission();
#endif
}
-bool DOMWindow::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
+bool DOMWindow::removeEventListener(const AtomicString& eventType, EventListener& listener, const ListenerOptions& options)
{
- if (!EventTarget::removeEventListener(eventType, listener, useCapture))
+ if (!EventTarget::removeEventListener(eventType, listener, options.capture))
return false;
if (Document* document = this->document()) {
- if (eventType == eventNames().wheelEvent || eventType == eventNames().mousewheelEvent)
- document->didRemoveWheelEventHandler();
+ if (eventNames().isWheelEventType(eventType))
+ document->didRemoveWheelEventHandler(*document);
else if (eventNames().isTouchEventType(eventType))
- document->didRemoveTouchEventHandler(document);
+ document->didRemoveTouchEventHandler(*document);
}
if (eventType == eventNames().unloadEvent)
@@ -1770,7 +1911,10 @@ bool DOMWindow::removeEventListener(const AtomicString& eventType, EventListener
--m_touchEventListenerCount;
}
#endif
-
+#if ENABLE(GAMEPAD)
+ else if (eventNames().isGamepadEventType(eventType))
+ decrementGamepadEventListenerCount();
+#endif
#if ENABLE(PROXIMITY_EVENTS)
else if (eventType == eventNames().webkitdeviceproximityEvent) {
if (DeviceProximityController* controller = DeviceProximityController::from(page()))
@@ -1781,58 +1925,63 @@ bool DOMWindow::removeEventListener(const AtomicString& eventType, EventListener
return true;
}
+void DOMWindow::languagesChanged()
+{
+ if (auto* document = this->document())
+ document->enqueueWindowEvent(Event::create(eventNames().languagechangeEvent, false, false));
+}
+
void DOMWindow::dispatchLoadEvent()
{
- RefPtr<Event> loadEvent(Event::create(eventNames().loadEvent, false, false));
- if (m_frame && m_frame->loader().documentLoader() && !m_frame->loader().documentLoader()->timing()->loadEventStart()) {
- // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed while dispatching
+ Ref<Event> loadEvent = Event::create(eventNames().loadEvent, false, false);
+ if (m_frame && m_frame->loader().documentLoader() && !m_frame->loader().documentLoader()->timing().loadEventStart()) {
+ // The DocumentLoader (and thus its LoadTiming) might get destroyed while dispatching
// the event, so protect it to prevent writing the end time into freed memory.
RefPtr<DocumentLoader> documentLoader = m_frame->loader().documentLoader();
- DocumentLoadTiming* timing = documentLoader->timing();
- timing->markLoadEventStart();
+ LoadTiming& timing = documentLoader->timing();
+ timing.markLoadEventStart();
dispatchEvent(loadEvent, document());
- timing->markLoadEventEnd();
+ timing.markLoadEventEnd();
} else
dispatchEvent(loadEvent, document());
// For load events, send a separate load event to the enclosing frame only.
// This is a DOM extension and is independent of bubbling/capturing rules of
// the DOM.
- Element* ownerElement = m_frame ? m_frame->ownerElement() : 0;
+ Element* ownerElement = m_frame ? m_frame->ownerElement() : nullptr;
if (ownerElement)
ownerElement->dispatchEvent(Event::create(eventNames().loadEvent, false, false));
InspectorInstrumentation::loadEventFired(frame());
}
-bool DOMWindow::dispatchEvent(PassRefPtr<Event> prpEvent, PassRefPtr<EventTarget> prpTarget)
+bool DOMWindow::dispatchEvent(Event& event, EventTarget* target)
{
- Ref<EventTarget> protect(*this);
- RefPtr<Event> event = prpEvent;
+ Ref<EventTarget> protectedThis(*this);
// Pausing a page may trigger pagehide and pageshow events. WebCore also implicitly fires these
// events when closing a WebView. Here we keep track of the state of the page to prevent duplicate,
// unbalanced events per the definition of the pageshow event:
// <http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#event-pageshow>.
- if (event->eventInterface() == PageTransitionEventInterfaceType) {
- if (event->type() == eventNames().pageshowEvent) {
- if (m_lastPageStatus == PageStatusShown)
+ if (event.eventInterface() == PageTransitionEventInterfaceType) {
+ if (event.type() == eventNames().pageshowEvent) {
+ if (m_lastPageStatus == PageStatus::Shown)
return true; // Event was previously dispatched; do not fire a duplicate event.
- m_lastPageStatus = PageStatusShown;
- } else if (event->type() == eventNames().pagehideEvent) {
- if (m_lastPageStatus == PageStatusHidden)
+ m_lastPageStatus = PageStatus::Shown;
+ } else if (event.type() == eventNames().pagehideEvent) {
+ if (m_lastPageStatus == PageStatus::Hidden)
return true; // Event was previously dispatched; do not fire a duplicate event.
- m_lastPageStatus = PageStatusHidden;
+ m_lastPageStatus = PageStatus::Hidden;
}
}
- event->setTarget(prpTarget ? prpTarget : this);
- event->setCurrentTarget(this);
- event->setEventPhase(Event::AT_TARGET);
+ event.setTarget(target ? target : this);
+ event.setCurrentTarget(this);
+ event.setEventPhase(Event::AT_TARGET);
- InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEventOnWindow(frame(), *event, this);
+ InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEventOnWindow(frame(), event, *this);
- bool result = fireEventListeners(event.get());
+ bool result = fireEventListeners(event);
InspectorInstrumentation::didDispatchEventOnWindow(cookie);
@@ -1870,7 +2019,7 @@ void DOMWindow::removeAllEventListeners()
#if ENABLE(TOUCH_EVENTS)
if (Document* document = this->document())
- document->didRemoveEventTargetNode(document);
+ document->didRemoveEventTargetNode(*document);
#endif
#if ENABLE(PROXIMITY_EVENTS)
@@ -1878,6 +2027,11 @@ void DOMWindow::removeAllEventListeners()
controller->removeAllDeviceEventListeners(this);
#endif
+#if ENABLE(WEB_TIMING)
+ if (m_performance)
+ m_performance->removeAllEventListeners();
+#endif
+
removeAllUnloadEventListeners(this);
removeAllBeforeUnloadEventListeners(this);
}
@@ -1896,11 +2050,12 @@ void DOMWindow::finishedLoading()
{
if (m_shouldPrintWhenFinishedLoading) {
m_shouldPrintWhenFinishedLoading = false;
- print();
+ if (m_frame->loader().activeDocumentLoader()->mainDocumentError().isNull())
+ print();
}
}
-void DOMWindow::setLocation(const String& urlString, DOMWindow& activeWindow, DOMWindow& firstWindow, SetLocationLocking locking)
+void DOMWindow::setLocation(DOMWindow& activeWindow, DOMWindow& firstWindow, const String& urlString, SetLocationLocking locking)
{
if (!isCurrentlyDisplayedInFrame())
return;
@@ -1924,11 +2079,12 @@ void DOMWindow::setLocation(const String& urlString, DOMWindow& activeWindow, DO
return;
// We want a new history item if we are processing a user gesture.
- m_frame->navigationScheduler().scheduleLocationChange(activeDocument->securityOrigin(),
+ LockHistory lockHistory = (locking != LockHistoryBasedOnGestureState || !ScriptController::processingUserGesture()) ? LockHistory::Yes : LockHistory::No;
+ LockBackForwardList lockBackForwardList = (locking != LockHistoryBasedOnGestureState) ? LockBackForwardList::Yes : LockBackForwardList::No;
+ m_frame->navigationScheduler().scheduleLocationChange(*activeDocument, activeDocument->securityOrigin(),
// FIXME: What if activeDocument()->frame() is 0?
completedURL, activeDocument->frame()->loader().outgoingReferrer(),
- locking != LockHistoryBasedOnGestureState || !ScriptController::processingUserGesture(),
- locking != LockHistoryBasedOnGestureState);
+ lockHistory, lockBackForwardList);
}
void DOMWindow::printErrorMessage(const String& message)
@@ -1936,7 +2092,8 @@ void DOMWindow::printErrorMessage(const String& message)
if (message.isEmpty())
return;
- pageConsole()->addMessage(JSMessageSource, ErrorMessageLevel, message);
+ if (PageConsoleClient* pageConsole = console())
+ pageConsole->addMessage(MessageSource::JS, MessageLevel::Error, message);
}
String DOMWindow::crossDomainAccessErrorMessage(const DOMWindow& activeWindow)
@@ -1945,18 +2102,18 @@ String DOMWindow::crossDomainAccessErrorMessage(const DOMWindow& activeWindow)
if (activeWindowURL.isNull())
return String();
- ASSERT(!activeWindow.document()->securityOrigin()->canAccess(document()->securityOrigin()));
+ ASSERT(!activeWindow.document()->securityOrigin().canAccess(document()->securityOrigin()));
// FIXME: This message, and other console messages, have extra newlines. Should remove them.
- SecurityOrigin* activeOrigin = activeWindow.document()->securityOrigin();
- SecurityOrigin* targetOrigin = document()->securityOrigin();
- String message = "Blocked a frame with origin \"" + activeOrigin->toString() + "\" from accessing a frame with origin \"" + targetOrigin->toString() + "\". ";
+ SecurityOrigin& activeOrigin = activeWindow.document()->securityOrigin();
+ SecurityOrigin& targetOrigin = document()->securityOrigin();
+ String message = "Blocked a frame with origin \"" + activeOrigin.toString() + "\" from accessing a frame with origin \"" + targetOrigin.toString() + "\". ";
// Sandbox errors: Use the origin of the frames' location, rather than their actual origin (since we know that at least one will be "null").
URL activeURL = activeWindow.document()->url();
URL targetURL = document()->url();
if (document()->isSandboxed(SandboxOrigin) || activeWindow.document()->isSandboxed(SandboxOrigin)) {
- message = "Blocked a frame at \"" + SecurityOrigin::create(activeURL)->toString() + "\" from accessing a frame at \"" + SecurityOrigin::create(targetURL)->toString() + "\". ";
+ message = "Blocked a frame at \"" + SecurityOrigin::create(activeURL).get().toString() + "\" from accessing a frame at \"" + SecurityOrigin::create(targetURL).get().toString() + "\". ";
if (document()->isSandboxed(SandboxOrigin) && activeWindow.document()->isSandboxed(SandboxOrigin))
return "Sandbox access violation: " + message + " Both frames are sandboxed and lack the \"allow-same-origin\" flag.";
if (document()->isSandboxed(SandboxOrigin))
@@ -1965,16 +2122,16 @@ String DOMWindow::crossDomainAccessErrorMessage(const DOMWindow& activeWindow)
}
// 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:'.
- if (targetOrigin->protocol() != activeOrigin->protocol())
+ if (targetOrigin.protocol() != activeOrigin.protocol())
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";
// 'document.domain' errors.
- if (targetOrigin->domainWasSetInDOM() && activeOrigin->domainWasSetInDOM())
- 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.";
- if (activeOrigin->domainWasSetInDOM())
- 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.";
- if (targetOrigin->domainWasSetInDOM())
- 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.";
+ if (targetOrigin.domainWasSetInDOM() && activeOrigin.domainWasSetInDOM())
+ 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.";
+ if (activeOrigin.domainWasSetInDOM())
+ 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.";
+ if (targetOrigin.domainWasSetInDOM())
+ 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.";
// Default.
return message + "Protocols, domains, and ports must match.";
@@ -1996,7 +2153,7 @@ bool DOMWindow::isInsecureScriptAccess(DOMWindow& activeWindow, const String& ur
// FIXME: The name canAccess seems to be a roundabout way to ask "can execute script".
// Can we name the SecurityOrigin function better to make this more clear?
- if (activeWindow.document()->securityOrigin()->canAccess(document()->securityOrigin()))
+ if (activeWindow.document()->securityOrigin().canAccess(document()->securityOrigin()))
return false;
}
@@ -2004,76 +2161,98 @@ bool DOMWindow::isInsecureScriptAccess(DOMWindow& activeWindow, const String& ur
return true;
}
-PassRefPtr<Frame> DOMWindow::createWindow(const String& urlString, const AtomicString& frameName, const WindowFeatures& windowFeatures, DOMWindow& activeWindow, Frame* firstFrame, Frame* openerFrame, std::function<void (DOMWindow&)> prepareDialogFunction)
+RefPtr<Frame> DOMWindow::createWindow(const String& urlString, const AtomicString& frameName, const WindowFeatures& windowFeatures, DOMWindow& activeWindow, Frame& firstFrame, Frame& openerFrame, std::function<void (DOMWindow&)> prepareDialogFunction)
{
Frame* activeFrame = activeWindow.frame();
+ if (!activeFrame)
+ return nullptr;
+
+ Document* activeDocument = activeWindow.document();
+ if (!activeDocument)
+ return nullptr;
- URL completedURL = urlString.isEmpty() ? URL(ParsedURLString, emptyString()) : firstFrame->document()->completeURL(urlString);
+ URL completedURL = urlString.isEmpty() ? URL(ParsedURLString, emptyString()) : firstFrame.document()->completeURL(urlString);
if (!completedURL.isEmpty() && !completedURL.isValid()) {
// Don't expose client code to invalid URLs.
activeWindow.printErrorMessage("Unable to open a window with invalid URL '" + completedURL.string() + "'.\n");
- return 0;
+ return nullptr;
}
// For whatever reason, Firefox uses the first frame to determine the outgoingReferrer. We replicate that behavior here.
- String referrer = SecurityPolicy::generateReferrerHeader(firstFrame->document()->referrerPolicy(), completedURL, firstFrame->loader().outgoingReferrer());
+ String referrer = SecurityPolicy::generateReferrerHeader(firstFrame.document()->referrerPolicy(), completedURL, firstFrame.loader().outgoingReferrer());
ResourceRequest request(completedURL, referrer);
- FrameLoader::addHTTPOriginIfNeeded(request, firstFrame->loader().outgoingOrigin());
- FrameLoadRequest frameRequest(activeWindow.document()->securityOrigin(), request, frameName);
+ FrameLoader::addHTTPOriginIfNeeded(request, firstFrame.loader().outgoingOrigin());
+ FrameLoadRequest frameRequest(activeDocument->securityOrigin(), request, frameName, LockHistory::No, LockBackForwardList::No, MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, ReplaceDocumentIfJavaScriptURL, activeDocument->shouldOpenExternalURLsPolicyToPropagate());
// We pass the opener frame for the lookupFrame in case the active frame is different from
// the opener frame, and the name references a frame relative to the opener frame.
bool created;
- RefPtr<Frame> newFrame = WebCore::createWindow(activeFrame, openerFrame, frameRequest, windowFeatures, created);
+ RefPtr<Frame> newFrame = WebCore::createWindow(*activeFrame, openerFrame, frameRequest, windowFeatures, created);
if (!newFrame)
- return 0;
+ return nullptr;
- newFrame->loader().setOpener(openerFrame);
+ newFrame->loader().setOpener(&openerFrame);
newFrame->page()->setOpenedByDOM();
if (newFrame->document()->domWindow()->isInsecureScriptAccess(activeWindow, completedURL))
- return newFrame.release();
+ return newFrame;
if (prepareDialogFunction)
prepareDialogFunction(*newFrame->document()->domWindow());
- if (created)
- newFrame->loader().changeLocation(activeWindow.document()->securityOrigin(), completedURL, referrer, false, false);
- else if (!urlString.isEmpty()) {
- bool lockHistory = !ScriptController::processingUserGesture();
- newFrame->navigationScheduler().scheduleLocationChange(activeWindow.document()->securityOrigin(), completedURL.string(), referrer, lockHistory, false);
+ if (created) {
+ ResourceRequest resourceRequest(completedURL, referrer, UseProtocolCachePolicy);
+ FrameLoadRequest frameRequest(activeWindow.document()->securityOrigin(), resourceRequest, "_self", LockHistory::No, LockBackForwardList::No, MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, activeDocument->shouldOpenExternalURLsPolicyToPropagate());
+ newFrame->loader().changeLocation(frameRequest);
+ } else if (!urlString.isEmpty()) {
+ LockHistory lockHistory = ScriptController::processingUserGesture() ? LockHistory::No : LockHistory::Yes;
+ newFrame->navigationScheduler().scheduleLocationChange(*activeWindow.document(), activeWindow.document()->securityOrigin(), completedURL, referrer, lockHistory, LockBackForwardList::No);
}
// Navigating the new frame could result in it being detached from its page by a navigation policy delegate.
if (!newFrame->page())
- return 0;
+ return nullptr;
- return newFrame.release();
+ return newFrame;
}
-PassRefPtr<DOMWindow> DOMWindow::open(const String& urlString, const AtomicString& frameName, const String& windowFeaturesString,
- DOMWindow& activeWindow, DOMWindow& firstWindow)
+RefPtr<DOMWindow> DOMWindow::open(const String& urlString, const AtomicString& frameName, const String& windowFeaturesString, DOMWindow& activeWindow, DOMWindow& firstWindow)
{
if (!isCurrentlyDisplayedInFrame())
- return 0;
- Document* activeDocument = activeWindow.document();
+ return nullptr;
+
+ auto* activeDocument = activeWindow.document();
if (!activeDocument)
- return 0;
- Frame* firstFrame = firstWindow.frame();
+ return nullptr;
+
+ auto* firstFrame = firstWindow.frame();
if (!firstFrame)
- return 0;
+ return nullptr;
+
+#if ENABLE(CONTENT_EXTENSIONS)
+ if (firstFrame->document()
+ && firstFrame->page()
+ && firstFrame->mainFrame().document()
+ && firstFrame->mainFrame().document()->loader()) {
+ ResourceLoadInfo resourceLoadInfo { firstFrame->document()->completeURL(urlString), firstFrame->mainFrame().document()->url(), ResourceType::Popup };
+ for (auto& action : firstFrame->page()->userContentProvider().actionsForResourceLoad(resourceLoadInfo, *firstFrame->mainFrame().document()->loader())) {
+ if (action.type() == ContentExtensions::ActionType::BlockLoad)
+ return nullptr;
+ }
+ }
+#endif
if (!firstWindow.allowPopUp()) {
- // Because FrameTree::find() returns true for empty strings, we must check for empty frame names.
+ // Because FrameTree::findFrameForNavigation() returns true for empty strings, we must check for empty frame names.
// Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker.
- if (frameName.isEmpty() || !m_frame->tree().find(frameName))
- return 0;
+ if (frameName.isEmpty() || !m_frame->loader().findFrameForNavigation(frameName, activeDocument))
+ return nullptr;
}
// Get the target frame for the special cases of _top and _parent.
// In those cases, we schedule a location change right now and return early.
- Frame* targetFrame = 0;
+ Frame* targetFrame = nullptr;
if (frameName == "_top")
targetFrame = &m_frame->tree().top();
else if (frameName == "_parent") {
@@ -2084,7 +2263,7 @@ PassRefPtr<DOMWindow> DOMWindow::open(const String& urlString, const AtomicStrin
}
if (targetFrame) {
if (!activeDocument->canNavigate(targetFrame))
- return 0;
+ return nullptr;
URL completedURL = firstFrame->document()->completeURL(urlString);
@@ -2096,43 +2275,39 @@ PassRefPtr<DOMWindow> DOMWindow::open(const String& urlString, const AtomicStrin
// For whatever reason, Firefox uses the first window rather than the active window to
// determine the outgoing referrer. We replicate that behavior here.
- bool lockHistory = !ScriptController::processingUserGesture();
- targetFrame->navigationScheduler().scheduleLocationChange(
- activeDocument->securityOrigin(),
- completedURL,
- firstFrame->loader().outgoingReferrer(),
- lockHistory,
- false);
+ LockHistory lockHistory = ScriptController::processingUserGesture() ? LockHistory::No : LockHistory::Yes;
+ targetFrame->navigationScheduler().scheduleLocationChange(*activeDocument, activeDocument->securityOrigin(), completedURL, firstFrame->loader().outgoingReferrer(),
+ lockHistory, LockBackForwardList::No);
return targetFrame->document()->domWindow();
}
- WindowFeatures windowFeatures(windowFeaturesString);
- RefPtr<Frame> result = createWindow(urlString, frameName, windowFeatures, activeWindow, firstFrame, m_frame);
- return result ? result->document()->domWindow() : 0;
+ RefPtr<Frame> result = createWindow(urlString, frameName, parseWindowFeatures(windowFeaturesString), activeWindow, *firstFrame, *m_frame);
+ return result ? result->document()->domWindow() : nullptr;
}
void DOMWindow::showModalDialog(const String& urlString, const String& dialogFeaturesString, DOMWindow& activeWindow, DOMWindow& firstWindow, std::function<void (DOMWindow&)> prepareDialogFunction)
{
if (!isCurrentlyDisplayedInFrame())
return;
- Frame* activeFrame = activeWindow.frame();
- if (!activeFrame)
+ if (!activeWindow.frame())
return;
Frame* firstFrame = firstWindow.frame();
if (!firstFrame)
return;
- // Pages are not allowed to cause modal alerts during BeforeUnload dispatch.
- if (page() && page()->isAnyFrameHandlingBeforeUnloadEvent()) {
- printErrorMessage("Use of window.showModalDialog is not allowed during beforeunload event dispatch.");
+ auto* page = m_frame->page();
+ if (!page)
+ return;
+
+ if (!page->arePromptsAllowed()) {
+ printErrorMessage("Use of window.showModalDialog is not allowed while unloading a page.");
return;
}
- if (!canShowModalDialogNow(m_frame) || !firstWindow.allowPopUp())
+ if (!canShowModalDialog(*m_frame) || !firstWindow.allowPopUp())
return;
- WindowFeatures windowFeatures(dialogFeaturesString, screenAvailableRect(m_frame->view()));
- RefPtr<Frame> dialogFrame = createWindow(urlString, emptyAtom, windowFeatures, activeWindow, firstFrame, m_frame, std::move(prepareDialogFunction));
+ RefPtr<Frame> dialogFrame = createWindow(urlString, emptyAtom, parseDialogFeatures(dialogFeaturesString, screenAvailableRect(m_frame->view())), activeWindow, *firstFrame, *m_frame, WTFMove(prepareDialogFunction));
if (!dialogFrame)
return;
dialogFrame->page()->chrome().runModal();