Commit daef464d authored by Maks Orlovich's avatar Maks Orlovich Committed by Commit Bot

Android Webview: probable fix for #840235

Posting headers gotten on IO thread from NetworkDelegate off to UI thread
isn't guaranteed to work (since the IO thread is still using them!); so
instead extract out the bits that are actually needed immediately.

Bug: 840235
Change-Id: I067378ab1fee252af6c6cbd7562b75776477e979
Reviewed-on: https://chromium-review.googlesource.com/1057875Reviewed-by: default avatarRichard Coles <torne@chromium.org>
Commit-Queue: Maks Orlovich <morlovich@chromium.org>
Cr-Commit-Position: refs/heads/master@{#558747}
parent f2173e44
...@@ -73,6 +73,10 @@ class UserData : public base::SupportsUserData::Data { ...@@ -73,6 +73,10 @@ class UserData : public base::SupportsUserData::Data {
} // namespace } // namespace
AwContentsClientBridge::HttpErrorInfo::HttpErrorInfo() : status_code(0) {}
AwContentsClientBridge::HttpErrorInfo::~HttpErrorInfo() {}
// static // static
void AwContentsClientBridge::Associate(WebContents* web_contents, void AwContentsClientBridge::Associate(WebContents* web_contents,
AwContentsClientBridge* handler) { AwContentsClientBridge* handler) {
...@@ -478,7 +482,7 @@ void AwContentsClientBridge::OnSafeBrowsingHit( ...@@ -478,7 +482,7 @@ void AwContentsClientBridge::OnSafeBrowsingHit(
void AwContentsClientBridge::OnReceivedHttpError( void AwContentsClientBridge::OnReceivedHttpError(
const AwWebResourceRequest& request, const AwWebResourceRequest& request,
const scoped_refptr<const net::HttpResponseHeaders>& response_headers) { std::unique_ptr<HttpErrorInfo> http_error_info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
JNIEnv* env = AttachCurrentThread(); JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
...@@ -488,42 +492,48 @@ void AwContentsClientBridge::OnReceivedHttpError( ...@@ -488,42 +492,48 @@ void AwContentsClientBridge::OnReceivedHttpError(
AwWebResourceRequest::AwJavaWebResourceRequest java_web_resource_request; AwWebResourceRequest::AwJavaWebResourceRequest java_web_resource_request;
AwWebResourceRequest::ConvertToJava(env, request, &java_web_resource_request); AwWebResourceRequest::ConvertToJava(env, request, &java_web_resource_request);
vector<std::string> response_header_names;
vector<std::string> response_header_values;
{
size_t headers_iterator = 0;
std::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);
}
}
std::string mime_type, encoding;
response_headers->GetMimeTypeAndCharset(&mime_type, &encoding);
ScopedJavaLocalRef<jstring> jstring_mime_type = ScopedJavaLocalRef<jstring> jstring_mime_type =
ConvertUTF8ToJavaString(env, mime_type); ConvertUTF8ToJavaString(env, http_error_info->mime_type);
ScopedJavaLocalRef<jstring> jstring_encoding = ScopedJavaLocalRef<jstring> jstring_encoding =
ConvertUTF8ToJavaString(env, encoding); ConvertUTF8ToJavaString(env, http_error_info->encoding);
int status_code = response_headers->response_code();
ScopedJavaLocalRef<jstring> jstring_reason = ScopedJavaLocalRef<jstring> jstring_reason =
ConvertUTF8ToJavaString(env, response_headers->GetStatusText()); ConvertUTF8ToJavaString(env, http_error_info->status_text);
ScopedJavaLocalRef<jobjectArray> jstringArray_response_header_names = ScopedJavaLocalRef<jobjectArray> jstringArray_response_header_names =
ToJavaArrayOfStrings(env, response_header_names); ToJavaArrayOfStrings(env, http_error_info->response_header_names);
ScopedJavaLocalRef<jobjectArray> jstringArray_response_header_values = ScopedJavaLocalRef<jobjectArray> jstringArray_response_header_values =
ToJavaArrayOfStrings(env, response_header_values); ToJavaArrayOfStrings(env, http_error_info->response_header_values);
Java_AwContentsClientBridge_onReceivedHttpError( Java_AwContentsClientBridge_onReceivedHttpError(
env, obj, java_web_resource_request.jurl, request.is_main_frame, env, obj, java_web_resource_request.jurl, request.is_main_frame,
request.has_user_gesture, java_web_resource_request.jmethod, request.has_user_gesture, java_web_resource_request.jmethod,
java_web_resource_request.jheader_names, java_web_resource_request.jheader_names,
java_web_resource_request.jheader_values, jstring_mime_type, java_web_resource_request.jheader_values, jstring_mime_type,
jstring_encoding, status_code, jstring_reason, jstring_encoding, http_error_info->status_code, jstring_reason,
jstringArray_response_header_names, jstringArray_response_header_values); jstringArray_response_header_names, jstringArray_response_header_values);
} }
// static
std::unique_ptr<AwContentsClientBridge::HttpErrorInfo>
AwContentsClientBridge::ExtractHttpErrorInfo(
const net::HttpResponseHeaders* response_headers) {
auto http_error_info = std::make_unique<HttpErrorInfo>();
{
size_t headers_iterator = 0;
std::string header_name, header_value;
while (response_headers->EnumerateHeaderLines(
&headers_iterator, &header_name, &header_value)) {
http_error_info->response_header_names.push_back(header_name);
http_error_info->response_header_values.push_back(header_value);
}
}
response_headers->GetMimeTypeAndCharset(&http_error_info->mime_type,
&http_error_info->encoding);
http_error_info->status_code = response_headers->response_code();
http_error_info->status_text = response_headers->GetStatusText();
return http_error_info;
}
void AwContentsClientBridge::ConfirmJsResult(JNIEnv* env, void AwContentsClientBridge::ConfirmJsResult(JNIEnv* env,
const JavaRef<jobject>&, const JavaRef<jobject>&,
int id, int id,
......
...@@ -43,6 +43,20 @@ namespace android_webview { ...@@ -43,6 +43,20 @@ namespace android_webview {
// any references. // any references.
class AwContentsClientBridge { class AwContentsClientBridge {
public: public:
// Used to package up information needed by OnReceivedHttpError for transfer
// between IO and UI threads.
struct HttpErrorInfo {
HttpErrorInfo();
~HttpErrorInfo();
int status_code;
std::string status_text;
std::string mime_type;
std::string encoding;
std::vector<std::string> response_header_names;
std::vector<std::string> response_header_values;
};
using CertErrorCallback = using CertErrorCallback =
base::OnceCallback<void(content::CertificateRequestResultType)>; base::OnceCallback<void(content::CertificateRequestResultType)>;
using SafeBrowsingActionCallback = using SafeBrowsingActionCallback =
...@@ -110,9 +124,12 @@ class AwContentsClientBridge { ...@@ -110,9 +124,12 @@ class AwContentsClientBridge {
SafeBrowsingActionCallback callback); SafeBrowsingActionCallback callback);
// Called when a response from the server is received with status code >= 400. // Called when a response from the server is received with status code >= 400.
void OnReceivedHttpError( void OnReceivedHttpError(const AwWebResourceRequest& request,
const AwWebResourceRequest& request, std::unique_ptr<HttpErrorInfo> error_info);
const scoped_refptr<const net::HttpResponseHeaders>& response_headers);
// This should be called from IO thread.
static std::unique_ptr<HttpErrorInfo> ExtractHttpErrorInfo(
const net::HttpResponseHeaders* response_headers);
// Methods called from Java. // Methods called from Java.
void ProceedSslError(JNIEnv* env, void ProceedSslError(JNIEnv* env,
......
...@@ -28,7 +28,7 @@ namespace { ...@@ -28,7 +28,7 @@ namespace {
void OnReceivedHttpErrorOnUiThread( void OnReceivedHttpErrorOnUiThread(
const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
const AwWebResourceRequest& request, const AwWebResourceRequest& request,
scoped_refptr<const net::HttpResponseHeaders> original_response_headers) { std::unique_ptr<AwContentsClientBridge::HttpErrorInfo> http_error_info) {
AwContentsClientBridge* client = AwContentsClientBridge* client =
AwContentsClientBridge::FromWebContentsGetter(web_contents_getter); AwContentsClientBridge::FromWebContentsGetter(web_contents_getter);
if (!client) { if (!client) {
...@@ -36,7 +36,7 @@ void OnReceivedHttpErrorOnUiThread( ...@@ -36,7 +36,7 @@ void OnReceivedHttpErrorOnUiThread(
<< request.url; << request.url;
return; return;
} }
client->OnReceivedHttpError(request, original_response_headers); client->OnReceivedHttpError(request, std::move(http_error_info));
} }
} // namespace } // namespace
...@@ -74,14 +74,16 @@ int AwNetworkDelegate::OnHeadersReceived( ...@@ -74,14 +74,16 @@ int AwNetworkDelegate::OnHeadersReceived(
// A request info may not exist for requests not originating from content. // A request info may not exist for requests not originating from content.
if (request_info == nullptr) if (request_info == nullptr)
return net::OK; return net::OK;
// keep a ref before binding and posting to UI thread.
scoped_refptr<const net::HttpResponseHeaders> response_headers( // extract out the info we need before posting to UI thread.
original_response_headers); std::unique_ptr<AwContentsClientBridge::HttpErrorInfo> error_info =
AwContentsClientBridge::ExtractHttpErrorInfo(original_response_headers);
BrowserThread::PostTask( BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE, BrowserThread::UI, FROM_HERE,
base::BindOnce(&OnReceivedHttpErrorOnUiThread, base::BindOnce(&OnReceivedHttpErrorOnUiThread,
request_info->GetWebContentsGetterForRequest(), request_info->GetWebContentsGetterForRequest(),
AwWebResourceRequest(*request), response_headers)); AwWebResourceRequest(*request), std::move(error_info)));
} }
return net::OK; return net::OK;
} }
......
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