diff options
-rw-r--r-- | WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp | 6 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/ChromeClientAndroid.h | 2 | ||||
-rwxr-xr-x | WebKit/android/WebCoreSupport/GeolocationPermissions.cpp | 108 | ||||
-rw-r--r--[-rwxr-xr-x] | WebKit/android/WebCoreSupport/GeolocationPermissions.h | 11 |
4 files changed, 93 insertions, 34 deletions
diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp index 9102395..e9e77e9 100644 --- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp +++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp @@ -479,6 +479,12 @@ void ChromeClientAndroid::requestGeolocationPermissionForFrame(Frame* frame, Geo m_geolocationPermissions->queryPermissionState(frame); } +void ChromeClientAndroid::cancelGeolocationPermissionRequestForFrame(Frame* frame) +{ + if (m_geolocationPermissions) + m_geolocationPermissions->cancelPermissionStateQuery(frame); +} + void ChromeClientAndroid::provideGeolocationPermissions(const String &origin, bool allow, bool remember) { ASSERT(m_geolocationPermissions); diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h index 15473ca..2c061b2 100644 --- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h +++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h @@ -143,7 +143,7 @@ namespace android { // Methods used to request and provide Geolocation permissions. virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*); - virtual void cancelGeolocationPermissionRequestForFrame(Frame*) { } + virtual void cancelGeolocationPermissionRequestForFrame(Frame*); // Android-specific void provideGeolocationPermissions(const String &origin, bool allow, bool remember); void storeGeolocationPermissions(); diff --git a/WebKit/android/WebCoreSupport/GeolocationPermissions.cpp b/WebKit/android/WebCoreSupport/GeolocationPermissions.cpp index aeee017..b630f66 100755 --- a/WebKit/android/WebCoreSupport/GeolocationPermissions.cpp +++ b/WebKit/android/WebCoreSupport/GeolocationPermissions.cpp @@ -100,21 +100,56 @@ void GeolocationPermissions::queryPermissionState(Frame* frame) } // If there's no pending request, prompt the user. - if (m_originInProgress.isEmpty()) { - m_originInProgress = originString; - + if (nextOriginInQueue().isEmpty()) { // 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; + m_webViewCore->geolocationPermissionsShowPrompt(originString); } - // If the request in progress is not for this origin, queue this request. - if ((m_originInProgress != originString) - && (m_queuedOrigins.find(originString) == WTF::notFound)) + // Add this request to the queue so we can track which frames requested it. + if (m_queuedOrigins.find(originString) == WTF::notFound) { m_queuedOrigins.append(originString); + FrameSet frameSet; + frameSet.add(frame); + m_queuedOriginsToFramesMap.add(originString, frameSet); + } else { + ASSERT(m_queuedOriginsToFramesMap.contains(originString)); + m_queuedOriginsToFramesMap.find(originString)->second.add(frame); + } +} + +void GeolocationPermissions::cancelPermissionStateQuery(WebCore::Frame* frame) +{ + // We cancel any queued request for the given frame. There can be at most + // one of these, since each frame maps to a single origin. We only cancel + // the request if this frame is the only one reqesting permission for this + // origin. + // + // We can use the origin string to avoid searching the map. + String originString = frame->document()->securityOrigin()->toString(); + size_t index = m_queuedOrigins.find(originString); + if (index == WTF::notFound) + return; + + ASSERT(m_queuedOriginsToFramesMap.contains(originString)); + OriginToFramesMap::iterator iter = m_queuedOriginsToFramesMap.find(originString); + ASSERT(iter->second.contains(frame)); + iter->second.remove(frame); + if (!iter->second.isEmpty()) + return; + + m_queuedOrigins.remove(index); + m_queuedOriginsToFramesMap.remove(iter); + + // If this is the origin currently being shown, cancel the prompt + // and show the next in the queue, if present. + if (index == 0) { + m_webViewCore->geolocationPermissionsHidePrompt(); + if (!nextOriginInQueue().isEmpty()) + m_webViewCore->geolocationPermissionsShowPrompt(nextOriginInQueue()); + } } void GeolocationPermissions::makeAsynchronousCallbackToGeolocation(String origin, bool allow) @@ -133,38 +168,38 @@ void GeolocationPermissions::providePermissionState(String origin, bool allow, b // 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) + if (origin != nextOriginInQueue()) return; - maybeCallbackFrames(m_originInProgress, allow); + maybeCallbackFrames(origin, 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); + cancelPendingRequestsInOtherTabs(origin); - // Clear the origin in progress to signal that this request is done. - m_originInProgress = ""; + // Clear the origin from the queue. + ASSERT(!m_queuedOrigins.isEmpty()); + m_queuedOrigins.remove(0); + ASSERT(m_queuedOriginsToFramesMap.contains(origin)); + m_queuedOriginsToFramesMap.remove(origin); // 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); - } + if (!nextOriginInQueue().isEmpty()) + m_webViewCore->geolocationPermissionsShowPrompt(nextOriginInQueue()); } void GeolocationPermissions::recordPermissionState(String origin, bool allow, bool remember) { if (remember) { - s_permanentPermissions.set(m_originInProgress, allow); + s_permanentPermissions.set(origin, allow); s_permanentPermissionsModified = true; } 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); + m_temporaryPermissions.set(origin, allow); } } @@ -179,19 +214,22 @@ void GeolocationPermissions::cancelPendingRequestsInOtherTabs(String 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); -#ifndef NDEBUG - PermissionsMap::const_iterator end = s_permanentPermissions.end(); - ASSERT(iter != end); -#endif - bool allow = iter->second; - maybeCallbackFrames(origin, allow); + // Don't cancel the request if it's currently being shown, in which case + // it's at index 0. + if (index == WTF::notFound || !index) + return; - m_queuedOrigins.remove(index); - } + // Get the permission from the permanent list. + ASSERT(s_permanentPermissions.contains(origin)); + PermissionsMap::const_iterator iter = s_permanentPermissions.find(origin); + bool allow = iter->second; + + maybeCallbackFrames(origin, allow); + + m_queuedOrigins.remove(index); + ASSERT(m_queuedOriginsToFramesMap.contains(origin)); + m_queuedOriginsToFramesMap.remove(origin); } void GeolocationPermissions::timerFired(Timer<GeolocationPermissions>* timer) @@ -203,8 +241,8 @@ void GeolocationPermissions::timerFired(Timer<GeolocationPermissions>* timer) void GeolocationPermissions::resetTemporaryPermissionStates() { ASSERT(s_permanentPermissionsLoaded); - m_originInProgress = ""; m_queuedOrigins.clear(); + m_queuedOriginsToFramesMap.clear(); m_temporaryPermissions.clear(); // If any permission results are being marshalled back to this thread, this // will render them inefective. @@ -213,6 +251,12 @@ void GeolocationPermissions::resetTemporaryPermissionStates() m_webViewCore->geolocationPermissionsHidePrompt(); } +const WebCore::String& GeolocationPermissions::nextOriginInQueue() +{ + static const String emptyString = ""; + return m_queuedOrigins.isEmpty() ? emptyString : m_queuedOrigins[0]; +} + void GeolocationPermissions::maybeCallbackFrames(String origin, bool allow) { // We can't track which frame issued the request, as frames can be deleted diff --git a/WebKit/android/WebCoreSupport/GeolocationPermissions.h b/WebKit/android/WebCoreSupport/GeolocationPermissions.h index 33434b9..e59c11b 100755..100644 --- a/WebKit/android/WebCoreSupport/GeolocationPermissions.h +++ b/WebKit/android/WebCoreSupport/GeolocationPermissions.h @@ -74,6 +74,7 @@ namespace android { // the Geolocation objects in all frames in this WebView that are from // the same origin as the requesting frame. void queryPermissionState(WebCore::Frame* frame); + void cancelPermissionStateQuery(WebCore::Frame*); // Provides this object with a permission state set by the user. The // permission is specified by 'allow' and applied to 'origin'. If @@ -135,11 +136,19 @@ namespace android { static void maybeLoadPermanentPermissions(); + const WebCore::String& nextOriginInQueue(); + WebViewCore* m_webViewCore; WebCore::Frame* m_mainFrame; - WebCore::String m_originInProgress; + // A vector of the origins queued to make a permission request. + // The first in the vector is the origin currently making the request. typedef Vector<WebCore::String> OriginVector; OriginVector m_queuedOrigins; + // A map from a queued origin to the set of frames that have requested + // permission for that origin. + typedef HashSet<WebCore::Frame*> FrameSet; + typedef HashMap<WebCore::String, FrameSet> OriginToFramesMap; + OriginToFramesMap m_queuedOriginsToFramesMap; typedef WTF::HashMap<WebCore::String, bool> PermissionsMap; PermissionsMap m_temporaryPermissions; |