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