Why doesn't WebViewClient.shouldInterceptRequest support redirects after 4.4?

情到浓时终转凉″ 提交于 2019-12-23 02:07:26

问题


I was trying to intercept all network communication going in and out of the WebView within the host application. My attempt focused around the two shouldInterceptRequest methods, provided by the WebViewClient:

@Override
public WebResourceResponse shouldInterceptRequest(final WebView view, String url) {
    Log.d(Constants.Tags.WEBVIEW_CLIENT, "WV REQUEST (OLD) " + url);
    return processRequest(url);
}

@Override
@TargetApi(21)
public WebResourceResponse shouldInterceptRequest(final WebView view, WebResourceRequest
        interceptedRequest) {
    Log.d(Constants.Tags.WEBVIEW_CLIENT, "WV REQUEST (NEW) " + interceptedRequest.getUrl
            ().toString() + " " + interceptedRequest.getMethod());
    return processRequest(interceptedRequest);
}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private WebResourceResponse processRequest(WebResourceRequest ir) {
    if (!"GET".equals(ir.getMethod())) {
        Log.d(Constants.Tags.WEBVIEW_CLIENT, "IGNORING " + ir.getMethod() + " " + ir.getUrl());
        return null;
    }
    return processRequest(ir.getUrl().toString());
}

private WebResourceResponse processRequest(String url) {
    Request request = new Request.Builder().url(url).build();
    try {
        return processResponse(okHttpClient.newCall(request).execute());
    } catch (SSLHandshakeException e) {
        Log.d(Constants.Tags.WEBVIEW_CLIENT, "SSLHandshakeException: " + e.getMessage());
    } catch (IOException e) {
        Log.d(Constants.Tags.WEBVIEW_CLIENT, "IOException: " + e.getMessage());
        e.printStackTrace();
    }
    return null;
}

private WebResourceResponse processResponse(Response response) {
    String contentType = response.body().contentType().toString();

    if (contentType != null) {
        String mimeType = contentType;

        if (contentType.contains(";")) {
            mimeType = contentType.split(";")[0].trim();
        }

        WebResourceResponse webResourceResponse = new WebResourceResponse(mimeType, response
                .header("content-encoding", "utf-8")
                , response.body().byteStream());

        if (Build.VERSION.SDK_INT > 21) {
            webResourceResponse.setResponseHeaders(convertHeaders(response.headers()));
            webResourceResponse.setStatusCodeAndReasonPhrase(response.code(),"whatever");
        }

        return webResourceResponse;
    }
    return null;
}

private Map<String, String> convertHeaders(Headers headers) {
    Map<String, String> map = new HashMap<>();
    for (int i = 0; i < headers.size(); i++) {
        map.put(headers.name(i), headers.value(i));
    }
    return map;
}

In order to make this a viable solution, I'm trying to attach all the headers and the response code to the WebResourceResponse object on API level 21 or over. One of the reasons why I believe this is impossible to do, even if I skip anything but GET requests is the fact that doesn't support the interception of redirects. That's valid both ways: Application --> Webview and WebView --> Application.

Excerpt from WebResourceResponse's documentation, regarding the value of the status code parameter in setStatusCodeAndReasonPhrase:

int: the status code needs to be in the ranges [100, 299], [400, 599]. Causing a redirect by specifying a 3xx code is not supported.

I managed to get response code 302 to work on browsers on Lollipop or newer by bypassing the monitored setter with reflection. This is only valid for Application --> WebView, since the WebView won't acknowledge the WebViewClient that it's executing a redirect request (next step after i pass back the hacky 302 WebResourceResponse). shouldInterceptRequest is simply not being called for that request.

I'm not going to bother anyone with my initial intentions. I simply want to know why doesn't the modern WebView support redirects? So far I'm working with the conclusion that the reason is compatibility with pre 4.4 WebView providers (potentially not Chromium based). That, however, doesn't make much sense: I simply can't make a call to setStatusCodeAndReasonPhrase on Android versions below 5.0.

Any feedback is highly appreciated.

来源:https://stackoverflow.com/questions/46636535/why-doesnt-webviewclient-shouldinterceptrequest-support-redirects-after-4-4

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!