Home | History | Annotate | Download | only in webkit
      1 /*
      2  * Copyright (C) 2012 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 
     17 package android.webkit;
     18 
     19 import android.os.Handler;
     20 import android.os.Message;
     21 
     22 import java.util.HashMap;
     23 import java.util.Map;
     24 import java.util.Set;
     25 import java.util.Vector;
     26 
     27 // This class is the Java counterpart of the WebKit C++ GeolocationPermissions
     28 // class. It simply marshals calls from the UI thread to the WebKit thread.
     29 final class GeolocationPermissionsClassic extends GeolocationPermissions {
     30     private Handler mHandler;
     31     private Handler mUIHandler;
     32 
     33     // A queue to store messages until the handler is ready.
     34     private Vector<Message> mQueuedMessages;
     35 
     36     // Message ids
     37     static final int GET_ORIGINS = 0;
     38     static final int GET_ALLOWED = 1;
     39     static final int CLEAR = 2;
     40     static final int ALLOW = 3;
     41     static final int CLEAR_ALL = 4;
     42 
     43     // Message ids on the UI thread
     44     static final int RETURN_ORIGINS = 0;
     45     static final int RETURN_ALLOWED = 1;
     46 
     47     private static final String ORIGINS = "origins";
     48     private static final String ORIGIN = "origin";
     49     private static final String CALLBACK = "callback";
     50     private static final String ALLOWED = "allowed";
     51 
     52     // Global instance
     53     private static GeolocationPermissionsClassic sInstance;
     54 
     55     public static GeolocationPermissionsClassic getInstance() {
     56         if (sInstance == null) {
     57             sInstance = new GeolocationPermissionsClassic();
     58         }
     59         return sInstance;
     60       }
     61 
     62     /**
     63      * Creates the UI message handler. Must be called on the UI thread.
     64      * @hide
     65      */
     66     public void createUIHandler() {
     67         if (mUIHandler == null) {
     68             mUIHandler = new Handler() {
     69                 @Override
     70                 public void handleMessage(Message msg) {
     71                     // Runs on the UI thread.
     72                     switch (msg.what) {
     73                         case RETURN_ORIGINS: {
     74                             Map values = (Map) msg.obj;
     75                             Set<String> origins = (Set<String>) values.get(ORIGINS);
     76                             ValueCallback<Set<String> > callback = (ValueCallback<Set<String> >) values.get(CALLBACK);
     77                             callback.onReceiveValue(origins);
     78                         } break;
     79                         case RETURN_ALLOWED: {
     80                             Map values = (Map) msg.obj;
     81                             Boolean allowed = (Boolean) values.get(ALLOWED);
     82                             ValueCallback<Boolean> callback = (ValueCallback<Boolean>) values.get(CALLBACK);
     83                             callback.onReceiveValue(allowed);
     84                         } break;
     85                     }
     86                 }
     87             };
     88         }
     89     }
     90 
     91     /**
     92      * Creates the message handler. Must be called on the WebKit thread.
     93      * @hide
     94      */
     95     public synchronized void createHandler() {
     96         if (mHandler == null) {
     97             mHandler = new Handler() {
     98                 @Override
     99                 public void handleMessage(Message msg) {
    100                     // Runs on the WebKit thread.
    101                     switch (msg.what) {
    102                         case GET_ORIGINS: {
    103                             Set origins = nativeGetOrigins();
    104                             ValueCallback callback = (ValueCallback) msg.obj;
    105                             Map values = new HashMap<String, Object>();
    106                             values.put(CALLBACK, callback);
    107                             values.put(ORIGINS, origins);
    108                             postUIMessage(Message.obtain(null, RETURN_ORIGINS, values));
    109                             } break;
    110                         case GET_ALLOWED: {
    111                             Map values = (Map) msg.obj;
    112                             String origin = (String) values.get(ORIGIN);
    113                             ValueCallback callback = (ValueCallback) values.get(CALLBACK);
    114                             boolean allowed = nativeGetAllowed(origin);
    115                             Map retValues = new HashMap<String, Object>();
    116                             retValues.put(CALLBACK, callback);
    117                             retValues.put(ALLOWED, Boolean.valueOf(allowed));
    118                             postUIMessage(Message.obtain(null, RETURN_ALLOWED, retValues));
    119                             } break;
    120                         case CLEAR:
    121                             nativeClear((String) msg.obj);
    122                             break;
    123                         case ALLOW:
    124                             nativeAllow((String) msg.obj);
    125                             break;
    126                         case CLEAR_ALL:
    127                             nativeClearAll();
    128                             break;
    129                     }
    130                 }
    131             };
    132 
    133             // Handle the queued messages
    134             if (mQueuedMessages != null) {
    135                 while (!mQueuedMessages.isEmpty()) {
    136                     mHandler.sendMessage(mQueuedMessages.remove(0));
    137                 }
    138                 mQueuedMessages = null;
    139             }
    140         }
    141     }
    142 
    143     /**
    144      * Utility function to send a message to our handler.
    145      */
    146     private synchronized void postMessage(Message msg) {
    147         if (mHandler == null) {
    148             if (mQueuedMessages == null) {
    149                 mQueuedMessages = new Vector<Message>();
    150             }
    151             mQueuedMessages.add(msg);
    152         } else {
    153             mHandler.sendMessage(msg);
    154         }
    155     }
    156 
    157     /**
    158      * Utility function to send a message to the handler on the UI thread
    159      */
    160     private void postUIMessage(Message msg) {
    161         if (mUIHandler != null) {
    162             mUIHandler.sendMessage(msg);
    163         }
    164     }
    165 
    166     // Note that we represent the origins as strings. These are created using
    167     // WebCore::SecurityOrigin::toString(). As long as all 'HTML 5 modules'
    168     // (Database, Geolocation etc) do so, it's safe to match up origins based
    169     // on this string.
    170     @Override
    171     public void getOrigins(ValueCallback<Set<String> > callback) {
    172         if (callback != null) {
    173             if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
    174                 Set origins = nativeGetOrigins();
    175                 callback.onReceiveValue(origins);
    176             } else {
    177                 postMessage(Message.obtain(null, GET_ORIGINS, callback));
    178             }
    179         }
    180     }
    181 
    182     @Override
    183     public void getAllowed(String origin, ValueCallback<Boolean> callback) {
    184         if (callback == null) {
    185             return;
    186         }
    187         if (origin == null) {
    188             callback.onReceiveValue(null);
    189             return;
    190         }
    191         if (WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName())) {
    192             boolean allowed = nativeGetAllowed(origin);
    193             callback.onReceiveValue(Boolean.valueOf(allowed));
    194         } else {
    195             Map values = new HashMap<String, Object>();
    196             values.put(ORIGIN, origin);
    197             values.put(CALLBACK, callback);
    198             postMessage(Message.obtain(null, GET_ALLOWED, values));
    199         }
    200     }
    201 
    202     // This method may be called before the WebKit
    203     // thread has intialized the message handler. Messages will be queued until
    204     // this time.
    205     @Override
    206     public void clear(String origin) {
    207         // Called on the UI thread.
    208         postMessage(Message.obtain(null, CLEAR, origin));
    209     }
    210 
    211     // This method may be called before the WebKit
    212     // thread has intialized the message handler. Messages will be queued until
    213     // this time.
    214     @Override
    215     public void allow(String origin) {
    216         // Called on the UI thread.
    217         postMessage(Message.obtain(null, ALLOW, origin));
    218     }
    219 
    220     @Override
    221     public void clearAll() {
    222         // Called on the UI thread.
    223         postMessage(Message.obtain(null, CLEAR_ALL));
    224     }
    225 
    226     GeolocationPermissionsClassic() {}
    227 
    228     // Native functions, run on the WebKit thread.
    229     private static native Set nativeGetOrigins();
    230     private static native boolean nativeGetAllowed(String origin);
    231     private static native void nativeClear(String origin);
    232     private static native void nativeAllow(String origin);
    233     private static native void nativeClearAll();
    234 }
    235