Commit 8a4a31d0 authored by mnaganov's avatar mnaganov Committed by Commit bot

[Android WebView] Implement OnReceivedHttpError callback

Implement OnReceivedHttpError via NetworkDelegate::OnHeadersReceived
for status codes >= 400.

BUG=456782

Review URL: https://codereview.chromium.org/976393002

Cr-Commit-Position: refs/heads/master@{#319856}
parent b6a70087
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
class GURL; class GURL;
namespace net { namespace net {
class HttpResponseHeaders;
class URLRequest; class URLRequest;
} }
...@@ -102,6 +103,11 @@ class AwContentsIoThreadClient { ...@@ -102,6 +103,11 @@ class AwContentsIoThreadClient {
virtual void NewLoginRequest(const std::string& realm, virtual void NewLoginRequest(const std::string& realm,
const std::string& account, const std::string& account,
const std::string& args) = 0; const std::string& args) = 0;
// Called when a response from the server is received with status code >= 400.
virtual void OnReceivedHttpError(
const net::URLRequest* request,
const net::HttpResponseHeaders* response_headers) = 0;
}; };
} // namespace android_webview } // namespace android_webview
......
...@@ -4,14 +4,20 @@ ...@@ -4,14 +4,20 @@
#include "android_webview/browser/net/aw_network_delegate.h" #include "android_webview/browser/net/aw_network_delegate.h"
#include "android_webview/browser/aw_contents_io_thread_client.h"
#include "android_webview/browser/aw_cookie_access_policy.h" #include "android_webview/browser/aw_cookie_access_policy.h"
#include "base/android/build_info.h" #include "base/android/build_info.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_request_info.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "net/base/completion_callback.h" #include "net/base/completion_callback.h"
#include "net/http/http_response_headers.h"
#include "net/proxy/proxy_info.h" #include "net/proxy/proxy_info.h"
#include "net/proxy/proxy_server.h" #include "net/proxy/proxy_server.h"
#include "net/url_request/url_request.h" #include "net/url_request/url_request.h"
using content::BrowserThread;
namespace android_webview { namespace android_webview {
AwNetworkDelegate::AwNetworkDelegate() { AwNetworkDelegate::AwNetworkDelegate() {
...@@ -49,6 +55,17 @@ int AwNetworkDelegate::OnHeadersReceived( ...@@ -49,6 +55,17 @@ int AwNetworkDelegate::OnHeadersReceived(
const net::HttpResponseHeaders* original_response_headers, const net::HttpResponseHeaders* original_response_headers,
scoped_refptr<net::HttpResponseHeaders>* override_response_headers, scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
GURL* allowed_unsafe_redirect_url) { GURL* allowed_unsafe_redirect_url) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
int render_process_id, render_frame_id;
if (original_response_headers->response_code() >= 400 &&
content::ResourceRequestInfo::GetRenderFrameForRequest(
request, &render_process_id, &render_frame_id)) {
scoped_ptr<AwContentsIoThreadClient> io_thread_client =
AwContentsIoThreadClient::FromID(render_process_id, render_frame_id);
if (io_thread_client.get()) {
io_thread_client->OnReceivedHttpError(request, original_response_headers);
}
}
return net::OK; return net::OK;
} }
......
...@@ -574,6 +574,17 @@ public class WebViewContentsClientAdapter extends AwContentsClient { ...@@ -574,6 +574,17 @@ public class WebViewContentsClientAdapter extends AwContentsClient {
} }
} }
@Override
public void onReceivedHttpError(AwWebResourceRequest request, AwWebResourceResponse response) {
try {
TraceEvent.begin("WebViewContentsClientAdapter.onReceivedHttpError");
if (TRACE) Log.d(TAG, "onReceivedHttpError=" + request.url);
// TODO(mnaganov): Call mWebViewClient.onReceivedHttpError(mWebView, request, response);
} finally {
TraceEvent.end("WebViewContentsClientAdapter.onReceivedHttpError");
}
}
/** /**
* @see ContentViewClient#onReceivedTitle(String) * @see ContentViewClient#onReceivedTitle(String)
*/ */
......
...@@ -416,6 +416,12 @@ public class AwContents implements SmartClipProvider, ...@@ -416,6 +416,12 @@ public class AwContents implements SmartClipProvider,
public void newLoginRequest(String realm, String account, String args) { public void newLoginRequest(String realm, String account, String args) {
mContentsClient.getCallbackHelper().postOnReceivedLoginRequest(realm, account, args); mContentsClient.getCallbackHelper().postOnReceivedLoginRequest(realm, account, args);
} }
@Override
public void onReceivedHttpError(AwContentsClient.AwWebResourceRequest request,
AwWebResourceResponse response) {
mContentsClient.getCallbackHelper().postOnReceivedHttpError(request, response);
}
} }
//-------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------
......
...@@ -297,6 +297,9 @@ public abstract class AwContentsClient { ...@@ -297,6 +297,9 @@ public abstract class AwContentsClient {
protected abstract void onReceivedError2( protected abstract void onReceivedError2(
AwWebResourceRequest request, AwWebResourceError error); AwWebResourceRequest request, AwWebResourceError error);
public abstract void onReceivedHttpError(AwWebResourceRequest request,
AwWebResourceResponse response);
// TODO (michaelbai): Remove this method once the same method remove from // TODO (michaelbai): Remove this method once the same method remove from
// WebViewContentsClientAdapter. // WebViewContentsClientAdapter.
public void onShowCustomView(View view, int requestedOrientation, public void onShowCustomView(View view, int requestedOrientation,
......
...@@ -69,6 +69,17 @@ public class AwContentsClientCallbackHelper { ...@@ -69,6 +69,17 @@ public class AwContentsClientCallbackHelper {
} }
} }
private static class OnReceivedHttpErrorInfo {
final AwContentsClient.AwWebResourceRequest mRequest;
final AwWebResourceResponse mResponse;
OnReceivedHttpErrorInfo(
AwContentsClient.AwWebResourceRequest request, AwWebResourceResponse response) {
mRequest = request;
mResponse = response;
}
}
private static final int MSG_ON_LOAD_RESOURCE = 1; private static final int MSG_ON_LOAD_RESOURCE = 1;
private static final int MSG_ON_PAGE_STARTED = 2; private static final int MSG_ON_PAGE_STARTED = 2;
private static final int MSG_ON_DOWNLOAD_START = 3; private static final int MSG_ON_DOWNLOAD_START = 3;
...@@ -76,6 +87,7 @@ public class AwContentsClientCallbackHelper { ...@@ -76,6 +87,7 @@ public class AwContentsClientCallbackHelper {
private static final int MSG_ON_RECEIVED_ERROR = 5; private static final int MSG_ON_RECEIVED_ERROR = 5;
private static final int MSG_ON_NEW_PICTURE = 6; private static final int MSG_ON_NEW_PICTURE = 6;
private static final int MSG_ON_SCALE_CHANGED_SCALED = 7; private static final int MSG_ON_SCALE_CHANGED_SCALED = 7;
private static final int MSG_ON_RECEIVED_HTTP_ERROR = 8;
// Minimum period allowed between consecutive onNewPicture calls, to rate-limit the callbacks. // Minimum period allowed between consecutive onNewPicture calls, to rate-limit the callbacks.
private static final long ON_NEW_PICTURE_MIN_PERIOD_MILLIS = 500; private static final long ON_NEW_PICTURE_MIN_PERIOD_MILLIS = 500;
...@@ -140,6 +152,11 @@ public class AwContentsClientCallbackHelper { ...@@ -140,6 +152,11 @@ public class AwContentsClientCallbackHelper {
mContentsClient.onScaleChangedScaled(oldScale, newScale); mContentsClient.onScaleChangedScaled(oldScale, newScale);
break; break;
} }
case MSG_ON_RECEIVED_HTTP_ERROR: {
OnReceivedHttpErrorInfo info = (OnReceivedHttpErrorInfo) msg.obj;
mContentsClient.onReceivedHttpError(info.mRequest, info.mResponse);
break;
}
default: default:
throw new IllegalStateException( throw new IllegalStateException(
"AwContentsClientCallbackHelper: unhandled message " + msg.what); "AwContentsClientCallbackHelper: unhandled message " + msg.what);
...@@ -195,4 +212,11 @@ public class AwContentsClientCallbackHelper { ...@@ -195,4 +212,11 @@ public class AwContentsClientCallbackHelper {
mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_SCALE_CHANGED_SCALED, mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_SCALE_CHANGED_SCALED,
Float.floatToIntBits(oldScale), Float.floatToIntBits(newScale))); Float.floatToIntBits(oldScale), Float.floatToIntBits(newScale)));
} }
public void postOnReceivedHttpError(AwContentsClient.AwWebResourceRequest request,
AwWebResourceResponse response) {
OnReceivedHttpErrorInfo info =
new OnReceivedHttpErrorInfo(request, response);
mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_RECEIVED_HTTP_ERROR, info));
}
} }
...@@ -8,6 +8,7 @@ import org.chromium.base.CalledByNative; ...@@ -8,6 +8,7 @@ import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace; import org.chromium.base.JNINamespace;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
/** /**
* Delegate for handling callbacks. All methods are called on the IO thread. * Delegate for handling callbacks. All methods are called on the IO thread.
...@@ -42,6 +43,9 @@ public abstract class AwContentsIoThreadClient { ...@@ -42,6 +43,9 @@ public abstract class AwContentsIoThreadClient {
public abstract AwWebResourceResponse shouldInterceptRequest( public abstract AwWebResourceResponse shouldInterceptRequest(
AwContentsClient.AwWebResourceRequest request); AwContentsClient.AwWebResourceRequest request);
public abstract void onReceivedHttpError(AwContentsClient.AwWebResourceRequest request,
AwWebResourceResponse response);
// Protected methods --------------------------------------------------------------------------- // Protected methods ---------------------------------------------------------------------------
@CalledByNative @CalledByNative
...@@ -60,4 +64,42 @@ public abstract class AwContentsIoThreadClient { ...@@ -60,4 +64,42 @@ public abstract class AwContentsIoThreadClient {
} }
return shouldInterceptRequest(request); return shouldInterceptRequest(request);
} }
@CalledByNative
protected void onReceivedHttpError(
// WebResourceRequest
String url, boolean isMainFrame, boolean hasUserGesture, String method,
String[] requestHeaderNames, String[] requestHeaderValues,
// WebResourceResponse
String mimeType, String encoding, int statusCode, String reasonPhrase,
String[] responseHeaderNames, String[] responseHeaderValues) {
AwContentsClient.AwWebResourceRequest request =
new AwContentsClient.AwWebResourceRequest();
request.url = url;
request.isMainFrame = isMainFrame;
request.hasUserGesture = hasUserGesture;
request.method = method;
request.requestHeaders = new HashMap<String, String>(requestHeaderNames.length);
for (int i = 0; i < requestHeaderNames.length; ++i) {
request.requestHeaders.put(requestHeaderNames[i], requestHeaderValues[i]);
}
Map<String, String> responseHeaders =
new HashMap<String, String>(responseHeaderNames.length);
// Note that we receive un-coalesced response header lines, thus we need to combine
// values for the same header.
for (int i = 0; i < responseHeaderNames.length; ++i) {
if (!responseHeaders.containsKey(responseHeaderNames[i])) {
responseHeaders.put(responseHeaderNames[i], responseHeaderValues[i]);
} else if (!responseHeaderValues[i].isEmpty()) {
String currentValue = responseHeaders.get(responseHeaderNames[i]);
if (!currentValue.isEmpty()) {
currentValue += ", ";
}
responseHeaders.put(responseHeaderNames[i], currentValue + responseHeaderValues[i]);
}
}
AwWebResourceResponse response = new AwWebResourceResponse(
mimeType, encoding, null, statusCode, reasonPhrase, responseHeaders);
onReceivedHttpError(request, response);
}
} }
...@@ -6,7 +6,6 @@ package org.chromium.android_webview; ...@@ -6,7 +6,6 @@ package org.chromium.android_webview;
import org.chromium.base.CalledByNative; import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace; import org.chromium.base.JNINamespace;
import org.chromium.base.VisibleForTesting;
import java.io.InputStream; import java.io.InputStream;
import java.util.Map; import java.util.Map;
...@@ -21,6 +20,7 @@ public class AwWebResourceResponse { ...@@ -21,6 +20,7 @@ public class AwWebResourceResponse {
private InputStream mData; private InputStream mData;
private int mStatusCode; private int mStatusCode;
private String mReasonPhrase; private String mReasonPhrase;
private Map<String, String> mResponseHeaders;
private String[] mResponseHeaderNames; private String[] mResponseHeaderNames;
private String[] mResponseHeaderValues; private String[] mResponseHeaderValues;
...@@ -36,53 +36,59 @@ public class AwWebResourceResponse { ...@@ -36,53 +36,59 @@ public class AwWebResourceResponse {
mStatusCode = statusCode; mStatusCode = statusCode;
mReasonPhrase = reasonPhrase; mReasonPhrase = reasonPhrase;
mResponseHeaders = responseHeaders;
}
if (responseHeaders != null) { private void fillInResponseHeaderNamesAndValuesIfNeeded() {
mResponseHeaderNames = new String[responseHeaders.size()]; if (mResponseHeaders == null || mResponseHeaderNames != null) return;
mResponseHeaderValues = new String[responseHeaders.size()]; mResponseHeaderNames = new String[mResponseHeaders.size()];
int i = 0; mResponseHeaderValues = new String[mResponseHeaders.size()];
for (Map.Entry<String, String> entry : responseHeaders.entrySet()) { int i = 0;
mResponseHeaderNames[i] = entry.getKey(); for (Map.Entry<String, String> entry : mResponseHeaders.entrySet()) {
mResponseHeaderValues[i] = entry.getValue(); mResponseHeaderNames[i] = entry.getKey();
i++; mResponseHeaderValues[i] = entry.getValue();
} i++;
} }
} }
@VisibleForTesting
@CalledByNative @CalledByNative
public String getMimeType() { public String getMimeType() {
return mMimeType; return mMimeType;
} }
@CalledByNative @CalledByNative
private String getCharset() { public String getCharset() {
return mCharset; return mCharset;
} }
@VisibleForTesting
@CalledByNative @CalledByNative
public InputStream getData() { public InputStream getData() {
return mData; return mData;
} }
@CalledByNative @CalledByNative
private int getStatusCode() { public int getStatusCode() {
return mStatusCode; return mStatusCode;
} }
@CalledByNative @CalledByNative
private String getReasonPhrase() { public String getReasonPhrase() {
return mReasonPhrase; return mReasonPhrase;
} }
public Map<String, String> getResponseHeaders() {
return mResponseHeaders;
}
@CalledByNative @CalledByNative
private String[] getResponseHeaderNames() { private String[] getResponseHeaderNames() {
fillInResponseHeaderNamesAndValuesIfNeeded();
return mResponseHeaderNames; return mResponseHeaderNames;
} }
@CalledByNative @CalledByNative
private String[] getResponseHeaderValues() { private String[] getResponseHeaderValues() {
fillInResponseHeaderNamesAndValuesIfNeeded();
return mResponseHeaderValues; return mResponseHeaderValues;
} }
} }
...@@ -273,6 +273,26 @@ public class AwTestBase ...@@ -273,6 +273,26 @@ public class AwTestBase
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);
} }
public void waitForVisualStateCallback(final AwContents awContents) throws Exception {
final CallbackHelper ch = new CallbackHelper();
final int chCount = ch.getCallCount();
getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
final long requestId = 666;
awContents.insertVisualStateCallback(requestId,
new AwContents.VisualStateCallback() {
@Override
public void onComplete(long id) {
assertEquals(requestId, id);
ch.notifyCalled();
}
});
}
});
ch.waitForCallback(chCount);
}
/** /**
* Checks the current test has |clazz| annotation. Note this swallows NoSuchMethodException * Checks the current test has |clazz| annotation. Note this swallows NoSuchMethodException
* and returns false in that case. * and returns false in that case.
......
...@@ -9,6 +9,8 @@ import android.net.http.SslError; ...@@ -9,6 +9,8 @@ import android.net.http.SslError;
import android.webkit.ConsoleMessage; import android.webkit.ConsoleMessage;
import android.webkit.ValueCallback; import android.webkit.ValueCallback;
import org.chromium.android_webview.AwContentsClient.AwWebResourceRequest;
import org.chromium.android_webview.AwWebResourceResponse;
import org.chromium.base.ThreadUtils; import org.chromium.base.ThreadUtils;
import org.chromium.content.browser.test.util.CallbackHelper; import org.chromium.content.browser.test.util.CallbackHelper;
import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnEvaluateJavaScriptResultHelper; import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnEvaluateJavaScriptResultHelper;
...@@ -25,6 +27,7 @@ public class TestAwContentsClient extends NullContentsClient { ...@@ -25,6 +27,7 @@ public class TestAwContentsClient extends NullContentsClient {
private final OnPageStartedHelper mOnPageStartedHelper; private final OnPageStartedHelper mOnPageStartedHelper;
private final OnPageFinishedHelper mOnPageFinishedHelper; private final OnPageFinishedHelper mOnPageFinishedHelper;
private final OnReceivedErrorHelper mOnReceivedErrorHelper; private final OnReceivedErrorHelper mOnReceivedErrorHelper;
private final OnReceivedHttpErrorHelper mOnReceivedHttpErrorHelper;
private final CallbackHelper mOnReceivedSslErrorHelper; private final CallbackHelper mOnReceivedSslErrorHelper;
private final OnDownloadStartHelper mOnDownloadStartHelper; private final OnDownloadStartHelper mOnDownloadStartHelper;
private final OnReceivedLoginRequestHelper mOnReceivedLoginRequestHelper; private final OnReceivedLoginRequestHelper mOnReceivedLoginRequestHelper;
...@@ -41,6 +44,7 @@ public class TestAwContentsClient extends NullContentsClient { ...@@ -41,6 +44,7 @@ public class TestAwContentsClient extends NullContentsClient {
mOnPageStartedHelper = new OnPageStartedHelper(); mOnPageStartedHelper = new OnPageStartedHelper();
mOnPageFinishedHelper = new OnPageFinishedHelper(); mOnPageFinishedHelper = new OnPageFinishedHelper();
mOnReceivedErrorHelper = new OnReceivedErrorHelper(); mOnReceivedErrorHelper = new OnReceivedErrorHelper();
mOnReceivedHttpErrorHelper = new OnReceivedHttpErrorHelper();
mOnReceivedSslErrorHelper = new CallbackHelper(); mOnReceivedSslErrorHelper = new CallbackHelper();
mOnDownloadStartHelper = new OnDownloadStartHelper(); mOnDownloadStartHelper = new OnDownloadStartHelper();
mOnReceivedLoginRequestHelper = new OnReceivedLoginRequestHelper(); mOnReceivedLoginRequestHelper = new OnReceivedLoginRequestHelper();
...@@ -66,6 +70,10 @@ public class TestAwContentsClient extends NullContentsClient { ...@@ -66,6 +70,10 @@ public class TestAwContentsClient extends NullContentsClient {
return mOnReceivedErrorHelper; return mOnReceivedErrorHelper;
} }
public OnReceivedHttpErrorHelper getOnReceivedHttpErrorHelper() {
return mOnReceivedHttpErrorHelper;
}
public CallbackHelper getOnReceivedSslErrorHelper() { public CallbackHelper getOnReceivedSslErrorHelper() {
return mOnReceivedSslErrorHelper; return mOnReceivedSslErrorHelper;
} }
...@@ -439,4 +447,32 @@ public class TestAwContentsClient extends NullContentsClient { ...@@ -439,4 +447,32 @@ public class TestAwContentsClient extends NullContentsClient {
public void doUpdateVisitedHistory(String url, boolean isReload) { public void doUpdateVisitedHistory(String url, boolean isReload) {
getDoUpdateVisitedHistoryHelper().notifyCalled(url, isReload); getDoUpdateVisitedHistoryHelper().notifyCalled(url, isReload);
} }
/**
* CallbackHelper for OnReceivedHttpError.
*/
public static class OnReceivedHttpErrorHelper extends CallbackHelper {
private AwWebResourceRequest mRequest;
private AwWebResourceResponse mResponse;
public void notifyCalled(AwWebResourceRequest request, AwWebResourceResponse response) {
mRequest = request;
mResponse = response;
notifyCalled();
}
public AwWebResourceRequest getRequest() {
assert getCallCount() > 0;
return mRequest;
}
public AwWebResourceResponse getResponse() {
assert getCallCount() > 0;
return mResponse;
}
}
@Override
public void onReceivedHttpError(AwWebResourceRequest request, AwWebResourceResponse response) {
super.onReceivedHttpError(request, response);
mOnReceivedHttpErrorHelper.notifyCalled(request, response);
}
} }
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_observer.h"
#include "jni/AwContentsIoThreadClient_jni.h" #include "jni/AwContentsIoThreadClient_jni.h"
#include "net/http/http_request_headers.h" #include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h" #include "net/url_request/url_request.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -375,6 +376,85 @@ void AwContentsIoThreadClientImpl::NewLoginRequest(const string& realm, ...@@ -375,6 +376,85 @@ void AwContentsIoThreadClientImpl::NewLoginRequest(const string& realm,
env, java_object_.obj(), jrealm.obj(), jaccount.obj(), jargs.obj()); env, java_object_.obj(), jrealm.obj(), jaccount.obj(), jargs.obj());
} }
void AwContentsIoThreadClientImpl::OnReceivedHttpError(
const net::URLRequest* request,
const net::HttpResponseHeaders* response_headers) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (java_object_.is_null())
return;
vector<string> request_header_names;
vector<string> request_header_values;
{
net::HttpRequestHeaders headers;
if (!request->GetFullRequestHeaders(&headers))
headers = request->extra_request_headers();
net::HttpRequestHeaders::Iterator headers_iterator(headers);
while (headers_iterator.GetNext()) {
request_header_names.push_back(headers_iterator.name());
request_header_values.push_back(headers_iterator.value());
}
}
vector<string> response_header_names;
vector<string> response_header_values;
{
void* headers_iterator = NULL;
string header_name, header_value;
while (response_headers->EnumerateHeaderLines(
&headers_iterator, &header_name, &header_value)) {
response_header_names.push_back(header_name);
response_header_values.push_back(header_value);
}
}
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jstring> jstring_url =
ConvertUTF8ToJavaString(env, request->url().spec());
ScopedJavaLocalRef<jstring> jstring_method =
ConvertUTF8ToJavaString(env, request->method());
ScopedJavaLocalRef<jobjectArray> jstringArray_request_header_names =
ToJavaArrayOfStrings(env, request_header_names);
ScopedJavaLocalRef<jobjectArray> jstringArray_request_header_values =
ToJavaArrayOfStrings(env, request_header_values);
const content::ResourceRequestInfo* info =
content::ResourceRequestInfo::ForRequest(request);
bool is_main_frame = info &&
info->GetResourceType() == content::RESOURCE_TYPE_MAIN_FRAME;
bool has_user_gesture = info && info->HasUserGesture();
string mime_type, encoding;
response_headers->GetMimeTypeAndCharset(&mime_type, &encoding);
ScopedJavaLocalRef<jstring> jstring_mime_type =
ConvertUTF8ToJavaString(env, mime_type);
ScopedJavaLocalRef<jstring> jstring_encoding =
ConvertUTF8ToJavaString(env, encoding);
int status_code = response_headers->response_code();
ScopedJavaLocalRef<jstring> jstring_reason =
ConvertUTF8ToJavaString(env, response_headers->GetStatusText());
ScopedJavaLocalRef<jobjectArray> jstringArray_response_header_names =
ToJavaArrayOfStrings(env, response_header_names);
ScopedJavaLocalRef<jobjectArray> jstringArray_response_header_values =
ToJavaArrayOfStrings(env, response_header_values);
Java_AwContentsIoThreadClient_onReceivedHttpError(
env,
java_object_.obj(),
jstring_url.obj(),
is_main_frame,
has_user_gesture,
jstring_method.obj(),
jstringArray_request_header_names.obj(),
jstringArray_request_header_values.obj(),
jstring_mime_type.obj(),
jstring_encoding.obj(),
status_code,
jstring_reason.obj(),
jstringArray_response_header_names.obj(),
jstringArray_response_header_values.obj());
}
bool RegisterAwContentsIoThreadClientImpl(JNIEnv* env) { bool RegisterAwContentsIoThreadClientImpl(JNIEnv* env) {
return RegisterNativesImpl(env); return RegisterNativesImpl(env);
} }
......
...@@ -62,6 +62,9 @@ class AwContentsIoThreadClientImpl : public AwContentsIoThreadClient { ...@@ -62,6 +62,9 @@ class AwContentsIoThreadClientImpl : public AwContentsIoThreadClient {
void NewLoginRequest(const std::string& realm, void NewLoginRequest(const std::string& realm,
const std::string& account, const std::string& account,
const std::string& args) override; const std::string& args) override;
void OnReceivedHttpError(
const net::URLRequest* request,
const net::HttpResponseHeaders* response_headers) override;
private: private:
bool pending_association_; bool pending_association_;
......
...@@ -171,6 +171,10 @@ public class NullContentsClient extends AwContentsClient { ...@@ -171,6 +171,10 @@ public class NullContentsClient extends AwContentsClient {
public void onReceivedError2(AwWebResourceRequest request, AwWebResourceError error) { public void onReceivedError2(AwWebResourceRequest request, AwWebResourceError error) {
} }
@Override
public void onReceivedHttpError(AwWebResourceRequest request, AwWebResourceResponse response) {
}
@Override @Override
public void onFormResubmission(Message dontResend, Message resend) { public void onFormResubmission(Message dontResend, Message resend) {
dontResend.sendToTarget(); dontResend.sendToTarget();
......
...@@ -252,8 +252,22 @@ public class TestWebServer { ...@@ -252,8 +252,22 @@ public class TestWebServer {
*/ */
public String setResponseWithNotFoundStatus( public String setResponseWithNotFoundStatus(
String requestPath) { String requestPath) {
return setResponseInternal(requestPath, "".getBytes(), null, null, return setResponseWithNotFoundStatus(requestPath, null);
RESPONSE_STATUS_NOT_FOUND); }
/**
* Sets a 404 (not found) response to be returned when a particular request path is passed in.
*
* @param requestPath The path to respond to.
* @param responseHeaders Any additional headers that should be returned along with the
* response (null is acceptable).
* @return The full URL including the path that should be requested to get the expected
* response.
*/
public String setResponseWithNotFoundStatus(
String requestPath, List<Pair<String, String>> responseHeaders) {
return setResponseInternal(
requestPath, "".getBytes(), responseHeaders, null, RESPONSE_STATUS_NOT_FOUND);
} }
/** /**
...@@ -468,6 +482,9 @@ public class TestWebServer { ...@@ -468,6 +482,9 @@ public class TestWebServer {
httpResponse = createResponse(HttpStatus.SC_NOT_FOUND); httpResponse = createResponse(HttpStatus.SC_NOT_FOUND);
} else if (response.mIsNotFound) { } else if (response.mIsNotFound) {
httpResponse = createResponse(HttpStatus.SC_NOT_FOUND); httpResponse = createResponse(HttpStatus.SC_NOT_FOUND);
for (Pair<String, String> header : response.mResponseHeaders) {
httpResponse.addHeader(header.first, header.second);
}
servedResponseFor(path, request); servedResponseFor(path, request);
} else if (response.mIsNoContent) { } else if (response.mIsNoContent) {
httpResponse = createResponse(HttpStatus.SC_NO_CONTENT); httpResponse = createResponse(HttpStatus.SC_NO_CONTENT);
...@@ -531,6 +548,7 @@ public class TestWebServer { ...@@ -531,6 +548,7 @@ public class TestWebServer {
ByteArrayEntity entity = createEntity(buf.toString().getBytes()); ByteArrayEntity entity = createEntity(buf.toString().getBytes());
response.setEntity(entity); response.setEntity(entity);
response.setHeader("Content-Length", "" + entity.getContentLength()); response.setHeader("Content-Length", "" + entity.getContentLength());
response.setReasonPhrase(reason);
} }
return response; return response;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment