summaryrefslogtreecommitdiffstats
path: root/WebKit
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit')
-rw-r--r--WebKit/Android.mk1
-rw-r--r--WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp24
-rw-r--r--WebKit/android/WebCoreSupport/ChromeClientAndroid.h15
-rwxr-xr-xWebKit/android/WebCoreSupport/GeolocationPermissions.cpp243
-rwxr-xr-xWebKit/android/WebCoreSupport/GeolocationPermissions.h135
-rw-r--r--WebKit/android/jni/WebCoreFrameBridge.cpp11
-rw-r--r--WebKit/android/jni/WebViewCore.cpp9
-rw-r--r--WebKit/android/jni/WebViewCore.h12
8 files changed, 447 insertions, 3 deletions
diff --git a/WebKit/Android.mk b/WebKit/Android.mk
index 5e79d5a..e4b739a 100644
--- a/WebKit/Android.mk
+++ b/WebKit/Android.mk
@@ -22,6 +22,7 @@ LOCAL_SRC_FILES := \
android/WebCoreSupport/EditorClientAndroid.cpp \
android/WebCoreSupport/FrameLoaderClientAndroid.cpp \
android/WebCoreSupport/MediaPlayerPrivateAndroid.cpp \
+ android/WebCoreSupport/GeolocationPermissions.cpp \
\
android/RenderSkinAndroid.cpp \
android/RenderSkinButton.cpp \
diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
index a0f3f8d..ac70939 100644
--- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
+++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
@@ -37,6 +37,7 @@
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameView.h"
+#include "Geolocation.h"
#include "Page.h"
#include "Screen.h"
#include "ScriptController.h"
@@ -326,7 +327,28 @@ void ChromeClientAndroid::reachedMaxAppCacheSize(int64_t spaceNeeded)
}
#endif
-void ChromeClientAndroid::requestGeolocationPermissionForFrame(Frame*, Geolocation*) { notImplemented(); }
+void ChromeClientAndroid::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation)
+{
+ ASSERT(geolocation);
+ if (!m_geolocationPermissions) {
+ m_geolocationPermissions = new GeolocationPermissions(android::WebViewCore::getWebViewCore(frame->view()),
+ m_webFrame->page()->mainFrame());
+ }
+ m_geolocationPermissions->queryPermissionState(frame);
+}
+
+void ChromeClientAndroid::provideGeolocationPermissions(const String &origin, bool allow, bool remember)
+{
+ ASSERT(m_geolocationPermissions);
+ m_geolocationPermissions->providePermissionState(origin, allow, remember);
+}
+
+void ChromeClientAndroid::onMainFrameLoadStarted()
+{
+ if (m_geolocationPermissions.get())
+ m_geolocationPermissions->resetTemporaryPermissionStates();
+}
+
void ChromeClientAndroid::runOpenPanel(Frame*, PassRefPtr<FileChooser>) { notImplemented(); }
bool ChromeClientAndroid::setCursor(PlatformCursorHandle)
{
diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
index 93426b8..ded1ea9 100644
--- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
+++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
@@ -28,7 +28,13 @@
#include "ChromeClient.h"
+#include "GeolocationPermissions.h"
#include "Threading.h"
+#include "Timer.h"
+
+namespace WebCore {
+ class Geolocation;
+}
using namespace WebCore;
@@ -37,7 +43,7 @@ namespace android {
class ChromeClientAndroid : public ChromeClient {
public:
- ChromeClientAndroid() : m_webFrame(NULL) {}
+ ChromeClientAndroid() : m_webFrame(0), m_geolocationPermissions(0) { }
virtual void chromeDestroyed();
virtual void setWindowRect(const FloatRect&);
@@ -114,7 +120,12 @@ namespace android {
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
virtual void reachedMaxAppCacheSize(int64_t spaceNeeded);
#endif
+ // Methods used to request and provide Geolocation permissions.
virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*);
+ // Android-specific
+ void provideGeolocationPermissions(const String &origin, bool allow, bool remember);
+ void onMainFrameLoadStarted();
+
virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>);
virtual bool setCursor(PlatformCursorHandle);
@@ -132,6 +143,8 @@ namespace android {
WTF::ThreadCondition m_quotaThreadCondition;
WTF::Mutex m_quotaThreadLock;
long m_newQuota;
+ // The Geolocation permissions manager.
+ RefPtr<GeolocationPermissions> m_geolocationPermissions;
};
}
diff --git a/WebKit/android/WebCoreSupport/GeolocationPermissions.cpp b/WebKit/android/WebCoreSupport/GeolocationPermissions.cpp
new file mode 100755
index 0000000..7c0424b
--- /dev/null
+++ b/WebKit/android/WebCoreSupport/GeolocationPermissions.cpp
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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
+ * 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 "GeolocationPermissions.h"
+
+#include "Frame.h"
+#include "Geolocation.h"
+#include "Navigator.h"
+#include "WebViewCore.h"
+
+using WebCore::Frame;
+using WebCore::String;
+using WebCore::Timer;
+
+namespace android {
+
+// TODO(steveblock): Write the permanent permissions to stable storage when
+// the browser closes and read them on startup.
+GeolocationPermissions::PermissionsMap GeolocationPermissions::s_permanentPermissions;
+GeolocationPermissions::GeolocationPermissionsVector GeolocationPermissions::s_instances;
+
+GeolocationPermissions::GeolocationPermissions(WebViewCore* webViewCore, Frame* mainFrame)
+ : m_webViewCore(webViewCore)
+ , m_mainFrame(mainFrame)
+ , m_timer(this, &GeolocationPermissions::timerFired)
+
+{
+ s_instances.append(this);
+ ASSERT(m_webViewCore);
+}
+
+GeolocationPermissions::~GeolocationPermissions()
+{
+ size_t index = s_instances.find(this);
+ s_instances.remove(index);
+}
+
+void GeolocationPermissions::queryPermissionState(Frame* frame)
+{
+ // We use SecurityOrigin::toString to key the map. Note that testing
+ // the SecurityOrigin pointer for equality is insufficient.
+ String originString = frame->document()->securityOrigin()->toString();
+
+ // See if we have a record for this origin in the temporary permissions for
+ // this tab. These take precedence over permanent permissions.
+ PermissionsMap::const_iterator iter = m_temporaryPermissions.find(originString);
+ PermissionsMap::const_iterator end = m_temporaryPermissions.end();
+ if (iter != end) {
+ bool allow = iter->second;
+ makeAsynchronousCallbackToGeolocation(originString, allow);
+ return;
+ }
+
+ // Check the permanent permisions.
+ iter = s_permanentPermissions.find(originString);
+ end = s_permanentPermissions.end();
+ if (iter != end) {
+ bool allow = iter->second;
+ makeAsynchronousCallbackToGeolocation(originString, allow);
+ return;
+ }
+
+ // If there's no pending request, prompt the user.
+ if (m_originInProgress.isEmpty()) {
+ m_originInProgress = originString;
+
+ // Although multiple tabs may request permissions for the same origin
+ // simultaneously, the routing in WebViewCore/CallbackProxy ensures that
+ // the result of the request will make it back to this object, so
+ // there's no need for a globally unique ID for the request.
+ m_webViewCore->geolocationPermissionsShowPrompt(m_originInProgress);
+ return;
+ }
+
+ // If the request in progress is not for this origin, queue this request.
+ if ((m_originInProgress != originString)
+ && (m_queuedOrigins.find(originString) != WTF::notFound))
+ m_queuedOrigins.append(originString);
+}
+
+void GeolocationPermissions::makeAsynchronousCallbackToGeolocation(String origin, bool allow)
+{
+ m_callbackData.origin = origin;
+ m_callbackData.allow = allow;
+ m_timer.startOneShot(0);
+}
+
+void GeolocationPermissions::providePermissionState(String origin, bool allow, bool remember)
+{
+ // It's possible that this method is called with an origin that doesn't
+ // match m_originInProgress. This can occur if this object is reset
+ // while a permission result is in the process of being marshalled back to
+ // the WebCore thread from the browser. In this case, we simply ignore the
+ // call.
+ if (origin != m_originInProgress)
+ return;
+
+ maybeCallbackFrames(m_originInProgress, allow);
+ recordPermissionState(origin, allow, remember);
+
+ // If the permissions are set to be remembered, cancel any queued requests
+ // for this domain in other tabs.
+ if (remember)
+ cancelPendingRequestsInOtherTabs(m_originInProgress);
+
+ // If there are other requests queued, start the next one.
+ if (!m_queuedOrigins.isEmpty()) {
+ m_originInProgress = m_queuedOrigins.first();
+ m_queuedOrigins.remove(0);
+ m_webViewCore->geolocationPermissionsShowPrompt(m_originInProgress);
+ }
+
+ m_originInProgress = "";
+}
+
+void GeolocationPermissions::recordPermissionState(String origin, bool allow, bool remember)
+{
+ if (remember) {
+ s_permanentPermissions.set(m_originInProgress, allow);
+ // If we already have a temporary permission for this origin, remove it,
+ // so that later clearing the permanent permission works as expected.
+ m_temporaryPermissions.remove(origin);
+ } else {
+ // It's possible that another tab recorded a permanent permission for
+ // this origin while our request was in progress, but we record it
+ // anyway.
+ m_temporaryPermissions.set(m_originInProgress, allow);
+ }
+}
+
+void GeolocationPermissions::cancelPendingRequestsInOtherTabs(String origin)
+{
+ for (GeolocationPermissionsVector::const_iterator iter = s_instances.begin();
+ iter != s_instances.end();
+ ++iter)
+ (*iter)->cancelPendingRequests(origin);
+}
+
+void GeolocationPermissions::cancelPendingRequests(String origin)
+{
+ size_t index = m_queuedOrigins.find(origin);
+ if (index != WTF::notFound) {
+ // Get the permission from the permanent list.
+ PermissionsMap::const_iterator iter = s_permanentPermissions.find(origin);
+ ASSERT(iter != (PermissionsMap::const_iterator end = s_permanentPermissions.end()));
+ bool allow = iter->second;
+
+ maybeCallbackFrames(origin, allow);
+
+ m_queuedOrigins.remove(index);
+ }
+}
+
+void GeolocationPermissions::timerFired(Timer<GeolocationPermissions>* timer)
+{
+ ASSERT(timer == m_timer);
+ maybeCallbackFrames(m_callbackData.origin, m_callbackData.allow);
+}
+
+void GeolocationPermissions::resetTemporaryPermissionStates()
+{
+ m_originInProgress = "";
+ m_queuedOrigins.clear();
+ m_temporaryPermissions.clear();
+ // If any permission results are being marshalled back to this thread, this
+ // will render them inefective.
+ m_timer.stop();
+
+ m_webViewCore->geolocationPermissionsHidePrompt();
+}
+
+void GeolocationPermissions::maybeCallbackFrames(String origin, bool allow)
+{
+ // We can't track which frame issued the request, as frames can be deleted
+ // or have their contents replaced. Even uniqueChildName is not unique when
+ // frames are dynamically deleted and created. Instead, we simply call back
+ // to the Geolocation object in all frames from the correct origin.
+ for (Frame* frame = m_mainFrame; frame; frame = frame->tree()->traverseNext()) {
+ if (origin == frame->document()->securityOrigin()->toString()) {
+ // If the page has changed, it may no longer have a Geolocation
+ // object.
+ Geolocation* geolocation = frame->domWindow()->navigator()->optionalGeolocation();
+ if (geolocation)
+ geolocation->setIsAllowed(allow);
+ }
+ }
+}
+
+GeolocationPermissions::OriginSet GeolocationPermissions::getOrigins()
+{
+ OriginSet origins;
+ PermissionsMap::const_iterator end = s_permanentPermissions.end();
+ for (PermissionsMap::const_iterator iter = s_permanentPermissions.begin(); iter != end; ++iter)
+ origins.add(iter->first);
+ return origins;
+}
+
+bool GeolocationPermissions::getAllowed(String origin)
+{
+ bool allowed = false;
+ PermissionsMap::const_iterator iter = s_permanentPermissions.find(origin);
+ PermissionsMap::const_iterator end = s_permanentPermissions.end();
+ if (iter != end)
+ allowed = iter->second;
+ return allowed;
+}
+
+void GeolocationPermissions::clear(String origin)
+{
+ PermissionsMap::iterator iter = s_permanentPermissions.find(origin);
+ if (iter != s_permanentPermissions.end())
+ s_permanentPermissions.remove(iter);
+}
+
+void GeolocationPermissions::clearAll()
+{
+ s_permanentPermissions.clear();
+}
+
+} // namespace android
diff --git a/WebKit/android/WebCoreSupport/GeolocationPermissions.h b/WebKit/android/WebCoreSupport/GeolocationPermissions.h
new file mode 100755
index 0000000..1dbc3da
--- /dev/null
+++ b/WebKit/android/WebCoreSupport/GeolocationPermissions.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2009, The Android Open Source Project
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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
+ * 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 GeolocationPermissions_h
+#define GeolocationPermissions_h
+
+#include "PlatformString.h"
+// We must include this before before HashMap.h, as it provides specalizations
+// for String hash types instantiated there.
+#include "StringHash.h"
+#include "HashMap.h"
+#include "HashSet.h"
+#include "Timer.h"
+#include "Vector.h"
+#include "wtf/RefCounted.h"
+
+namespace WebCore {
+ class Frame;
+ class Geolocation;
+}
+
+namespace android {
+
+ class WebViewCore;
+
+ // The GeolocationPermissions class manages permissions for the browser.
+ // Each instance handles permissions for a given main frame. The class
+ // enforces the following policy.
+ // - Non-remembered permissions last for the dureation of the main frame.
+ // - Remembered permissions last indefinitely.
+ // - All permissions are shared between child frames of a main frame.
+ // - Only remembered permissions are shared between main frames.
+ // - Remembered permissions are made available for use in the browser
+ // settings menu.
+ class GeolocationPermissions : public RefCounted<GeolocationPermissions> {
+ public:
+ // Creates the GeolocationPermissions object to manage permissions for
+ // the specified main frame (i.e. tab). The WebViewCore is used to
+ // communicate with the browser to display UI.
+ GeolocationPermissions(WebViewCore* webViewCore, WebCore::Frame* mainFrame);
+ virtual ~GeolocationPermissions();
+
+ // Queries the permission state for the specified frame. If the
+ // permission state has not yet been set, prompts the user. Once the
+ // permission state has been determined, asynchronously calls back to
+ // the Geolocation objects in all frames in this WebView that are from
+ // the same origin as the requesting frame.
+ void queryPermissionState(WebCore::Frame* frame);
+
+ // Provides this object the given permission state from the user. The
+ // new permission state is recorded and will trigger callbacks to
+ // geolocation objects as described above. If any other permission
+ // requests are queued, the next is started.
+ void providePermissionState(WebCore::String origin, bool allow, bool remember);
+
+ // Clears the temporary permission state and any pending requests. Used
+ // when the main frame is refreshed or navigated to a new URL.
+ void resetTemporaryPermissionStates();
+
+ // Static methods for use from Java. These are used to interact with the
+ // browser settings menu.
+ typedef HashSet<WebCore::String> OriginSet;
+ static OriginSet getOrigins();
+ static bool getAllowed(WebCore::String origin);
+ static void clear(WebCore::String origin);
+ static void clearAll();
+
+ private:
+ // Records the permission state for the specified origin.
+ void recordPermissionState(WebCore::String origin, bool allow, bool remember);
+
+ // Used to make an asynchronous callback to the Geolocation objects.
+ void makeAsynchronousCallbackToGeolocation(WebCore::String origin, bool allow);
+ void timerFired(WebCore::Timer<GeolocationPermissions>* timer);
+
+ // Calls back to the Geolocation objects in all frames from the
+ // specified origin. There may be no such objects, as the frames using
+ // Geolocation from the specified origin may no longer use Geolocation,
+ // or may have been navigated to a different origin..
+ void maybeCallbackFrames(WebCore::String origin, bool allow);
+
+ // Cancels pending permission requests for the specified origin in
+ // other main frames (ie browser tabs). This is used when the user
+ // specifies permission to be remembered.
+ static void cancelPendingRequestsInOtherTabs(WebCore::String origin);
+ void cancelPendingRequests(WebCore::String origin);
+
+ WebViewCore* m_webViewCore;
+ WebCore::Frame* m_mainFrame;
+ WebCore::String m_originInProgress;
+ typedef Vector<WebCore::String> OriginVector;
+ OriginVector m_queuedOrigins;
+
+ typedef WTF::HashMap<WebCore::String, bool> PermissionsMap;
+ PermissionsMap m_temporaryPermissions;
+ static PermissionsMap s_permanentPermissions;
+
+ typedef WTF::Vector<GeolocationPermissions*> GeolocationPermissionsVector;
+ static GeolocationPermissionsVector s_instances;
+
+ WebCore::Timer<GeolocationPermissions> m_timer;
+
+ struct CallbackData {
+ WebCore::String origin;
+ bool allow;
+ };
+ CallbackData m_callbackData;
+
+ };
+
+} // namespace android
+
+#endif
diff --git a/WebKit/android/jni/WebCoreFrameBridge.cpp b/WebKit/android/jni/WebCoreFrameBridge.cpp
index 46e1fdc..b856e10 100644
--- a/WebKit/android/jni/WebCoreFrameBridge.cpp
+++ b/WebKit/android/jni/WebCoreFrameBridge.cpp
@@ -426,6 +426,16 @@ WebFrame::loadStarted(WebCore::Frame* frame)
env->DeleteLocalRef(urlStr);
if (favicon)
env->DeleteLocalRef(favicon);
+
+ // Inform the client that the main frame has started a new load.
+ if (isMainFrame && mPage) {
+ Chrome* chrome = mPage->chrome();
+ if (chrome) {
+ ChromeClientAndroid* client = static_cast<ChromeClientAndroid*>(chrome->client());
+ if (client)
+ client->onMainFrameLoadStarted();
+ }
+ }
}
void
@@ -1358,4 +1368,3 @@ int register_webframe(JNIEnv* env)
}
} /* namespace android */
-
diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp
index f46759a..0bcb80b 100644
--- a/WebKit/android/jni/WebViewCore.cpp
+++ b/WebKit/android/jni/WebViewCore.cpp
@@ -1950,6 +1950,15 @@ void WebViewCore::reachedMaxAppCacheSize(const unsigned long long spaceNeeded)
env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_reachedMaxAppCacheSize, spaceNeeded);
checkException(env);
#endif
+
+void WebViewCore::geolocationPermissionsShowPrompt(const WebCore::String& origin)
+{
+ // FIXME: Implement.
+}
+
+void WebViewCore::geolocationPermissionsHidePrompt()
+{
+ // FIXME: Implement.
}
bool WebViewCore::jsConfirm(const WebCore::String& url, const WebCore::String& text)
diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h
index 8fbe934..c47be86 100644
--- a/WebKit/android/jni/WebViewCore.h
+++ b/WebKit/android/jni/WebViewCore.h
@@ -199,6 +199,18 @@ namespace android {
*/
void reachedMaxAppCacheSize(const unsigned long long spaceNeeded);
+ /**
+ * Instruct the browser to show a Geolocation permission prompt for the
+ * specified origin.
+ * @param origin The origin of the frame requesting Geolocation
+ * permissions.
+ */
+ void geolocationPermissionsShowPrompt(const WebCore::String& origin);
+ /**
+ * Instruct the browser to hide the Geolocation permission prompt.
+ */
+ void geolocationPermissionsHidePrompt();
+
void addMessageToConsole(const String& message, unsigned int lineNumber, const String& sourceID);
//