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 {
} // namespace
AwContentsClientBridge::HttpErrorInfo::HttpErrorInfo() : status_code(0) {}
AwContentsClientBridge::HttpErrorInfo::~HttpErrorInfo() {}
// static
void AwContentsClientBridge::Associate(WebContents* web_contents,
AwContentsClientBridge* handler) {
......@@ -478,7 +482,7 @@ void AwContentsClientBridge::OnSafeBrowsingHit(
void AwContentsClientBridge::OnReceivedHttpError(
const AwWebResourceRequest& request,
const scoped_refptr<const net::HttpResponseHeaders>& response_headers) {
std::unique_ptr<HttpErrorInfo> http_error_info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
......@@ -488,42 +492,48 @@ void AwContentsClientBridge::OnReceivedHttpError(
AwWebResourceRequest::AwJavaWebResourceRequest 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 =
ConvertUTF8ToJavaString(env, mime_type);
ConvertUTF8ToJavaString(env, http_error_info->mime_type);
ScopedJavaLocalRef<jstring> jstring_encoding =
ConvertUTF8ToJavaString(env, encoding);
int status_code = response_headers->response_code();
ConvertUTF8ToJavaString(env, http_error_info->encoding);
ScopedJavaLocalRef<jstring> jstring_reason =
ConvertUTF8ToJavaString(env, response_headers->GetStatusText());
ConvertUTF8ToJavaString(env, http_error_info->status_text);
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 =
ToJavaArrayOfStrings(env, response_header_values);
ToJavaArrayOfStrings(env, http_error_info->response_header_values);
Java_AwContentsClientBridge_onReceivedHttpError(
env, obj, java_web_resource_request.jurl, request.is_main_frame,
request.has_user_gesture, java_web_resource_request.jmethod,
java_web_resource_request.jheader_names,
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);
}
// 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,
const JavaRef<jobject>&,
int id,
......
......@@ -43,6 +43,20 @@ namespace android_webview {
// any references.
class AwContentsClientBridge {
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 =
base::OnceCallback<void(content::CertificateRequestResultType)>;
using SafeBrowsingActionCallback =
......@@ -110,9 +124,12 @@ class AwContentsClientBridge {
SafeBrowsingActionCallback callback);
// Called when a response from the server is received with status code >= 400.
void OnReceivedHttpError(
const AwWebResourceRequest& request,
const scoped_refptr<const net::HttpResponseHeaders>& response_headers);
void OnReceivedHttpError(const AwWebResourceRequest& request,
std::unique_ptr<HttpErrorInfo> error_info);
// This should be called from IO thread.
static std::unique_ptr<HttpErrorInfo> ExtractHttpErrorInfo(
const net::HttpResponseHeaders* response_headers);
// Methods called from Java.
void ProceedSslError(JNIEnv* env,
......
......@@ -28,7 +28,7 @@ namespace {
void OnReceivedHttpErrorOnUiThread(
const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
const AwWebResourceRequest& request,
scoped_refptr<const net::HttpResponseHeaders> original_response_headers) {
std::unique_ptr<AwContentsClientBridge::HttpErrorInfo> http_error_info) {
AwContentsClientBridge* client =
AwContentsClientBridge::FromWebContentsGetter(web_contents_getter);
if (!client) {
......@@ -36,7 +36,7 @@ void OnReceivedHttpErrorOnUiThread(
<< request.url;
return;
}
client->OnReceivedHttpError(request, original_response_headers);
client->OnReceivedHttpError(request, std::move(http_error_info));
}
} // namespace
......@@ -74,14 +74,16 @@ int AwNetworkDelegate::OnHeadersReceived(
// A request info may not exist for requests not originating from content.
if (request_info == nullptr)
return net::OK;
// keep a ref before binding and posting to UI thread.
scoped_refptr<const net::HttpResponseHeaders> response_headers(
original_response_headers);
// extract out the info we need before posting to UI thread.
std::unique_ptr<AwContentsClientBridge::HttpErrorInfo> error_info =
AwContentsClientBridge::ExtractHttpErrorInfo(original_response_headers);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&OnReceivedHttpErrorOnUiThread,
request_info->GetWebContentsGetterForRequest(),
AwWebResourceRequest(*request), response_headers));
AwWebResourceRequest(*request), std::move(error_info)));
}
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