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