blob: cbbbc47664af495e3b155080e084e73b294918b1 [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/android/render_widget_host_connector.h"
#include "base/memory/raw_ptr.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/browser/web_contents/web_contents_android.h"
#include "content/browser/web_contents/web_contents_impl.h"
namespace content {
// Observes RenderWidgetHostViewAndroid to keep the instance up to date.
class RenderWidgetHostConnector::Observer
: public WebContentsObserver,
public WebContentsAndroid::DestructionObserver,
public RenderWidgetHostViewAndroid::DestructionObserver {
public:
Observer(WebContents* web_contents, RenderWidgetHostConnector* connector);
Observer(const Observer&) = delete;
Observer& operator=(const Observer&) = delete;
~Observer() override;
// WebContentsObserver implementation.
void RenderViewReady() override;
void RenderFrameHostChanged(RenderFrameHost* old_host,
RenderFrameHost* new_host) override;
// WebContentsAndroid::DestructionObserver implementation.
void WebContentsAndroidDestroyed(
WebContentsAndroid* web_contents_android) override;
// RenderWidgetHostViewAndroid::DestructionObserver implementation.
void RenderWidgetHostViewDestroyed(
RenderWidgetHostViewAndroid* rwhva) override;
void DestroyEarly();
void UpdateRenderWidgetHostView(RenderWidgetHostViewAndroid* new_rwhva);
RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid() const;
RenderWidgetHostViewAndroid* active_rwhva() const { return active_rwhva_; }
private:
void DoDestroy(WebContentsAndroid* web_contents_android);
const raw_ptr<RenderWidgetHostConnector> connector_;
// Active RenderWidgetHostView connected to this instance.
raw_ptr<RenderWidgetHostViewAndroid> active_rwhva_;
};
RenderWidgetHostConnector::Observer::Observer(
WebContents* web_contents,
RenderWidgetHostConnector* connector)
: WebContentsObserver(web_contents),
connector_(connector),
active_rwhva_(nullptr) {
static_cast<WebContentsImpl*>(web_contents)
->GetWebContentsAndroid()
->AddDestructionObserver(this);
}
RenderWidgetHostConnector::Observer::~Observer() {
DCHECK(!active_rwhva_);
}
void RenderWidgetHostConnector::Observer::RenderViewReady() {
UpdateRenderWidgetHostView(GetRenderWidgetHostViewAndroid());
}
void RenderWidgetHostConnector::Observer::RenderFrameHostChanged(
RenderFrameHost* old_host,
RenderFrameHost* new_host) {
if (!new_host->IsInPrimaryMainFrame()) {
return;
}
auto* new_view = new_host ? static_cast<RenderWidgetHostViewBase*>(
new_host->GetRenderWidgetHost()->GetView())
: nullptr;
DCHECK(!new_view || !new_view->IsRenderWidgetHostViewChildFrame());
auto* new_view_android = static_cast<RenderWidgetHostViewAndroid*>(new_view);
UpdateRenderWidgetHostView(new_view_android);
}
void RenderWidgetHostConnector::Observer::WebContentsAndroidDestroyed(
WebContentsAndroid* web_contents_android) {
DoDestroy(web_contents_android);
}
void RenderWidgetHostConnector::Observer::DestroyEarly() {
DoDestroy(
static_cast<WebContentsImpl*>(web_contents())->GetWebContentsAndroid());
}
void RenderWidgetHostConnector::Observer::DoDestroy(
WebContentsAndroid* web_contents_android) {
web_contents_android->RemoveDestructionObserver(this);
DCHECK(!active_rwhva_ || active_rwhva_ == GetRenderWidgetHostViewAndroid());
UpdateRenderWidgetHostView(nullptr);
delete connector_;
}
void RenderWidgetHostConnector::Observer::RenderWidgetHostViewDestroyed(
RenderWidgetHostViewAndroid* destroyed_rwhva) {
// Null out the raw pointer here and in the connector impl to keep
// them from referencing the rwvha about to be destroyed.
if (destroyed_rwhva == active_rwhva_)
UpdateRenderWidgetHostView(nullptr);
}
void RenderWidgetHostConnector::Observer::UpdateRenderWidgetHostView(
RenderWidgetHostViewAndroid* new_rwhva) {
if (active_rwhva_ == new_rwhva)
return;
if (active_rwhva_)
active_rwhva_->RemoveDestructionObserver(this);
if (new_rwhva)
new_rwhva->AddDestructionObserver(this);
connector_->UpdateRenderProcessConnection(active_rwhva_, new_rwhva);
active_rwhva_ = new_rwhva;
}
RenderWidgetHostViewAndroid*
RenderWidgetHostConnector::Observer::GetRenderWidgetHostViewAndroid() const {
RenderWidgetHostView* rwhv = web_contents()->GetRenderWidgetHostView();
DCHECK(!rwhv || !static_cast<RenderWidgetHostViewBase*>(rwhv)
->IsRenderWidgetHostViewChildFrame());
return static_cast<RenderWidgetHostViewAndroid*>(rwhv);
}
RenderWidgetHostConnector::RenderWidgetHostConnector(WebContents* web_contents)
: render_widget_observer_(new Observer(web_contents, this)) {}
void RenderWidgetHostConnector::Initialize() {
render_widget_observer_->UpdateRenderWidgetHostView(
render_widget_observer_->GetRenderWidgetHostViewAndroid());
}
RenderWidgetHostConnector::~RenderWidgetHostConnector() {}
RenderWidgetHostViewAndroid* RenderWidgetHostConnector::GetRWHVAForTesting()
const {
return render_widget_observer_->active_rwhva();
}
void RenderWidgetHostConnector::DestroyEarly() {
render_widget_observer_->DestroyEarly();
}
WebContents* RenderWidgetHostConnector::web_contents() const {
return render_widget_observer_->web_contents();
}
} // namespace content