mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Move message routing from CefBrowser to CefFrame (see issue #2498).
This change moves the SendProcessMessage method from CefBrowser to CefFrame and adds CefBrowser parameters to OnProcessMessageReceived and OnDraggableRegionsChanged. The internal implementation has changed as follows: - Frame IDs are now a 64-bit combination of the 32-bit render_process_id and render_routing_id values that uniquely identify a RenderFrameHost (RFH). - CefFrameHostImpl objects are now managed by CefBrowserInfo with life span tied to RFH expectations. Specifically, a CefFrameHostImpl object representing a sub-frame will be created when a RenderFrame is created in the renderer process and detached when the associated RenderFrame is deleted or the renderer process in which it runs has died. - The CefFrameHostImpl object representing the main frame will always be valid but the underlying RFH (and associated frame ID) may change over time as a result of cross-origin navigations. Despite these changes calling LoadURL on the main frame object in the browser process will always navigate as expected. - Speculative RFHs, which may be created as a result of a cross-origin navigation and discarded if that navigation is not committed, are now handled correctly (e.g. ignored in most cases until they're committed). - It is less likely, but still possible, to receive a CefFrame object with an invalid frame ID (ID < 0). This can happen in cases where a RFH has not yet been created for a sub-frame. For example, when OnBeforeBrowse is called before initiating navigation in a previously nonexisting sub-frame. To test: All tests pass with NetworkService enabled and disabled.
This commit is contained in:
@@ -7,135 +7,171 @@
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
#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<CefBrowserInfo> {
|
||||
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<std::pair<int, int>> 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<int> 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<CefDictionaryValue> extra_info);
|
||||
|
||||
int browser_id() const { return browser_id_; }
|
||||
bool is_popup() const { return is_popup_; }
|
||||
bool is_windowless() const { return is_windowless_; }
|
||||
|
||||
CefRefPtr<CefDictionaryValue> 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<CefBrowserHostImpl> browser() const;
|
||||
void set_browser(CefRefPtr<CefBrowserHostImpl> browser);
|
||||
|
||||
// Set or clear the browser. Called from the CefBrowserHostImpl constructor
|
||||
// (to set) and DestroyBrowser (to clear).
|
||||
void SetBrowser(CefRefPtr<CefBrowserHostImpl> 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<CefFrameHostImpl> 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<CefFrameHostImpl> 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<CefFrameHostImpl> 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<CefFrameHostImpl> 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<CefFrameHostImpl> 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<CefFrameHostImpl> 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<CefRefPtr<CefFrameHostImpl>> FrameHostList;
|
||||
FrameHostList GetAllFrames() const;
|
||||
|
||||
private:
|
||||
friend class base::RefCountedThreadSafe<CefBrowserInfo>;
|
||||
|
||||
~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<CefFrameHostImpl> frame_;
|
||||
};
|
||||
|
||||
void MaybeUpdateFrameTreeNodeIdMap(FrameInfo* info);
|
||||
|
||||
CefRefPtr<CefFrameHostImpl> GetFrameForFrameTreeNodeInternal(
|
||||
int frame_tree_node_id,
|
||||
bool* is_guest_view = nullptr) const;
|
||||
|
||||
void RemoveAllFrames();
|
||||
|
||||
int browser_id_;
|
||||
bool is_popup_;
|
||||
bool is_windowless_;
|
||||
CefRefPtr<CefDictionaryValue> 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<CefBrowserHostImpl> browser_;
|
||||
|
||||
CefRefPtr<CefDictionaryValue> extra_info_;
|
||||
// Owner of FrameInfo structs.
|
||||
typedef std::set<std::unique_ptr<FrameInfo>, 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<int64_t, FrameInfo*> FrameIDMap;
|
||||
FrameIDMap frame_id_map_;
|
||||
|
||||
// Map a frame_tree_node_id to one frame.
|
||||
typedef std::unordered_map<int, FrameInfo*> FrameTreeNodeIDMap;
|
||||
FrameTreeNodeIDMap frame_tree_node_id_map_;
|
||||
|
||||
// The current main frame.
|
||||
CefRefPtr<CefFrameHostImpl> main_frame_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefBrowserInfo);
|
||||
};
|
||||
|
Reference in New Issue
Block a user