native/request_handler.cpp (219 lines of code) (raw):

// Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. #include "request_handler.h" #include "client_handler.h" #include "jni_util.h" #include "resource_handler.h" #include "resource_request_handler.h" #include "util.h" #include "include/base/cef_logging.h" namespace { jobject NewCefX509Certificate(JNIEnv_* env, CefRefPtr<CefX509Certificate> ssl_info) { ScopedJNIClass byteArrayCls(env, env->FindClass("[B")); if (!byteArrayCls) { if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear(); } return nullptr; } CefX509Certificate::IssuerChainBinaryList der_chain; ssl_info->GetDEREncodedIssuerChain(der_chain); der_chain.insert(der_chain.begin(), ssl_info->GetDEREncoded()); ScopedJNIObjectLocal certificatesChain( env, env->NewObjectArray(static_cast<int>(der_chain.size()), byteArrayCls, nullptr)); for (size_t i = 0; i < der_chain.size(); ++i) { const auto& der_cert = der_chain[i]; ScopedJNIObjectLocal derArray( env, env->NewByteArray((jsize)der_cert->GetSize())); { void* buf = env->GetPrimitiveArrayCritical((jarray)derArray.get(), 0); der_cert->GetData(buf, der_cert->GetSize(), 0); env->ReleasePrimitiveArrayCritical((jarray)derArray.get(), buf, 0); } env->SetObjectArrayElement((jobjectArray)certificatesChain.get(), (jsize)i, derArray); } return NewJNIObject(env, "org/cef/security/CefX509Certificate", "([[B)V", certificatesChain.get()); } jobject NewCefSSLInfo(JNIEnv_* env, CefRefPtr<CefSSLInfo> ssl_info) { ScopedJNIObjectLocal certificate( env, NewCefX509Certificate(env, ssl_info->GetX509Certificate())); return NewJNIObject(env, "org/cef/security/CefSSLInfo", "(ILorg/cef/security/CefX509Certificate;)V", ssl_info.get()->GetCertStatus(), certificate.get()); } } // namespace RequestHandler::RequestHandler(JNIEnv* env, jobject handler) : handle_(env, handler) {} bool RequestHandler::OnBeforeBrowse(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, bool user_gesture, bool is_redirect) { // Forward request to ClientHandler to make the message_router_ happy. CefRefPtr<ClientHandler> client = (ClientHandler*)browser->GetHost()->GetClient().get(); client->OnBeforeBrowse(browser, frame); ScopedJNIEnv env; if (!env) return false; ScopedJNIBrowser jbrowser(env, browser); ScopedJNIFrame jframe(env, frame); jframe.SetTemporary(); ScopedJNIRequest jrequest(env, request); jrequest.SetTemporary(); jboolean jresult = JNI_FALSE; JNI_CALL_METHOD(env, handle_, "onBeforeBrowse", "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;Lorg/" "cef/network/CefRequest;ZZ)Z", Boolean, jresult, jbrowser.get(), jframe.get(), jrequest.get(), (user_gesture ? JNI_TRUE : JNI_FALSE), (is_redirect ? JNI_TRUE : JNI_FALSE)); return (jresult != JNI_FALSE); } bool RequestHandler::OnOpenURLFromTab(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, const CefString& target_url, WindowOpenDisposition target_disposition, bool user_gesture) { ScopedJNIEnv env; if (!env) return false; ScopedJNIBrowser jbrowser(env, browser); ScopedJNIFrame jframe(env, frame); jframe.SetTemporary(); ScopedJNIString jtargetUrl(env, target_url); jboolean jresult = JNI_FALSE; JNI_CALL_METHOD(env, handle_, "onOpenURLFromTab", "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;" "Ljava/lang/String;Z)Z", Boolean, jresult, jbrowser.get(), jframe.get(), jtargetUrl.get(), (user_gesture ? JNI_TRUE : JNI_FALSE)); return (jresult != JNI_FALSE); } CefRefPtr<CefResourceRequestHandler> RequestHandler::GetResourceRequestHandler( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, bool is_navigation, bool is_download, const CefString& request_initiator, bool& disable_default_handling) { ScopedJNIEnv env; if (!env) return nullptr; ScopedJNIBrowser jbrowser(env, browser); ScopedJNIFrame jframe(env, frame); jframe.SetTemporary(); ScopedJNIRequest jrequest(env, request); jrequest.SetTemporary(); ScopedJNIString jrequestInitiator(env, request_initiator); ScopedJNIBoolRef jdisableDefaultHandling(env, disable_default_handling); ScopedJNIObjectResult jresult(env); JNI_CALL_METHOD(env, handle_, "getResourceRequestHandler", "(Lorg/cef/browser/CefBrowser;Lorg/cef/browser/CefFrame;Lorg/" "cef/network/CefRequest;ZZLjava/lang/String;Lorg/cef/misc/" "BoolRef;)Lorg/cef/handler/CefResourceRequestHandler;", Object, jresult, jbrowser.get(), jframe.get(), jrequest.get(), is_navigation ? JNI_TRUE : JNI_FALSE, is_download ? JNI_TRUE : JNI_FALSE, jrequestInitiator.get(), jdisableDefaultHandling.get()); disable_default_handling = jdisableDefaultHandling; if (jresult) return new ResourceRequestHandler(env, jresult); return nullptr; } bool RequestHandler::GetAuthCredentials(CefRefPtr<CefBrowser> browser, const CefString& origin_url, bool isProxy, const CefString& host, int port, const CefString& realm, const CefString& scheme, CefRefPtr<CefAuthCallback> callback) { ScopedJNIEnv env; if (!env) return false; ScopedJNIBrowser jbrowser(env, browser); ScopedJNIString joriginUrl(env, origin_url); ScopedJNIString jhost(env, host); ScopedJNIString jrealm(env, realm); ScopedJNIString jscheme(env, scheme); ScopedJNIAuthCallback jcallback(env, callback); jboolean jresult = JNI_FALSE; JNI_CALL_METHOD( env, handle_, "getAuthCredentials", "(Lorg/cef/browser/CefBrowser;Ljava/lang/String;ZLjava/lang/String;" "ILjava/lang/String;Ljava/lang/String;" "Lorg/cef/callback/CefAuthCallback;)Z", Boolean, jresult, jbrowser.get(), joriginUrl.get(), (isProxy ? JNI_TRUE : JNI_FALSE), jhost.get(), port, jrealm.get(), jscheme.get(), jcallback.get()); if (jresult == JNI_FALSE) { // If the Java method returns "false" the callback won't be used and // the reference can therefore be removed. jcallback.SetTemporary(); } return (jresult != JNI_FALSE); } bool RequestHandler::OnCertificateError(CefRefPtr<CefBrowser> browser, cef_errorcode_t cert_error, const CefString& request_url, CefRefPtr<CefSSLInfo> ssl_info, CefRefPtr<CefCallback> callback) { ScopedJNIEnv env; if (!env) return false; ScopedJNIBrowser jbrowser(env, browser); ScopedJNIObjectLocal jcertError(env, NewJNIErrorCode(env, cert_error)); ScopedJNIString jrequestUrl(env, request_url); ScopedJNIObjectLocal jSSLInfo(env, NewCefSSLInfo(env, ssl_info)); ScopedJNICallback jcallback(env, callback); jboolean jresult = JNI_FALSE; JNI_CALL_METHOD( env, handle_, "onCertificateError", "(Lorg/cef/browser/CefBrowser;Lorg/cef/handler/CefLoadHandler$ErrorCode;" "Ljava/lang/String;Lorg/cef/security/CefSSLInfo;Lorg/cef/callback/" "CefCallback;)Z", Boolean, jresult, jbrowser.get(), jcertError.get(), jrequestUrl.get(), jSSLInfo.get(), jcallback.get()); if (jresult == JNI_FALSE) { // If the Java method returns "false" the callback won't be used and // the reference can therefore be removed. jcallback.SetTemporary(); } return (jresult != JNI_FALSE); } void RequestHandler::OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser, TerminationStatus status, int error_code, const CefString& error_string) { // Forward request to ClientHandler to make the message_router_ happy. CefRefPtr<ClientHandler> client = (ClientHandler*)browser->GetHost()->GetClient().get(); client->OnRenderProcessTerminated(browser); ScopedJNIEnv env; if (!env) return; ScopedJNIBrowser jbrowser(env, browser); ScopedJNIObjectResult jstatus(env); switch (status) { JNI_CASE(env, "org/cef/handler/CefRequestHandler$TerminationStatus", TS_ABNORMAL_TERMINATION, jstatus); JNI_CASE(env, "org/cef/handler/CefRequestHandler$TerminationStatus", TS_PROCESS_WAS_KILLED, jstatus); JNI_CASE(env, "org/cef/handler/CefRequestHandler$TerminationStatus", TS_PROCESS_CRASHED, jstatus); JNI_CASE(env, "org/cef/handler/CefRequestHandler$TerminationStatus", TS_PROCESS_OOM, jstatus); JNI_CASE(env, "org/cef/handler/CefRequestHandler$TerminationStatus", TS_LAUNCH_FAILED, jstatus); JNI_CASE(env, "org/cef/handler/CefRequestHandler$TerminationStatus", TS_INTEGRITY_FAILURE, jstatus); JNI_CASE(env, "org/cef/handler/CefRequestHandler$TerminationStatus", TS_NUM_VALUES, jstatus); } ScopedJNIString jerrorString(env, error_string); JNI_CALL_VOID_METHOD(env, handle_, "onRenderProcessTerminated", "(Lorg/cef/browser/CefBrowser;" "Lorg/cef/handler/CefRequestHandler$TerminationStatus;" "ILjava/lang/String;)V", jbrowser.get(), jstatus.get(), error_code, jerrorString.get()); }