blob: d8373e9d12733deeedabf0fa2de5dd6df4097927 [file] [log] [blame]
// Copyright 2017 The Chromium 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 "content/browser/android/render_widget_host_connector.h"
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_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 RenderWidgetHostViewAndroid::DestructionObserver {
public:
Observer(WebContents* web_contents, RenderWidgetHostConnector* connector);
~Observer() override;
// WebContentsObserver implementation.
void RenderViewReady() override;
void RenderViewHostChanged(RenderViewHost* old_host,
RenderViewHost* new_host) override;
void DidAttachInterstitialPage() override;
void DidDetachInterstitialPage() override;
void WebContentsDestroyed() override;
// RenderWidgetHostViewAndroid::DestructionObserver implementation.
void RenderWidgetHostViewDestroyed(
RenderWidgetHostViewAndroid* rwhva) override;
void UpdateRenderWidgetHostView(RenderWidgetHostViewAndroid* new_rwhva);
RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid() const;
RenderWidgetHostViewAndroid* active_rwhva() const { return active_rwhva_; }
private:
RenderWidgetHostConnector* const connector_;
// Active RenderWidgetHostView connected to this instance. Can also point to
// an interstitial while it is showing.
RenderWidgetHostViewAndroid* active_rwhva_;
DISALLOW_COPY_AND_ASSIGN(Observer);
};
RenderWidgetHostConnector::Observer::Observer(
WebContents* web_contents,
RenderWidgetHostConnector* connector)
: WebContentsObserver(web_contents),
connector_(connector),
active_rwhva_(nullptr) {}
RenderWidgetHostConnector::Observer::~Observer() {
DCHECK(!active_rwhva_);
}
void RenderWidgetHostConnector::Observer::RenderViewReady() {
UpdateRenderWidgetHostView(GetRenderWidgetHostViewAndroid());
}
void RenderWidgetHostConnector::Observer::RenderViewHostChanged(
RenderViewHost* old_host,
RenderViewHost* new_host) {
// |RenderViewHostChanged| is called only for main rwhva change.
// No need to update connection if an interstitial page is active.
if (web_contents()->ShowingInterstitialPage())
return;
auto* new_view = new_host ? static_cast<RenderWidgetHostViewAndroid*>(
new_host->GetWidget()->GetView())
: nullptr;
UpdateRenderWidgetHostView(new_view);
}
void RenderWidgetHostConnector::Observer::DidAttachInterstitialPage() {
UpdateRenderWidgetHostView(GetRenderWidgetHostViewAndroid());
}
void RenderWidgetHostConnector::Observer::DidDetachInterstitialPage() {
UpdateRenderWidgetHostView(GetRenderWidgetHostViewAndroid());
}
void RenderWidgetHostConnector::Observer::WebContentsDestroyed() {
DCHECK_EQ(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();
WebContentsImpl* web_contents_impl =
static_cast<WebContentsImpl*>(web_contents());
if (web_contents_impl->ShowingInterstitialPage()) {
rwhv = web_contents_impl->GetInterstitialPage()
->GetMainFrame()
->GetRenderViewHost()
->GetWidget()
->GetView();
}
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();
}
WebContents* RenderWidgetHostConnector::web_contents() const {
return render_widget_observer_->web_contents();
}
} // namespace content