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