Chromium Code Reviews| Index: content/browser/android/render_widget_host_connector.cc |
| diff --git a/content/browser/android/render_widget_host_connector.cc b/content/browser/android/render_widget_host_connector.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..86bce031295efd062d6a2e75f23e20332774f5e4 |
| --- /dev/null |
| +++ b/content/browser/android/render_widget_host_connector.cc |
| @@ -0,0 +1,165 @@ |
| +// 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; |
| + |
| + RenderWidgetHostViewAndroid* main_rwhva() const { return main_rwhva_; } |
| + RenderWidgetHostViewAndroid* interstitial_rwhva() const { |
| + return interstitial_rwhva_; |
| + } |
| + |
| + private: |
| + void UpdateRenderWidgetHostView(RenderWidgetHostViewAndroid* old_rwhva, |
| + RenderWidgetHostViewAndroid* new_rwhva); |
| + RenderWidgetHostViewAndroid* GetRenderWidgetHostViewAndroid() const; |
| + |
| + RenderWidgetHostConnector* const connector_; |
| + |
| + // Active RenderWidgetHostView connected to this instance. |
| + // Note that |main_rwhva_| points to the inactive one in the background |
| + // (rather than nulled out) while an interstitial page is showing. |
| + RenderWidgetHostViewAndroid* main_rwhva_; |
| + RenderWidgetHostViewAndroid* interstitial_rwhva_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Observer); |
| +}; |
| + |
| +RenderWidgetHostConnector::Observer::Observer( |
| + WebContents* web_contents, |
| + RenderWidgetHostConnector* connector) |
| + : WebContentsObserver(web_contents), |
| + connector_(connector), |
| + main_rwhva_(nullptr), |
| + interstitial_rwhva_(nullptr) {} |
| + |
| +RenderWidgetHostConnector::Observer::~Observer() { |
| + DCHECK(!main_rwhva_); |
| +} |
| + |
| +void RenderWidgetHostConnector::Observer::RenderViewReady() { |
| + auto* new_rwhva = GetRenderWidgetHostViewAndroid(); |
| + UpdateRenderWidgetHostView(main_rwhva_, new_rwhva); |
| + main_rwhva_ = new_rwhva; |
| +} |
| + |
| +void RenderWidgetHostConnector::Observer::RenderViewHostChanged( |
| + RenderViewHost* old_host, |
| + RenderViewHost* new_host) { |
| + auto* new_view = new_host ? static_cast<RenderWidgetHostViewAndroid*>( |
| + new_host->GetWidget()->GetView()) |
| + : nullptr; |
| + |
| + // |RenderViewHostChanged| is called only for main rwhva change. |
| + // No need to update connection if an interstitial page is active. |
| + if (!interstitial_rwhva_) |
| + UpdateRenderWidgetHostView(main_rwhva_, new_view); |
| + main_rwhva_ = new_view; |
| +} |
| + |
| +void RenderWidgetHostConnector::Observer::DidAttachInterstitialPage() { |
| + auto* new_rwhva = GetRenderWidgetHostViewAndroid(); |
| + UpdateRenderWidgetHostView(main_rwhva_, new_rwhva); |
| + interstitial_rwhva_ = new_rwhva; |
| +} |
| + |
| +void RenderWidgetHostConnector::Observer::DidDetachInterstitialPage() { |
| + auto* new_rwhva = GetRenderWidgetHostViewAndroid(); |
| + UpdateRenderWidgetHostView(interstitial_rwhva_, new_rwhva); |
| + interstitial_rwhva_ = nullptr; |
| + main_rwhva_ = new_rwhva; |
| +} |
| + |
| +void RenderWidgetHostConnector::Observer::WebContentsDestroyed() { |
| + auto* cur_rwhva = interstitial_rwhva_ ? interstitial_rwhva_ : main_rwhva_; |
| + DCHECK_EQ(cur_rwhva, GetRenderWidgetHostViewAndroid()); |
| + UpdateRenderWidgetHostView(cur_rwhva, nullptr); |
| + interstitial_rwhva_ = nullptr; |
| + main_rwhva_ = nullptr; |
| + delete connector_; |
| +} |
| + |
| +void RenderWidgetHostConnector::Observer::RenderWidgetHostViewDestroyed( |
| + RenderWidgetHostViewAndroid* destroyed_rwhva) { |
| + // Null out the matched raw pointer here and in the connector impl to keep |
| + // them from referencing the rwvha about to be destroyed. |
| + if (destroyed_rwhva == interstitial_rwhva_) { |
| + connector_->UpdateRenderProcessConnection(interstitial_rwhva_, nullptr); |
| + interstitial_rwhva_ = nullptr; |
| + } else if (destroyed_rwhva == main_rwhva_) { |
| + if (!interstitial_rwhva_) |
| + connector_->UpdateRenderProcessConnection(main_rwhva_, nullptr); |
| + main_rwhva_ = nullptr; |
| + } |
| +} |
| + |
| +void RenderWidgetHostConnector::Observer::UpdateRenderWidgetHostView( |
| + RenderWidgetHostViewAndroid* old_rwhva, |
| + RenderWidgetHostViewAndroid* new_rwhva) { |
| + if (old_rwhva == new_rwhva) |
| + return; |
| + if (old_rwhva) |
| + old_rwhva->RemoveDestructionObserver(this); |
|
boliu
2017/04/15 00:52:54
this doesn't work anymore. I think you need to obs
Jinsuk Kim
2017/04/15 01:19:07
At certain time there is (and should be) only one
boliu
2017/04/15 02:06:21
what if the non-interstitial rwhva is destroyed wh
Jinsuk Kim
2017/04/16 23:16:43
Main rwhva is not connected to ime, so its destruc
|
| + if (new_rwhva) |
| + new_rwhva->AddDestructionObserver(this); |
| + |
| + connector_->UpdateRenderProcessConnection(old_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)) {} |
| + |
| +RenderWidgetHostConnector::~RenderWidgetHostConnector() {} |
| + |
| +RenderWidgetHostViewAndroid* RenderWidgetHostConnector::GetMainRWHVAForTesting() |
| + const { |
| + return render_widget_observer_->main_rwhva(); |
| +} |
| + |
| +RenderWidgetHostViewAndroid* |
| +RenderWidgetHostConnector::GetInterstitialRWHVAForTesting() const { |
| + return render_widget_observer_->interstitial_rwhva(); |
| +} |
| + |
| +} // namespace content |