diff options
| -rw-r--r-- | api/current.xml | 110 | ||||
| -rw-r--r-- | core/java/android/webkit/BrowserFrame.java | 34 | ||||
| -rw-r--r-- | core/java/android/webkit/CallbackProxy.java | 14 | ||||
| -rw-r--r-- | core/java/android/webkit/FrameLoader.java | 16 | ||||
| -rw-r--r-- | core/java/android/webkit/WebResourceResponse.java | 116 | ||||
| -rw-r--r-- | core/java/android/webkit/WebViewClient.java | 20 |
6 files changed, 283 insertions, 27 deletions
diff --git a/api/current.xml b/api/current.xml index 4400a002ed5a..e022092a34fc 100644 --- a/api/current.xml +++ b/api/current.xml @@ -222269,6 +222269,101 @@ </parameter> </method> </interface> +<class name="WebResourceResponse" + extends="java.lang.Object" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<constructor name="WebResourceResponse" + type="android.webkit.WebResourceResponse" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="mimeType" type="java.lang.String"> +</parameter> +<parameter name="encoding" type="java.lang.String"> +</parameter> +<parameter name="data" type="java.io.InputStream"> +</parameter> +</constructor> +<method name="getData" + return="java.io.InputStream" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getEncoding" + return="java.lang.String" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getMimeType" + return="java.lang.String" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="setData" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="data" type="java.io.InputStream"> +</parameter> +</method> +<method name="setEncoding" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="encoding" type="java.lang.String"> +</parameter> +</method> +<method name="setMimeType" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="mimeType" type="java.lang.String"> +</parameter> +</method> +</class> <class name="WebSettings" extends="java.lang.Object" abstract="false" @@ -225358,6 +225453,21 @@ <parameter name="event" type="android.view.KeyEvent"> </parameter> </method> +<method name="shouldInterceptRequest" + return="android.webkit.WebResourceResponse" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="view" type="android.webkit.WebView"> +</parameter> +<parameter name="url" type="java.lang.String"> +</parameter> +</method> <method name="shouldOverrideKeyEvent" return="boolean" abstract="false" diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java index ed5663e0f610..d3c0ffd17e14 100644 --- a/core/java/android/webkit/BrowserFrame.java +++ b/core/java/android/webkit/BrowserFrame.java @@ -654,23 +654,6 @@ class BrowserFrame extends Handler { } /** - * Called by JNI. - * Read from an InputStream into a supplied byte[] - * This method catches any exceptions so they don't crash the JVM. - * @param inputStream InputStream to read from. - * @param output Bytearray that gets the output. - * @return the number of bytes read, or -i if then end of stream has been reached - */ - private static int readFromStream(InputStream inputStream, byte[] output) { - try { - return inputStream.read(output); - } catch(java.io.IOException e) { - // If we get an exception, return end of stream - return -1; - } - } - - /** * Get the InputStream for an Android resource * There are three different kinds of android resources: * - file:///android_res @@ -859,8 +842,6 @@ class BrowserFrame extends Handler { this, url, loaderHandle, synchronous, isMainFramePage, mainResource, userGesture, postDataIdentifier, username, password); - mCallbackProxy.onLoadResource(url); - if (LoadListener.getNativeLoaderCount() > MAX_OUTSTANDING_REQUESTS) { // send an error message, so that loadListener can be deleted // after this is returned. This is important as LoadListener's @@ -872,7 +853,11 @@ class BrowserFrame extends Handler { return loadListener; } - FrameLoader loader = new FrameLoader(loadListener, mSettings, method); + // Note that we are intentionally skipping + // inputStreamForAndroidResource. This is so that FrameLoader will use + // the various StreamLoader classes to handle assets. + FrameLoader loader = new FrameLoader(loadListener, mSettings, method, + mCallbackProxy.shouldInterceptRequest(url)); loader.setHeaders(headers); loader.setPostData(postData); // Set the load mode to the mode used for the current page. @@ -889,6 +874,15 @@ class BrowserFrame extends Handler { return !synchronous ? loadListener : null; } + // Called by jni from the chrome network stack. + private WebResourceResponse shouldInterceptRequest(String url) { + InputStream androidResource = inputStreamForAndroidResource(url); + if (androidResource != null) { + return new WebResourceResponse(null, null, androidResource); + } + return mCallbackProxy.shouldInterceptRequest(url); + } + /** * Set the progress for the browser activity. Called by native code. * Uses a delay so it does not happen too often. diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java index 0078e7a90a8f..160fc2e84498 100644 --- a/core/java/android/webkit/CallbackProxy.java +++ b/core/java/android/webkit/CallbackProxy.java @@ -1008,13 +1008,17 @@ class CallbackProxy extends Handler { sendMessage(obtainMessage(UPDATE_VISITED, isReload ? 1 : 0, 0, url)); } - public void onLoadResource(String url) { - // Do an unsynchronized quick check to avoid posting if no callback has - // been set. + WebResourceResponse shouldInterceptRequest(String url) { if (mWebViewClient == null) { - return; + return null; + } + // Note: This method does _not_ send a message. + WebResourceResponse r = + mWebViewClient.shouldInterceptRequest(mWebView, url); + if (r == null) { + sendMessage(obtainMessage(LOAD_RESOURCE, url)); } - sendMessage(obtainMessage(LOAD_RESOURCE, url)); + return r; } public void onUnhandledKeyEvent(KeyEvent event) { diff --git a/core/java/android/webkit/FrameLoader.java b/core/java/android/webkit/FrameLoader.java index 0f127d561013..951dab36785a 100644 --- a/core/java/android/webkit/FrameLoader.java +++ b/core/java/android/webkit/FrameLoader.java @@ -38,6 +38,7 @@ class FrameLoader { private String mReferrer; private String mContentType; private final String mUaprofHeader; + private final WebResourceResponse mInterceptResponse; private static final int URI_PROTOCOL = 0x100; @@ -54,12 +55,13 @@ class FrameLoader { private static final String LOGTAG = "webkit"; FrameLoader(LoadListener listener, WebSettings settings, - String method) { + String method, WebResourceResponse interceptResponse) { mListener = listener; mHeaders = null; mMethod = method; mCacheMode = WebSettings.LOAD_NORMAL; mSettings = settings; + mInterceptResponse = interceptResponse; mUaprofHeader = mListener.getContext().getResources().getString( com.android.internal.R.string.config_useragentprofile_url, Build.MODEL); } @@ -100,7 +102,17 @@ class FrameLoader { public boolean executeLoad() { String url = mListener.url(); - if (URLUtil.isNetworkUrl(url)){ + // Process intercepted requests first as they could be any url. + if (mInterceptResponse != null) { + if (mListener.isSynchronous()) { + mInterceptResponse.loader(mListener).load(); + } else { + WebViewWorker.getHandler().obtainMessage( + WebViewWorker.MSG_ADD_STREAMLOADER, + mInterceptResponse.loader(mListener)).sendToTarget(); + } + return true; + } else if (URLUtil.isNetworkUrl(url)){ if (mSettings.getBlockNetworkLoads()) { mListener.error(EventHandler.ERROR_BAD_URL, mListener.getContext().getString( diff --git a/core/java/android/webkit/WebResourceResponse.java b/core/java/android/webkit/WebResourceResponse.java new file mode 100644 index 000000000000..e786838615a6 --- /dev/null +++ b/core/java/android/webkit/WebResourceResponse.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.webkit; + +import android.net.http.Headers; + +import java.io.InputStream; + +/** + * A WebResourceResponse is return by + * {@link WebViewClient#shouldInterceptRequest} and + * contains the response information for a particular resource. + */ +public class WebResourceResponse { + + private class Loader extends StreamLoader { + Loader(LoadListener loadListener) { + super(loadListener); + mDataStream = mInputStream; + } + @Override + protected boolean setupStreamAndSendStatus() { + mLoadListener.status(1, 1, mDataStream != null ? 200 : 404, ""); + return true; + } + @Override + protected void buildHeaders(Headers headers) { + headers.setContentType(mMimeType); + headers.setContentEncoding(mEncoding); + } + } + + // Accessed by jni, do not rename without modifying the jni code. + private String mMimeType; + private String mEncoding; + private InputStream mInputStream; + + /** + * Construct a response with the given mime type, encoding, and data. + * @param mimeType The mime type of the data (i.e. text/html). + * @param encoding The encoding of the bytes read from data. + * @param data An InputStream for reading custom data. The implementation + * must implement {@link InputStream#read(byte[])}. + */ + public WebResourceResponse(String mimeType, String encoding, + InputStream data) { + mMimeType = mimeType; + mEncoding = encoding; + mInputStream = data; + } + + /** + * Set the mime type of the response data (i.e. text/html). + * @param mimeType + */ + public void setMimeType(String mimeType) { + mMimeType = mimeType; + } + + /** + * @see #setMimeType + */ + public String getMimeType() { + return mMimeType; + } + + /** + * Set the encoding of the response data (i.e. utf-8). This will be used to + * decode the raw bytes from the input stream. + * @param encoding + */ + public void setEncoding(String encoding) { + mEncoding = encoding; + } + + /** + * @see #setEncoding + */ + public String getEncoding() { + return mEncoding; + } + + /** + * Set the input stream containing the data for this resource. + * @param data An InputStream for reading custom data. The implementation + * must implement {@link InputStream#read(byte[])}. + */ + public void setData(InputStream data) { + mInputStream = data; + } + + /** + * @see #setData + */ + public InputStream getData() { + return mInputStream; + } + + StreamLoader loader(LoadListener listener) { + return new Loader(listener); + } +} diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java index 1f8eeba9016c..db605de6dc77 100644 --- a/core/java/android/webkit/WebViewClient.java +++ b/core/java/android/webkit/WebViewClient.java @@ -78,6 +78,26 @@ public class WebViewClient { } /** + * Notify the host application of a resource request and allow the + * application to return the data. If the return value is null, the WebView + * will continue to load the resource as usual. Otherwise, the return + * response and data will be used. NOTE: This method is called by the + * network thread so clients should exercise caution when accessing private + * data. + * + * @param view The {@link android.webkit.WebView} that is requesting the + * resource. + * @param url The raw url of the resource. + * @return A {@link android.webkit.WebResourceResponse} containing the + * response information or null if the WebView should load the + * resource itself. + */ + public WebResourceResponse shouldInterceptRequest(WebView view, + String url) { + return null; + } + + /** * Notify the host application that there have been an excessive number of * HTTP redirects. As the host application if it would like to continue * trying to load the resource. The default behavior is to send the cancel |