fix: don't handle browser messages before document element is created (#19718)
* fix: don't handle browser messages before document element is created * fix: bind ElectronApiServiceImpl later DidCreateDocumentElement is called before the ElectronApiServiceImpl gets bound. * chore: add comment
This commit is contained in:
parent
398c5d553d
commit
04dbd5c53f
5 changed files with 90 additions and 35 deletions
|
@ -98,38 +98,61 @@ ElectronApiServiceImpl::~ElectronApiServiceImpl() = default;
|
|||
|
||||
ElectronApiServiceImpl::ElectronApiServiceImpl(
|
||||
content::RenderFrame* render_frame,
|
||||
RendererClientBase* renderer_client,
|
||||
mojom::ElectronRendererAssociatedRequest request)
|
||||
RendererClientBase* renderer_client)
|
||||
: content::RenderFrameObserver(render_frame),
|
||||
binding_(this),
|
||||
render_frame_(render_frame),
|
||||
renderer_client_(renderer_client) {
|
||||
renderer_client_(renderer_client),
|
||||
weak_factory_(this) {}
|
||||
|
||||
void ElectronApiServiceImpl::BindTo(
|
||||
mojom::ElectronRendererAssociatedRequest request) {
|
||||
// Note: BindTo might be called for multiple times.
|
||||
if (binding_.is_bound())
|
||||
binding_.Unbind();
|
||||
|
||||
binding_.Bind(std::move(request));
|
||||
binding_.set_connection_error_handler(base::BindOnce(
|
||||
&ElectronApiServiceImpl::OnDestruct, base::Unretained(this)));
|
||||
binding_.set_connection_error_handler(
|
||||
base::BindOnce(&ElectronApiServiceImpl::OnConnectionError, GetWeakPtr()));
|
||||
}
|
||||
|
||||
// static
|
||||
void ElectronApiServiceImpl::CreateMojoService(
|
||||
content::RenderFrame* render_frame,
|
||||
RendererClientBase* renderer_client,
|
||||
mojom::ElectronRendererAssociatedRequest request) {
|
||||
DCHECK(render_frame);
|
||||
|
||||
// Owns itself. Will be deleted when the render frame is destroyed.
|
||||
new ElectronApiServiceImpl(render_frame, renderer_client, std::move(request));
|
||||
void ElectronApiServiceImpl::DidCreateDocumentElement() {
|
||||
document_created_ = true;
|
||||
}
|
||||
|
||||
void ElectronApiServiceImpl::OnDestruct() {
|
||||
delete this;
|
||||
}
|
||||
|
||||
void ElectronApiServiceImpl::OnConnectionError() {
|
||||
if (binding_.is_bound())
|
||||
binding_.Unbind();
|
||||
}
|
||||
|
||||
void ElectronApiServiceImpl::Message(bool internal,
|
||||
bool send_to_all,
|
||||
const std::string& channel,
|
||||
base::Value arguments,
|
||||
int32_t sender_id) {
|
||||
blink::WebLocalFrame* frame = render_frame_->GetWebFrame();
|
||||
// Don't handle browser messages before document element is created.
|
||||
//
|
||||
// Note: It is probably better to save the message and then replay it after
|
||||
// document is ready, but current behavior has been there since the first
|
||||
// day of Electron, and no one has complained so far.
|
||||
//
|
||||
// Reason 1:
|
||||
// When we receive a message from the browser, we try to transfer it
|
||||
// to a web page, and when we do that Blink creates an empty
|
||||
// document element if it hasn't been created yet, and it makes our init
|
||||
// script to run while `window.location` is still "about:blank".
|
||||
// (See https://github.com/electron/electron/pull/1044.)
|
||||
//
|
||||
// Reason 2:
|
||||
// The libuv message loop integration would be broken for unkown reasons.
|
||||
// (See https://github.com/electron/electron/issues/19368.)
|
||||
if (!document_created_)
|
||||
return;
|
||||
|
||||
blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
|
||||
if (!frame)
|
||||
return;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue