Add WasShown/WasHidden to RenderFrameObserver.
BUG=304341
Review URL: https://codereview.chromium.org/298283003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@273375 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 552962dd..65bd5a0 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -19,6 +19,7 @@
#include "content/browser/renderer_host/input/input_router.h"
#include "content/browser/renderer_host/input/timeout_monitor.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/desktop_notification_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/input_messages.h"
@@ -488,6 +489,10 @@
frame_tree_node()->navigator()->DidNavigate(this, validated_params);
}
+RenderWidgetHostImpl* RenderFrameHostImpl::GetRenderWidgetHost() {
+ return static_cast<RenderWidgetHostImpl*>(render_view_host_);
+}
+
int RenderFrameHostImpl::GetEnabledBindings() {
return render_view_host_->GetEnabledBindings();
}
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 835f6e7..ab32d9f 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -39,6 +39,7 @@
class RenderFrameProxyHost;
class RenderProcessHost;
class RenderViewHostImpl;
+class RenderWidgetHostImpl;
struct ContextMenuParams;
struct GlobalRequestID;
struct Referrer;
@@ -80,6 +81,9 @@
RenderViewHostImpl* render_view_host() { return render_view_host_; }
RenderFrameHostDelegate* delegate() { return delegate_; }
FrameTreeNode* frame_tree_node() { return frame_tree_node_; }
+ // TODO(nasko): The RenderWidgetHost will be owned by RenderFrameHost in
+ // the future, so update this accessor to return the right pointer.
+ RenderWidgetHostImpl* GetRenderWidgetHost();
// This function is called when this is a swapped out RenderFrameHost that
// lives in the same process as the parent frame. The
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 5c3be86..1bcf3fc 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -216,6 +216,14 @@
NavigateFrameToURL(root->child_at(0), http_url);
EXPECT_EQ(http_url, observer.navigation_url());
EXPECT_TRUE(observer.navigation_succeeded());
+ {
+ // There should be only one RenderWidgetHost when there are no
+ // cross-process iframes.
+ std::set<RenderWidgetHostImpl*> widgets_set =
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetRenderWidgetHostsInTree();
+ EXPECT_EQ(1U, widgets_set.size());
+ }
// These must stay in scope with replace_host.
GURL::Replacements replace_host;
@@ -238,6 +246,14 @@
EXPECT_NE(shell()->web_contents()->GetRenderViewHost(), rvh);
EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site_instance);
EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(), rph);
+ {
+ // There should be now two RenderWidgetHosts, one for each process
+ // rendering a frame.
+ std::set<RenderWidgetHostImpl*> widgets_set =
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetRenderWidgetHostsInTree();
+ EXPECT_EQ(2U, widgets_set.size());
+ }
// Load another cross-site page into the same iframe.
cross_site_url = test_server()->GetURL("files/title3.html");
@@ -262,6 +278,12 @@
EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(),
child->current_frame_host()->GetProcess());
EXPECT_NE(rph, child->current_frame_host()->GetProcess());
+ {
+ std::set<RenderWidgetHostImpl*> widgets_set =
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetRenderWidgetHostsInTree();
+ EXPECT_EQ(2U, widgets_set.size());
+ }
}
// Crash a subframe and ensures its children are cleared from the FrameTree.
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 1256f58c..6ed02ce 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -217,6 +217,11 @@
rfh->Send(message_copy);
}
+void AddRenderWidgetHostToSet(std::set<RenderWidgetHostImpl*>* set,
+ RenderFrameHost* rfh) {
+ set->insert(static_cast<RenderFrameHostImpl*>(rfh)->GetRenderWidgetHost());
+}
+
} // namespace
WebContents* WebContents::Create(const WebContents::CreateParams& params) {
@@ -938,12 +943,18 @@
void WebContentsImpl::WasShown() {
controller_.SetActive(true);
- RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
- if (rwhv) {
- rwhv->Show();
+
+ std::set<RenderWidgetHostImpl*> widgets = GetRenderWidgetHostsInTree();
+ for (std::set<RenderWidgetHostImpl*>::iterator iter = widgets.begin();
+ iter != widgets.end();
+ iter++) {
+ RenderWidgetHostView* rwhv = (*iter)->GetView();
+ if (rwhv) {
+ rwhv->Show();
#if defined(OS_MACOSX)
- rwhv->SetActive(true);
+ rwhv->SetActive(true);
#endif
+ }
}
last_active_time_ = base::TimeTicks::Now();
@@ -971,9 +982,14 @@
// removes the |GetRenderViewHost()|; then when we actually destroy the
// window, OnWindowPosChanged() notices and calls WasHidden() (which
// calls us).
- RenderWidgetHostView* rwhv = GetRenderWidgetHostView();
- if (rwhv)
- rwhv->Hide();
+ std::set<RenderWidgetHostImpl*> widgets = GetRenderWidgetHostsInTree();
+ for (std::set<RenderWidgetHostImpl*>::iterator iter = widgets.begin();
+ iter != widgets.end();
+ iter++) {
+ RenderWidgetHostView* rwhv = (*iter)->GetView();
+ if (rwhv)
+ rwhv->Hide();
+ }
}
FOR_EACH_OBSERVER(WebContentsObserver, observers_, WasHidden());
@@ -1129,6 +1145,12 @@
observers_.RemoveObserver(observer);
}
+std::set<RenderWidgetHostImpl*> WebContentsImpl::GetRenderWidgetHostsInTree() {
+ std::set<RenderWidgetHostImpl*> set;
+ ForEachFrame(base::Bind(&AddRenderWidgetHostToSet, base::Unretained(&set)));
+ return set;
+}
+
void WebContentsImpl::Activate() {
if (delegate_)
delegate_->ActivateContents(this);
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index d65036d..c8a0355b 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -644,6 +644,7 @@
FRIEND_TEST_ALL_PREFIXES(FormStructureBrowserTest, HTMLFiles);
FRIEND_TEST_ALL_PREFIXES(NavigationControllerTest, HistoryNavigate);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest, PageDoesBackAndReload);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest, CrossSiteIframe);
// So InterstitialPageImpl can access SetIsLoading.
friend class InterstitialPageImpl;
@@ -674,6 +675,10 @@
// watching |web_contents|. No-op if there is no such observer.
void RemoveDestructionObserver(WebContentsImpl* web_contents);
+ // Traverses all the RenderFrameHosts in the FrameTree and creates a set
+ // all the unique RenderWidgetHosts.
+ std::set<RenderWidgetHostImpl*> GetRenderWidgetHostsInTree();
+
// Callback function when showing JavaScript dialogs. Takes in a routing ID
// pair to identify the RenderFrameHost that opened the dialog, because it's
// possible for the RenderFrameHost to be deleted by the time this is called.
diff --git a/content/public/renderer/render_frame_observer.h b/content/public/renderer/render_frame_observer.h
index 63c73a5..ac836bb 100644
--- a/content/public/renderer/render_frame_observer.h
+++ b/content/public/renderer/render_frame_observer.h
@@ -39,6 +39,10 @@
// Called when a load is explicitly stopped by the user or browser.
virtual void OnStop() {}
+ // Called when the RenderFrame visiblity is changed.
+ virtual void WasHidden() {}
+ virtual void WasShown() {}
+
// These match the Blink API notifications
virtual void DidCommitProvisionalLoad(bool is_new_navigation) {}
virtual void DidStartProvisionalLoad() {}
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index a1bf793..7be5f6e 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -416,6 +416,8 @@
g_routing_id_frame_map.Get().insert(std::make_pair(routing_id_, this));
CHECK(result.second) << "Inserting a duplicate item.";
+ render_view_->RegisterRenderFrame(this);
+
#if defined(OS_ANDROID)
new JavaBridgeDispatcher(this);
#endif
@@ -428,10 +430,13 @@
RenderFrameImpl::~RenderFrameImpl() {
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, RenderFrameGone());
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, OnDestruct());
+
#if defined(VIDEO_HOLE)
if (media_player_manager_)
render_view_->UnregisterVideoHoleFrame(this);
#endif // defined(VIDEO_HOLE)
+
+ render_view_->UnregisterRenderFrame(this);
g_routing_id_frame_map.Get().erase(routing_id_);
RenderThread::Get()->RemoveRoute(routing_id_);
}
@@ -2887,6 +2892,14 @@
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, OnStop());
}
+void RenderFrameImpl::WasHidden() {
+ FOR_EACH_OBSERVER(RenderFrameObserver, observers_, WasHidden());
+}
+
+void RenderFrameImpl::WasShown() {
+ FOR_EACH_OBSERVER(RenderFrameObserver, observers_, WasShown());
+}
+
// Tell the embedding application that the URL of the active page has changed.
void RenderFrameImpl::UpdateURL(blink::WebFrame* frame) {
DCHECK(!frame_ || frame_ == frame);
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 166f8194..e122028 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -131,6 +131,10 @@
// Notification from RenderView.
virtual void OnStop();
+ // Notifications from RenderWidget.
+ void WasHidden();
+ void WasShown();
+
// Start/Stop loading notifications.
// TODO(nasko): Those are page-level methods at this time and come from
// WebViewClient. We should move them to be WebFrameClient calls and put
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 5428b542..646b94b 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -768,6 +768,8 @@
TRACE_EVENT0("renderer", "RenderWidget::OnWasHidden");
// Go into a mode where we stop generating paint and scrolling events.
SetHidden(true);
+ FOR_EACH_OBSERVER(RenderFrameImpl, render_frames_,
+ WasHidden());
}
void RenderWidget::OnWasShown(bool needs_repainting) {
@@ -778,6 +780,8 @@
// See OnWasHidden
SetHidden(false);
+ FOR_EACH_OBSERVER(RenderFrameImpl, render_frames_,
+ WasShown());
if (!needs_repainting)
return;
@@ -2124,6 +2128,14 @@
swapped_out_frames_.RemoveObserver(frame);
}
+void RenderWidget::RegisterRenderFrame(RenderFrameImpl* frame) {
+ render_frames_.AddObserver(frame);
+}
+
+void RenderWidget::UnregisterRenderFrame(RenderFrameImpl* frame) {
+ render_frames_.RemoveObserver(frame);
+}
+
#if defined(VIDEO_HOLE)
void RenderWidget::RegisterVideoHoleFrame(RenderFrameImpl* frame) {
video_hole_frames_.AddObserver(frame);
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index 43811c38..fac71786 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -113,6 +113,11 @@
void RegisterSwappedOutChildFrame(RenderFrameImpl* frame);
void UnregisterSwappedOutChildFrame(RenderFrameImpl* frame);
+ // Functions to track all RenderFrame objects associated with this
+ // RenderWidget.
+ void RegisterRenderFrame(RenderFrameImpl* frame);
+ void UnregisterRenderFrame(RenderFrameImpl* frame);
+
#if defined(VIDEO_HOLE)
void RegisterVideoHoleFrame(RenderFrameImpl* frame);
void UnregisterVideoHoleFrame(RenderFrameImpl* frame);
@@ -720,6 +725,11 @@
ObserverList<RenderFrameImpl> video_hole_frames_;
#endif // defined(VIDEO_HOLE)
+ // A list of RenderFrames associated with this RenderWidget. Notifications
+ // are sent to each frame in the list for events such as changing
+ // visibility state for example.
+ ObserverList<RenderFrameImpl> render_frames_;
+
ui::MenuSourceType context_menu_source_type_;
gfx::Point touch_editing_context_menu_location_;