1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "android_webview/browser/aw_contents_client_bridge.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "android_webview/browser_jni_headers/AwContentsClientBridge_jni.h"
11 #include "android_webview/common/devtools_instrumentation.h"
12 #include "android_webview/grit/components_strings.h"
13 #include "base/android/jni_android.h"
14 #include "base/android/jni_array.h"
15 #include "base/android/jni_string.h"
16 #include "base/macros.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/task/current_thread.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/client_certificate_delegate.h"
21 #include "content/public/browser/render_frame_host.h"
22 #include "content/public/browser/render_process_host.h"
23 #include "content/public/browser/web_contents.h"
24 #include "net/cert/x509_certificate.h"
25 #include "net/cert/x509_util.h"
26 #include "net/http/http_response_headers.h"
27 #include "net/ssl/ssl_cert_request_info.h"
28 #include "net/ssl/ssl_client_cert_type.h"
29 #include "net/ssl/ssl_platform_key_android.h"
30 #include "net/ssl/ssl_private_key.h"
31 #include "ui/base/l10n/l10n_util.h"
32 #include "url/gurl.h"
33
34 using base::android::AttachCurrentThread;
35 using base::android::ConvertJavaStringToUTF16;
36 using base::android::ConvertUTF8ToJavaString;
37 using base::android::ConvertUTF16ToJavaString;
38 using base::android::HasException;
39 using base::android::JavaRef;
40 using base::android::ScopedJavaLocalRef;
41 using base::android::ToJavaArrayOfStrings;
42 using content::BrowserThread;
43 using content::WebContents;
44 using std::vector;
45
46 namespace android_webview {
47
48 namespace {
49
50 const void* const kAwContentsClientBridge = &kAwContentsClientBridge;
51
52 // This class is invented so that the UserData registry that we inject the
53 // AwContentsClientBridge object does not own and destroy it.
54 class UserData : public base::SupportsUserData::Data {
55 public:
GetContents(content::WebContents * web_contents)56 static AwContentsClientBridge* GetContents(
57 content::WebContents* web_contents) {
58 if (!web_contents)
59 return NULL;
60 UserData* data = static_cast<UserData*>(
61 web_contents->GetUserData(kAwContentsClientBridge));
62 return data ? data->contents_ : NULL;
63 }
64
UserData(AwContentsClientBridge * ptr)65 explicit UserData(AwContentsClientBridge* ptr) : contents_(ptr) {}
66
67 private:
68 AwContentsClientBridge* contents_;
69
70 DISALLOW_COPY_AND_ASSIGN(UserData);
71 };
72
73 } // namespace
74
HttpErrorInfo()75 AwContentsClientBridge::HttpErrorInfo::HttpErrorInfo() : status_code(0) {}
76
~HttpErrorInfo()77 AwContentsClientBridge::HttpErrorInfo::~HttpErrorInfo() {}
78
79 // static
Associate(WebContents * web_contents,AwContentsClientBridge * handler)80 void AwContentsClientBridge::Associate(WebContents* web_contents,
81 AwContentsClientBridge* handler) {
82 web_contents->SetUserData(kAwContentsClientBridge,
83 std::make_unique<UserData>(handler));
84 }
85
86 // static
Dissociate(WebContents * web_contents)87 void AwContentsClientBridge::Dissociate(WebContents* web_contents) {
88 web_contents->RemoveUserData(kAwContentsClientBridge);
89 }
90
91 // static
FromWebContents(WebContents * web_contents)92 AwContentsClientBridge* AwContentsClientBridge::FromWebContents(
93 WebContents* web_contents) {
94 return UserData::GetContents(web_contents);
95 }
96
97 // static
FromWebContentsGetter(const content::WebContents::Getter & web_contents_getter)98 AwContentsClientBridge* AwContentsClientBridge::FromWebContentsGetter(
99 const content::WebContents::Getter& web_contents_getter) {
100 DCHECK_CURRENTLY_ON(BrowserThread::UI);
101 WebContents* web_contents = web_contents_getter.Run();
102 return UserData::GetContents(web_contents);
103 }
104
105 // static
FromID(int render_process_id,int render_frame_id)106 AwContentsClientBridge* AwContentsClientBridge::FromID(int render_process_id,
107 int render_frame_id) {
108 DCHECK_CURRENTLY_ON(BrowserThread::UI);
109 content::RenderFrameHost* rfh =
110 content::RenderFrameHost::FromID(render_process_id, render_frame_id);
111 content::WebContents* web_contents =
112 content::WebContents::FromRenderFrameHost(rfh);
113 return UserData::GetContents(web_contents);
114 }
115
AwContentsClientBridge(JNIEnv * env,const JavaRef<jobject> & obj)116 AwContentsClientBridge::AwContentsClientBridge(JNIEnv* env,
117 const JavaRef<jobject>& obj)
118 : java_ref_(env, obj) {
119 DCHECK(obj);
120 Java_AwContentsClientBridge_setNativeContentsClientBridge(
121 env, obj, reinterpret_cast<intptr_t>(this));
122 }
123
~AwContentsClientBridge()124 AwContentsClientBridge::~AwContentsClientBridge() {
125 JNIEnv* env = AttachCurrentThread();
126
127 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
128 if (obj) {
129 // Clear the weak reference from the java peer to the native object since
130 // it is possible that java object lifetime can exceed the AwContens.
131 Java_AwContentsClientBridge_setNativeContentsClientBridge(env, obj, 0);
132 }
133 }
134
AllowCertificateError(int cert_error,net::X509Certificate * cert,const GURL & request_url,CertErrorCallback callback,bool * cancel_request)135 void AwContentsClientBridge::AllowCertificateError(int cert_error,
136 net::X509Certificate* cert,
137 const GURL& request_url,
138 CertErrorCallback callback,
139 bool* cancel_request) {
140 DCHECK_CURRENTLY_ON(BrowserThread::UI);
141 JNIEnv* env = AttachCurrentThread();
142
143 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
144 if (!obj)
145 return;
146
147 base::StringPiece der_string =
148 net::x509_util::CryptoBufferAsStringPiece(cert->cert_buffer());
149 ScopedJavaLocalRef<jbyteArray> jcert = base::android::ToJavaByteArray(
150 env, reinterpret_cast<const uint8_t*>(der_string.data()),
151 der_string.length());
152 ScopedJavaLocalRef<jstring> jurl(
153 ConvertUTF8ToJavaString(env, request_url.spec()));
154 // We need to add the callback before making the call to java side,
155 // as it may do a synchronous callback prior to returning.
156 int request_id = pending_cert_error_callbacks_.Add(
157 std::make_unique<CertErrorCallback>(std::move(callback)));
158 *cancel_request = !Java_AwContentsClientBridge_allowCertificateError(
159 env, obj, cert_error, jcert, jurl, request_id);
160 // if the request is cancelled, then cancel the stored callback
161 if (*cancel_request) {
162 pending_cert_error_callbacks_.Remove(request_id);
163 }
164 }
165
ProceedSslError(JNIEnv * env,const JavaRef<jobject> & obj,jboolean proceed,jint id)166 void AwContentsClientBridge::ProceedSslError(JNIEnv* env,
167 const JavaRef<jobject>& obj,
168 jboolean proceed,
169 jint id) {
170 DCHECK_CURRENTLY_ON(BrowserThread::UI);
171 CertErrorCallback* callback = pending_cert_error_callbacks_.Lookup(id);
172 if (!callback || callback->is_null()) {
173 LOG(WARNING) << "Ignoring unexpected ssl error proceed callback";
174 return;
175 }
176 std::move(*callback).Run(
177 proceed ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE
178 : content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL);
179 pending_cert_error_callbacks_.Remove(id);
180 }
181
182 // This method is inspired by SelectClientCertificate() in
183 // components/browser_ui/client_certificate/android/
184 // ssl_client_certificate_request.cc
SelectClientCertificate(net::SSLCertRequestInfo * cert_request_info,std::unique_ptr<content::ClientCertificateDelegate> delegate)185 void AwContentsClientBridge::SelectClientCertificate(
186 net::SSLCertRequestInfo* cert_request_info,
187 std::unique_ptr<content::ClientCertificateDelegate> delegate) {
188 DCHECK_CURRENTLY_ON(BrowserThread::UI);
189
190 JNIEnv* env = base::android::AttachCurrentThread();
191 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
192 if (!obj)
193 return;
194
195 // Build the |key_types| JNI parameter, as a String[]
196 std::vector<std::string> key_types;
197 for (size_t i = 0; i < cert_request_info->cert_key_types.size(); ++i) {
198 switch (cert_request_info->cert_key_types[i]) {
199 case net::CLIENT_CERT_RSA_SIGN:
200 key_types.push_back("RSA");
201 break;
202 case net::CLIENT_CERT_ECDSA_SIGN:
203 key_types.push_back("ECDSA");
204 break;
205 default:
206 // Ignore unknown types.
207 break;
208 }
209 }
210
211 ScopedJavaLocalRef<jobjectArray> key_types_ref =
212 base::android::ToJavaArrayOfStrings(env, key_types);
213 if (!key_types_ref) {
214 LOG(ERROR) << "Could not create key types array (String[])";
215 return;
216 }
217
218 // Build the |encoded_principals| JNI parameter, as a byte[][]
219 ScopedJavaLocalRef<jobjectArray> principals_ref =
220 base::android::ToJavaArrayOfByteArray(
221 env, cert_request_info->cert_authorities);
222 if (!principals_ref) {
223 LOG(ERROR) << "Could not create principals array (byte[][])";
224 return;
225 }
226
227 // Build the |host_name| and |port| JNI parameters, as a String and
228 // a jint.
229 ScopedJavaLocalRef<jstring> host_name_ref =
230 base::android::ConvertUTF8ToJavaString(
231 env, cert_request_info->host_and_port.host());
232
233 int request_id =
234 pending_client_cert_request_delegates_.Add(std::move(delegate));
235 Java_AwContentsClientBridge_selectClientCertificate(
236 env, obj, request_id, key_types_ref, principals_ref, host_name_ref,
237 cert_request_info->host_and_port.port());
238 }
239
240 // This method is inspired by OnSystemRequestCompletion() in
241 // components/browser_ui/client_certificate/android/
242 // ssl_client_certificate_request.cc
ProvideClientCertificateResponse(JNIEnv * env,const JavaRef<jobject> & obj,int request_id,const JavaRef<jobjectArray> & encoded_chain_ref,const JavaRef<jobject> & private_key_ref)243 void AwContentsClientBridge::ProvideClientCertificateResponse(
244 JNIEnv* env,
245 const JavaRef<jobject>& obj,
246 int request_id,
247 const JavaRef<jobjectArray>& encoded_chain_ref,
248 const JavaRef<jobject>& private_key_ref) {
249 DCHECK_CURRENTLY_ON(BrowserThread::UI);
250
251 std::unique_ptr<content::ClientCertificateDelegate> delegate =
252 pending_client_cert_request_delegates_.Replace(request_id, nullptr);
253 pending_client_cert_request_delegates_.Remove(request_id);
254 DCHECK(delegate);
255
256 if (!encoded_chain_ref || !private_key_ref) {
257 LOG(ERROR) << "No client certificate selected";
258 delegate->ContinueWithCertificate(nullptr, nullptr);
259 return;
260 }
261
262 // Convert the encoded chain to a vector of strings.
263 std::vector<std::string> encoded_chain_strings;
264 if (encoded_chain_ref) {
265 base::android::JavaArrayOfByteArrayToStringVector(env, encoded_chain_ref,
266 &encoded_chain_strings);
267 }
268
269 std::vector<base::StringPiece> encoded_chain;
270 for (size_t i = 0; i < encoded_chain_strings.size(); ++i)
271 encoded_chain.push_back(encoded_chain_strings[i]);
272
273 // Create the X509Certificate object from the encoded chain.
274 scoped_refptr<net::X509Certificate> client_cert(
275 net::X509Certificate::CreateFromDERCertChain(encoded_chain));
276 if (!client_cert.get()) {
277 LOG(ERROR) << "Could not decode client certificate chain";
278 return;
279 }
280
281 // Create an SSLPrivateKey wrapper for the private key JNI reference.
282 scoped_refptr<net::SSLPrivateKey> private_key =
283 net::WrapJavaPrivateKey(client_cert.get(), private_key_ref);
284 if (!private_key) {
285 LOG(ERROR) << "Could not create OpenSSL wrapper for private key";
286 return;
287 }
288
289 delegate->ContinueWithCertificate(std::move(client_cert),
290 std::move(private_key));
291 }
292
RunJavaScriptDialog(content::JavaScriptDialogType dialog_type,const GURL & origin_url,const base::string16 & message_text,const base::string16 & default_prompt_text,content::JavaScriptDialogManager::DialogClosedCallback callback)293 void AwContentsClientBridge::RunJavaScriptDialog(
294 content::JavaScriptDialogType dialog_type,
295 const GURL& origin_url,
296 const base::string16& message_text,
297 const base::string16& default_prompt_text,
298 content::JavaScriptDialogManager::DialogClosedCallback callback) {
299 DCHECK_CURRENTLY_ON(BrowserThread::UI);
300 JNIEnv* env = AttachCurrentThread();
301
302 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
303 if (!obj) {
304 std::move(callback).Run(false, base::string16());
305 return;
306 }
307
308 int callback_id = pending_js_dialog_callbacks_.Add(
309 std::make_unique<content::JavaScriptDialogManager::DialogClosedCallback>(
310 std::move(callback)));
311 ScopedJavaLocalRef<jstring> jurl(
312 ConvertUTF8ToJavaString(env, origin_url.spec()));
313 ScopedJavaLocalRef<jstring> jmessage(
314 ConvertUTF16ToJavaString(env, message_text));
315
316 switch (dialog_type) {
317 case content::JAVASCRIPT_DIALOG_TYPE_ALERT: {
318 devtools_instrumentation::ScopedEmbedderCallbackTask("onJsAlert");
319 Java_AwContentsClientBridge_handleJsAlert(env, obj, jurl, jmessage,
320 callback_id);
321 break;
322 }
323 case content::JAVASCRIPT_DIALOG_TYPE_CONFIRM: {
324 devtools_instrumentation::ScopedEmbedderCallbackTask("onJsConfirm");
325 Java_AwContentsClientBridge_handleJsConfirm(env, obj, jurl, jmessage,
326 callback_id);
327 break;
328 }
329 case content::JAVASCRIPT_DIALOG_TYPE_PROMPT: {
330 ScopedJavaLocalRef<jstring> jdefault_value(
331 ConvertUTF16ToJavaString(env, default_prompt_text));
332 devtools_instrumentation::ScopedEmbedderCallbackTask("onJsPrompt");
333 Java_AwContentsClientBridge_handleJsPrompt(env, obj, jurl, jmessage,
334 jdefault_value, callback_id);
335 break;
336 }
337 default:
338 NOTREACHED();
339 }
340 }
341
RunBeforeUnloadDialog(const GURL & origin_url,content::JavaScriptDialogManager::DialogClosedCallback callback)342 void AwContentsClientBridge::RunBeforeUnloadDialog(
343 const GURL& origin_url,
344 content::JavaScriptDialogManager::DialogClosedCallback callback) {
345 DCHECK_CURRENTLY_ON(BrowserThread::UI);
346 JNIEnv* env = AttachCurrentThread();
347
348 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
349 if (!obj) {
350 std::move(callback).Run(false, base::string16());
351 return;
352 }
353
354 const base::string16 message_text =
355 l10n_util::GetStringUTF16(IDS_BEFOREUNLOAD_MESSAGEBOX_MESSAGE);
356
357 int callback_id = pending_js_dialog_callbacks_.Add(
358 std::make_unique<content::JavaScriptDialogManager::DialogClosedCallback>(
359 std::move(callback)));
360 ScopedJavaLocalRef<jstring> jurl(
361 ConvertUTF8ToJavaString(env, origin_url.spec()));
362 ScopedJavaLocalRef<jstring> jmessage(
363 ConvertUTF16ToJavaString(env, message_text));
364
365 devtools_instrumentation::ScopedEmbedderCallbackTask("onJsBeforeUnload");
366 Java_AwContentsClientBridge_handleJsBeforeUnload(env, obj, jurl, jmessage,
367 callback_id);
368 }
369
ShouldOverrideUrlLoading(const base::string16 & url,bool has_user_gesture,bool is_redirect,bool is_main_frame,bool * ignore_navigation)370 bool AwContentsClientBridge::ShouldOverrideUrlLoading(const base::string16& url,
371 bool has_user_gesture,
372 bool is_redirect,
373 bool is_main_frame,
374 bool* ignore_navigation) {
375 *ignore_navigation = false;
376 JNIEnv* env = AttachCurrentThread();
377 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
378 if (!obj)
379 return true;
380 ScopedJavaLocalRef<jstring> jurl = ConvertUTF16ToJavaString(env, url);
381 devtools_instrumentation::ScopedEmbedderCallbackTask(
382 "shouldOverrideUrlLoading");
383 *ignore_navigation = Java_AwContentsClientBridge_shouldOverrideUrlLoading(
384 env, obj, jurl, has_user_gesture, is_redirect, is_main_frame);
385 if (HasException(env)) {
386 // Tell the chromium message loop to not perform any tasks after the current
387 // one - we want to make sure we return to Java cleanly without first making
388 // any new JNI calls.
389 base::CurrentUIThread::Get()->Abort();
390 // If we crashed we don't want to continue the navigation.
391 *ignore_navigation = true;
392 return false;
393 }
394 return true;
395 }
396
NewDownload(const GURL & url,const std::string & user_agent,const std::string & content_disposition,const std::string & mime_type,int64_t content_length)397 void AwContentsClientBridge::NewDownload(const GURL& url,
398 const std::string& user_agent,
399 const std::string& content_disposition,
400 const std::string& mime_type,
401 int64_t content_length) {
402 DCHECK_CURRENTLY_ON(BrowserThread::UI);
403 JNIEnv* env = AttachCurrentThread();
404 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
405 if (!obj)
406 return;
407
408 ScopedJavaLocalRef<jstring> jstring_url =
409 ConvertUTF8ToJavaString(env, url.spec());
410 ScopedJavaLocalRef<jstring> jstring_user_agent =
411 ConvertUTF8ToJavaString(env, user_agent);
412 ScopedJavaLocalRef<jstring> jstring_content_disposition =
413 ConvertUTF8ToJavaString(env, content_disposition);
414 ScopedJavaLocalRef<jstring> jstring_mime_type =
415 ConvertUTF8ToJavaString(env, mime_type);
416
417 Java_AwContentsClientBridge_newDownload(
418 env, obj, jstring_url, jstring_user_agent, jstring_content_disposition,
419 jstring_mime_type, content_length);
420 }
421
NewLoginRequest(const std::string & realm,const std::string & account,const std::string & args)422 void AwContentsClientBridge::NewLoginRequest(const std::string& realm,
423 const std::string& account,
424 const std::string& args) {
425 DCHECK_CURRENTLY_ON(BrowserThread::UI);
426 JNIEnv* env = AttachCurrentThread();
427 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
428 if (!obj)
429 return;
430
431 ScopedJavaLocalRef<jstring> jrealm = ConvertUTF8ToJavaString(env, realm);
432 ScopedJavaLocalRef<jstring> jargs = ConvertUTF8ToJavaString(env, args);
433
434 ScopedJavaLocalRef<jstring> jaccount;
435 if (!account.empty())
436 jaccount = ConvertUTF8ToJavaString(env, account);
437
438 Java_AwContentsClientBridge_newLoginRequest(env, obj, jrealm, jaccount,
439 jargs);
440 }
441
OnReceivedError(const AwWebResourceRequest & request,int error_code,bool safebrowsing_hit,bool should_omit_notifications_for_safebrowsing_hit)442 void AwContentsClientBridge::OnReceivedError(
443 const AwWebResourceRequest& request,
444 int error_code,
445 bool safebrowsing_hit,
446 bool should_omit_notifications_for_safebrowsing_hit) {
447 DCHECK(request.is_renderer_initiated.has_value());
448 DCHECK_CURRENTLY_ON(BrowserThread::UI);
449 JNIEnv* env = AttachCurrentThread();
450 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
451 if (!obj)
452 return;
453
454 ScopedJavaLocalRef<jstring> jstring_description =
455 ConvertUTF8ToJavaString(env, net::ErrorToString(error_code));
456
457 AwWebResourceRequest::AwJavaWebResourceRequest java_web_resource_request;
458 AwWebResourceRequest::ConvertToJava(env, request, &java_web_resource_request);
459 Java_AwContentsClientBridge_onReceivedError(
460 env, obj, java_web_resource_request.jurl, request.is_main_frame,
461 request.has_user_gesture, *request.is_renderer_initiated,
462 java_web_resource_request.jmethod,
463 java_web_resource_request.jheader_names,
464 java_web_resource_request.jheader_values, error_code, jstring_description,
465 safebrowsing_hit, should_omit_notifications_for_safebrowsing_hit);
466 }
467
OnSafeBrowsingHit(const AwWebResourceRequest & request,const safe_browsing::SBThreatType & threat_type,SafeBrowsingActionCallback callback)468 void AwContentsClientBridge::OnSafeBrowsingHit(
469 const AwWebResourceRequest& request,
470 const safe_browsing::SBThreatType& threat_type,
471 SafeBrowsingActionCallback callback) {
472 int request_id = safe_browsing_callbacks_.Add(
473 std::make_unique<SafeBrowsingActionCallback>(std::move(callback)));
474
475 DCHECK_CURRENTLY_ON(BrowserThread::UI);
476 JNIEnv* env = AttachCurrentThread();
477 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
478 if (!obj)
479 return;
480
481 AwWebResourceRequest::AwJavaWebResourceRequest java_web_resource_request;
482 AwWebResourceRequest::ConvertToJava(env, request, &java_web_resource_request);
483 Java_AwContentsClientBridge_onSafeBrowsingHit(
484 env, obj, java_web_resource_request.jurl, request.is_main_frame,
485 request.has_user_gesture, java_web_resource_request.jmethod,
486 java_web_resource_request.jheader_names,
487 java_web_resource_request.jheader_values, static_cast<int>(threat_type),
488 request_id);
489 }
490
OnReceivedHttpError(const AwWebResourceRequest & request,std::unique_ptr<HttpErrorInfo> http_error_info)491 void AwContentsClientBridge::OnReceivedHttpError(
492 const AwWebResourceRequest& request,
493 std::unique_ptr<HttpErrorInfo> http_error_info) {
494 DCHECK_CURRENTLY_ON(BrowserThread::UI);
495 JNIEnv* env = AttachCurrentThread();
496 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
497 if (!obj)
498 return;
499
500 AwWebResourceRequest::AwJavaWebResourceRequest java_web_resource_request;
501 AwWebResourceRequest::ConvertToJava(env, request, &java_web_resource_request);
502
503 ScopedJavaLocalRef<jstring> jstring_mime_type =
504 ConvertUTF8ToJavaString(env, http_error_info->mime_type);
505 ScopedJavaLocalRef<jstring> jstring_encoding =
506 ConvertUTF8ToJavaString(env, http_error_info->encoding);
507 ScopedJavaLocalRef<jstring> jstring_reason =
508 ConvertUTF8ToJavaString(env, http_error_info->status_text);
509 ScopedJavaLocalRef<jobjectArray> jstringArray_response_header_names =
510 ToJavaArrayOfStrings(env, http_error_info->response_header_names);
511 ScopedJavaLocalRef<jobjectArray> jstringArray_response_header_values =
512 ToJavaArrayOfStrings(env, http_error_info->response_header_values);
513
514 Java_AwContentsClientBridge_onReceivedHttpError(
515 env, obj, java_web_resource_request.jurl, request.is_main_frame,
516 request.has_user_gesture, java_web_resource_request.jmethod,
517 java_web_resource_request.jheader_names,
518 java_web_resource_request.jheader_values, jstring_mime_type,
519 jstring_encoding, http_error_info->status_code, jstring_reason,
520 jstringArray_response_header_names, jstringArray_response_header_values);
521 }
522
523 // static
524 std::unique_ptr<AwContentsClientBridge::HttpErrorInfo>
ExtractHttpErrorInfo(const net::HttpResponseHeaders * response_headers)525 AwContentsClientBridge::ExtractHttpErrorInfo(
526 const net::HttpResponseHeaders* response_headers) {
527 auto http_error_info = std::make_unique<HttpErrorInfo>();
528 {
529 size_t headers_iterator = 0;
530 std::string header_name, header_value;
531 while (response_headers->EnumerateHeaderLines(
532 &headers_iterator, &header_name, &header_value)) {
533 http_error_info->response_header_names.push_back(header_name);
534 http_error_info->response_header_values.push_back(header_value);
535 }
536 }
537
538 response_headers->GetMimeTypeAndCharset(&http_error_info->mime_type,
539 &http_error_info->encoding);
540 http_error_info->status_code = response_headers->response_code();
541 http_error_info->status_text = response_headers->GetStatusText();
542 return http_error_info;
543 }
544
ConfirmJsResult(JNIEnv * env,const JavaRef<jobject> &,int id,const JavaRef<jstring> & prompt)545 void AwContentsClientBridge::ConfirmJsResult(JNIEnv* env,
546 const JavaRef<jobject>&,
547 int id,
548 const JavaRef<jstring>& prompt) {
549 DCHECK_CURRENTLY_ON(BrowserThread::UI);
550 content::JavaScriptDialogManager::DialogClosedCallback* callback =
551 pending_js_dialog_callbacks_.Lookup(id);
552 if (!callback) {
553 LOG(WARNING) << "Unexpected JS dialog confirm. " << id;
554 return;
555 }
556 base::string16 prompt_text;
557 if (prompt) {
558 prompt_text = ConvertJavaStringToUTF16(env, prompt);
559 }
560 std::move(*callback).Run(true, prompt_text);
561 pending_js_dialog_callbacks_.Remove(id);
562 }
563
TakeSafeBrowsingAction(JNIEnv *,const JavaRef<jobject> &,int action,bool reporting,int request_id)564 void AwContentsClientBridge::TakeSafeBrowsingAction(JNIEnv*,
565 const JavaRef<jobject>&,
566 int action,
567 bool reporting,
568 int request_id) {
569 DCHECK_CURRENTLY_ON(BrowserThread::UI);
570 auto* callback = safe_browsing_callbacks_.Lookup(request_id);
571 if (!callback) {
572 LOG(WARNING) << "Unexpected TakeSafeBrowsingAction. " << request_id;
573 return;
574 }
575 std::move(*callback).Run(
576 static_cast<AwUrlCheckerDelegateImpl::SafeBrowsingAction>(action),
577 reporting);
578 safe_browsing_callbacks_.Remove(request_id);
579 }
580
CancelJsResult(JNIEnv *,const JavaRef<jobject> &,int id)581 void AwContentsClientBridge::CancelJsResult(JNIEnv*,
582 const JavaRef<jobject>&,
583 int id) {
584 DCHECK_CURRENTLY_ON(BrowserThread::UI);
585 content::JavaScriptDialogManager::DialogClosedCallback* callback =
586 pending_js_dialog_callbacks_.Lookup(id);
587 if (!callback) {
588 LOG(WARNING) << "Unexpected JS dialog cancel. " << id;
589 return;
590 }
591 std::move(*callback).Run(false, base::string16());
592 pending_js_dialog_callbacks_.Remove(id);
593 }
594
595 } // namespace android_webview
596