2 * Copyright (C) 2009 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package android.webkit;
19 import android.os.Handler;
20 import android.os.Message;
21 import android.util.Log;
22 import java.util.HashMap;
23 import java.util.HashSet;
26 import java.util.Vector;
30 * This class is used to get Geolocation permissions from, and set them on the
31 * WebView. For example, it could be used to allow a user to manage Geolocation
32 * permissions from a browser's UI.
34 * Permissions are managed on a per-origin basis, as required by the
35 * Geolocation spec - http://dev.w3.org/geo/api/spec-source.html. An origin
36 * specifies the scheme, host and port of particular frame. An origin is
37 * represented here as a string, using the output of
38 * WebCore::SecurityOrigin::toString.
40 * This class is the Java counterpart of the WebKit C++ GeolocationPermissions
41 * class. It simply marshalls calls from the UI thread to the WebKit thread.
43 * Within WebKit, Geolocation permissions may be applied either temporarily
44 * (for the duration of the page) or permanently. This class deals only with
45 * permanent permissions.
47 public final class GeolocationPermissions {
49 * Callback interface used by the browser to report a Geolocation permission
50 * state set by the user in response to a permissions prompt.
52 public interface Callback {
53 public void invoke(String origin, boolean allow, boolean remember);
57 private static final String TAG = "geolocationPermissions";
60 private static GeolocationPermissions sInstance;
62 private Handler mHandler;
63 private Handler mUIHandler;
65 // A queue to store messages until the handler is ready.
66 private Vector<Message> mQueuedMessages;
69 static final int GET_ORIGINS = 0;
70 static final int GET_ALLOWED = 1;
71 static final int CLEAR = 2;
72 static final int ALLOW = 3;
73 static final int CLEAR_ALL = 4;
75 // Message ids on the UI thread
76 static final int RETURN_ORIGINS = 0;
77 static final int RETURN_ALLOWED = 1;
79 private static final String ORIGINS = "origins";
80 private static final String ORIGIN = "origin";
81 private static final String CALLBACK = "callback";
82 private static final String ALLOWED = "allowed";
85 * Gets the singleton instance of the class.
87 public static GeolocationPermissions getInstance() {
88 if (sInstance == null) {
89 sInstance = new GeolocationPermissions();
95 * Creates the UI message handler. Must be called on the UI thread.
98 public void createUIHandler() {
99 if (mUIHandler == null) {
100 mUIHandler = new Handler() {
102 public void handleMessage(Message msg) {
103 // Runs on the UI thread.
105 case RETURN_ORIGINS: {
106 Map values = (Map) msg.obj;
107 Set<String> origins = (Set<String>) values.get(ORIGINS);
108 ValueCallback<Set<String> > callback = (ValueCallback<Set<String> >) values.get(CALLBACK);
109 callback.onReceiveValue(origins);
111 case RETURN_ALLOWED: {
112 Map values = (Map) msg.obj;
113 Boolean allowed = (Boolean) values.get(ALLOWED);
114 ValueCallback<Boolean> callback = (ValueCallback<Boolean>) values.get(CALLBACK);
115 callback.onReceiveValue(allowed);
124 * Creates the message handler. Must be called on the WebKit thread.
127 public synchronized void createHandler() {
128 if (mHandler == null) {
129 mHandler = new Handler() {
131 public void handleMessage(Message msg) {
132 // Runs on the WebKit thread.
135 Set origins = nativeGetOrigins();
136 ValueCallback callback = (ValueCallback) msg.obj;
137 Map values = new HashMap<String, Object>();
138 values.put(CALLBACK, callback);
139 values.put(ORIGINS, origins);
140 postUIMessage(Message.obtain(null, RETURN_ORIGINS, values));
143 Map values = (Map) msg.obj;
144 String origin = (String) values.get(ORIGIN);
145 ValueCallback callback = (ValueCallback) values.get(CALLBACK);
146 boolean allowed = nativeGetAllowed(origin);
147 Map retValues = new HashMap<String, Object>();
148 retValues.put(CALLBACK, callback);
149 retValues.put(ALLOWED, new Boolean(allowed));
150 postUIMessage(Message.obtain(null, RETURN_ALLOWED, retValues));
153 nativeClear((String) msg.obj);
156 nativeAllow((String) msg.obj);
165 // Handle the queued messages
166 if (mQueuedMessages != null) {
167 while (!mQueuedMessages.isEmpty()) {
168 mHandler.sendMessage(mQueuedMessages.remove(0));
170 mQueuedMessages = null;
176 * Utility function to send a message to our handler.
178 private synchronized void postMessage(Message msg) {
179 if (mHandler == null) {
180 if (mQueuedMessages == null) {
181 mQueuedMessages = new Vector<Message>();
183 mQueuedMessages.add(msg);
185 mHandler.sendMessage(msg);
190 * Utility function to send a message to the handler on the UI thread
192 private void postUIMessage(Message msg) {
193 if (mUIHandler != null) {
194 mUIHandler.sendMessage(msg);
199 * Gets the set of origins for which Geolocation permissions are stored.
200 * Note that we represent the origins as strings. These are created using
201 * WebCore::SecurityOrigin::toString(). As long as all 'HTML 5 modules'
202 * (Database, Geolocation etc) do so, it's safe to match up origins based
205 * Callback is a ValueCallback object whose onReceiveValue method will be
206 * called asynchronously with the set of origins.
208 public void getOrigins(ValueCallback<Set<String> > callback) {
209 if (callback != null) {
210 if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
211 Set origins = nativeGetOrigins();
212 callback.onReceiveValue(origins);
214 postMessage(Message.obtain(null, GET_ORIGINS, callback));
220 * Gets the permission state for the specified origin.
222 * Callback is a ValueCallback object whose onReceiveValue method will be
223 * called asynchronously with the permission state for the origin.
225 public void getAllowed(String origin, ValueCallback<Boolean> callback) {
226 if (callback == null) {
229 if (origin == null) {
230 callback.onReceiveValue(null);
233 if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
234 boolean allowed = nativeGetAllowed(origin);
235 callback.onReceiveValue(new Boolean(allowed));
237 Map values = new HashMap<String, Object>();
238 values.put(ORIGIN, origin);
239 values.put(CALLBACK, callback);
240 postMessage(Message.obtain(null, GET_ALLOWED, values));
245 * Clears the permission state for the specified origin. This method may be
246 * called before the WebKit thread has intialized the message handler.
247 * Messages will be queued until this time.
249 public void clear(String origin) {
250 // Called on the UI thread.
251 postMessage(Message.obtain(null, CLEAR, origin));
255 * Allows the specified origin. This method may be called before the WebKit
256 * thread has intialized the message handler. Messages will be queued until
259 public void allow(String origin) {
260 // Called on the UI thread.
261 postMessage(Message.obtain(null, ALLOW, origin));
265 * Clears the permission state for all origins.
267 public void clearAll() {
268 // Called on the UI thread.
269 postMessage(Message.obtain(null, CLEAR_ALL));
272 // Native functions, run on the WebKit thread.
273 private static native Set nativeGetOrigins();
274 private static native boolean nativeGetAllowed(String origin);
275 private static native void nativeClear(String origin);
276 private static native void nativeAllow(String origin);
277 private static native void nativeClearAll();