279 lines
10 KiB
Java
279 lines
10 KiB
Java
|
/*
|
||
|
* Copyright (C) 2009 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
package android.webkit;
|
||
|
|
||
|
import android.os.Handler;
|
||
|
import android.os.Message;
|
||
|
import android.util.Log;
|
||
|
import java.util.HashMap;
|
||
|
import java.util.HashSet;
|
||
|
import java.util.Map;
|
||
|
import java.util.Set;
|
||
|
import java.util.Vector;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* This class is used to get Geolocation permissions from, and set them on the
|
||
|
* WebView. For example, it could be used to allow a user to manage Geolocation
|
||
|
* permissions from a browser's UI.
|
||
|
*
|
||
|
* Permissions are managed on a per-origin basis, as required by the
|
||
|
* Geolocation spec - http://dev.w3.org/geo/api/spec-source.html. An origin
|
||
|
* specifies the scheme, host and port of particular frame. An origin is
|
||
|
* represented here as a string, using the output of
|
||
|
* WebCore::SecurityOrigin::toString.
|
||
|
*
|
||
|
* This class is the Java counterpart of the WebKit C++ GeolocationPermissions
|
||
|
* class. It simply marshalls calls from the UI thread to the WebKit thread.
|
||
|
*
|
||
|
* Within WebKit, Geolocation permissions may be applied either temporarily
|
||
|
* (for the duration of the page) or permanently. This class deals only with
|
||
|
* permanent permissions.
|
||
|
*/
|
||
|
public final class GeolocationPermissions {
|
||
|
/**
|
||
|
* Callback interface used by the browser to report a Geolocation permission
|
||
|
* state set by the user in response to a permissions prompt.
|
||
|
*/
|
||
|
public interface Callback {
|
||
|
public void invoke(String origin, boolean allow, boolean remember);
|
||
|
};
|
||
|
|
||
|
// Log tag
|
||
|
private static final String TAG = "geolocationPermissions";
|
||
|
|
||
|
// Global instance
|
||
|
private static GeolocationPermissions sInstance;
|
||
|
|
||
|
private Handler mHandler;
|
||
|
private Handler mUIHandler;
|
||
|
|
||
|
// A queue to store messages until the handler is ready.
|
||
|
private Vector<Message> mQueuedMessages;
|
||
|
|
||
|
// Message ids
|
||
|
static final int GET_ORIGINS = 0;
|
||
|
static final int GET_ALLOWED = 1;
|
||
|
static final int CLEAR = 2;
|
||
|
static final int ALLOW = 3;
|
||
|
static final int CLEAR_ALL = 4;
|
||
|
|
||
|
// Message ids on the UI thread
|
||
|
static final int RETURN_ORIGINS = 0;
|
||
|
static final int RETURN_ALLOWED = 1;
|
||
|
|
||
|
private static final String ORIGINS = "origins";
|
||
|
private static final String ORIGIN = "origin";
|
||
|
private static final String CALLBACK = "callback";
|
||
|
private static final String ALLOWED = "allowed";
|
||
|
|
||
|
/**
|
||
|
* Gets the singleton instance of the class.
|
||
|
*/
|
||
|
public static GeolocationPermissions getInstance() {
|
||
|
if (sInstance == null) {
|
||
|
sInstance = new GeolocationPermissions();
|
||
|
}
|
||
|
return sInstance;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates the UI message handler. Must be called on the UI thread.
|
||
|
* @hide
|
||
|
*/
|
||
|
public void createUIHandler() {
|
||
|
if (mUIHandler == null) {
|
||
|
mUIHandler = new Handler() {
|
||
|
@Override
|
||
|
public void handleMessage(Message msg) {
|
||
|
// Runs on the UI thread.
|
||
|
switch (msg.what) {
|
||
|
case RETURN_ORIGINS: {
|
||
|
Map values = (Map) msg.obj;
|
||
|
Set<String> origins = (Set<String>) values.get(ORIGINS);
|
||
|
ValueCallback<Set<String> > callback = (ValueCallback<Set<String> >) values.get(CALLBACK);
|
||
|
callback.onReceiveValue(origins);
|
||
|
} break;
|
||
|
case RETURN_ALLOWED: {
|
||
|
Map values = (Map) msg.obj;
|
||
|
Boolean allowed = (Boolean) values.get(ALLOWED);
|
||
|
ValueCallback<Boolean> callback = (ValueCallback<Boolean>) values.get(CALLBACK);
|
||
|
callback.onReceiveValue(allowed);
|
||
|
} break;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates the message handler. Must be called on the WebKit thread.
|
||
|
* @hide
|
||
|
*/
|
||
|
public synchronized void createHandler() {
|
||
|
if (mHandler == null) {
|
||
|
mHandler = new Handler() {
|
||
|
@Override
|
||
|
public void handleMessage(Message msg) {
|
||
|
// Runs on the WebKit thread.
|
||
|
switch (msg.what) {
|
||
|
case GET_ORIGINS: {
|
||
|
Set origins = nativeGetOrigins();
|
||
|
ValueCallback callback = (ValueCallback) msg.obj;
|
||
|
Map values = new HashMap<String, Object>();
|
||
|
values.put(CALLBACK, callback);
|
||
|
values.put(ORIGINS, origins);
|
||
|
postUIMessage(Message.obtain(null, RETURN_ORIGINS, values));
|
||
|
} break;
|
||
|
case GET_ALLOWED: {
|
||
|
Map values = (Map) msg.obj;
|
||
|
String origin = (String) values.get(ORIGIN);
|
||
|
ValueCallback callback = (ValueCallback) values.get(CALLBACK);
|
||
|
boolean allowed = nativeGetAllowed(origin);
|
||
|
Map retValues = new HashMap<String, Object>();
|
||
|
retValues.put(CALLBACK, callback);
|
||
|
retValues.put(ALLOWED, new Boolean(allowed));
|
||
|
postUIMessage(Message.obtain(null, RETURN_ALLOWED, retValues));
|
||
|
} break;
|
||
|
case CLEAR:
|
||
|
nativeClear((String) msg.obj);
|
||
|
break;
|
||
|
case ALLOW:
|
||
|
nativeAllow((String) msg.obj);
|
||
|
break;
|
||
|
case CLEAR_ALL:
|
||
|
nativeClearAll();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Handle the queued messages
|
||
|
if (mQueuedMessages != null) {
|
||
|
while (!mQueuedMessages.isEmpty()) {
|
||
|
mHandler.sendMessage(mQueuedMessages.remove(0));
|
||
|
}
|
||
|
mQueuedMessages = null;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Utility function to send a message to our handler.
|
||
|
*/
|
||
|
private synchronized void postMessage(Message msg) {
|
||
|
if (mHandler == null) {
|
||
|
if (mQueuedMessages == null) {
|
||
|
mQueuedMessages = new Vector<Message>();
|
||
|
}
|
||
|
mQueuedMessages.add(msg);
|
||
|
} else {
|
||
|
mHandler.sendMessage(msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Utility function to send a message to the handler on the UI thread
|
||
|
*/
|
||
|
private void postUIMessage(Message msg) {
|
||
|
if (mUIHandler != null) {
|
||
|
mUIHandler.sendMessage(msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the set of origins for which Geolocation permissions are stored.
|
||
|
* Note that we represent the origins as strings. These are created using
|
||
|
* WebCore::SecurityOrigin::toString(). As long as all 'HTML 5 modules'
|
||
|
* (Database, Geolocation etc) do so, it's safe to match up origins based
|
||
|
* on this string.
|
||
|
*
|
||
|
* Callback is a ValueCallback object whose onReceiveValue method will be
|
||
|
* called asynchronously with the set of origins.
|
||
|
*/
|
||
|
public void getOrigins(ValueCallback<Set<String> > callback) {
|
||
|
if (callback != null) {
|
||
|
if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
|
||
|
Set origins = nativeGetOrigins();
|
||
|
callback.onReceiveValue(origins);
|
||
|
} else {
|
||
|
postMessage(Message.obtain(null, GET_ORIGINS, callback));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the permission state for the specified origin.
|
||
|
*
|
||
|
* Callback is a ValueCallback object whose onReceiveValue method will be
|
||
|
* called asynchronously with the permission state for the origin.
|
||
|
*/
|
||
|
public void getAllowed(String origin, ValueCallback<Boolean> callback) {
|
||
|
if (callback == null) {
|
||
|
return;
|
||
|
}
|
||
|
if (origin == null) {
|
||
|
callback.onReceiveValue(null);
|
||
|
return;
|
||
|
}
|
||
|
if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
|
||
|
boolean allowed = nativeGetAllowed(origin);
|
||
|
callback.onReceiveValue(new Boolean(allowed));
|
||
|
} else {
|
||
|
Map values = new HashMap<String, Object>();
|
||
|
values.put(ORIGIN, origin);
|
||
|
values.put(CALLBACK, callback);
|
||
|
postMessage(Message.obtain(null, GET_ALLOWED, values));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Clears the permission state for the specified origin. This method may be
|
||
|
* called before the WebKit thread has intialized the message handler.
|
||
|
* Messages will be queued until this time.
|
||
|
*/
|
||
|
public void clear(String origin) {
|
||
|
// Called on the UI thread.
|
||
|
postMessage(Message.obtain(null, CLEAR, origin));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Allows the specified origin. This method may be called before the WebKit
|
||
|
* thread has intialized the message handler. Messages will be queued until
|
||
|
* this time.
|
||
|
*/
|
||
|
public void allow(String origin) {
|
||
|
// Called on the UI thread.
|
||
|
postMessage(Message.obtain(null, ALLOW, origin));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Clears the permission state for all origins.
|
||
|
*/
|
||
|
public void clearAll() {
|
||
|
// Called on the UI thread.
|
||
|
postMessage(Message.obtain(null, CLEAR_ALL));
|
||
|
}
|
||
|
|
||
|
// Native functions, run on the WebKit thread.
|
||
|
private static native Set nativeGetOrigins();
|
||
|
private static native boolean nativeGetAllowed(String origin);
|
||
|
private static native void nativeClear(String origin);
|
||
|
private static native void nativeAllow(String origin);
|
||
|
private static native void nativeClearAll();
|
||
|
}
|