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