diff --git a/BUILD.gn b/BUILD.gn index d883fab46..350b41d6a 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -514,6 +514,8 @@ static_library("libcef_static") { "libcef/common/extensions/extensions_util.cc", "libcef/common/extensions/extensions_util.h", "libcef/common/file_util_impl.cc", + "libcef/common/frame_util.cc", + "libcef/common/frame_util.h", "libcef/common/json_impl.cc", "libcef/common/main_delegate.cc", "libcef/common/main_delegate.h", diff --git a/include/capi/cef_browser_capi.h b/include/capi/cef_browser_capi.h index 0b1944f9b..d96a78dc6 100644 --- a/include/capi/cef_browser_capi.h +++ b/include/capi/cef_browser_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=2385e0531c91a419fe7f4036b5a59da743b1622e$ +// $hash=623d324a1ef5637353ae74761fdc04eac4d99716$ // #ifndef CEF_INCLUDE_CAPI_CEF_BROWSER_CAPI_H_ @@ -45,7 +45,6 @@ #include "include/capi/cef_frame_capi.h" #include "include/capi/cef_image_capi.h" #include "include/capi/cef_navigation_entry_capi.h" -#include "include/capi/cef_process_message_capi.h" #include "include/capi/cef_request_context_capi.h" #ifdef __cplusplus @@ -179,15 +178,6 @@ typedef struct _cef_browser_t { /// void(CEF_CALLBACK* get_frame_names)(struct _cef_browser_t* self, cef_string_list_t names); - - /// - // Send a message to the specified |target_process|. Returns true (1) if the - // message was sent successfully. - /// - int(CEF_CALLBACK* send_process_message)( - struct _cef_browser_t* self, - cef_process_id_t target_process, - struct _cef_process_message_t* message); } cef_browser_t; /// diff --git a/include/capi/cef_client_capi.h b/include/capi/cef_client_capi.h index 802ed79d4..3c8c32428 100644 --- a/include/capi/cef_client_capi.h +++ b/include/capi/cef_client_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=485de431252b72e5516f3f7f16a8d6f416801dfd$ +// $hash=c8b6ce6786bb8369c3d9bb9e932a115fb379b145$ // #ifndef CEF_INCLUDE_CAPI_CEF_CLIENT_CAPI_H_ @@ -166,6 +166,7 @@ typedef struct _cef_client_t { int(CEF_CALLBACK* on_process_message_received)( struct _cef_client_t* self, struct _cef_browser_t* browser, + struct _cef_frame_t* frame, cef_process_id_t source_process, struct _cef_process_message_t* message); } cef_client_t; diff --git a/include/capi/cef_drag_handler_capi.h b/include/capi/cef_drag_handler_capi.h index a05d36d46..e34d1b030 100644 --- a/include/capi/cef_drag_handler_capi.h +++ b/include/capi/cef_drag_handler_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=22ebb1d811a4e0a834eb115859d797c72a5c4ca3$ +// $hash=5c7eb1cee72dcb8b7657007b3f9db64680ea8c4d$ // #ifndef CEF_INCLUDE_CAPI_CEF_DRAG_HANDLER_CAPI_H_ @@ -43,6 +43,7 @@ #include "include/capi/cef_base_capi.h" #include "include/capi/cef_browser_capi.h" #include "include/capi/cef_drag_data_capi.h" +#include "include/capi/cef_frame_capi.h" #ifdef __cplusplus extern "C" { @@ -79,6 +80,7 @@ typedef struct _cef_drag_handler_t { void(CEF_CALLBACK* on_draggable_regions_changed)( struct _cef_drag_handler_t* self, struct _cef_browser_t* browser, + struct _cef_frame_t* frame, size_t regionsCount, cef_draggable_region_t const* regions); } cef_drag_handler_t; diff --git a/include/capi/cef_frame_capi.h b/include/capi/cef_frame_capi.h index 23472d153..0fdaa3ac9 100644 --- a/include/capi/cef_frame_capi.h +++ b/include/capi/cef_frame_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=4e8384d7f289708b09f08be98c5477f2be3fde97$ +// $hash=6bef924a259845dbf03e9cf5084ff7feb2771034$ // #ifndef CEF_INCLUDE_CAPI_CEF_FRAME_CAPI_H_ @@ -42,6 +42,7 @@ #include "include/capi/cef_base_capi.h" #include "include/capi/cef_dom_capi.h" +#include "include/capi/cef_process_message_capi.h" #include "include/capi/cef_request_capi.h" #include "include/capi/cef_stream_capi.h" #include "include/capi/cef_string_visitor_capi.h" @@ -244,6 +245,17 @@ typedef struct _cef_frame_t { struct _cef_frame_t* self, struct _cef_request_t* request, struct _cef_urlrequest_client_t* client); + + /// + // Send a message to the specified |target_process|. Message delivery is not + // guaranteed in all cases (for example, if the browser is closing, + // navigating, or if the target process crashes). Send an ACK message back + // from the target process if confirmation is required. + /// + void(CEF_CALLBACK* send_process_message)( + struct _cef_frame_t* self, + cef_process_id_t target_process, + struct _cef_process_message_t* message); } cef_frame_t; #ifdef __cplusplus diff --git a/include/capi/cef_render_process_handler_capi.h b/include/capi/cef_render_process_handler_capi.h index 6d01d80c5..4c893e613 100644 --- a/include/capi/cef_render_process_handler_capi.h +++ b/include/capi/cef_render_process_handler_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=a3cf58db4b29d7395975ab8d63461b5ea8aad064$ +// $hash=6c6efd722dda7480a5449ef31f1d6d9a16fd3465$ // #ifndef CEF_INCLUDE_CAPI_CEF_RENDER_PROCESS_HANDLER_CAPI_H_ @@ -166,6 +166,7 @@ typedef struct _cef_render_process_handler_t { int(CEF_CALLBACK* on_process_message_received)( struct _cef_render_process_handler_t* self, struct _cef_browser_t* browser, + struct _cef_frame_t* frame, cef_process_id_t source_process, struct _cef_process_message_t* message); } cef_render_process_handler_t; diff --git a/include/cef_api_hash.h b/include/cef_api_hash.h index b2e17bfe4..6d0e5c1eb 100644 --- a/include/cef_api_hash.h +++ b/include/cef_api_hash.h @@ -34,7 +34,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=2fc75812c34a605fb4e67a5942f6597c6dd3be78$ +// $hash=0bc0d1faa22392b4245dc6eaf56337e7847a1900$ // #ifndef CEF_INCLUDE_API_HASH_H_ @@ -47,13 +47,13 @@ // way that may cause binary incompatibility with other builds. The universal // hash value will change if any platform is affected whereas the platform hash // values will change only if that particular platform is affected. -#define CEF_API_HASH_UNIVERSAL "f9715e9bc13434498505eecee052706483eb7892" +#define CEF_API_HASH_UNIVERSAL "31b55dcbcf52e9f51fe423741f64e5c77e71c65a" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "7bd952f75673366dc4834de5e5995798d3db91f0" +#define CEF_API_HASH_PLATFORM "afb8ea794d1bb0f56ba5ce1718a16e5dfd64229e" #elif defined(OS_MACOSX) -#define CEF_API_HASH_PLATFORM "daa91396f67341e7bde65747f69487ecde4e3cf5" +#define CEF_API_HASH_PLATFORM "e3a279cf087095495c08fd9fa88daef5dbafff3a" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "be8ed9d9ba0b53e18c5c0adae09ff841b1fa7063" +#define CEF_API_HASH_PLATFORM "d25833941c670d82cff0aa0ccf47b557d6813634" #endif #ifdef __cplusplus diff --git a/include/cef_browser.h b/include/cef_browser.h index 69f048c2a..79c9259bd 100644 --- a/include/cef_browser.h +++ b/include/cef_browser.h @@ -44,7 +44,6 @@ #include "include/cef_frame.h" #include "include/cef_image.h" #include "include/cef_navigation_entry.h" -#include "include/cef_process_message.h" #include "include/cef_request_context.h" class CefBrowserHost; @@ -181,14 +180,6 @@ class CefBrowser : public virtual CefBaseRefCounted { /// /*--cef()--*/ virtual void GetFrameNames(std::vector& names) = 0; - - /// - // Send a message to the specified |target_process|. Returns true if the - // message was sent successfully. - /// - /*--cef()--*/ - virtual bool SendProcessMessage(CefProcessId target_process, - CefRefPtr message) = 0; }; /// diff --git a/include/cef_client.h b/include/cef_client.h index 986d44ae1..d4e3696f0 100644 --- a/include/cef_client.h +++ b/include/cef_client.h @@ -158,6 +158,7 @@ class CefClient : public virtual CefBaseRefCounted { /// /*--cef()--*/ virtual bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) { return false; diff --git a/include/cef_drag_handler.h b/include/cef_drag_handler.h index 0410c0d8d..dfa226e31 100644 --- a/include/cef_drag_handler.h +++ b/include/cef_drag_handler.h @@ -41,6 +41,7 @@ #include "include/cef_base.h" #include "include/cef_browser.h" #include "include/cef_drag_data.h" +#include "include/cef_frame.h" /// // Implement this interface to handle events related to dragging. The methods of @@ -74,6 +75,7 @@ class CefDragHandler : public virtual CefBaseRefCounted { /*--cef()--*/ virtual void OnDraggableRegionsChanged( CefRefPtr browser, + CefRefPtr frame, const std::vector& regions) {} }; diff --git a/include/cef_frame.h b/include/cef_frame.h index 4533b037f..6d1ac6bc7 100644 --- a/include/cef_frame.h +++ b/include/cef_frame.h @@ -40,6 +40,7 @@ #include "include/cef_base.h" #include "include/cef_dom.h" +#include "include/cef_process_message.h" #include "include/cef_request.h" #include "include/cef_stream.h" #include "include/cef_string_visitor.h" @@ -248,6 +249,16 @@ class CefFrame : public virtual CefBaseRefCounted { virtual CefRefPtr CreateURLRequest( CefRefPtr request, CefRefPtr client) = 0; + + /// + // Send a message to the specified |target_process|. Message delivery is not + // guaranteed in all cases (for example, if the browser is closing, + // navigating, or if the target process crashes). Send an ACK message back + // from the target process if confirmation is required. + /// + /*--cef()--*/ + virtual void SendProcessMessage(CefProcessId target_process, + CefRefPtr message) = 0; }; #endif // CEF_INCLUDE_CEF_FRAME_H_ diff --git a/include/cef_render_process_handler.h b/include/cef_render_process_handler.h index de2d9a447..98680cffb 100644 --- a/include/cef_render_process_handler.h +++ b/include/cef_render_process_handler.h @@ -148,6 +148,7 @@ class CefRenderProcessHandler : public virtual CefBaseRefCounted { /// /*--cef()--*/ virtual bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) { return false; diff --git a/include/wrapper/cef_message_router.h b/include/wrapper/cef_message_router.h index 9765be76a..93442222a 100644 --- a/include/wrapper/cef_message_router.h +++ b/include/wrapper/cef_message_router.h @@ -360,6 +360,7 @@ class CefMessageRouterBrowserSide /// virtual bool OnProcessMessageReceived( CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) = 0; @@ -415,6 +416,7 @@ class CefMessageRouterRendererSide /// virtual bool OnProcessMessageReceived( CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) = 0; diff --git a/libcef/browser/audio_mirror_destination.cc b/libcef/browser/audio_mirror_destination.cc index 020d146cc..e295886b8 100644 --- a/libcef/browser/audio_mirror_destination.cc +++ b/libcef/browser/audio_mirror_destination.cc @@ -68,8 +68,8 @@ void CefAudioMirrorDestination::QueryForMatchesOnUIThread( std::set matches; for (auto& candidate : candidates) { CefRefPtr browser = - CefBrowserHostImpl::GetBrowserForFrame(candidate.child_id, - candidate.frame_routing_id); + CefBrowserHostImpl::GetBrowserForFrameRoute(candidate.child_id, + candidate.frame_routing_id); if (browser == browser_) { matches.insert(candidate); } diff --git a/libcef/browser/browser_host_impl.cc b/libcef/browser/browser_host_impl.cc index beb14425b..974de0fab 100644 --- a/libcef/browser/browser_host_impl.cc +++ b/libcef/browser/browser_host_impl.cc @@ -25,7 +25,6 @@ #include "libcef/browser/extensions/extension_web_contents_observer.h" #include "libcef/browser/image_impl.h" #include "libcef/browser/media_capture_devices_dispatcher.h" -#include "libcef/browser/navigate_params.h" #include "libcef/browser/navigation_entry_impl.h" #include "libcef/browser/net/chrome_scheme_handler.h" #include "libcef/browser/net/scheme_handler.h" @@ -38,7 +37,6 @@ #include "libcef/common/drag_data_impl.h" #include "libcef/common/extensions/extensions_util.h" #include "libcef/common/main_delegate.h" -#include "libcef/common/process_message_impl.h" #include "libcef/common/request_impl.h" #include "libcef/common/values_impl.h" @@ -85,10 +83,6 @@ using content::KeyboardEventProcessingResult; namespace { -const int kUnspecifiedFrameTreeNodeId = -3; -const int kMainFrameTreeNodeId = -2; -const int kUnusedFrameTreeNodeId = -1; - // Associates a CefBrowserHostImpl instance with a WebContents. This object will // be deleted automatically when the WebContents is destroyed. class WebContentsUserDataAdapter : public base::SupportsUserData::Data { @@ -386,9 +380,8 @@ CefRefPtr CefBrowserHostImpl::Create( browser->web_contents(), create_params.url, create_params.extension_host_type); } else if (!create_params.url.is_empty()) { - browser->LoadURL(CefFrameHostImpl::kMainFrameId, create_params.url.spec(), - content::Referrer(), ui::PAGE_TRANSITION_TYPED, - std::string()); + browser->LoadMainFrameURL(create_params.url.spec(), content::Referrer(), + ui::PAGE_TRANSITION_TYPED, std::string()); } return browser.get(); @@ -496,32 +489,6 @@ CefRefPtr CefBrowserHostImpl::GetBrowserForContents( return WebContentsUserDataAdapter::Get(contents); } -// static -CefRefPtr CefBrowserHostImpl::GetBrowserForRequest( - const net::URLRequest* request) { - DCHECK(request); - CEF_REQUIRE_IOT(); - - // When navigating the main frame a new (pre-commit) URLRequest will be - // created before the RenderFrameHost. Consequently we can't rely on - // ResourceRequestInfo::GetRenderFrameForRequest returning a valid frame - // ID. See https://crbug.com/776884 for background. - int render_process_id = -1; - int render_frame_id = MSG_ROUTING_NONE; - if (content::ResourceRequestInfo::GetRenderFrameForRequest( - request, &render_process_id, &render_frame_id) && - render_process_id >= 0 && render_frame_id >= 0) { - return GetBrowserForFrame(render_process_id, render_frame_id); - } - - content::ResourceRequestInfo* request_info = - content::ResourceRequestInfo::ForRequest(request); - if (request_info) - return GetBrowserForFrameTreeNode(request_info->GetFrameTreeNodeId()); - - return nullptr; -} - // static CefRefPtr CefBrowserHostImpl::GetBrowserForFrameTreeNode( int frame_tree_node_id) { @@ -543,7 +510,7 @@ CefRefPtr CefBrowserHostImpl::GetBrowserForFrameTreeNode( } // static -CefRefPtr CefBrowserHostImpl::GetBrowserForFrame( +CefRefPtr CefBrowserHostImpl::GetBrowserForFrameRoute( int render_process_id, int render_routing_id) { if (render_process_id == -1 || render_routing_id == MSG_ROUTING_NONE) @@ -560,7 +527,7 @@ CefRefPtr CefBrowserHostImpl::GetBrowserForFrame( // Use the thread-safe approach. bool is_guest_view = false; scoped_refptr info = - CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrame( + CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameRoute( render_process_id, render_routing_id, &is_guest_view); if (info.get() && !is_guest_view) { CefRefPtr browser = info->browser(); @@ -1446,95 +1413,60 @@ CefRefPtr CefBrowserHostImpl::GetFocusedFrame() { } CefRefPtr CefBrowserHostImpl::GetFrame(int64 identifier) { - base::AutoLock lock_scope(state_lock_); - - if (main_frame_id_ == CefFrameHostImpl::kInvalidFrameId) { - // A main frame does not exist yet. Return the placeholder frame that - // provides limited functionality. - return GetOrCreatePendingFrame(kMainFrameTreeNodeId, - CefFrameHostImpl::kInvalidFrameId, nullptr) - .get(); - } - - if (identifier == CefFrameHostImpl::kMainFrameId) { - identifier = main_frame_id_; - } else if (identifier == CefFrameHostImpl::kFocusedFrameId) { - // Return the main frame if no focused frame is currently identified. - if (focused_frame_id_ == CefFrameHostImpl::kInvalidFrameId) - identifier = main_frame_id_; - else - identifier = focused_frame_id_; - } - - if (identifier == CefFrameHostImpl::kInvalidFrameId) + if (identifier == CefFrameHostImpl::kInvalidFrameId) { return nullptr; + } else if (identifier == CefFrameHostImpl::kMainFrameId) { + return browser_info_->GetMainFrame(); + } else if (identifier == CefFrameHostImpl::kFocusedFrameId) { + base::AutoLock lock_scope(state_lock_); + if (!focused_frame_) { + // The main frame is focused by default. + return browser_info_->GetMainFrame(); + } + return focused_frame_; + } - FrameIdMap::const_iterator it = frames_.find(identifier); - if (it != frames_.end()) - return it->second.get(); - - return nullptr; + return browser_info_->GetFrameForId(identifier); } CefRefPtr CefBrowserHostImpl::GetFrame(const CefString& name) { - base::AutoLock lock_scope(state_lock_); - - FrameIdMap::const_iterator it = frames_.begin(); - for (; it != frames_.end(); ++it) { - if (it->second->GetName() == name) - return it->second.get(); + for (const auto& frame : browser_info_->GetAllFrames()) { + if (frame->GetName() == name) + return frame; } - return nullptr; } size_t CefBrowserHostImpl::GetFrameCount() { - base::AutoLock lock_scope(state_lock_); - return frames_.size(); + return browser_info_->GetAllFrames().size(); } void CefBrowserHostImpl::GetFrameIdentifiers(std::vector& identifiers) { - base::AutoLock lock_scope(state_lock_); - if (identifiers.size() > 0) identifiers.clear(); - FrameIdMap::const_iterator it = frames_.begin(); - for (; it != frames_.end(); ++it) - identifiers.push_back(it->first); + const auto frames = browser_info_->GetAllFrames(); + if (frames.empty()) + return; + + identifiers.reserve(frames.size()); + for (const auto& frame : frames) { + identifiers.push_back(frame->GetIdentifier()); + } } void CefBrowserHostImpl::GetFrameNames(std::vector& names) { - base::AutoLock lock_scope(state_lock_); - if (names.size() > 0) names.clear(); - FrameIdMap::const_iterator it = frames_.begin(); - for (; it != frames_.end(); ++it) - names.push_back(it->second->GetName()); -} + const auto frames = browser_info_->GetAllFrames(); + if (frames.empty()) + return; -bool CefBrowserHostImpl::SendProcessMessage( - CefProcessId target_process, - CefRefPtr message) { - DCHECK_EQ(PID_RENDERER, target_process); - DCHECK(message.get()); - - Cef_Request_Params params; - CefProcessMessageImpl* impl = - static_cast(message.get()); - if (!impl->CopyTo(params)) - return false; - - DCHECK(!params.name.empty()); - - params.frame_id = -1; - params.user_initiated = true; - params.request_id = -1; - params.expect_response = false; - - return Send(new CefMsg_Request(MSG_ROUTING_NONE, params)); + names.reserve(frames.size()); + for (const auto& frame : frames) { + names.push_back(frame->GetName()); + } } // CefBrowserHostImpl public methods. @@ -1595,13 +1527,7 @@ void CefBrowserHostImpl::DestroyBrowser() { // Disassociate the platform delegate from this browser. platform_delegate_->BrowserDestroyed(this); - while (!queued_messages_.empty()) { - delete queued_messages_.front(); - queued_messages_.pop(); - } - registrar_.reset(NULL); - response_manager_.reset(NULL); content::WebContentsObserver::Observe(NULL); if (owned_web_contents_) owned_web_contents_.reset(NULL); @@ -1615,10 +1541,8 @@ void CefBrowserHostImpl::DestroyBrowser() { // Delete the platform delegate. platform_delegate_.reset(NULL); - DetachAllFrames(); - CefBrowserInfoManager::GetInstance()->RemoveBrowserInfo(browser_info_); - browser_info_->set_browser(NULL); + browser_info_->SetBrowser(nullptr); } #if defined(USE_AURA) @@ -1644,228 +1568,89 @@ void CefBrowserHostImpl::CancelContextMenu() { } CefRefPtr CefBrowserHostImpl::GetFrameForHost( - const content::RenderFrameHost* host_const) { + const content::RenderFrameHost* host) { CEF_REQUIRE_UIT(); - if (!host_const) + if (!host) return nullptr; - content::RenderFrameHost* host = - const_cast(host_const); - content::RenderFrameHost* parent = host->GetParent(); - return GetOrCreateFrame( - host->GetRoutingID(), host->GetFrameTreeNodeId(), - parent ? parent->GetRoutingID() : CefFrameHostImpl::kUnspecifiedFrameId, - parent == nullptr /* is_main_frame */, - false /* is_main_frame_state_flaky */, base::string16(), GURL()); + + return browser_info_->GetFrameForHost(host); } -CefRefPtr CefBrowserHostImpl::GetFrameForHostRoutingId( - int render_frame_id) { - return GetOrCreateFrame( - render_frame_id, kUnspecifiedFrameTreeNodeId, - CefFrameHostImpl::kUnspecifiedFrameId, false /* is_main_frame */, - true /* is_main_frame_state_flaky */, base::string16(), GURL()); -} - -CefRefPtr CefBrowserHostImpl::GetFrameForRequest( - const net::URLRequest* request) { - CEF_REQUIRE_IOT(); - content::ResourceRequestInfo* info = - content::ResourceRequestInfo::ForRequest(request); - if (!info) - return nullptr; - // The value of |IsMainFrame| is unreliable in these cases. - const bool is_main_frame_state_flaky = - info->IsDownload() || - info->GetResourceType() == content::RESOURCE_TYPE_XHR || - info->GetResourceType() == content::RESOURCE_TYPE_SCRIPT; - return GetOrCreateFrame(info->GetRenderFrameID(), info->GetFrameTreeNodeId(), - CefFrameHostImpl::kUnspecifiedFrameId, - info->IsMainFrame(), is_main_frame_state_flaky, - base::string16(), GURL()); -} - -void CefBrowserHostImpl::Navigate(const CefNavigateParams& params) { - // Only known frame ids and kMainFrameId are supported. - DCHECK(params.frame_id >= CefFrameHostImpl::kMainFrameId); - - CefMsg_LoadRequest_Params request; - request.url = params.url; - if (!request.url.is_valid()) { - LOG(ERROR) << "Invalid URL passed to CefBrowserHostImpl::Navigate: " - << params.url; +void CefBrowserHostImpl::LoadMainFrameURL(const std::string& url, + const content::Referrer& referrer, + ui::PageTransition transition, + const std::string& extra_headers) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::BindOnce(&CefBrowserHostImpl::LoadMainFrameURL, this, + url, referrer, transition, extra_headers)); return; } - request.method = params.method; - request.referrer = params.referrer.url; - request.referrer_policy = - CefRequestImpl::BlinkReferrerPolicyToNetReferrerPolicy( - params.referrer.policy); - request.frame_id = params.frame_id; - request.site_for_cookies = params.site_for_cookies; - request.headers = params.headers; - request.load_flags = params.load_flags; - request.upload_data = params.upload_data; + // Go through the navigation controller. + if (navigation_locked()) { + // Try again after the lock has been released. + set_pending_navigation_action( + base::BindOnce(&CefBrowserHostImpl::LoadMainFrameURL, this, url, + referrer, transition, extra_headers)); + return; + } - Send(new CefMsg_LoadRequest(MSG_ROUTING_NONE, request)); + if (web_contents()) { + GURL gurl = GURL(url); - OnSetFocus(FOCUS_SOURCE_NAVIGATION); -} - -void CefBrowserHostImpl::LoadRequest(int64 frame_id, - CefRefPtr request) { - CefNavigateParams params(GURL(), ui::PAGE_TRANSITION_TYPED); - params.frame_id = frame_id; - - static_cast(request.get())->Get(params); - - Navigate(params); -} - -void CefBrowserHostImpl::LoadURL(int64 frame_id, - const std::string& url, - const content::Referrer& referrer, - ui::PageTransition transition, - const std::string& extra_headers) { - if (frame_id == CefFrameHostImpl::kMainFrameId) { - // Go through the navigation controller. - if (CEF_CURRENTLY_ON_UIT()) { - if (navigation_locked()) { - // Try again after the lock has been released. - set_pending_navigation_action( - base::BindOnce(&CefBrowserHostImpl::LoadURL, this, frame_id, url, - referrer, transition, extra_headers)); - return; - } - - if (web_contents()) { - GURL gurl = GURL(url); - - if (!gurl.is_valid() && !gurl.has_scheme()) { - // Try to add "http://" at the beginning - std::string new_url = std::string("http://") + url; - gurl = GURL(new_url); - } - - if (!gurl.is_valid()) { - LOG(ERROR) << "Invalid URL passed to CefBrowserHostImpl::LoadURL: " - << url; - return; - } - - web_contents()->GetController().LoadURL(gurl, referrer, transition, - extra_headers); - OnSetFocus(FOCUS_SOURCE_NAVIGATION); - } - } else { - CEF_POST_TASK(CEF_UIT, - base::BindOnce(&CefBrowserHostImpl::LoadURL, this, frame_id, - url, referrer, transition, extra_headers)); + if (!gurl.is_valid() && !gurl.has_scheme()) { + // Try to add "http://" at the beginning + std::string new_url = std::string("http://") + url; + gurl = GURL(new_url); } - } else { - CefNavigateParams params(GURL(url), transition); - params.frame_id = frame_id; - params.referrer = referrer; - params.headers = extra_headers; - Navigate(params); + + if (!gurl.is_valid()) { + LOG(ERROR) + << "Invalid URL passed to CefBrowserHostImpl::LoadMainFrameURL: " + << url; + return; + } + + web_contents()->GetController().LoadURL(gurl, referrer, transition, + extra_headers); + OnSetFocus(FOCUS_SOURCE_NAVIGATION); } } -void CefBrowserHostImpl::LoadString(int64 frame_id, - const std::string& string, - const std::string& url) { - // Only known frame ids or kMainFrameId are supported. - DCHECK(frame_id >= CefFrameHostImpl::kMainFrameId); +void CefBrowserHostImpl::OnFrameFocused(CefRefPtr frame) { + DCHECK(frame); - Cef_Request_Params params; - params.name = "load-string"; - params.frame_id = frame_id; - params.user_initiated = false; - params.request_id = -1; - params.expect_response = false; + CefRefPtr previous_frame; + { + base::AutoLock lock_scope(state_lock_); + previous_frame = focused_frame_; + if (frame->IsMain()) + focused_frame_ = nullptr; + else + focused_frame_ = frame; + } - params.arguments.AppendString(string); - params.arguments.AppendString(url); + if (!previous_frame) { + // The main frame is focused by default. + previous_frame = browser_info_->GetMainFrame(); + } - Send(new CefMsg_Request(MSG_ROUTING_NONE, params)); -} - -void CefBrowserHostImpl::SendCommand( - int64 frame_id, - const std::string& command, - CefRefPtr responseHandler) { - // Only known frame ids are supported. - DCHECK(frame_id > CefFrameHostImpl::kMainFrameId); - DCHECK(!command.empty()); - - // Execute on the UI thread because CefResponseManager is not thread safe. - if (CEF_CURRENTLY_ON_UIT()) { - TRACE_EVENT2("cef", "CefBrowserHostImpl::SendCommand", "frame_id", frame_id, - "needsResponse", responseHandler.get() ? 1 : 0); - Cef_Request_Params params; - params.name = "execute-command"; - params.frame_id = frame_id; - params.user_initiated = false; - - if (responseHandler.get()) { - params.request_id = response_manager_->RegisterHandler(responseHandler); - params.expect_response = true; - } else { - params.request_id = -1; - params.expect_response = false; - } - - params.arguments.AppendString(command); - - Send(new CefMsg_Request(MSG_ROUTING_NONE, params)); - } else { - CEF_POST_TASK(CEF_UIT, - base::BindOnce(&CefBrowserHostImpl::SendCommand, this, - frame_id, command, responseHandler)); + if (previous_frame->GetIdentifier() != frame->GetIdentifier()) { + previous_frame->SetFocused(false); + frame->SetFocused(true); } } -void CefBrowserHostImpl::SendCode( - int64 frame_id, - bool is_javascript, - const std::string& code, - const std::string& script_url, - int script_start_line, - CefRefPtr responseHandler) { - // Only known frame ids are supported. - DCHECK(frame_id >= CefFrameHostImpl::kMainFrameId); - DCHECK(!code.empty()); - DCHECK_GE(script_start_line, 0); +void CefBrowserHostImpl::OnDidFinishLoad(CefRefPtr frame, + const GURL& validated_url, + int http_status_code) { + frame->RefreshAttributes(); - // Execute on the UI thread because CefResponseManager is not thread safe. - if (CEF_CURRENTLY_ON_UIT()) { - TRACE_EVENT2("cef", "CefBrowserHostImpl::SendCommand", "frame_id", frame_id, - "needsResponse", responseHandler.get() ? 1 : 0); - Cef_Request_Params params; - params.name = "execute-code"; - params.frame_id = frame_id; - params.user_initiated = false; + // Give internal scheme handlers an opportunity to update content. + scheme::DidFinishLoad(frame, validated_url); - if (responseHandler.get()) { - params.request_id = response_manager_->RegisterHandler(responseHandler); - params.expect_response = true; - } else { - params.request_id = -1; - params.expect_response = false; - } - - params.arguments.AppendBoolean(is_javascript); - params.arguments.AppendString(code); - params.arguments.AppendString(script_url); - params.arguments.AppendInteger(script_start_line); - - Send(new CefMsg_Request(MSG_ROUTING_NONE, params)); - } else { - CEF_POST_TASK(CEF_UIT, - base::BindOnce(&CefBrowserHostImpl::SendCode, this, frame_id, - is_javascript, code, script_url, - script_start_line, responseHandler)); - } + OnLoadEnd(frame, validated_url, http_status_code); } void CefBrowserHostImpl::ViewText(const std::string& text) { @@ -2229,8 +2014,8 @@ content::WebContents* CefBrowserHostImpl::OpenURLFromTab( if (!cancel) { // Start a navigation in the current browser that will result in the // creation of a new render process. - LoadURL(CefFrameHostImpl::kMainFrameId, params.url.spec(), params.referrer, - params.transition, params.extra_headers); + LoadMainFrameURL(params.url.spec(), params.referrer, params.transition, + params.extra_headers); return source; } @@ -2689,25 +2474,7 @@ bool CefBrowserHostImpl::IsNeverVisible(content::WebContents* web_contents) { void CefBrowserHostImpl::RenderFrameCreated( content::RenderFrameHost* render_frame_host) { - const int render_process_id = render_frame_host->GetProcess()->GetID(); - const int render_routing_id = render_frame_host->GetRoutingID(); - if (!browser_info_->render_id_manager()->is_render_frame_id_match( - render_process_id, render_routing_id)) { - browser_info_->render_id_manager()->add_render_frame_id(render_process_id, - render_routing_id); - } - - const int frame_tree_node_id = render_frame_host->GetFrameTreeNodeId(); - if (!browser_info_->frame_tree_node_id_manager()->is_frame_tree_node_id_match( - frame_tree_node_id)) { - browser_info_->frame_tree_node_id_manager()->add_frame_tree_node_id( - frame_tree_node_id); - } - - const bool is_main_frame = (render_frame_host->GetParent() == nullptr); - request_context_->OnRenderFrameCreated(render_process_id, render_routing_id, - frame_tree_node_id, is_main_frame, - false); + browser_info_->MaybeCreateFrame(render_frame_host, false /* is_guest_view */); } void CefBrowserHostImpl::RenderFrameHostChanged( @@ -2717,44 +2484,15 @@ void CefBrowserHostImpl::RenderFrameHostChanged( RenderFrameCreated(new_host); } -void CefBrowserHostImpl::FrameDeleted( +void CefBrowserHostImpl::RenderFrameDeleted( content::RenderFrameHost* render_frame_host) { - // The ID entries should currently exist. - const int render_process_id = render_frame_host->GetProcess()->GetID(); - const int render_routing_id = render_frame_host->GetRoutingID(); - browser_info_->render_id_manager()->remove_render_frame_id(render_process_id, - render_routing_id); - - const int frame_tree_node_id = render_frame_host->GetFrameTreeNodeId(); - browser_info_->frame_tree_node_id_manager()->remove_frame_tree_node_id( - frame_tree_node_id); - - const bool is_main_frame = (render_frame_host->GetParent() == nullptr); - request_context_->OnRenderFrameDeleted(render_process_id, render_routing_id, - frame_tree_node_id, is_main_frame, - false); + const auto frame_id = CefFrameHostImpl::MakeFrameId(render_frame_host); + browser_info_->RemoveFrame(render_frame_host); base::AutoLock lock_scope(state_lock_); - if (render_routing_id >= 0) { - FrameIdMap::iterator it = frames_.find(render_routing_id); - if (it != frames_.end()) { - it->second->Detach(); - frames_.erase(it); - } - - if (main_frame_id_ == render_routing_id) - main_frame_id_ = CefFrameHostImpl::kInvalidFrameId; - if (focused_frame_id_ == render_routing_id) - focused_frame_id_ = CefFrameHostImpl::kInvalidFrameId; - } - - if (frame_tree_node_id >= 0) { - FrameTreeNodeIdMap::iterator it = pending_frames_.find(frame_tree_node_id); - if (it != pending_frames_.end()) { - it->second->Detach(); - pending_frames_.erase(it); - } + if (focused_frame_ && focused_frame_->GetIdentifier() == frame_id) { + focused_frame_ = nullptr; } } @@ -2788,13 +2526,6 @@ void CefBrowserHostImpl::RenderViewDeleted( void CefBrowserHostImpl::RenderViewReady() { ConfigureAutoResize(); - // Send the queued messages. - queue_messages_ = false; - while (!queued_messages_.empty()) { - Send(queued_messages_.front()); - queued_messages_.pop(); - } - if (client_.get()) { CefRefPtr handler = client_->GetRequestHandler(); if (handler.get()) @@ -2803,8 +2534,6 @@ void CefBrowserHostImpl::RenderViewReady() { } void CefBrowserHostImpl::RenderProcessGone(base::TerminationStatus status) { - queue_messages_ = true; - cef_termination_status_t ts = TS_ABNORMAL_TERMINATION; if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) ts = TS_PROCESS_WAS_KILLED; @@ -2833,18 +2562,13 @@ void CefBrowserHostImpl::DidFinishNavigation( if (!navigation_handle->HasCommitted() && error_code == net::OK) return; - const int64 frame_id = - navigation_handle->GetRenderFrameHost() - ? navigation_handle->GetRenderFrameHost()->GetRoutingID() - : CefFrameHostImpl::kUnspecifiedFrameId; const bool is_main_frame = navigation_handle->IsInMainFrame(); const GURL& url = (error_code == net::OK ? navigation_handle->GetURL() : GURL()); - CefRefPtr frame = - GetOrCreateFrame(frame_id, navigation_handle->GetFrameTreeNodeId(), - CefFrameHostImpl::kUnspecifiedFrameId, is_main_frame, - false, base::string16(), url); + CefRefPtr frame = browser_info_->GetFrameForFrameTreeNode( + navigation_handle->GetFrameTreeNodeId()); + frame->RefreshAttributes(); if (error_code == net::OK) { // The navigation has been committed and there is no error. @@ -2853,17 +2577,17 @@ void CefBrowserHostImpl::DidFinishNavigation( // Don't call OnLoadStart for same page navigations (fragments, // history state). if (!navigation_handle->IsSameDocument()) - OnLoadStart(frame, navigation_handle->GetPageTransition()); + OnLoadStart(frame.get(), navigation_handle->GetPageTransition()); if (is_main_frame) - OnAddressChange(frame, url); + OnAddressChange(url); } else { // The navigation failed with an error. This may happen before commit // (e.g. network error) or after commit (e.g. response filter error). // If the error happened before commit then this call will originate from // RenderFrameHostImpl::OnDidFailProvisionalLoadWithError. // OnLoadStart/OnLoadEnd will not be called. - OnLoadError(frame, navigation_handle->GetURL(), error_code); + OnLoadError(frame.get(), navigation_handle->GetURL(), error_code); } if (web_contents()) { @@ -2876,14 +2600,16 @@ void CefBrowserHostImpl::DidFinishNavigation( } void CefBrowserHostImpl::DidStopLoading() { - // Notify the renderer that loading has stopped. We used to use + // Notify all renderers that loading has stopped. We used to use // RenderFrameObserver::DidStopLoading which was removed in // https://crrev.com/3e37dd0ead. However, that callback wasn't necessarily // accurate because it wasn't called in all of the cases where // RenderFrameImpl sends the FrameHostMsg_DidStopLoading message. This adds // an additional round trip but should provide the same or improved // functionality. - Send(new CefMsg_DidStopLoading(MSG_ROUTING_NONE)); + for (const auto& frame : browser_info_->GetAllFrames()) { + frame->MaybeSendDidStopLoading(); + } } void CefBrowserHostImpl::DocumentAvailableInMainFrame() { @@ -2898,12 +2624,8 @@ void CefBrowserHostImpl::DidFailLoad( const base::string16& error_description) { // The navigation failed after commit. OnLoadStart was called so we also call // OnLoadEnd. - const bool is_main_frame = !render_frame_host->GetParent(); - CefRefPtr frame = - GetOrCreateFrame(render_frame_host->GetRoutingID(), - render_frame_host->GetFrameTreeNodeId(), - CefFrameHostImpl::kUnspecifiedFrameId, is_main_frame, - false, base::string16(), validated_url); + auto frame = browser_info_->GetFrameForHost(render_frame_host); + frame->RefreshAttributes(); OnLoadError(frame, validated_url, error_code); OnLoadEnd(frame, validated_url, error_code); } @@ -2949,30 +2671,19 @@ bool CefBrowserHostImpl::OnMessageReceived(const IPC::Message& message) { if (message.type() == WidgetHostMsg_SetCursor::ID) return IsMouseCursorChangeDisabled(); - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(CefBrowserHostImpl, message) - IPC_MESSAGE_HANDLER(CefHostMsg_FrameIdentified, OnFrameIdentified) - IPC_MESSAGE_HANDLER(CefHostMsg_DidFinishLoad, OnDidFinishLoad) - IPC_MESSAGE_HANDLER(CefHostMsg_UpdateDraggableRegions, - OnUpdateDraggableRegions) - IPC_MESSAGE_HANDLER(CefHostMsg_Request, OnRequest) - IPC_MESSAGE_HANDLER(CefHostMsg_Response, OnResponse) - IPC_MESSAGE_HANDLER(CefHostMsg_ResponseAck, OnResponseAck) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; + return false; } bool CefBrowserHostImpl::OnMessageReceived( const IPC::Message& message, content::RenderFrameHost* render_frame_host) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(CefBrowserHostImpl, message, - render_frame_host) - IPC_MESSAGE_HANDLER(CefHostMsg_FrameFocused, OnFrameFocused) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; + // Messages may arrive after a frame is detached. Ignore those messages. + auto frame = GetFrameForHost(render_frame_host); + if (frame) { + return static_cast(frame.get()) + ->OnMessageReceived(message); + } + return false; } void CefBrowserHostImpl::AccessibilityEventReceived( @@ -3075,130 +2786,6 @@ void CefBrowserHostImpl::set_pending_navigation_action( pending_navigation_action_ = std::move(action); } -// content::WebContentsObserver::OnMessageReceived() message handlers. -// ----------------------------------------------------------------------------- - -void CefBrowserHostImpl::OnFrameIdentified(int64 frame_id, - int64 parent_frame_id, - base::string16 name) { - bool is_main_frame = (parent_frame_id == CefFrameHostImpl::kMainFrameId); - GetOrCreateFrame(frame_id, kUnspecifiedFrameTreeNodeId, parent_frame_id, - is_main_frame, false, name, GURL()); -} - -void CefBrowserHostImpl::OnFrameFocused( - content::RenderFrameHost* render_frame_host) { - const int64 frame_id = render_frame_host->GetRoutingID(); - - CefRefPtr unfocused_frame; - CefRefPtr focused_frame; - - { - base::AutoLock lock_scope(state_lock_); - - if (focused_frame_id_ != CefFrameHostImpl::kInvalidFrameId) { - // Unfocus the previously focused frame. - FrameIdMap::const_iterator it = frames_.find(frame_id); - if (it != frames_.end()) - unfocused_frame = it->second; - } - - // Focus the newly focused frame. - FrameIdMap::iterator it = frames_.find(frame_id); - if (it != frames_.end()) - focused_frame = it->second; - - focused_frame_id_ = - focused_frame.get() ? frame_id : CefFrameHostImpl::kInvalidFrameId; - } - - if (unfocused_frame.get()) - unfocused_frame->SetFocused(false); - if (focused_frame.get()) - focused_frame->SetFocused(true); -} - -void CefBrowserHostImpl::OnDidFinishLoad(int64 frame_id, - const GURL& validated_url, - bool is_main_frame, - int http_status_code) { - CefRefPtr frame = - GetOrCreateFrame(frame_id, kUnspecifiedFrameTreeNodeId, - CefFrameHostImpl::kUnspecifiedFrameId, is_main_frame, - false, base::string16(), validated_url); - - // Give internal scheme handlers an opportunity to update content. - scheme::DidFinishLoad(frame, validated_url); - - OnLoadEnd(frame, validated_url, http_status_code); -} - -void CefBrowserHostImpl::OnUpdateDraggableRegions( - const std::vector& regions) { - std::vector draggable_regions; - draggable_regions.reserve(regions.size()); - - std::vector::const_iterator it = regions.begin(); - for (; it != regions.end(); ++it) { - const gfx::Rect& rect(it->bounds); - const CefRect bounds(rect.x(), rect.y(), rect.width(), rect.height()); - draggable_regions.push_back(CefDraggableRegion(bounds, it->draggable)); - } - - if (client_.get()) { - CefRefPtr handler = client_->GetDragHandler(); - if (handler.get()) { - handler->OnDraggableRegionsChanged(this, draggable_regions); - } - } -} - -void CefBrowserHostImpl::OnRequest(const Cef_Request_Params& params) { - CEF_REQUIRE_UIT(); - - bool success = false; - std::string response; - bool expect_response_ack = false; - - if (params.user_initiated) { - // Give the user a chance to handle the request. - if (client_.get()) { - CefRefPtr message(new CefProcessMessageImpl( - const_cast(¶ms), false, true)); - success = - client_->OnProcessMessageReceived(this, PID_RENDERER, message.get()); - message->Detach(NULL); - } - } else { - // Invalid request. - NOTREACHED(); - } - - if (params.expect_response) { - DCHECK_GE(params.request_id, 0); - - // Send a response to the renderer. - Cef_Response_Params response_params; - response_params.request_id = params.request_id; - response_params.success = success; - response_params.response = response; - response_params.expect_response_ack = expect_response_ack; - Send(new CefMsg_Response(MSG_ROUTING_NONE, response_params)); - } -} - -void CefBrowserHostImpl::OnResponse(const Cef_Response_Params& params) { - CEF_REQUIRE_UIT(); - - response_manager_->RunHandler(params); - if (params.expect_response_ack) - Send(new CefMsg_ResponseAck(MSG_ROUTING_NONE, params.request_id)); -} - -void CefBrowserHostImpl::OnResponseAck(int request_id) { - response_manager_->RunAckHandler(request_id); -} - // content::NotificationObserver methods. // ----------------------------------------------------------------------------- @@ -3244,9 +2831,6 @@ CefBrowserHostImpl::CefBrowserHostImpl( can_go_forward_(false), has_document_(false), is_fullscreen_(false), - queue_messages_(true), - main_frame_id_(CefFrameHostImpl::kInvalidFrameId), - focused_frame_id_(CefFrameHostImpl::kInvalidFrameId), destruction_state_(DESTRUCTION_STATE_NONE), window_destroyed_(false), is_in_onsetfocus_(false), @@ -3261,7 +2845,7 @@ CefBrowserHostImpl::CefBrowserHostImpl( } DCHECK(!browser_info_->browser().get()); - browser_info_->set_browser(this); + browser_info_->SetBrowser(this); web_contents->SetDelegate(this); @@ -3279,8 +2863,6 @@ CefBrowserHostImpl::CefBrowserHostImpl( content::Source( &web_contents->GetController())); - response_manager_.reset(new CefResponseManager); - PrefsTabHelper::CreateForWebContents(web_contents); printing::CefPrintViewManager::CreateForWebContents(web_contents); @@ -3373,188 +2955,6 @@ void CefBrowserHostImpl::OnExtensionHostDeleted() { extension_host_ = nullptr; } -CefRefPtr CefBrowserHostImpl::GetOrCreateFrame( - int64 frame_id, - int frame_tree_node_id, - int64 parent_frame_id, - bool is_main_frame, - bool is_main_frame_state_flaky, - base::string16 frame_name, - const GURL& frame_url) { - // We need either a valid |frame_id| or a valid |frame_tree_node_id|. - DCHECK(frame_id >= 0 || frame_tree_node_id >= kUnusedFrameTreeNodeId); - - CefString url; - if (frame_url.is_valid()) - url = frame_url.spec(); - - CefString name; - if (!frame_name.empty()) - name = frame_name; - - CefRefPtr frame; - bool frame_created = false; - - base::AutoLock lock_scope(state_lock_); - - if (frame_id < 0) { - // With PlzNavigate the renderer process representation might not exist yet. - if ((is_main_frame || is_main_frame_state_flaky) && - main_frame_id_ != CefFrameHostImpl::kInvalidFrameId) { - // Operating in the main frame. Continue using the existing main frame - // object until the new renderer process representation is created. - frame_id = main_frame_id_; - } else { - if (is_main_frame || is_main_frame_state_flaky) { - // Always use the same pending object for the main frame. - frame_tree_node_id = kMainFrameTreeNodeId; - } - - // Operating in a sub-frame, or the main frame hasn't yet navigated for - // the first time. Use a pending object keyed on |frame_tree_node_id|. - frame = GetOrCreatePendingFrame(frame_tree_node_id, parent_frame_id, - &frame_created); - } - } - - if (!frame) { - // Delete the pending object, if any. - { - FrameTreeNodeIdMap::iterator it = - pending_frames_.find(frame_tree_node_id); - if (it != pending_frames_.end()) { - DCHECK_EQ(is_main_frame, it->second->IsMain()); - - // Persist URL and name to the new frame. - if (url.empty()) - url = it->second->GetURL(); - if (name.empty()) - name = it->second->GetName(); - - pending_frames_.erase(it); - } - } - - // Update the main frame object if the ID has changed. - if (is_main_frame && main_frame_id_ != frame_id) { - if (main_frame_id_ != CefFrameHostImpl::kInvalidFrameId) { - // Remove the old main frame object before adding the new one. - FrameIdMap::iterator it = frames_.find(main_frame_id_); - if (it != frames_.end()) { - // Persist URL and name to the new main frame. - if (url.empty()) - url = it->second->GetURL(); - if (name.empty()) - name = it->second->GetName(); - - it->second->Detach(); - frames_.erase(it); - } - - if (focused_frame_id_ == main_frame_id_) - focused_frame_id_ = frame_id; - } - - main_frame_id_ = frame_id; - } - - // Check if a frame object already exists for the ID. If so, re-use it. - { - FrameIdMap::const_iterator it = frames_.find(frame_id); - if (it != frames_.end()) - frame = it->second; - } - - if (!frame) { - frame = new CefFrameHostImpl(this, frame_id, is_main_frame, url, name, - parent_frame_id); - frame_created = true; - frames_.insert(std::make_pair(frame_id, frame)); - } - } - - if (!frame_created && !is_main_frame_state_flaky) - frame->SetAttributes(is_main_frame, url, name, parent_frame_id); - -#if DCHECK_IS_ON() - // The main frame should always be correctly attributed. - DCHECK(main_frame_id_ == CefFrameHostImpl::kInvalidFrameId || - main_frame_id_ >= 0) - << main_frame_id_; - if (main_frame_id_ == CefFrameHostImpl::kInvalidFrameId) { - // With PlzNavigate the renderer process representation might not exist yet. - DCHECK(frame_id == CefFrameHostImpl::kMainFrameId || - frame_id == CefFrameHostImpl::kUnspecifiedFrameId) - << frame_id; - DCHECK(frame->IsMain()); - } else if (main_frame_id_ == frame_id) { - DCHECK(frame->IsMain()); - } else { - DCHECK(!frame->IsMain()); - } -#endif - - return frame.get(); -} - -CefRefPtr CefBrowserHostImpl::GetOrCreatePendingFrame( - int frame_tree_node_id, - int64 parent_frame_id, - bool* created) { - const bool is_main_frame = (frame_tree_node_id == kMainFrameTreeNodeId); - DCHECK(is_main_frame || frame_tree_node_id >= 0); - - state_lock_.AssertAcquired(); - - FrameTreeNodeIdMap::const_iterator it = - pending_frames_.find(frame_tree_node_id); - if (it != pending_frames_.end()) { - DCHECK_EQ(is_main_frame, it->second->IsMain()); - return it->second; - } - - CefRefPtr frame = new CefFrameHostImpl( - this, CefFrameHostImpl::kInvalidFrameId, is_main_frame, CefString(), - CefString(), parent_frame_id); - pending_frames_.insert(std::make_pair(frame_tree_node_id, frame)); - if (created) - *created = true; - - return frame; -} - -void CefBrowserHostImpl::DetachAllFrames() { - FrameIdMap frames; - FrameTreeNodeIdMap pending_frames; - - { - base::AutoLock lock_scope(state_lock_); - - frames = frames_; - frames_.clear(); - - pending_frames = pending_frames_; - pending_frames_.clear(); - - if (main_frame_id_ != CefFrameHostImpl::kInvalidFrameId) - main_frame_id_ = CefFrameHostImpl::kInvalidFrameId; - if (focused_frame_id_ != CefFrameHostImpl::kInvalidFrameId) - focused_frame_id_ = CefFrameHostImpl::kInvalidFrameId; - } - - { - FrameIdMap::const_iterator it = frames.begin(); - for (; it != frames.end(); ++it) - it->second->Detach(); - } - - { - FrameTreeNodeIdMap::const_iterator it = pending_frames.begin(); - for (; it != pending_frames.end(); ++it) - it->second->Detach(); - } -} - gfx::Point CefBrowserHostImpl::GetScreenPoint(const gfx::Point& view) const { CEF_REQUIRE_UIT(); if (platform_delegate_) @@ -3580,8 +2980,7 @@ void CefBrowserHostImpl::UpdateDragCursor(blink::WebDragOperation operation) { platform_delegate_->UpdateDragCursor(operation); } -void CefBrowserHostImpl::OnAddressChange(CefRefPtr frame, - const GURL& url) { +void CefBrowserHostImpl::OnAddressChange(const GURL& url) { if (client_.get()) { CefRefPtr handler = client_->GetDisplayHandler(); if (handler.get()) { @@ -3677,29 +3076,6 @@ void CefBrowserHostImpl::ConfigureAutoResize() { } } -bool CefBrowserHostImpl::Send(IPC::Message* message) { - if (!CEF_CURRENTLY_ON_UIT()) { - CEF_POST_TASK(CEF_UIT, - base::BindOnce(base::IgnoreResult(&CefBrowserHostImpl::Send), - this, message)); - return true; - } - - if (queue_messages_) { - queued_messages_.push(message); - return true; - } else if (web_contents()) { - content::RenderViewHost* rvh = web_contents()->GetRenderViewHost(); - if (rvh) { - message->set_routing_id(rvh->GetRoutingID()); - return rvh->Send(message); - } - } - - delete message; - return false; -} - void CefBrowserHostImpl::SendTouchEvent(const CefTouchEvent& event) { if (!IsWindowless()) { NOTREACHED() << "Window rendering is not disabled"; diff --git a/libcef/browser/browser_host_impl.h b/libcef/browser/browser_host_impl.h index 47d40f8d4..72284f1ef 100644 --- a/libcef/browser/browser_host_impl.h +++ b/libcef/browser/browser_host_impl.h @@ -8,7 +8,6 @@ #pragma once #include -#include #include #include @@ -23,7 +22,6 @@ #include "libcef/browser/javascript_dialog_manager.h" #include "libcef/browser/menu_manager.h" #include "libcef/browser/request_context_impl.h" -#include "libcef/common/response_manager.h" #include "base/observer_list.h" #include "base/strings/string16.h" @@ -45,24 +43,16 @@ class Extension; class ExtensionHost; } // namespace extensions -namespace net { -class URLRequest; -} - #if defined(USE_AURA) namespace views { class Widget; } #endif // defined(USE_AURA) -struct Cef_DraggableRegion_Params; -struct Cef_Request_Params; -struct Cef_Response_Params; class CefAudioMirrorDestination; class CefBrowserInfo; class CefBrowserPlatformDelegate; class CefDevToolsFrontend; -struct CefNavigateParams; class SiteInstance; // Implementation of CefBrowser. @@ -155,14 +145,11 @@ class CefBrowserHostImpl : public CefBrowserHost, // Returns the browser associated with the specified WebContents. static CefRefPtr GetBrowserForContents( const content::WebContents* contents); - // Returns the browser associated with the specified URLRequest. - static CefRefPtr GetBrowserForRequest( - const net::URLRequest* request); - // Returns the browser associated with the specified FrameTreeNode. + // Returns the browser associated with the specified FrameTreeNode ID. static CefRefPtr GetBrowserForFrameTreeNode( int frame_tree_node_id); // Returns the browser associated with the specified frame routing IDs. - static CefRefPtr GetBrowserForFrame( + static CefRefPtr GetBrowserForFrameRoute( int render_process_id, int render_routing_id); @@ -282,8 +269,6 @@ class CefBrowserHostImpl : public CefBrowserHost, size_t GetFrameCount() override; void GetFrameIdentifiers(std::vector& identifiers) override; void GetFrameNames(std::vector& names) override; - bool SendProcessMessage(CefProcessId target_process, - CefRefPtr message) override; // Returns true if windowless rendering is enabled. bool IsWindowless() const; @@ -314,42 +299,17 @@ class CefBrowserHostImpl : public CefBrowserHost, // Returns the frame associated with the specified RenderFrameHost. CefRefPtr GetFrameForHost(const content::RenderFrameHost* host); - // Returns the frame associated with the specified RenderFrameHost routing ID. - CefRefPtr GetFrameForHostRoutingId(int render_frame_id); + // Load the specified URL in the main frame. + void LoadMainFrameURL(const std::string& url, + const content::Referrer& referrer, + ui::PageTransition transition, + const std::string& extra_headers); - // Returns the frame associated with the specified URLRequest. - CefRefPtr GetFrameForRequest(const net::URLRequest* request); - - // Navigate as specified by the |params| argument. - void Navigate(const CefNavigateParams& params); - - // Load the specified request. - void LoadRequest(int64 frame_id, CefRefPtr request); - - // Load the specified URL. - void LoadURL(int64 frame_id, - const std::string& url, - const content::Referrer& referrer, - ui::PageTransition transition, - const std::string& extra_headers); - - // Load the specified string. - void LoadString(int64 frame_id, - const std::string& string, - const std::string& url); - - // Send a command to the renderer for execution. - void SendCommand(int64 frame_id, - const std::string& command, - CefRefPtr responseHandler); - - // Send code to the renderer for execution. - void SendCode(int64 frame_id, - bool is_javascript, - const std::string& code, - const std::string& script_url, - int script_start_line, - CefRefPtr responseHandler); + // Called from CefFrameHostImpl. + void OnFrameFocused(CefRefPtr frame); + void OnDidFinishLoad(CefRefPtr frame, + const GURL& validated_url, + int http_status_code); // Open the specified text in the default text editor. void ViewText(const std::string& text); @@ -500,7 +460,7 @@ class CefBrowserHostImpl : public CefBrowserHost, void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override; void RenderFrameHostChanged(content::RenderFrameHost* old_host, content::RenderFrameHost* new_host) override; - void FrameDeleted(content::RenderFrameHost* render_frame_host) override; + void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; void RenderViewCreated(content::RenderViewHost* render_view_host) override; void RenderViewDeleted(content::RenderViewHost* render_view_host) override; void RenderViewReady() override; @@ -568,21 +528,6 @@ class CefBrowserHostImpl : public CefBrowserHost, std::unique_ptr platform_delegate, CefRefPtr extension); - // content::WebContentsObserver::OnMessageReceived() message handlers. - void OnFrameIdentified(int64 frame_id, - int64 parent_frame_id, - base::string16 name); - void OnFrameFocused(content::RenderFrameHost* render_frame_host); - void OnDidFinishLoad(int64 frame_id, - const GURL& validated_url, - bool is_main_frame, - int http_status_code); - void OnUpdateDraggableRegions( - const std::vector& regions); - void OnRequest(const Cef_Request_Params& params); - void OnResponse(const Cef_Response_Params& params); - void OnResponseAck(int request_id); - // content::NotificationObserver methods. void Observe(int type, const content::NotificationSource& source, @@ -617,42 +562,7 @@ class CefBrowserHostImpl : public CefBrowserHost, // Action to be executed once the navigation lock is released. void set_pending_navigation_action(base::OnceClosure action); - // Update or create a frame object. |frame_id| (renderer routing id) will be - // >= 0 if the frame currently exists in the renderer process. |frame_id| will - // be < 0 for the main frame if it has not yet navigated for the first time, - // or for sub-frames if PlzNavigate is enabled and the sub-frame does not yet - // have a renderer process representation. |frame_tree_node_id| will be - // kUnspecifiedFrameTreeNodeId for calls that originate from the renderer - // process (meaning that |frame_id| should be >= 0); kUnusedFrameTreeNodeId - // if PlzNavigate is disabled; or >= 0 otherwise. |parent_frame_id| will be - // CefFrameHostImpl::kUnspecifiedFrameId if unknown. In cases where |frame_id| - // is < 0 either the existing main frame object or a pending object will be - // returned depending on current state. If |is_main_frame_state_flaky| is true - // then the value of |is_main_frame| cannot be relied on. - CefRefPtr GetOrCreateFrame(int64 frame_id, - int frame_tree_node_id, - int64 parent_frame_id, - bool is_main_frame, - bool is_main_frame_state_flaky, - base::string16 frame_name, - const GURL& frame_url); - - // Returns a pending frame object. If the main frame has not yet navigated for - // the first time then |frame_tree_node_id| will be kMainFrameTreeNodeId and a - // single pending object will be returned. Otherwise, this method will be - // called with a |frame_tree_node_id| value >= 0 when PlzNavigate is enabled - // and there will then be one pending object for each frame that does not yet - // have a renderer process representation. |parent_frame_id| will be - // CefFrameHostImpl::kUnspecifiedFrameId if unknown. |created| will be set to - // true if |created| is non-nullptr and the frame object was created. - CefRefPtr GetOrCreatePendingFrame(int frame_tree_node_id, - int64 parent_frame_id, - bool* created); - - // Remove the references to all frames and mark them as detached. - void DetachAllFrames(); - - void OnAddressChange(CefRefPtr frame, const GURL& url); + void OnAddressChange(const GURL& url); void OnLoadStart(CefRefPtr frame, ui::PageTransition transition_type); void OnLoadError(CefRefPtr frame, const GURL& url, int error_code); @@ -669,11 +579,6 @@ class CefBrowserHostImpl : public CefBrowserHost, void ConfigureAutoResize(); - // Send a message to the RenderViewHost associated with this browser. - // TODO(cef): With the introduction of OOPIFs, WebContents can span multiple - // processes. Messages should be sent to specific RenderFrameHosts instead. - bool Send(IPC::Message* message); - CefBrowserSettings settings_; CefRefPtr client_; scoped_refptr browser_info_; @@ -698,26 +603,8 @@ class CefBrowserHostImpl : public CefBrowserHost, bool has_document_; bool is_fullscreen_; - // Messages we queue while waiting for the RenderView to be ready. We queue - // them here instead of in the RenderProcessHost to ensure that they're sent - // after the CefRenderViewObserver has been created on the renderer side. - std::queue queued_messages_; - bool queue_messages_; - - // Map of frame tree node id to CefFrameHostImpl. These are frames that do not - // yet have a renderer process representation. - typedef std::map> FrameTreeNodeIdMap; - FrameTreeNodeIdMap pending_frames_; - - // Map of unique frame id (renderer routing id) to CefFrameHostImpl. These are - // frames that do have a renderer process representation. - typedef std::map> FrameIdMap; - FrameIdMap frames_; - - // The unique frame id currently identified as the main frame. - int64 main_frame_id_; - // The unique frame id currently identified as the focused frame. - int64 focused_frame_id_; + // The currently focused frame, or nullptr if the main frame is focused. + CefRefPtr focused_frame_; // Represents the current browser destruction state. Only accessed on the UI // thread. @@ -747,9 +634,6 @@ class CefBrowserHostImpl : public CefBrowserHost, // Used for managing notification subscriptions. std::unique_ptr registrar_; - // Manages response registrations. - std::unique_ptr response_manager_; - // Used for creating and managing file dialogs. std::unique_ptr file_dialog_manager_; diff --git a/libcef/browser/browser_info.cc b/libcef/browser/browser_info.cc index 1326228af..790cc2f27 100644 --- a/libcef/browser/browser_info.cc +++ b/libcef/browser/browser_info.cc @@ -8,142 +8,351 @@ #include "libcef/browser/thread_util.h" #include "libcef/common/values_impl.h" +#include "base/logging.h" +#include "content/browser/frame_host/frame_tree_node.h" +#include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/public/browser/render_process_host.h" #include "ipc/ipc_message.h" -// CefBrowserInfo::RenderIDManager - -CefBrowserInfo::RenderIDManager::RenderIDManager(base::Lock* lock) - : lock_(lock) { - DCHECK(lock); -} - -void CefBrowserInfo::RenderIDManager::add_render_frame_id( - int render_process_id, - int render_routing_id) { - DCHECK_GT(render_process_id, 0); - DCHECK_GT(render_routing_id, 0); - - base::AutoLock lock_scope(*lock_); - - if (!render_frame_id_set_.empty()) { - RenderIdSet::const_iterator it = render_frame_id_set_.find( - std::make_pair(render_process_id, render_routing_id)); - DCHECK(it == render_frame_id_set_.end()); - if (it != render_frame_id_set_.end()) - return; +CefBrowserInfo::FrameInfo::~FrameInfo() { + if (frame_ && !is_main_frame_) { + // Disassociate sub-frames from the browser. + frame_->Detach(); } - - render_frame_id_set_.insert( - std::make_pair(render_process_id, render_routing_id)); } -void CefBrowserInfo::RenderIDManager::remove_render_frame_id( - int render_process_id, - int render_routing_id) { - DCHECK_GT(render_process_id, 0); - DCHECK_GT(render_routing_id, 0); - - base::AutoLock lock_scope(*lock_); - - DCHECK(!render_frame_id_set_.empty()); - if (render_frame_id_set_.empty()) - return; - - bool erased = render_frame_id_set_.erase( - std::make_pair(render_process_id, render_routing_id)) != 0; - DCHECK(erased); -} - -bool CefBrowserInfo::RenderIDManager::is_render_frame_id_match( - int render_process_id, - int render_routing_id) const { - base::AutoLock lock_scope(*lock_); - - if (render_frame_id_set_.empty()) - return false; - - RenderIdSet::const_iterator it = render_frame_id_set_.find( - std::make_pair(render_process_id, render_routing_id)); - return (it != render_frame_id_set_.end()); -} - -// CefBrowserInfo::FrameTreeNodeIDManager - -CefBrowserInfo::FrameTreeNodeIDManager::FrameTreeNodeIDManager(base::Lock* lock) - : lock_(lock) { - DCHECK(lock); -} - -void CefBrowserInfo::FrameTreeNodeIDManager::add_frame_tree_node_id( - int frame_tree_node_id) { - DCHECK_GE(frame_tree_node_id, 0); - - base::AutoLock lock_scope(*lock_); - - if (!frame_tree_node_id_set_.empty()) { - FrameTreeNodeIdSet::const_iterator it = - frame_tree_node_id_set_.find(frame_tree_node_id); - DCHECK(it == frame_tree_node_id_set_.end()); - if (it != frame_tree_node_id_set_.end()) - return; - } - - frame_tree_node_id_set_.insert(frame_tree_node_id); -} - -void CefBrowserInfo::FrameTreeNodeIDManager::remove_frame_tree_node_id( - int frame_tree_node_id) { - DCHECK_GE(frame_tree_node_id, 0); - - base::AutoLock lock_scope(*lock_); - - DCHECK(!frame_tree_node_id_set_.empty()); - if (frame_tree_node_id_set_.empty()) - return; - - bool erased = frame_tree_node_id_set_.erase(frame_tree_node_id) != 0; - DCHECK(erased); -} - -bool CefBrowserInfo::FrameTreeNodeIDManager::is_frame_tree_node_id_match( - int frame_tree_node_id) const { - base::AutoLock lock_scope(*lock_); - - if (frame_tree_node_id_set_.empty()) - return false; - - FrameTreeNodeIdSet::const_iterator it = - frame_tree_node_id_set_.find(frame_tree_node_id); - return (it != frame_tree_node_id_set_.end()); -} - -// CefBrowserInfo - CefBrowserInfo::CefBrowserInfo(int browser_id, bool is_popup, + bool is_windowless, CefRefPtr extra_info) : browser_id_(browser_id), is_popup_(is_popup), - is_windowless_(false), - render_id_manager_(&lock_), - guest_render_id_manager_(&lock_), - frame_tree_node_id_manager_(&lock_), + is_windowless_(is_windowless), extra_info_(extra_info) { DCHECK_GT(browser_id, 0); } CefBrowserInfo::~CefBrowserInfo() {} -void CefBrowserInfo::set_windowless(bool windowless) { - is_windowless_ = windowless; -} - CefRefPtr CefBrowserInfo::browser() const { base::AutoLock lock_scope(lock_); return browser_; } -void CefBrowserInfo::set_browser(CefRefPtr browser) { +void CefBrowserInfo::SetBrowser(CefRefPtr browser) { base::AutoLock lock_scope(lock_); browser_ = browser; + + if (!browser) { + RemoveAllFrames(); + } +} + +void CefBrowserInfo::MaybeCreateFrame(content::RenderFrameHost* host, + bool is_guest_view) { + CEF_REQUIRE_UIT(); + + const auto frame_id = CefFrameHostImpl::MakeFrameId(host); + const int frame_tree_node_id = host->GetFrameTreeNodeId(); + const bool is_main_frame = (host->GetParent() == nullptr); + + // A speculative RFH will be created in response to a browser-initiated + // cross-origin navigation (e.g. via LoadURL) and eventually either discarded + // or swapped in based on whether the navigation is committed. We'll create a + // frame object for the speculative RFH so that it can be found by + // frame/routing ID. However, we won't replace the main frame with a + // speculative RFH until after it's swapped in, and we'll generally prefer to + // return a non-speculative RFH for the same node ID if one exists. + const bool is_speculative = (static_cast(host) + ->frame_tree_node() + ->render_manager() + ->current_frame_host() != host); + + base::AutoLock lock_scope(lock_); + DCHECK(browser_); + + const auto it = frame_id_map_.find(frame_id); + if (it != frame_id_map_.end()) { + auto info = it->second; + +#if DCHECK_IS_ON() + // Check that the frame info hasn't changed unexpectedly. + DCHECK_EQ(info->frame_id_, frame_id); + DCHECK_EQ(info->frame_tree_node_id_, frame_tree_node_id); + DCHECK_EQ(info->is_guest_view_, is_guest_view); + DCHECK_EQ(info->is_main_frame_, is_main_frame); +#endif + + if (!info->is_guest_view_ && info->is_speculative_ && !is_speculative) { + // Upgrade the frame info from speculative to non-speculative. + if (info->is_main_frame_) { + if (main_frame_) { + // Update the existing main frame object. + main_frame_->SetRenderFrameHost(host); + info->frame_ = main_frame_; + } else { + // Set the main frame object. + main_frame_ = info->frame_; + } + } + info->is_speculative_ = false; + MaybeUpdateFrameTreeNodeIdMap(info); + } + return; + } + + auto frame_info = new FrameInfo; + frame_info->host_ = host; + frame_info->frame_id_ = frame_id; + frame_info->frame_tree_node_id_ = frame_tree_node_id; + frame_info->is_guest_view_ = is_guest_view; + frame_info->is_main_frame_ = is_main_frame; + frame_info->is_speculative_ = is_speculative; + + // Guest views don't get their own CefBrowser or CefFrame objects. + if (!is_guest_view) { + if (is_main_frame && main_frame_ && !is_speculative) { + // Update the existing main frame object. + main_frame_->SetRenderFrameHost(host); + frame_info->frame_ = main_frame_; + } else { + // Create a new frame object. + frame_info->frame_ = new CefFrameHostImpl(this, host); + if (is_main_frame && !is_speculative) { + main_frame_ = frame_info->frame_; + } + } +#if DCHECK_IS_ON() + // Check that the frame info hasn't changed unexpectedly. + DCHECK_EQ(frame_id, frame_info->frame_->GetIdentifier()); + DCHECK_EQ(frame_info->is_main_frame_, frame_info->frame_->IsMain()); +#endif + } + + browser_->request_context()->OnRenderFrameCreated( + host->GetProcess()->GetID(), host->GetRoutingID(), frame_tree_node_id, + is_main_frame, is_guest_view); + + // Populate the lookup maps. + frame_id_map_.insert(std::make_pair(frame_id, frame_info)); + MaybeUpdateFrameTreeNodeIdMap(frame_info); + + // And finally set the ownership. + frame_info_set_.insert(base::WrapUnique(frame_info)); +} + +void CefBrowserInfo::RemoveFrame(content::RenderFrameHost* host) { + CEF_REQUIRE_UIT(); + + base::AutoLock lock_scope(lock_); + + const auto frame_id = CefFrameHostImpl::MakeFrameId(host); + + auto it = frame_id_map_.find(frame_id); + DCHECK(it != frame_id_map_.end()); + + auto frame_info = it->second; + + browser_->request_context()->OnRenderFrameDeleted( + host->GetProcess()->GetID(), host->GetRoutingID(), + frame_info->frame_tree_node_id_, frame_info->is_main_frame_, + frame_info->is_guest_view_); + + // Remove from the lookup maps. + frame_id_map_.erase(it); + + // A new RFH with the same node ID may be added before the old RFH is deleted, + // or this might be a speculative RFH. Therefore only delete the map entry if + // it's currently pointing to the to-be-deleted frame info object. + if (frame_tree_node_id_map_.find(frame_info->frame_tree_node_id_)->second == + frame_info) { + frame_tree_node_id_map_.erase(frame_info->frame_tree_node_id_); + } + + // And finally delete the frame info. + auto it2 = frame_info_set_.find(frame_info); + frame_info_set_.erase(it2); +} + +CefRefPtr CefBrowserInfo::GetMainFrame() { + base::AutoLock lock_scope(lock_); + DCHECK(browser_); + if (!main_frame_) { + // Create a temporary object that will eventually be updated with real + // routing information. + main_frame_ = + new CefFrameHostImpl(this, true, CefFrameHostImpl::kInvalidFrameId); + } + return main_frame_; +} + +CefRefPtr CefBrowserInfo::CreateTempSubFrame( + int64_t parent_frame_id) { + CefRefPtr parent = GetFrameForId(parent_frame_id); + if (!parent) + parent = GetMainFrame(); + return new CefFrameHostImpl(this, false, parent->GetIdentifier()); +} + +CefRefPtr CefBrowserInfo::GetFrameForHost( + const content::RenderFrameHost* host, + bool* is_guest_view) const { + if (is_guest_view) + *is_guest_view = false; + + if (!host) + return nullptr; + + return GetFrameForId(CefFrameHostImpl::MakeFrameId(host), is_guest_view); +} + +CefRefPtr CefBrowserInfo::GetFrameForRoute( + int32_t render_process_id, + int32_t render_routing_id, + bool* is_guest_view) const { + if (is_guest_view) + *is_guest_view = false; + + if (render_process_id < 0 || render_routing_id < 0) + return nullptr; + + return GetFrameForId( + CefFrameHostImpl::MakeFrameId(render_process_id, render_routing_id), + is_guest_view); +} + +CefRefPtr CefBrowserInfo::GetFrameForId( + int64_t frame_id, + bool* is_guest_view) const { + if (is_guest_view) + *is_guest_view = false; + + if (frame_id < 0) + return nullptr; + + base::AutoLock lock_scope(lock_); + + const auto it = frame_id_map_.find(frame_id); + if (it != frame_id_map_.end()) { + const auto info = it->second; + + if (info->is_guest_view_) { + if (is_guest_view) + *is_guest_view = true; + return nullptr; + } + + if (info->is_speculative_) { + if (info->is_main_frame_ && main_frame_) { + // Always prefer the non-speculative main frame. + return main_frame_; + } else { + // Always prefer an existing non-speculative frame for the same node ID. + bool is_guest_view_tmp; + auto frame = GetFrameForFrameTreeNodeInternal(info->frame_tree_node_id_, + &is_guest_view_tmp); + if (is_guest_view_tmp) { + if (is_guest_view) + *is_guest_view = true; + return nullptr; + } + if (frame) + return frame; + } + + LOG(WARNING) << "Returning a speculative frame for frame id " << frame_id; + } + + DCHECK(info->frame_); + return info->frame_; + } + + return nullptr; +} + +CefRefPtr CefBrowserInfo::GetFrameForFrameTreeNode( + int frame_tree_node_id, + bool* is_guest_view) const { + if (is_guest_view) + *is_guest_view = false; + + if (frame_tree_node_id < 0) + return nullptr; + + base::AutoLock lock_scope(lock_); + return GetFrameForFrameTreeNodeInternal(frame_tree_node_id, is_guest_view); +} + +CefBrowserInfo::FrameHostList CefBrowserInfo::GetAllFrames() const { + base::AutoLock lock_scope(lock_); + FrameHostList frames; + for (const auto& info : frame_info_set_) { + if (info->frame_ && !info->is_speculative_) + frames.insert(info->frame_); + } + return frames; +} + +void CefBrowserInfo::MaybeUpdateFrameTreeNodeIdMap(FrameInfo* info) { + lock_.AssertAcquired(); + + auto it = frame_tree_node_id_map_.find(info->frame_tree_node_id_); + const bool has_entry = (it != frame_tree_node_id_map_.end()); + + if (has_entry && it->second == info) { + // Already mapping to |info|. + return; + } + + // Don't replace an existing node ID entry with a speculative RFH, but do + // add an entry if one doesn't already exist. + if (!info->is_speculative_ || !has_entry) { + // A new RFH with the same node ID may be added before the old RFH is + // deleted. To avoid duplicate entries in the map remove the old entry, if + // any, before adding the new entry. + if (has_entry) + frame_tree_node_id_map_.erase(it); + + frame_tree_node_id_map_.insert( + std::make_pair(info->frame_tree_node_id_, info)); + } +} + +CefRefPtr CefBrowserInfo::GetFrameForFrameTreeNodeInternal( + int frame_tree_node_id, + bool* is_guest_view) const { + if (is_guest_view) + *is_guest_view = false; + + lock_.AssertAcquired(); + + const auto it = frame_tree_node_id_map_.find(frame_tree_node_id); + if (it != frame_tree_node_id_map_.end()) { + const auto info = it->second; + + LOG_IF(WARNING, info->is_speculative_) + << "Returning a speculative frame for node id " << frame_tree_node_id; + + if (info->is_guest_view_) { + if (is_guest_view) + *is_guest_view = true; + return nullptr; + } + + DCHECK(info->frame_); + return info->frame_; + } + + return nullptr; +} + +void CefBrowserInfo::RemoveAllFrames() { + lock_.AssertAcquired(); + + // Clear the lookup maps. + frame_id_map_.clear(); + frame_tree_node_id_map_.clear(); + + // And finally delete the frame info. + frame_info_set_.clear(); } diff --git a/libcef/browser/browser_info.h b/libcef/browser/browser_info.h index ae27aaa03..c48328ff7 100644 --- a/libcef/browser/browser_info.h +++ b/libcef/browser/browser_info.h @@ -7,135 +7,171 @@ #pragma once #include +#include #include "include/internal/cef_ptr.h" #include "libcef/common/values_impl.h" +#include "base/containers/unique_ptr_adapters.h" #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" #include "base/values.h" +namespace content { +class RenderFrameHost; +} + class CefBrowserHostImpl; +class CefFrameHostImpl; // CefBrowserInfo is used to associate a browser ID and render view/process // IDs with a particular CefBrowserHostImpl. Render view/process IDs may change // during the lifetime of a single CefBrowserHostImpl. // -// CefBrowserInfo objects are managed by CefContentBrowserClient and should not -// be created directly. +// CefBrowserInfo objects are managed by CefBrowserInfoManager and should not be +// created directly. class CefBrowserInfo : public base::RefCountedThreadSafe { public: - class RenderIDManager { - public: - explicit RenderIDManager(base::Lock* lock); - - // Adds an ID pair if it doesn't already exist. - void add_render_frame_id(int render_process_id, int render_routing_id); - - // Remove an ID pair if it exists. - void remove_render_frame_id(int render_process_id, int render_routing_id); - - // Returns true if this browser matches the specified ID pair. - bool is_render_frame_id_match(int render_process_id, - int render_routing_id) const; - - private: - typedef std::set> RenderIdSet; - - // Access to |render_frame_id_set_| must be protected by |lock_|. - mutable base::Lock* lock_; - - // Set of mapped (process_id, routing_id) pairs. Keeping this set is - // necessary for the following reasons: - // 1. When navigating cross-origin the new (pending) RenderFrameHost will be - // created before the old (current) RenderFrameHost is destroyed. - // 2. When canceling and asynchronously continuing navigation of the same - // URL a new RenderFrameHost may be created for the first (canceled) - // navigation and then destroyed as a result of the second (allowed) - // navigation. - // 3. Out-of-process iframes have their own render IDs which must also be - // associated with the host browser. - RenderIdSet render_frame_id_set_; - }; - - class FrameTreeNodeIDManager { - public: - explicit FrameTreeNodeIDManager(base::Lock* lock); - - // Adds an ID if it doesn't already exist. - void add_frame_tree_node_id(int frame_tree_node_id); - - // Remove an ID if it exists. - void remove_frame_tree_node_id(int frame_tree_node_id); - - // Returns true if this browser matches the specified ID. - bool is_frame_tree_node_id_match(int frame_tree_node_id) const; - - private: - typedef std::set FrameTreeNodeIdSet; - - // Access to |request_id_set_| must be protected by |lock_|. - mutable base::Lock* lock_; - - // Set of mapped frame_tree_node_id values. Keeping this set is necessary - // because, when navigating the main frame, a new (pre-commit) URLRequest - // will be created before the RenderFrameHost. Consequently we can't rely - // on ResourceRequestInfo::GetRenderFrameForRequest returning a valid frame - // ID. See https://crbug.com/776884 for background. - FrameTreeNodeIdSet frame_tree_node_id_set_; - }; - CefBrowserInfo(int browser_id, bool is_popup, + bool is_windowless, CefRefPtr extra_info); int browser_id() const { return browser_id_; } bool is_popup() const { return is_popup_; } bool is_windowless() const { return is_windowless_; } - CefRefPtr extra_info() const { return extra_info_; } - void set_windowless(bool windowless); - - // Returns the render ID manager for this browser. - RenderIDManager* render_id_manager() { return &render_id_manager_; } - - // Returns the render ID manager for guest views owned by this browser. - RenderIDManager* guest_render_id_manager() { - return &guest_render_id_manager_; - } - - // Returns the frame tree node ID manager for this browser. - FrameTreeNodeIDManager* frame_tree_node_id_manager() { - return &frame_tree_node_id_manager_; - } - + // May return NULL if the browser has not yet been created or if the browser + // has been destroyed. CefRefPtr browser() const; - void set_browser(CefRefPtr browser); + + // Set or clear the browser. Called from the CefBrowserHostImpl constructor + // (to set) and DestroyBrowser (to clear). + void SetBrowser(CefRefPtr browser); + + // Ensure that a frame record exists for |host|. Called for the main frame + // when the RenderView is created, or for a sub-frame when the associated + // RenderFrame is created in the renderer process. + // Called from CefBrowserHostImpl::RenderFrameCreated (is_guest_view = false) + // or CefMimeHandlerViewGuestDelegate::OnGuestAttached (is_guest_view = true). + void MaybeCreateFrame(content::RenderFrameHost* host, bool is_guest_view); + + // Remove the frame record for |host|. Called for the main frame when the + // RenderView is destroyed, or for a sub-frame when the associated RenderFrame + // is destroyed in the renderer process. + // Called from CefBrowserHostImpl::FrameDeleted or + // CefMimeHandlerViewGuestDelegate::OnGuestDetached. + void RemoveFrame(content::RenderFrameHost* host); + + // Returns the main frame object. This object will remain valid until the + // browser is destroyed even though the indentifier may change with cross- + // origin navigations. Furthermore, calling LoadURL on this object will always + // behave as expected because the call is routed through the browser's + // NavigationController. + CefRefPtr GetMainFrame(); + + // Creates a temporary sub-frame object for situations during navigation or + // resource loading where a RFH does not yet exist. If |parent_frame_id| + // is invalid the current main frame will be specified as the parent. + // Temporary frame objects are not tracked but will be implicitly detached + // on browser destruction. + CefRefPtr CreateTempSubFrame(int64_t parent_frame_id); + + // Returns the frame object matching the specified host or nullptr if no match + // is found. Nullptr will also be returned if a guest view match is found + // because we don't create frame objects for guest views. If |is_guest_view| + // is non-nullptr it will be set to true in this case. Must be called on the + // UI thread. + CefRefPtr GetFrameForHost( + const content::RenderFrameHost* host, + bool* is_guest_view = nullptr) const; + + // Returns the frame object matching the specified IDs or nullptr if no match + // is found. Nullptr will also be returned if a guest view match is found + // because we don't create frame objects for guest views. If |is_guest_view| + // is non-nullptr it will be set to true in this case. Safe to call from any + // thread. + CefRefPtr GetFrameForRoute( + int32_t render_process_id, + int32_t render_routing_id, + bool* is_guest_view = nullptr) const; + + // Returns the frame object matching the specified ID or nullptr if no match + // is found. Nullptr will also be returned if a guest view match is found + // because we don't create frame objects for guest views. If |is_guest_view| + // is non-nullptr it will be set to true in this case. Safe to call from any + // thread. + CefRefPtr GetFrameForId( + int64_t frame_id, + bool* is_guest_view = nullptr) const; + + // Returns the frame object matching the specified ID or nullptr if no match + // is found. Nullptr will also be returned if a guest view match is found + // because we don't create frame objects for guest views. If |is_guest_view| + // is non-nullptr it will be set to true in this case. Safe to call from any + // thread. + CefRefPtr GetFrameForFrameTreeNode( + int frame_tree_node_id, + bool* is_guest_view = nullptr) const; + + // Returns all non-speculative frame objects that currently exist. Guest views + // will be excluded because they don't have a frame object. Safe to call from + // any thread. + typedef std::set> FrameHostList; + FrameHostList GetAllFrames() const; private: friend class base::RefCountedThreadSafe; - ~CefBrowserInfo(); + virtual ~CefBrowserInfo(); + + struct FrameInfo { + ~FrameInfo(); + + content::RenderFrameHost* host_; + int64_t frame_id_; // Combination of render_process_id + render_routing_id. + int frame_tree_node_id_; + bool is_guest_view_; + bool is_main_frame_; + bool is_speculative_; + CefRefPtr frame_; + }; + + void MaybeUpdateFrameTreeNodeIdMap(FrameInfo* info); + + CefRefPtr GetFrameForFrameTreeNodeInternal( + int frame_tree_node_id, + bool* is_guest_view = nullptr) const; + + void RemoveAllFrames(); int browser_id_; bool is_popup_; bool is_windowless_; + CefRefPtr extra_info_; mutable base::Lock lock_; // The below members must be protected by |lock_|. - RenderIDManager render_id_manager_; - RenderIDManager guest_render_id_manager_; - - FrameTreeNodeIDManager frame_tree_node_id_manager_; - - // May be NULL if the browser has not yet been created or if the browser has - // been destroyed. CefRefPtr browser_; - CefRefPtr extra_info_; + // Owner of FrameInfo structs. + typedef std::set, base::UniquePtrComparator> + FrameInfoSet; + FrameInfoSet frame_info_set_; + + // Map a frame ID (e.g. MakeFrameId(process_id, routing_id)) to one frame. + typedef std::unordered_map FrameIDMap; + FrameIDMap frame_id_map_; + + // Map a frame_tree_node_id to one frame. + typedef std::unordered_map FrameTreeNodeIDMap; + FrameTreeNodeIDMap frame_tree_node_id_map_; + + // The current main frame. + CefRefPtr main_frame_; DISALLOW_COPY_AND_ASSIGN(CefBrowserInfo); }; diff --git a/libcef/browser/browser_info_manager.cc b/libcef/browser/browser_info_manager.cc index e27b989f9..a0ec4dc66 100644 --- a/libcef/browser/browser_info_manager.cc +++ b/libcef/browser/browser_info_manager.cc @@ -65,13 +65,10 @@ scoped_refptr CefBrowserInfoManager::CreateBrowserInfo( CefRefPtr extra_info) { base::AutoLock lock_scope(browser_info_lock_); - scoped_refptr browser_info = - new CefBrowserInfo(++next_browser_id_, is_popup, extra_info); + scoped_refptr browser_info = new CefBrowserInfo( + ++next_browser_id_, is_popup, is_windowless, extra_info); browser_info_list_.push_back(browser_info); - if (is_windowless) - browser_info->set_windowless(true); - return browser_info; } @@ -81,32 +78,20 @@ scoped_refptr CefBrowserInfoManager::CreatePopupBrowserInfo( CefRefPtr extra_info) { base::AutoLock lock_scope(browser_info_lock_); - content::RenderFrameHost* frame_host = new_contents->GetMainFrame(); + auto frame_host = new_contents->GetMainFrame(); const int render_process_id = frame_host->GetProcess()->GetID(); - const int render_frame_routing_id = frame_host->GetRoutingID(); + const auto frame_id = CefFrameHostImpl::MakeFrameId(frame_host); scoped_refptr browser_info = - new CefBrowserInfo(++next_browser_id_, true, extra_info); - browser_info->render_id_manager()->add_render_frame_id( - render_process_id, render_frame_routing_id); + new CefBrowserInfo(++next_browser_id_, true, is_windowless, extra_info); browser_info_list_.push_back(browser_info); - if (is_windowless) - browser_info->set_windowless(true); - // Continue any pending NewBrowserInfo requests. - PendingNewBrowserInfoList::iterator it = - pending_new_browser_info_list_.begin(); - for (; it != pending_new_browser_info_list_.end(); ++it) { - PendingNewBrowserInfo* info = it->get(); - if (info->render_process_id == render_process_id && - info->render_frame_routing_id == render_frame_routing_id) { - SendNewBrowserInfoResponse(render_process_id, browser_info, false, - info->reply_msg); - - pending_new_browser_info_list_.erase(it); - break; - } + auto it = pending_new_browser_info_map_.find(frame_id); + if (it != pending_new_browser_info_map_.end()) { + SendNewBrowserInfoResponse(render_process_id, browser_info, false, + it->second->reply_msg); + pending_new_browser_info_map_.erase(it); } return browser_info; @@ -159,8 +144,8 @@ bool CefBrowserInfoManager::CanCreateWindow( auto pending_popup = std::make_unique(); pending_popup->step = CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW; - pending_popup->opener_process_id = opener->GetProcess()->GetID(); - pending_popup->opener_frame_id = opener->GetRoutingID(); + pending_popup->opener_render_process_id = opener->GetProcess()->GetID(); + pending_popup->opener_render_routing_id = opener->GetRoutingID(); pending_popup->target_url = target_url; pending_popup->target_frame_name = frame_name; @@ -171,8 +156,8 @@ bool CefBrowserInfoManager::CanCreateWindow( if (client.get()) { CefRefPtr handler = client->GetLifeSpanHandler(); if (handler.get()) { - CefRefPtr frame = - browser->GetFrame(pending_popup->opener_frame_id); + CefRefPtr opener_frame = browser->GetFrameForHost(opener); + DCHECK(opener_frame); CefPopupFeatures cef_features; TranslatePopupFeatures(features, cef_features); @@ -190,7 +175,7 @@ bool CefBrowserInfoManager::CanCreateWindow( #endif allow = !handler->OnBeforePopup( - browser.get(), frame, pending_popup->target_url.spec(), + browser.get(), opener_frame, pending_popup->target_url.spec(), pending_popup->target_frame_name, static_cast(disposition), user_gesture, cef_features, *window_info, pending_popup->client, @@ -229,14 +214,14 @@ bool CefBrowserInfoManager::CanCreateWindow( void CefBrowserInfoManager::GetCustomWebContentsView( const GURL& target_url, int opener_render_process_id, - int opener_render_frame_id, + int opener_render_routing_id, content::WebContentsView** view, content::RenderViewHostDelegateView** delegate_view) { CEF_REQUIRE_UIT(); std::unique_ptr pending_popup = PopPendingPopup(CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW, - opener_render_process_id, opener_render_frame_id, + opener_render_process_id, opener_render_routing_id, target_url); DCHECK(pending_popup.get()); DCHECK(pending_popup->platform_delegate.get()); @@ -254,7 +239,7 @@ void CefBrowserInfoManager::GetCustomWebContentsView( void CefBrowserInfoManager::WebContentsCreated( const GURL& target_url, int opener_render_process_id, - int opener_render_frame_id, + int opener_render_routing_id, CefBrowserSettings& settings, CefRefPtr& client, std::unique_ptr& platform_delegate, @@ -264,7 +249,7 @@ void CefBrowserInfoManager::WebContentsCreated( std::unique_ptr pending_popup = PopPendingPopup( CefBrowserInfoManager::PendingPopup::GET_CUSTOM_WEB_CONTENTS_VIEW, - opener_render_process_id, opener_render_frame_id, target_url); + opener_render_process_id, opener_render_routing_id, target_url); DCHECK(pending_popup.get()); DCHECK(pending_popup->platform_delegate.get()); @@ -275,18 +260,18 @@ void CefBrowserInfoManager::WebContentsCreated( } void CefBrowserInfoManager::OnGetNewBrowserInfo(int render_process_id, - int render_frame_routing_id, + int render_routing_id, IPC::Message* reply_msg) { DCHECK_NE(render_process_id, content::ChildProcessHost::kInvalidUniqueID); - DCHECK_GT(render_frame_routing_id, 0); + DCHECK_GT(render_routing_id, 0); DCHECK(reply_msg); base::AutoLock lock_scope(browser_info_lock_); bool is_guest_view = false; - scoped_refptr browser_info = GetBrowserInfo( - render_process_id, render_frame_routing_id, &is_guest_view); + scoped_refptr browser_info = + GetBrowserInfo(render_process_id, render_routing_id, &is_guest_view); if (browser_info.get()) { // Send the response immediately. @@ -295,27 +280,20 @@ void CefBrowserInfoManager::OnGetNewBrowserInfo(int render_process_id, return; } -#if DCHECK_IS_ON() + const auto frame_id = + CefFrameHostImpl::MakeFrameId(render_process_id, render_routing_id); + // Verify that no request for the same route is currently queued. - { - PendingNewBrowserInfoList::const_iterator it = - pending_new_browser_info_list_.begin(); - for (; it != pending_new_browser_info_list_.end(); ++it) { - PendingNewBrowserInfo* info = it->get(); - if (info->render_process_id == render_process_id && - info->render_frame_routing_id == render_frame_routing_id) { - NOTREACHED(); - } - } - } -#endif + DCHECK(pending_new_browser_info_map_.find(frame_id) == + pending_new_browser_info_map_.end()); // Queue the request. std::unique_ptr pending(new PendingNewBrowserInfo()); pending->render_process_id = render_process_id; - pending->render_frame_routing_id = render_frame_routing_id; + pending->render_routing_id = render_routing_id; pending->reply_msg = reply_msg; - pending_new_browser_info_list_.push_back(std::move(pending)); + pending_new_browser_info_map_.insert( + std::make_pair(frame_id, std::move(pending))); } void CefBrowserInfoManager::RemoveBrowserInfo( @@ -363,26 +341,32 @@ void CefBrowserInfoManager::DestroyAllBrowsers() { #endif } -scoped_refptr CefBrowserInfoManager::GetBrowserInfoForFrame( - int render_process_id, - int render_routing_id, - bool* is_guest_view) { +scoped_refptr +CefBrowserInfoManager::GetBrowserInfoForFrameRoute(int render_process_id, + int render_routing_id, + bool* is_guest_view) { base::AutoLock lock_scope(browser_info_lock_); return GetBrowserInfo(render_process_id, render_routing_id, is_guest_view); } scoped_refptr -CefBrowserInfoManager::GetBrowserInfoForFrameTreeNode(int frame_tree_node_id) { +CefBrowserInfoManager::GetBrowserInfoForFrameTreeNode(int frame_tree_node_id, + bool* is_guest_view) { + if (is_guest_view) + *is_guest_view = false; + if (frame_tree_node_id < 0) return nullptr; base::AutoLock lock_scope(browser_info_lock_); - BrowserInfoList::const_iterator it = browser_info_list_.begin(); - for (; it != browser_info_list_.end(); ++it) { - const scoped_refptr& browser_info = *it; - if (browser_info->frame_tree_node_id_manager()->is_frame_tree_node_id_match( - frame_tree_node_id)) { + for (const auto& browser_info : browser_info_list_) { + bool is_guest_view_tmp; + auto frame = browser_info->GetFrameForFrameTreeNode(frame_tree_node_id, + &is_guest_view_tmp); + if (frame || is_guest_view_tmp) { + if (is_guest_view) + *is_guest_view = is_guest_view_tmp; return browser_info; } } @@ -390,9 +374,12 @@ CefBrowserInfoManager::GetBrowserInfoForFrameTreeNode(int frame_tree_node_id) { return nullptr; } -void CefBrowserInfoManager::GetBrowserInfoList(BrowserInfoList& list) { +CefBrowserInfoManager::BrowserInfoList +CefBrowserInfoManager::GetBrowserInfoList() { base::AutoLock lock_scope(browser_info_lock_); - list = browser_info_list_; + BrowserInfoList copy; + copy.assign(browser_info_list_.begin(), browser_info_list_.end()); + return copy; } void CefBrowserInfoManager::RenderProcessHostDestroyed( @@ -406,12 +393,12 @@ void CefBrowserInfoManager::RenderProcessHostDestroyed( { base::AutoLock lock_scope(browser_info_lock_); - PendingNewBrowserInfoList::iterator it = - pending_new_browser_info_list_.begin(); - while (it != pending_new_browser_info_list_.end()) { - PendingNewBrowserInfo* info = it->get(); + PendingNewBrowserInfoMap::iterator it = + pending_new_browser_info_map_.begin(); + while (it != pending_new_browser_info_map_.end()) { + auto info = it->second.get(); if (info->render_process_id == render_process_id) - it = pending_new_browser_info_list_.erase(it); + it = pending_new_browser_info_map_.erase(it); else ++it; } @@ -422,7 +409,7 @@ void CefBrowserInfoManager::RenderProcessHostDestroyed( PendingPopupList::iterator it = pending_popup_list_.begin(); while (it != pending_popup_list_.end()) { PendingPopup* popup = it->get(); - if (popup->opener_process_id == render_process_id) { + if (popup->opener_render_process_id == render_process_id) { it = pending_popup_list_.erase(it); } else { ++it; @@ -439,18 +426,19 @@ void CefBrowserInfoManager::PushPendingPopup( std::unique_ptr CefBrowserInfoManager::PopPendingPopup(PendingPopup::Step step, - int opener_process_id, - int opener_frame_id, + int opener_render_process_id, + int opener_render_routing_id, const GURL& target_url) { CEF_REQUIRE_UIT(); - DCHECK_GT(opener_process_id, 0); - DCHECK_GT(opener_frame_id, 0); + DCHECK_GT(opener_render_process_id, 0); + DCHECK_GT(opener_render_routing_id, 0); PendingPopupList::iterator it = pending_popup_list_.begin(); for (; it != pending_popup_list_.end(); ++it) { PendingPopup* popup = it->get(); - if (popup->step == step && popup->opener_process_id == opener_process_id && - popup->opener_frame_id == opener_frame_id && + if (popup->step == step && + popup->opener_render_process_id == opener_render_process_id && + popup->opener_render_routing_id == opener_render_routing_id && popup->target_url == target_url) { // Transfer ownership of the pointer. it->release(); @@ -463,29 +451,24 @@ CefBrowserInfoManager::PopPendingPopup(PendingPopup::Step step, } scoped_refptr CefBrowserInfoManager::GetBrowserInfo( - int render_frame_process_id, - int render_frame_routing_id, + int render_process_id, + int render_routing_id, bool* is_guest_view) { browser_info_lock_.AssertAcquired(); if (is_guest_view) *is_guest_view = false; - if (render_frame_process_id < 0 || render_frame_routing_id < 0) + if (render_process_id < 0 || render_routing_id < 0) return nullptr; - BrowserInfoList::const_iterator it = browser_info_list_.begin(); - for (; it != browser_info_list_.end(); ++it) { - const scoped_refptr& browser_info = *it; - if (browser_info->render_id_manager()->is_render_frame_id_match( - render_frame_process_id, render_frame_routing_id)) { - return browser_info; - } - if (extensions::ExtensionsEnabled() && - browser_info->guest_render_id_manager()->is_render_frame_id_match( - render_frame_process_id, render_frame_routing_id)) { + for (const auto& browser_info : browser_info_list_) { + bool is_guest_view_tmp; + auto frame = browser_info->GetFrameForRoute( + render_process_id, render_routing_id, &is_guest_view_tmp); + if (frame || is_guest_view_tmp) { if (is_guest_view) - *is_guest_view = true; + *is_guest_view = is_guest_view_tmp; return browser_info; } } diff --git a/libcef/browser/browser_info_manager.h b/libcef/browser/browser_info_manager.h index fbd5e5ede..5983a4834 100644 --- a/libcef/browser/browser_info_manager.h +++ b/libcef/browser/browser_info_manager.h @@ -8,7 +8,7 @@ #include "include/cef_client.h" -#include +#include #include #include @@ -80,7 +80,7 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { void GetCustomWebContentsView( const GURL& target_url, int opener_render_process_id, - int opener_render_frame_id, + int opener_render_routing_id, content::WebContentsView** view, content::RenderViewHostDelegateView** delegate_view); @@ -89,7 +89,7 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { void WebContentsCreated( const GURL& target_url, int opener_render_process_id, - int opener_render_frame_id, + int opener_render_routing_id, CefBrowserSettings& settings, CefRefPtr& client, std::unique_ptr& platform_delegate, @@ -103,7 +103,7 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { // already exist for traditional popup browsers depending on timing. See // comments on PendingPopup for more information. void OnGetNewBrowserInfo(int render_process_id, - int render_frame_routing_id, + int render_routing_id, IPC::Message* reply_msg); // Called from CefBrowserHostImpl::DestroyBrowser() when a browser is @@ -113,27 +113,30 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { // Called from CefContext::FinishShutdownOnUIThread() to destroy all browsers. void DestroyAllBrowsers(); - // Retrieves the CefBrowserInfo matching the specified IDs or an empty - // pointer if no match is found. It is allowed to add new callers of this - // method but consider using CefBrowserHostImpl::GetBrowserForFrame() - // or extensions::GetOwnerBrowserForFrame() instead. - // |is_guest_view| will be set to true if the IDs match a guest view - // associated with the returned browser info instead of the browser itself. - scoped_refptr GetBrowserInfoForFrame(int render_process_id, - int render_routing_id, - bool* is_guest_view); + // Returns the CefBrowserInfo matching the specified IDs or nullptr if no + // match is found. It is allowed to add new callers of this method but + // consider using CefBrowserHostImpl::GetBrowserForFrameRoute() or + // extensions::GetOwnerBrowserForFrameRoute() instead. If |is_guest_view| is + // non-nullptr it will be set to true if the IDs match a guest view associated + // with the returned browser info instead of the browser itself. + scoped_refptr GetBrowserInfoForFrameRoute( + int render_process_id, + int render_routing_id, + bool* is_guest_view = nullptr); - // Retrieves the CefBrowserInfo matching the specified ID or an empty - // pointer if no match is found. It is allowed to add new callers of this - // method but consider using CefBrowserHostImpl::GetBrowserForRequest() - // instead since we generally use this mapping for URLRequests on the IO - // thread. + // Returns the CefBrowserInfo matching the specified ID or nullptr if no match + // is found. It is allowed to add new callers of this method but consider + // using CefBrowserHostImpl::GetBrowserForFrameTreeNode() instead. If + // |is_guest_view| is non-nullptr it will be set to true if the IDs match a + // guest view associated with the returned browser info instead of the browser + // itself. scoped_refptr GetBrowserInfoForFrameTreeNode( - int frame_tree_node_id); + int frame_tree_node_id, + bool* is_guest_view = nullptr); - // Retrieves all existing CefBrowserInfo objects. + // Returns all existing CefBrowserInfo objects. typedef std::list> BrowserInfoList; - void GetBrowserInfoList(BrowserInfoList& list); + BrowserInfoList GetBrowserInfoList(); private: // RenderProcessHostObserver methods: @@ -164,8 +167,8 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { // Initial state from ViewHostMsg_CreateWindow. // |target_url| will be empty if a popup is created via window.open() and // never navigated. For example: javascript:window.open(); - int opener_process_id; - int opener_frame_id; + int opener_render_process_id; + int opener_render_routing_id; GURL target_url; std::string target_frame_name; @@ -182,13 +185,13 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { void PushPendingPopup(std::unique_ptr popup); std::unique_ptr PopPendingPopup(PendingPopup::Step step, int opener_process_id, - int opener_frame_id, + int opener_routing_id, const GURL& target_url); // Retrieves the BrowserInfo matching the specified IDs. If both sets are // valid then this method makes sure both sets have been registered. - scoped_refptr GetBrowserInfo(int render_frame_process_id, - int render_frame_routing_id, + scoped_refptr GetBrowserInfo(int render_process_id, + int render_routing_id, bool* is_guest_view); // Send the response for a pending OnGetNewBrowserInfo request. @@ -201,7 +204,7 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { // Pending request for OnGetNewBrowserInfo. struct PendingNewBrowserInfo { int render_process_id; - int render_frame_routing_id; + int render_routing_id; IPC::Message* reply_msg; }; @@ -212,9 +215,10 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { BrowserInfoList browser_info_list_; int next_browser_id_; - using PendingNewBrowserInfoList = - std::vector>; - PendingNewBrowserInfoList pending_new_browser_info_list_; + // Map of frame ID to info. + using PendingNewBrowserInfoMap = + std::map>; + PendingNewBrowserInfoMap pending_new_browser_info_map_; // Only accessed on the UI thread. using PendingPopupList = std::vector>; diff --git a/libcef/browser/content_browser_client.cc b/libcef/browser/content_browser_client.cc index eb2007a83..ab26ef681 100644 --- a/libcef/browser/content_browser_client.cc +++ b/libcef/browser/content_browser_client.cc @@ -334,8 +334,8 @@ class CefQuotaPermissionContext : public content::QuotaPermissionContext { bool handled = false; CefRefPtr browser = - CefBrowserHostImpl::GetBrowserForFrame(render_process_id, - params.render_frame_id); + CefBrowserHostImpl::GetBrowserForFrameRoute(render_process_id, + params.render_frame_id); if (browser.get()) { CefRefPtr client = browser->GetClient(); if (client.get()) { @@ -427,8 +427,8 @@ int GetCrashSignalFD(const base::CommandLine& command_line) { // |is_main_frame| argument once this problem is fixed. bool NavigationOnUIThread( bool is_main_frame, - int64 frame_id, - int64 parent_frame_id, + int64_t frame_id, + int64_t parent_frame_id, content::WebContents* source, const navigation_interception::NavigationParams& params) { CEF_REQUIRE_UIT(); @@ -448,12 +448,11 @@ bool NavigationOnUIThread( } else if (frame_id >= 0) { frame = browser->GetFrame(frame_id); DCHECK(frame); - } else { + } + if (!frame) { // Create a temporary frame object for navigation of sub-frames that // don't yet exist. - frame = new CefFrameHostImpl( - browser.get(), CefFrameHostImpl::kInvalidFrameId, false, - CefString(), CefString(), parent_frame_id); + frame = browser->browser_info()->CreateTempSubFrame(parent_frame_id); } CefRefPtr request = new CefRequestImpl(); @@ -1089,24 +1088,16 @@ CefContentBrowserClient::CreateThrottlesForNavigation( const bool is_main_frame = navigation_handle->IsInMainFrame(); - int64 parent_frame_id = CefFrameHostImpl::kUnspecifiedFrameId; - if (!is_main_frame) { - // Identify the RenderFrameHost that originated the navigation. - content::RenderFrameHost* parent_frame_host = - navigation_handle->GetParentFrame(); - DCHECK(parent_frame_host); - if (parent_frame_host) - parent_frame_id = parent_frame_host->GetRoutingID(); - if (parent_frame_id < 0) - parent_frame_id = CefFrameHostImpl::kUnspecifiedFrameId; - } + // Identify the RenderFrameHost that originated the navigation. + const int64_t parent_frame_id = + !is_main_frame + ? CefFrameHostImpl::MakeFrameId(navigation_handle->GetParentFrame()) + : CefFrameHostImpl::kInvalidFrameId; - int64 frame_id = CefFrameHostImpl::kInvalidFrameId; - if (!is_main_frame && navigation_handle->HasCommitted()) { - frame_id = navigation_handle->GetRenderFrameHost()->GetRoutingID(); - if (frame_id < 0) - frame_id = CefFrameHostImpl::kInvalidFrameId; - } + const int64_t frame_id = !is_main_frame && navigation_handle->HasCommitted() + ? CefFrameHostImpl::MakeFrameId( + navigation_handle->GetRenderFrameHost()) + : CefFrameHostImpl::kInvalidFrameId; // Must use SynchronyMode::kSync to ensure that OnBeforeBrowse is always // called before OnBeforeResourceLoad. diff --git a/libcef/browser/extensions/browser_extensions_util.cc b/libcef/browser/extensions/browser_extensions_util.cc index 5a6b93db8..7c6ec9078 100644 --- a/libcef/browser/extensions/browser_extensions_util.cc +++ b/libcef/browser/extensions/browser_extensions_util.cc @@ -61,9 +61,10 @@ content::WebContents* GetOwnerForGuestContents(content::WebContents* guest) { return NULL; } -CefRefPtr GetOwnerBrowserForFrame(int render_process_id, - int render_routing_id, - bool* is_guest_view) { +CefRefPtr GetOwnerBrowserForFrameRoute( + int render_process_id, + int render_routing_id, + bool* is_guest_view) { if (CEF_CURRENTLY_ON_UIT()) { // Use the non-thread-safe but potentially faster approach. content::RenderFrameHost* host = @@ -74,7 +75,7 @@ CefRefPtr GetOwnerBrowserForFrame(int render_process_id, } else { // Use the thread-safe approach. scoped_refptr info = - CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrame( + CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameRoute( render_process_id, render_routing_id, is_guest_view); if (info.get()) { CefRefPtr browser = info->browser(); @@ -143,9 +144,8 @@ CefRefPtr GetBrowserForTabId( CefBrowserContext* browser_context_impl = CefBrowserContext::GetForContext(browser_context); - CefBrowserInfoManager::BrowserInfoList list; - CefBrowserInfoManager::GetInstance()->GetBrowserInfoList(list); - for (auto browser_info : list) { + for (const auto& browser_info : + CefBrowserInfoManager::GetInstance()->GetBrowserInfoList()) { CefRefPtr current_browser = browser_info->browser(); if (current_browser && current_browser->GetIdentifier() == tab_id) { // Make sure we're operating in the same BrowserContextImpl. diff --git a/libcef/browser/extensions/browser_extensions_util.h b/libcef/browser/extensions/browser_extensions_util.h index c4432234a..a4de94bc4 100644 --- a/libcef/browser/extensions/browser_extensions_util.h +++ b/libcef/browser/extensions/browser_extensions_util.h @@ -36,9 +36,10 @@ content::WebContents* GetOwnerForGuestContents(content::WebContents* guest); // routing IDs, if any. |is_guest_view| will be set to true if the IDs // match a guest view associated with the returned browser instead of the // browser itself. -CefRefPtr GetOwnerBrowserForFrame(int render_process_id, - int render_routing_id, - bool* is_guest_view); +CefRefPtr GetOwnerBrowserForFrameRoute( + int render_process_id, + int render_routing_id, + bool* is_guest_view); // Returns the CefBrowserHostImpl that owns the specified |host|, if any. // |is_guest_view| will be set to true if the host matches a guest view diff --git a/libcef/browser/extensions/mime_handler_view_guest_delegate.cc b/libcef/browser/extensions/mime_handler_view_guest_delegate.cc index 2dce78463..157e8afb6 100644 --- a/libcef/browser/extensions/mime_handler_view_guest_delegate.cc +++ b/libcef/browser/extensions/mime_handler_view_guest_delegate.cc @@ -54,25 +54,9 @@ void CefMimeHandlerViewGuestDelegate::OnGuestAttached( content::WebContents* web_contents = guest_->web_contents(); DCHECK(web_contents); - CefRefPtr owner_browser = GetOwnerBrowser(guest_); - // Associate guest state information with the owner browser. - scoped_refptr info = owner_browser->browser_info(); - content::RenderFrameHost* main_frame_host = web_contents->GetMainFrame(); - - const int render_process_id = main_frame_host->GetProcess()->GetID(); - const int render_frame_id = main_frame_host->GetRoutingID(); - info->guest_render_id_manager()->add_render_frame_id(render_process_id, - render_frame_id); - - const int frame_tree_node_id = main_frame_host->GetFrameTreeNodeId(); - info->frame_tree_node_id_manager()->add_frame_tree_node_id( - frame_tree_node_id); - - const bool is_main_frame = (main_frame_host->GetParent() == nullptr); - owner_browser->request_context()->OnRenderFrameCreated( - render_process_id, render_frame_id, frame_tree_node_id, is_main_frame, - true); + GetOwnerBrowser(guest_)->browser_info()->MaybeCreateFrame( + web_contents->GetMainFrame(), true /* is_guest_view */); } void CefMimeHandlerViewGuestDelegate::OnGuestDetached( @@ -80,25 +64,9 @@ void CefMimeHandlerViewGuestDelegate::OnGuestDetached( content::WebContents* web_contents = guest_->web_contents(); DCHECK(web_contents); - CefRefPtr owner_browser = GetOwnerBrowser(guest_); - // Disassociate guest state information with the owner browser. - scoped_refptr info = owner_browser->browser_info(); - content::RenderFrameHost* main_frame_host = web_contents->GetMainFrame(); - - const int render_process_id = main_frame_host->GetProcess()->GetID(); - const int render_frame_id = main_frame_host->GetRoutingID(); - info->guest_render_id_manager()->remove_render_frame_id(render_process_id, - render_frame_id); - - const int frame_tree_node_id = main_frame_host->GetFrameTreeNodeId(); - info->frame_tree_node_id_manager()->remove_frame_tree_node_id( - frame_tree_node_id); - - const bool is_main_frame = (main_frame_host->GetParent() == nullptr); - owner_browser->request_context()->OnRenderFrameDeleted( - render_process_id, render_frame_id, frame_tree_node_id, is_main_frame, - true); + GetOwnerBrowser(guest_)->browser_info()->RemoveFrame( + web_contents->GetMainFrame()); } bool CefMimeHandlerViewGuestDelegate::HandleContextMenu( diff --git a/libcef/browser/frame_host_impl.cc b/libcef/browser/frame_host_impl.cc index ed84b0f42..2513c2970 100644 --- a/libcef/browser/frame_host_impl.cc +++ b/libcef/browser/frame_host_impl.cc @@ -9,12 +9,17 @@ #include "include/cef_v8.h" #include "include/test/cef_test_helpers.h" #include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/navigate_params.h" #include "libcef/browser/net/browser_urlrequest_old_impl.h" #include "libcef/browser/net_service/browser_urlrequest_impl.h" #include "libcef/common/cef_messages.h" +#include "libcef/common/frame_util.h" #include "libcef/common/net_service/util.h" +#include "libcef/common/process_message_impl.h" +#include "libcef/common/request_impl.h" #include "libcef/common/task_runner_impl.h" +#include "content/browser/frame_host/frame_tree_node.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" @@ -55,55 +60,91 @@ class ViewTextHandler : public CefResponseManager::Handler { } // namespace -CefFrameHostImpl::CefFrameHostImpl(CefBrowserHostImpl* browser, - int64 frame_id, +CefFrameHostImpl::CefFrameHostImpl(scoped_refptr browser_info, bool is_main_frame, - const CefString& url, - const CefString& name, - int64 parent_frame_id) - : frame_id_(frame_id), - is_main_frame_(is_main_frame), - browser_(browser), + int64_t parent_frame_id) + : is_main_frame_(is_main_frame), + frame_id_(kInvalidFrameId), + browser_info_(browser_info), is_focused_(is_main_frame_), // The main frame always starts focused. - url_(url), - name_(name), - parent_frame_id_(parent_frame_id == kUnspecifiedFrameId + parent_frame_id_(parent_frame_id) { +#if DCHECK_IS_ON() + DCHECK(browser_info_); + if (is_main_frame_) { + DCHECK_EQ(parent_frame_id_, kInvalidFrameId); + } else { + DCHECK_GT(parent_frame_id_, 0); + } +#endif +} + +CefFrameHostImpl::CefFrameHostImpl(scoped_refptr browser_info, + content::RenderFrameHost* render_frame_host) + : is_main_frame_(render_frame_host->GetParent() == nullptr), + frame_id_(MakeFrameId(render_frame_host)), + browser_info_(browser_info), + is_focused_(is_main_frame_), // The main frame always starts focused. + url_(render_frame_host->GetLastCommittedURL().spec()), + name_(render_frame_host->GetFrameName()), + parent_frame_id_(is_main_frame_ ? kInvalidFrameId - : parent_frame_id) {} + : MakeFrameId(render_frame_host->GetParent())), + render_frame_host_(render_frame_host), + response_manager_(new CefResponseManager) { + DCHECK(browser_info_); +} CefFrameHostImpl::~CefFrameHostImpl() {} -bool CefFrameHostImpl::IsValid() { +void CefFrameHostImpl::SetRenderFrameHost(content::RenderFrameHost* host) { + CEF_REQUIRE_UIT(); + base::AutoLock lock_scope(state_lock_); - return (browser_ != NULL); + + // We should not be detached. + CHECK(browser_info_); + // We should be the main frame. + CHECK(is_main_frame_); + + render_frame_host_ = host; + frame_id_ = MakeFrameId(host); + url_ = host->GetLastCommittedURL().spec(); + name_ = host->GetFrameName(); + + // Cancel any existing messages. + response_manager_.reset(new CefResponseManager); +} + +bool CefFrameHostImpl::IsValid() { + return !!GetBrowserHostImpl(); } void CefFrameHostImpl::Undo() { - SendCommand("Undo", NULL); + SendCommand("Undo", nullptr); } void CefFrameHostImpl::Redo() { - SendCommand("Redo", NULL); + SendCommand("Redo", nullptr); } void CefFrameHostImpl::Cut() { - SendCommand("Cut", NULL); + SendCommand("Cut", nullptr); } void CefFrameHostImpl::Copy() { - SendCommand("Copy", NULL); + SendCommand("Copy", nullptr); } void CefFrameHostImpl::Paste() { - SendCommand("Paste", NULL); + SendCommand("Paste", nullptr); } void CefFrameHostImpl::Delete() { - SendCommand("Delete", NULL); + SendCommand("Delete", nullptr); } void CefFrameHostImpl::SelectAll() { - SendCommand("SelectAll", NULL); + SendCommand("SelectAll", nullptr); } void CefFrameHostImpl::ViewSource() { @@ -119,48 +160,33 @@ void CefFrameHostImpl::GetText(CefRefPtr visitor) { } void CefFrameHostImpl::LoadRequest(CefRefPtr request) { - CefRefPtr browser; - int64 frame_id; - - { - base::AutoLock lock_scope(state_lock_); - browser = browser_; - frame_id = (is_main_frame_ ? kMainFrameId : frame_id_); - } - - if (browser.get() && frame_id != kInvalidFrameId) - browser->LoadRequest(frame_id, request); + CefNavigateParams params(GURL(), ui::PAGE_TRANSITION_TYPED); + static_cast(request.get())->Get(params); + Navigate(params); } void CefFrameHostImpl::LoadURL(const CefString& url) { - CefRefPtr browser; - int64 frame_id; - - { - base::AutoLock lock_scope(state_lock_); - browser = browser_; - frame_id = (is_main_frame_ ? kMainFrameId : frame_id_); - } - - if (browser.get() && frame_id != kInvalidFrameId) { - browser->LoadURL(frame_id, url, content::Referrer(), - ui::PAGE_TRANSITION_TYPED, std::string()); - } + LoadURLWithExtras(url, content::Referrer(), ui::PAGE_TRANSITION_TYPED, + std::string()); } void CefFrameHostImpl::LoadString(const CefString& string, const CefString& url) { - CefRefPtr browser; - int64 frame_id; + // Only known frame ids or kMainFrameId are supported. + const auto frame_id = GetFrameId(); + if (frame_id < CefFrameHostImpl::kMainFrameId) + return; - { - base::AutoLock lock_scope(state_lock_); - browser = browser_; - frame_id = (is_main_frame_ ? kMainFrameId : frame_id_); - } + Cef_Request_Params params; + params.name = "load-string"; + params.user_initiated = false; + params.request_id = -1; + params.expect_response = false; - if (browser.get() && frame_id != kInvalidFrameId) - browser->LoadString(frame_id, string, url); + params.arguments.AppendString(string); + params.arguments.AppendString(url); + + Send(new CefMsg_Request(MSG_ROUTING_NONE, params)); } void CefFrameHostImpl::ExecuteJavaScript(const CefString& jsCode, @@ -184,25 +210,25 @@ CefString CefFrameHostImpl::GetName() { } int64 CefFrameHostImpl::GetIdentifier() { + base::AutoLock lock_scope(state_lock_); return frame_id_; } CefRefPtr CefFrameHostImpl::GetParent() { - CefRefPtr browser; int64 parent_frame_id; { base::AutoLock lock_scope(state_lock_); if (is_main_frame_ || parent_frame_id_ == kInvalidFrameId) - return NULL; - browser = browser_; + return nullptr; parent_frame_id = parent_frame_id_; } - if (browser.get()) + auto browser = GetBrowserHostImpl(); + if (browser) return browser->GetFrame(parent_frame_id); - return NULL; + return nullptr; } CefString CefFrameHostImpl::GetURL() { @@ -211,32 +237,12 @@ CefString CefFrameHostImpl::GetURL() { } CefRefPtr CefFrameHostImpl::GetBrowser() { - base::AutoLock lock_scope(state_lock_); - return browser_; -} - -void CefFrameHostImpl::SetFocused(bool focused) { - base::AutoLock lock_scope(state_lock_); - is_focused_ = focused; -} - -void CefFrameHostImpl::SetAttributes(bool is_main_frame, - const CefString& url, - const CefString& name, - int64 parent_frame_id) { - base::AutoLock lock_scope(state_lock_); - is_main_frame_ = is_main_frame; - if (!url.empty() && url != url_) - url_ = url; - if (!name.empty() && name != name_) - name_ = name; - if (parent_frame_id != kUnspecifiedFrameId) - parent_frame_id_ = parent_frame_id; + return GetBrowserHostImpl().get(); } CefRefPtr CefFrameHostImpl::GetV8Context() { NOTREACHED() << "GetV8Context cannot be called from the browser process"; - return NULL; + return nullptr; } void CefFrameHostImpl::VisitDOM(CefRefPtr visitor) { @@ -247,21 +253,16 @@ CefRefPtr CefFrameHostImpl::CreateURLRequest( CefRefPtr request, CefRefPtr client) { if (!request || !client) - return NULL; + return nullptr; if (!CefTaskRunnerImpl::GetCurrentTaskRunner()) { NOTREACHED() << "called on invalid thread"; - return NULL; - } - - CefRefPtr browser; - { - base::AutoLock lock_scope(state_lock_); - browser = browser_; + return nullptr; } + auto browser = GetBrowserHostImpl(); if (!browser) - return NULL; + return nullptr; auto request_context = browser->request_context(); @@ -276,7 +277,184 @@ CefRefPtr CefFrameHostImpl::CreateURLRequest( if (impl->Start()) return impl.get(); } - return NULL; + return nullptr; +} + +void CefFrameHostImpl::SendProcessMessage( + CefProcessId target_process, + CefRefPtr message) { + DCHECK_EQ(PID_RENDERER, target_process); + DCHECK(message.get()); + + Cef_Request_Params params; + CefProcessMessageImpl* impl = + static_cast(message.get()); + if (!impl->CopyTo(params)) + return; + + DCHECK(!params.name.empty()); + + params.user_initiated = true; + params.request_id = -1; + params.expect_response = false; + + Send(new CefMsg_Request(MSG_ROUTING_NONE, params)); +} + +void CefFrameHostImpl::SetFocused(bool focused) { + base::AutoLock lock_scope(state_lock_); + is_focused_ = focused; +} + +void CefFrameHostImpl::RefreshAttributes() { + CEF_REQUIRE_UIT(); + + base::AutoLock lock_scope(state_lock_); + if (!render_frame_host_) + return; + url_ = render_frame_host_->GetLastCommittedURL().spec(); + + // Use the assigned name if it is non-empty. This represents the name property + // on the frame DOM element. If the assigned name is empty, revert to the + // internal unique name. This matches the logic in render_frame_util::GetName. + name_ = render_frame_host_->GetFrameName(); + if (name_.empty()) { + const auto node = content::FrameTreeNode::GloballyFindByID( + render_frame_host_->GetFrameTreeNodeId()); + if (node) { + name_ = node->unique_name(); + } + } + + if (!is_main_frame_) + parent_frame_id_ = MakeFrameId(render_frame_host_->GetParent()); +} + +void CefFrameHostImpl::Navigate(const CefNavigateParams& params) { + CefMsg_LoadRequest_Params request; + request.url = params.url; + if (!request.url.is_valid()) { + LOG(ERROR) << "Invalid URL passed to CefFrameHostImpl::Navigate: " + << params.url; + return; + } + + request.method = params.method; + request.referrer = params.referrer.url; + request.referrer_policy = + CefRequestImpl::BlinkReferrerPolicyToNetReferrerPolicy( + params.referrer.policy); + request.site_for_cookies = params.site_for_cookies; + request.headers = params.headers; + request.load_flags = params.load_flags; + request.upload_data = params.upload_data; + + Send(new CefMsg_LoadRequest(MSG_ROUTING_NONE, request)); + + auto browser = GetBrowserHostImpl(); + if (browser) + browser->OnSetFocus(FOCUS_SOURCE_NAVIGATION); +} + +void CefFrameHostImpl::LoadURLWithExtras(const std::string& url, + const content::Referrer& referrer, + ui::PageTransition transition, + const std::string& extra_headers) { + // Only known frame ids or kMainFrameId are supported. + const auto frame_id = GetFrameId(); + if (frame_id < CefFrameHostImpl::kMainFrameId) + return; + + if (frame_id == CefFrameHostImpl::kMainFrameId) { + // Load via the browser using NavigationController. + auto browser = GetBrowserHostImpl(); + if (browser) { + browser->LoadMainFrameURL(url, referrer, transition, extra_headers); + } + } else { + CefNavigateParams params(GURL(url), transition); + params.referrer = referrer; + params.headers = extra_headers; + Navigate(params); + } +} + +void CefFrameHostImpl::SendCommand( + const std::string& command, + CefRefPtr responseHandler) { + DCHECK(!command.empty()); + + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefFrameHostImpl::SendCommand, this, + command, responseHandler)); + return; + } + + // Only known frame ids or kMainFrameId are supported. + const auto frame_id = GetFrameId(); + if (frame_id < CefFrameHostImpl::kMainFrameId) + return; + + TRACE_EVENT2("cef", "CefFrameHostImpl::SendCommand", "frame_id", frame_id, + "needsResponse", responseHandler.get() ? 1 : 0); + Cef_Request_Params params; + params.name = "execute-command"; + params.user_initiated = false; + + if (responseHandler.get()) { + params.request_id = response_manager_->RegisterHandler(responseHandler); + params.expect_response = true; + } else { + params.request_id = -1; + params.expect_response = false; + } + + params.arguments.AppendString(command); + + Send(new CefMsg_Request(MSG_ROUTING_NONE, params)); +} + +void CefFrameHostImpl::SendCode( + bool is_javascript, + const std::string& code, + const std::string& script_url, + int script_start_line, + CefRefPtr responseHandler) { + DCHECK(!code.empty()); + DCHECK_GE(script_start_line, 0); + + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefFrameHostImpl::SendCode, this, + is_javascript, code, script_url, + script_start_line, responseHandler)); + return; + } + + // Only known frame ids or kMainFrameId are supported. + auto frame_id = GetFrameId(); + if (frame_id < CefFrameHostImpl::kMainFrameId) + return; + + TRACE_EVENT2("cef", "CefFrameHostImpl::SendCommand", "frame_id", frame_id, + "needsResponse", responseHandler.get() ? 1 : 0); + Cef_Request_Params params; + params.name = "execute-code"; + params.user_initiated = false; + + if (responseHandler.get()) { + params.request_id = response_manager_->RegisterHandler(responseHandler); + params.expect_response = true; + } else { + params.request_id = -1; + params.expect_response = false; + } + + params.arguments.AppendBoolean(is_javascript); + params.arguments.AppendString(code); + params.arguments.AppendString(script_url); + params.arguments.AppendInteger(script_start_line); + + Send(new CefMsg_Request(MSG_ROUTING_NONE, params)); } void CefFrameHostImpl::SendJavaScript(const std::string& jsCode, @@ -291,17 +469,39 @@ void CefFrameHostImpl::SendJavaScript(const std::string& jsCode, startLine = 1; } - CefRefPtr browser; - int64 frame_id; + SendCode(true, jsCode, scriptUrl, startLine, nullptr); +} - { - base::AutoLock lock_scope(state_lock_); - browser = browser_; - frame_id = (is_main_frame_ ? kMainFrameId : frame_id_); +void CefFrameHostImpl::MaybeSendDidStopLoading() { + auto rfh = GetRenderFrameHost(); + if (!rfh) + return; + + // We only want to notify for the highest-level LocalFrame in this frame's + // renderer process subtree. If this frame has a parent in the same process + // then the notification will be sent via the parent instead. + auto rfh_parent = rfh->GetParent(); + if (rfh_parent && rfh_parent->GetProcess() == rfh->GetProcess()) { + return; } - if (browser.get() && frame_id != kInvalidFrameId) - browser->SendCode(frame_id, true, jsCode, scriptUrl, startLine, NULL); + Send(new CefMsg_DidStopLoading(MSG_ROUTING_NONE)); +} + +bool CefFrameHostImpl::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(CefFrameHostImpl, message) + IPC_MESSAGE_HANDLER(CefHostMsg_FrameAttached, OnAttached) + IPC_MESSAGE_HANDLER(CefHostMsg_FrameFocused, OnFocused) + IPC_MESSAGE_HANDLER(CefHostMsg_DidFinishLoad, OnDidFinishLoad) + IPC_MESSAGE_HANDLER(CefHostMsg_UpdateDraggableRegions, + OnUpdateDraggableRegions) + IPC_MESSAGE_HANDLER(CefHostMsg_Request, OnRequest) + IPC_MESSAGE_HANDLER(CefHostMsg_Response, OnResponse) + IPC_MESSAGE_HANDLER(CefHostMsg_ResponseAck, OnResponseAck) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; } void CefFrameHostImpl::ExecuteJavaScriptWithUserGestureForTests( @@ -320,52 +520,184 @@ void CefFrameHostImpl::ExecuteJavaScriptWithUserGestureForTests( rfh->ExecuteJavaScriptWithUserGestureForTests(javascript); } -content::RenderFrameHost* CefFrameHostImpl::GetRenderFrameHost() { +content::RenderFrameHost* CefFrameHostImpl::GetRenderFrameHost() const { CEF_REQUIRE_UIT(); - - CefRefPtr browser; - int64 frame_id; - - { - base::AutoLock lock_scope(state_lock_); - browser = browser_; - frame_id = (is_main_frame_ ? kMainFrameId : frame_id_); - } - - if (!browser || frame_id == kInvalidFrameId) - return nullptr; - - auto web_contents = browser->web_contents(); - if (!web_contents) - return nullptr; - - if (frame_id == kMainFrameId) - return web_contents->GetMainFrame(); - - return content::RenderFrameHost::FromID( - web_contents->GetRenderViewHost()->GetProcess()->GetID(), frame_id); + return render_frame_host_; } void CefFrameHostImpl::Detach() { - base::AutoLock lock_scope(state_lock_); - browser_ = NULL; -} - -void CefFrameHostImpl::SendCommand( - const std::string& command, - CefRefPtr responseHandler) { - CefRefPtr browser; - int64 frame_id; + CEF_REQUIRE_UIT(); { base::AutoLock lock_scope(state_lock_); - browser = browser_; - // Commands can only be sent to known frame ids. - frame_id = frame_id_; + browser_info_ = nullptr; } - if (browser.get() && frame_id != kInvalidFrameId) - browser->SendCommand(frame_id, command, responseHandler); + // In case we never attached, clean up. + while (!queued_messages_.empty()) { + queued_messages_.pop(); + } + + response_manager_.reset(); + render_frame_host_ = nullptr; +} + +// static +int64_t CefFrameHostImpl::MakeFrameId(const content::RenderFrameHost* host) { + CEF_REQUIRE_UIT(); + auto host_nonconst = const_cast(host); + return MakeFrameId(host_nonconst->GetProcess()->GetID(), + host_nonconst->GetRoutingID()); +} + +// static +int64_t CefFrameHostImpl::MakeFrameId(int32_t render_process_id, + int32_t render_routing_id) { + return frame_util::MakeFrameId(render_process_id, render_routing_id); +} + +// kMainFrameId must be -1 to align with renderer expectations. +const int64_t CefFrameHostImpl::kMainFrameId = -1; +const int64_t CefFrameHostImpl::kFocusedFrameId = -2; +const int64_t CefFrameHostImpl::kUnspecifiedFrameId = -3; +const int64_t CefFrameHostImpl::kInvalidFrameId = -4; + +int64 CefFrameHostImpl::GetFrameId() const { + base::AutoLock lock_scope(state_lock_); + return is_main_frame_ ? kMainFrameId : frame_id_; +} + +CefRefPtr CefFrameHostImpl::GetBrowserHostImpl() const { + base::AutoLock lock_scope(state_lock_); + if (browser_info_) + return browser_info_->browser(); + return nullptr; +} + +void CefFrameHostImpl::OnAttached() { + if (!is_attached_) { + is_attached_ = true; + while (!queued_messages_.empty()) { + Send(queued_messages_.front().release()); + queued_messages_.pop(); + } + } +} + +void CefFrameHostImpl::OnFocused() { + if (!IsFocused()) { + // Calls back to SetFocused(true) after updating state on the previously + // focused frame. + auto browser = GetBrowserHostImpl(); + if (browser) + browser->OnFrameFocused(this); + } +} + +void CefFrameHostImpl::OnDidFinishLoad(const GURL& validated_url, + int http_status_code) { + auto browser = GetBrowserHostImpl(); + if (browser) + browser->OnDidFinishLoad(this, validated_url, http_status_code); +} + +void CefFrameHostImpl::OnUpdateDraggableRegions( + const std::vector& regions) { + auto browser = GetBrowserHostImpl(); + if (!browser) + return; + + CefRefPtr handler; + auto client = browser->GetClient(); + if (client) + handler = client->GetDragHandler(); + if (!handler) + return; + + std::vector draggable_regions; + draggable_regions.reserve(regions.size()); + + std::vector::const_iterator it = regions.begin(); + for (; it != regions.end(); ++it) { + const gfx::Rect& rect(it->bounds); + const CefRect bounds(rect.x(), rect.y(), rect.width(), rect.height()); + draggable_regions.push_back(CefDraggableRegion(bounds, it->draggable)); + } + + handler->OnDraggableRegionsChanged(browser.get(), this, draggable_regions); +} + +void CefFrameHostImpl::OnRequest(const Cef_Request_Params& params) { + CEF_REQUIRE_UIT(); + + bool success = false; + std::string response; + bool expect_response_ack = false; + + if (params.user_initiated) { + auto browser = GetBrowserHostImpl(); + if (browser && browser->client()) { + // Give the user a chance to handle the request. + CefRefPtr message(new CefProcessMessageImpl( + const_cast(¶ms), false, true)); + success = browser->client()->OnProcessMessageReceived( + browser.get(), this, PID_RENDERER, message.get()); + message->Detach(nullptr); + } + } else { + // Invalid request. + NOTREACHED(); + } + + if (params.expect_response) { + DCHECK_GE(params.request_id, 0); + + // Send a response to the renderer. + Cef_Response_Params response_params; + response_params.request_id = params.request_id; + response_params.success = success; + response_params.response = response; + response_params.expect_response_ack = expect_response_ack; + Send(new CefMsg_Response(MSG_ROUTING_NONE, response_params)); + } +} + +void CefFrameHostImpl::OnResponse(const Cef_Response_Params& params) { + CEF_REQUIRE_UIT(); + + response_manager_->RunHandler(params); + if (params.expect_response_ack) + Send(new CefMsg_ResponseAck(MSG_ROUTING_NONE, params.request_id)); +} + +void CefFrameHostImpl::OnResponseAck(int request_id) { + response_manager_->RunAckHandler(request_id); +} + +void CefFrameHostImpl::Send(IPC::Message* message) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::BindOnce(base::IgnoreResult(&CefFrameHostImpl::Send), + this, message)); + return; + } + + if (!render_frame_host_) { + // Either we're a placeholder frame without a renderer representation, or + // we've been detached. + delete message; + return; + } + + if (!is_attached_) { + // Queue messages until we're notified by the renderer that it's ready to + // handle them. + queued_messages_.push(base::WrapUnique(message)); + return; + } + + message->set_routing_id(render_frame_host_->GetRoutingID()); + render_frame_host_->Send(message); } void CefExecuteJavaScriptWithUserGestureForTests(CefRefPtr frame, diff --git a/libcef/browser/frame_host_impl.h b/libcef/browser/frame_host_impl.h index 71469a237..68460bdbe 100644 --- a/libcef/browser/frame_host_impl.h +++ b/libcef/browser/frame_host_impl.h @@ -6,30 +6,50 @@ #define CEF_LIBCEF_BROWSER_FRAME_HOST_IMPL_H_ #pragma once +#include +#include #include #include "include/cef_frame.h" #include "libcef/common/response_manager.h" #include "base/synchronization/lock.h" +#include "ui/base/page_transition_types.h" namespace content { class RenderFrameHost; +struct Referrer; +} // namespace content + +namespace IPC { +class Message; } -class CefBrowserHostImpl; +class GURL; -// Implementation of CefFrame. CefFrameHostImpl objects are owned by the -// CefBrowerHostImpl and will be detached when the browser is notified that the -// associated renderer WebFrame will close. +struct Cef_DraggableRegion_Params; +struct Cef_Request_Params; +struct Cef_Response_Params; +class CefBrowserInfo; +class CefBrowserHostImpl; +struct CefNavigateParams; + +// Implementation of CefFrame. CefFrameHostImpl objects should always be created +// or retrieved via CefBrowerInfo. class CefFrameHostImpl : public CefFrame { public: - CefFrameHostImpl(CefBrowserHostImpl* browser, - int64 frame_id, + // Create a temporary frame. + CefFrameHostImpl(scoped_refptr browser_info, bool is_main_frame, - const CefString& url, - const CefString& name, - int64 parent_frame_id); + int64_t parent_frame_id); + + // Create a frame backed by a RFH and owned by CefBrowserInfo. + CefFrameHostImpl(scoped_refptr browser_info, + content::RenderFrameHost* render_frame_host); + + // Update an existing main frame object. + void SetRenderFrameHost(content::RenderFrameHost* host); + ~CefFrameHostImpl() override; // CefFrame methods @@ -62,48 +82,103 @@ class CefFrameHostImpl : public CefFrame { CefRefPtr CreateURLRequest( CefRefPtr request, CefRefPtr client) override; + void SendProcessMessage(CefProcessId target_process, + CefRefPtr message) override; void SetFocused(bool focused); - void SetAttributes(bool is_main_frame, - const CefString& url, - const CefString& name, - int64 parent_frame_id); + void RefreshAttributes(); - // Avoids unnecessary string type conversions. + // Navigate as specified by the |params| argument. + void Navigate(const CefNavigateParams& params); + + // Load the specified URL. + void LoadURLWithExtras(const std::string& url, + const content::Referrer& referrer, + ui::PageTransition transition, + const std::string& extra_headers); + + // Send a command to the renderer for execution. + void SendCommand(const std::string& command, + CefRefPtr responseHandler); + + // Send code to the renderer for execution. + void SendCode(bool is_javascript, + const std::string& code, + const std::string& script_url, + int script_start_line, + CefRefPtr responseHandler); + + // Send JavaScript to the renderer for execution. void SendJavaScript(const std::string& jsCode, const std::string& scriptUrl, int startLine); + // Called from CefBrowserHostImpl::DidStopLoading. + void MaybeSendDidStopLoading(); + + // Called from CefBrowserHostImpl::OnMessageReceived. + bool OnMessageReceived(const IPC::Message& message); + void ExecuteJavaScriptWithUserGestureForTests(const CefString& javascript); // Returns the RFH associated with this frame. Must be called on the UI // thread. - content::RenderFrameHost* GetRenderFrameHost(); + content::RenderFrameHost* GetRenderFrameHost() const; - // Detach the frame from the browser. + // Owned frame objects will be detached explicitly when the associated + // RenderFrame is deleted. Temporary frame objects will be detached + // implicitly via CefBrowserInfo::browser() returning nullptr. void Detach(); - // kMainFrameId must be -1 to align with renderer expectations. - static const int64 kMainFrameId = -1; - static const int64 kFocusedFrameId = -2; - static const int64 kUnspecifiedFrameId = -3; - static const int64 kInvalidFrameId = -4; + static int64_t MakeFrameId(const content::RenderFrameHost* host); + static int64_t MakeFrameId(int32_t render_process_id, + int32_t render_routing_id); - protected: - void SendCommand(const std::string& command, - CefRefPtr responseHandler); + static const int64_t kMainFrameId; + static const int64_t kFocusedFrameId; + static const int64_t kUnspecifiedFrameId; + static const int64_t kInvalidFrameId; + private: + int64 GetFrameId() const; + CefRefPtr GetBrowserHostImpl() const; + + // OnMessageReceived message handlers. + void OnAttached(); + void OnFocused(); + void OnDidFinishLoad(const GURL& validated_url, int http_status_code); + void OnUpdateDraggableRegions( + const std::vector& regions); + void OnRequest(const Cef_Request_Params& params); + void OnResponse(const Cef_Response_Params& params); + void OnResponseAck(int request_id); + + // Send a message to the RenderFrameHost associated with this frame. + void Send(IPC::Message* message); + + const bool is_main_frame_; + + // The following members may be read/modified from any thread. All access must + // be protected by |state_lock_|. + mutable base::Lock state_lock_; int64 frame_id_; - bool is_main_frame_; - - // Volatile state information. All access must be protected by the state lock. - base::Lock state_lock_; - CefBrowserHostImpl* browser_; + scoped_refptr browser_info_; bool is_focused_; CefString url_; CefString name_; int64 parent_frame_id_; + // The following members are only accessed on the UI thread. + content::RenderFrameHost* render_frame_host_ = nullptr; + + bool is_attached_ = false; + + // Qeueud messages to send when the renderer process attaches. + std::queue> queued_messages_; + + // Manages response registrations. + std::unique_ptr response_manager_; + IMPLEMENT_REFCOUNTING(CefFrameHostImpl); DISALLOW_COPY_AND_ASSIGN(CefFrameHostImpl); }; diff --git a/libcef/browser/navigate_params.cc b/libcef/browser/navigate_params.cc index 0a0eed5f6..be925efaf 100644 --- a/libcef/browser/navigate_params.cc +++ b/libcef/browser/navigate_params.cc @@ -7,12 +7,6 @@ CefNavigateParams::CefNavigateParams(const GURL& a_url, ui::PageTransition a_transition) - : url(a_url), - frame_id(-1), - load_flags(0), - disposition(WindowOpenDisposition::CURRENT_TAB), - transition(a_transition), - is_renderer_initiated(false), - user_gesture(true) {} + : url(a_url), transition(a_transition) {} CefNavigateParams::~CefNavigateParams() {} diff --git a/libcef/browser/navigate_params.h b/libcef/browser/navigate_params.h index c0108de6f..77b1b0d20 100644 --- a/libcef/browser/navigate_params.h +++ b/libcef/browser/navigate_params.h @@ -17,7 +17,7 @@ #include "ui/base/window_open_disposition.h" #include "url/gurl.h" -// Parameters that tell CefBrowserHostImpl::Navigate() what to do. +// Parameters that tell CefFrameHostImpl::Navigate() what to do. struct CefNavigateParams { CefNavigateParams(const GURL& a_url, ui::PageTransition a_transition); ~CefNavigateParams(); @@ -32,9 +32,6 @@ struct CefNavigateParams { GURL url; content::Referrer referrer; - // The frame that the request should be loaded in or -1 to use the main frame. - int64_t frame_id; - // Usually the URL of the document in the top-level window, which may be // checked by the third-party cookie blocking policy. Leaving it empty may // lead to undesired cookie blocking. Third-party cookie blocking can be @@ -46,7 +43,7 @@ struct CefNavigateParams { std::string headers; // net::URLRequest load flags (0 by default). - int load_flags; + int load_flags = 0; // Upload data (may be NULL). scoped_refptr upload_data; @@ -56,20 +53,20 @@ struct CefNavigateParams { // --------------------------------------------------------------------------- // The disposition requested by the navigation source. Default is CURRENT_TAB. - WindowOpenDisposition disposition; + WindowOpenDisposition disposition = WindowOpenDisposition::CURRENT_TAB; // The transition type of the navigation. ui::PageTransition transition; // Whether this navigation was initiated by the renderer process. - bool is_renderer_initiated; + bool is_renderer_initiated = false; // If non-empty, the new tab contents encoding is overriden by this value. std::string override_encoding; // If false then the navigation was not initiated by a user gesture. Default // is true. - bool user_gesture; + bool user_gesture = true; // Refers to a navigation that was parked in the browser in order to be // transferred to another RVH. Only used in case of a redirection of a request diff --git a/libcef/browser/net/net_util.cc b/libcef/browser/net/net_util.cc index b684e406d..758e57fcf 100644 --- a/libcef/browser/net/net_util.cc +++ b/libcef/browser/net/net_util.cc @@ -125,6 +125,64 @@ bool IsInternalRequest(const net::URLRequest* request) { return false; } +CefRefPtr GetBrowserForRequest( + const net::URLRequest* request) { + DCHECK(request); + CEF_REQUIRE_IOT(); + + // When navigating the main frame a new (pre-commit) URLRequest will be + // created before the RenderFrameHost. Consequently we can't rely on + // ResourceRequestInfo::GetRenderFrameForRequest returning a valid frame + // ID. See https://crbug.com/776884 for background. + int render_process_id = -1; + int render_frame_id = MSG_ROUTING_NONE; + if (content::ResourceRequestInfo::GetRenderFrameForRequest( + request, &render_process_id, &render_frame_id) && + render_process_id >= 0 && render_frame_id >= 0) { + return CefBrowserHostImpl::GetBrowserForFrameRoute(render_process_id, + render_frame_id); + } + + content::ResourceRequestInfo* request_info = + content::ResourceRequestInfo::ForRequest(request); + if (request_info) { + return CefBrowserHostImpl::GetBrowserForFrameTreeNode( + request_info->GetFrameTreeNodeId()); + } + + return nullptr; +} + +CefRefPtr GetFrameForRequest( + scoped_refptr browser_info, + const net::URLRequest* request) { + CEF_REQUIRE_IOT(); + content::ResourceRequestInfo* info = + content::ResourceRequestInfo::ForRequest(request); + if (!info) + return nullptr; + + // Try to locate the most reasonable match by ID. + auto frame = + browser_info->GetFrameForFrameTreeNode(info->GetFrameTreeNodeId()); + if (!frame) { + frame = browser_info->GetFrameForRoute(info->GetRouteID(), + info->GetRenderFrameID()); + } + if (frame) + return frame; + + // The IsMainFrame() flag isn't completely reliable, so do this after + // searching by ID. + if (info->IsMainFrame()) + return browser_info->GetMainFrame(); + + // Create a temporary frame object for requests referencing sub-frames that + // don't yet exist. Use the main frame as the parent because we don't know + // the real parent. + return browser_info->CreateTempSubFrame(CefFrameHostImpl::kInvalidFrameId); +} + CefRefPtr GetResourceRequestHandler( const net::URLRequest* request, CefRefPtr& cef_request, @@ -153,15 +211,14 @@ CefRefPtr GetResourceRequestHandler( CefRefPtr resource_request_handler; - CefRefPtr browser = - CefBrowserHostImpl::GetBrowserForRequest(request); + CefRefPtr browser = GetBrowserForRequest(request); CefRefPtr frame; CefRefPtr requestPtr; // Give the browser handler a chance first. if (browser) { // A frame should always exist, or be created. - frame = browser->GetFrameForRequest(request); + frame = GetFrameForRequest(browser->browser_info(), request); DCHECK(frame); CefRefPtr client = browser->GetClient(); diff --git a/libcef/browser/net/net_util.h b/libcef/browser/net/net_util.h index f7f5a0dff..99c6ebb02 100644 --- a/libcef/browser/net/net_util.h +++ b/libcef/browser/net/net_util.h @@ -17,12 +17,24 @@ class URLRequest; class GURL; +class CefBrowserHostImpl; +class CefBrowserInfo; + namespace net_util { // Returns true if |request| is handled internally and should not be exposed via // the CEF API. bool IsInternalRequest(const net::URLRequest* request); +// Returns the browser associated with the specified URLRequest. +CefRefPtr GetBrowserForRequest( + const net::URLRequest* request); + +// Returns the frame associated with the specified URLRequest. +CefRefPtr GetFrameForRequest( + scoped_refptr browser_info, + const net::URLRequest* request); + // Returns the appropriate CefResourceRequestHandler as determined by the // associated CefBrowser/CefRequestHandler and/or CefRequestContextHandler, if // any. The out-params will be nullptr if no handler is returned. Otherwise, diff --git a/libcef/browser/net/network_delegate.cc b/libcef/browser/net/network_delegate.cc index 57f97101a..8900a8628 100644 --- a/libcef/browser/net/network_delegate.cc +++ b/libcef/browser/net/network_delegate.cc @@ -389,13 +389,14 @@ net::NetworkDelegate::AuthRequiredResponse CefNetworkDelegate::OnAuthRequired( return AUTH_REQUIRED_RESPONSE_NO_ACTION; CefRefPtr browser = - CefBrowserHostImpl::GetBrowserForRequest(request); + net_util::GetBrowserForRequest(request); if (browser.get()) { CefRefPtr client = browser->GetClient(); if (client.get()) { CefRefPtr handler = client->GetRequestHandler(); if (handler.get()) { - CefRefPtr frame = browser->GetFrameForRequest(request); + CefRefPtr frame = + net_util::GetFrameForRequest(browser->browser_info(), request); CefRefPtr callbackPtr( new CefAuthCallbackImpl(std::move(callback), credentials)); diff --git a/libcef/browser/net/url_request_manager.cc b/libcef/browser/net/url_request_manager.cc index cbca2bdfe..f2481ddac 100644 --- a/libcef/browser/net/url_request_manager.cc +++ b/libcef/browser/net/url_request_manager.cc @@ -9,6 +9,7 @@ #include "include/cef_scheme.h" #include "libcef/browser/browser_context.h" #include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/net/net_util.h" #include "libcef/browser/net/resource_request_job.h" #include "libcef/browser/net/scheme_handler.h" #include "libcef/browser/thread_util.h" @@ -247,10 +248,11 @@ net::URLRequestJob* CefURLRequestManager::GetRequestJob( GetHandlerFactory(request, scheme); if (factory.get()) { CefRefPtr browser = - CefBrowserHostImpl::GetBrowserForRequest(request); + net_util::GetBrowserForRequest(request); CefRefPtr frame; - if (browser.get()) - frame = browser->GetFrameForRequest(request); + if (browser.get()) { + frame = net_util::GetFrameForRequest(browser->browser_info(), request); + } // Populate the request data. CefRefPtr requestPtr(new CefRequestImpl()); diff --git a/libcef/browser/net_service/resource_request_handler_wrapper.cc b/libcef/browser/net_service/resource_request_handler_wrapper.cc index 25e57a975..1587ec978 100644 --- a/libcef/browser/net_service/resource_request_handler_wrapper.cc +++ b/libcef/browser/net_service/resource_request_handler_wrapper.cc @@ -959,7 +959,6 @@ void InitOnUIThread( web_contents->GetRenderViewHost()->GetProcess()->GetID(); content::RenderFrameHost* frame = nullptr; - bool get_frame_by_route = false; if (request.render_frame_id >= 0) { // TODO(network): Are these main frame checks equivalent? @@ -977,11 +976,9 @@ void InitOnUIThread( render_process_id); } if (!frame) { - // Use the main frame for the CefBrowserHost, but choose a more - // appropriate CefFrame for the route. + // Use the main frame for the CefBrowserHost. frame = web_contents->GetMainFrame(); DCHECK(frame); - get_frame_by_route = true; } } } @@ -992,7 +989,7 @@ void InitOnUIThread( // |frame| may be null for service worker requests. if (frame) { #if DCHECK_IS_ON() - if (frame_tree_node_id >= 0 && !get_frame_by_route) { + if (frame_tree_node_id >= 0) { // Sanity check that we ended up with the expected frame. DCHECK_EQ(frame_tree_node_id, frame->GetFrameTreeNodeId()); } @@ -1000,15 +997,9 @@ void InitOnUIThread( browserPtr = CefBrowserHostImpl::GetBrowserForHost(frame); if (browserPtr) { - if (get_frame_by_route) { - framePtr = - browserPtr->GetFrameForHostRoutingId(request.render_frame_id); - frame_tree_node_id = -1; - } else { - framePtr = browserPtr->GetFrameForHost(frame); - if (frame_tree_node_id < 0) - frame_tree_node_id = frame->GetFrameTreeNodeId(); - } + framePtr = browserPtr->GetFrameForHost(frame); + if (frame_tree_node_id < 0) + frame_tree_node_id = frame->GetFrameTreeNodeId(); DCHECK(framePtr); } } diff --git a/libcef/browser/printing/print_dialog_linux.cc b/libcef/browser/printing/print_dialog_linux.cc index e92a4af9e..5092c6f53 100644 --- a/libcef/browser/printing/print_dialog_linux.cc +++ b/libcef/browser/printing/print_dialog_linux.cc @@ -149,8 +149,9 @@ void CefPrintDialogLinux::OnPrintStart(int render_process_id, if (!handler.get()) return; - CefRefPtr browser = extensions::GetOwnerBrowserForFrame( - render_process_id, render_routing_id, NULL); + CefRefPtr browser = + extensions::GetOwnerBrowserForFrameRoute(render_process_id, + render_routing_id, NULL); if (browser.get()) handler->OnPrintStart(browser.get()); } @@ -158,7 +159,7 @@ void CefPrintDialogLinux::OnPrintStart(int render_process_id, CefPrintDialogLinux::CefPrintDialogLinux(PrintingContextLinux* context) : context_(context) { DCHECK(context_); - browser_ = extensions::GetOwnerBrowserForFrame( + browser_ = extensions::GetOwnerBrowserForFrameRoute( context_->render_process_id(), context_->render_frame_id(), NULL); DCHECK(browser_); } diff --git a/libcef/common/cef_messages.h b/libcef/common/cef_messages.h index 84b90df04..2ed8d4eda 100644 --- a/libcef/common/cef_messages.h +++ b/libcef/common/cef_messages.h @@ -51,9 +51,6 @@ IPC_STRUCT_BEGIN(Cef_Request_Params) // Unique request id to match requests and responses. IPC_STRUCT_MEMBER(int, request_id) - // Unique id of the target frame. -1 if unknown / invalid. - IPC_STRUCT_MEMBER(int64_t, frame_id) - // True if the request is user-initiated instead of internal. IPC_STRUCT_MEMBER(bool, user_initiated) @@ -112,10 +109,6 @@ IPC_STRUCT_BEGIN(CefMsg_LoadRequest_Params) // One of the cef_referrer_policy_t values. IPC_STRUCT_MEMBER(int, referrer_policy) - // Identifies the frame within the RenderView that sent the request. - // -1 if unknown / invalid. - IPC_STRUCT_MEMBER(int64_t, frame_id) - // Usually the URL of the document in the top-level window, which may be // checked by the third-party cookie blocking policy. Leaving it empty may // lead to undesired cookie blocking. Third-party cookie blocking can be @@ -197,20 +190,15 @@ IPC_SYNC_MESSAGE_CONTROL1_1( int /* render_frame_routing_id */, CefProcessHostMsg_GetNewBrowserInfo_Params /* params*/) -// Sent when a frame is identified for the first time. -IPC_MESSAGE_ROUTED3(CefHostMsg_FrameIdentified, - int64_t /* frame_id */, - int64_t /* parent_frame_id */, - base::string16 /* frame_name */) +// Sent by the renderer when the frame can begin receiving messages. +IPC_MESSAGE_ROUTED0(CefHostMsg_FrameAttached) // Sent by the renderer when the frame becomes focused. IPC_MESSAGE_ROUTED0(CefHostMsg_FrameFocused) // Sent when a frame has finished loading. Based on ViewHostMsg_DidFinishLoad. -IPC_MESSAGE_ROUTED4(CefHostMsg_DidFinishLoad, - int64_t /* frame_id */, +IPC_MESSAGE_ROUTED2(CefHostMsg_DidFinishLoad, GURL /* validated_url */, - bool /* is_main_frame */, int /* http_status_code */) // Sent when the renderer has a request for the browser. The browser may respond diff --git a/libcef/common/frame_util.cc b/libcef/common/frame_util.cc new file mode 100644 index 000000000..267132966 --- /dev/null +++ b/libcef/common/frame_util.cc @@ -0,0 +1,14 @@ +// Copyright (c) 2019 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 "libcef/common/frame_util.h" + +namespace frame_util { + +int64_t MakeFrameId(int32_t render_process_id, int32_t render_routing_id) { + return (static_cast(render_process_id) << 32) | + static_cast(render_routing_id); +} + +} // namespace frame_util diff --git a/libcef/common/frame_util.h b/libcef/common/frame_util.h new file mode 100644 index 000000000..7ca5d7b69 --- /dev/null +++ b/libcef/common/frame_util.h @@ -0,0 +1,18 @@ +// Copyright (c) 2019 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. + +#ifndef CEF_LIBCEF_COMMON_FRAME_UTIL_H_ +#define CEF_LIBCEF_COMMON_FRAME_UTIL_H_ + +#include + +namespace frame_util { + +// Returns the frame ID, which is a 64-bit combination of |render_process_id| +// and |render_routing_id|. +int64_t MakeFrameId(int32_t render_process_id, int32_t render_routing_id); + +} // namespace frame_util + +#endif // CEF_LIBCEF_COMMON_FRAME_UTIL_H_ diff --git a/libcef/renderer/browser_impl.cc b/libcef/renderer/browser_impl.cc index 0023520f8..fe622e99b 100644 --- a/libcef/renderer/browser_impl.cc +++ b/libcef/renderer/browser_impl.cc @@ -10,12 +10,8 @@ #include "libcef/common/cef_messages.h" #include "libcef/common/content_client.h" -#include "libcef/common/process_message_impl.h" -#include "libcef/common/request_impl.h" -#include "libcef/common/response_manager.h" #include "libcef/renderer/blink_glue.h" #include "libcef/renderer/content_renderer_client.h" -#include "libcef/renderer/dom_document_impl.h" #include "libcef/renderer/render_frame_util.h" #include "libcef/renderer/thread_util.h" @@ -27,25 +23,15 @@ #include "content/public/renderer/render_view.h" #include "content/renderer/navigation_state.h" #include "third_party/blink/public/platform/web_string.h" -#include "third_party/blink/public/platform/web_url.h" #include "third_party/blink/public/platform/web_url_error.h" #include "third_party/blink/public/platform/web_url_response.h" #include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_frame.h" #include "third_party/blink/public/web/web_frame_content_dumper.h" #include "third_party/blink/public/web/web_local_frame.h" -#include "third_party/blink/public/web/web_node.h" -#include "third_party/blink/public/web/web_script_source.h" #include "third_party/blink/public/web/web_security_policy.h" #include "third_party/blink/public/web/web_view.h" -using blink::WebFrame; -using blink::WebLocalFrame; -using blink::WebScriptSource; -using blink::WebString; -using blink::WebURL; -using blink::WebView; - // CefBrowserImpl static methods. // ----------------------------------------------------------------------------- @@ -108,7 +94,7 @@ void CefBrowserImpl::Reload() { CEF_REQUIRE_RT_RETURN_VOID(); if (render_view()->GetWebView()) { - WebFrame* main_frame = render_view()->GetWebView()->MainFrame(); + blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame(); if (main_frame && main_frame->IsWebLocalFrame()) { main_frame->ToWebLocalFrame()->StartReload( blink::WebFrameLoadType::kReload); @@ -120,7 +106,7 @@ void CefBrowserImpl::ReloadIgnoreCache() { CEF_REQUIRE_RT_RETURN_VOID(); if (render_view()->GetWebView()) { - WebFrame* main_frame = render_view()->GetWebView()->MainFrame(); + blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame(); if (main_frame && main_frame->IsWebLocalFrame()) { main_frame->ToWebLocalFrame()->StartReload( blink::WebFrameLoadType::kReloadBypassingCache); @@ -132,7 +118,7 @@ void CefBrowserImpl::StopLoad() { CEF_REQUIRE_RT_RETURN_VOID(); if (render_view()->GetWebView()) { - WebFrame* main_frame = render_view()->GetWebView()->MainFrame(); + blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame(); if (main_frame && main_frame->IsWebLocalFrame()) { main_frame->ToWebLocalFrame()->StopLoading(); } @@ -162,7 +148,7 @@ bool CefBrowserImpl::HasDocument() { CEF_REQUIRE_RT_RETURN(false); if (render_view()->GetWebView()) { - WebFrame* main_frame = render_view()->GetWebView()->MainFrame(); + blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame(); if (main_frame && main_frame->IsWebLocalFrame()) { return !main_frame->ToWebLocalFrame()->GetDocument().IsNull(); } @@ -174,7 +160,7 @@ CefRefPtr CefBrowserImpl::GetMainFrame() { CEF_REQUIRE_RT_RETURN(nullptr); if (render_view()->GetWebView()) { - WebFrame* main_frame = render_view()->GetWebView()->MainFrame(); + blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame(); if (main_frame && main_frame->IsWebLocalFrame()) { return GetWebFrameImpl(main_frame->ToWebLocalFrame()).get(); } @@ -206,13 +192,13 @@ CefRefPtr CefBrowserImpl::GetFrame(const CefString& name) { const blink::WebString& frame_name = blink::WebString::FromUTF16(name.ToString16()); // Search by assigned frame name (Frame::name). - WebFrame* frame = web_view->MainFrame(); + blink::WebFrame* frame = web_view->MainFrame(); if (frame && frame->IsWebLocalFrame()) frame = frame->ToWebLocalFrame()->FindFrameByName(frame_name); if (!frame) { // Search by unique frame name (Frame::uniqueName). const std::string& searchname = name; - for (WebFrame* cur_frame = web_view->MainFrame(); cur_frame; + for (blink::WebFrame* cur_frame = web_view->MainFrame(); cur_frame; cur_frame = cur_frame->TraverseNext()) { if (cur_frame->IsWebLocalFrame() && render_frame_util::GetName(cur_frame->ToWebLocalFrame()) == @@ -235,8 +221,8 @@ size_t CefBrowserImpl::GetFrameCount() { int count = 0; if (render_view()->GetWebView()) { - for (WebFrame* frame = render_view()->GetWebView()->MainFrame(); frame; - frame = frame->TraverseNext()) { + for (blink::WebFrame* frame = render_view()->GetWebView()->MainFrame(); + frame; frame = frame->TraverseNext()) { count++; } } @@ -251,8 +237,8 @@ void CefBrowserImpl::GetFrameIdentifiers(std::vector& identifiers) { identifiers.clear(); if (render_view()->GetWebView()) { - for (WebFrame* frame = render_view()->GetWebView()->MainFrame(); frame; - frame = frame->TraverseNext()) { + for (blink::WebFrame* frame = render_view()->GetWebView()->MainFrame(); + frame; frame = frame->TraverseNext()) { if (frame->IsWebLocalFrame()) identifiers.push_back( render_frame_util::GetIdentifier(frame->ToWebLocalFrame())); @@ -267,27 +253,14 @@ void CefBrowserImpl::GetFrameNames(std::vector& names) { names.clear(); if (render_view()->GetWebView()) { - for (WebFrame* frame = render_view()->GetWebView()->MainFrame(); frame; - frame = frame->TraverseNext()) { + for (blink::WebFrame* frame = render_view()->GetWebView()->MainFrame(); + frame; frame = frame->TraverseNext()) { if (frame->IsWebLocalFrame()) names.push_back(render_frame_util::GetName(frame->ToWebLocalFrame())); } } } -bool CefBrowserImpl::SendProcessMessage(CefProcessId target_process, - CefRefPtr message) { - Cef_Request_Params params; - CefProcessMessageImpl* impl = - static_cast(message.get()); - if (impl->CopyTo(params)) { - return SendProcessMessage(target_process, params.name, ¶ms.arguments, - true); - } - - return false; -} - // CefBrowserImpl public methods. // ----------------------------------------------------------------------------- @@ -298,44 +271,10 @@ CefBrowserImpl::CefBrowserImpl(content::RenderView* render_view, : content::RenderViewObserver(render_view), browser_id_(browser_id), is_popup_(is_popup), - is_windowless_(is_windowless) { - response_manager_.reset(new CefResponseManager); -} + is_windowless_(is_windowless) {} CefBrowserImpl::~CefBrowserImpl() {} -void CefBrowserImpl::LoadRequest(const CefMsg_LoadRequest_Params& params) { - CefRefPtr framePtr = GetWebFrameImpl(params.frame_id); - if (!framePtr.get()) - return; - - WebLocalFrame* web_frame = framePtr->web_frame(); - - blink::WebURLRequest request; - CefRequestImpl::Get(params, request); - - web_frame->StartNavigation(request); -} - -bool CefBrowserImpl::SendProcessMessage(CefProcessId target_process, - const std::string& name, - base::ListValue* arguments, - bool user_initiated) { - DCHECK_EQ(PID_BROWSER, target_process); - DCHECK(!name.empty()); - - Cef_Request_Params params; - params.name = name; - if (arguments) - params.arguments.Swap(arguments); - params.frame_id = -1; - params.user_initiated = user_initiated; - params.request_id = -1; - params.expect_response = false; - - return Send(new CefHostMsg_Request(routing_id(), params)); -} - CefRefPtr CefBrowserImpl::GetWebFrameImpl( blink::WebLocalFrame* frame) { DCHECK(frame); @@ -349,25 +288,13 @@ CefRefPtr CefBrowserImpl::GetWebFrameImpl( CefRefPtr framePtr(new CefFrameImpl(this, frame, frame_id)); frames_.insert(std::make_pair(frame_id, framePtr)); - const int64_t parent_id = frame->Parent() == NULL - ? blink_glue::kInvalidFrameId - : frame->Parent()->IsWebLocalFrame() - ? render_frame_util::GetIdentifier( - frame->Parent()->ToWebLocalFrame()) - : blink_glue::kInvalidFrameId; - const base::string16& name = - base::UTF8ToUTF16(render_frame_util::GetName(frame)); - - // Notify the browser that the frame has been identified. - Send(new CefHostMsg_FrameIdentified(routing_id(), frame_id, parent_id, name)); - return framePtr; } CefRefPtr CefBrowserImpl::GetWebFrameImpl(int64_t frame_id) { if (frame_id == blink_glue::kInvalidFrameId) { if (render_view()->GetWebView()) { - WebFrame* main_frame = render_view()->GetWebView()->MainFrame(); + blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame(); if (main_frame && main_frame->IsWebLocalFrame()) { return GetWebFrameImpl(main_frame->ToWebLocalFrame()); } @@ -382,8 +309,8 @@ CefRefPtr CefBrowserImpl::GetWebFrameImpl(int64_t frame_id) { if (render_view()->GetWebView()) { // Check if the frame exists but we don't know about it yet. - for (WebFrame* frame = render_view()->GetWebView()->MainFrame(); frame; - frame = frame->TraverseNext()) { + for (blink::WebFrame* frame = render_view()->GetWebView()->MainFrame(); + frame; frame = frame->TraverseNext()) { if (frame->IsWebLocalFrame() && render_frame_util::GetIdentifier(frame->ToWebLocalFrame()) == frame_id) { @@ -425,19 +352,9 @@ void CefBrowserImpl::OnDestruct() { handler->OnBrowserDestroyed(this); } - response_manager_.reset(); - CefContentRendererClient::Get()->OnBrowserDestroyed(this); } -void CefBrowserImpl::DidFinishLoad(blink::WebLocalFrame* frame) { - blink::WebDocumentLoader* dl = frame->GetDocumentLoader(); - Send(new CefHostMsg_DidFinishLoad( - routing_id(), render_frame_util::GetIdentifier(frame), dl->GetUrl(), - !frame->Parent(), dl->GetResponse().HttpStatusCode())); - OnLoadEnd(frame); -} - void CefBrowserImpl::DidFailProvisionalLoad(blink::WebLocalFrame* frame, const blink::WebURLError& error) { OnLoadError(frame, error); @@ -451,14 +368,11 @@ void CefBrowserImpl::DidCommitProvisionalLoad(blink::WebLocalFrame* frame, OnLoadStart(frame); } -void CefBrowserImpl::FrameDetached(WebLocalFrame* frame) { - int64_t frame_id = render_frame_util::GetIdentifier(frame); - +void CefBrowserImpl::FrameDetached(int64_t frame_id) { if (!frames_.empty()) { // Remove the frame from the map. FrameMap::iterator it = frames_.find(frame_id); if (it != frames_.end()) { - it->second->Detach(); frames_.erase(it); } } @@ -471,192 +385,6 @@ void CefBrowserImpl::FrameDetached(WebLocalFrame* frame) { } } -void CefBrowserImpl::FocusedNodeChanged(const blink::WebNode& node) { - // Notify the handler. - CefRefPtr app = CefContentClient::Get()->application(); - if (app.get()) { - CefRefPtr handler = app->GetRenderProcessHandler(); - if (handler.get()) { - if (node.IsNull()) { - handler->OnFocusedNodeChanged(this, GetFocusedFrame(), NULL); - } else { - const blink::WebDocument& document = node.GetDocument(); - if (!document.IsNull()) { - blink::WebFrame* frame = document.GetFrame(); - if (!frame->IsWebLocalFrame()) - return; - CefRefPtr documentImpl = - new CefDOMDocumentImpl(this, frame->ToWebLocalFrame()); - handler->OnFocusedNodeChanged( - this, GetWebFrameImpl(frame->ToWebLocalFrame()).get(), - documentImpl->GetOrCreateNode(node)); - documentImpl->Detach(); - } - } - } - } -} - -// Based on ExtensionHelper::DraggableRegionsChanged. -void CefBrowserImpl::DraggableRegionsChanged(blink::WebLocalFrame* frame) { - blink::WebVector webregions = - frame->GetDocument().DraggableRegions(); - std::vector regions; - for (size_t i = 0; i < webregions.size(); ++i) { - Cef_DraggableRegion_Params region; - render_view()->ConvertViewportToWindowViaWidget(&webregions[i].bounds); - region.bounds = webregions[i].bounds; - region.draggable = webregions[i].draggable; - regions.push_back(region); - } - Send(new CefHostMsg_UpdateDraggableRegions(routing_id(), regions)); -} - -bool CefBrowserImpl::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(CefBrowserImpl, message) - IPC_MESSAGE_HANDLER(CefMsg_Request, OnRequest) - IPC_MESSAGE_HANDLER(CefMsg_Response, OnResponse) - IPC_MESSAGE_HANDLER(CefMsg_ResponseAck, OnResponseAck) - IPC_MESSAGE_HANDLER(CefMsg_LoadRequest, LoadRequest) - IPC_MESSAGE_HANDLER(CefMsg_DidStopLoading, OnDidStopLoading) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - -// RenderViewObserver::OnMessageReceived message handlers. -// ----------------------------------------------------------------------------- - -void CefBrowserImpl::OnRequest(const Cef_Request_Params& params) { - bool success = false; - std::string response; - bool expect_response_ack = false; - - TRACE_EVENT2("cef", "CefBrowserImpl::OnRequest", "request_id", - params.request_id, "expect_response", - params.expect_response ? 1 : 0); - - if (params.user_initiated) { - // Give the user a chance to handle the request. - CefRefPtr app = CefContentClient::Get()->application(); - if (app.get()) { - CefRefPtr handler = - app->GetRenderProcessHandler(); - if (handler.get()) { - CefRefPtr message(new CefProcessMessageImpl( - const_cast(¶ms), false, true)); - success = - handler->OnProcessMessageReceived(this, PID_BROWSER, message.get()); - message->Detach(nullptr); - } - } - } else if (params.name == "execute-code") { - // Execute code. - CefRefPtr framePtr = GetWebFrameImpl(params.frame_id); - if (framePtr.get()) { - WebLocalFrame* web_frame = framePtr->web_frame(); - if (web_frame) { - DCHECK_EQ(params.arguments.GetSize(), (size_t)4); - - bool is_javascript = false; - std::string code, script_url; - int script_start_line = 0; - - params.arguments.GetBoolean(0, &is_javascript); - params.arguments.GetString(1, &code); - DCHECK(!code.empty()); - params.arguments.GetString(2, &script_url); - params.arguments.GetInteger(3, &script_start_line); - DCHECK_GE(script_start_line, 0); - - if (is_javascript) { - web_frame->ExecuteScript( - WebScriptSource(blink::WebString::FromUTF8(code), - GURL(script_url), script_start_line)); - success = true; - } else { - // TODO(cef): implement support for CSS code. - NOTIMPLEMENTED(); - } - } - } - } else if (params.name == "execute-command") { - // Execute command. - CefRefPtr framePtr = GetWebFrameImpl(params.frame_id); - if (framePtr.get()) { - WebLocalFrame* web_frame = framePtr->web_frame(); - if (web_frame) { - DCHECK_EQ(params.arguments.GetSize(), (size_t)1); - - std::string command; - - params.arguments.GetString(0, &command); - DCHECK(!command.empty()); - - if (base::LowerCaseEqualsASCII(command, "getsource")) { - response = - blink::WebFrameContentDumper::DumpAsMarkup(web_frame).Utf8(); - success = true; - } else if (base::LowerCaseEqualsASCII(command, "gettext")) { - response = blink_glue::DumpDocumentText(web_frame); - success = true; - } else if (web_frame->ExecuteCommand( - blink::WebString::FromUTF8(command))) { - success = true; - } - } - } - } else if (params.name == "load-string") { - // Load a string. - CefRefPtr framePtr = GetWebFrameImpl(params.frame_id); - if (framePtr.get()) { - WebLocalFrame* web_frame = framePtr->web_frame(); - if (web_frame) { - DCHECK_EQ(params.arguments.GetSize(), (size_t)2); - - std::string string, url; - - params.arguments.GetString(0, &string); - params.arguments.GetString(1, &url); - - content::RenderFrame::FromWebFrame(web_frame)->LoadHTMLString( - string, GURL(url), "UTF-8", GURL(), - false /* replace_current_item */); - } - } - } else { - // Invalid request. - NOTREACHED(); - } - - if (params.expect_response) { - DCHECK_GE(params.request_id, 0); - - // Send a response to the browser. - Cef_Response_Params response_params; - response_params.request_id = params.request_id; - response_params.success = success; - response_params.response = response; - response_params.expect_response_ack = expect_response_ack; - Send(new CefHostMsg_Response(routing_id(), response_params)); - } -} - -void CefBrowserImpl::OnResponse(const Cef_Response_Params& params) { - response_manager_->RunHandler(params); - if (params.expect_response_ack) - Send(new CefHostMsg_ResponseAck(routing_id(), params.request_id)); -} - -void CefBrowserImpl::OnResponseAck(int request_id) { - response_manager_->RunAckHandler(request_id); -} - -void CefBrowserImpl::OnDidStopLoading() { - OnLoadingStateChange(false); -} - void CefBrowserImpl::OnLoadingStateChange(bool isLoading) { CefRefPtr app = CefContentClient::Get()->application(); if (app.get()) { @@ -664,12 +392,22 @@ void CefBrowserImpl::OnLoadingStateChange(bool isLoading) { if (handler.get()) { CefRefPtr load_handler = handler->GetLoadHandler(); if (load_handler.get()) { - WebView* web_view = render_view()->GetWebView(); + blink::WebView* web_view = render_view()->GetWebView(); const bool canGoBack = blink_glue::CanGoBack(web_view); const bool canGoForward = blink_glue::CanGoForward(web_view); + // Don't call OnLoadingStateChange multiple times with the same status. + // This can occur in cases where there are multiple highest-level + // LocalFrames in-process for the same browser. + if (last_loading_state_ && + last_loading_state_->IsMatch(isLoading, canGoBack, canGoForward)) { + return; + } + load_handler->OnLoadingStateChange(this, isLoading, canGoBack, canGoForward); + last_loading_state_.reset( + new LoadingState(isLoading, canGoBack, canGoForward)); } } } @@ -689,22 +427,6 @@ void CefBrowserImpl::OnLoadStart(blink::WebLocalFrame* frame) { } } -void CefBrowserImpl::OnLoadEnd(blink::WebLocalFrame* frame) { - CefRefPtr app = CefContentClient::Get()->application(); - if (app.get()) { - CefRefPtr handler = app->GetRenderProcessHandler(); - if (handler.get()) { - CefRefPtr load_handler = handler->GetLoadHandler(); - if (load_handler.get()) { - CefRefPtr cef_frame = GetWebFrameImpl(frame); - int httpStatusCode = - frame->GetDocumentLoader()->GetResponse().HttpStatusCode(); - load_handler->OnLoadEnd(this, cef_frame.get(), httpStatusCode); - } - } - } -} - void CefBrowserImpl::OnLoadError(blink::WebLocalFrame* frame, const blink::WebURLError& error) { CefRefPtr app = CefContentClient::Get()->application(); diff --git a/libcef/renderer/browser_impl.h b/libcef/renderer/browser_impl.h index b5a849b88..140fe12d1 100644 --- a/libcef/renderer/browser_impl.h +++ b/libcef/renderer/browser_impl.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -20,17 +21,6 @@ #include "content/public/renderer/render_view_observer.h" -class GURL; -struct CefMsg_LoadRequest_Params; -struct Cef_Request_Params; -struct Cef_Response_Params; -class CefContentRendererClient; -class CefResponseManager; - -namespace base { -class ListValue; -} - namespace blink { class WebFrame; class WebNode; @@ -40,11 +30,7 @@ class WebNode; // between RenderView on the renderer side and RenderViewHost on the browser // side. // -// RenderViewObserver: Interface for observing RenderView notifications and IPC -// messages. IPC messages received by the RenderView will be forwarded to this -// RenderViewObserver implementation. IPC messages sent using -// RenderViewObserver::Send() will be forwarded to the RenderView. Use -// RenderViewObserver::routing_id() when sending IPC messages. +// RenderViewObserver: Interface for observing RenderView notifications. class CefBrowserImpl : public CefBrowser, public content::RenderViewObserver { public: // Returns the browser associated with the specified RenderView. @@ -74,8 +60,6 @@ class CefBrowserImpl : public CefBrowser, public content::RenderViewObserver { size_t GetFrameCount() override; void GetFrameIdentifiers(std::vector& identifiers) override; void GetFrameNames(std::vector& names) override; - bool SendProcessMessage(CefProcessId target_process, - CefRefPtr message) override; CefBrowserImpl(content::RenderView* render_view, int browser_id, @@ -83,14 +67,6 @@ class CefBrowserImpl : public CefBrowser, public content::RenderViewObserver { bool is_windowless); ~CefBrowserImpl() override; - void LoadRequest(const CefMsg_LoadRequest_Params& params); - - // Avoids unnecessary string type conversions. - bool SendProcessMessage(CefProcessId target_process, - const std::string& name, - base::ListValue* arguments, - bool user_initiated); - // Returns the matching CefFrameImpl reference or creates a new one. CefRefPtr GetWebFrameImpl(blink::WebLocalFrame* frame); CefRefPtr GetWebFrameImpl(int64_t frame_id); @@ -111,24 +87,13 @@ class CefBrowserImpl : public CefBrowser, public content::RenderViewObserver { const blink::WebURLError& error) override; void DidCommitProvisionalLoad(blink::WebLocalFrame* frame, bool is_new_navigation) override; - bool OnMessageReceived(const IPC::Message& message) override; - // Forwarded from CefRenderFrameObserver. - void DidFinishLoad(blink::WebLocalFrame* frame); - void FrameDetached(blink::WebLocalFrame* frame); - void FocusedNodeChanged(const blink::WebNode& node); - void DraggableRegionsChanged(blink::WebLocalFrame* frame); - - private: - // RenderViewObserver::OnMessageReceived message handlers. - void OnRequest(const Cef_Request_Params& params); - void OnResponse(const Cef_Response_Params& params); - void OnResponseAck(int request_id); - void OnDidStopLoading(); + void FrameDetached(int64_t frame_id); void OnLoadingStateChange(bool isLoading); + + private: void OnLoadStart(blink::WebLocalFrame* frame); - void OnLoadEnd(blink::WebLocalFrame* frame); void OnLoadError(blink::WebLocalFrame* frame, const blink::WebURLError& error); @@ -148,8 +113,22 @@ class CefBrowserImpl : public CefBrowser, public content::RenderViewObserver { typedef std::map> FrameObjectMap; FrameObjectMap frame_objects_; - // Manages response registrations. - std::unique_ptr response_manager_; + struct LoadingState { + LoadingState(bool is_loading, bool can_go_back, bool can_go_forward) + : is_loading_(is_loading), + can_go_back_(can_go_back), + can_go_forward_(can_go_forward) {} + + bool IsMatch(bool is_loading, bool can_go_back, bool can_go_forward) const { + return is_loading_ == is_loading && can_go_back_ == can_go_back && + can_go_forward_ == can_go_forward; + } + + bool is_loading_; + bool can_go_back_; + bool can_go_forward_; + }; + std::unique_ptr last_loading_state_; IMPLEMENT_REFCOUNTING(CefBrowserImpl); DISALLOW_COPY_AND_ASSIGN(CefBrowserImpl); diff --git a/libcef/renderer/content_renderer_client.cc b/libcef/renderer/content_renderer_client.cc index 634d49efa..a92a7b565 100644 --- a/libcef/renderer/content_renderer_client.cc +++ b/libcef/renderer/content_renderer_client.cc @@ -476,14 +476,20 @@ void CefContentRendererClient::RenderFrameCreated( new SpellCheckProvider(render_frame, spellcheck_.get(), this); } - BrowserCreated(render_frame->GetRenderView(), render_frame); + auto browser = + MaybeCreateBrowser(render_frame->GetRenderView(), render_frame); + if (browser) { + // Attach the frame to the observer for message routing purposes. + render_frame_observer->AttachFrame( + browser->GetWebFrameImpl(render_frame->GetWebFrame()).get()); + } } void CefContentRendererClient::RenderViewCreated( content::RenderView* render_view) { new CefPrerendererClient(render_view); - BrowserCreated(render_view, render_view->GetMainRenderFrame()); + MaybeCreateBrowser(render_view, render_view->GetMainRenderFrame()); } bool CefContentRendererClient::OverrideCreatePlugin( @@ -637,16 +643,20 @@ void CefContentRendererClient::WillDestroyCurrentMessageLoop() { single_process_cleanup_complete_ = true; } -void CefContentRendererClient::BrowserCreated( +CefRefPtr CefContentRendererClient::MaybeCreateBrowser( content::RenderView* render_view, content::RenderFrame* render_frame) { if (!render_view || !render_frame) - return; + return nullptr; // Don't create another browser or guest view object if one already exists for // the view. - if (GetBrowserForView(render_view).get() || HasGuestViewForView(render_view)) - return; + auto browser = GetBrowserForView(render_view); + if (browser) + return browser; + + if (HasGuestViewForView(render_view)) + return nullptr; const int render_frame_routing_id = render_frame->GetRoutingID(); @@ -657,14 +667,14 @@ void CefContentRendererClient::BrowserCreated( render_frame_routing_id, ¶ms)); if (params.browser_id == 0) { // The popup may have been canceled during creation. - return; + return nullptr; } if (params.is_guest_view) { // Don't create a CefBrowser for guest views. guest_views_.insert(std::make_pair( render_view, std::make_unique(render_view))); - return; + return nullptr; } #if defined(OS_MACOSX) @@ -676,8 +686,8 @@ void CefContentRendererClient::BrowserCreated( !params.is_windowless); #endif - CefRefPtr browser = new CefBrowserImpl( - render_view, params.browser_id, params.is_popup, params.is_windowless); + browser = new CefBrowserImpl(render_view, params.browser_id, params.is_popup, + params.is_windowless); browsers_.insert(std::make_pair(render_view, browser)); // Notify the render process handler. @@ -692,6 +702,8 @@ void CefContentRendererClient::BrowserCreated( dictValuePtr->Detach(NULL); } } + + return browser; } void CefContentRendererClient::RunSingleProcessCleanupOnUIThread() { diff --git a/libcef/renderer/content_renderer_client.h b/libcef/renderer/content_renderer_client.h index 5430bea6c..1c3a0253e 100644 --- a/libcef/renderer/content_renderer_client.h +++ b/libcef/renderer/content_renderer_client.h @@ -152,8 +152,11 @@ class CefContentRendererClient void WillDestroyCurrentMessageLoop() override; private: - void BrowserCreated(content::RenderView* render_view, - content::RenderFrame* render_frame); + // Maybe create a new browser object, return the existing one, or return + // nullptr for guest views. + CefRefPtr MaybeCreateBrowser( + content::RenderView* render_view, + content::RenderFrame* render_frame); // Perform cleanup work for single-process mode. void RunSingleProcessCleanupOnUIThread(); diff --git a/libcef/renderer/frame_impl.cc b/libcef/renderer/frame_impl.cc index 95d8eba4a..548271a54 100644 --- a/libcef/renderer/frame_impl.cc +++ b/libcef/renderer/frame_impl.cc @@ -18,8 +18,11 @@ #endif #include "libcef/common/cef_messages.h" +#include "libcef/common/content_client.h" #include "libcef/common/net/http_header_utils.h" +#include "libcef/common/process_message_impl.h" #include "libcef/common/request_impl.h" +#include "libcef/common/response_manager.h" #include "libcef/renderer/blink_glue.h" #include "libcef/renderer/browser_impl.h" #include "libcef/renderer/dom_document_impl.h" @@ -28,6 +31,8 @@ #include "libcef/renderer/thread_util.h" #include "libcef/renderer/v8_impl.h" +#include "base/strings/utf_string_conversions.h" +#include "content/public/renderer/render_view.h" #include "content/renderer/render_frame_impl.h" #include "third_party/blink/public/platform/web_data.h" #include "third_party/blink/public/platform/web_string.h" @@ -41,12 +46,13 @@ #include "third_party/blink/public/web/web_script_source.h" #include "third_party/blink/public/web/web_view.h" -using blink::WebString; - CefFrameImpl::CefFrameImpl(CefBrowserImpl* browser, blink::WebLocalFrame* frame, int64_t frame_id) - : browser_(browser), frame_(frame), frame_id_(frame_id) {} + : browser_(browser), + frame_(frame), + frame_id_(frame_id), + response_manager_(new CefResponseManager) {} CefFrameImpl::~CefFrameImpl() {} @@ -99,7 +105,6 @@ void CefFrameImpl::GetSource(CefRefPtr visitor) { void CefFrameImpl::GetText(CefRefPtr visitor) { CEF_REQUIRE_RT_RETURN_VOID(); - if (frame_) { const CefString& content = blink_glue::DumpDocumentText(frame_); visitor->Visit(content); @@ -109,13 +114,12 @@ void CefFrameImpl::GetText(CefRefPtr visitor) { void CefFrameImpl::LoadRequest(CefRefPtr request) { CEF_REQUIRE_RT_RETURN_VOID(); - if (!browser_) + if (!frame_) return; CefMsg_LoadRequest_Params params; params.url = GURL(std::string(request->GetURL())); params.method = request->GetMethod(); - params.frame_id = frame_id_; params.site_for_cookies = GURL(std::string(request->GetFirstPartyForCookies())); @@ -133,21 +137,20 @@ void CefFrameImpl::LoadRequest(CefRefPtr request) { params.load_flags = request->GetFlags(); - browser_->LoadRequest(params); + OnLoadRequest(params); } void CefFrameImpl::LoadURL(const CefString& url) { CEF_REQUIRE_RT_RETURN_VOID(); - if (!browser_) + if (!frame_) return; CefMsg_LoadRequest_Params params; params.url = GURL(url.ToString()); params.method = "GET"; - params.frame_id = frame_id_; - browser_->LoadRequest(params); + OnLoadRequest(params); } void CefFrameImpl::LoadString(const CefString& string, const CefString& url) { @@ -174,7 +177,7 @@ void CefFrameImpl::ExecuteJavaScript(const CefString& jsCode, if (frame_) { GURL gurl = GURL(scriptUrl.ToString()); frame_->ExecuteScript(blink::WebScriptSource( - WebString::FromUTF16(jsCode.ToString16()), gurl, startLine)); + blink::WebString::FromUTF16(jsCode.ToString16()), gurl, startLine)); } } @@ -291,6 +294,16 @@ CefRefPtr CefFrameImpl::CreateURLRequest( return NULL; } +void CefFrameImpl::SendProcessMessage(CefProcessId target_process, + CefRefPtr message) { + Cef_Request_Params params; + CefProcessMessageImpl* impl = + static_cast(message.get()); + if (impl->CopyTo(params)) { + SendProcessMessage(target_process, params.name, ¶ms.arguments, true); + } +} + blink::WebURLLoaderFactory* CefFrameImpl::GetURLLoaderFactory() { CEF_REQUIRE_RT(); if (!url_loader_factory_ && frame_) { @@ -302,16 +315,234 @@ blink::WebURLLoaderFactory* CefFrameImpl::GetURLLoaderFactory() { return url_loader_factory_.get(); } -void CefFrameImpl::Detach() { - browser_ = NULL; - frame_ = NULL; +void CefFrameImpl::OnAttached() { + Send(new CefHostMsg_FrameAttached(MSG_ROUTING_NONE)); +} + +bool CefFrameImpl::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(CefFrameImpl, message) + IPC_MESSAGE_HANDLER(CefMsg_Request, OnRequest) + IPC_MESSAGE_HANDLER(CefMsg_Response, OnResponse) + IPC_MESSAGE_HANDLER(CefMsg_ResponseAck, OnResponseAck) + IPC_MESSAGE_HANDLER(CefMsg_LoadRequest, OnLoadRequest) + IPC_MESSAGE_HANDLER(CefMsg_DidStopLoading, OnDidStopLoading) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void CefFrameImpl::OnDidFinishLoad() { + blink::WebDocumentLoader* dl = frame_->GetDocumentLoader(); + const int http_status_code = dl->GetResponse().HttpStatusCode(); + Send(new CefHostMsg_DidFinishLoad(MSG_ROUTING_NONE, dl->GetUrl(), + http_status_code)); + + CefRefPtr app = CefContentClient::Get()->application(); + if (app) { + CefRefPtr handler = app->GetRenderProcessHandler(); + if (handler) { + CefRefPtr load_handler = handler->GetLoadHandler(); + if (load_handler) { + load_handler->OnLoadEnd(browser_, this, http_status_code); + } + } + } +} + +void CefFrameImpl::OnFocused() { + Send(new CefHostMsg_FrameFocused(MSG_ROUTING_NONE)); +} + +void CefFrameImpl::OnDraggableRegionsChanged() { + blink::WebVector webregions = + frame_->GetDocument().DraggableRegions(); + std::vector regions; + for (size_t i = 0; i < webregions.size(); ++i) { + Cef_DraggableRegion_Params region; + browser_->render_view()->ConvertViewportToWindowViaWidget( + &webregions[i].bounds); + region.bounds = webregions[i].bounds; + region.draggable = webregions[i].draggable; + regions.push_back(region); + } + Send(new CefHostMsg_UpdateDraggableRegions(MSG_ROUTING_NONE, regions)); +} + +void CefFrameImpl::OnDetached() { + // The browser may hold the last reference to |this|. Take a reference here to + // keep |this| alive until after this method returns. + CefRefPtr self = this; + + browser_->FrameDetached(frame_id_); + + browser_ = nullptr; + frame_ = nullptr; url_loader_factory_.reset(); + response_manager_.reset(); } void CefFrameImpl::ExecuteCommand(const std::string& command) { CEF_REQUIRE_RT_RETURN_VOID(); if (frame_) - frame_->ExecuteCommand(WebString::FromUTF8(command)); + frame_->ExecuteCommand(blink::WebString::FromUTF8(command)); +} + +void CefFrameImpl::SendProcessMessage(CefProcessId target_process, + const std::string& name, + base::ListValue* arguments, + bool user_initiated) { + DCHECK_EQ(PID_BROWSER, target_process); + DCHECK(!name.empty()); + + if (!frame_) + return; + + Cef_Request_Params params; + params.name = name; + if (arguments) + params.arguments.Swap(arguments); + params.user_initiated = user_initiated; + params.request_id = -1; + params.expect_response = false; + + Send(new CefHostMsg_Request(MSG_ROUTING_NONE, params)); +} + +void CefFrameImpl::Send(IPC::Message* message) { + if (!frame_) { + delete message; + return; + } + + auto render_frame = content::RenderFrame::FromWebFrame(frame_); + message->set_routing_id(render_frame->GetRoutingID()); + render_frame->Send(message); +} + +void CefFrameImpl::OnRequest(const Cef_Request_Params& params) { + DCHECK(browser_); + DCHECK(frame_); + + bool success = false; + std::string response; + bool expect_response_ack = false; + + TRACE_EVENT2("cef", "CefBrowserImpl::OnRequest", "request_id", + params.request_id, "expect_response", + params.expect_response ? 1 : 0); + + if (params.user_initiated) { + // Give the user a chance to handle the request. + CefRefPtr app = CefContentClient::Get()->application(); + if (app.get()) { + CefRefPtr handler = + app->GetRenderProcessHandler(); + if (handler.get()) { + CefRefPtr message(new CefProcessMessageImpl( + const_cast(¶ms), false, true)); + success = handler->OnProcessMessageReceived(browser_, this, PID_BROWSER, + message.get()); + message->Detach(nullptr); + } + } + } else if (params.name == "execute-code") { + // Execute code. + DCHECK_EQ(params.arguments.GetSize(), (size_t)4); + + bool is_javascript = false; + std::string code, script_url; + int script_start_line = 0; + + params.arguments.GetBoolean(0, &is_javascript); + params.arguments.GetString(1, &code); + DCHECK(!code.empty()); + params.arguments.GetString(2, &script_url); + params.arguments.GetInteger(3, &script_start_line); + DCHECK_GE(script_start_line, 0); + + if (is_javascript) { + frame_->ExecuteScript( + blink::WebScriptSource(blink::WebString::FromUTF8(code), + GURL(script_url), script_start_line)); + success = true; + } else { + // TODO(cef): implement support for CSS code. + NOTIMPLEMENTED(); + } + } else if (params.name == "execute-command") { + // Execute command. + DCHECK_EQ(params.arguments.GetSize(), (size_t)1); + + std::string command; + + params.arguments.GetString(0, &command); + DCHECK(!command.empty()); + + if (base::LowerCaseEqualsASCII(command, "getsource")) { + response = blink::WebFrameContentDumper::DumpAsMarkup(frame_).Utf8(); + success = true; + } else if (base::LowerCaseEqualsASCII(command, "gettext")) { + response = blink_glue::DumpDocumentText(frame_); + success = true; + } else if (frame_->ExecuteCommand(blink::WebString::FromUTF8(command))) { + success = true; + } + } else if (params.name == "load-string") { + // Load a string. + DCHECK_EQ(params.arguments.GetSize(), (size_t)2); + + std::string string, url; + + params.arguments.GetString(0, &string); + params.arguments.GetString(1, &url); + + content::RenderFrame::FromWebFrame(frame_)->LoadHTMLString( + string, GURL(url), "UTF-8", GURL(), false /* replace_current_item */); + } else { + // Invalid request. + NOTREACHED(); + } + + if (params.expect_response) { + DCHECK_GE(params.request_id, 0); + + // Send a response to the browser. + Cef_Response_Params response_params; + response_params.request_id = params.request_id; + response_params.success = success; + response_params.response = response; + response_params.expect_response_ack = expect_response_ack; + Send(new CefHostMsg_Response(MSG_ROUTING_NONE, response_params)); + } +} + +void CefFrameImpl::OnResponse(const Cef_Response_Params& params) { + response_manager_->RunHandler(params); + if (params.expect_response_ack) + Send(new CefHostMsg_ResponseAck(MSG_ROUTING_NONE, params.request_id)); +} + +void CefFrameImpl::OnResponseAck(int request_id) { + response_manager_->RunAckHandler(request_id); +} + +void CefFrameImpl::OnDidStopLoading() { + // We should only receive this notification for the highest-level LocalFrame + // in this frame's in-process subtree. If there are multiple of these for the + // same browser then the other occurrences will be discarded in + // OnLoadingStateChange. + DCHECK(frame_->IsLocalRoot()); + browser_->OnLoadingStateChange(false); +} + +void CefFrameImpl::OnLoadRequest(const CefMsg_LoadRequest_Params& params) { + DCHECK(frame_); + + blink::WebURLRequest request; + CefRequestImpl::Get(params, request); + + frame_->StartNavigation(request); } // Enable deprecation warnings on Windows. See http://crbug.com/585142. diff --git a/libcef/renderer/frame_impl.h b/libcef/renderer/frame_impl.h index 880942c3c..66596ebd2 100644 --- a/libcef/renderer/frame_impl.h +++ b/libcef/renderer/frame_impl.h @@ -10,13 +10,27 @@ #include "include/cef_frame.h" #include "include/cef_v8.h" -class CefBrowserImpl; +namespace base { +class ListValue; +} namespace blink { class WebLocalFrame; class WebURLLoaderFactory; } // namespace blink +namespace IPC { +class Message; +} + +class GURL; + +class CefBrowserImpl; +class CefResponseManager; +struct CefMsg_LoadRequest_Params; +struct Cef_Request_Params; +struct Cef_Response_Params; + // Implementation of CefFrame. CefFrameImpl objects are owned by the // CefBrowerImpl and will be detached when the browser is notified that the // associated renderer WebFrame will close. @@ -57,23 +71,50 @@ class CefFrameImpl : public CefFrame { CefRefPtr CreateURLRequest( CefRefPtr request, CefRefPtr client) override; + void SendProcessMessage(CefProcessId target_process, + CefRefPtr message) override; // Used by CefRenderURLRequest. blink::WebURLLoaderFactory* GetURLLoaderFactory(); - void Detach(); + // Forwarded from CefRenderFrameObserver. + void OnAttached(); + bool OnMessageReceived(const IPC::Message& message); + void OnDidFinishLoad(); + void OnFocused(); + void OnDraggableRegionsChanged(); + void OnDetached(); blink::WebLocalFrame* web_frame() const { return frame_; } private: void ExecuteCommand(const std::string& command); + // Avoids unnecessary string type conversions. + void SendProcessMessage(CefProcessId target_process, + const std::string& name, + base::ListValue* arguments, + bool user_initiated); + + // Send a message to the RenderFrame associated with this frame. + void Send(IPC::Message* message); + + // OnMessageReceived message handlers. + void OnRequest(const Cef_Request_Params& params); + void OnResponse(const Cef_Response_Params& params); + void OnResponseAck(int request_id); + void OnDidStopLoading(); + void OnLoadRequest(const CefMsg_LoadRequest_Params& params); + CefBrowserImpl* browser_; blink::WebLocalFrame* frame_; - int64 frame_id_; + const int64 frame_id_; std::unique_ptr url_loader_factory_; + // Manages response registrations. + std::unique_ptr response_manager_; + IMPLEMENT_REFCOUNTING(CefFrameImpl); DISALLOW_COPY_AND_ASSIGN(CefFrameImpl); }; diff --git a/libcef/renderer/render_frame_observer.cc b/libcef/renderer/render_frame_observer.cc index 3a577bb9b..837341b81 100644 --- a/libcef/renderer/render_frame_observer.cc +++ b/libcef/renderer/render_frame_observer.cc @@ -17,15 +17,17 @@ #include "libcef/renderer/render_frame_observer.h" -#include "libcef/common/cef_messages.h" #include "libcef/common/content_client.h" #include "libcef/renderer/blink_glue.h" #include "libcef/renderer/browser_impl.h" +#include "libcef/renderer/dom_document_impl.h" #include "libcef/renderer/v8_impl.h" #include "content/public/renderer/render_frame.h" #include "third_party/blink/public/web/blink.h" +#include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/public/web/web_node.h" CefRenderFrameObserver::CefRenderFrameObserver( content::RenderFrame* render_frame) @@ -40,47 +42,59 @@ void CefRenderFrameObserver::OnInterfaceRequestForFrame( } void CefRenderFrameObserver::DidFinishLoad() { - blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); - CefRefPtr browserPtr = - CefBrowserImpl::GetBrowserForMainFrame(frame->Top()); - if (!browserPtr.get()) - return; - - browserPtr->DidFinishLoad(frame); + if (frame_) { + frame_->OnDidFinishLoad(); + } } void CefRenderFrameObserver::FrameDetached() { - blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); - CefRefPtr browserPtr = - CefBrowserImpl::GetBrowserForMainFrame(frame->Top()); - if (!browserPtr.get()) - return; - - browserPtr->FrameDetached(frame); + if (frame_) { + frame_->OnDetached(); + frame_ = nullptr; + } } void CefRenderFrameObserver::FrameFocused() { - Send(new CefHostMsg_FrameFocused(render_frame()->GetRoutingID())); + if (frame_) { + frame_->OnFocused(); + } } void CefRenderFrameObserver::FocusedNodeChanged(const blink::WebNode& node) { blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); CefRefPtr browserPtr = CefBrowserImpl::GetBrowserForMainFrame(frame->Top()); - if (!browserPtr.get()) + if (!browserPtr) return; - browserPtr->FocusedNodeChanged(node); + CefRefPtr handler; + CefRefPtr application = CefContentClient::Get()->application(); + if (application) + handler = application->GetRenderProcessHandler(); + if (!handler) + return; + + CefRefPtr framePtr = browserPtr->GetWebFrameImpl(frame); + + if (node.IsNull()) { + handler->OnFocusedNodeChanged(browserPtr.get(), framePtr.get(), nullptr); + return; + } + + if (node.GetDocument().IsNull()) + return; + + CefRefPtr documentImpl = + new CefDOMDocumentImpl(browserPtr.get(), frame); + handler->OnFocusedNodeChanged(browserPtr.get(), framePtr.get(), + documentImpl->GetOrCreateNode(node)); + documentImpl->Detach(); } void CefRenderFrameObserver::DraggableRegionsChanged() { - blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); - CefRefPtr browserPtr = - CefBrowserImpl::GetBrowserForMainFrame(frame->Top()); - if (!browserPtr.get()) - return; - - browserPtr->DraggableRegionsChanged(frame); + if (frame_) { + frame_->OnDraggableRegionsChanged(); + } } void CefRenderFrameObserver::DidCreateScriptContext( @@ -89,14 +103,14 @@ void CefRenderFrameObserver::DidCreateScriptContext( blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); CefRefPtr browserPtr = CefBrowserImpl::GetBrowserForMainFrame(frame->Top()); - if (!browserPtr.get()) + if (!browserPtr) return; CefRefPtr handler; CefRefPtr application = CefContentClient::Get()->application(); - if (application.get()) + if (application) handler = application->GetRenderProcessHandler(); - if (!handler.get()) + if (!handler) return; CefRefPtr framePtr = browserPtr->GetWebFrameImpl(frame); @@ -118,12 +132,12 @@ void CefRenderFrameObserver::WillReleaseScriptContext( blink::WebLocalFrame* frame = render_frame()->GetWebFrame(); CefRefPtr browserPtr = CefBrowserImpl::GetBrowserForMainFrame(frame->Top()); - if (browserPtr.get()) { + if (browserPtr) { CefRefPtr application = CefContentClient::Get()->application(); - if (application.get()) { + if (application) { CefRefPtr handler = application->GetRenderProcessHandler(); - if (handler.get()) { + if (handler) { CefRefPtr framePtr = browserPtr->GetWebFrameImpl(frame); v8::Isolate* isolate = blink::MainThreadIsolate(); @@ -150,6 +164,20 @@ void CefRenderFrameObserver::OnDestruct() { delete this; } +bool CefRenderFrameObserver::OnMessageReceived(const IPC::Message& message) { + if (frame_) { + return frame_->OnMessageReceived(message); + } + return false; +} + +void CefRenderFrameObserver::AttachFrame(CefFrameImpl* frame) { + DCHECK(frame); + DCHECK(!frame_); + frame_ = frame; + frame_->OnAttached(); +} + // Enable deprecation warnings on Windows. See http://crbug.com/585142. #if defined(OS_WIN) #if defined(__clang__) diff --git a/libcef/renderer/render_frame_observer.h b/libcef/renderer/render_frame_observer.h index 378996157..2601b603e 100644 --- a/libcef/renderer/render_frame_observer.h +++ b/libcef/renderer/render_frame_observer.h @@ -12,6 +12,8 @@ namespace content { class RenderFrame; } +class CefFrameImpl; + class CefRenderFrameObserver : public content::RenderFrameObserver { public: explicit CefRenderFrameObserver(content::RenderFrame* render_frame); @@ -31,11 +33,15 @@ class CefRenderFrameObserver : public content::RenderFrameObserver { void WillReleaseScriptContext(v8::Handle context, int world_id) override; void OnDestruct() override; + bool OnMessageReceived(const IPC::Message& message) override; service_manager::BinderRegistry* registry() { return ®istry_; } + void AttachFrame(CefFrameImpl* frame); + private: service_manager::BinderRegistry registry_; + CefFrameImpl* frame_ = nullptr; DISALLOW_COPY_AND_ASSIGN(CefRenderFrameObserver); }; diff --git a/libcef/renderer/render_frame_util.cc b/libcef/renderer/render_frame_util.cc index 5466aa5eb..21f9ac85f 100644 --- a/libcef/renderer/render_frame_util.cc +++ b/libcef/renderer/render_frame_util.cc @@ -5,9 +5,11 @@ #include "libcef/renderer/render_frame_util.h" +#include "libcef/common/frame_util.h" #include "libcef/renderer/blink_glue.h" #include "base/logging.h" +#include "content/public/renderer/render_view.h" #include "content/renderer/render_frame_impl.h" #include "third_party/blink/public/web/web_local_frame.h" @@ -18,17 +20,16 @@ int64_t GetIdentifier(blink::WebLocalFrame* frame) { // routing IDs are unique within a given renderer process. content::RenderFrame* render_frame = content::RenderFrame::FromWebFrame(frame); - DCHECK(render_frame); - if (render_frame) - return render_frame->GetRoutingID(); - return blink_glue::kInvalidFrameId; + return frame_util::MakeFrameId(render_frame->GetRenderView()->GetRoutingID(), + render_frame->GetRoutingID()); } std::string GetName(blink::WebLocalFrame* frame) { DCHECK(frame); // Return the assigned name if it is non-empty. This represents the name // property on the frame DOM element. If the assigned name is empty, revert to - // the internal unique name. + // the internal unique name. This matches the logic in + // CefFrameHostImpl::RefreshAttributes. if (frame->AssignedName().length() > 0) { return frame->AssignedName().Utf8(); } diff --git a/libcef_dll/cpptoc/browser_cpptoc.cc b/libcef_dll/cpptoc/browser_cpptoc.cc index 5c5966b3e..cb31bf07d 100644 --- a/libcef_dll/cpptoc/browser_cpptoc.cc +++ b/libcef_dll/cpptoc/browser_cpptoc.cc @@ -9,14 +9,13 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=97f834d04878d403755dd16060a55dd53a6c7b1a$ +// $hash=2124256e7c33c16c141e46243eec1a815539199d$ // #include "libcef_dll/cpptoc/browser_cpptoc.h" #include #include "libcef_dll/cpptoc/browser_host_cpptoc.h" #include "libcef_dll/cpptoc/frame_cpptoc.h" -#include "libcef_dll/cpptoc/process_message_cpptoc.h" #include "libcef_dll/shutdown_checker.h" #include "libcef_dll/transfer_util.h" @@ -374,30 +373,6 @@ void CEF_CALLBACK browser_get_frame_names(struct _cef_browser_t* self, transfer_string_list_contents(namesList, names); } -int CEF_CALLBACK -browser_send_process_message(struct _cef_browser_t* self, - cef_process_id_t target_process, - struct _cef_process_message_t* message) { - shutdown_checker::AssertNotShutdown(); - - // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - - DCHECK(self); - if (!self) - return 0; - // Verify param: message; type: refptr_same - DCHECK(message); - if (!message) - return 0; - - // Execute - bool _retval = CefBrowserCppToC::Get(self)->SendProcessMessage( - target_process, CefProcessMessageCppToC::Unwrap(message)); - - // Return type: bool - return _retval; -} - } // namespace // CONSTRUCTOR - Do not edit by hand. @@ -423,7 +398,6 @@ CefBrowserCppToC::CefBrowserCppToC() { GetStruct()->get_frame_count = browser_get_frame_count; GetStruct()->get_frame_identifiers = browser_get_frame_identifiers; GetStruct()->get_frame_names = browser_get_frame_names; - GetStruct()->send_process_message = browser_send_process_message; } // DESTRUCTOR - Do not edit by hand. diff --git a/libcef_dll/cpptoc/client_cpptoc.cc b/libcef_dll/cpptoc/client_cpptoc.cc index a94bd7a9c..17f7bd8d6 100644 --- a/libcef_dll/cpptoc/client_cpptoc.cc +++ b/libcef_dll/cpptoc/client_cpptoc.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=47ed1f92a294b94c071f554621484722483c3bd6$ +// $hash=64b2576447d3776b829e06007036acf579b2c47c$ // #include "libcef_dll/cpptoc/client_cpptoc.h" @@ -28,6 +28,7 @@ #include "libcef_dll/cpptoc/render_handler_cpptoc.h" #include "libcef_dll/cpptoc/request_handler_cpptoc.h" #include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/frame_ctocpp.h" #include "libcef_dll/ctocpp/process_message_ctocpp.h" namespace { @@ -261,6 +262,7 @@ client_get_request_handler(struct _cef_client_t* self) { int CEF_CALLBACK client_on_process_message_received(struct _cef_client_t* self, cef_browser_t* browser, + struct _cef_frame_t* frame, cef_process_id_t source_process, struct _cef_process_message_t* message) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING @@ -272,6 +274,10 @@ client_on_process_message_received(struct _cef_client_t* self, DCHECK(browser); if (!browser) return 0; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return 0; // Verify param: message; type: refptr_diff DCHECK(message); if (!message) @@ -279,8 +285,8 @@ client_on_process_message_received(struct _cef_client_t* self, // Execute bool _retval = CefClientCppToC::Get(self)->OnProcessMessageReceived( - CefBrowserCToCpp::Wrap(browser), source_process, - CefProcessMessageCToCpp::Wrap(message)); + CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame), + source_process, CefProcessMessageCToCpp::Wrap(message)); // Return type: bool return _retval; diff --git a/libcef_dll/cpptoc/drag_handler_cpptoc.cc b/libcef_dll/cpptoc/drag_handler_cpptoc.cc index 0a2260589..ff4b8fda7 100644 --- a/libcef_dll/cpptoc/drag_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/drag_handler_cpptoc.cc @@ -9,12 +9,13 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=c85e942b6518aa3951dbd47b3ff1097f4a6f88fa$ +// $hash=9c1c7a83aab83ba8cdb751db09373aaa49601ded$ // #include "libcef_dll/cpptoc/drag_handler_cpptoc.h" #include "libcef_dll/ctocpp/browser_ctocpp.h" #include "libcef_dll/ctocpp/drag_data_ctocpp.h" +#include "libcef_dll/ctocpp/frame_ctocpp.h" #include "libcef_dll/shutdown_checker.h" namespace { @@ -52,6 +53,7 @@ int CEF_CALLBACK drag_handler_on_drag_enter(struct _cef_drag_handler_t* self, void CEF_CALLBACK drag_handler_on_draggable_regions_changed( struct _cef_drag_handler_t* self, cef_browser_t* browser, + struct _cef_frame_t* frame, size_t regionsCount, cef_draggable_region_t const* regions) { shutdown_checker::AssertNotShutdown(); @@ -65,6 +67,10 @@ void CEF_CALLBACK drag_handler_on_draggable_regions_changed( DCHECK(browser); if (!browser) return; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return; // Verify param: regions; type: simple_vec_byref_const DCHECK(regionsCount == 0 || regions); if (regionsCount > 0 && !regions) @@ -81,7 +87,8 @@ void CEF_CALLBACK drag_handler_on_draggable_regions_changed( // Execute CefDragHandlerCppToC::Get(self)->OnDraggableRegionsChanged( - CefBrowserCToCpp::Wrap(browser), regionsList); + CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame), + regionsList); } } // namespace diff --git a/libcef_dll/cpptoc/frame_cpptoc.cc b/libcef_dll/cpptoc/frame_cpptoc.cc index 5984f77a9..9e16458a0 100644 --- a/libcef_dll/cpptoc/frame_cpptoc.cc +++ b/libcef_dll/cpptoc/frame_cpptoc.cc @@ -9,11 +9,12 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=eaff0c45fa3549df59bb9e64d5ac189205136ed3$ +// $hash=49a9d7412f4d9b8d5d7e15ce9f6f62e1b03ea248$ // #include "libcef_dll/cpptoc/frame_cpptoc.h" #include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/process_message_cpptoc.h" #include "libcef_dll/cpptoc/request_cpptoc.h" #include "libcef_dll/cpptoc/urlrequest_cpptoc.h" #include "libcef_dll/cpptoc/v8context_cpptoc.h" @@ -440,6 +441,27 @@ frame_create_urlrequest(struct _cef_frame_t* self, return CefURLRequestCppToC::Wrap(_retval); } +void CEF_CALLBACK +frame_send_process_message(struct _cef_frame_t* self, + cef_process_id_t target_process, + struct _cef_process_message_t* message) { + shutdown_checker::AssertNotShutdown(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: message; type: refptr_same + DCHECK(message); + if (!message) + return; + + // Execute + CefFrameCppToC::Get(self)->SendProcessMessage( + target_process, CefProcessMessageCppToC::Unwrap(message)); +} + } // namespace // CONSTRUCTOR - Do not edit by hand. @@ -470,6 +492,7 @@ CefFrameCppToC::CefFrameCppToC() { GetStruct()->get_v8context = frame_get_v8context; GetStruct()->visit_dom = frame_visit_dom; GetStruct()->create_urlrequest = frame_create_urlrequest; + GetStruct()->send_process_message = frame_send_process_message; } // DESTRUCTOR - Do not edit by hand. diff --git a/libcef_dll/cpptoc/render_process_handler_cpptoc.cc b/libcef_dll/cpptoc/render_process_handler_cpptoc.cc index 354e4d82d..e8d70e9a6 100644 --- a/libcef_dll/cpptoc/render_process_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/render_process_handler_cpptoc.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=7b918e87169c8fee39d93a9093ac700eceb6a061$ +// $hash=1abf9303cc2c0f6d86b9e84b4edddcb294330294$ // #include "libcef_dll/cpptoc/render_process_handler_cpptoc.h" @@ -239,6 +239,7 @@ void CEF_CALLBACK render_process_handler_on_focused_node_changed( int CEF_CALLBACK render_process_handler_on_process_message_received( struct _cef_render_process_handler_t* self, cef_browser_t* browser, + cef_frame_t* frame, cef_process_id_t source_process, cef_process_message_t* message) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING @@ -250,6 +251,10 @@ int CEF_CALLBACK render_process_handler_on_process_message_received( DCHECK(browser); if (!browser) return 0; + // Verify param: frame; type: refptr_diff + DCHECK(frame); + if (!frame) + return 0; // Verify param: message; type: refptr_diff DCHECK(message); if (!message) @@ -258,8 +263,8 @@ int CEF_CALLBACK render_process_handler_on_process_message_received( // Execute bool _retval = CefRenderProcessHandlerCppToC::Get(self)->OnProcessMessageReceived( - CefBrowserCToCpp::Wrap(browser), source_process, - CefProcessMessageCToCpp::Wrap(message)); + CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame), + source_process, CefProcessMessageCToCpp::Wrap(message)); // Return type: bool return _retval; diff --git a/libcef_dll/ctocpp/browser_ctocpp.cc b/libcef_dll/ctocpp/browser_ctocpp.cc index 7c8416541..a0827c3fb 100644 --- a/libcef_dll/ctocpp/browser_ctocpp.cc +++ b/libcef_dll/ctocpp/browser_ctocpp.cc @@ -9,14 +9,13 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=3a2fc11634093382ba9354ca64a2da50bb677e9f$ +// $hash=cfc1a36565ce6b7c8db6a26532319da2fbef9f2a$ // #include "libcef_dll/ctocpp/browser_ctocpp.h" #include #include "libcef_dll/ctocpp/browser_host_ctocpp.h" #include "libcef_dll/ctocpp/frame_ctocpp.h" -#include "libcef_dll/ctocpp/process_message_ctocpp.h" #include "libcef_dll/shutdown_checker.h" #include "libcef_dll/transfer_util.h" @@ -373,31 +372,6 @@ void CefBrowserCToCpp::GetFrameNames(std::vector& names) { } } -NO_SANITIZE("cfi-icall") -bool CefBrowserCToCpp::SendProcessMessage( - CefProcessId target_process, - CefRefPtr message) { - shutdown_checker::AssertNotShutdown(); - - cef_browser_t* _struct = GetStruct(); - if (CEF_MEMBER_MISSING(_struct, send_process_message)) - return false; - - // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - - // Verify param: message; type: refptr_same - DCHECK(message.get()); - if (!message.get()) - return false; - - // Execute - int _retval = _struct->send_process_message( - _struct, target_process, CefProcessMessageCToCpp::Unwrap(message)); - - // Return type: bool - return _retval ? true : false; -} - // CONSTRUCTOR - Do not edit by hand. CefBrowserCToCpp::CefBrowserCToCpp() {} diff --git a/libcef_dll/ctocpp/browser_ctocpp.h b/libcef_dll/ctocpp/browser_ctocpp.h index 1c30ade79..5e1d09784 100644 --- a/libcef_dll/ctocpp/browser_ctocpp.h +++ b/libcef_dll/ctocpp/browser_ctocpp.h @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=8f3cd27505fb1c95ab77ce1ca8a499eb79c0ede4$ +// $hash=af9ed3cfda9c94f046f4f9b5c9c94b1b38ff2e64$ // #ifndef CEF_LIBCEF_DLL_CTOCPP_BROWSER_CTOCPP_H_ @@ -56,8 +56,6 @@ class CefBrowserCToCpp size_t GetFrameCount() OVERRIDE; void GetFrameIdentifiers(std::vector& identifiers) OVERRIDE; void GetFrameNames(std::vector& names) OVERRIDE; - bool SendProcessMessage(CefProcessId target_process, - CefRefPtr message) OVERRIDE; }; #endif // CEF_LIBCEF_DLL_CTOCPP_BROWSER_CTOCPP_H_ diff --git a/libcef_dll/ctocpp/client_ctocpp.cc b/libcef_dll/ctocpp/client_ctocpp.cc index 597dda378..96b63600b 100644 --- a/libcef_dll/ctocpp/client_ctocpp.cc +++ b/libcef_dll/ctocpp/client_ctocpp.cc @@ -9,11 +9,12 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=69de5a63c075f401a8bfc34b9b30d7cec595d432$ +// $hash=4cf201c5e2c106fe4054cb3704114f937e763295$ // #include "libcef_dll/ctocpp/client_ctocpp.h" #include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/frame_cpptoc.h" #include "libcef_dll/cpptoc/process_message_cpptoc.h" #include "libcef_dll/ctocpp/audio_handler_ctocpp.h" #include "libcef_dll/ctocpp/context_menu_handler_ctocpp.h" @@ -246,6 +247,7 @@ CefRefPtr CefClientCToCpp::GetRequestHandler() { NO_SANITIZE("cfi-icall") bool CefClientCToCpp::OnProcessMessageReceived( CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) { cef_client_t* _struct = GetStruct(); @@ -258,6 +260,10 @@ bool CefClientCToCpp::OnProcessMessageReceived( DCHECK(browser.get()); if (!browser.get()) return false; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return false; // Verify param: message; type: refptr_diff DCHECK(message.get()); if (!message.get()) @@ -265,8 +271,8 @@ bool CefClientCToCpp::OnProcessMessageReceived( // Execute int _retval = _struct->on_process_message_received( - _struct, CefBrowserCppToC::Wrap(browser), source_process, - CefProcessMessageCppToC::Wrap(message)); + _struct, CefBrowserCppToC::Wrap(browser), CefFrameCppToC::Wrap(frame), + source_process, CefProcessMessageCppToC::Wrap(message)); // Return type: bool return _retval ? true : false; diff --git a/libcef_dll/ctocpp/client_ctocpp.h b/libcef_dll/ctocpp/client_ctocpp.h index 448f9f4e7..6f285afe7 100644 --- a/libcef_dll/ctocpp/client_ctocpp.h +++ b/libcef_dll/ctocpp/client_ctocpp.h @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=82dc5a810e754b785f0257cea28d1a3bc6fa0ab9$ +// $hash=bbac20a2027ea623832f37512f716092f29eef3f$ // #ifndef CEF_LIBCEF_DLL_CTOCPP_CLIENT_CTOCPP_H_ @@ -48,6 +48,7 @@ class CefClientCToCpp CefRefPtr GetRenderHandler() override; CefRefPtr GetRequestHandler() override; bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override; }; diff --git a/libcef_dll/ctocpp/drag_handler_ctocpp.cc b/libcef_dll/ctocpp/drag_handler_ctocpp.cc index 8f2477c23..ca3fe7dc8 100644 --- a/libcef_dll/ctocpp/drag_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/drag_handler_ctocpp.cc @@ -9,12 +9,13 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=c8a4667e566076b36af39a83ba15cb1015821da9$ +// $hash=ed9ec27e4e93df6821437ee0d49da3ebd122bed3$ // #include "libcef_dll/ctocpp/drag_handler_ctocpp.h" #include "libcef_dll/cpptoc/browser_cpptoc.h" #include "libcef_dll/cpptoc/drag_data_cpptoc.h" +#include "libcef_dll/cpptoc/frame_cpptoc.h" #include "libcef_dll/shutdown_checker.h" // VIRTUAL METHODS - Body may be edited by hand. @@ -51,6 +52,7 @@ bool CefDragHandlerCToCpp::OnDragEnter(CefRefPtr browser, NO_SANITIZE("cfi-icall") void CefDragHandlerCToCpp::OnDraggableRegionsChanged( CefRefPtr browser, + CefRefPtr frame, const std::vector& regions) { shutdown_checker::AssertNotShutdown(); @@ -64,6 +66,10 @@ void CefDragHandlerCToCpp::OnDraggableRegionsChanged( DCHECK(browser.get()); if (!browser.get()) return; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return; // Translate param: regions; type: simple_vec_byref_const const size_t regionsCount = regions.size(); @@ -80,7 +86,8 @@ void CefDragHandlerCToCpp::OnDraggableRegionsChanged( // Execute _struct->on_draggable_regions_changed( - _struct, CefBrowserCppToC::Wrap(browser), regionsCount, regionsList); + _struct, CefBrowserCppToC::Wrap(browser), CefFrameCppToC::Wrap(frame), + regionsCount, regionsList); // Restore param:regions; type: simple_vec_byref_const if (regionsList) diff --git a/libcef_dll/ctocpp/drag_handler_ctocpp.h b/libcef_dll/ctocpp/drag_handler_ctocpp.h index 3ffd1f6da..034d1be5f 100644 --- a/libcef_dll/ctocpp/drag_handler_ctocpp.h +++ b/libcef_dll/ctocpp/drag_handler_ctocpp.h @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=a602f4f6b80980bc86d8bb814e6ce34d07a2e4b6$ +// $hash=dc795e4c004c83502c99e5dcced1bcd322b25d3d$ // #ifndef CEF_LIBCEF_DLL_CTOCPP_DRAG_HANDLER_CTOCPP_H_ @@ -40,6 +40,7 @@ class CefDragHandlerCToCpp : public CefCToCppRefCounted browser, + CefRefPtr frame, const std::vector& regions) override; }; diff --git a/libcef_dll/ctocpp/frame_ctocpp.cc b/libcef_dll/ctocpp/frame_ctocpp.cc index 39fc73144..0783c3348 100644 --- a/libcef_dll/ctocpp/frame_ctocpp.cc +++ b/libcef_dll/ctocpp/frame_ctocpp.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=301b9573f13ede3bc9cb210caaae109fdf909130$ +// $hash=957f55c65387757a411f9b898827bdef95531c45$ // #include "libcef_dll/ctocpp/frame_ctocpp.h" @@ -17,6 +17,7 @@ #include "libcef_dll/cpptoc/string_visitor_cpptoc.h" #include "libcef_dll/cpptoc/urlrequest_client_cpptoc.h" #include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/process_message_ctocpp.h" #include "libcef_dll/ctocpp/request_ctocpp.h" #include "libcef_dll/ctocpp/urlrequest_ctocpp.h" #include "libcef_dll/ctocpp/v8context_ctocpp.h" @@ -448,6 +449,27 @@ CefRefPtr CefFrameCToCpp::CreateURLRequest( return CefURLRequestCToCpp::Wrap(_retval); } +NO_SANITIZE("cfi-icall") +void CefFrameCToCpp::SendProcessMessage(CefProcessId target_process, + CefRefPtr message) { + shutdown_checker::AssertNotShutdown(); + + cef_frame_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, send_process_message)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: message; type: refptr_same + DCHECK(message.get()); + if (!message.get()) + return; + + // Execute + _struct->send_process_message(_struct, target_process, + CefProcessMessageCToCpp::Unwrap(message)); +} + // CONSTRUCTOR - Do not edit by hand. CefFrameCToCpp::CefFrameCToCpp() {} diff --git a/libcef_dll/ctocpp/frame_ctocpp.h b/libcef_dll/ctocpp/frame_ctocpp.h index 20f053765..3b3d09ef4 100644 --- a/libcef_dll/ctocpp/frame_ctocpp.h +++ b/libcef_dll/ctocpp/frame_ctocpp.h @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=7479de0c460d69b7846c0c13df0ea50f3b9aeae1$ +// $hash=1f9305ea3945990271795caf303c11ae09f662a4$ // #ifndef CEF_LIBCEF_DLL_CTOCPP_FRAME_CTOCPP_H_ @@ -68,6 +68,8 @@ class CefFrameCToCpp CefRefPtr CreateURLRequest( CefRefPtr request, CefRefPtr client) OVERRIDE; + void SendProcessMessage(CefProcessId target_process, + CefRefPtr message) OVERRIDE; }; #endif // CEF_LIBCEF_DLL_CTOCPP_FRAME_CTOCPP_H_ diff --git a/libcef_dll/ctocpp/render_process_handler_ctocpp.cc b/libcef_dll/ctocpp/render_process_handler_ctocpp.cc index 9a1fe2f81..ad4b7d363 100644 --- a/libcef_dll/ctocpp/render_process_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/render_process_handler_ctocpp.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=366d6e567451af19ce5a4cc5f6f06791f504af26$ +// $hash=3983c8f521d444195dc52b4605840b51289e77e0$ // #include "libcef_dll/ctocpp/render_process_handler_ctocpp.h" @@ -241,6 +241,7 @@ void CefRenderProcessHandlerCToCpp::OnFocusedNodeChanged( NO_SANITIZE("cfi-icall") bool CefRenderProcessHandlerCToCpp::OnProcessMessageReceived( CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) { cef_render_process_handler_t* _struct = GetStruct(); @@ -253,6 +254,10 @@ bool CefRenderProcessHandlerCToCpp::OnProcessMessageReceived( DCHECK(browser.get()); if (!browser.get()) return false; + // Verify param: frame; type: refptr_diff + DCHECK(frame.get()); + if (!frame.get()) + return false; // Verify param: message; type: refptr_diff DCHECK(message.get()); if (!message.get()) @@ -260,8 +265,8 @@ bool CefRenderProcessHandlerCToCpp::OnProcessMessageReceived( // Execute int _retval = _struct->on_process_message_received( - _struct, CefBrowserCppToC::Wrap(browser), source_process, - CefProcessMessageCppToC::Wrap(message)); + _struct, CefBrowserCppToC::Wrap(browser), CefFrameCppToC::Wrap(frame), + source_process, CefProcessMessageCppToC::Wrap(message)); // Return type: bool return _retval ? true : false; diff --git a/libcef_dll/ctocpp/render_process_handler_ctocpp.h b/libcef_dll/ctocpp/render_process_handler_ctocpp.h index 2871ad5fb..51eb6f403 100644 --- a/libcef_dll/ctocpp/render_process_handler_ctocpp.h +++ b/libcef_dll/ctocpp/render_process_handler_ctocpp.h @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=c8931d822a351fe827ffd29ba89b888e3e44f6ea$ +// $hash=56503073200b87c109a84c0161dda30f01285c66$ // #ifndef CEF_LIBCEF_DLL_CTOCPP_RENDER_PROCESS_HANDLER_CTOCPP_H_ @@ -56,6 +56,7 @@ class CefRenderProcessHandlerCToCpp CefRefPtr frame, CefRefPtr node) override; bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override; }; diff --git a/libcef_dll/wrapper/cef_message_router.cc b/libcef_dll/wrapper/cef_message_router.cc index 6c063bdca..9bf2f2d66 100644 --- a/libcef_dll/wrapper/cef_message_router.cc +++ b/libcef_dll/wrapper/cef_message_router.cc @@ -82,7 +82,7 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { DCHECK(!router_); } - virtual void Success(const CefString& response) OVERRIDE { + void Success(const CefString& response) OVERRIDE { if (!CefCurrentlyOn(TID_UI)) { // Must execute on the UI thread to access member variables. CefPostTask(TID_UI, base::Bind(&CallbackImpl::Success, this, response)); @@ -102,8 +102,7 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { } } - virtual void Failure(int error_code, - const CefString& error_message) OVERRIDE { + void Failure(int error_code, const CefString& error_message) OVERRIDE { if (!CefCurrentlyOn(TID_UI)) { // Must execute on the UI thread to access member variables. CefPostTask(TID_UI, base::Bind(&CallbackImpl::Failure, this, error_code, @@ -149,7 +148,7 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { DCHECK(browser_query_info_map_.empty()); } - virtual bool AddHandler(Handler* handler, bool first) OVERRIDE { + bool AddHandler(Handler* handler, bool first) OVERRIDE { CEF_REQUIRE_UI_THREAD(); if (handler_set_.find(handler) == handler_set_.end()) { handler_set_.insert(first ? handler_set_.begin() : handler_set_.end(), @@ -159,7 +158,7 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { return false; } - virtual bool RemoveHandler(Handler* handler) OVERRIDE { + bool RemoveHandler(Handler* handler) OVERRIDE { CEF_REQUIRE_UI_THREAD(); if (handler_set_.erase(handler) > 0) { CancelPendingFor(NULL, handler, true); @@ -168,13 +167,12 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { return false; } - virtual void CancelPending(CefRefPtr browser, - Handler* handler) OVERRIDE { + void CancelPending(CefRefPtr browser, Handler* handler) OVERRIDE { CancelPendingFor(browser, handler, true); } - virtual int GetPendingCount(CefRefPtr browser, - Handler* handler) OVERRIDE { + int GetPendingCount(CefRefPtr browser, + Handler* handler) OVERRIDE { CEF_REQUIRE_UI_THREAD(); if (browser_query_info_map_.empty()) @@ -186,10 +184,10 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { public: explicit Visitor(Handler* handler) : handler_(handler), count_(0) {} - virtual bool OnNextInfo(int browser_id, - InfoIdType info_id, - InfoObjectType info, - bool* remove) OVERRIDE { + bool OnNextInfo(int browser_id, + InfoIdType info_id, + InfoObjectType info, + bool* remove) OVERRIDE { if (info->handler == handler_) count_++; return true; @@ -223,53 +221,45 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { return 0; } - virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE { + void OnBeforeClose(CefRefPtr browser) OVERRIDE { CancelPendingFor(browser, NULL, false); } - virtual void OnRenderProcessTerminated( - CefRefPtr browser) OVERRIDE { + void OnRenderProcessTerminated(CefRefPtr browser) OVERRIDE { CancelPendingFor(browser, NULL, false); } - virtual void OnBeforeBrowse(CefRefPtr browser, - CefRefPtr frame) OVERRIDE { + void OnBeforeBrowse(CefRefPtr browser, + CefRefPtr frame) OVERRIDE { if (frame->IsMain()) CancelPendingFor(browser, NULL, false); } - virtual bool OnProcessMessageReceived( - CefRefPtr browser, - CefProcessId source_process, - CefRefPtr message) OVERRIDE { + bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, + CefProcessId source_process, + CefRefPtr message) OVERRIDE { CEF_REQUIRE_UI_THREAD(); const std::string& message_name = message->GetName(); if (message_name == query_message_name_) { CefRefPtr args = message->GetArgumentList(); - DCHECK_EQ(args->GetSize(), 7U); + DCHECK_EQ(args->GetSize(), 4U); - const int64 frame_id = CefInt64Set(args->GetInt(0), args->GetInt(1)); - const bool is_main_frame = args->GetBool(2); - const int context_id = args->GetInt(3); - const int request_id = args->GetInt(4); - const CefString& request = args->GetString(5); - const bool persistent = args->GetBool(6); + const int context_id = args->GetInt(0); + const int request_id = args->GetInt(1); + const CefString& request = args->GetString(2); + const bool persistent = args->GetBool(3); if (handler_set_.empty()) { // No handlers so cancel the query. - CancelUnhandledQuery(browser, context_id, request_id); + CancelUnhandledQuery(browser, frame, context_id, request_id); return true; } const int browser_id = browser->GetIdentifier(); const int64 query_id = query_id_generator_.GetNextId(); - CefRefPtr frame; - if (is_main_frame) - frame = browser->GetMainFrame(); - else - frame = browser->GetFrame(frame_id); CefRefPtr callback( new CallbackImpl(this, browser_id, query_id, persistent)); @@ -297,8 +287,7 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { // asynchronously. QueryInfo* info = new QueryInfo; info->browser = browser; - info->frame_id = frame_id; - info->is_main_frame = is_main_frame; + info->frame = frame; info->context_id = context_id; info->request_id = request_id; info->persistent = persistent; @@ -310,7 +299,7 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { callback->Detach(); // No one chose to handle the query so cancel it. - CancelUnhandledQuery(browser, context_id, request_id); + CancelUnhandledQuery(browser, frame, context_id, request_id); } return true; @@ -334,8 +323,7 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { struct QueryInfo { // Browser and frame originated the query. CefRefPtr browser; - int64 frame_id; - bool is_main_frame; + CefRefPtr frame; // IDs that uniquely identify the query in the renderer process. These // values are opaque to the browser process but must be returned with the @@ -368,10 +356,10 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { explicit Visitor(bool always_remove) : always_remove_(always_remove), removed_(false) {} - virtual bool OnNextInfo(int browser_id, - InfoIdType info_id, - InfoObjectType info, - bool* remove) OVERRIDE { + bool OnNextInfo(int browser_id, + InfoIdType info_id, + InfoObjectType info, + bool* remove) OVERRIDE { *remove = removed_ = (always_remove_ || !info->persistent); return true; } @@ -423,11 +411,12 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { } void SendQuerySuccess(QueryInfo* info, const CefString& response) { - SendQuerySuccess(info->browser, info->context_id, info->request_id, - response); + SendQuerySuccess(info->browser, info->frame, info->context_id, + info->request_id, response); } void SendQuerySuccess(CefRefPtr browser, + CefRefPtr frame, int context_id, int request_id, const CefString& response) { @@ -438,17 +427,18 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { args->SetInt(1, request_id); args->SetBool(2, true); // Indicates a success result. args->SetString(3, response); - browser->SendProcessMessage(PID_RENDERER, message); + frame->SendProcessMessage(PID_RENDERER, message); } void SendQueryFailure(QueryInfo* info, int error_code, const CefString& error_message) { - SendQueryFailure(info->browser, info->context_id, info->request_id, - error_code, error_message); + SendQueryFailure(info->browser, info->frame, info->context_id, + info->request_id, error_code, error_message); } void SendQueryFailure(CefRefPtr browser, + CefRefPtr frame, int context_id, int request_id, int error_code, @@ -461,14 +451,15 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { args->SetBool(2, false); // Indicates a failure result. args->SetInt(3, error_code); args->SetString(4, error_message); - browser->SendProcessMessage(PID_RENDERER, message); + frame->SendProcessMessage(PID_RENDERER, message); } // Cancel a query that has not been sent to a handler. void CancelUnhandledQuery(CefRefPtr browser, + CefRefPtr frame, int context_id, int request_id) { - SendQueryFailure(browser, context_id, request_id, kCanceledErrorCode, + SendQueryFailure(browser, frame, context_id, request_id, kCanceledErrorCode, kCanceledErrorMessage); } @@ -477,12 +468,7 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { if (notify_renderer) SendQueryFailure(info, kCanceledErrorCode, kCanceledErrorMessage); - CefRefPtr frame; - if (info->is_main_frame) - frame = info->browser->GetMainFrame(); - else - frame = info->browser->GetFrame(info->frame_id); - info->handler->OnQueryCanceled(info->browser, frame, query_id); + info->handler->OnQueryCanceled(info->browser, info->frame, query_id); // Invalidate the callback. info->callback->Detach(); @@ -514,10 +500,10 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { handler_(handler), notify_renderer_(notify_renderer) {} - virtual bool OnNextInfo(int browser_id, - InfoIdType info_id, - InfoObjectType info, - bool* remove) OVERRIDE { + bool OnNextInfo(int browser_id, + InfoIdType info_id, + InfoObjectType info, + bool* remove) OVERRIDE { if (!handler_ || info->handler == handler_) { *remove = true; router_->CancelQuery(info_id, info, notify_renderer_); @@ -553,10 +539,10 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide { int request_id) : router_(router), context_id_(context_id), request_id_(request_id) {} - virtual bool OnNextInfo(int browser_id, - InfoIdType info_id, - InfoObjectType info, - bool* remove) OVERRIDE { + bool OnNextInfo(int browser_id, + InfoIdType info_id, + InfoObjectType info, + bool* remove) OVERRIDE { if (info->context_id == context_id_ && (request_id_ == kReservedId || info->request_id == request_id_)) { *remove = true; @@ -609,11 +595,11 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide { const CefMessageRouterConfig& config) : router_(router), config_(config), context_id_(kReservedId) {} - virtual bool Execute(const CefString& name, - CefRefPtr object, - const CefV8ValueList& arguments, - CefRefPtr& retval, - CefString& exception) OVERRIDE { + bool Execute(const CefString& name, + CefRefPtr object, + const CefV8ValueList& arguments, + CefRefPtr& retval, + CefString& exception) OVERRIDE { if (name == config_.js_query_function) { if (arguments.size() != 1 || !arguments[0]->IsObject()) { exception = "Invalid arguments; expecting a single object"; @@ -665,13 +651,11 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide { CefRefPtr context = CefV8Context::GetCurrentContext(); const int context_id = GetIDForContext(context); - const int64 frame_id = context->GetFrame()->GetIdentifier(); - const bool is_main_frame = context->GetFrame()->IsMain(); const bool persistent = (persistentVal.get() && persistentVal->GetBoolValue()); const int request_id = router_->SendQuery( - context->GetBrowser(), frame_id, is_main_frame, context_id, + context->GetBrowser(), context->GetFrame(), context_id, requestVal->GetStringValue(), persistent, successVal, failureVal); retval = CefV8Value::CreateInt(request_id); return true; @@ -686,8 +670,9 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide { if (request_id != kReservedId) { CefRefPtr context = CefV8Context::GetCurrentContext(); const int context_id = GetIDForContext(context); - result = router_->SendCancel(context->GetBrowser(), context_id, - request_id); + result = + router_->SendCancel(context->GetBrowser(), context->GetFrame(), + context_id, request_id); } retval = CefV8Value::CreateBool(result); return true; @@ -721,8 +706,8 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide { virtual ~CefMessageRouterRendererSideImpl() {} - virtual int GetPendingCount(CefRefPtr browser, - CefRefPtr context) OVERRIDE { + int GetPendingCount(CefRefPtr browser, + CefRefPtr context) OVERRIDE { CEF_REQUIRE_RENDERER_THREAD(); if (browser_request_info_map_.empty()) @@ -738,10 +723,10 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide { public: explicit Visitor(int context_id) : context_id_(context_id), count_(0) {} - virtual bool OnNextInfo(int browser_id, - InfoIdType info_id, - InfoObjectType info, - bool* remove) OVERRIDE { + bool OnNextInfo(int browser_id, + InfoIdType info_id, + InfoObjectType info, + bool* remove) OVERRIDE { if (info_id.first == context_id_) count_++; return true; @@ -775,9 +760,9 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide { return 0; } - virtual void OnContextCreated(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr context) OVERRIDE { + void OnContextCreated(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr context) OVERRIDE { CEF_REQUIRE_RENDERER_THREAD(); // Register function handlers with the 'window' object. @@ -800,23 +785,23 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide { window->SetValue(config_.js_cancel_function, cancel_func, attributes); } - virtual void OnContextReleased(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr context) OVERRIDE { + void OnContextReleased(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr context) OVERRIDE { CEF_REQUIRE_RENDERER_THREAD(); // Get the context ID and remove the context from the map. const int context_id = GetIDForContext(context, true); if (context_id != kReservedId) { // Cancel all pending requests for the context. - SendCancel(browser, context_id, kReservedId); + SendCancel(browser, frame, context_id, kReservedId); } } - virtual bool OnProcessMessageReceived( - CefRefPtr browser, - CefProcessId source_process, - CefRefPtr message) OVERRIDE { + bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, + CefProcessId source_process, + CefRefPtr message) OVERRIDE { CEF_REQUIRE_RENDERER_THREAD(); const std::string& message_name = message->GetName(); @@ -882,10 +867,10 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide { explicit Visitor(bool always_remove) : always_remove_(always_remove), removed_(false) {} - virtual bool OnNextInfo(int browser_id, - InfoIdType info_id, - InfoObjectType info, - bool* remove) OVERRIDE { + bool OnNextInfo(int browser_id, + InfoIdType info_id, + InfoObjectType info, + bool* remove) OVERRIDE { *remove = removed_ = (always_remove_ || !info->persistent); return true; } @@ -907,8 +892,7 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide { // Returns the new request ID. int SendQuery(CefRefPtr browser, - int64 frame_id, - bool is_main_frame, + CefRefPtr frame, int context_id, const CefString& request, bool persistent, @@ -929,15 +913,12 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide { CefProcessMessage::Create(query_message_name_); CefRefPtr args = message->GetArgumentList(); - args->SetInt(0, CefInt64GetLow(frame_id)); - args->SetInt(1, CefInt64GetHigh(frame_id)); - args->SetBool(2, is_main_frame); - args->SetInt(3, context_id); - args->SetInt(4, request_id); - args->SetString(5, request); - args->SetBool(6, persistent); + args->SetInt(0, context_id); + args->SetInt(1, request_id); + args->SetString(2, request); + args->SetBool(3, persistent); - browser->SendProcessMessage(PID_BROWSER, message); + frame->SendProcessMessage(PID_BROWSER, message); return request_id; } @@ -946,6 +927,7 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide { // will be canceled, otherwise only the specified |request_id| will be // canceled. Returns true if any request was canceled. bool SendCancel(CefRefPtr browser, + CefRefPtr frame, int context_id, int request_id) { CEF_REQUIRE_RENDERER_THREAD(); @@ -970,10 +952,10 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide { explicit Visitor(int context_id) : context_id_(context_id), cancel_count_(0) {} - virtual bool OnNextInfo(int browser_id, - InfoIdType info_id, - InfoObjectType info, - bool* remove) OVERRIDE { + bool OnNextInfo(int browser_id, + InfoIdType info_id, + InfoObjectType info, + bool* remove) OVERRIDE { if (info_id.first == context_id_) { *remove = true; delete info; @@ -1002,7 +984,7 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide { args->SetInt(0, context_id); args->SetInt(1, request_id); - browser->SendProcessMessage(PID_BROWSER, message); + frame->SendProcessMessage(PID_BROWSER, message); return true; } diff --git a/tests/cefclient/browser/client_handler.cc b/tests/cefclient/browser/client_handler.cc index f01f6a0f6..1cdccdbda 100644 --- a/tests/cefclient/browser/client_handler.cc +++ b/tests/cefclient/browser/client_handler.cc @@ -281,11 +281,12 @@ void ClientHandler::DetachDelegate() { bool ClientHandler::OnProcessMessageReceived( CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) { CEF_REQUIRE_UI_THREAD(); - if (message_router_->OnProcessMessageReceived(browser, source_process, + if (message_router_->OnProcessMessageReceived(browser, frame, source_process, message)) { return true; } @@ -486,6 +487,7 @@ bool ClientHandler::OnDragEnter(CefRefPtr browser, void ClientHandler::OnDraggableRegionsChanged( CefRefPtr browser, + CefRefPtr frame, const std::vector& regions) { CEF_REQUIRE_UI_THREAD(); diff --git a/tests/cefclient/browser/client_handler.h b/tests/cefclient/browser/client_handler.h index 34b52ffce..eba05dd21 100644 --- a/tests/cefclient/browser/client_handler.h +++ b/tests/cefclient/browser/client_handler.h @@ -110,6 +110,7 @@ class ClientHandler : public CefClient, CefRefPtr GetLoadHandler() OVERRIDE { return this; } CefRefPtr GetRequestHandler() OVERRIDE { return this; } bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) OVERRIDE; @@ -166,6 +167,7 @@ class ClientHandler : public CefClient, CefDragHandler::DragOperationsMask mask) OVERRIDE; void OnDraggableRegionsChanged( CefRefPtr browser, + CefRefPtr frame, const std::vector& regions) OVERRIDE; // CefFocusHandler methods diff --git a/tests/cefclient/renderer/client_renderer.cc b/tests/cefclient/renderer/client_renderer.cc index 71f1e458a..100fe2c75 100644 --- a/tests/cefclient/renderer/client_renderer.cc +++ b/tests/cefclient/renderer/client_renderer.cc @@ -69,16 +69,17 @@ class ClientRenderDelegate : public ClientAppRenderer::Delegate { CefRefPtr message = CefProcessMessage::Create(kFocusedNodeChangedMessage); message->GetArgumentList()->SetBool(0, is_editable); - browser->SendProcessMessage(PID_BROWSER, message); + frame->SendProcessMessage(PID_BROWSER, message); } } bool OnProcessMessageReceived(CefRefPtr app, CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) OVERRIDE { - return message_router_->OnProcessMessageReceived(browser, source_process, - message); + return message_router_->OnProcessMessageReceived(browser, frame, + source_process, message); } private: diff --git a/tests/ceftests/dom_unittest.cc b/tests/ceftests/dom_unittest.cc index ac4cb2422..1b262524b 100644 --- a/tests/ceftests/dom_unittest.cc +++ b/tests/ceftests/dom_unittest.cc @@ -223,7 +223,7 @@ class TestDOMVisitor : public CefDOMVisitor { CefRefPtr return_msg = CefProcessMessage::Create(kTestMessage); EXPECT_TRUE(return_msg->GetArgumentList()->SetBool(0, result)); - EXPECT_TRUE(browser_->SendProcessMessage(PID_BROWSER, return_msg)); + browser_->GetMainFrame()->SendProcessMessage(PID_BROWSER, return_msg); } CefRefPtr browser_; @@ -239,6 +239,7 @@ class DOMRendererTest : public ClientAppRenderer::Delegate { bool OnProcessMessageReceived(CefRefPtr app, CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { if (message->GetName() == kTestMessage) { @@ -288,11 +289,12 @@ class TestDOMHandler : public TestHandler { CefRefPtr message( CefProcessMessage::Create(kTestMessage)); message->GetArgumentList()->SetInt(0, test_type_); - EXPECT_TRUE(browser->SendProcessMessage(PID_RENDERER, message)); + frame->SendProcessMessage(PID_RENDERER, message); } } bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { EXPECT_STREQ(message->GetName().ToString().c_str(), kTestMessage); diff --git a/tests/ceftests/draggable_regions_unittest.cc b/tests/ceftests/draggable_regions_unittest.cc index 1a179453c..fea4fc081 100644 --- a/tests/ceftests/draggable_regions_unittest.cc +++ b/tests/ceftests/draggable_regions_unittest.cc @@ -47,7 +47,7 @@ const char kTestHTMLWithChangingRegions[] = " " ""; -class DraggableRegionsTestHandler : public TestHandler { +class DraggableRegionsTestHandler : public TestHandler, public CefDragHandler { public: DraggableRegionsTestHandler() : step_(kStepWithRegions) {} @@ -65,11 +65,15 @@ class DraggableRegionsTestHandler : public TestHandler { SetTestTimeout(); } + CefRefPtr GetDragHandler() override { return this; } + void OnDraggableRegionsChanged( CefRefPtr browser, + CefRefPtr frame, const std::vector& regions) override { EXPECT_TRUE(CefCurrentlyOn(TID_UI)); EXPECT_TRUE(browser->IsSame(GetBrowser())); + EXPECT_TRUE(frame->IsMain()); did_call_on_draggable_regions_changed_.yes(); diff --git a/tests/ceftests/frame_unittest.cc b/tests/ceftests/frame_unittest.cc index 7421701a9..4daa2b709 100644 --- a/tests/ceftests/frame_unittest.cc +++ b/tests/ceftests/frame_unittest.cc @@ -110,7 +110,8 @@ FrameNavFactoryId g_frame_nav_factory_id = FNF_ID_INVALID; // Abstract base class representing expectations that result from a navigation. class FrameNavExpectations { public: - typedef base::Callback)> CompletionCallback; + typedef base::Callback, CefRefPtr)> + CompletionCallback; FrameNavExpectations(int nav, bool renderer) : nav_(nav), renderer_(renderer) {} @@ -135,12 +136,13 @@ class FrameNavExpectations { // Signal that all expectations are completed. Should be called as a result of // notifications. - void SignalComplete(CefRefPtr browser) { + void SignalComplete(CefRefPtr browser, + CefRefPtr frame) { if (!completion_callback_.is_null()) { // Execute the callback asynchronously to avoid any issues with what's // currently on the stack. CefPostTask((renderer_ ? TID_RENDERER : TID_UI), - base::Bind(completion_callback_, browser)); + base::Bind(completion_callback_, browser, frame)); completion_callback_.Reset(); } } @@ -197,6 +199,7 @@ class FrameNavExpectationsBrowser : public FrameNavExpectations { // Called when the renderer signals completion. virtual bool OnRendererComplete(CefRefPtr browser, + CefRefPtr frame, int renderer_nav, bool renderer_result) = 0; }; @@ -374,7 +377,8 @@ class FrameNavRendererTest : public ClientAppRenderer::Delegate, // Send the test results. // Will be called via FrameNavExpectations::SignalComplete. - void SendTestResults(CefRefPtr browser) { + void SendTestResults(CefRefPtr browser, + CefRefPtr frame) { // End of the current expectations object. EXPECT_TRUE(expectations_->Finalize()) << "nav = " << nav_; expectations_.reset(NULL); @@ -389,7 +393,7 @@ class FrameNavRendererTest : public ClientAppRenderer::Delegate, EXPECT_TRUE(args.get()); EXPECT_TRUE(args->SetInt(0, nav_)); EXPECT_TRUE(args->SetBool(1, result)); - EXPECT_TRUE(browser->SendProcessMessage(PID_BROWSER, return_msg)); + frame->SendProcessMessage(PID_BROWSER, return_msg); nav_++; } @@ -434,7 +438,7 @@ class FrameNavTestHandler : public TestHandler { // Transition to the next navigation. // Will be called via FrameNavExpectations::SignalComplete. - void RunNextNav(CefRefPtr browser) { + void RunNextNav(CefRefPtr browser, CefRefPtr frame) { // End of the current expectations object. EXPECT_TRUE(expectations_->Finalize()); expectations_.reset(NULL); @@ -512,6 +516,7 @@ class FrameNavTestHandler : public TestHandler { } bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { if (message->GetName().ToString() == kFrameNavMsg) { @@ -519,8 +524,8 @@ class FrameNavTestHandler : public TestHandler { CefRefPtr args = message->GetArgumentList(); EXPECT_TRUE(args.get()); - EXPECT_TRUE(expectations_->OnRendererComplete(browser, args->GetInt(0), - args->GetBool(1))) + EXPECT_TRUE(expectations_->OnRendererComplete( + browser, frame, args->GetInt(0), args->GetBool(1))) << "nav = " << nav_; return true; } @@ -580,7 +585,7 @@ class FrameNavExpectationsBrowserSingleNav } else { EXPECT_FALSE(got_loading_state_change_end_); got_loading_state_change_end_.yes(); - SignalCompleteIfDone(browser); + SignalCompleteIfDone(browser, browser->GetMainFrame()); } return true; } @@ -596,7 +601,7 @@ class FrameNavExpectationsBrowserSingleNav CefRefPtr frame) override { EXPECT_FALSE(got_load_end_); got_load_end_.yes(); - SignalCompleteIfDone(browser); + SignalCompleteIfDone(browser, frame); return true; } @@ -622,13 +627,14 @@ class FrameNavExpectationsBrowserSingleNav } bool OnRendererComplete(CefRefPtr browser, + CefRefPtr frame, int renderer_nav, bool renderer_result) override { EXPECT_EQ(nav(), renderer_nav); EXPECT_TRUE(renderer_result); EXPECT_FALSE(got_renderer_done_); got_renderer_done_.yes(); - SignalCompleteIfDone(browser); + SignalCompleteIfDone(browser, frame); return true; } @@ -650,9 +656,10 @@ class FrameNavExpectationsBrowserSingleNav } private: - void SignalCompleteIfDone(CefRefPtr browser) { + void SignalCompleteIfDone(CefRefPtr browser, + CefRefPtr frame) { if (got_renderer_done_ && got_load_end_ && got_loading_state_change_end_) - SignalComplete(browser); + SignalComplete(browser, frame); } TrackCallback got_load_start_; @@ -685,7 +692,7 @@ class FrameNavExpectationsRendererSingleNav } else { EXPECT_FALSE(got_loading_state_change_end_); got_loading_state_change_end_.yes(); - SignalCompleteIfDone(browser); + SignalCompleteIfDone(browser, browser->GetMainFrame()); } return true; } @@ -701,7 +708,7 @@ class FrameNavExpectationsRendererSingleNav CefRefPtr frame) override { EXPECT_FALSE(got_load_end_); got_load_end_.yes(); - SignalCompleteIfDone(browser); + SignalCompleteIfDone(browser, frame); return true; } @@ -719,9 +726,10 @@ class FrameNavExpectationsRendererSingleNav } private: - void SignalCompleteIfDone(CefRefPtr browser) { + void SignalCompleteIfDone(CefRefPtr browser, + CefRefPtr frame) { if (got_load_end_ && got_loading_state_change_end_) - SignalComplete(browser); + SignalComplete(browser, frame); } TrackCallback got_load_start_; @@ -860,17 +868,12 @@ namespace { bool VerifySingleBrowserFrame(CefRefPtr browser, CefRefPtr frame, - bool frame_should_exist, const std::string& expected_url) { V_DECLARE(); V_EXPECT_TRUE(frame.get()); V_EXPECT_TRUE(frame->IsValid()); const int64 frame_id = frame->GetIdentifier(); - if (frame_should_exist) { - V_EXPECT_TRUE(frame_id >= 0) << frame_id; - } else { - V_EXPECT_TRUE(frame_id == -4) << frame_id; // kInvalidFrameId - } + V_EXPECT_TRUE(frame_id > 0) << frame_id; V_EXPECT_TRUE(frame->IsValid()); V_EXPECT_TRUE(frame->IsMain()); V_EXPECT_TRUE(frame->IsFocused()); @@ -888,46 +891,39 @@ bool VerifySingleBrowserFrame(CefRefPtr browser, bool VerifySingleBrowserFrames(CefRefPtr browser, CefRefPtr frame, - bool frame_should_exist, const std::string& expected_url) { V_DECLARE(); V_EXPECT_TRUE(browser.get()); // |frame| may be NULL for callbacks that don't specify one. if (frame.get()) { - V_EXPECT_TRUE(VerifySingleBrowserFrame(browser, frame, frame_should_exist, - expected_url)); + V_EXPECT_TRUE(VerifySingleBrowserFrame(browser, frame, expected_url)); } CefRefPtr main_frame = browser->GetMainFrame(); - V_EXPECT_TRUE(VerifySingleBrowserFrame(browser, main_frame, - frame_should_exist, expected_url)); + V_EXPECT_TRUE(VerifySingleBrowserFrame(browser, main_frame, expected_url)); CefRefPtr focused_frame = browser->GetFocusedFrame(); - V_EXPECT_TRUE(VerifySingleBrowserFrame(browser, focused_frame, - frame_should_exist, expected_url)); + V_EXPECT_TRUE(VerifySingleBrowserFrame(browser, focused_frame, expected_url)); size_t frame_count = browser->GetFrameCount(); - if (frame_should_exist) { - V_EXPECT_TRUE(frame_count == 1U); + V_EXPECT_TRUE(frame_count == 1U); - std::vector identifiers; - browser->GetFrameIdentifiers(identifiers); - V_EXPECT_TRUE(identifiers.size() == 1U); - if (identifiers.size() == 1U) { - V_EXPECT_TRUE(identifiers[0] == main_frame->GetIdentifier()); - V_EXPECT_TRUE(identifiers[0] == focused_frame->GetIdentifier()); - } + std::vector identifiers; + browser->GetFrameIdentifiers(identifiers); + V_EXPECT_TRUE(identifiers.size() == 1U); + if (identifiers.size() == 1U) { + V_EXPECT_TRUE(identifiers[0] == main_frame->GetIdentifier()); + V_EXPECT_TRUE(identifiers[0] == focused_frame->GetIdentifier()); + } - std::vector names; - browser->GetFrameNames(names); - V_EXPECT_TRUE(names.size() == 1U); - if (names.size() == 1U) { - V_EXPECT_TRUE(names[0].ToString() == main_frame->GetName().ToString()); - V_EXPECT_TRUE(names[0].ToString() == focused_frame->GetName().ToString()); - } - } else { - V_EXPECT_TRUE(frame_count == 0U); + // Names may be empty for callbacks that execute while the frame is loading. + std::vector names; + browser->GetFrameNames(names); + V_EXPECT_TRUE(names.size() <= 1U); + if (names.size() == 1U) { + V_EXPECT_TRUE(names[0].ToString() == main_frame->GetName().ToString()); + V_EXPECT_TRUE(names[0].ToString() == focused_frame->GetName().ToString()); } V_RETURN(); @@ -950,14 +946,8 @@ class FrameNavExpectationsBrowserTestSingleNav bool OnLoadingStateChange(CefRefPtr browser, bool isLoading) override { V_DECLARE(); - if (isLoading) { - // No frame exists before the first load. - V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, NULL, false, std::string())); - } else { - V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, NULL, true, kFrameNavOrigin0)); - } + V_EXPECT_TRUE(VerifySingleBrowserFrames( + browser, NULL, isLoading ? std::string() : kFrameNavOrigin0)); V_EXPECT_TRUE(parent::OnLoadingStateChange(browser, isLoading)); V_RETURN(); } @@ -965,8 +955,7 @@ class FrameNavExpectationsBrowserTestSingleNav bool OnLoadStart(CefRefPtr browser, CefRefPtr frame) override { V_DECLARE(); - V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, frame, true, kFrameNavOrigin0)); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, kFrameNavOrigin0)); V_EXPECT_TRUE(parent::OnLoadStart(browser, frame)); V_RETURN(); } @@ -974,16 +963,14 @@ class FrameNavExpectationsBrowserTestSingleNav bool OnLoadEnd(CefRefPtr browser, CefRefPtr frame) override { V_DECLARE(); - V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, frame, true, kFrameNavOrigin0)); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, kFrameNavOrigin0)); V_EXPECT_TRUE(parent::OnLoadEnd(browser, frame)); V_RETURN(); } bool OnAfterCreated(CefRefPtr browser) override { V_DECLARE(); - V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, NULL, false, std::string())); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, NULL, std::string())); V_EXPECT_TRUE(parent::OnAfterCreated(browser)); V_RETURN(); } @@ -992,10 +979,7 @@ class FrameNavExpectationsBrowserTestSingleNav CefRefPtr frame, const std::string& url) override { V_DECLARE(); - // When browser-side navigation is enabled this method will be called - // before the frame is created. - V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, frame, false, std::string())); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, std::string())); V_EXPECT_TRUE(parent::OnBeforeBrowse(browser, frame, url)); V_RETURN(); } @@ -1003,18 +987,17 @@ class FrameNavExpectationsBrowserTestSingleNav bool GetResourceHandler(CefRefPtr browser, CefRefPtr frame) override { V_DECLARE(); - // When browser-side navigation is enabled, and NetworkService is disabled, - // this method will be called before the frame is created. - V_EXPECT_TRUE(VerifySingleBrowserFrames( - browser, frame, IsNetworkServiceEnabled(), std::string())); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, std::string())); V_EXPECT_TRUE(parent::GetResourceHandler(browser, frame)); V_RETURN(); } bool OnRendererComplete(CefRefPtr browser, + CefRefPtr frame, int renderer_nav, bool renderer_result) override { - return parent::OnRendererComplete(browser, renderer_nav, renderer_result); + return parent::OnRendererComplete(browser, frame, renderer_nav, + renderer_result); } bool Finalize() override { return parent::Finalize(); } @@ -1031,8 +1014,7 @@ class FrameNavExpectationsRendererTestSingleNav bool isLoading) override { V_DECLARE(); // A frame should always exist in the renderer process. - V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, NULL, true, kFrameNavOrigin0)); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, NULL, kFrameNavOrigin0)); V_EXPECT_TRUE(parent::OnLoadingStateChange(browser, isLoading)); V_RETURN(); } @@ -1040,8 +1022,7 @@ class FrameNavExpectationsRendererTestSingleNav bool OnLoadStart(CefRefPtr browser, CefRefPtr frame) override { V_DECLARE(); - V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, frame, true, kFrameNavOrigin0)); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, kFrameNavOrigin0)); V_EXPECT_TRUE(parent::OnLoadStart(browser, frame)); V_RETURN(); } @@ -1049,8 +1030,7 @@ class FrameNavExpectationsRendererTestSingleNav bool OnLoadEnd(CefRefPtr browser, CefRefPtr frame) override { V_DECLARE(); - V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, frame, true, kFrameNavOrigin0)); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, kFrameNavOrigin0)); V_EXPECT_TRUE(parent::OnLoadEnd(browser, frame)); V_RETURN(); } @@ -1113,21 +1093,22 @@ class FrameNavExpectationsBrowserMultiNav : public FrameNavExpectationsBrowser { bool OnLoadingStateChange(CefRefPtr browser, bool isLoading) override { if (!isLoading) - SignalCompleteIfDone(browser); + SignalCompleteIfDone(browser, browser->GetMainFrame()); return true; } bool OnLoadEnd(CefRefPtr browser, CefRefPtr frame) override { - SignalCompleteIfDone(browser); + SignalCompleteIfDone(browser, frame); return true; } bool OnRendererComplete(CefRefPtr browser, + CefRefPtr frame, int renderer_nav, bool renderer_result) override { EXPECT_TRUE(renderer_result); - SignalCompleteIfDone(browser); + SignalCompleteIfDone(browser, frame); return true; } @@ -1141,9 +1122,10 @@ class FrameNavExpectationsBrowserMultiNav : public FrameNavExpectationsBrowser { } private: - void SignalCompleteIfDone(CefRefPtr browser) { + void SignalCompleteIfDone(CefRefPtr browser, + CefRefPtr frame) { if (IsNavigationDone()) - SignalComplete(browser); + SignalComplete(browser, frame); } TrackCallback got_finalize_; @@ -1166,13 +1148,13 @@ class FrameNavExpectationsRendererMultiNav bool OnLoadingStateChange(CefRefPtr browser, bool isLoading) override { if (!isLoading) - SignalCompleteIfDone(browser); + SignalCompleteIfDone(browser, browser->GetMainFrame()); return true; } bool OnLoadEnd(CefRefPtr browser, CefRefPtr frame) override { - SignalCompleteIfDone(browser); + SignalCompleteIfDone(browser, frame); return true; } @@ -1186,9 +1168,10 @@ class FrameNavExpectationsRendererMultiNav } private: - void SignalCompleteIfDone(CefRefPtr browser) { + void SignalCompleteIfDone(CefRefPtr browser, + CefRefPtr frame) { if (IsNavigationDone()) - SignalComplete(browser); + SignalComplete(browser, frame); } TrackCallback got_finalize_; @@ -1272,12 +1255,14 @@ class FrameNavExpectationsBrowserTestMultiNavHarness } bool OnRendererComplete(CefRefPtr browser, + CefRefPtr frame, int renderer_nav, bool renderer_result) override { EXPECT_FALSE(got_renderer_complete_); got_renderer_complete_.yes(); EXPECT_EQ(nav(), renderer_nav); - return parent::OnRendererComplete(browser, renderer_nav, renderer_result); + return parent::OnRendererComplete(browser, frame, renderer_nav, + renderer_result); } bool Finalize() override { @@ -1450,17 +1435,14 @@ class FrameNavExpectationsBrowserTestMultiNav if (!isLoading) got_load_state_change_done_.yes(); V_DECLARE(); - // A frame should exist in all cases except for the very first load. if (isLoading && nav() == 0) { - V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, NULL, false, std::string())); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, NULL, std::string())); } else if (isLoading) { // Expect the URL from the previous load. V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, NULL, true, GetPreviousMainURL())); + VerifySingleBrowserFrames(browser, NULL, GetPreviousMainURL())); } else { - V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, NULL, true, GetMainURL())); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, NULL, GetMainURL())); } V_EXPECT_TRUE(parent::OnLoadingStateChange(browser, isLoading)); V_RETURN(); @@ -1469,8 +1451,7 @@ class FrameNavExpectationsBrowserTestMultiNav bool OnLoadStart(CefRefPtr browser, CefRefPtr frame) override { V_DECLARE(); - V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, frame, true, GetMainURL())); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, GetMainURL())); V_EXPECT_TRUE(parent::OnLoadStart(browser, frame)); V_RETURN(); } @@ -1479,16 +1460,14 @@ class FrameNavExpectationsBrowserTestMultiNav CefRefPtr frame) override { got_load_end_.yes(); V_DECLARE(); - V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, frame, true, GetMainURL())); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, GetMainURL())); V_EXPECT_TRUE(parent::OnLoadEnd(browser, frame)); V_RETURN(); } bool OnAfterCreated(CefRefPtr browser) override { V_DECLARE(); - V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, NULL, false, std::string())); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, NULL, std::string())); V_EXPECT_TRUE(parent::OnAfterCreated(browser)); V_RETURN(); } @@ -1500,10 +1479,7 @@ class FrameNavExpectationsBrowserTestMultiNav std::string expected_url; if (nav() > 0) expected_url = GetPreviousMainURL(); - // When browser-side navigation is enabled this method will be called - // before the frame is created for the first navigation. - V_EXPECT_TRUE(VerifySingleBrowserFrames( - browser, frame, nav() == 0 ? false : true, expected_url)); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, expected_url)); V_EXPECT_TRUE(parent::OnBeforeBrowse(browser, frame, url)); V_RETURN(); } @@ -1514,24 +1490,20 @@ class FrameNavExpectationsBrowserTestMultiNav std::string expected_url; if (nav() > 0) expected_url = GetPreviousMainURL(); - // When browser-side navigation is enabled, and NetworkService is disabled, - // this method will be called before the frame is created for the first - // navigation. - V_EXPECT_TRUE(VerifySingleBrowserFrames( - browser, frame, nav() == 0 ? IsNetworkServiceEnabled() : true, - expected_url)); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, expected_url)); V_EXPECT_TRUE(parent::GetResourceHandler(browser, frame)); V_RETURN(); } bool OnRendererComplete(CefRefPtr browser, + CefRefPtr frame, int renderer_nav, bool renderer_result) override { got_renderer_complete_.yes(); V_DECLARE(); V_EXPECT_TRUE(nav() == renderer_nav); - V_EXPECT_TRUE( - parent::OnRendererComplete(browser, renderer_nav, renderer_result)); + V_EXPECT_TRUE(parent::OnRendererComplete(browser, frame, renderer_nav, + renderer_result)); V_RETURN(); } @@ -1572,8 +1544,7 @@ class FrameNavExpectationsRendererTestMultiNav if (!isLoading) got_load_state_change_done_.yes(); V_DECLARE(); - // A frame should always exist in the renderer process. - V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, NULL, true, GetMainURL())); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, NULL, GetMainURL())); V_EXPECT_TRUE(parent::OnLoadingStateChange(browser, isLoading)); V_RETURN(); } @@ -1581,8 +1552,7 @@ class FrameNavExpectationsRendererTestMultiNav bool OnLoadStart(CefRefPtr browser, CefRefPtr frame) override { V_DECLARE(); - V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, frame, true, GetMainURL())); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, GetMainURL())); V_EXPECT_TRUE(parent::OnLoadStart(browser, frame)); V_RETURN(); } @@ -1591,8 +1561,7 @@ class FrameNavExpectationsRendererTestMultiNav CefRefPtr frame) override { got_load_end_.yes(); V_DECLARE(); - V_EXPECT_TRUE( - VerifySingleBrowserFrames(browser, frame, true, GetMainURL())); + V_EXPECT_TRUE(VerifySingleBrowserFrames(browser, frame, GetMainURL())); V_EXPECT_TRUE(parent::OnLoadEnd(browser, frame)); V_RETURN(); } @@ -1685,6 +1654,28 @@ bool VerifyBrowserIframe(CefRefPtr browser, int64 frame0id, frame1id, frame2id, frame3id; std::string frame0url, frame1url, frame2url, frame3url; + // Verify the GetFrameNames result. + std::set expected_names = {kFrame0Name, kFrame1Name, kFrame2Name, + kFrame3Name}; + + std::vector names; + browser->GetFrameNames(names); + V_EXPECT_TRUE(names.size() == expected_names.size()) + << "expected: " << expected_names.size() << " actual: " << names.size(); + + for (const auto& name : names) { + const std::string& nameStr = name; + auto it = expected_names.find(nameStr); + V_EXPECT_FALSE(it == expected_names.end()) + << "Unexpected name: \"" << nameStr << "\""; + if (it != expected_names.end()) + expected_names.erase(it); + } + + for (const auto& name : expected_names) { + V_EXPECT_FALSE(true) << "Missing name: \"" << name << "\""; + } + // Find frames by name. frame0 = browser->GetFrame(kFrame0Name); V_EXPECT_TRUE(frame0.get()); @@ -1695,6 +1686,10 @@ bool VerifyBrowserIframe(CefRefPtr browser, frame3 = browser->GetFrame(kFrame3Name); V_EXPECT_TRUE(frame3.get()); + if (!frame0 || !frame1 || !frame2 || !frame3) { + V_RETURN(); + } + // Verify that the name matches. V_EXPECT_TRUE(frame0->GetName().ToString() == kFrame0Name) << "expected: " << kFrame0Name @@ -1762,6 +1757,10 @@ bool VerifyBrowserIframe(CefRefPtr browser, frame3b = browser->GetFrame(frame3->GetIdentifier()); V_EXPECT_TRUE(frame3b.get()); + if (!frame0b || !frame1b || !frame2b || !frame3b) { + V_RETURN(); + } + // Verify that the id matches. V_EXPECT_TRUE(frame0b->GetIdentifier() == frame0id) << "expected: " << frame0id << " actual: " << frame0b->GetIdentifier(); @@ -1773,33 +1772,26 @@ bool VerifyBrowserIframe(CefRefPtr browser, << "expected: " << frame3id << " actual: " << frame3b->GetIdentifier(); size_t frame_count = browser->GetFrameCount(); - V_EXPECT_TRUE(frame_count == 4U) << "actual: " << frame_count; - - // Verify the GetFrameNames result. - std::vector names; - browser->GetFrameNames(names); - V_EXPECT_TRUE(names.size() == 4U) << "actual: " << names.size(); - V_EXPECT_TRUE(names[0].ToString() == kFrame0Name) - << "expected: " << kFrame0Name << " actual: " << names[0].ToString(); - V_EXPECT_TRUE(names[1].ToString() == kFrame1Name) - << "expected: " << kFrame1Name << " actual: " << names[1].ToString(); - V_EXPECT_TRUE(names[2].ToString() == kFrame2Name) - << "expected: " << kFrame2Name << " actual: " << names[2].ToString(); - V_EXPECT_TRUE(names[3].ToString() == kFrame3Name) - << "expected: " << kFrame3Name << " actual: " << names[3].ToString(); + V_EXPECT_TRUE(frame_count == 4U) << " actual: " << frame_count; // Verify the GetFrameIdentifiers result. + std::set expected_idents = {frame0id, frame1id, frame2id, frame3id}; + std::vector idents; browser->GetFrameIdentifiers(idents); - V_EXPECT_TRUE(idents.size() == 4U) << "actual: " << idents.size(); - V_EXPECT_TRUE(idents[0] == frame0id) - << "expected: " << frame0id << " actual: " << idents[0]; - V_EXPECT_TRUE(idents[1] == frame1id) - << "expected: " << frame1id << " actual: " << idents[1]; - V_EXPECT_TRUE(idents[2] == frame2id) - << "expected: " << frame2id << " actual: " << idents[2]; - V_EXPECT_TRUE(idents[3] == frame3id) - << "expected: " << frame3id << " actual: " << idents[3]; + V_EXPECT_TRUE(idents.size() == expected_idents.size()) + << "expected: " << expected_idents.size() << " actual: " << idents.size(); + + for (const auto& ident : idents) { + auto it = expected_idents.find(ident); + V_EXPECT_FALSE(it == expected_idents.end()) << "Unexpected id: " << ident; + if (it != expected_idents.end()) + expected_idents.erase(it); + } + + for (const auto& ident : expected_idents) { + V_EXPECT_FALSE(true) << "Missing id: " << ident; + } // Verify parent hierarchy. V_EXPECT_FALSE(frame0->GetParent().get()); @@ -1996,6 +1988,7 @@ class FrameNavExpectationsBrowserTestNestedIframes } bool OnRendererComplete(CefRefPtr browser, + CefRefPtr frame, int renderer_nav, bool renderer_result) override { V_DECLARE(); @@ -2009,8 +2002,8 @@ class FrameNavExpectationsBrowserTestNestedIframes got_renderer_complete_.yes(); - V_EXPECT_TRUE( - parent::OnRendererComplete(browser, renderer_nav, renderer_result)); + V_EXPECT_TRUE(parent::OnRendererComplete(browser, frame, renderer_nav, + renderer_result)); V_RETURN(); } diff --git a/tests/ceftests/message_router_unittest.cc b/tests/ceftests/message_router_unittest.cc index 66a3f9604..f51950d4e 100644 --- a/tests/ceftests/message_router_unittest.cc +++ b/tests/ceftests/message_router_unittest.cc @@ -56,19 +56,13 @@ class MRRenderDelegate : public ClientAppRenderer::Delegate { const CefString& msg = arguments[0]->GetStringValue(); CefRefPtr context = CefV8Context::GetCurrentContext(); - CefRefPtr browser = context->GetBrowser(); CefRefPtr frame = context->GetFrame(); - const int64 frame_id = frame->GetIdentifier(); - const bool is_main_frame = frame->IsMain(); CefRefPtr message = CefProcessMessage::Create(kDoneMessageName); CefRefPtr args = message->GetArgumentList(); - args->SetInt(0, CefInt64GetLow(frame_id)); - args->SetInt(1, CefInt64GetHigh(frame_id)); - args->SetBool(2, is_main_frame); - args->SetString(3, msg); - EXPECT_TRUE(browser->SendProcessMessage(PID_BROWSER, message)); + args->SetString(0, msg); + frame->SendProcessMessage(PID_BROWSER, message); return true; } else { EXPECT_EQ(1U, arguments.size()); @@ -166,14 +160,15 @@ class MRRenderDelegate : public ClientAppRenderer::Delegate { bool OnProcessMessageReceived(CefRefPtr app, CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { const std::string& url = browser->GetMainFrame()->GetURL(); if (url.find(kTestDomainRoot) != 0) return false; - return message_router_->OnProcessMessageReceived(browser, source_process, - message); + return message_router_->OnProcessMessageReceived(browser, frame, + source_process, message); } private: @@ -237,32 +232,20 @@ class MRTestHandler : public TestHandler { // Returns true if the router handled the navigation. bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { const std::string& message_name = message->GetName(); if (message_name == kDoneMessageName) { CefRefPtr args = message->GetArgumentList(); - EXPECT_EQ(4U, args->GetSize()); - EXPECT_EQ(VTYPE_INT, args->GetType(0)); - EXPECT_EQ(VTYPE_INT, args->GetType(1)); - EXPECT_EQ(VTYPE_BOOL, args->GetType(2)); - EXPECT_EQ(VTYPE_STRING, args->GetType(3)); - - const int64 frame_id = CefInt64Set(args->GetInt(0), args->GetInt(1)); - const bool is_main_frame = args->GetBool(2); - CefRefPtr frame; - if (is_main_frame) - frame = browser->GetMainFrame(); - else - frame = browser->GetFrame(frame_id); - EXPECT_TRUE(frame.get()); - - OnNotify(browser, frame, args->GetString(3)); + EXPECT_EQ(1U, args->GetSize()); + EXPECT_EQ(VTYPE_STRING, args->GetType(0)); + OnNotify(browser, frame, args->GetString(0)); return true; } - return message_router_->OnProcessMessageReceived(browser, source_process, - message); + return message_router_->OnProcessMessageReceived(browser, frame, + source_process, message); } CefRefPtr GetRouter() const { diff --git a/tests/ceftests/navigation_unittest.cc b/tests/ceftests/navigation_unittest.cc index 3b027e54d..c723ecb58 100644 --- a/tests/ceftests/navigation_unittest.cc +++ b/tests/ceftests/navigation_unittest.cc @@ -120,7 +120,7 @@ class HistoryNavRendererTest : public ClientAppRenderer::Delegate, got_loading_state_start_.yes(); } else { got_loading_state_end_.yes(); - SendTestResultsIfDone(browser); + SendTestResultsIfDone(browser, browser->GetMainFrame()); } } @@ -153,17 +153,19 @@ class HistoryNavRendererTest : public ClientAppRenderer::Delegate, EXPECT_EQ(item.can_go_back, browser->CanGoBack()); EXPECT_EQ(item.can_go_forward, browser->CanGoForward()); - SendTestResultsIfDone(browser); + SendTestResultsIfDone(browser, frame); } protected: - void SendTestResultsIfDone(CefRefPtr browser) { + void SendTestResultsIfDone(CefRefPtr browser, + CefRefPtr frame) { if (got_load_end_ && got_loading_state_end_) - SendTestResults(browser); + SendTestResults(browser, frame); } // Send the test results. - void SendTestResults(CefRefPtr browser) { + void SendTestResults(CefRefPtr browser, + CefRefPtr frame) { EXPECT_TRUE(got_loading_state_start_); EXPECT_TRUE(got_loading_state_end_); EXPECT_TRUE(got_load_start_); @@ -179,7 +181,7 @@ class HistoryNavRendererTest : public ClientAppRenderer::Delegate, EXPECT_TRUE(args.get()); EXPECT_TRUE(args->SetInt(0, nav_)); EXPECT_TRUE(args->SetBool(1, result)); - EXPECT_TRUE(browser->SendProcessMessage(PID_BROWSER, return_msg)); + frame->SendProcessMessage(PID_BROWSER, return_msg); // Reset the test results for the next navigation. got_loading_state_start_.reset(); @@ -489,6 +491,7 @@ class HistoryNavTestHandler : public TestHandler { } bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { if (message->GetName().ToString() == kHistoryNavMsg) { @@ -1263,7 +1266,8 @@ class OrderNavRendererTest : public ClientAppRenderer::Delegate, EXPECT_GT(browser->GetIdentifier(), 0); // Use |browser_main_| to send the message otherwise it will fail. - SendTestResults(browser_main_, kOrderNavClosedMsg); + SendTestResults(browser_main_, browser_main_->GetMainFrame(), + kOrderNavClosedMsg); } else { EXPECT_TRUE(got_browser_created_main_); EXPECT_FALSE(got_browser_destroyed_main_); @@ -1307,7 +1311,7 @@ class OrderNavRendererTest : public ClientAppRenderer::Delegate, } if (!isLoading) - SendTestResultsIfDone(browser); + SendTestResultsIfDone(browser, browser->GetMainFrame()); } void OnLoadStart(CefRefPtr browser, @@ -1347,7 +1351,7 @@ class OrderNavRendererTest : public ClientAppRenderer::Delegate, state_main_.OnLoadEnd(browser, frame, httpStatusCode); } - SendTestResultsIfDone(browser); + SendTestResultsIfDone(browser, frame); } void OnLoadError(CefRefPtr browser, @@ -1360,7 +1364,8 @@ class OrderNavRendererTest : public ClientAppRenderer::Delegate, } protected: - void SendTestResultsIfDone(CefRefPtr browser) { + void SendTestResultsIfDone(CefRefPtr browser, + CefRefPtr frame) { bool done = false; if (browser->IsPopup()) done = state_popup_.IsDone(); @@ -1368,11 +1373,13 @@ class OrderNavRendererTest : public ClientAppRenderer::Delegate, done = state_main_.IsDone(); if (done) - SendTestResults(browser, kOrderNavMsg); + SendTestResults(browser, frame, kOrderNavMsg); } // Send the test results. - void SendTestResults(CefRefPtr browser, const char* msg_name) { + void SendTestResults(CefRefPtr browser, + CefRefPtr frame, + const char* msg_name) { // Check if the test has failed. bool result = !TestFailed(); @@ -1386,7 +1393,7 @@ class OrderNavRendererTest : public ClientAppRenderer::Delegate, EXPECT_TRUE(args->SetInt(1, browser_id_popup_)); else EXPECT_TRUE(args->SetInt(1, browser_id_main_)); - EXPECT_TRUE(browser->SendProcessMessage(PID_BROWSER, return_msg)); + frame->SendProcessMessage(PID_BROWSER, return_msg); } bool run_test_; @@ -1566,6 +1573,7 @@ class OrderNavTestHandler : public TestHandler { } bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { if (browser->IsPopup()) { @@ -1759,13 +1767,14 @@ class LoadNavRendererTest : public ClientAppRenderer::Delegate, EXPECT_EQ(browser_id_, browser->GetIdentifier()); load_ct_++; - SendTestResults(browser); + SendTestResults(browser, browser->GetMainFrame()); } } protected: // Send the test results. - void SendTestResults(CefRefPtr browser) { + void SendTestResults(CefRefPtr browser, + CefRefPtr frame) { // Check if the test has failed. bool result = !TestFailed(); @@ -1777,7 +1786,7 @@ class LoadNavRendererTest : public ClientAppRenderer::Delegate, EXPECT_TRUE(args->SetBool(0, result)); EXPECT_TRUE(args->SetInt(1, browser->GetIdentifier())); EXPECT_TRUE(args->SetInt(2, load_ct_)); - EXPECT_TRUE(browser->SendProcessMessage(PID_BROWSER, return_msg)); + frame->SendProcessMessage(PID_BROWSER, return_msg); } bool run_test_; @@ -2015,6 +2024,7 @@ class LoadNavTestHandler : public TestHandler { } bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { EXPECT_GT(browser_id_current_, 0); @@ -3486,12 +3496,13 @@ class ExtraInfoNavRendererTest : public ClientAppRenderer::Delegate { SetBrowserExtraInfo(expected); TestDictionaryEqual(expected, extra_info); - SendTestResults(browser); + SendTestResults(browser, browser->GetMainFrame()); } protected: // Send the test results. - void SendTestResults(CefRefPtr browser) { + void SendTestResults(CefRefPtr browser, + CefRefPtr frame) { // Check if the test has failed. bool result = !TestFailed(); @@ -3501,7 +3512,7 @@ class ExtraInfoNavRendererTest : public ClientAppRenderer::Delegate { EXPECT_TRUE(args.get()); EXPECT_TRUE(args->SetBool(0, result)); EXPECT_TRUE(args->SetBool(1, browser->IsPopup())); - EXPECT_TRUE(browser->SendProcessMessage(PID_BROWSER, return_msg)); + frame->SendProcessMessage(PID_BROWSER, return_msg); } bool run_test_; @@ -3567,6 +3578,7 @@ class ExtraInfoNavTestHandler : public TestHandler { } bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { if (message->GetName().ToString() == kExtraInfoNavMsg) { diff --git a/tests/ceftests/process_message_unittest.cc b/tests/ceftests/process_message_unittest.cc index 8352f2039..262612871 100644 --- a/tests/ceftests/process_message_unittest.cc +++ b/tests/ceftests/process_message_unittest.cc @@ -47,17 +47,19 @@ class SendRecvRendererTest : public ClientAppRenderer::Delegate { bool OnProcessMessageReceived(CefRefPtr app, CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { if (message->GetName() == kSendRecvMsg) { EXPECT_TRUE(browser.get()); + EXPECT_TRUE(frame.get()); EXPECT_EQ(PID_BROWSER, source_process); EXPECT_TRUE(message.get()); - std::string url = browser->GetMainFrame()->GetURL(); + const std::string& url = frame->GetURL(); if (url == kSendRecvUrl) { // Echo the message back to the sender natively. - EXPECT_TRUE(browser->SendProcessMessage(PID_BROWSER, message)); + frame->SendProcessMessage(PID_BROWSER, message); return true; } } @@ -92,18 +94,20 @@ class SendRecvTestHandler : public TestHandler { // Send the message to the renderer process. if (!CefCurrentlyOn(send_thread_)) { - CefPostTask(send_thread_, - base::Bind(&SendRecvTestHandler::SendMessage, this, browser)); + CefPostTask(send_thread_, base::Bind(&SendRecvTestHandler::SendMessage, + this, browser, frame)); } else { - SendMessage(browser); + SendMessage(browser, frame); } } bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { EXPECT_TRUE(CefCurrentlyOn(TID_UI)); EXPECT_TRUE(browser.get()); + EXPECT_TRUE(frame.get()); EXPECT_EQ(PID_RENDERER, source_process); EXPECT_TRUE(message.get()); EXPECT_TRUE(message->IsReadOnly()); @@ -126,9 +130,9 @@ class SendRecvTestHandler : public TestHandler { } private: - void SendMessage(CefRefPtr browser) { + void SendMessage(CefRefPtr browser, CefRefPtr frame) { EXPECT_TRUE(CefCurrentlyOn(send_thread_)); - EXPECT_TRUE(browser->SendProcessMessage(PID_RENDERER, message_)); + frame->SendProcessMessage(PID_RENDERER, message_); } cef_thread_id_t send_thread_; diff --git a/tests/ceftests/request_handler_unittest.cc b/tests/ceftests/request_handler_unittest.cc index 55ce732dc..ecac667d4 100644 --- a/tests/ceftests/request_handler_unittest.cc +++ b/tests/ceftests/request_handler_unittest.cc @@ -6,6 +6,7 @@ #include #include #include +#include #include "include/base/cef_bind.h" #include "include/base/cef_scoped_ptr.h" @@ -199,10 +200,10 @@ class NetNotifyTestHandler : public TestHandler { CefRefPtr args = message->GetArgumentList(); args->SetInt(0, test_type_); args->SetString(1, url); - EXPECT_TRUE(browser->SendProcessMessage(PID_RENDERER, message)); + frame->SendProcessMessage(PID_RENDERER, message); } else { // Load the URL from the browser process. - browser->GetMainFrame()->LoadURL(url); + frame->LoadURL(url); } // Cancel the load. @@ -232,6 +233,7 @@ class NetNotifyTestHandler : public TestHandler { } bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { if (message->GetName().ToString() == kNetNotifyMsg) { @@ -405,11 +407,12 @@ class NetNotifyRendererTest : public ClientAppRenderer::Delegate, CefProcessMessage::Create(kNetNotifyMsg); CefRefPtr args = message->GetArgumentList(); args->SetString(0, url); - EXPECT_TRUE(browser->SendProcessMessage(PID_BROWSER, message)); + frame->SendProcessMessage(PID_BROWSER, message); } bool OnProcessMessageReceived(CefRefPtr app, CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { if (message->GetName().ToString() == kNetNotifyMsg) { @@ -423,7 +426,7 @@ class NetNotifyRendererTest : public ClientAppRenderer::Delegate, const std::string& url = args->GetString(1); // Load the URL from the render process. - browser->GetMainFrame()->LoadURL(url); + frame->LoadURL(url); return true; } @@ -437,28 +440,29 @@ class NetNotifyRendererTest : public ClientAppRenderer::Delegate, IMPLEMENT_REFCOUNTING(NetNotifyRendererTest); }; -void RunNetNotifyTest(NetNotifyTestType test_type, bool same_origin) { +void RunNetNotifyTest(NetNotifyTestType test_type, + bool same_origin, + size_t count = 3U) { g_net_notify_test = true; - TestHandler::CompletionState completion_state(3); - - CefRefPtr handler1 = - new NetNotifyTestHandler(&completion_state, test_type, same_origin); - CefRefPtr handler2 = - new NetNotifyTestHandler(&completion_state, test_type, same_origin); - CefRefPtr handler3 = - new NetNotifyTestHandler(&completion_state, test_type, same_origin); - + TestHandler::CompletionState completion_state(count); TestHandler::Collection collection(&completion_state); - collection.AddTestHandler(handler1.get()); - collection.AddTestHandler(handler2.get()); - collection.AddTestHandler(handler3.get()); + + std::vector> handlers; + for (size_t i = 0U; i < count; ++i) { + CefRefPtr handler = + new NetNotifyTestHandler(&completion_state, test_type, same_origin); + collection.AddTestHandler(handler); + handlers.push_back(handler); + } collection.ExecuteTests(); - ReleaseAndWaitForDestructor(handler1); - ReleaseAndWaitForDestructor(handler2); - ReleaseAndWaitForDestructor(handler3); + while (!handlers.empty()) { + auto handler = handlers.front(); + handlers.erase(handlers.begin()); + ReleaseAndWaitForDestructor(handler); + } g_net_notify_test = false; } diff --git a/tests/ceftests/routing_test_handler.cc b/tests/ceftests/routing_test_handler.cc index f380625bf..0f02ced13 100644 --- a/tests/ceftests/routing_test_handler.cc +++ b/tests/ceftests/routing_test_handler.cc @@ -42,10 +42,11 @@ class RoutingRenderDelegate : public ClientAppRenderer::Delegate { bool OnProcessMessageReceived(CefRefPtr app, CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { - return message_router_->OnProcessMessageReceived(browser, source_process, - message); + return message_router_->OnProcessMessageReceived(browser, frame, + source_process, message); } private: @@ -91,10 +92,11 @@ bool RoutingTestHandler::OnBeforeBrowse(CefRefPtr browser, bool RoutingTestHandler::OnProcessMessageReceived( CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) { - return message_router_->OnProcessMessageReceived(browser, source_process, - message); + return message_router_->OnProcessMessageReceived(browser, frame, + source_process, message); } // Entry point for creating the test delegate. diff --git a/tests/ceftests/routing_test_handler.h b/tests/ceftests/routing_test_handler.h index 16a33dd33..89f820c95 100644 --- a/tests/ceftests/routing_test_handler.h +++ b/tests/ceftests/routing_test_handler.h @@ -31,6 +31,7 @@ class RoutingTestHandler : public TestHandler, // Returns true if the router handled the navigation. bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override; diff --git a/tests/ceftests/test_handler.h b/tests/ceftests/test_handler.h index 6c7681dfb..96b31373d 100644 --- a/tests/ceftests/test_handler.h +++ b/tests/ceftests/test_handler.h @@ -58,7 +58,6 @@ class TestHandler : public CefClient, public CefDialogHandler, public CefDisplayHandler, public CefDownloadHandler, - public CefDragHandler, public CefJSDialogHandler, public CefLifeSpanHandler, public CefLoadHandler, @@ -155,7 +154,6 @@ class TestHandler : public CefClient, CefRefPtr GetDialogHandler() override { return this; } CefRefPtr GetDisplayHandler() override { return this; } CefRefPtr GetDownloadHandler() override { return this; } - CefRefPtr GetDragHandler() override { return this; } CefRefPtr GetJSDialogHandler() override { return this; } CefRefPtr GetLifeSpanHandler() override { return this; } CefRefPtr GetLoadHandler() override { return this; } @@ -168,11 +166,6 @@ class TestHandler : public CefClient, const CefString& suggested_name, CefRefPtr callback) override {} - // CefDragHandler methods - void OnDraggableRegionsChanged( - CefRefPtr browser, - const std::vector& regions) override {} - // CefLifeSpanHandler methods void OnAfterCreated(CefRefPtr browser) override; void OnBeforeClose(CefRefPtr browser) override; diff --git a/tests/ceftests/thread_unittest.cc b/tests/ceftests/thread_unittest.cc index 3eaca7a2f..db2390970 100644 --- a/tests/ceftests/thread_unittest.cc +++ b/tests/ceftests/thread_unittest.cc @@ -323,14 +323,16 @@ class RenderThreadTestHandler : public TestHandler { // Return the test in the render process. CefRefPtr msg = CefProcessMessage::Create(kRenderThreadTestMsg); - EXPECT_TRUE(browser->SendProcessMessage(PID_RENDERER, msg)); + browser->GetMainFrame()->SendProcessMessage(PID_RENDERER, msg); } } bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { EXPECT_TRUE(browser.get()); + EXPECT_TRUE(frame.get()); EXPECT_EQ(PID_RENDERER, source_process); EXPECT_TRUE(message.get()); EXPECT_TRUE(message->IsReadOnly()); @@ -371,6 +373,7 @@ class RenderThreadRendererTest : public ClientAppRenderer::Delegate { bool OnProcessMessageReceived(CefRefPtr app, CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { if (message->GetName().ToString() == kRenderThreadTestMsg) { @@ -408,7 +411,7 @@ class RenderThreadRendererTest : public ClientAppRenderer::Delegate { CefRefPtr return_msg = CefProcessMessage::Create(kRenderThreadTestMsg); EXPECT_TRUE(return_msg->GetArgumentList()->SetBool(0, result)); - EXPECT_TRUE(browser_->SendProcessMessage(PID_BROWSER, return_msg)); + browser_->GetMainFrame()->SendProcessMessage(PID_BROWSER, return_msg); browser_ = nullptr; } diff --git a/tests/ceftests/urlrequest_unittest.cc b/tests/ceftests/urlrequest_unittest.cc index 866de05a9..75d999e30 100644 --- a/tests/ceftests/urlrequest_unittest.cc +++ b/tests/ceftests/urlrequest_unittest.cc @@ -2056,10 +2056,12 @@ class RequestRendererTest : public ClientAppRenderer::Delegate { bool OnProcessMessageReceived(CefRefPtr app, CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { if (message->GetName() == kRequestTestMsg) { EXPECT_TRUE(CefCurrentlyOn(TID_RENDERER)); + EXPECT_TRUE(frame->IsMain()); app_ = app; browser_ = browser; @@ -2069,7 +2071,7 @@ class RequestRendererTest : public ClientAppRenderer::Delegate { const bool use_frame_method = args->GetBool(2); if (use_frame_method) - frame_ = browser->GetMainFrame(); + frame_ = frame; test_mode_ = static_cast(args->GetInt(0)); test_runner_ = new RequestTestRunner(false, args->GetBool(1), @@ -2115,7 +2117,7 @@ class RequestRendererTest : public ClientAppRenderer::Delegate { CefRefPtr return_msg = CefProcessMessage::Create(kRequestTestMsg); EXPECT_TRUE(return_msg->GetArgumentList()->SetBool(0, result)); - EXPECT_TRUE(browser_->SendProcessMessage(PID_BROWSER, return_msg)); + browser_->GetMainFrame()->SendProcessMessage(PID_BROWSER, return_msg); app_ = NULL; browser_ = NULL; @@ -2315,14 +2317,16 @@ class RequestTestHandler : public TestHandler { test_running_ = true; // Send a message to the renderer process to run the test. - EXPECT_TRUE(browser->SendProcessMessage(PID_RENDERER, test_message)); + frame->SendProcessMessage(PID_RENDERER, test_message); } } bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { EXPECT_TRUE(browser.get()); + EXPECT_TRUE(frame.get()); EXPECT_EQ(PID_RENDERER, source_process); EXPECT_TRUE(message.get()); EXPECT_TRUE(message->IsReadOnly()); diff --git a/tests/ceftests/v8_unittest.cc b/tests/ceftests/v8_unittest.cc index e3c9c969c..9bb2de2b7 100644 --- a/tests/ceftests/v8_unittest.cc +++ b/tests/ceftests/v8_unittest.cc @@ -2715,6 +2715,7 @@ class V8RendererTest : public ClientAppRenderer::Delegate, bool OnProcessMessageReceived(CefRefPtr app, CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { if (test_mode_ == V8TEST_NONE) @@ -2807,7 +2808,7 @@ class V8RendererTest : public ClientAppRenderer::Delegate, CefRefPtr return_msg = CefProcessMessage::Create(kV8TestMsg); EXPECT_TRUE(return_msg->GetArgumentList()->SetBool(0, result)); - EXPECT_TRUE(browser_->SendProcessMessage(PID_BROWSER, return_msg)); + browser_->GetMainFrame()->SendProcessMessage(PID_BROWSER, return_msg); app_ = NULL; browser_ = NULL; @@ -2994,14 +2995,17 @@ class V8TestHandler : public TestHandler { // Run the test. CefRefPtr return_msg = CefProcessMessage::Create(kV8RunTestMsg); - EXPECT_TRUE(browser->SendProcessMessage(PID_RENDERER, return_msg)); + frame->SendProcessMessage(PID_RENDERER, return_msg); } } bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) override { EXPECT_TRUE(browser.get()); + EXPECT_TRUE(frame.get()); + EXPECT_TRUE(frame->IsMain()); EXPECT_EQ(PID_RENDERER, source_process); EXPECT_TRUE(message.get()); EXPECT_TRUE(message->IsReadOnly()); diff --git a/tests/shared/renderer/client_app_renderer.cc b/tests/shared/renderer/client_app_renderer.cc index 96ac30620..b2020a5e2 100644 --- a/tests/shared/renderer/client_app_renderer.cc +++ b/tests/shared/renderer/client_app_renderer.cc @@ -87,6 +87,7 @@ void ClientAppRenderer::OnFocusedNodeChanged(CefRefPtr browser, bool ClientAppRenderer::OnProcessMessageReceived( CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) { DCHECK_EQ(source_process, PID_BROWSER); @@ -95,8 +96,8 @@ bool ClientAppRenderer::OnProcessMessageReceived( DelegateSet::iterator it = delegates_.begin(); for (; it != delegates_.end() && !handled; ++it) { - handled = - (*it)->OnProcessMessageReceived(this, browser, source_process, message); + handled = (*it)->OnProcessMessageReceived(this, browser, frame, + source_process, message); } return handled; diff --git a/tests/shared/renderer/client_app_renderer.h b/tests/shared/renderer/client_app_renderer.h index 1e4b3bb98..38b25950d 100644 --- a/tests/shared/renderer/client_app_renderer.h +++ b/tests/shared/renderer/client_app_renderer.h @@ -66,6 +66,7 @@ class ClientAppRenderer : public ClientApp, public CefRenderProcessHandler { virtual bool OnProcessMessageReceived( CefRefPtr app, CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) { return false; @@ -108,6 +109,7 @@ class ClientAppRenderer : public ClientApp, public CefRenderProcessHandler { CefRefPtr frame, CefRefPtr node) OVERRIDE; bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) OVERRIDE;