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