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