GeolocationPermissions.java revision 4faee09c422a70439129e9fb40dd82f03d42c98d
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.concurrent.locks.Condition; 23import java.util.concurrent.locks.Lock; 24import java.util.concurrent.locks.ReentrantLock; 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 50 // Members used to transfer the origins and permissions between threads. 51 private Set<String> mOrigins; 52 private boolean mAllowed; 53 private static Lock mLock = new ReentrantLock(); 54 private static boolean mUpdated; 55 private static Condition mUpdatedCondition = mLock.newCondition(); 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 CLEAR_ALL = 3; 62 63 /** 64 * Gets the singleton instance of the class. 65 */ 66 public static GeolocationPermissions getInstance() { 67 if (sInstance == null) { 68 sInstance = new GeolocationPermissions(); 69 } 70 return sInstance; 71 } 72 73 /** 74 * Creates the message handler. Must be called on the WebKit thread. 75 */ 76 public void createHandler() { 77 if (mHandler == null) { 78 mHandler = new Handler() { 79 @Override 80 public void handleMessage(Message msg) { 81 // Runs on the WebKit thread. 82 switch (msg.what) { 83 case GET_ORIGINS: 84 getOriginsImpl(); 85 break; 86 case GET_ALLOWED: 87 getAllowedImpl((String) msg.obj); 88 break; 89 case CLEAR: 90 nativeClear((String) msg.obj); 91 break; 92 case CLEAR_ALL: 93 nativeClearAll(); 94 break; 95 } 96 } 97 }; 98 } 99 } 100 101 /** 102 * Utility function to send a message to our handler. 103 */ 104 private void postMessage(Message msg) { 105 assert(mHandler != null); 106 mHandler.sendMessage(msg); 107 } 108 109 /** 110 * Gets the set of origins for which Geolocation permissions are stored. 111 * Note that we represent the origins as strings. These are created using 112 * WebCore::SecurityOrigin::toString(). As long as all 'HTML 5 modules' 113 * (Database, Geolocation etc) do so, it's safe to match up origins for the 114 * purposes of displaying UI. 115 */ 116 public Set getOrigins() { 117 // Called on the UI thread. 118 Set origins = null; 119 mLock.lock(); 120 try { 121 mUpdated = false; 122 postMessage(Message.obtain(null, GET_ORIGINS)); 123 while (!mUpdated) { 124 mUpdatedCondition.await(); 125 } 126 origins = mOrigins; 127 } catch (InterruptedException e) { 128 Log.e(TAG, "Exception while waiting for update", e); 129 } finally { 130 mLock.unlock(); 131 } 132 return origins; 133 } 134 135 /** 136 * Helper method to get the set of origins. 137 */ 138 private void getOriginsImpl() { 139 // Called on the WebKit thread. 140 mLock.lock(); 141 mOrigins = nativeGetOrigins(); 142 mUpdated = true; 143 mUpdatedCondition.signal(); 144 mLock.unlock(); 145 } 146 147 /** 148 * Gets the permission state for the specified origin. 149 */ 150 public boolean getAllowed(String origin) { 151 // Called on the UI thread. 152 boolean allowed = false; 153 mLock.lock(); 154 try { 155 mUpdated = false; 156 postMessage(Message.obtain(null, GET_ALLOWED, origin)); 157 while (!mUpdated) { 158 mUpdatedCondition.await(); 159 } 160 allowed = mAllowed; 161 } catch (InterruptedException e) { 162 Log.e(TAG, "Exception while waiting for update", e); 163 } finally { 164 mLock.unlock(); 165 } 166 return allowed; 167 } 168 169 /** 170 * Helper method to get the permission state. 171 */ 172 private void getAllowedImpl(String origin) { 173 // Called on the WebKit thread. 174 mLock.lock(); 175 mAllowed = nativeGetAllowed(origin); 176 mUpdated = true; 177 mUpdatedCondition.signal(); 178 mLock.unlock(); 179 } 180 181 /** 182 * Clears the permission state for the specified origin. 183 */ 184 public void clear(String origin) { 185 // Called on the UI thread. 186 postMessage(Message.obtain(null, CLEAR, origin)); 187 } 188 189 /** 190 * Clears the permission state for all origins. 191 */ 192 public void clearAll() { 193 // Called on the UI thread. 194 postMessage(Message.obtain(null, CLEAR_ALL)); 195 } 196 197 // Native functions, run on the WebKit thread. 198 private static native Set nativeGetOrigins(); 199 private static native boolean nativeGetAllowed(String origin); 200 private static native void nativeClear(String origin); 201 private static native void nativeClearAll(); 202} 203