summaryrefslogtreecommitdiffstats
path: root/WebCore/bindings/generic
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/bindings/generic')
-rw-r--r--WebCore/bindings/generic/ActiveDOMCallback.cpp144
-rw-r--r--WebCore/bindings/generic/ActiveDOMCallback.h58
-rw-r--r--WebCore/bindings/generic/BindingDOMWindow.h177
-rw-r--r--WebCore/bindings/generic/BindingSecurity.h25
-rw-r--r--WebCore/bindings/generic/RuntimeEnabledFeatures.cpp1
-rw-r--r--WebCore/bindings/generic/RuntimeEnabledFeatures.h6
6 files changed, 405 insertions, 6 deletions
diff --git a/WebCore/bindings/generic/ActiveDOMCallback.cpp b/WebCore/bindings/generic/ActiveDOMCallback.cpp
new file mode 100644
index 0000000..2e69d10
--- /dev/null
+++ b/WebCore/bindings/generic/ActiveDOMCallback.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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.
+ */
+
+#include "config.h"
+#include "ActiveDOMCallback.h"
+
+#include "ActiveDOMObject.h"
+#include "ScriptExecutionContext.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/ThreadingPrimitives.h>
+
+namespace WebCore {
+
+static void destroyOnContextThread(PassOwnPtr<ActiveDOMObjectCallbackImpl>);
+
+class DestroyOnContextThreadTask : public ScriptExecutionContext::Task {
+public:
+ static PassOwnPtr<DestroyOnContextThreadTask> create(PassOwnPtr<ActiveDOMObjectCallbackImpl> impl)
+ {
+ return adoptPtr(new DestroyOnContextThreadTask(impl));
+ }
+
+ virtual void performTask(ScriptExecutionContext*)
+ {
+ destroyOnContextThread(m_impl.release());
+ }
+
+private:
+ DestroyOnContextThreadTask(PassOwnPtr<ActiveDOMObjectCallbackImpl> impl)
+ : m_impl(impl)
+ {
+ }
+
+ OwnPtr<ActiveDOMObjectCallbackImpl> m_impl;
+};
+
+// Instances of this class are accessed only on the context thread, so we don't need to use locks.
+class ActiveDOMObjectCallbackImpl : public ActiveDOMObject {
+public:
+ ActiveDOMObjectCallbackImpl(ScriptExecutionContext* context)
+ : ActiveDOMObject(context, this)
+ , m_suspended(false)
+ , m_stopped(false)
+ {
+ }
+
+ virtual void contextDestroyed()
+ {
+ MutexLocker locker(m_mutex);
+ ActiveDOMObject::contextDestroyed();
+ }
+ virtual bool canSuspend() const { return false; }
+ virtual void suspend()
+ {
+ MutexLocker locker(m_mutex);
+ m_suspended = true;
+ }
+ virtual void resume()
+ {
+ MutexLocker locker(m_mutex);
+ m_suspended = false;
+ }
+ virtual void stop()
+ {
+ MutexLocker locker(m_mutex);
+ m_stopped = true;
+ }
+ bool canInvokeCallback()
+ {
+ MutexLocker locker(m_mutex);
+ return (!m_suspended && !m_stopped);
+ }
+ ScriptExecutionContext* scriptExecutionContext()
+ {
+ MutexLocker locker(m_mutex);
+ return ActiveDOMObject::scriptExecutionContext();
+ }
+ Mutex& mutex() { return m_mutex; }
+
+private:
+ Mutex m_mutex;
+ bool m_suspended;
+ bool m_stopped;
+};
+
+static void destroyOnContextThread(PassOwnPtr<ActiveDOMObjectCallbackImpl> impl)
+{
+ OwnPtr<ActiveDOMObjectCallbackImpl> implOwnPtr = impl;
+
+ ScriptExecutionContext* context = implOwnPtr->scriptExecutionContext();
+ MutexLocker locker(implOwnPtr->mutex());
+ if (context && !context->isContextThread())
+ context->postTask(DestroyOnContextThreadTask::create(implOwnPtr.release()));
+}
+
+ActiveDOMCallback::ActiveDOMCallback(ScriptExecutionContext* context)
+ : m_impl(new ActiveDOMObjectCallbackImpl(context))
+{
+ ASSERT(context->isContextThread());
+}
+
+ActiveDOMCallback::~ActiveDOMCallback()
+{
+ destroyOnContextThread(m_impl.release());
+}
+
+bool ActiveDOMCallback::canInvokeCallback() const
+{
+ return m_impl->canInvokeCallback();
+}
+
+ScriptExecutionContext* ActiveDOMCallback::scriptExecutionContext() const
+{
+ return m_impl->scriptExecutionContext();
+}
+
+} // namespace WebCore
diff --git a/WebCore/bindings/generic/ActiveDOMCallback.h b/WebCore/bindings/generic/ActiveDOMCallback.h
new file mode 100644
index 0000000..2fe99ab
--- /dev/null
+++ b/WebCore/bindings/generic/ActiveDOMCallback.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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.
+ */
+
+#ifndef ActiveDOMCallback_h
+#define ActiveDOMCallback_h
+
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class ActiveDOMObjectCallbackImpl;
+class ScriptExecutionContext;
+
+// A class that allows callbacks to behave like ActiveDOMObjects, and also
+// be destroyed on the context thread or any other thread.
+class ActiveDOMCallback {
+public:
+ ActiveDOMCallback(ScriptExecutionContext* context);
+ ~ActiveDOMCallback();
+
+ bool canInvokeCallback() const;
+ ScriptExecutionContext* scriptExecutionContext() const;
+
+private:
+ // The ActiveDOMObject part of the callback.
+ OwnPtr<ActiveDOMObjectCallbackImpl> m_impl;
+};
+
+} // namespace WebCore
+
+#endif // ActiveDOMCallback_h
diff --git a/WebCore/bindings/generic/BindingDOMWindow.h b/WebCore/bindings/generic/BindingDOMWindow.h
index f883d11..dda5644 100644
--- a/WebCore/bindings/generic/BindingDOMWindow.h
+++ b/WebCore/bindings/generic/BindingDOMWindow.h
@@ -1,10 +1,10 @@
/*
* Copyright (C) 2010 Google Inc. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -31,11 +31,17 @@
#ifndef BindingDOMWindow_h
#define BindingDOMWindow_h
+#include "DOMWindow.h"
#include "Frame.h"
#include "FrameLoadRequest.h"
+#include "FrameLoader.h"
+#include "FrameView.h"
#include "GenericBinding.h"
#include "Page.h"
+#include "PlatformScreen.h"
+#include "ScriptController.h"
#include "SecurityOrigin.h"
+#include "WindowFeatures.h"
namespace WebCore {
@@ -52,6 +58,20 @@ public:
const String& frameName,
const WindowFeatures& windowFeatures,
BindingValue dialogArgs);
+
+ static WebCore::DOMWindow* open(State<Binding>*,
+ WebCore::DOMWindow* parent,
+ const String& url,
+ const String& frameName,
+ const WindowFeatures& rawFeatures);
+
+ // FIXME: There should be a place for generic binding utilities.
+ static KURL completeURL(State<Binding>*, const String& relativeURL);
+
+private:
+ // Horizontal and vertical offset, from the parent content area,
+ // around newly opened popups that don't specify a location.
+ static const int popupTilePixels = 10;
};
// Implementations of templated methods must be in this file.
@@ -103,8 +123,8 @@ Frame* BindingDOMWindow<Binding>::createWindow(State<Binding>* state,
if (!protocolIsJavaScript(url) || BindingSecurity<Binding>::canAccessFrame(state, newFrame, true)) {
KURL completedUrl =
- url.isEmpty() ? KURL(ParsedURLString, "") : completeURL(url);
- bool userGesture = processingUserGesture();
+ url.isEmpty() ? KURL(ParsedURLString, "") : completeURL(state, url);
+ bool userGesture = state->processingUserGesture();
if (created)
newFrame->loader()->changeLocation(completedUrl, referrer, false, false, userGesture);
@@ -115,6 +135,153 @@ Frame* BindingDOMWindow<Binding>::createWindow(State<Binding>* state,
return newFrame;
}
+template<class Binding>
+WebCore::DOMWindow* BindingDOMWindow<Binding>::open(State<Binding>* state,
+ WebCore::DOMWindow* parent,
+ const String& urlString,
+ const String& frameName,
+ const WindowFeatures& rawFeatures)
+{
+ Frame* frame = parent->frame();
+
+ if (!BindingSecurity<Binding>::canAccessFrame(state, frame, true))
+ return 0;
+
+ Frame* firstFrame = state->getFirstFrame();
+ if (!firstFrame)
+ return 0;
+
+ Frame* activeFrame = state->getActiveFrame();
+ // We may not have a calling context if we are invoked by a plugin
+ // via NPAPI.
+ if (!activeFrame)
+ activeFrame = firstFrame;
+
+ Page* page = frame->page();
+ if (!page)
+ return 0;
+
+ // Because FrameTree::find() returns true for empty strings, we must check
+ // for empty framenames. Otherwise, illegitimate window.open() calls with
+ // no name will pass right through the popup blocker.
+ if (!BindingSecurity<Binding>::allowPopUp(state)
+ && (frameName.isEmpty() || !frame->tree()->find(frameName))) {
+ return 0;
+ }
+
+ // Get the target frame for the special cases of _top and _parent.
+ // In those cases, we can schedule a location change right now and
+ // return early.
+ bool topOrParent = false;
+ if (frameName == "_top") {
+ frame = frame->tree()->top();
+ topOrParent = true;
+ } else if (frameName == "_parent") {
+ if (Frame* parent = frame->tree()->parent())
+ frame = parent;
+ topOrParent = true;
+ }
+ if (topOrParent) {
+ if (!BindingSecurity<Binding>::shouldAllowNavigation(state, frame))
+ return 0;
+
+ String completedUrl;
+ if (!urlString.isEmpty())
+ completedUrl = completeURL(state, urlString);
+
+ if (!completedUrl.isEmpty()
+ && (!protocolIsJavaScript(completedUrl)
+ || BindingSecurity<Binding>::canAccessFrame(state, frame, true))) {
+ bool userGesture = state->processingUserGesture();
+
+ // For whatever reason, Firefox uses the first frame to determine
+ // the outgoingReferrer. We replicate that behavior here.
+ String referrer = firstFrame->loader()->outgoingReferrer();
+
+ frame->redirectScheduler()->scheduleLocationChange(completedUrl, referrer, false, false, userGesture);
+ }
+ return frame->domWindow();
+ }
+
+ // In the case of a named frame or a new window, we'll use the
+ // createWindow() helper.
+
+ // Work with a copy of the parsed values so we can restore the
+ // values we may not want to overwrite after we do the multiple
+ // monitor fixes.
+ WindowFeatures windowFeatures(rawFeatures);
+ FloatRect screenRect = screenAvailableRect(page->mainFrame()->view());
+
+ // Set default size and location near parent window if none were specified.
+ // These may be further modified by adjustWindowRect, below.
+ if (!windowFeatures.xSet) {
+ windowFeatures.x = parent->screenX() - screenRect.x() + popupTilePixels;
+ windowFeatures.xSet = true;
+ }
+ if (!windowFeatures.ySet) {
+ windowFeatures.y = parent->screenY() - screenRect.y() + popupTilePixels;
+ windowFeatures.ySet = true;
+ }
+ if (!windowFeatures.widthSet) {
+ windowFeatures.width = parent->innerWidth();
+ windowFeatures.widthSet = true;
+ }
+ if (!windowFeatures.heightSet) {
+ windowFeatures.height = parent->innerHeight();
+ windowFeatures.heightSet = true;
+ }
+
+ FloatRect windowRect(windowFeatures.x, windowFeatures.y, windowFeatures.width, windowFeatures.height);
+
+ // The new window's location is relative to its current screen, so shift
+ // it in case it's on a secondary monitor. See http://b/viewIssue?id=967905.
+ windowRect.move(screenRect.x(), screenRect.y());
+ WebCore::DOMWindow::adjustWindowRect(screenRect, windowRect, windowRect);
+
+ windowFeatures.x = windowRect.x();
+ windowFeatures.y = windowRect.y();
+ windowFeatures.height = windowRect.height();
+ windowFeatures.width = windowRect.width();
+
+ // If either of the origin coordinates or dimensions weren't set
+ // in the original string, make sure they aren't set now.
+ if (!rawFeatures.xSet) {
+ windowFeatures.x = 0;
+ windowFeatures.xSet = false;
+ }
+ if (!rawFeatures.ySet) {
+ windowFeatures.y = 0;
+ windowFeatures.ySet = false;
+ }
+ if (!rawFeatures.widthSet) {
+ windowFeatures.width = 0;
+ windowFeatures.widthSet = false;
+ }
+ if (!rawFeatures.heightSet) {
+ windowFeatures.height = 0;
+ windowFeatures.heightSet = false;
+ }
+
+ frame = createWindow(state, activeFrame, firstFrame, frame, urlString, frameName, windowFeatures, Binding::emptyScriptValue());
+
+ if (!frame)
+ return 0;
+
+ return frame->domWindow();
+}
+
+template <class Binding>
+KURL BindingDOMWindow<Binding>::completeURL(State<Binding>* state,
+ const String& relativeURL)
+{
+ // For historical reasons, we need to complete the URL using the
+ // dynamic frame.
+ Frame* frame = state->getFirstFrame();
+ if (!frame)
+ return KURL();
+ return frame->loader()->completeURL(relativeURL);
+}
+
} // namespace WebCore
#endif // BindingDOMWindow_h
diff --git a/WebCore/bindings/generic/BindingSecurity.h b/WebCore/bindings/generic/BindingSecurity.h
index d7c9dfe..1124f7e 100644
--- a/WebCore/bindings/generic/BindingSecurity.h
+++ b/WebCore/bindings/generic/BindingSecurity.h
@@ -34,14 +34,15 @@
#include "BindingSecurityBase.h"
#include "CSSHelper.h"
#include "Element.h"
+#include "Frame.h"
#include "GenericBinding.h"
#include "HTMLFrameElementBase.h"
#include "HTMLNames.h"
+#include "Settings.h"
namespace WebCore {
class DOMWindow;
-class Frame;
class Node;
// Security functions shared by various language bindings.
@@ -55,9 +56,12 @@ public:
// current security context.
static bool checkNodeSecurity(State<Binding>*, Node* target);
+ static bool allowPopUp(State<Binding>*);
static bool allowSettingFrameSrcToJavascriptUrl(State<Binding>*, HTMLFrameElementBase*, String value);
static bool allowSettingSrcToJavascriptURL(State<Binding>*, Element*, String name, String value);
+ static bool shouldAllowNavigation(State<Binding>*, Frame*);
+
private:
explicit BindingSecurity() {}
~BindingSecurity();
@@ -110,6 +114,18 @@ bool BindingSecurity<Binding>::checkNodeSecurity(State<Binding>* state, Node* no
}
template <class Binding>
+bool BindingSecurity<Binding>::allowPopUp(State<Binding>* state)
+{
+ if (state->processingUserGesture())
+ return true;
+
+ Frame* frame = state->getFirstFrame();
+ ASSERT(frame);
+ Settings* settings = frame->settings();
+ return settings && settings->javaScriptCanOpenWindowsAutomatically();
+}
+
+template <class Binding>
bool BindingSecurity<Binding>::allowSettingFrameSrcToJavascriptUrl(State<Binding>* state, HTMLFrameElementBase* frame, String value)
{
if (protocolIsJavaScript(deprecatedParseURL(value))) {
@@ -128,6 +144,13 @@ bool BindingSecurity<Binding>::allowSettingSrcToJavascriptURL(State<Binding>* st
return true;
}
+template <class Binding>
+bool BindingSecurity<Binding>::shouldAllowNavigation(State<Binding>* state, Frame* frame)
+{
+ Frame* activeFrame = state->getActiveFrame();
+ return activeFrame && activeFrame->loader()->shouldAllowNavigation(frame);
+}
+
}
#endif // BindingSecurity_h
diff --git a/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp b/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp
index eb027c3..94e984f 100644
--- a/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp
+++ b/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp
@@ -47,6 +47,7 @@ bool RuntimeEnabledFeatures::isIndexedDBEnabled = false;
bool RuntimeEnabledFeatures::isWebGLEnabled = false;
bool RuntimeEnabledFeatures::isPushStateEnabled = false;
bool RuntimeEnabledFeatures::isTouchEnabled = true;
+bool RuntimeEnabledFeatures::isDeviceMotionEnabled = true;
bool RuntimeEnabledFeatures::isDeviceOrientationEnabled = true;
bool RuntimeEnabledFeatures::isSpeechInputEnabled = true;
diff --git a/WebCore/bindings/generic/RuntimeEnabledFeatures.h b/WebCore/bindings/generic/RuntimeEnabledFeatures.h
index c9eb21f..fd7308e 100644
--- a/WebCore/bindings/generic/RuntimeEnabledFeatures.h
+++ b/WebCore/bindings/generic/RuntimeEnabledFeatures.h
@@ -114,6 +114,11 @@ public:
static bool ontouchcancelEnabled() { return isTouchEnabled; }
#endif
+ static void setDeviceMotionEnabled(bool isEnabled) { isDeviceMotionEnabled = isEnabled; }
+ static bool deviceMotionEnabled() { return isDeviceMotionEnabled; }
+ static bool deviceMotionEventEnabled() { return isDeviceMotionEnabled; }
+ static bool ondevicemotionEnabled() { return isDeviceMotionEnabled; }
+
static void setDeviceOrientationEnabled(bool isEnabled) { isDeviceOrientationEnabled = isEnabled; }
static bool deviceOrientationEnabled() { return isDeviceOrientationEnabled; }
static bool deviceOrientationEventEnabled() { return isDeviceOrientationEnabled; }
@@ -136,6 +141,7 @@ private:
static bool isWebGLEnabled;
static bool isPushStateEnabled;
static bool isTouchEnabled;
+ static bool isDeviceMotionEnabled;
static bool isDeviceOrientationEnabled;
static bool isSpeechInputEnabled;
};