diff --git a/include/CefViewBrowserClient.h b/include/CefViewBrowserClient.h index e332b55..a1b3c5d 100644 --- a/include/CefViewBrowserClient.h +++ b/include/CefViewBrowserClient.h @@ -338,10 +338,17 @@ class CefViewBrowserClient const void* buffer, int width, int height) override; +#if CEF_VERSION_MAJOR >= 122 + virtual void OnAcceleratedPaint(CefRefPtr browser, + PaintElementType type, + const RectList& dirtyRects, + const CefAcceleratedPaintInfo& info) override; +#else virtual void OnAcceleratedPaint(CefRefPtr browser, PaintElementType type, const RectList& dirtyRects, void* shared_handle) override; +#endif virtual bool StartDragging(CefRefPtr browser, CefRefPtr drag_data, CefRenderHandler::DragOperationsMask allowed_ops, @@ -378,8 +385,14 @@ class CefViewBrowserClient int64 new_size, CefRefPtr callback) override; #endif - +#if CEF_VERSION_MAJOR >= 122 + virtual void OnRenderProcessTerminated(CefRefPtr browser, + TerminationStatus status, + int error_code, + const CefString& error_string) override; +#else virtual void OnRenderProcessTerminated(CefRefPtr browser, TerminationStatus status) override; +#endif #pragma endregion // CefResourceRequestHandler diff --git a/include/CefViewBrowserClientDelegate.h b/include/CefViewBrowserClientDelegate.h index 5fdfbb9..231c54d 100644 --- a/include/CefViewBrowserClientDelegate.h +++ b/include/CefViewBrowserClientDelegate.h @@ -13,6 +13,7 @@ #include #include +#include /// /// @@ -27,6 +28,26 @@ class CefViewBrowserClientDelegateInterface virtual void processUrlRequest(const std::string& url) = 0; +#if CEF_VERSION_MAJOR >= 122 + virtual void processQueryRequest(CefRefPtr& browser, + const std::string& frameId, + const std::string& query, + const int64_t query_id) = 0; + + virtual void focusedEditableNodeChanged(CefRefPtr& browser, + const std::string& frameId, + bool focusOnEditableNode) = 0; + + virtual void invokeMethodNotify(CefRefPtr& browser, + const std::string& frameId, + const std::string& method, + const CefRefPtr& arguments) = 0; + + virtual void reportJSResult(CefRefPtr& browser, + const std::string& frameId, + const std::string& context, + const CefRefPtr& result) = 0; +#else virtual void processQueryRequest(CefRefPtr& browser, int64_t frameId, const std::string& query, @@ -45,6 +66,7 @@ class CefViewBrowserClientDelegateInterface int64_t frameId, const std::string& context, const CefRefPtr& result) = 0; +#endif // context menu handler #pragma region ContextMenuHandler @@ -80,7 +102,11 @@ class CefViewBrowserClientDelegateInterface // display handler #pragma region DisplayHandler +#if CEF_VERSION_MAJOR >= 122 + virtual void addressChanged(CefRefPtr& browser, const std::string& frameId, const std::string& url) = 0; +#else virtual void addressChanged(CefRefPtr& browser, int64_t frameId, const std::string& url) = 0; +#endif virtual void titleChanged(CefRefPtr& browser, const std::string& title) = 0; @@ -129,6 +155,16 @@ class CefViewBrowserClientDelegateInterface // life span handler #pragma region LifeSpanHandler +#if CEF_VERSION_MAJOR >= 122 + virtual bool onBeforePopup(CefRefPtr& browser, + const std::string& frameId, + const std::string& targetUrl, + const std::string& targetFrameName, + CefLifeSpanHandler::WindowOpenDisposition targetDisposition, + CefWindowInfo& windowInfo, + CefBrowserSettings& settings, + bool& DisableJavascriptAccess) = 0; +#else virtual bool onBeforePopup(CefRefPtr& browser, int64_t frameId, const std::string& targetUrl, @@ -137,6 +173,8 @@ class CefViewBrowserClientDelegateInterface CefWindowInfo& windowInfo, CefBrowserSettings& settings, bool& DisableJavascriptAccess) = 0; +#endif + virtual void onAfterCreate(CefRefPtr& browser) = 0; virtual bool doClose(CefRefPtr browser) = 0; @@ -209,12 +247,21 @@ class CefViewBrowserClientDelegateInterface int height) { } +#if CEF_VERSION_MAJOR >= 122 + virtual void onAcceleratedPaint(CefRefPtr browser, + CefRenderHandler::PaintElementType type, + const CefRenderHandler::RectList& dirtyRects, + const CefAcceleratedPaintInfo& info) + { + } +#else virtual void onAcceleratedPaint(CefRefPtr browser, CefRenderHandler::PaintElementType type, const CefRenderHandler::RectList& dirtyRects, void* shared_handle) { } +#endif virtual bool startDragging(CefRefPtr browser, CefRefPtr drag_data, CefRenderHandler::DragOperationsMask allowed_ops, diff --git a/src/CefView/CefBrowserApp/CefViewBrowserClient_RenderHandler.cpp b/src/CefView/CefBrowserApp/CefViewBrowserClient_RenderHandler.cpp index 4d58e28..0e3e201 100644 --- a/src/CefView/CefBrowserApp/CefViewBrowserClient_RenderHandler.cpp +++ b/src/CefView/CefBrowserApp/CefViewBrowserClient_RenderHandler.cpp @@ -89,12 +89,19 @@ CefViewBrowserClient::OnPaint(CefRefPtr browser, if (delegate) return delegate->onPaint(browser, type, dirtyRects, buffer, width, height); } - +#if CEF_VERSION_MAJOR >= 122 +void +CefViewBrowserClient::OnAcceleratedPaint(CefRefPtr browser, + PaintElementType type, + const RectList& dirtyRects, + const CefAcceleratedPaintInfo& shared_handle) +#else void CefViewBrowserClient::OnAcceleratedPaint(CefRefPtr browser, PaintElementType type, const RectList& dirtyRects, void* shared_handle) +#endif { auto delegate = client_delegate_.lock(); if (delegate) diff --git a/src/CefView/CefBrowserApp/CefViewBrowserClient_RequestHandler.cpp b/src/CefView/CefBrowserApp/CefViewBrowserClient_RequestHandler.cpp index d82d1c7..c7067db 100644 --- a/src/CefView/CefBrowserApp/CefViewBrowserClient_RequestHandler.cpp +++ b/src/CefView/CefBrowserApp/CefViewBrowserClient_RequestHandler.cpp @@ -61,8 +61,16 @@ CefViewBrowserClient::OnQuotaRequest(CefRefPtr browser, } #endif +#if CEF_VERSION_MAJOR >= 122 +void +CefViewBrowserClient::OnRenderProcessTerminated(CefRefPtr browser, + TerminationStatus status, + int error_code, + const CefString& error_string) +#else void CefViewBrowserClient::OnRenderProcessTerminated(CefRefPtr browser, TerminationStatus status) +#endif { CEF_REQUIRE_UI_THREAD(); diff --git a/src/CefWing/CefRenderApp/RenderDelegates/CefViewDefaultRenderDelegate.cpp b/src/CefWing/CefRenderApp/RenderDelegates/CefViewDefaultRenderDelegate.cpp index 375bee0..7a80d0b 100644 --- a/src/CefWing/CefRenderApp/RenderDelegates/CefViewDefaultRenderDelegate.cpp +++ b/src/CefWing/CefRenderApp/RenderDelegates/CefViewDefaultRenderDelegate.cpp @@ -1,103 +1,123 @@ -#pragma region project_headers -#include "Common/CefViewCoreLog.h" -#include "CefViewDefaultRenderDelegate.h" -#include "CefViewClient.h" -#include "CefViewCoreProtocol.h" -#pragma endregion project_headers - -namespace CefViewDefaultRenderDelegate { -void -CreateBrowserDelegate(CefViewRenderApp::RenderDelegateSet& delegates, const std::string& bridge_name) -{ - delegates.insert(new RenderDelegate(bridge_name)); -} +#include + +#pragma region std_headers +#include +#include +#include +#pragma endregion std_headers + +#pragma region cef_headers +#include +#pragma endregion cef_headers -RenderDelegate::RenderDelegate(const std::string& bridge_name) - : bridge_object_name_(bridge_name) +#include +#include + +CefViewBrowserClient::CefViewBrowserClient(CefRefPtr app, + CefViewBrowserClientDelegateInterface::RefPtr delegate) + : is_closing_(false) + , close_by_native_(false) + , initial_navigation_(true) + , app_(app) + , client_delegate_(delegate) + , cefquery_handler_(nullptr) + , message_router_(nullptr) + , resource_manager_(new CefResourceManager()) { + app_->CheckInClient(this); + + // Create the browser-side router for query handling. + message_router_config_.js_query_function = kCefViewQueryFuntionName; + message_router_config_.js_cancel_function = kCefViewQueryCancelFunctionName; } -void -RenderDelegate::OnWebKitInitialized(CefRefPtr app) +CefViewBrowserClient::~CefViewBrowserClient() { - CefMessageRouterConfig config; - config.js_query_function = kCefViewQueryFuntionName; - config.js_cancel_function = kCefViewQueryCancelFunctionName; - render_message_router_ = CefMessageRouterRendererSide::Create(config); + log_debug("CefViewBrowserClient::~CefViewBrowserClient()"); + app_->CheckOutClient(this); } void -RenderDelegate::OnContextCreated(CefRefPtr app, - CefRefPtr browser, - CefRefPtr frame, - CefRefPtr context) +CefViewBrowserClient::CloseAllBrowsers() { - // [Javascript Context] - // V8 context for this frame has been initialized already, - // but the script of the page hasn't been executed now - render_message_router_->OnContextCreated(browser, frame, context); - - // log this event - frame->ExecuteJavaScript("console.info('[JSRuntime]:frame context created')", frame->GetURL(), 0); - - // binding bridge object and functions - auto frameId = frame->GetIdentifier(); - auto it = frame_id_to_client_map_.find(frameId); - if (it == frame_id_to_client_map_.end()) { - // create and insert the bridge Object into this frame.window object - CefRefPtr objWindow = context->GetGlobal(); - CefRefPtr objClient = new CefViewClient(browser, frame, objWindow, bridge_object_name_); - if (!objClient) { - log_error("Failed to create the client object"); - return; - } - frame_id_to_client_map_[frameId] = objClient; + close_by_native_ = true; + auto browsers = browser_map_; + for (auto& kv : browsers) { + kv.second->StopLoad(); + kv.second->GetHost()->CloseBrowser(true); } } void -RenderDelegate::OnContextReleased(CefRefPtr app, - CefRefPtr browser, - CefRefPtr frame, - CefRefPtr context) +CefViewBrowserClient::AddLocalDirectoryResourceProvider(const std::string& dir_path, + const std::string& url, + int priority /* = 0*/) { - render_message_router_->OnContextReleased(browser, frame, context); + if (dir_path.empty() || url.empty()) + return; - auto frameId = frame->GetIdentifier(); - auto it = frame_id_to_client_map_.find(frameId); - if (it != frame_id_to_client_map_.end()) { - frame_id_to_client_map_.erase(it); - } + // convert to lower case + auto lower_url = url; + std::transform( + lower_url.begin(), lower_url.end(), lower_url.begin(), [](unsigned char c) { return std::tolower(c); }); + + std::string identifier; + resource_manager_->AddDirectoryProvider(lower_url, dir_path, priority, identifier); } void -RenderDelegate::OnFocusedNodeChanged(CefRefPtr app, - CefRefPtr browser, - CefRefPtr frame, - CefRefPtr node) +CefViewBrowserClient::AddArchiveResourceProvider(const std::string& archive_path, + const std::string& url, + const std::string& password, + int priority /*= 0*/) { - bool is_editable = (node.get() && node->IsEditable()); - if (is_editable != last_node_is_editable_) { - // Notify the browser of the change in focused element type. - last_node_is_editable_ = is_editable; - CefRefPtr message = CefProcessMessage::Create(kCefViewClientRenderFocusedNodeChangedMessage); - message->GetArgumentList()->SetBool(0, is_editable); - frame->SendProcessMessage(PID_BROWSER, message); - } + if (archive_path.empty() || url.empty()) + return; + + std::string identifier; + resource_manager_->AddArchiveProvider(url, archive_path, password, 0, identifier); } bool -RenderDelegate::OnProcessMessageReceived(CefRefPtr app, - CefRefPtr browser, - CefRefPtr frame, - CefProcessId source_process, - CefRefPtr message) +CefViewBrowserClient::TriggerEvent(CefRefPtr browser, + const int64_t frame_id, + const CefRefPtr msg) { - if (render_message_router_->OnProcessMessageReceived(browser, frame, source_process, message)) { - return true; - } + if (msg->GetName().empty()) + return false; + + if (browser) { +#if CEF_VERSION_MAJOR >= 122 + std::vector frameIds; + if (MAIN_FRAME == frame_id) { + frameIds.push_back(browser->GetMainFrame()->GetIdentifier()); + } else if (ALL_FRAMES == frame_id) { + browser->GetFrameIdentifiers(frameIds); + } else { + frameIds.push_back(std::to_string(frame_id)); + } +#else + std::vector frameIds; + if (MAIN_FRAME == frame_id) { + frameIds.push_back(browser->GetMainFrame()->GetIdentifier()); + } else if (ALL_FRAMES == frame_id) { + browser->GetFrameIdentifiers(frameIds); + } else { + frameIds.push_back(frame_id); + } +#endif + + + for (const auto& id : frameIds) { + auto m = msg->Copy(); +#if CEF_VERSION_MAJOR >= 122 + auto frame = browser->GetFrameByIdentifier(id); +#else + auto frame = browser->GetFrame(id); +#endif + frame->SendProcessMessage(PID_RENDERER, m); + } - if (OnTriggerEventNotifyMessage(browser, frame, source_process, message)) { return true; } @@ -105,59 +125,154 @@ RenderDelegate::OnProcessMessageReceived(CefRefPtr app, } bool -RenderDelegate::OnTriggerEventNotifyMessage(CefRefPtr browser, - CefRefPtr frame, - CefProcessId source_process, - CefRefPtr message) +CefViewBrowserClient::ResponseQuery(const int64_t query, bool success, const CefString& response, int error) { - if (message->GetName() == kCefViewClientBrowserTriggerEventMessage) { - CefRefPtr args = message->GetArgumentList()->Copy(); - //** arguments(CefValueList) - //** +------------+ - //** | event name | - //** | event arg1 | - //** | event arg2 | - //** | event arg3 | - //** | event arg4 | - //** | ... | - //** | ... | - //** | ... | - //** | ... | - //** +------------+ - if (!args || args->GetSize() <= 0) { - log_error("Invalid message arguments, event name is required"); - return true; - } + if (cefquery_handler_) + return cefquery_handler_->Response(query, success, response, error); - if (CefValueType::VTYPE_STRING != args->GetType(0)) { - log_error("Invalid message arguments, invalid type for event name"); - return true; - } + return false; +} - auto name = args->GetString(0); - args->Remove(0); - ExecuteEventListener(browser, frame, name, args); +int64_t +CefViewBrowserClient::AsyncExecuteJSCode(CefRefPtr browser, + CefRefPtr frame, + const CefString& code, + const CefString& url, + const CefString& context) +{ + /* + * Javascript code: + * + * window.__cefview_report_js_result__(context, function() { ... })()); + */ + std::ostringstream codeWrapper; + codeWrapper << "window." << kCefViewReportJSResultFunctionName // + << "(" // + << "\"" << context << "\", " // + << "function(){" << code << " }()" // + << ");"; - return true; + frame->ExecuteJavaScript(codeWrapper.str().c_str(), url, 0); + + return true; +} + +bool +CefViewBrowserClient::DispatchRenderMessage(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr message) +{ + auto msgName = message->GetName(); + if (msgName == kCefViewClientRenderFocusedNodeChangedMessage) { + return OnRenderFocusedNodeChangedMessage(browser, frame, message); + } else if (msgName == kCefViewClientRenderInvokeMethodMessage) { + return OnRenderInvokeMethodMessage(browser, frame, message); + } else if (msgName == kCefViewClientRenderReportJSResultMessage) { + return OnRenderReportJSResultMessage(browser, frame, message); + } else { } return false; } -void -RenderDelegate::ExecuteEventListener(CefRefPtr browser, - CefRefPtr frame, - const CefString& name, - CefRefPtr args) +bool +CefViewBrowserClient::OnRenderFocusedNodeChangedMessage(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr message) { - if (browser && frame) { - auto frameId = frame->GetIdentifier(); - auto it = frame_id_to_client_map_.find(frameId); - if (it != frame_id_to_client_map_.end()) { - const CefRefPtr& objClient = it->second; - objClient->ExecuteEventListener(name, args); - } - } + auto delegate = client_delegate_.lock(); + if (!delegate) + return false; + + // validate the argument list + CefRefPtr arguments = message->GetArgumentList(); + if (!arguments || (arguments->GetSize() < 1)) + return false; + + if (CefValueType::VTYPE_BOOL != arguments->GetType(0)) + return false; + + bool focusOnEditableField = message->GetArgumentList()->GetBool(0); + delegate->focusedEditableNodeChanged(browser, frame->GetIdentifier(), focusOnEditableField); + + return true; +} + +bool +CefViewBrowserClient::OnRenderInvokeMethodMessage(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr message) +{ + // validate the argument list + CefRefPtr arguments = message->GetArgumentList(); + if (!arguments || (arguments->GetSize() < 1)) + return false; + + // validate the delegate + auto delegate = client_delegate_.lock(); + if (!delegate) + return false; + + // copy the arguments + arguments = arguments->Copy(); + + // validate the method name + std::string method; + if (CefValueType::VTYPE_STRING != arguments->GetType(0)) + return false; + method = arguments->GetString(0).ToString(); + if (method.empty()) + return false; + arguments->Remove(0); + + delegate->invokeMethodNotify(browser, frame->GetIdentifier(), method, arguments); + + return true; +} + +bool +CefViewBrowserClient::OnRenderReportJSResultMessage(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr message) +{ + // validate the argument list + CefRefPtr arguments = message->GetArgumentList(); + if (!arguments || (arguments->GetSize() != 2)) + return false; + + // validate the delegate + auto delegate = client_delegate_.lock(); + if (!delegate) + return false; + + // get context + std::string context; + if (CefValueType::VTYPE_STRING != arguments->GetType(0)) + return false; + context = arguments->GetString(0).ToString(); + if (context.empty()) + return false; + + // get script result + auto result = arguments->GetValue(1); + + delegate->reportJSResult(browser, frame->GetIdentifier(), context, result); + + return true; } -} // namespace CefViewDefaultRenderDelegate +bool +CefViewBrowserClient::OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, + CefProcessId source_process, + CefRefPtr message) +{ + CEF_REQUIRE_UI_THREAD(); + if (message_router_->OnProcessMessageReceived(browser, frame, source_process, message)) + return true; + + if (DispatchRenderMessage(browser, frame, message)) + return true; + + return false; +} diff --git a/src/CefWing/CefRenderApp/RenderDelegates/CefViewDefaultRenderDelegate.h b/src/CefWing/CefRenderApp/RenderDelegates/CefViewDefaultRenderDelegate.h index 81e69cd..d612947 100644 --- a/src/CefWing/CefRenderApp/RenderDelegates/CefViewDefaultRenderDelegate.h +++ b/src/CefWing/CefRenderApp/RenderDelegates/CefViewDefaultRenderDelegate.h @@ -4,6 +4,7 @@ #pragma endregion #pragma region cef_headers +#include #include #pragma endregion cef_headers @@ -27,7 +28,11 @@ class RenderDelegate : public CefViewRenderApp::RenderDelegate /// /// /// +#if CEF_VERSION_MAJOR >= 122 + typedef std::unordered_map> FrameID2CefClientMap; +#else typedef std::unordered_map> FrameID2CefClientMap; +#endif public: /// diff --git a/src/Shared/Common/CefViewDebug.cpp b/src/Shared/Common/CefViewDebug.cpp index d09928b..ad40bc8 100644 --- a/src/Shared/Common/CefViewDebug.cpp +++ b/src/Shared/Common/CefViewDebug.cpp @@ -45,7 +45,9 @@ std::string toString(CefRefPtr frame) msg += ", IsMain=" + std::to_string(frame->IsMain()); msg += ", IsFocused=" + std::to_string(frame->IsFocused()); msg += ", GetName=" + frame->GetName().ToString(); +#if CEF_VERSION_MAJOR < 122 msg += ", GetIdentifier=" + std::to_string(frame->GetIdentifier()); +#endif msg += ", GetParent=" + std::to_string((int64_t)frame->GetParent().get()); msg += ", GetURL=" + frame->GetURL().ToString(); msg += ", GetBrowser=" + std::to_string((int64_t)frame->GetBrowser().get());