cef/libcef/renderer/frame_impl.cc

815 lines
26 KiB
C++
Raw Normal View History

// Copyright (c) 2012 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/renderer/frame_impl.h"
#include "build/build_config.h"
// Enable deprecation warnings on Windows. See http://crbug.com/585142.
#if BUILDFLAG(IS_WIN)
#if defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wdeprecated-declarations"
#else
#pragma warning(push)
#pragma warning(default : 4996)
#endif
#endif
#include "include/cef_urlrequest.h"
#include "libcef/common/app_manager.h"
#include "libcef/common/frame_util.h"
#include "libcef/common/net/http_header_utils.h"
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.
2019-05-24 22:23:43 +02:00
#include "libcef/common/process_message_impl.h"
#include "libcef/common/process_message_smr_impl.h"
#include "libcef/common/request_impl.h"
#include "libcef/common/string_util.h"
#include "libcef/renderer/blink_glue.h"
#include "libcef/renderer/browser_impl.h"
#include "libcef/renderer/dom_document_impl.h"
#include "libcef/renderer/render_frame_util.h"
#include "libcef/renderer/thread_util.h"
#include "libcef/renderer/v8_impl.h"
#include "base/strings/stringprintf.h"
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.
2019-05-24 22:23:43 +02:00
#include "base/strings/utf_string_conversions.h"
#include "content/renderer/render_frame_impl.h"
#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/public/web/web_document.h"
2018-07-09 22:12:39 +02:00
#include "third_party/blink/public/web/web_document_loader.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_navigation_control.h"
#include "third_party/blink/public/web/web_script_source.h"
#include "third_party/blink/public/web/web_view.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace {
// Maximum number of times to retry the browser connection.
constexpr size_t kConnectionRetryMaxCt = 3U;
// Length of time to wait before initiating a browser connection retry.
constexpr auto kConnectionRetryDelay = base::Seconds(1);
// Length of time to wait for the browser connection ACK before timing out.
constexpr auto kConnectionTimeout = base::Seconds(10);
} // namespace
CefFrameImpl::CefFrameImpl(CefBrowserImpl* browser,
blink::WebLocalFrame* frame,
int64_t frame_id)
: browser_(browser), frame_(frame), frame_id_(frame_id) {}
CefFrameImpl::~CefFrameImpl() {}
bool CefFrameImpl::IsValid() {
CEF_REQUIRE_RT_RETURN(false);
return (frame_ != nullptr);
}
void CefFrameImpl::Undo() {
SendCommand("Undo");
}
void CefFrameImpl::Redo() {
SendCommand("Redo");
}
void CefFrameImpl::Cut() {
SendCommand("Cut");
}
void CefFrameImpl::Copy() {
SendCommand("Copy");
}
void CefFrameImpl::Paste() {
SendCommand("Paste");
}
void CefFrameImpl::Delete() {
SendCommand("Delete");
}
void CefFrameImpl::SelectAll() {
SendCommand("SelectAll");
}
void CefFrameImpl::ViewSource() {
DCHECK(false) << "ViewSource cannot be called from the renderer process";
}
void CefFrameImpl::GetSource(CefRefPtr<CefStringVisitor> visitor) {
CEF_REQUIRE_RT_RETURN_VOID();
if (frame_) {
CefString content;
string_util::GetCefString(blink_glue::DumpDocumentMarkup(frame_), content);
visitor->Visit(content);
}
}
void CefFrameImpl::GetText(CefRefPtr<CefStringVisitor> visitor) {
CEF_REQUIRE_RT_RETURN_VOID();
if (frame_) {
CefString content;
string_util::GetCefString(blink_glue::DumpDocumentText(frame_), content);
visitor->Visit(content);
}
}
void CefFrameImpl::LoadRequest(CefRefPtr<CefRequest> request) {
CEF_REQUIRE_RT_RETURN_VOID();
2023-01-02 23:59:03 +01:00
if (!frame_) {
return;
2023-01-02 23:59:03 +01:00
}
auto params = cef::mojom::RequestParams::New();
static_cast<CefRequestImpl*>(request.get())->Get(params);
LoadRequest(std::move(params));
}
void CefFrameImpl::LoadURL(const CefString& url) {
CEF_REQUIRE_RT_RETURN_VOID();
2023-01-02 23:59:03 +01:00
if (!frame_) {
return;
2023-01-02 23:59:03 +01:00
}
auto params = cef::mojom::RequestParams::New();
params->url = GURL(url.ToString());
params->method = "GET";
LoadRequest(std::move(params));
}
void CefFrameImpl::ExecuteJavaScript(const CefString& jsCode,
const CefString& scriptUrl,
int startLine) {
SendJavaScript(jsCode, scriptUrl, startLine);
}
bool CefFrameImpl::IsMain() {
CEF_REQUIRE_RT_RETURN(false);
2023-01-02 23:59:03 +01:00
if (frame_) {
return (frame_->Parent() == nullptr);
2023-01-02 23:59:03 +01:00
}
return false;
}
bool CefFrameImpl::IsFocused() {
CEF_REQUIRE_RT_RETURN(false);
2023-01-02 23:59:03 +01:00
if (frame_ && frame_->View()) {
return (frame_->View()->FocusedFrame() == frame_);
2023-01-02 23:59:03 +01:00
}
return false;
}
CefString CefFrameImpl::GetName() {
CefString name;
CEF_REQUIRE_RT_RETURN(name);
2023-01-02 23:59:03 +01:00
if (frame_) {
name = render_frame_util::GetName(frame_);
2023-01-02 23:59:03 +01:00
}
return name;
}
int64_t CefFrameImpl::GetIdentifier() {
CEF_REQUIRE_RT_RETURN(0);
return frame_id_;
}
CefRefPtr<CefFrame> CefFrameImpl::GetParent() {
CEF_REQUIRE_RT_RETURN(nullptr);
if (frame_) {
blink::WebFrame* parent = frame_->Parent();
2023-01-02 23:59:03 +01:00
if (parent && parent->IsWebLocalFrame()) {
return browser_->GetWebFrameImpl(parent->ToWebLocalFrame()).get();
2023-01-02 23:59:03 +01:00
}
}
return nullptr;
}
CefString CefFrameImpl::GetURL() {
CefString url;
CEF_REQUIRE_RT_RETURN(url);
if (frame_) {
GURL gurl = frame_->GetDocument().Url();
url = gurl.spec();
}
return url;
}
CefRefPtr<CefBrowser> CefFrameImpl::GetBrowser() {
CEF_REQUIRE_RT_RETURN(nullptr);
return browser_;
}
CefRefPtr<CefV8Context> CefFrameImpl::GetV8Context() {
CEF_REQUIRE_RT_RETURN(nullptr);
if (frame_) {
v8::Isolate* isolate = blink::MainThreadIsolate();
v8::HandleScope handle_scope(isolate);
return new CefV8ContextImpl(isolate, frame_->MainWorldScriptContext());
} else {
return nullptr;
}
}
void CefFrameImpl::VisitDOM(CefRefPtr<CefDOMVisitor> visitor) {
CEF_REQUIRE_RT_RETURN_VOID();
2023-01-02 23:59:03 +01:00
if (!frame_) {
return;
2023-01-02 23:59:03 +01:00
}
// Create a CefDOMDocumentImpl object that is valid only for the scope of this
// method.
CefRefPtr<CefDOMDocumentImpl> documentImpl;
const blink::WebDocument& document = frame_->GetDocument();
2023-01-02 23:59:03 +01:00
if (!document.IsNull()) {
documentImpl = new CefDOMDocumentImpl(browser_, frame_);
2023-01-02 23:59:03 +01:00
}
visitor->Visit(documentImpl.get());
2023-01-02 23:59:03 +01:00
if (documentImpl.get()) {
documentImpl->Detach();
2023-01-02 23:59:03 +01:00
}
}
CefRefPtr<CefURLRequest> CefFrameImpl::CreateURLRequest(
CefRefPtr<CefRequest> request,
CefRefPtr<CefURLRequestClient> client) {
DCHECK(false) << "CreateURLRequest cannot be called from the render process";
return nullptr;
}
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.
2019-05-24 22:23:43 +02:00
void CefFrameImpl::SendProcessMessage(CefProcessId target_process,
CefRefPtr<CefProcessMessage> message) {
CEF_REQUIRE_RT_RETURN_VOID();
DCHECK_EQ(PID_BROWSER, target_process);
DCHECK(message && message->IsValid());
2023-01-02 23:59:03 +01:00
if (!message || !message->IsValid()) {
return;
2023-01-02 23:59:03 +01:00
}
if (message->GetArgumentList() != nullptr) {
// Invalidate the message object immediately by taking the argument list.
auto argument_list =
static_cast<CefProcessMessageImpl*>(message.get())->TakeArgumentList();
SendToBrowserFrame(
__FUNCTION__,
base::BindOnce(
[](const CefString& name, base::Value::List argument_list,
const BrowserFrameType& render_frame) {
render_frame->SendMessage(name, std::move(argument_list));
},
message->GetName(), std::move(argument_list)));
} else {
auto region =
static_cast<CefProcessMessageSMRImpl*>(message.get())->TakeRegion();
SendToBrowserFrame(
__FUNCTION__,
base::BindOnce(
[](const CefString& name, base::WritableSharedMemoryRegion region,
const BrowserFrameType& render_frame) {
render_frame->SendSharedMemoryRegion(name, std::move(region));
},
message->GetName(), std::move(region)));
}
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.
2019-05-24 22:23:43 +02:00
}
void CefFrameImpl::OnAttached() {
// Called indirectly from RenderFrameCreated.
ConnectBrowserFrame(ConnectReason::RENDER_FRAME_CREATED);
}
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.
2019-05-24 22:23:43 +02:00
void CefFrameImpl::OnWasShown() {
if (browser_connection_state_ == ConnectionState::DISCONNECTED) {
// Reconnect a frame that has exited the bfcache.
ConnectBrowserFrame(ConnectReason::WAS_SHOWN);
}
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.
2019-05-24 22:23:43 +02:00
}
void CefFrameImpl::OnDidCommitProvisionalLoad() {
did_commit_provisional_load_ = true;
MaybeInitializeScriptContext();
}
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.
2019-05-24 22:23:43 +02:00
void CefFrameImpl::OnDidFinishLoad() {
Add support for MimeHandlerViewInCrossProcessFrame (fixes issue #2727) The PDF loading documentation in extension_system.cc has be updated to describe the new code paths. To support delivery of input events to the mime handler renderer process it is now necessary to route events via the correct RWHV interface. For Aura-based platforms (Windows/Linux) this means RWHVAura::On*Event and for macOS this means RWHVMac::RouteOrProcess*Event. Since Aura uses UI event types these have become the source of truth on Aura-based platforms with conversion to Web event types when needed (primarily for OSR). This change also adds a timeout for CefProcessHostMsg_GetNewBrowserInfo to avoid a hung renderer process if the guest WebContents route is not registered via CefMimeHandlerViewGuestDelegate::OnGuestDetached as expected prior to CefBrowserInfoManager::OnGetNewBrowserInfo being called. This timeout can be disabled for testing purposes by passing the `--disable-new-browser-info-timeout` command-line flag. The `--disable-features=MimeHandlerViewInCrossProcessFrame` command-line flag can be used for a limited time to restore the previous implementation based on BrowserPlugin. That implementation will be deleted starting with the 3897 branch update. Known issues: - ExecuteJavaScript calls on the frame hosting the PDF extension will not be routed to the mime handler renderer process. - The PDF extension will not load successfully if blocked by ChromePluginPlaceholder and then manually continued via the "Run this plugin" context menu option (see https://crbug.com/533069#c41).
2020-01-23 22:58:01 +01:00
// Ignore notifications from the embedded frame hosting a mime-type plugin.
// We'll eventually receive a notification from the owner frame.
2023-01-02 23:59:03 +01:00
if (blink_glue::HasPluginFrameOwner(frame_)) {
Add support for MimeHandlerViewInCrossProcessFrame (fixes issue #2727) The PDF loading documentation in extension_system.cc has be updated to describe the new code paths. To support delivery of input events to the mime handler renderer process it is now necessary to route events via the correct RWHV interface. For Aura-based platforms (Windows/Linux) this means RWHVAura::On*Event and for macOS this means RWHVMac::RouteOrProcess*Event. Since Aura uses UI event types these have become the source of truth on Aura-based platforms with conversion to Web event types when needed (primarily for OSR). This change also adds a timeout for CefProcessHostMsg_GetNewBrowserInfo to avoid a hung renderer process if the guest WebContents route is not registered via CefMimeHandlerViewGuestDelegate::OnGuestDetached as expected prior to CefBrowserInfoManager::OnGetNewBrowserInfo being called. This timeout can be disabled for testing purposes by passing the `--disable-new-browser-info-timeout` command-line flag. The `--disable-features=MimeHandlerViewInCrossProcessFrame` command-line flag can be used for a limited time to restore the previous implementation based on BrowserPlugin. That implementation will be deleted starting with the 3897 branch update. Known issues: - ExecuteJavaScript calls on the frame hosting the PDF extension will not be routed to the mime handler renderer process. - The PDF extension will not load successfully if blocked by ChromePluginPlaceholder and then manually continued via the "Run this plugin" context menu option (see https://crbug.com/533069#c41).
2020-01-23 22:58:01 +01:00
return;
2023-01-02 23:59:03 +01:00
}
Add support for MimeHandlerViewInCrossProcessFrame (fixes issue #2727) The PDF loading documentation in extension_system.cc has be updated to describe the new code paths. To support delivery of input events to the mime handler renderer process it is now necessary to route events via the correct RWHV interface. For Aura-based platforms (Windows/Linux) this means RWHVAura::On*Event and for macOS this means RWHVMac::RouteOrProcess*Event. Since Aura uses UI event types these have become the source of truth on Aura-based platforms with conversion to Web event types when needed (primarily for OSR). This change also adds a timeout for CefProcessHostMsg_GetNewBrowserInfo to avoid a hung renderer process if the guest WebContents route is not registered via CefMimeHandlerViewGuestDelegate::OnGuestDetached as expected prior to CefBrowserInfoManager::OnGetNewBrowserInfo being called. This timeout can be disabled for testing purposes by passing the `--disable-new-browser-info-timeout` command-line flag. The `--disable-features=MimeHandlerViewInCrossProcessFrame` command-line flag can be used for a limited time to restore the previous implementation based on BrowserPlugin. That implementation will be deleted starting with the 3897 branch update. Known issues: - ExecuteJavaScript calls on the frame hosting the PDF extension will not be routed to the mime handler renderer process. - The PDF extension will not load successfully if blocked by ChromePluginPlaceholder and then manually continued via the "Run this plugin" context menu option (see https://crbug.com/533069#c41).
2020-01-23 22:58:01 +01:00
if (!blink::RuntimeEnabledFeatures::BackForwardCacheEnabled() && IsMain()) {
// Refresh draggable regions. Otherwise, we may not receive updated regions
// after navigation because LocalFrameView::UpdateDocumentAnnotatedRegion
// lacks sufficient context. When bfcache is disabled we use this method
// instead of DidStopLoading() because it provides more accurate timing.
OnDraggableRegionsChanged();
}
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.
2019-05-24 22:23:43 +02:00
blink::WebDocumentLoader* dl = frame_->GetDocumentLoader();
const int http_status_code = dl->GetWebResponse().HttpStatusCode();
CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
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.
2019-05-24 22:23:43 +02:00
if (app) {
CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
if (handler) {
CefRefPtr<CefLoadHandler> load_handler = handler->GetLoadHandler();
if (load_handler) {
load_handler->OnLoadEnd(browser_, this, http_status_code);
}
}
}
}
void CefFrameImpl::OnDraggableRegionsChanged() {
Fix draggable region update with BackForwardCache enabled (see issue #2421) When BackForwardCache is enabled and the user navigates the main frame back/forward a new RFH may be created for an existing main frame GlobalId value and CefFrameHostImpl (e.g. an object that was previously Detach()ed after main frame navigation called SetMainFrame, but for which RenderFrameDeleted was not subsequently called due to insertion in the BackForwardCache). In this case we can re-attach the new RFH to the existing main frame CefFrameHostImpl in RenderFrameHostStateChanged and resume processing of messages. Swapping back/forward to an existing (already loaded) renderer does not trigger new notifications for draggable regions (e.g. RenderFrameObserver:: DraggableRegionsChanged is not called by default). We therefore explicitly request an update of draggable regions by sending the DidStopLoading message to the renderer. A new |reattached| parameter is added to CefFrameHandler::OnFrameAttached to support identification of BackForwardCache usage by the client. To test with unit tests: Run `ceftests --gtest_filter=DraggableRegionsTest.DraggableRegionsCrossOrigin --enable-features=BackForwardCache` To test manually: 1. Run `cefclient --enable-features=BackForwardCache --use-views --url=http://tests/draggable`, note that draggable regions work. 2. Load https://www.google.com via the address bar, note that draggable regions are removed. 3. Go back to http://tests/draggable, note that draggable regions work. 4. Go forward to https://www.google.com, note that draggable regions are removed.
2021-09-15 13:40:08 +02:00
// Match the behavior in ChromeRenderFrameObserver::DraggableRegionsChanged.
// Only the main frame is allowed to control draggable regions, to avoid other
// frames manipulate the regions in the browser process.
2023-01-02 23:59:03 +01:00
if (frame_->Parent() != nullptr) {
Fix draggable region update with BackForwardCache enabled (see issue #2421) When BackForwardCache is enabled and the user navigates the main frame back/forward a new RFH may be created for an existing main frame GlobalId value and CefFrameHostImpl (e.g. an object that was previously Detach()ed after main frame navigation called SetMainFrame, but for which RenderFrameDeleted was not subsequently called due to insertion in the BackForwardCache). In this case we can re-attach the new RFH to the existing main frame CefFrameHostImpl in RenderFrameHostStateChanged and resume processing of messages. Swapping back/forward to an existing (already loaded) renderer does not trigger new notifications for draggable regions (e.g. RenderFrameObserver:: DraggableRegionsChanged is not called by default). We therefore explicitly request an update of draggable regions by sending the DidStopLoading message to the renderer. A new |reattached| parameter is added to CefFrameHandler::OnFrameAttached to support identification of BackForwardCache usage by the client. To test with unit tests: Run `ceftests --gtest_filter=DraggableRegionsTest.DraggableRegionsCrossOrigin --enable-features=BackForwardCache` To test manually: 1. Run `cefclient --enable-features=BackForwardCache --use-views --url=http://tests/draggable`, note that draggable regions work. 2. Load https://www.google.com via the address bar, note that draggable regions are removed. 3. Go back to http://tests/draggable, note that draggable regions work. 4. Go forward to https://www.google.com, note that draggable regions are removed.
2021-09-15 13:40:08 +02:00
return;
2023-01-02 23:59:03 +01:00
}
Fix draggable region update with BackForwardCache enabled (see issue #2421) When BackForwardCache is enabled and the user navigates the main frame back/forward a new RFH may be created for an existing main frame GlobalId value and CefFrameHostImpl (e.g. an object that was previously Detach()ed after main frame navigation called SetMainFrame, but for which RenderFrameDeleted was not subsequently called due to insertion in the BackForwardCache). In this case we can re-attach the new RFH to the existing main frame CefFrameHostImpl in RenderFrameHostStateChanged and resume processing of messages. Swapping back/forward to an existing (already loaded) renderer does not trigger new notifications for draggable regions (e.g. RenderFrameObserver:: DraggableRegionsChanged is not called by default). We therefore explicitly request an update of draggable regions by sending the DidStopLoading message to the renderer. A new |reattached| parameter is added to CefFrameHandler::OnFrameAttached to support identification of BackForwardCache usage by the client. To test with unit tests: Run `ceftests --gtest_filter=DraggableRegionsTest.DraggableRegionsCrossOrigin --enable-features=BackForwardCache` To test manually: 1. Run `cefclient --enable-features=BackForwardCache --use-views --url=http://tests/draggable`, note that draggable regions work. 2. Load https://www.google.com via the address bar, note that draggable regions are removed. 3. Go back to http://tests/draggable, note that draggable regions work. 4. Go forward to https://www.google.com, note that draggable regions are removed.
2021-09-15 13:40:08 +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.
2019-05-24 22:23:43 +02:00
blink::WebVector<blink::WebDraggableRegion> webregions =
frame_->GetDocument().DraggableRegions();
std::vector<cef::mojom::DraggableRegionEntryPtr> regions;
if (!webregions.empty()) {
auto render_frame = content::RenderFrameImpl::FromWebFrame(frame_);
regions.reserve(webregions.size());
for (const auto& webregion : webregions) {
auto region = cef::mojom::DraggableRegionEntry::New(webregion.bounds,
webregion.draggable);
render_frame->ConvertViewportToWindow(&region->bounds);
regions.push_back(std::move(region));
}
}
using RegionsArg =
absl::optional<std::vector<cef::mojom::DraggableRegionEntryPtr>>;
RegionsArg regions_arg =
regions.empty() ? absl::nullopt : absl::make_optional(std::move(regions));
SendToBrowserFrame(
__FUNCTION__,
base::BindOnce(
[](RegionsArg regions_arg, const BrowserFrameType& browser_frame) {
browser_frame->UpdateDraggableRegions(std::move(regions_arg));
},
std::move(regions_arg)));
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.
2019-05-24 22:23:43 +02:00
}
void CefFrameImpl::OnContextCreated(v8::Local<v8::Context> context) {
context_created_ = true;
CHECK(frame_);
while (!queued_context_actions_.empty()) {
auto& action = queued_context_actions_.front();
std::move(action.second).Run(frame_);
queued_context_actions_.pop();
}
execution_context_lifecycle_state_observer_ =
blink_glue::RegisterExecutionContextLifecycleStateObserver(context, this);
}
void CefFrameImpl::OnContextReleased() {
execution_context_lifecycle_state_observer_.reset();
}
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.
2019-05-24 22:23:43 +02:00
void CefFrameImpl::OnDetached() {
// Called when this frame has been detached from the view. This *will* be
// called for child frames when a parent frame is detached.
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.
2019-05-24 22:23:43 +02:00
// The browser may hold the last reference to |this|. Take a reference here to
// keep |this| alive until after this method returns.
CefRefPtr<CefFrameImpl> self = this;
frame_ = nullptr;
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.
2019-05-24 22:23:43 +02:00
browser_->FrameDetached(frame_id_);
OnDisconnect(DisconnectReason::DETACHED);
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.
2019-05-24 22:23:43 +02:00
browser_ = nullptr;
// In case we never attached.
while (!queued_browser_actions_.empty()) {
auto& action = queued_browser_actions_.front();
LOG(WARNING) << action.first << " sent to detached " << GetDebugString()
<< " will be ignored";
queued_browser_actions_.pop();
}
// In case we're destroyed without the context being created.
while (!queued_context_actions_.empty()) {
auto& action = queued_context_actions_.front();
LOG(WARNING) << action.first << " sent to detached " << GetDebugString()
<< " will be ignored";
queued_context_actions_.pop();
}
}
void CefFrameImpl::ExecuteOnLocalFrame(const std::string& function_name,
LocalFrameAction action) {
CEF_REQUIRE_RT_RETURN_VOID();
if (!context_created_) {
queued_context_actions_.push(
std::make_pair(function_name, std::move(action)));
MaybeInitializeScriptContext();
return;
}
if (frame_) {
std::move(action).Run(frame_);
} else {
LOG(WARNING) << function_name << " sent to detached " << GetDebugString()
<< " will be ignored";
}
}
void CefFrameImpl::ConnectBrowserFrame(ConnectReason reason) {
DCHECK(browser_connection_state_ == ConnectionState::DISCONNECTED ||
browser_connection_state_ == ConnectionState::RECONNECT_PENDING);
if (VLOG_IS_ON(1)) {
std::string reason_str;
switch (reason) {
case ConnectReason::RENDER_FRAME_CREATED:
reason_str = "RENDER_FRAME_CREATED";
break;
case ConnectReason::WAS_SHOWN:
reason_str = "WAS_SHOWN";
break;
case ConnectReason::RETRY:
reason_str = base::StringPrintf(
"RETRY %zu/%zu", browser_connect_retry_ct_, kConnectionRetryMaxCt);
break;
}
VLOG(1) << GetDebugString() << " connection request (reason=" << reason_str
<< ")";
}
// Don't attempt to connect an invalid or bfcache'd frame. If a bfcache'd
// frame returns to active status a reconnect will be triggered via
// OnWasShown().
if (!frame_ || blink_glue::IsInBackForwardCache(frame_)) {
browser_connection_state_ = ConnectionState::DISCONNECTED;
browser_connect_timer_.Stop();
VLOG(1) << GetDebugString() << " connection retry canceled (reason="
<< (frame_ ? "BFCACHED" : "INVALID") << ")";
return;
}
browser_connection_state_ = ConnectionState::CONNECTION_PENDING;
browser_connect_timer_.Start(FROM_HERE, kConnectionTimeout, this,
&CefFrameImpl::OnBrowserFrameTimeout);
auto& browser_frame = GetBrowserFrame(/*expect_acked=*/false);
CHECK(browser_frame);
// True if this connection is a retry or if the frame just exited the
// BackForwardCache.
const bool reattached =
browser_connect_retry_ct_ > 0 || reason == ConnectReason::WAS_SHOWN;
// If the channel is working we should get a call to FrameAttachedAck().
// Otherwise, OnDisconnect() should be called to retry the
// connection.
browser_frame->FrameAttached(receiver_.BindNewPipeAndPassRemote(),
reattached);
receiver_.set_disconnect_handler(
base::BindOnce(&CefFrameImpl::OnDisconnect, this,
DisconnectReason::RENDER_FRAME_DISCONNECT));
}
const mojo::Remote<cef::mojom::BrowserFrame>& CefFrameImpl::GetBrowserFrame(
bool expect_acked) {
DCHECK_EQ(expect_acked,
browser_connection_state_ == ConnectionState::CONNECTION_ACKED);
if (!browser_frame_.is_bound()) {
auto render_frame = content::RenderFrameImpl::FromWebFrame(frame_);
if (render_frame) {
// Triggers creation of a CefBrowserFrame in the browser process.
render_frame->GetBrowserInterfaceBroker()->GetInterface(
browser_frame_.BindNewPipeAndPassReceiver());
browser_frame_.set_disconnect_handler(
base::BindOnce(&CefFrameImpl::OnDisconnect, this,
DisconnectReason::BROWSER_FRAME_DISCONNECT));
}
}
return browser_frame_;
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.
2019-05-24 22:23:43 +02:00
}
void CefFrameImpl::OnBrowserFrameTimeout() {
LOG(ERROR) << GetDebugString() << " connection timeout";
OnDisconnect(DisconnectReason::CONNECT_TIMEOUT);
}
void CefFrameImpl::OnDisconnect(DisconnectReason reason) {
// Ignore multiple calls in close proximity (which may occur if both
// |browser_frame_| and |receiver_| disconnect). |frame_| will be nullptr
// when called from/after OnDetached().
if (frame_ &&
browser_connection_state_ == ConnectionState::RECONNECT_PENDING) {
return;
}
if (VLOG_IS_ON(1)) {
std::string reason_str;
switch (reason) {
case DisconnectReason::DETACHED:
reason_str = "DETACHED";
break;
case DisconnectReason::BROWSER_FRAME_DETACHED:
reason_str = "BROWSER_FRAME_DETACHED";
break;
case DisconnectReason::CONNECT_TIMEOUT:
reason_str = "CONNECT_TIMEOUT";
break;
case DisconnectReason::RENDER_FRAME_DISCONNECT:
reason_str = "RENDER_FRAME_DISCONNECT";
break;
case DisconnectReason::BROWSER_FRAME_DISCONNECT:
reason_str = "BROWSER_FRAME_DISCONNECT";
break;
};
std::string state_str;
switch (browser_connection_state_) {
case ConnectionState::DISCONNECTED:
state_str = "DISCONNECTED";
break;
case ConnectionState::CONNECTION_PENDING:
state_str = "CONNECTION_PENDING";
break;
case ConnectionState::CONNECTION_ACKED:
state_str = "CONNECTION_ACKED";
break;
case ConnectionState::RECONNECT_PENDING:
state_str = "RECONNECT_PENDING";
break;
}
2023-01-02 23:59:03 +01:00
if (!frame_) {
state_str += ", FRAME_INVALID";
2023-01-02 23:59:03 +01:00
}
VLOG(1) << GetDebugString() << " disconnected (reason=" << reason_str
<< ", current_state=" << state_str << ")";
}
browser_frame_.reset();
receiver_.reset();
browser_connection_state_ = ConnectionState::DISCONNECTED;
browser_connect_timer_.Stop();
// Only retry if the frame is still valid and the browser process has not
// intentionally detached.
if (frame_ && reason != DisconnectReason::BROWSER_FRAME_DETACHED) {
if (browser_connect_retry_ct_++ < kConnectionRetryMaxCt) {
VLOG(1) << GetDebugString() << " connection retry scheduled";
// Retry after a delay in case the frame is currently navigating, being
// destroyed, or entering the bfcache. In the navigation case the retry
// will likely succeed. In the destruction case the retry will be
// ignored/canceled due to OnDetached(). In the bfcache case the status
// may not be updated immediately, so we allow the reconnect timer to
// trigger and check the status in ConnectBrowserFrame() instead.
browser_connection_state_ = ConnectionState::RECONNECT_PENDING;
browser_connect_timer_.Start(
FROM_HERE, kConnectionRetryDelay,
base::BindOnce(&CefFrameImpl::ConnectBrowserFrame, this,
ConnectReason::RETRY));
} else {
// Trigger a crash in official builds.
LOG(FATAL) << GetDebugString() << " connection retry failed";
}
}
}
void CefFrameImpl::SendToBrowserFrame(const std::string& function_name,
BrowserFrameAction action) {
if (!frame_) {
// We've been detached.
LOG(WARNING) << function_name << " sent to detached " << GetDebugString()
<< " will be ignored";
return;
}
if (browser_connection_state_ != ConnectionState::CONNECTION_ACKED) {
// Queue actions until we're notified by the browser that it's ready to
// handle them.
queued_browser_actions_.push(
std::make_pair(function_name, std::move(action)));
return;
}
auto& browser_frame = GetBrowserFrame();
CHECK(browser_frame);
std::move(action).Run(browser_frame);
}
void CefFrameImpl::MaybeInitializeScriptContext() {
if (did_initialize_script_context_) {
return;
}
if (!did_commit_provisional_load_) {
// Too soon for context initialization.
return;
}
if (queued_context_actions_.empty()) {
// Don't need early context initialization. Avoid it due to performance
// consequences.
return;
}
did_initialize_script_context_ = true;
// Explicitly force creation of the script context. This occurred implicitly
// via DidCommitProvisionalLoad prior to https://crrev.com/5150754880a.
// Otherwise, a script context may never be created for a frame that doesn't
// contain JS code.
v8::HandleScope handle_scope(blink::MainThreadIsolate());
frame_->MainWorldScriptContext();
}
void CefFrameImpl::FrameAttachedAck() {
// Sent from the browser process in response to ConnectBrowserFrame() sending
// FrameAttached().
CHECK_EQ(ConnectionState::CONNECTION_PENDING, browser_connection_state_);
browser_connection_state_ = ConnectionState::CONNECTION_ACKED;
browser_connect_retry_ct_ = 0;
browser_connect_timer_.Stop();
auto& browser_frame = GetBrowserFrame();
CHECK(browser_frame);
while (!queued_browser_actions_.empty()) {
std::move(queued_browser_actions_.front().second).Run(browser_frame);
queued_browser_actions_.pop();
}
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.
2019-05-24 22:23:43 +02:00
}
void CefFrameImpl::FrameDetached() {
// Sent from the browser process in response to CefFrameHostImpl::Detach().
CHECK_EQ(ConnectionState::CONNECTION_ACKED, browser_connection_state_);
OnDisconnect(DisconnectReason::BROWSER_FRAME_DETACHED);
}
void CefFrameImpl::SendMessage(const std::string& name,
base::Value::List arguments) {
if (auto app = CefAppManager::Get()->GetApplication()) {
if (auto handler = app->GetRenderProcessHandler()) {
CefRefPtr<CefProcessMessageImpl> message(
new CefProcessMessageImpl(name, std::move(arguments),
/*read_only=*/true));
handler->OnProcessMessageReceived(browser_, this, PID_BROWSER,
message.get());
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.
2019-05-24 22:23:43 +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.
2019-05-24 22:23:43 +02:00
void CefFrameImpl::SendSharedMemoryRegion(
const std::string& name,
base::WritableSharedMemoryRegion region) {
if (auto app = CefAppManager::Get()->GetApplication()) {
if (auto handler = app->GetRenderProcessHandler()) {
CefRefPtr<CefProcessMessage> message(
new CefProcessMessageSMRImpl(name, std::move(region)));
handler->OnProcessMessageReceived(browser_, this, PID_BROWSER, message);
}
}
}
void CefFrameImpl::SendCommand(const std::string& command) {
ExecuteOnLocalFrame(
__FUNCTION__,
base::BindOnce(
[](const std::string& command, blink::WebLocalFrame* frame) {
frame->ExecuteCommand(blink::WebString::FromUTF8(command));
},
command));
}
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.
2019-05-24 22:23:43 +02:00
void CefFrameImpl::SendCommandWithResponse(
const std::string& command,
cef::mojom::RenderFrame::SendCommandWithResponseCallback callback) {
ExecuteOnLocalFrame(
__FUNCTION__,
base::BindOnce(
[](const std::string& command,
cef::mojom::RenderFrame::SendCommandWithResponseCallback callback,
blink::WebLocalFrame* frame) {
blink::WebString response;
if (base::EqualsCaseInsensitiveASCII(command, "getsource")) {
response = blink_glue::DumpDocumentMarkup(frame);
} else if (base::EqualsCaseInsensitiveASCII(command, "gettext")) {
response = blink_glue::DumpDocumentText(frame);
}
std::move(callback).Run(
string_util::CreateSharedMemoryRegion(response));
},
command, std::move(callback)));
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.
2019-05-24 22:23:43 +02:00
}
void CefFrameImpl::SendJavaScript(const std::u16string& jsCode,
const std::string& scriptUrl,
int32_t startLine) {
ExecuteOnLocalFrame(
__FUNCTION__,
base::BindOnce(
[](const std::u16string& jsCode, const std::string& scriptUrl,
blink::WebLocalFrame* frame) {
frame->ExecuteScript(blink::WebScriptSource(
blink::WebString::FromUTF16(jsCode), GURL(scriptUrl)));
},
jsCode, scriptUrl));
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.
2019-05-24 22:23:43 +02:00
}
void CefFrameImpl::LoadRequest(cef::mojom::RequestParamsPtr params) {
ExecuteOnLocalFrame(
__FUNCTION__,
base::BindOnce(
[](cef::mojom::RequestParamsPtr params, blink::WebLocalFrame* frame) {
blink::WebURLRequest request;
CefRequestImpl::Get(params, request);
blink_glue::StartNavigation(frame, request);
},
std::move(params)));
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.
2019-05-24 22:23:43 +02:00
}
void CefFrameImpl::DidStopLoading() {
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.
2019-05-24 22:23:43 +02:00
// 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
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.
2019-05-24 22:23:43 +02:00
// OnLoadingStateChange.
browser_->OnLoadingStateChange(false);
Fix draggable region update with BackForwardCache enabled (see issue #2421) When BackForwardCache is enabled and the user navigates the main frame back/forward a new RFH may be created for an existing main frame GlobalId value and CefFrameHostImpl (e.g. an object that was previously Detach()ed after main frame navigation called SetMainFrame, but for which RenderFrameDeleted was not subsequently called due to insertion in the BackForwardCache). In this case we can re-attach the new RFH to the existing main frame CefFrameHostImpl in RenderFrameHostStateChanged and resume processing of messages. Swapping back/forward to an existing (already loaded) renderer does not trigger new notifications for draggable regions (e.g. RenderFrameObserver:: DraggableRegionsChanged is not called by default). We therefore explicitly request an update of draggable regions by sending the DidStopLoading message to the renderer. A new |reattached| parameter is added to CefFrameHandler::OnFrameAttached to support identification of BackForwardCache usage by the client. To test with unit tests: Run `ceftests --gtest_filter=DraggableRegionsTest.DraggableRegionsCrossOrigin --enable-features=BackForwardCache` To test manually: 1. Run `cefclient --enable-features=BackForwardCache --use-views --url=http://tests/draggable`, note that draggable regions work. 2. Load https://www.google.com via the address bar, note that draggable regions are removed. 3. Go back to http://tests/draggable, note that draggable regions work. 4. Go forward to https://www.google.com, note that draggable regions are removed.
2021-09-15 13:40:08 +02:00
if (blink::RuntimeEnabledFeatures::BackForwardCacheEnabled()) {
// Refresh draggable regions. Otherwise, we may not receive updated regions
// after navigation because LocalFrameView::UpdateDocumentAnnotatedRegion
// lacks sufficient context. When bfcache is enabled we can't rely on
// OnDidFinishLoad() as the frame may not actually be reloaded.
OnDraggableRegionsChanged();
}
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.
2019-05-24 22:23:43 +02:00
}
void CefFrameImpl::MoveOrResizeStarted() {
if (frame_) {
auto web_view = frame_->View();
if (web_view) {
web_view->CancelPagePopup();
}
}
}
void CefFrameImpl::ContextLifecycleStateChanged(
blink::mojom::blink::FrameLifecycleState state) {
if (state == blink::mojom::FrameLifecycleState::kFrozen && IsMain() &&
blink_glue::IsInBackForwardCache(frame_)) {
browser_->OnEnterBFCache();
}
}
std::string CefFrameImpl::GetDebugString() const {
return "frame " + frame_util::GetFrameDebugString(frame_id_);
}
// Enable deprecation warnings on Windows. See http://crbug.com/585142.
#if BUILDFLAG(IS_WIN)
#if defined(__clang__)
#pragma GCC diagnostic pop
#else
#pragma warning(pop)
#endif
#endif