GeolocationPermissions.java revision 0691ad50ca6b7a2968a0b95e1e9bb7228dd47d65
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 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 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 17package android.webkit; 18 19import android.os.Handler; 20import android.os.Message; 21import android.util.Log; 22import java.util.HashMap; 23import java.util.HashSet; 24import java.util.Map; 25import java.util.Set; 26 27 28/** 29 * Implements the Java side of GeolocationPermissions. Simply marshalls calls 30 * from the UI thread to the WebKit thread. 31 */ 32public final class GeolocationPermissions { 33 /** 34 * Callback interface used by the browser to report a Geolocation permission 35 * state set by the user in response to a permissions prompt. 36 */ 37 public interface Callback { 38 public void invoke(String origin, boolean allow, boolean remember); 39 }; 40 41 // Log tag 42 private static final String TAG = "geolocationPermissions"; 43 44 // Global instance 45 private static GeolocationPermissions sInstance; 46 47 private Handler mHandler; 48 private Handler mUIHandler; 49 50 // Members used to transfer the origins and permissions between threads. 51 private Set<String> mOrigins; 52 private boolean mAllowed; 53 private Set<String> mOriginsToClear; 54 private Set<String> mOriginsToAllow; 55 56 // Message ids 57 static final int GET_ORIGINS = 0; 58 static final int GET_ALLOWED = 1; 59 static final int CLEAR = 2; 60 static final int ALLOW = 3; 61 static final int CLEAR_ALL = 4; 62 63 // Message ids on the UI thread 64 static final int RETURN_ORIGINS = 0; 65 static final int RETURN_ALLOWED = 1; 66 67 private static final String ORIGINS = "origins"; 68 private static final String ORIGIN = "origin"; 69 private static final String CALLBACK = "callback"; 70 private static final String ALLOWED = "allowed"; 71 72 /** 73 * Gets the singleton instance of the class. 74 */ 75 public static GeolocationPermissions getInstance() { 76 if (sInstance == null) { 77 sInstance = new GeolocationPermissions(); 78 } 79 return sInstance; 80 } 81 82 /** 83 * Creates the UI message handler. Must be called on the UI thread. 84 * @hide 85 */ 86 public void createUIHandler() { 87 if (mUIHandler == null) { 88 mUIHandler = new Handler() { 89 @Override 90 public void handleMessage(Message msg) { 91 // Runs on the UI thread. 92 switch (msg.what) { 93 case RETURN_ORIGINS: { 94 Map values = (Map) msg.obj; 95 Set origins = (Set) values.get(ORIGINS); 96 ValueCallback<Set> callback = (ValueCallback<Set>) values.get(CALLBACK); 97 callback.onReceiveValue(origins); 98 } break; 99 case RETURN_ALLOWED: { 100 Map values = (Map) msg.obj; 101 Boolean allowed = (Boolean) values.get(ALLOWED); 102 ValueCallback<Boolean> callback = (ValueCallback<Boolean>) values.get(CALLBACK); 103 callback.onReceiveValue(allowed); 104 } break; 105 } 106 } 107 }; 108 } 109 } 110 111 /** 112 * Creates the message handler. Must be called on the WebKit thread. 113 * @hide 114 */ 115 public void createHandler() { 116 if (mHandler == null) { 117 mHandler = new Handler() { 118 @Override 119 public void handleMessage(Message msg) { 120 // Runs on the WebKit thread. 121 switch (msg.what) { 122 case GET_ORIGINS: { 123 getOriginsImpl(); 124 ValueCallback callback = (ValueCallback) msg.obj; 125 Set origins = new HashSet(mOrigins); 126 Map values = new HashMap<String, Object>(); 127 values.put(CALLBACK, callback); 128 values.put(ORIGINS, origins); 129 postUIMessage(Message.obtain(null, RETURN_ORIGINS, values)); 130 } break; 131 case GET_ALLOWED: { 132 Map values = (Map) msg.obj; 133 String origin = (String) values.get(ORIGIN); 134 ValueCallback callback = (ValueCallback) values.get(CALLBACK); 135 getAllowedImpl(origin); 136 Map retValues = new HashMap<String, Object>(); 137 retValues.put(CALLBACK, callback); 138 retValues.put(ALLOWED, new Boolean(mAllowed)); 139 postUIMessage(Message.obtain(null, RETURN_ALLOWED, retValues)); 140 } break; 141 case CLEAR: 142 nativeClear((String) msg.obj); 143 break; 144 case ALLOW: 145 nativeAllow((String) msg.obj); 146 break; 147 case CLEAR_ALL: 148 nativeClearAll(); 149 break; 150 } 151 } 152 }; 153 154 if (mOriginsToClear != null) { 155 for (String origin : mOriginsToClear) { 156 nativeClear(origin); 157 } 158 } 159 if (mOriginsToAllow != null) { 160 for (String origin : mOriginsToAllow) { 161 nativeAllow(origin); 162 } 163 } 164 } 165 } 166 167 /** 168 * Utility function to send a message to our handler. 169 */ 170 private void postMessage(Message msg) { 171 assert(mHandler != null); 172 mHandler.sendMessage(msg); 173 } 174 175 /** 176 * Utility function to send a message to the handler on the UI thread 177 */ 178 private void postUIMessage(Message msg) { 179 if (mUIHandler != null) { 180 mUIHandler.sendMessage(msg); 181 } 182 } 183 184 /** 185 * Gets the set of origins for which Geolocation permissions are stored. 186 * Note that we represent the origins as strings. These are created using 187 * WebCore::SecurityOrigin::toString(). As long as all 'HTML 5 modules' 188 * (Database, Geolocation etc) do so, it's safe to match up origins for the 189 * purposes of displaying UI. 190 */ 191 public void getOrigins(ValueCallback<Set> callback) { 192 if (callback != null) { 193 if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { 194 getOriginsImpl(); 195 Set origins = new HashSet(mOrigins); 196 callback.onReceiveValue(origins); 197 } else { 198 postMessage(Message.obtain(null, GET_ORIGINS, callback)); 199 } 200 } 201 } 202 203 /** 204 * Helper method to get the set of origins. 205 */ 206 private void getOriginsImpl() { 207 // Called on the WebKit thread. 208 mOrigins = nativeGetOrigins(); 209 } 210 211 /** 212 * Gets the permission state for the specified origin. 213 */ 214 public void getAllowed(String origin, ValueCallback<Boolean> callback) { 215 if (callback == null) { 216 return; 217 } 218 if (origin == null) { 219 callback.onReceiveValue(null); 220 return; 221 } 222 if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) { 223 getAllowedImpl(origin); 224 callback.onReceiveValue(new Boolean(mAllowed)); 225 } else { 226 Map values = new HashMap<String, Object>(); 227 values.put(ORIGIN, origin); 228 values.put(CALLBACK, callback); 229 postMessage(Message.obtain(null, GET_ALLOWED, values)); 230 } 231 } 232 233 /** 234 * Helper method to get the permission state. 235 */ 236 private void getAllowedImpl(String origin) { 237 // Called on the WebKit thread. 238 mAllowed = nativeGetAllowed(origin); 239 } 240 241 /** 242 * Clears the permission state for the specified origin. This method may be 243 * called before the WebKit thread has intialized the message handler. 244 * Messages will be queued until this time. 245 */ 246 public void clear(String origin) { 247 // Called on the UI thread. 248 if (mHandler == null) { 249 if (mOriginsToClear == null) { 250 mOriginsToClear = new HashSet<String>(); 251 } 252 mOriginsToClear.add(origin); 253 if (mOriginsToAllow != null) { 254 mOriginsToAllow.remove(origin); 255 } 256 } else { 257 postMessage(Message.obtain(null, CLEAR, origin)); 258 } 259 } 260 261 /** 262 * Allows the specified origin. This method may be called before the WebKit 263 * thread has intialized the message handler. Messages will be queued until 264 * this time. 265 */ 266 public void allow(String origin) { 267 // Called on the UI thread. 268 if (mHandler == null) { 269 if (mOriginsToAllow == null) { 270 mOriginsToAllow = new HashSet<String>(); 271 } 272 mOriginsToAllow.add(origin); 273 if (mOriginsToClear != null) { 274 mOriginsToClear.remove(origin); 275 } 276 } else { 277 postMessage(Message.obtain(null, ALLOW, origin)); 278 } 279 } 280 281 /** 282 * Clears the permission state for all origins. 283 */ 284 public void clearAll() { 285 // Called on the UI thread. 286 postMessage(Message.obtain(null, CLEAR_ALL)); 287 } 288 289 // Native functions, run on the WebKit thread. 290 private static native Set nativeGetOrigins(); 291 private static native boolean nativeGetAllowed(String origin); 292 private static native void nativeClear(String origin); 293 private static native void nativeAllow(String origin); 294 private static native void nativeClearAll(); 295} 296