Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c12544a2 authored by Patrick Scott's avatar Patrick Scott
Browse files

Offer a callback to intercept url requests.

The new callback allows applications to return a response for a particular url.
Deprecate onLoadResource in favor of the new api.  onLoadResource is not
currently being used by the new network stack and applications can post a
message from shouldInterceptRequest to handle onLoadResource.

Bug: 2905943
Change-Id: Icf48ab3110d85d76112b3c3b4a1a8c8a333b82f0
parent 83d4a23c
Loading
Loading
Loading
Loading
+110 −0
Original line number Diff line number Diff line
@@ -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"
+14 −20
Original line number Diff line number Diff line
@@ -653,23 +653,6 @@ class BrowserFrame extends Handler {
        return size;
    }

    /**
     * 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:
@@ -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.
+9 −5
Original line number Diff line number Diff line
@@ -1008,14 +1008,18 @@ 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));
        }
        return r;
    }

    public void onUnhandledKeyEvent(KeyEvent event) {
        // Do an unsynchronized quick check to avoid posting if no callback has
+14 −2
Original line number Diff line number Diff line
@@ -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(
+116 −0
Original line number Diff line number Diff line
/*
 * 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);
    }
}
Loading