aw_contents_client_bridge.cc 22 KB

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