remote/ServerHandler.cpp (1,522 lines of code) (raw):

#include "ServerHandler.h" #include "include/cef_base.h" #include "include/cef_parser.h" #include "browser/RemoteDevToolsMessageObserver.h" #include "browser/RemoteFrame.h" #include "callback/RemoteMediaAccessCallback.h" #include "handlers/RemoteClientHandler.h" #include "handlers/app/RemoteAppHandler.h" #include "network/RemoteCookieManager.h" #include "network/RemoteCookieVisitor.h" #include "network/RemotePostData.h" #include "network/RemoteRequest.h" #include "network/RemoteResponse.h" #include "RemoteObjects.h" #include "callback/RemoteAuthCallback.h" #include "callback/RemoteCallback.h" #include "callback/RemoteCefRunContextMenuCallback.h" #include "callback/RemoteCompletionCallback.h" #include "callback/RemoteIntCallback.h" #include "callback/RemoteRegistration.h" #include "callback/RemoteSchemeHandlerFactory.h" #include "callback/RemoteStringVisitor.h" #include "callback/RemoteRunFileDialogCallback.h" #include "callback/RemotePdfPrintCallback.h" #include "include/base/cef_callback.h" #include "include/wrapper/cef_closure_task.h" #include "router/MessageRoutersManager.h" #include "router/RemoteMessageRouter.h" #include "router/RemoteMessageRouterHandler.h" #include "router/RemoteQueryCallback.h" #include "ServerApplication.h" #include "ServerHandlerContext.h" #include "../native/critical_wait.h" #include "CefUtils.h" #include "browser/RemoteBrowser.h" #include "browser/RemoteClient.h" using namespace apache::thrift; namespace { const bool doTrace = getBoolEnv("CEF_SERVER_TRACE_ServerHandler_ALL"); const bool doTraceClient = doTrace || getBoolEnv("CEF_SERVER_TRACE_ServerHandler_Client"); const bool doTraceBrowser = doTrace || getBoolEnv("CEF_SERVER_TRACE_ServerHandler_Browser"); const bool doTraceBrowserJS = doTraceBrowser || getBoolEnv("CEF_SERVER_TRACE_ServerHandler_Browser_JS"); const bool doTraceRequest = doTrace || getBoolEnv("CEF_SERVER_TRACE_ServerHandler_Request"); const bool doTraceCallbacks = doTrace || getBoolEnv("CEF_SERVER_TRACE_ServerHandler_Callbacks"); const bool doTraceMessageRouter = doTrace || getBoolEnv("CEF_SERVER_TRACE_ServerHandler_MessageRouter"); const bool doTraceMessageRouterCallbacks = doTrace || getBoolEnv("CEF_SERVER_TRACE_ServerHandler_MessageRouterCallbacks"); const bool doTraceCookie = doTrace || getBoolEnv("CEF_SERVER_TRACE_ServerHandler_Cookie"); #ifndef NDEBUG const bool doMeasureTimes = getBoolEnv("CEF_SERVER_MEASURE_ServerHandler", true); #else const bool doMeasureTimes = getBoolEnv("CEF_SERVER_MEASURE_ServerHandler", false); #endif void executeDevToolsMethod(CefRefPtr<CefBrowserHost> host, const CefString& method, const CefString& parametersAsJson, CefRefPtr<RemoteIntCallback> callback ) { CefRefPtr<CefDictionaryValue> parameters = nullptr; if (!parametersAsJson.empty()) { CefRefPtr<CefValue> value = CefParseJSON( parametersAsJson, cef_json_parser_options_t::JSON_PARSER_RFC); if (!value || value->GetType() != VTYPE_DICTIONARY) { callback->OnComplete(0); return; } parameters = value->GetDictionary(); } callback->OnComplete(host->ExecuteDevToolsMethod(0, method, parameters)); } } #define MEASURE utils::Measurer measurer(doMeasureTimes, "ServerHandler", __FUNCTION__) ServerHandler::ServerHandler() : myCtx(nullptr) {} ServerHandler::~ServerHandler() { if (myCtx) myCtx->close(); } int ServerHandler::connectImpl(std::function<void()> openBackwardTransport) { MEASURE; if (myCtx != nullptr) { Log::error("ServerHandler: client already connected, other attempts will be ignored."); return -1; } static int s_counter = 0; const int counter = s_counter++; Log::setThreadName(string_format("ServerHandler_%d", counter)); // Connect to client's side (for cef-callbacks execution on java side) myCtx = std::make_shared<ServerHandlerContext>(); myIsMainHandler = true; try { openBackwardTransport(); static const bool testBackwardTransport = getBoolEnv("CEF_SERVER_TEST_BACKWARD_TRANSPORT"); if (testBackwardTransport) { // simple test for connection std::string testMsg = "123test!!"; std::string returnVal; myCtx->javaService()->exec( [&](JavaService s) { s->echo(returnVal, testMsg); }); if (testMsg.compare(returnVal) != 0) { Log::error("ServerHandler: JavaClient returns invalid echo '%s'", returnVal.c_str()); myCtx->close(); return -1; } } ServerApplication::instance().getCefAppHandler()->setService(myCtx->javaService()); } catch (TException& tx) { Log::error(tx.what()); myCtx->close(); return -1; } return myCid = counter; } int32_t ServerHandler::connect(const std::string& backwardConnectionPipe, bool isMaster) { myIsMaster = isMaster; return connectImpl([&](){ myCtx->initJavaServicePipe(backwardConnectionPipe); }); } int32_t ServerHandler::connectTcp(int backwardConnectionPort, bool isMaster) { myIsMaster = isMaster; return connectImpl([&](){ myCtx->initJavaServicePort(backwardConnectionPort); }); } void ServerHandler::attach(int connectionId) { myCtx = ServerApplication::instance().getCtx(connectionId); } int32_t ServerHandler::Client_Create(int handlersMask) { MEASURE; std::shared_ptr<RemoteClient> result = myCtx->createRemoteClient(handlersMask, myCtx); if (doTraceClient && Log::isTraceEnabled()) Log::trace("ServerHandler: created RemoteClient with cid=%d, handlers: %s", result->getCid(), HandlerMasks::toString(handlersMask).c_str()); return result->getCid(); } void ServerHandler::Client_Dispose(int cid) { MEASURE; myCtx->disposeRemoteClient(cid); if (doTraceClient && Log::isTraceEnabled()) Log::trace("ServerHandler: disposed RemoteClient with cid=%d", cid); } void ServerHandler::Client_AddHandlers(int cid, int handlersMask) { MEASURE; std::shared_ptr<RemoteClient> rc = myCtx->findRemoteClient(cid); if (!rc) { Log::error("ServerHandler: Client_AddHandlers: can't find RemoteClient by cid=%d", cid); return; } rc->addHandlers(handlersMask); if (doTraceClient && Log::isTraceEnabled()) Log::trace("ServerHandler: Client_AddHandlers [mask=%d] for RemoteClient with cid=%d", handlersMask, cid); } void ServerHandler::Client_RemoveHandlers(int cid, int handlersMask) { MEASURE; std::shared_ptr<RemoteClient> rc = myCtx->findRemoteClient(cid); if (!rc) { Log::error("ServerHandler: Client_RemoveHandlers: can't find RemoteClient by cid=%d", cid); return; } if (doTraceClient && Log::isTraceEnabled()) Log::trace("ServerHandler: Client_RemoveHandlers [mask=%d] for RemoteClient with cid=%d", handlersMask, cid); rc->removeHandlers(handlersMask); } int32_t ServerHandler::Browser_Create(int cid, const thrift_codegen::RObject& requestContextHandler) { MEASURE; std::shared_ptr<RemoteClient> rc = myCtx->findRemoteClient(cid); if (!rc) { Log::error("ServerHandler: Browser_Create: can't find RemoteClient by cid=%d", cid); return -1; } std::shared_ptr<RemoteBrowser> result = rc->createBrowser(rc, myCtx, requestContextHandler); if (Log::isTraceEnabled()) { std::string hdesc = ""; if (!requestContextHandler.isNull) hdesc = string_format(" [request context handler %d]", requestContextHandler.objId); Log::trace("ServerHandler: created remote browser cid=%d, bid=%d%s", cid, result->getBid(), hdesc.c_str()); } return result->getBid(); } void ServerHandler::Browser_StartNativeCreation(int bid, const std::string& url) { MEASURE; std::shared_ptr<RemoteBrowser> rb = RemoteBrowser::find(bid); if (!rb) return; rb->startNativeBrowserCreation(url); Log::trace("ServerHandler: started creation of native CefBrowser for remote browser bid=%d, url=%s", bid, url.c_str()); } void ServerHandler::Browser_OpenDevTools(int bid, int x, int y) { MEASURE; std::shared_ptr<RemoteBrowser> rb = RemoteBrowser::find(bid); if (!rb) return; rb->openDevTools(x, y); Log::trace("ServerHandler: started opening of dev-tools of remote browser bid=%d", bid); } void ServerHandler::Browser_Close(const int32_t bid) { MEASURE; std::shared_ptr<RemoteBrowser> rb = RemoteBrowser::find(bid); if (!rb) return; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: close remote browser bid=%d", bid); rb->close(); } void ServerHandler::stop() { MEASURE; Log::debug("ServerHandler: handler %p asked to stop server.", this); ServerApplication::instance().startShuttingDown(); } void ServerHandler::getServerInfo(std::string& _return, const std::string& request) { if (request.compare("version") == 0) _return.assign(CefUtils::getVersionWithSha()); else if (request.compare("state") == 0) _return = ServerApplication::instance().getState(); else if (request.compare("state_with_details") == 0) _return = ServerApplication::instance().getStateWithDetails(); else if (request.compare("logger_details") == 0) _return = Log::printLevelAndPath(); else if (request.compare("root") == 0) _return = ServerApplication::instance().getCefAppHandler()->getRootPath(); else if (request.compare("doCrash") == 0) { Log::trace("ServerHandler: %p will crash server now.", this); fprintf(stdout, "%d", *((int*)1)); } else _return = "Unknown request: " + request; } #define GET_BROWSER_OR_RETURN() \ auto rb = RemoteBrowser::find(bid); \ if (!rb) \ return; \ auto browser = rb->getCefBrowser(); \ if (browser == nullptr) \ return; #define GET_BROWSER_OR_RETURN_VAL(val) \ auto rb = RemoteBrowser::find(bid); \ if (!rb) \ return val; \ auto browser = rb->getCefBrowser(); \ if (browser == nullptr) \ return val; #define GET_CLIENT_OR_RETURN() \ auto client = RemoteClient::findByBid(bid); \ if (!client) \ return; #define GET_CLIENT_OR_RETURN_VAL(val) \ auto client = RemoteClient::findByBid(bid); \ if (!client) \ return val; #define GET_COOKIE_MANAGER_OR_RETURN() \ auto manager = RemoteCookieManager::find(cookieManager.objId); \ if (manager == nullptr) { \ Log::error("ServerHandler: can't find RemoteCookieManager by id=%d", cookieManager.objId); \ return; \ } #define GET_COOKIE_MANAGER_OR_RETURN_VAL(val) \ auto manager = RemoteCookieManager::find(cookieManager.objId); \ if (manager == nullptr) { \ Log::error("ServerHandler: can't find RemoteCookieManager by id=%d", cookieManager.objId); \ return val; \ } void ServerHandler::Browser_CloseDevTools(const int32_t bid) { MEASURE; GET_BROWSER_OR_RETURN() if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_CloseDevTools, bid=%d", bid); browser->GetHost()->CloseDevTools(); } void ServerHandler::Browser_Reload(const int32_t bid) { MEASURE; GET_BROWSER_OR_RETURN() if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_Reload, bid=%d", bid); browser->Reload(); } void ServerHandler::Browser_ReloadIgnoreCache(const int32_t bid) { MEASURE; GET_BROWSER_OR_RETURN() if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_ReloadIgnoreCache, bid=%d", bid); browser->ReloadIgnoreCache(); } void ServerHandler::Browser_LoadURL(const int32_t bid, const std::string& url) { MEASURE; if (url.compare("doCrash") == 0) { Log::trace("ServerHandler: browser %d will crash server now.", bid); Log::trace("%d", *((int*)1)); } GET_BROWSER_OR_RETURN() Log::trace("ServerHandler: browser %d is loading URL '%s'", bid, url.c_str()); browser->GetMainFrame()->LoadURL(url); } void ServerHandler::Browser_LoadRequest(const int32_t bid, const thrift_codegen::RObject & request) { MEASURE; GET_BROWSER_OR_RETURN() std::shared_ptr<RemoteRequest> rr = RemoteRequest::get(request.objId); if (rr == nullptr) { Log::trace("ServerHandler: can't find RemoteRequest %d", request.objId); return; } Log::trace("ServerHandler: browser %d is loading request %d", bid, request.objId); browser->GetMainFrame()->LoadRequest(rr->getDelegate()); } void ServerHandler::Browser_GetURL(std::string& _return, const int32_t bid) { MEASURE; GET_BROWSER_OR_RETURN() if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_GetURL, bid=%d", bid); _return = browser->GetMainFrame()->GetURL().ToString(); } void ServerHandler::Browser_ExecuteJavaScript(const int32_t bid,const std::string& code,const std::string& url,const int32_t line) { MEASURE; GET_BROWSER_OR_RETURN() if (doTraceBrowserJS && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_ExecuteJavaScript, bid=%d, code='%s', url='%s', line=%d", bid, code.c_str(), url.c_str(), line); browser->GetMainFrame()->ExecuteJavaScript(code, url, line); } void ServerHandler::Frame_ExecuteJavaScript(const int32_t frameId, const std::string& code, const std::string& url, const int32_t line) { MEASURE; if (doTraceBrowserJS && Log::isTraceEnabled()) Log::trace("ServerHandler: Frame_ExecuteJavaScript, frameId=%d, code='%s', url='%s', line=%d", frameId, code.c_str(), url.c_str(), line); std::shared_ptr<RemoteFrame> rf = RemoteFrame::get(frameId); if (rf != nullptr) rf->getDelegate()->ExecuteJavaScript(code, url, line); } void ServerHandler::Frame_Dispose(const int32_t frameId) { MEASURE; if (doTrace && Log::isTraceEnabled()) Log::trace("ServerHandler: Frame_Dispose, frameId=%d", frameId); RemoteFrame::dispose(frameId); } void ServerHandler::Frame_GetParent(thrift_codegen::RObject & _return, int frameId) { MEASURE; if (doTrace && Log::isTraceEnabled()) Log::trace("ServerHandler: Frame_GetParent, frameId=%d", frameId); std::shared_ptr<RemoteFrame> rf = RemoteFrame::get(frameId); if (rf == nullptr) return; std::shared_ptr<RemoteFrame> rparent = RemoteFrame::create(rf->getDelegate()->GetParent()); if (rparent != nullptr) _return = rparent->serverId(); } void ServerHandler::Frame_Undo(int frameId) { MEASURE; if (doTrace && Log::isTraceEnabled()) Log::trace("ServerHandler: Frame_Undo, frameId=%d", frameId); std::shared_ptr<RemoteFrame> rf = RemoteFrame::get(frameId); if (rf != nullptr) rf->getDelegate()->Undo(); } void ServerHandler::Frame_Redo(int frameId) { MEASURE; if (doTrace && Log::isTraceEnabled()) Log::trace("ServerHandler: Frame_Redo, frameId=%d", frameId); std::shared_ptr<RemoteFrame> rf = RemoteFrame::get(frameId); if (rf != nullptr) rf->getDelegate()->Redo(); } void ServerHandler::Frame_Cut(int frameId) { MEASURE; if (doTrace && Log::isTraceEnabled()) Log::trace("ServerHandler: Frame_Cut, frameId=%d", frameId); std::shared_ptr<RemoteFrame> rf = RemoteFrame::get(frameId); if (rf != nullptr) rf->getDelegate()->Cut(); } void ServerHandler::Frame_Copy(int frameId) { MEASURE; if (doTrace && Log::isTraceEnabled()) Log::trace("ServerHandler: Frame_Copy, frameId=%d", frameId); std::shared_ptr<RemoteFrame> rf = RemoteFrame::get(frameId); if (rf != nullptr) rf->getDelegate()->Copy(); } void ServerHandler::Frame_Paste(int frameId) { MEASURE; if (doTrace && Log::isTraceEnabled()) Log::trace("ServerHandler: Frame_Paste, frameId=%d", frameId); std::shared_ptr<RemoteFrame> rf = RemoteFrame::get(frameId); if (rf != nullptr) rf->getDelegate()->Paste(); } void ServerHandler::Frame_Delete(int frameId) { MEASURE; if (doTrace && Log::isTraceEnabled()) Log::trace("ServerHandler: Frame_Delete, frameId=%d", frameId); std::shared_ptr<RemoteFrame> rf = RemoteFrame::get(frameId); if (rf != nullptr) rf->getDelegate()->Delete(); } void ServerHandler::Frame_SelectAll(int frameId) { MEASURE; if (doTrace && Log::isTraceEnabled()) Log::trace("ServerHandler: Frame_SelectAll, frameId=%d", frameId); std::shared_ptr<RemoteFrame> rf = RemoteFrame::get(frameId); if (rf != nullptr) rf->getDelegate()->SelectAll(); } void ServerHandler::Browser_WasResized(const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_WasResized, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GetHost()->WasResized(); } void ServerHandler::Browser_NotifyScreenInfoChanged(const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_NotifyScreenInfoChanged, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GetHost()->NotifyScreenInfoChanged(); } void ServerHandler::Browser_Invalidate(const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_Invalidate, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GetHost()->Invalidate(PET_VIEW);; } extern void processKeyEvent( CefKeyEvent & cef_event, int event_type, // event.getID() int modifiers, // event.getModifiersEx() char16_t key_char, // event.getKeyChar() long scanCode, // event.scancode, windows only int key_code // event.getKeyCode() ); void ServerHandler::Browser_SendCefKeyEvent( const int32_t bid, const thrift_codegen::CefKeyEventAttributes& event) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_SendCefKeyEvent, bid=%d", bid); GET_BROWSER_OR_RETURN() CefKeyEvent cef_event{}; cef_event.type = static_cast<cef_key_event_type_t>(event.type); cef_event.modifiers = event.modifiers; cef_event.windows_key_code = event.windows_key_code; cef_event.native_key_code = event.native_key_code; cef_event.is_system_key = event.is_system_key; cef_event.character = event.character; cef_event.unmodified_character = event.unmodified_character; browser->GetHost()->SendKeyEvent(cef_event); } extern void processMouseEvent( CefRefPtr<CefBrowser> browser, int event_type, // getID int x, // getX int y, // getY int modifiers, // getModifiersEx int click_count, // getClickCount int button // getButton ); void ServerHandler::Browser_SendMouseEvent(const int32_t bid,const int32_t event_type,const int32_t x,const int32_t y,const int32_t modifiers,const int32_t click_count,const int32_t button) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_SendMouseEvent, bid=%d", bid); GET_BROWSER_OR_RETURN() processMouseEvent(browser, event_type, x, y, modifiers, click_count, button); } extern void processMouseWheelEvent( CefRefPtr<CefBrowser> browser, int scroll_type, // getScrollType int x, // getX int y, // getY int modifiers, // getModifiersEx int delta, // getWheelRotation int units_to_scroll // getUnitsToScroll ); void ServerHandler::Browser_SendMouseWheelEvent(const int32_t bid,const int32_t scroll_type,const int32_t x,const int32_t y,const int32_t modifiers,const int32_t delta,const int32_t units_to_scroll) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_SendMouseWheelEvent, bid=%d", bid); GET_BROWSER_OR_RETURN() processMouseWheelEvent(browser, scroll_type, x, y, modifiers, delta, units_to_scroll); } void ServerHandler::Browser_GoBack(const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_GoBack, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GoBack(); } bool ServerHandler::Browser_CanGoForward(const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_CanGoForward, bid=%d", bid); GET_BROWSER_OR_RETURN_VAL(false) return browser->CanGoForward(); } bool ServerHandler::Browser_CanGoBack(const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_CanGoBack, bid=%d", bid); GET_BROWSER_OR_RETURN_VAL(false) return browser->CanGoBack(); } void ServerHandler::Browser_GoForward(const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_GoForward, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GoForward(); } bool ServerHandler::Browser_IsLoading(const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_IsLoading, bid=%d", bid); GET_BROWSER_OR_RETURN_VAL(false) return browser->IsLoading(); } void ServerHandler::Browser_StopLoad(const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_StopLoad, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->StopLoad(); } void ServerHandler::Browser_GetMainFrame(thrift_codegen::RObject& _return, const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_GetMainFrame, bid=%d", bid); GET_BROWSER_OR_RETURN() CefRefPtr<CefFrame> frame = browser->GetMainFrame(); std::shared_ptr<RemoteFrame> rf = RemoteFrame::create(frame); if (rf != nullptr) _return = rf->serverId(); } void ServerHandler::Browser_GetFocusedFrame(thrift_codegen::RObject& _return, const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_GetFocusedFrame, bid=%d", bid); GET_BROWSER_OR_RETURN() CefRefPtr<CefFrame> frame = browser->GetFocusedFrame(); std::shared_ptr<RemoteFrame> rf = RemoteFrame::create(frame); if (rf != nullptr) _return = rf->serverId(); } void ServerHandler::Browser_GetFrameByIdentifier(thrift_codegen::RObject& _return, const int32_t bid, const std::string& id) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_GetFrameByIdentifier, bid=%d", bid); GET_BROWSER_OR_RETURN() CefRefPtr<CefFrame> frame = browser->GetFrameByIdentifier(id); std::shared_ptr<RemoteFrame> rf = RemoteFrame::create(frame); if (rf != nullptr) _return = rf->serverId(); } void ServerHandler::Browser_GetFrameByName(thrift_codegen::RObject& _return, const int32_t bid, const std::string& name) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_GetFrameByName, bid=%d", bid); GET_BROWSER_OR_RETURN() CefRefPtr<CefFrame> frame = browser->GetFrameByName(name); std::shared_ptr<RemoteFrame> rf = RemoteFrame::create(frame); if (rf != nullptr) _return = rf->serverId(); } void ServerHandler::Browser_GetFrameIdentifiers(std::vector<std::string>& _return, const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_GetFrameIdentifiers, bid=%d", bid); GET_BROWSER_OR_RETURN() std::vector<CefString> identifiers; browser->GetFrameIdentifiers(identifiers); for (const auto & fid: identifiers) _return.push_back(fid.ToString()); } void ServerHandler::Browser_GetFrameNames(std::vector<std::string>& _return, const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_GetFrameNames, bid=%d", bid); GET_BROWSER_OR_RETURN() std::vector<CefString> names; browser->GetFrameNames(names); for (const auto & name : names) _return.push_back(name.ToString()); } int32_t ServerHandler::Browser_GetFrameCount(const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_GetFrameCount, bid=%d", bid); GET_BROWSER_OR_RETURN_VAL(0) return (int32_t)browser->GetFrameCount(); } bool ServerHandler::Browser_IsPopup(const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_IsPopup, bid=%d", bid); GET_BROWSER_OR_RETURN_VAL(false) return browser->IsPopup(); } bool ServerHandler::Browser_HasDocument(const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_HasDocument, bid=%d", bid); GET_BROWSER_OR_RETURN_VAL(false) return browser->HasDocument(); } void ServerHandler::Browser_ViewSource(const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_ViewSource, bid=%d", bid); GET_BROWSER_OR_RETURN() CefRefPtr<CefFrame> mainFrame = browser->GetMainFrame(); CefPostTask(TID_UI, base::BindOnce(&CefFrame::ViewSource, mainFrame.get())); } void ServerHandler::Browser_GetSource(const int32_t bid, const thrift_codegen::RObject& stringVisitor) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_GetSource, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GetMainFrame()->GetSource(new RemoteStringVisitor(myCtx, stringVisitor)); } void ServerHandler::Browser_GetText(const int32_t bid, const thrift_codegen::RObject& stringVisitor) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_GetText, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GetMainFrame()->GetText(new RemoteStringVisitor(myCtx, stringVisitor)); } void ServerHandler::Browser_SetFocus(const int32_t bid, bool enable) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_SetFocus, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GetHost()->SetFocus(enable); } namespace { void _runTaskAndWakeup(std::shared_ptr<CriticalWait> waitCond, base::OnceClosure task) { WaitGuard guard(*waitCond); std::move(task).Run(); waitCond->WakeUp(); } void CefPostTaskAndWait(CefThreadId threadId, base::OnceClosure task, long waitMillis) { std::shared_ptr<CriticalLock> lock = std::make_shared<CriticalLock>(); std::shared_ptr<CriticalWait> waitCond = std::make_shared<CriticalWait>(lock.get()); LockGuard guard(*lock); CefPostTask(threadId, base::BindOnce(_runTaskAndWakeup, waitCond, std::move(task))); waitCond->Wait(static_cast<unsigned>(waitMillis)); } void getZoomLevel(CefRefPtr<CefBrowserHost> host, std::shared_ptr<double> result) { *result = host->GetZoomLevel(); } } double ServerHandler::Browser_GetZoomLevel(const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_GetZoomLevel, bid=%d", bid); GET_BROWSER_OR_RETURN_VAL(0.0f) CefRefPtr<CefBrowserHost> host = browser->GetHost(); if (CefCurrentlyOn(TID_UI)) { return host->GetZoomLevel(); } std::shared_ptr<double> result = std::make_shared<double>(0.0); CefPostTaskAndWait(TID_UI, base::BindOnce(getZoomLevel, host, result), 100); return *result; } void ServerHandler::Browser_SetZoomLevel(const int32_t bid, const double val) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_SetZoomLevel, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GetHost()->SetZoomLevel(val); } void ServerHandler::Browser_StartDownload(const int32_t bid, const std::string& url) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_StartDownload, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GetHost()->StartDownload(url); } void ServerHandler::Browser_Find(const int32_t bid, const std::string& searchText, const bool forward, const bool matchCase, const bool findNext) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_Find, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GetHost()->Find(searchText, forward, matchCase, findNext); } void ServerHandler::Browser_StopFinding(const int32_t bid, const bool clearSelection) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_StopFinding, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GetHost()->StopFinding(clearSelection); } void ServerHandler::Browser_ReplaceMisspelling(const int32_t bid, const std::string& word) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_ReplaceMisspelling, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GetHost()->ReplaceMisspelling(word); } void ServerHandler::Browser_SetFrameRate(const int32_t bid, int32_t val) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_SetFrameRate, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GetHost()->SetWindowlessFrameRate(val); } void ServerHandler::Browser_AddDevToolsMessageObserver(thrift_codegen::RObject& _return, const int32_t bid, const thrift_codegen::RObject& observer) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_AddDevToolsMessageObserver, bid=%d", bid); GET_BROWSER_OR_RETURN() CefRefPtr<RemoteDevToolsMessageObserver> robserver(new RemoteDevToolsMessageObserver(myCtx, observer)); CefRefPtr<CefRegistration> registration = browser->GetHost()->AddDevToolsMessageObserver(robserver); _return = RemoteRegistration::create(registration)->serverId(); } void ServerHandler::Browser_ExecuteDevToolsMethod( const int32_t bid, const std::string& method, const std::string& parametersAsJson, const thrift_codegen::RObject& intCallback ) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_ExecuteDevToolsMethod, bid=%d", bid); GET_BROWSER_OR_RETURN() CefRefPtr<RemoteIntCallback> callback = new RemoteIntCallback(myCtx, intCallback); if (!browser.get()) { callback->OnComplete(0); return; } if (CefCurrentlyOn(TID_UI)) { executeDevToolsMethod(browser->GetHost(), method, parametersAsJson, callback); } else { CefPostTask(TID_UI, base::BindOnce(executeDevToolsMethod, browser->GetHost(), method, parametersAsJson, callback)); } } void ServerHandler::Browser_RunFileDialog( const int32_t bid, const std::string& mode, const std::string& title, const std::string& defaultFilePath, const std::vector<std::string>& acceptFilters, const thrift_codegen::RObject& runFileDialogCallback) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_RunFileDialog, bid=%d", bid); GET_BROWSER_OR_RETURN() CefRefPtr<RemoteRunFileDialogCallback> callback = new RemoteRunFileDialogCallback(myCtx, runFileDialogCallback); if (!browser.get()) { callback->OnFileDialogDismissed(std::vector<CefString>()); return; } std::vector<CefString> accept_types; for (const auto & fp: acceptFilters) accept_types.push_back(CefString(fp)); CefBrowserHost::FileDialogMode fdMode; if (mode.find("FILE_DIALOG_OPEN_MULTIPLE") != std::string::npos) fdMode = FILE_DIALOG_OPEN_MULTIPLE; else if (mode.find("FILE_DIALOG_OPEN") != std::string::npos) fdMode = FILE_DIALOG_OPEN; else if (mode.find("FILE_DIALOG_SAVE") != std::string::npos) fdMode = FILE_DIALOG_SAVE; else fdMode = FILE_DIALOG_OPEN; browser->GetHost()->RunFileDialog(fdMode, CefString(title), CefString(defaultFilePath), accept_types, callback); } namespace { void setFieldValueD(double & field, const std::string & val) { try { field = stod(val); } catch (const std::logic_error & ex) { Log::error("ServerHandler: PrintToPDF: can't convert string '%s' to double. Error: %s", val.c_str(), ex.what()); field = 1.f; } } void setFieldValueB(int & field, const std::string & val) { field = (val.compare("true") == 0); } } void ServerHandler::Browser_PrintToPDF( const int32_t bid, const std::string& path, const std::map<std::string, std::string>& pdfPrintSettings, const thrift_codegen::RObject& pdfPrintCallback) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_PrintToPDF, bid=%d", bid); GET_BROWSER_OR_RETURN() CefRefPtr<RemotePdfPrintCallback> callback = new RemotePdfPrintCallback(myCtx, pdfPrintCallback); if (!browser.get()) { callback->OnPdfPrintFinished(CefString(path), false); return; } CefPdfPrintSettings settings; for (const auto & kv: pdfPrintSettings) { if (kv.first.compare("landscape") == 0) setFieldValueB(settings.landscape, kv.second); else if (kv.first.compare("print_background") == 0) setFieldValueB(settings.print_background, kv.second); else if (kv.first.compare("scale") == 0) setFieldValueD(settings.scale, kv.second); else if (kv.first.compare("paper_width") == 0) setFieldValueD(settings.paper_width, kv.second); else if (kv.first.compare("paper_height") == 0) setFieldValueD(settings.paper_height, kv.second); else if (kv.first.compare("prefer_css_page_size") == 0) setFieldValueB(settings.prefer_css_page_size, kv.second); else if (kv.first.compare("margin_type") == 0) { settings.margin_type = PDF_PRINT_MARGIN_DEFAULT; if (kv.second.find("NONE") != std::string::npos) settings.margin_type = PDF_PRINT_MARGIN_NONE; else if (kv.second.find("CUSTOM") != std::string::npos) settings.margin_type = PDF_PRINT_MARGIN_CUSTOM; } else if (kv.first.compare("margin_top") == 0) setFieldValueD(settings.margin_top, kv.second); else if (kv.first.compare("margin_bottom") == 0) setFieldValueD(settings.margin_bottom, kv.second); else if (kv.first.compare("margin_right") == 0) setFieldValueD(settings.margin_right, kv.second); else if (kv.first.compare("margin_left") == 0) setFieldValueD(settings.margin_left, kv.second); else if (kv.first.compare("page_ranges") == 0) { std::string ranges = kv.second; CefString(&settings.page_ranges) = ranges; } else if (kv.first.compare("display_header_footer") == 0) setFieldValueB(settings.display_header_footer, kv.second); else if (kv.first.compare("header_template") == 0) { std::string templ = kv.second; CefString(&settings.header_template) = templ; } else if (kv.first.compare("footer_template") == 0) { std::string templ = kv.second; CefString(&settings.footer_template) = templ; } else if (kv.first.compare("generate_document_outline") == 0) { setFieldValueB(settings.generate_document_outline, kv.second); } else if (kv.first.compare("generate_tagged_pdf") == 0) { setFieldValueB(settings.generate_tagged_pdf, kv.second); } } browser->GetHost()->PrintToPDF(path, settings, callback); } void ServerHandler::Browser_Print(const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_Print, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GetHost()->Print(); } void ServerHandler::Browser_ImeSetComposition( const int32_t bid, const std::string& text, const std::vector<thrift_codegen::CompositionUnderline>& underlines, const thrift_codegen::Range& replacementRange, const thrift_codegen::Range& selectionRange) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_ImeSetComposition, bid=%d", bid); GET_BROWSER_OR_RETURN() std::vector<CefCompositionUnderline> cef_underlines; for (const auto & underline: underlines) { CefCompositionUnderline cef_underline; cef_underline.range = CefRange(underline.range.from, underline.range.to); cef_underline.thick = underline.thick; cef_underline.color = CefColorSetARGB( underline.color.alpha, underline.color.red, underline.color.green, underline.color.blue ); cef_underline.background_color = CefColorSetARGB( underline.backgroundColor.alpha, underline.backgroundColor.red, underline.backgroundColor.green, underline.backgroundColor.blue ); cef_underlines.push_back(cef_underline); } browser->GetHost()->ImeSetComposition( CefString(text), cef_underlines, CefRange(replacementRange.from, replacementRange.to), CefRange(selectionRange.from, selectionRange.to) ); } void ServerHandler::Browser_ImeCommitText( const int32_t bid, const std::string& text, const thrift_codegen::Range& replacementRange, const int32_t relativeCursorPos) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_ImeCommitText, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GetHost()->ImeCommitText( CefString(text), CefRange(replacementRange.from, replacementRange.to), relativeCursorPos ); } void ServerHandler::Browser_ImeFinishComposingText(const int32_t bid, const bool keepSelection) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_ImeFinishComposingText, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GetHost()->ImeFinishComposingText(keepSelection); } void ServerHandler::Browser_ImeCancelComposing(const int32_t bid) { MEASURE; if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: Browser_ImeCancelComposing, bid=%d", bid); GET_BROWSER_OR_RETURN() browser->GetHost()->ImeCancelComposition(); } void ServerHandler::Request_Create(thrift_codegen::RObject& result) { MEASURE; if (doTraceRequest && Log::isTraceEnabled()) Log::trace("ServerHandler: Request_Create"); CefRefPtr<CefRequest> request = CefRequest::Create(); std::shared_ptr<RemoteRequest> rr = RemoteRequest::create(request); if (rr != nullptr) { result = rr->serverId(); result.isNull = false; } } void ServerHandler::Request_Dispose(int requestId) { MEASURE; if (doTraceRequest && Log::isTraceEnabled()) Log::trace("ServerHandler: Request_Dispose, id=%d", requestId); RemoteRequest::dispose(requestId); } void ServerHandler::Request_Update(const thrift_codegen::RObject & request) { MEASURE; if (doTraceRequest && Log::isTraceEnabled()) Log::trace("ServerHandler: Request_Update, id=%d", request.objId); std::shared_ptr<RemoteRequest> rr = RemoteRequest::get(request.objId); if (rr == nullptr) return; rr->update(request.objInfo); } void ServerHandler::Response_Update(const thrift_codegen::RObject& response) { MEASURE; if (doTraceRequest && Log::isTraceEnabled()) Log::trace("ServerHandler: Response_Update, id=%d", response.objId); std::shared_ptr<RemoteResponse> rr = RemoteResponse::get(response.objId); if (rr == nullptr) return; rr->update(response.objInfo); } void ServerHandler::Request_GetHeaderByName( std::string& _return, const thrift_codegen::RObject& request, const std::string& name) { MEASURE; if (doTraceRequest && Log::isTraceEnabled()) Log::trace("ServerHandler: Request_GetHeaderByName, id=%d, name=%s", request.objId, name.c_str()); std::shared_ptr<RemoteRequest> rr = RemoteRequest::get(request.objId); if (rr == nullptr) return; std::string result = rr->getDelegate()->GetHeaderByName(name).ToString(); _return.assign(result); } void ServerHandler::Request_SetHeaderByName( const thrift_codegen::RObject& request, const std::string& name, const std::string& value, const bool overwrite) { MEASURE; if (doTraceRequest && Log::isTraceEnabled()) Log::trace("ServerHandler: Request_SetHeaderByName, id=%d, name=%s, value=%s", request.objId, name.c_str(), value.c_str()); std::shared_ptr<RemoteRequest> rr = RemoteRequest::get(request.objId); if (rr == nullptr) return; rr->getDelegate()->SetHeaderByName(name, value, overwrite); } void ServerHandler::Request_GetHeaderMap( std::map<std::string, std::string>& _return, const thrift_codegen::RObject& request) { MEASURE; if (doTraceRequest && Log::isTraceEnabled()) Log::trace("ServerHandler: Request_GetHeaderMap, id=%d", request.objId); std::shared_ptr<RemoteRequest> rr = RemoteRequest::get(request.objId); if (rr == nullptr) return; CefRequest::HeaderMap hmap; rr->getDelegate()->GetHeaderMap(hmap); fillMap(_return, hmap); } void ServerHandler::Request_SetHeaderMap( const thrift_codegen::RObject& request, const std::map<std::string, std::string>& headerMap) { MEASURE; if (doTraceRequest && Log::isTraceEnabled()) Log::trace("ServerHandler: Request_SetHeaderMap, id=%d", request.objId); std::shared_ptr<RemoteRequest> rr = RemoteRequest::get(request.objId); if (rr == nullptr) return; CefRequest::HeaderMap hmap; fillMap(hmap, headerMap); rr->getDelegate()->SetHeaderMap(hmap); } void ServerHandler::Response_GetHeaderByName( std::string& _return, const thrift_codegen::RObject& response, const std::string& name) { MEASURE; if (doTraceRequest && Log::isTraceEnabled()) Log::trace("ServerHandler: Response_GetHeaderByName, id=%d, name=%s", response.objId, name.c_str()); std::shared_ptr<RemoteResponse> rr = RemoteResponse::get(response.objId); if (rr == nullptr) return; std::string result = rr->getDelegate()->GetHeaderByName(name).ToString(); _return.assign(result); } void ServerHandler::Response_SetHeaderByName( const thrift_codegen::RObject& response, const std::string& name, const std::string& value, const bool overwrite) { MEASURE; if (doTraceRequest && Log::isTraceEnabled()) Log::trace("ServerHandler: Response_SetHeaderByName, id=%d, name=%s, value=%s", response.objId, name.c_str(), value.c_str()); std::shared_ptr<RemoteResponse> rr = RemoteResponse::get(response.objId); if (rr == nullptr) return; rr->getDelegate()->SetHeaderByName(name, value, overwrite); } void ServerHandler::Response_GetHeaderMap( std::map<std::string, std::string>& _return, const thrift_codegen::RObject& response) { MEASURE; if (doTraceRequest && Log::isTraceEnabled()) Log::trace("ServerHandler: Response_GetHeaderMap, id=%d", response.objId); std::shared_ptr<RemoteResponse> rr = RemoteResponse::get(response.objId); if (rr == nullptr) return; CefRequest::HeaderMap hmap; rr->getDelegate()->GetHeaderMap(hmap); fillMap(_return, hmap); } void ServerHandler::Response_SetHeaderMap( const thrift_codegen::RObject& response, const std::map<std::string, std::string>& headerMap) { MEASURE; if (doTraceRequest && Log::isTraceEnabled()) Log::trace("ServerHandler: Response_SetHeaderMap, id=%d", response.objId); std::shared_ptr<RemoteResponse> rr = RemoteResponse::get(response.objId); if (rr == nullptr) return; CefRequest::HeaderMap hmap; fillMap(hmap, headerMap); rr->getDelegate()->SetHeaderMap(hmap); } void ServerHandler::Request_GetPostData( thrift_codegen::PostData& _return, const thrift_codegen::RObject& request ) { MEASURE; if (doTraceRequest && Log::isTraceEnabled()) Log::trace("ServerHandler: Request_GetPostData, id=%d", request.objId); std::shared_ptr<RemoteRequest> rr = RemoteRequest::get(request.objId); if (rr == nullptr) return; CefRefPtr<CefPostData> pd = rr->getDelegate()->GetPostData(); if (!pd) return; _return.isNull = false; _return.isReadOnly = pd->IsReadOnly(); _return.hasExcludedElements = pd->HasExcludedElements(); if (pd->GetElementCount() > 0) { std::vector<thrift_codegen::PostDataElement> resultElements; CefPostData::ElementVector elements; pd->GetElements(elements); for (auto e : elements) { thrift_codegen::PostDataElement ee; ee.isReadOnly = e->IsReadOnly(); ee.type = e->GetType(); if (e->GetType() == PDE_TYPE_FILE) ee.__set_file(e->GetFile()); if (e->GetBytesCount() > 0) { char* buf = new char[e->GetBytesCount()]; e->GetBytes(e->GetBytesCount(), buf); std::string bytes((const char*)buf, e->GetBytesCount()); bytes.assign((const char*)buf, e->GetBytesCount()); ee.__set_bytes(bytes); delete[] buf; } resultElements.push_back(ee); } _return.__set_elements(resultElements); } } void ServerHandler::Request_SetPostData( const thrift_codegen::RObject& request, const thrift_codegen::PostData& postData) { MEASURE; if (doTraceRequest && Log::isTraceEnabled()) Log::trace("ServerHandler: Request_SetPostData, id=%d, PostData isNull=%d", request.objId, postData.isNull); std::shared_ptr<RemoteRequest> rr = RemoteRequest::get(request.objId); if (rr == nullptr) return; CefRefPtr<CefPostData> pd = new RemotePostData(postData); rr->getDelegate()->SetPostData(pd); } void ServerHandler::Request_Set( const thrift_codegen::RObject& request, const std::string& url, const std::string& method, const thrift_codegen::PostData& postData, const std::map<std::string, std::string>& headerMap) { MEASURE; if (doTraceRequest && Log::isTraceEnabled()) Log::trace("ServerHandler: Request_Set, id=%d, url=%s, method=%s, PostData isNull=%d", request.objId, url.c_str(), method.c_str(), postData.isNull); std::shared_ptr<RemoteRequest> rr = RemoteRequest::get(request.objId); if (rr == nullptr) return; CefRefPtr<CefPostData> pd = new RemotePostData(postData); CefRequest::HeaderMap hmap; fillMap(hmap, headerMap); rr->getDelegate()->Set(url, method, pd, hmap); } void ServerHandler::AuthCallback_Dispose(const thrift_codegen::RObject& authCallback) { MEASURE; if (doTraceCallbacks && Log::isTraceEnabled()) Log::trace("ServerHandler: AuthCallback_Dispose, id=%d", authCallback.objId); RemoteAuthCallback::dispose(authCallback.objId); } void ServerHandler::AuthCallback_Continue( const thrift_codegen::RObject& authCallback, const std::string& username, const std::string& password ) { MEASURE; if (doTraceCallbacks && Log::isTraceEnabled()) Log::trace("ServerHandler: AuthCallback_Continue, id=%d", authCallback.objId); std::shared_ptr<RemoteAuthCallback> rc = RemoteAuthCallback::get(authCallback.objId); if (rc == nullptr) return; rc->getDelegate()->Continue(username, password); RemoteAuthCallback::dispose(authCallback.objId); } void ServerHandler::AuthCallback_Cancel(const thrift_codegen::RObject& authCallback) { MEASURE; if (doTraceCallbacks && Log::isTraceEnabled()) Log::trace("ServerHandler: AuthCallback_Cancel, id=%d", authCallback.objId); std::shared_ptr<RemoteAuthCallback> rc = RemoteAuthCallback::get(authCallback.objId); if (rc == nullptr) return; rc->getDelegate()->Cancel(); RemoteAuthCallback::dispose(authCallback.objId); } void ServerHandler::Callback_Dispose(const thrift_codegen::RObject& callback) { MEASURE; if (doTraceCallbacks && Log::isTraceEnabled()) Log::trace("ServerHandler: Callback_Dispose, id=%d", callback.objId); RemoteCallback::dispose(callback.objId); } void ServerHandler::Callback_Continue(const thrift_codegen::RObject& callback) { MEASURE; if (doTraceCallbacks && Log::isTraceEnabled()) Log::trace("ServerHandler: Callback_Continue, id=%d", callback.objId); std::shared_ptr<RemoteCallback> rc = RemoteCallback::get(callback.objId); if (rc == nullptr) return; rc->getDelegate()->Continue(); RemoteCallback::dispose(callback.objId); } void ServerHandler::Callback_Cancel(const thrift_codegen::RObject& callback) { MEASURE; if (doTraceCallbacks && Log::isTraceEnabled()) Log::trace("ServerHandler: Callback_Cancel, id=%d", callback.objId); std::shared_ptr<RemoteCallback> rc = RemoteCallback::get(callback.objId); if (rc == nullptr) return; rc->getDelegate()->Cancel(); RemoteCallback::dispose(callback.objId); } void ServerHandler::CefRunContextMenuCallback_Dispose(const thrift_codegen::RObject& self) { MEASURE; if (doTraceCallbacks && Log::isTraceEnabled()) Log::trace("ServerHandler: CefRunContextMenuCallback_Dispose, id=%d", self.objId); RemoteCefRunContextMenuCallback::dispose(self.objId); } void ServerHandler::CefRunContextMenuCallback_Continue( const thrift_codegen::RObject& self, const int32_t command_id, const int32_t event_flag) { MEASURE; if (doTraceCallbacks && Log::isTraceEnabled()) Log::trace("ServerHandler: CefRunContextMenuCallback_Continue, id=%d", self.objId); const auto self_wrapper = RemoteCefRunContextMenuCallback::get(self.objId); if (self_wrapper == nullptr) return; self_wrapper->getDelegate()->Continue(command_id, static_cast<cef_event_flags_t>(event_flag)); RemoteCefRunContextMenuCallback::dispose(self.objId); } void ServerHandler::CefRunContextMenuCallback_Cancel(const thrift_codegen::RObject& self) { MEASURE; if (doTraceCallbacks && Log::isTraceEnabled()) Log::trace("ServerHandler: CefRunContextMenuCallback_Cancel, id=%d", self.objId); const auto self_wrapper = RemoteCefRunContextMenuCallback::get(self.objId); if (self_wrapper == nullptr) return; self_wrapper->getDelegate()->Cancel(); RemoteCefRunContextMenuCallback::dispose(self.objId); } void ServerHandler::MessageRouter_Create(thrift_codegen::RObject& _return, const std::string& query, const std::string& cancel) { MEASURE; _return = RemoteMessageRouter::create(myCtx, query, cancel)->serverId(); if (doTraceMessageRouter && Log::isTraceEnabled()) Log::trace("ServerHandler: MessageRouter_Create, query='%s', cancel='%s', created id=%d", query.c_str(), cancel.c_str(), _return.objId); } void ServerHandler::MessageRouter_Dispose(const thrift_codegen::RObject& msgRouter) { MEASURE; if (doTraceMessageRouter && Log::isTraceEnabled()) Log::trace("ServerHandler: MessageRouter_Dispose, id=%d", msgRouter.objId); RemoteMessageRouter::dispose(msgRouter.objId); } void ServerHandler::Client_AddMessageRouter(int cid, const thrift_codegen::RObject& msgRouter) { MEASURE; if ((doTraceMessageRouter || doTraceClient) && Log::isTraceEnabled()) Log::trace("ServerHandler: Client_AddMessageRouter, cid=%d, id=%d", cid, msgRouter.objId); std::shared_ptr<RemoteMessageRouter> rmr = RemoteMessageRouter::get(msgRouter.objId); if (rmr == nullptr) { Log::error("ServerHandler: Client_AddMessageRouter: can't find RemoteMessageRouter by objId=%d", msgRouter.objId); return; } std::shared_ptr<RemoteClient> rc = myCtx->findRemoteClient(cid); if (!rc) { Log::error("ServerHandler: Client_AddMessageRouter: can't find RemoteClient by cid=%d", cid); return; } rc->addMessageRouter(rmr); } void ServerHandler::Client_RemoveMessageRouter(int cid, const thrift_codegen::RObject& msgRouter) { MEASURE; if ((doTraceMessageRouter || doTraceClient) && Log::isTraceEnabled()) Log::trace("ServerHandler: Client_RemoveMessageRouter, cid=%d, id=%d", cid, msgRouter.objId); std::shared_ptr<RemoteMessageRouter> rmr = RemoteMessageRouter::get(msgRouter.objId); if (rmr == nullptr) { Log::error("ServerHandler: Client_RemoveMessageRouter: can't find RemoteMessageRouter by objId=%d", msgRouter.objId); return; } std::shared_ptr<RemoteClient> rc = myCtx->findRemoteClient(cid); if (!rc) { Log::error("ServerHandler: Client_RemoveMessageRouter: can't find RemoteClient by cid=%d", cid); return; } rc->removeMessageRouter(rmr); } namespace { // NOTE: must be called on UI thread (and [docs says] that CancelPending can be called on any thread) void ServerHandler_MessageRouter_AddHandler_Impl( std::shared_ptr<RpcExecutor> service, const thrift_codegen::RObject& msgRouter, const thrift_codegen::RObject& handler, bool first) { MEASURE; if (doTraceMessageRouter && Log::isTraceEnabled()) Log::trace("ServerHandler: MessageRouter_AddHandler, router id=%d, handler id=%d", msgRouter.objId, handler.objId); std::shared_ptr<RemoteMessageRouter> rmr = RemoteMessageRouter::get(msgRouter.objId); if (rmr == nullptr) { Log::error("ServerHandler: can't find router %d", msgRouter.objId); return; } rmr->AddRemoteHandler(handler, first); } void ServerHandler_MessageRouter_RemoveHandler_Impl( const thrift_codegen::RObject& msgRouter, const thrift_codegen::RObject& handler) { MEASURE; if (doTraceMessageRouter && Log::isTraceEnabled()) Log::trace("ServerHandler: MessageRouter_RemoveHandler, router id=%d, handler id=%d", msgRouter.objId, handler.objId); std::shared_ptr<RemoteMessageRouter> rmr = RemoteMessageRouter::get(msgRouter.objId); if (rmr != nullptr) { rmr->RemoveRemoteHandler(handler); } else Log::error("ServerHandler: can't find router %d for removing handler %d", msgRouter.objId, handler.objId); } } void ServerHandler::MessageRouter_AddHandler( const thrift_codegen::RObject& msgRouter, const thrift_codegen::RObject& handler, bool first) { if (CefCurrentlyOn(TID_UI)) { ServerHandler_MessageRouter_AddHandler_Impl(myCtx->javaService(), msgRouter, handler, first); } else { CefPostTask(TID_UI, base::BindOnce( [](std::shared_ptr<RpcExecutor> service, const thrift_codegen::RObject& msgRouter, const thrift_codegen::RObject& handler, bool first) { ServerHandler_MessageRouter_AddHandler_Impl(service, msgRouter, handler, first); }, myCtx->javaService(), msgRouter, handler, first)); } } void ServerHandler::MessageRouter_RemoveHandler( const thrift_codegen::RObject& msgRouter, const thrift_codegen::RObject& handler) { if (CefCurrentlyOn(TID_UI)) { ServerHandler_MessageRouter_RemoveHandler_Impl(msgRouter, handler); } else { CefPostTask(TID_UI, base::BindOnce( []( const thrift_codegen::RObject& msgRouter, const thrift_codegen::RObject& handler) { ServerHandler_MessageRouter_RemoveHandler_Impl(msgRouter, handler); }, msgRouter, handler)); } } void ServerHandler::MessageRouter_CancelPending( const thrift_codegen::RObject& msgRouter, const int32_t bid, const thrift_codegen::RObject& handler) { MEASURE; if (doTraceMessageRouter && Log::isTraceEnabled()) Log::trace("ServerHandler: MessageRouter_CancelPending, router id=%d, handler id=%d, bid=%d", msgRouter.objId, handler.objId, bid); std::shared_ptr<RemoteMessageRouter> rmr = RemoteMessageRouter::get(msgRouter.objId); if (!rmr) return; std::shared_ptr<RemoteBrowser> rb = RemoteBrowser::find(bid); if (!rb) return; CefRefPtr<CefBrowser> browser = rb->getCefBrowser(); if (!browser) return; std::shared_ptr<RemoteMessageRouterHandler> rmrh = rmr->FindRemoteHandler(handler.objId); if (rmrh) rmr->getDelegate()->CancelPending(browser, rmrh.get()); } void ServerHandler::QueryCallback_Dispose(const thrift_codegen::RObject& qcallback) { MEASURE; if (doTraceMessageRouterCallbacks && Log::isTraceEnabled()) Log::trace("ServerHandler: QueryCallback_Dispose, id=%d", qcallback.objId); RemoteQueryCallback::dispose(qcallback.objId); } void ServerHandler::QueryCallback_Success( const thrift_codegen::RObject& qcallback, const std::string& response) { MEASURE; if (doTraceMessageRouterCallbacks && Log::isTraceEnabled()) Log::trace("ServerHandler: QueryCallback_Success, id=%d, response='%s'", qcallback.objId, response.c_str()); std::shared_ptr<RemoteQueryCallback> rc = RemoteQueryCallback::get(qcallback.objId); if (rc == nullptr) return; rc->getDelegate()->Success(response); RemoteQueryCallback::dispose(qcallback.objId); } void ServerHandler::QueryCallback_Failure( const thrift_codegen::RObject& qcallback, const int32_t error_code, const std::string& error_message) { MEASURE; if (doTraceMessageRouterCallbacks && Log::isTraceEnabled()) Log::trace("ServerHandler: QueryCallback_Failure, id=%d, err_code=%d, err_msg='%s'", qcallback.objId, error_code, error_message.c_str()); std::shared_ptr<RemoteQueryCallback> rc = RemoteQueryCallback::get(qcallback.objId); if (rc == nullptr) return; rc->getDelegate()->Failure(error_code, error_message); RemoteQueryCallback::dispose(qcallback.objId); } /// /// Register a scheme handler factory with the global request context. An empty /// |domain_name| value for a standard scheme will cause the factory to match /// all domain names. The |domain_name| value will be ignored for non-standard /// schemes. If |scheme_name| is a built-in scheme and no handler is returned by /// |factory| then the built-in scheme handler factory will be called. If /// |scheme_name| is a custom scheme then you must also implement the /// CefApp::OnRegisterCustomSchemes() method in all processes. This function may /// be called multiple times to change or remove the factory that matches the /// specified |scheme_name| and optional |domain_name|. Returns false if an /// error occurs. This function may be called on any thread in the browser /// process. Using this function is equivalent to calling /// CefRequestContext::GetGlobalContext()->RegisterSchemeHandlerFactory(). /// void ServerHandler::SchemeHandlerFactory_Register( const std::string& schemeName, const std::string& domainName, const thrift_codegen::RObject& schemeHandlerFactory) { MEASURE; CefRefPtr<RemoteSchemeHandlerFactory> factory = new RemoteSchemeHandlerFactory(myCtx, schemeHandlerFactory); const bool result = CefRegisterSchemeHandlerFactory(schemeName,domainName, factory); if (result) Log::trace("ServerHandler: registered SchemeHandlerFactory: schemeName=%s, domainName=%s, peer-id=%d", schemeName.c_str(), domainName.c_str(), schemeHandlerFactory.objId); else Log::error("ServerHandler: can't register SchemeHandlerFactory: schemeName=%s, domainName=%s, peer-id=%d", schemeName.c_str(), domainName.c_str(), schemeHandlerFactory.objId); } void ServerHandler::ClearAllSchemeHandlerFactories() { MEASURE; Log::trace("ServerHandler: cleared all SchemeHandlerFactory instances."); CefClearSchemeHandlerFactories(); } void ServerHandler::RequestContext_ClearCertificateExceptions(const int32_t bid, const thrift_codegen::RObject& rcompletionCallback) { MEASURE; CefRefPtr<RemoteCompletionCallback> cb; if (!rcompletionCallback.isNull) cb = new RemoteCompletionCallback(myCtx, rcompletionCallback); if (bid < 0) { // NOTE: assume that GlobalContext is linked with negative bid. CefRefPtr<CefRequestContext> globalContext = CefRequestContext::GetGlobalContext(); if (globalContext) { globalContext->ClearCertificateExceptions(cb); Log::debug("ServerHandler: cleared all certificate exceptions in global RequestContext."); } return; } auto rb = RemoteBrowser::find(bid); if (!rb) return; rb->getRequestContext()->ClearCertificateExceptions(cb); if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: RequestContext_ClearCertificateExceptions, bid=%d.", bid); } void ServerHandler::RequestContext_CloseAllConnections(const int32_t bid, const thrift_codegen::RObject& rcompletionCallback) { MEASURE; CefRefPtr<RemoteCompletionCallback> cb; if (!rcompletionCallback.isNull) cb = new RemoteCompletionCallback(myCtx, rcompletionCallback); if (bid < 0) { // NOTE: assume that GlobalContext is linked with negative bid. CefRefPtr<CefRequestContext> globalContext = CefRequestContext::GetGlobalContext(); if (globalContext) { globalContext->CloseAllConnections(cb); Log::debug("ServerHandler: closed all connections in global RequestContext."); } return; } auto rb = RemoteBrowser::find(bid); if (!rb) return; rb->getRequestContext()->CloseAllConnections(cb); if (doTraceBrowser && Log::isTraceEnabled()) Log::trace("ServerHandler: RequestContext_CloseAllConnections, bid=%d.", bid); } void ServerHandler::CookieManager_Create(thrift_codegen::RObject& _return) { MEASURE; // TODO(JCEF): Expose the callback object. CefRefPtr<CefCookieManager> manager = CefCookieManager::GetGlobalManager(nullptr); if (!manager) return; std::shared_ptr<RemoteCookieManager> rm = RemoteCookieManager::create(myCtx->javaServiceIO(), manager); _return = rm->serverId(); if (doTraceCookie && Log::isTraceEnabled()) Log::trace("ServerHandler: CookieManager_Create, created id=%d", rm->getId()); } void ServerHandler::CookieManager_Dispose(const thrift_codegen::RObject& cookieManager) { MEASURE; if (doTraceCookie && Log::isTraceEnabled()) Log::trace("ServerHandler: CookieManager_Dispose, id=%d", cookieManager.objId); RemoteCookieManager::dispose(cookieManager.objId); } bool ServerHandler::CookieManager_VisitAllCookies(const thrift_codegen::RObject& cookieManager, const thrift_codegen::RObject& visitor) { MEASURE; if (doTraceCookie && Log::isTraceEnabled()) Log::trace("ServerHandler: CookieManager_VisitAllCookies, id=%d", cookieManager.objId); GET_COOKIE_MANAGER_OR_RETURN_VAL(false); CefRefPtr<RemoteCookieVisitor> rvisitor(new RemoteCookieVisitor(myCtx, visitor)); return manager->getDelegate()->VisitAllCookies(rvisitor); } bool ServerHandler::CookieManager_VisitUrlCookies( const thrift_codegen::RObject& cookieManager, const thrift_codegen::RObject& visitor, const std::string& url, const bool includeHttpOnly ) { MEASURE; if (doTraceCookie && Log::isTraceEnabled()) Log::trace("ServerHandler: CookieManager_VisitUrlCookies, id=%d, url=%s", cookieManager.objId, url.c_str()); GET_COOKIE_MANAGER_OR_RETURN_VAL(false); CefRefPtr<RemoteCookieVisitor> rvisitor(new RemoteCookieVisitor(myCtx, visitor)); return manager->getDelegate()->VisitUrlCookies(url, includeHttpOnly, rvisitor); } bool ServerHandler::CookieManager_SetCookie( const thrift_codegen::RObject& cookieManager, const std::string& url, const thrift_codegen::Cookie& c ) { MEASURE; if (doTraceCookie && Log::isTraceEnabled()) Log::trace("ServerHandler: CookieManager_SetCookie, id=%d, url=%s", cookieManager.objId, url.c_str()); GET_COOKIE_MANAGER_OR_RETURN_VAL(false); CefCookie cookie; RemoteCookieVisitor::toCefCookie(c, cookie); // The method CefCookieManager::SetCookie must be called on the IO thread. // We ignore its return value and return the result of the PostTask event to // java instead. // TODO(JCEF): Expose the callback object. bool result = CefPostTask( TID_IO, base::BindOnce(base::IgnoreResult(&CefCookieManager::SetCookie), manager->getDelegate(), url, cookie, CefRefPtr<CefSetCookieCallback>())); return result; } bool ServerHandler::CookieManager_DeleteCookies( const thrift_codegen::RObject& cookieManager, const std::string& url, const std::string& cookieName ) { MEASURE; if (doTraceCookie && Log::isTraceEnabled()) Log::trace("ServerHandler: CookieManager_DeleteCookies, id=%d, url=%s, name=%s", cookieManager.objId, url.c_str(), cookieName.c_str()); GET_COOKIE_MANAGER_OR_RETURN_VAL(false); // The method CefCookieManager::DeleteCookies must be called on the IO thread. // We ignore its return value and return the result of the PostTask event to // java instead. // TODO(JCEF): Expose the callback object. bool result = CefPostTask( TID_IO, base::BindOnce(base::IgnoreResult(&CefCookieManager::DeleteCookies), manager->getDelegate(), url, cookieName, CefRefPtr<CefDeleteCookiesCallback>())); return result; } bool ServerHandler::CookieManager_FlushStore( const thrift_codegen::RObject& cookieManager, const thrift_codegen::RObject& rcompletionCallback ) { MEASURE; if (doTraceCookie && Log::isTraceEnabled()) Log::trace("ServerHandler: CookieManager_FlushStore, id=%d", cookieManager.objId); GET_COOKIE_MANAGER_OR_RETURN_VAL(false); CefRefPtr<RemoteCompletionCallback> cb; if (!rcompletionCallback.isNull) cb = new RemoteCompletionCallback(myCtx, rcompletionCallback); return manager->getDelegate()->FlushStore(cb); } void ServerHandler::Registration_Dispose(const thrift_codegen::RObject& registration) { MEASURE; if (doTraceCallbacks && Log::isTraceEnabled()) Log::trace("ServerHandler: Registration_Dispose, id=%d", registration.objId); RemoteRegistration::dispose(registration.objId); } void ServerHandler::MediaAccessCallback_Dispose(const thrift_codegen::RObject& mediaAccessCallback) { MEASURE; if (doTraceCallbacks && Log::isTraceEnabled()) Log::trace("ServerHandler: MediaAccessCallback_Dispose, id=%d", mediaAccessCallback.objId); RemoteMediaAccessCallback::dispose(mediaAccessCallback.objId); } void ServerHandler::MediaAccessCallback_Continue(const thrift_codegen::RObject& mediaAccessCallback, const int32_t allowed_permissions) { MEASURE; if (doTraceCallbacks && Log::isTraceEnabled()) Log::trace("ServerHandler: MediaAccessCallback_Continue, id=%d, permissions=%d", mediaAccessCallback.objId, allowed_permissions); auto rc = RemoteMediaAccessCallback::get(mediaAccessCallback.objId); if (rc == nullptr) return; rc->getDelegate()->Continue(allowed_permissions); RemoteMediaAccessCallback::dispose(mediaAccessCallback.objId); } void ServerHandler::MediaAccessCallback_Cancel(const thrift_codegen::RObject& mediaAccessCallback) { MEASURE; if (doTraceCallbacks && Log::isTraceEnabled()) Log::trace("ServerHandler: MediaAccessCallback_Cancel, id=%d", mediaAccessCallback.objId); auto rc = RemoteMediaAccessCallback::get(mediaAccessCallback.objId); if (rc == nullptr) return; rc->getDelegate()->Cancel(); RemoteMediaAccessCallback::dispose(mediaAccessCallback.objId); } std::string ServerHandler::getDebugInfo(int tabs) const { std::stringstream ss; for (int i = 0; i < tabs; ++i) ss << "\t"; const std::shared_ptr<ServerHandlerContext> ctx = myCtx; if (!ctx) ss << "ServerHandler with disposed ctx " << this << std::endl; else { ss << "ServerHandler " << this << std::endl; ss << ctx->getDebugInfo(tabs + 1, myIsMainHandler); } return ss.str(); }