// Copyright (c) 2013 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 "client_handler.h"
#include
#include
#include
#include
#include
#include
#include "browser_process_handler.h"
#include "context_menu_handler.h"
#include "dialog_handler.h"
#include "display_handler.h"
#include "audio_handler.h"
#include "download_handler.h"
#include "drag_handler.h"
#include "focus_handler.h"
#include "jsdialog_handler.h"
#include "keyboard_handler.h"
#include "life_span_handler.h"
#include "load_handler.h"
#include "message_router_handler.h"
#include "print_handler.h"
#include "render_handler.h"
#include "request_handler.h"
#include "include/cef_browser.h"
#include "include/cef_frame.h"
#include "include/cef_parser.h"
#include "include/cef_path_util.h"
#include "include/cef_process_util.h"
#include "include/cef_trace.h"
#include "include/wrapper/cef_stream_resource_handler.h"
#include "jni_util.h"
#include "util.h"
namespace {
CefRefPtr GetMessageRouter(JNIEnv* env,
jobject jmessageRouter) {
ScopedJNIMessageRouter messageRouter(env);
messageRouter.SetHandle(jmessageRouter, false /* should_delete */);
return messageRouter.GetCefObject();
}
CefMessageRouterConfig GetMessageRouterConfig(JNIEnv* env,
jobject jmessageRouter) {
ScopedJNIObjectResult jrouterConfig(env);
JNI_CALL_METHOD(env, jmessageRouter, "getMessageRouterConfig",
"()Lorg/cef/browser/CefMessageRouter$CefMessageRouterConfig;",
Object, jrouterConfig);
return GetJNIMessageRouterConfig(env, jrouterConfig);
}
} // namespace
ClientHandler::ClientHandler(JNIEnv* env, jobject handler)
: handle_(env, handler) {}
template
CefRefPtr ClientHandler::GetHandler(const char* class_name) {
std::string methodName, className, methodSig;
std::stringstream ss;
ss << "get" << class_name;
methodName = ss.str();
ss.str(std::string());
ss << "Cef" << class_name;
className = ss.str();
ss.str(std::string());
ss << "()Lorg/cef/handler/" << className << ";";
methodSig = ss.str();
ScopedJNIEnv env;
if (!env)
return nullptr;
CefRefPtr result = nullptr;
ScopedJNIObjectResult jresult(env);
JNI_CALL_METHOD(env, handle_, methodName.c_str(), methodSig.c_str(), Object,
jresult);
if (jresult) {
ScopedJNIObject jhandler(env, jresult.Release(),
true /* should_delete */, className.c_str());
result = jhandler.GetOrCreateCefObject();
}
return result;
}
CefRefPtr ClientHandler::GetContextMenuHandler() {
return GetHandler("ContextMenuHandler");
}
CefRefPtr ClientHandler::GetDialogHandler() {
return GetHandler("DialogHandler");
}
CefRefPtr ClientHandler::GetDisplayHandler() {
return GetHandler("DisplayHandler");
}
CefRefPtr ClientHandler::GetAudioHandler() {
return GetHandler("AudioHandler");
}
CefRefPtr ClientHandler::GetDownloadHandler() {
return GetHandler("DownloadHandler");
}
CefRefPtr ClientHandler::GetDragHandler() {
return GetHandler("DragHandler");
}
CefRefPtr ClientHandler::GetFocusHandler() {
return GetHandler("FocusHandler");
}
CefRefPtr ClientHandler::GetJSDialogHandler() {
return GetHandler("JSDialogHandler");
}
CefRefPtr ClientHandler::GetKeyboardHandler() {
return GetHandler("KeyboardHandler");
}
CefRefPtr ClientHandler::GetLifeSpanHandler() {
return GetHandler("LifeSpanHandler");
}
CefRefPtr ClientHandler::GetLoadHandler() {
return GetHandler("LoadHandler");
}
CefRefPtr ClientHandler::GetPrintHandler() {
return GetHandler("PrintHandler");
}
CefRefPtr ClientHandler::GetRenderHandler() {
return GetHandler("RenderHandler");
}
CefRefPtr ClientHandler::GetRequestHandler() {
return GetHandler("RequestHandler");
}
bool ClientHandler::OnProcessMessageReceived(
CefRefPtr browser,
CefRefPtr frame,
CefProcessId source_process,
CefRefPtr message) {
bool handled = false;
// Iterate on a copy of |message_routers_| to avoid re-entrancy of
// |message_router_lock_| if the client CefMessageRouterHandler impl
// calls CefClientHandler.addMessageRouter/removeMessageRouter.
MessageRouterSet message_routers;
{
base::AutoLock lock_scope(message_router_lock_);
message_routers = message_routers_;
}
for (auto& router : message_routers) {
handled = router->OnProcessMessageReceived(browser, frame, source_process,
message);
if (handled)
break;
}
return handled;
}
CefRefPtr ClientHandler::GetWindowHandler() {
return GetHandler("WindowHandler");
}
void ClientHandler::AddMessageRouter(JNIEnv* env, jobject jmessageRouter) {
CefRefPtr router = GetMessageRouter(env, jmessageRouter);
if (!router)
return;
CefMessageRouterConfig config = GetMessageRouterConfig(env, jmessageRouter);
// 1) Add CefMessageRouterBrowserSide into the list.
{
base::AutoLock lock_scope(message_router_lock_);
message_routers_.insert(router);
}
// 2) Update CefApp for new render-processes.
BrowserProcessHandler::AddMessageRouterConfig(config);
// 3) Update running render-processes.
BrowserSet allBrowsers = GetAllBrowsers(env);
if (allBrowsers.empty())
return;
CefRefPtr message =
CefProcessMessage::Create("AddMessageRouter");
CefRefPtr args = message->GetArgumentList();
args->SetString(0, config.js_query_function);
args->SetString(1, config.js_cancel_function);
BrowserSet::const_iterator it = allBrowsers.begin();
for (; it != allBrowsers.end(); ++it) {
(*it)->GetMainFrame()->SendProcessMessage(PID_RENDERER, message);
}
}
void ClientHandler::RemoveMessageRouter(JNIEnv* env, jobject jmessageRouter) {
CefRefPtr router = GetMessageRouter(env, jmessageRouter);
if (!router)
return;
CefMessageRouterConfig config = GetMessageRouterConfig(env, jmessageRouter);
// 1) Remove CefMessageRouterBrowserSide from the list.
{
base::AutoLock lock_scope(message_router_lock_);
message_routers_.erase(router);
}
// 2) Update CefApp.
BrowserProcessHandler::RemoveMessageRouterConfig(config);
// 3) Update running render-processes.
BrowserSet allBrowsers = GetAllBrowsers(env);
if (allBrowsers.empty())
return;
CefRefPtr message =
CefProcessMessage::Create("RemoveMessageRouter");
CefRefPtr args = message->GetArgumentList();
args->SetString(0, config.js_query_function);
args->SetString(1, config.js_cancel_function);
BrowserSet::const_iterator it = allBrowsers.begin();
for (; it != allBrowsers.end(); ++it) {
(*it)->GetMainFrame()->SendProcessMessage(PID_RENDERER, message);
}
}
void ClientHandler::OnAfterCreated() {}
void ClientHandler::OnBeforeClose(CefRefPtr browser) {
REQUIRE_UI_THREAD();
base::AutoLock lock_scope(message_router_lock_);
for (auto& router : message_routers_) {
router->OnBeforeClose(browser);
}
}
void ClientHandler::OnBeforeBrowse(CefRefPtr browser,
CefRefPtr frame) {
REQUIRE_UI_THREAD();
base::AutoLock lock_scope(message_router_lock_);
for (auto& router : message_routers_) {
router->OnBeforeBrowse(browser, frame);
}
}
void ClientHandler::OnRenderProcessTerminated(CefRefPtr browser) {
REQUIRE_UI_THREAD();
base::AutoLock lock_scope(message_router_lock_);
for (auto& router : message_routers_) {
router->OnRenderProcessTerminated(browser);
}
}
jobject ClientHandler::getBrowser(JNIEnv* env, CefRefPtr browser) {
jobject jbrowser = nullptr;
JNI_CALL_METHOD(env, handle_, "getBrowser", "(I)Lorg/cef/browser/CefBrowser;",
Object, jbrowser, browser->GetIdentifier());
return jbrowser;
}
ClientHandler::BrowserSet ClientHandler::GetAllBrowsers(JNIEnv* env) {
BrowserSet result;
jobject jbrowsers = nullptr;
JNI_CALL_METHOD(env, handle_, "getAllBrowser", "()[Ljava/lang/Object;",
Object, jbrowsers);
if (!jbrowsers)
return result;
jobjectArray jbrowserArray = (jobjectArray)jbrowsers;
jint length = env->GetArrayLength(jbrowserArray);
for (int i = 0; i < length; ++i) {
jobject jbrowser = env->GetObjectArrayElement(jbrowserArray, i);
if (!jbrowser)
continue;
ScopedJNIBrowser sbrowser(env);
sbrowser.SetHandle(jbrowser, true /* should_delete */);
CefRefPtr browser = sbrowser.GetCefObject();
if (!browser)
continue;
result.insert(browser);
}
env->DeleteLocalRef(jbrowserArray);
return result;
}