Home | History | Annotate | Download | only in webkit
      1 /*
      2  * Copyright (C) 2006 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 import android.util.Log;
     22 
     23 import java.util.Set;
     24 
     25 final class JWebCoreJavaBridge extends Handler {
     26     // Identifier for the timer message.
     27     private static final int TIMER_MESSAGE = 1;
     28     // ID for servicing functionptr queue
     29     private static final int FUNCPTR_MESSAGE = 2;
     30     // Log system identifier.
     31     private static final String LOGTAG = "webkit-timers";
     32 
     33     // Native object pointer for interacting in native code.
     34     private int mNativeBridge;
     35     // Instant timer is used to implement a timer that needs to fire almost
     36     // immediately.
     37     private boolean mHasInstantTimer;
     38 
     39     // Reference count the pause/resume of timers
     40     private int mPauseTimerRefCount;
     41 
     42     private boolean mTimerPaused;
     43     private boolean mHasDeferredTimers;
     44 
     45     // keep track of the main WebView attached to the current window so that we
     46     // can get the proper Context.
     47     private WebView mCurrentMainWebView;
     48 
     49     /* package */
     50     static final int REFRESH_PLUGINS = 100;
     51 
     52     /**
     53      * Construct a new JWebCoreJavaBridge to interface with
     54      * WebCore timers and cookies.
     55      */
     56     public JWebCoreJavaBridge() {
     57         nativeConstructor();
     58     }
     59 
     60     @Override
     61     protected void finalize() {
     62         nativeFinalize();
     63     }
     64 
     65     synchronized void setActiveWebView(WebView webview) {
     66         if (mCurrentMainWebView != null) {
     67             // it is possible if there is a sub-WebView. Do nothing.
     68             return;
     69         }
     70         mCurrentMainWebView = webview;
     71     }
     72 
     73     synchronized void removeActiveWebView(WebView webview) {
     74         if (mCurrentMainWebView != webview) {
     75             // it is possible if there is a sub-WebView. Do nothing.
     76             return;
     77         }
     78         mCurrentMainWebView = null;
     79     }
     80 
     81     /**
     82      * Call native timer callbacks.
     83      */
     84     private void fireSharedTimer() {
     85         PerfChecker checker = new PerfChecker();
     86         // clear the flag so that sharedTimerFired() can set a new timer
     87         mHasInstantTimer = false;
     88         sharedTimerFired();
     89         checker.responseAlert("sharedTimer");
     90     }
     91 
     92     /**
     93      * handleMessage
     94      * @param msg The dispatched message.
     95      *
     96      * The only accepted message currently is TIMER_MESSAGE
     97      */
     98     @Override
     99     public void handleMessage(Message msg) {
    100         switch (msg.what) {
    101             case TIMER_MESSAGE: {
    102                 if (mTimerPaused) {
    103                     mHasDeferredTimers = true;
    104                 } else {
    105                     fireSharedTimer();
    106                 }
    107                 break;
    108             }
    109             case FUNCPTR_MESSAGE:
    110                 nativeServiceFuncPtrQueue();
    111                 break;
    112             case REFRESH_PLUGINS:
    113                 nativeUpdatePluginDirectories(PluginManager.getInstance(null)
    114                         .getPluginDirectories(), ((Boolean) msg.obj)
    115                         .booleanValue());
    116                 break;
    117         }
    118     }
    119 
    120     // called from JNI side
    121     private void signalServiceFuncPtrQueue() {
    122         Message msg = obtainMessage(FUNCPTR_MESSAGE);
    123         sendMessage(msg);
    124     }
    125 
    126     private native void nativeServiceFuncPtrQueue();
    127 
    128     /**
    129      * Pause all timers.
    130      */
    131     public void pause() {
    132         if (--mPauseTimerRefCount == 0) {
    133             mTimerPaused = true;
    134             mHasDeferredTimers = false;
    135         }
    136     }
    137 
    138     /**
    139      * Resume all timers.
    140      */
    141     public void resume() {
    142         if (++mPauseTimerRefCount == 1) {
    143            mTimerPaused = false;
    144            if (mHasDeferredTimers) {
    145                mHasDeferredTimers = false;
    146                fireSharedTimer();
    147            }
    148         }
    149     }
    150 
    151     /**
    152      * Set WebCore cache size.
    153      * @param bytes The cache size in bytes.
    154      */
    155     public native void setCacheSize(int bytes);
    156 
    157     /**
    158      * Store a cookie string associated with a url.
    159      * @param url The url to be used as a key for the cookie.
    160      * @param value The cookie string to be stored.
    161      */
    162     private void setCookies(String url, String value) {
    163         if (value.contains("\r") || value.contains("\n")) {
    164             // for security reason, filter out '\r' and '\n' from the cookie
    165             int size = value.length();
    166             StringBuilder buffer = new StringBuilder(size);
    167             int i = 0;
    168             while (i != -1 && i < size) {
    169                 int ir = value.indexOf('\r', i);
    170                 int in = value.indexOf('\n', i);
    171                 int newi = (ir == -1) ? in : (in == -1 ? ir : (ir < in ? ir
    172                         : in));
    173                 if (newi > i) {
    174                     buffer.append(value.subSequence(i, newi));
    175                 } else if (newi == -1) {
    176                     buffer.append(value.subSequence(i, size));
    177                     break;
    178                 }
    179                 i = newi + 1;
    180             }
    181             value = buffer.toString();
    182         }
    183         CookieManager.getInstance().setCookie(url, value);
    184     }
    185 
    186     /**
    187      * Retrieve the cookie string for the given url.
    188      * @param url The resource's url.
    189      * @return A String representing the cookies for the given resource url.
    190      */
    191     private String cookies(String url) {
    192         return CookieManager.getInstance().getCookie(url);
    193     }
    194 
    195     /**
    196      * Returns whether cookies are enabled or not.
    197      */
    198     private boolean cookiesEnabled() {
    199         return CookieManager.getInstance().acceptCookie();
    200     }
    201 
    202     /**
    203      * Returns an array of plugin directoies
    204      */
    205     private String[] getPluginDirectories() {
    206         return PluginManager.getInstance(null).getPluginDirectories();
    207     }
    208 
    209     /**
    210      * Returns the path of the plugin data directory
    211      */
    212     private String getPluginSharedDataDirectory() {
    213         return PluginManager.getInstance(null).getPluginSharedDataDirectory();
    214     }
    215 
    216     /**
    217      * setSharedTimer
    218      * @param timemillis The relative time when the timer should fire
    219      */
    220     private void setSharedTimer(long timemillis) {
    221         if (DebugFlags.J_WEB_CORE_JAVA_BRIDGE) Log.v(LOGTAG, "setSharedTimer " + timemillis);
    222 
    223         if (timemillis <= 0) {
    224             // we don't accumulate the sharedTimer unless it is a delayed
    225             // request. This way we won't flood the message queue with
    226             // WebKit messages. This should improve the browser's
    227             // responsiveness to key events.
    228             if (mHasInstantTimer) {
    229                 return;
    230             } else {
    231                 mHasInstantTimer = true;
    232                 Message msg = obtainMessage(TIMER_MESSAGE);
    233                 sendMessageDelayed(msg, timemillis);
    234             }
    235         } else {
    236             Message msg = obtainMessage(TIMER_MESSAGE);
    237             sendMessageDelayed(msg, timemillis);
    238         }
    239     }
    240 
    241     /**
    242      * Stop the shared timer.
    243      */
    244     private void stopSharedTimer() {
    245         if (DebugFlags.J_WEB_CORE_JAVA_BRIDGE) {
    246             Log.v(LOGTAG, "stopSharedTimer removing all timers");
    247         }
    248         removeMessages(TIMER_MESSAGE);
    249         mHasInstantTimer = false;
    250         mHasDeferredTimers = false;
    251     }
    252 
    253     private String[] getKeyStrengthList() {
    254         return CertTool.getKeyStrengthList();
    255     }
    256 
    257     synchronized private String getSignedPublicKey(int index, String challenge,
    258             String url) {
    259         if (mCurrentMainWebView != null) {
    260             // generateKeyPair expects organizations which we don't have. Ignore
    261             // url.
    262             return CertTool.getSignedPublicKey(
    263                     mCurrentMainWebView.getContext(), index, challenge);
    264         } else {
    265             Log.e(LOGTAG, "There is no active WebView for getSignedPublicKey");
    266             return "";
    267         }
    268     }
    269 
    270     private native void nativeConstructor();
    271     private native void nativeFinalize();
    272     private native void sharedTimerFired();
    273     private native void nativeUpdatePluginDirectories(String[] directories,
    274             boolean reload);
    275     public native void setNetworkOnLine(boolean online);
    276     public native void setNetworkType(String type, String subtype);
    277     public native void addPackageNames(Set<String> packageNames);
    278     public native void addPackageName(String packageName);
    279     public native void removePackageName(String packageName);
    280 }
    281