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