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:
Marshall Greenblatt
2019-05-24 23:23:43 +03:00
parent 35295d2e27
commit 241941a44a
80 changed files with 2382 additions and 2378 deletions

View File

@@ -6,30 +6,50 @@
#define CEF_LIBCEF_BROWSER_FRAME_HOST_IMPL_H_
#pragma once
#include <memory>
#include <queue>
#include <string>
#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<CefBrowserInfo> 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<CefBrowserInfo> 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<CefURLRequest> CreateURLRequest(
CefRefPtr<CefRequest> request,
CefRefPtr<CefURLRequestClient> client) override;
void SendProcessMessage(CefProcessId target_process,
CefRefPtr<CefProcessMessage> 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<CefResponseManager::Handler> 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<CefResponseManager::Handler> 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<CefResponseManager::Handler> 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<CefBrowserHostImpl> GetBrowserHostImpl() const;
// OnMessageReceived message handlers.
void OnAttached();
void OnFocused();
void OnDidFinishLoad(const GURL& validated_url, int http_status_code);
void OnUpdateDraggableRegions(
const std::vector<Cef_DraggableRegion_Params>& 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<CefBrowserInfo> 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<std::unique_ptr<IPC::Message>> queued_messages_;
// Manages response registrations.
std::unique_ptr<CefResponseManager> response_manager_;
IMPLEMENT_REFCOUNTING(CefFrameHostImpl);
DISALLOW_COPY_AND_ASSIGN(CefFrameHostImpl);
};