Skip to content

Commit

Permalink
Add TestObserver to RenderFrameProxyHost
Browse files Browse the repository at this point in the history
This CL adds TestObserver to RenderFrameProxyHost to replace testing
callbacks.

Also RenderFrameProxyHost::BindRemoteMainFrameInterfaces is separated
from RenderFrameProxyHost::CreateAndBindRemoteMainFrameInterfaces. So,
TestObserver can call OnRemoteMainFrameBound in the right place.

This is a precursor CL to pass RemoteFrame mojo interfaces through its
creation messages.

Bug: 1190158
Change-Id: Iac085c475aef27b1d4f18d0fea2205125a465f68
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2945253
Commit-Queue: Yeunjoo Choi <ychoi@igalia.com>
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#891961}
  • Loading branch information
duswnchl authored and Chromium LUCI CQ committed Jun 14, 2021
1 parent 10c414d commit 9d7385c
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 150 deletions.
4 changes: 2 additions & 2 deletions content/browser/renderer_host/render_frame_host_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3941,7 +3941,7 @@ void RenderFrameHostImpl::Unload(RenderFrameProxyHost* proxy, bool is_loading) {
proxy->GetRoutingID(), is_loading,
proxy->frame_tree_node()->current_replication_state().Clone(),
proxy->GetFrameToken(),
proxy->BindAndPassRemoteMainFrameInterfaces());
proxy->CreateAndBindRemoteMainFrameInterfaces());
// Remember that a RenderFrameProxy was created as part of processing the
// Unload message above.
proxy->SetRenderFrameProxyCreated(true);
Expand Down Expand Up @@ -3974,7 +3974,7 @@ void RenderFrameHostImpl::SwapOuterDelegateFrame(RenderFrameProxyHost* proxy) {
GetMojomFrameInRenderer()->Unload(
proxy->GetRoutingID(), /*is_loading=*/false,
frame_tree_node()->current_replication_state().Clone(),
proxy->GetFrameToken(), proxy->BindAndPassRemoteMainFrameInterfaces());
proxy->GetFrameToken(), proxy->CreateAndBindRemoteMainFrameInterfaces());
}

void RenderFrameHostImpl::DetachFromProxy() {
Expand Down
119 changes: 64 additions & 55 deletions content/browser/renderer_host/render_frame_host_manager_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2067,16 +2067,13 @@ TEST_P(RenderFrameHostManagerTestWithSiteIsolation,
// This class intercepts RenderFrameProxyHost creations, and overrides their
// respective blink::mojom::RemoteFrame instances, so that it can watch the
// updates of opener frames.
class UpdateOpenerProxyObserver {
class UpdateOpenerProxyObserver : public RenderFrameProxyHost::TestObserver {
public:
UpdateOpenerProxyObserver() {
RenderFrameProxyHost::SetCreatedCallbackForTesting(base::BindRepeating(
&UpdateOpenerProxyObserver::RenderFrameProxyHostCreatedCallback,
base::Unretained(this)));
RenderFrameProxyHost::SetObserverForTesting(this);
}
~UpdateOpenerProxyObserver() {
RenderFrameProxyHost::SetCreatedCallbackForTesting(
RenderFrameProxyHost::CreatedCallback());
~UpdateOpenerProxyObserver() override {
RenderFrameProxyHost::SetObserverForTesting(nullptr);
}
absl::optional<blink::FrameToken> OpenerFrameToken(
RenderFrameProxyHost* proxy) {
Expand All @@ -2101,7 +2098,7 @@ class UpdateOpenerProxyObserver {
absl::optional<blink::FrameToken> frame_token_;
};

void RenderFrameProxyHostCreatedCallback(RenderFrameProxyHost* proxy_host) {
void OnCreated(RenderFrameProxyHost* proxy_host) override {
remote_frames_[proxy_host] = std::make_unique<Remote>(proxy_host);
}

Expand Down Expand Up @@ -2328,19 +2325,41 @@ TEST_P(RenderFrameHostManagerTest, TraverseComplexOpenerChain) {
nodes_with_back_links.end());
}

// Stub out remote frame mojo binding. Intercepts calls to SetPageFocus
// and marks the message as received.
class PageFocusRemoteFrame : public content::FakeRemoteFrame {
// This class intercepts RenderFrameProxyHost creations, and overrides their
// respective blink::mojom::RemoteFrame instances, so that it can watch the
// start and stop loading states.
class PageFocusProxyObserver : public RenderFrameProxyHost::TestObserver {
public:
explicit PageFocusRemoteFrame(RenderFrameProxyHost* render_frame_proxy_host) {
Init(render_frame_proxy_host->GetRemoteAssociatedInterfacesTesting());
PageFocusProxyObserver() {
RenderFrameProxyHost::SetObserverForTesting(this);
}
~PageFocusProxyObserver() override {
RenderFrameProxyHost::SetObserverForTesting(nullptr);
}
bool IsPageFocused(RenderFrameProxyHost* proxy) {
return remote_frames_[proxy]->set_page_focus();
}

void SetPageFocus(bool is_focused) override { set_page_focus_ = is_focused; }
bool IsPageFocused() { return set_page_focus_; }

private:
bool set_page_focus_ = false;
class Remote : public content::FakeRemoteFrame {
public:
explicit Remote(RenderFrameProxyHost* proxy) {
Init(proxy->GetRemoteAssociatedInterfacesTesting());
}
void SetPageFocus(bool is_focused) override {
set_page_focus_ = is_focused;
}
bool set_page_focus() { return set_page_focus_; }

private:
bool set_page_focus_ = false;
};

void OnCreated(RenderFrameProxyHost* proxy_host) override {
remote_frames_[proxy_host] = std::make_unique<Remote>(proxy_host);
}

std::map<RenderFrameProxyHost*, std::unique_ptr<Remote>> remote_frames_;
};

// Check that when a window is focused/blurred, the message that sets
Expand All @@ -2355,6 +2374,9 @@ TEST_P(RenderFrameHostManagerTest, PageFocusPropagatesToSubframeProcesses) {
if (!AreAllSitesIsolatedForTesting())
return;

// Start monitoring RenderFrameProxyHost.
PageFocusProxyObserver proxy_observer;

const GURL kUrlA("http://a.com/");
const GURL kUrlB("http://b.com/");
const GURL kUrlC("http://c.com/");
Expand Down Expand Up @@ -2407,9 +2429,6 @@ TEST_P(RenderFrameHostManagerTest, PageFocusPropagatesToSubframeProcesses) {
root->render_manager()->GetRenderFrameProxyHost(host1->GetSiteInstance());
EXPECT_TRUE(proxyB);

// Create PageFocusRemoteFrame to intercept SetPageFocus to RemoteFrame.
PageFocusRemoteFrame remote_frame1(proxyB);

TestRenderFrameHost* host2 =
static_cast<TestRenderFrameHost*>(NavigateToEntry(child2, &entryB));

Expand All @@ -2430,9 +2449,6 @@ TEST_P(RenderFrameHostManagerTest, PageFocusPropagatesToSubframeProcesses) {
root->render_manager()->GetRenderFrameProxyHost(host3->GetSiteInstance());
EXPECT_TRUE(proxyC);

// Create PageFocusRemoteFrame to intercept SetPageFocus to RemoteFrame.
PageFocusRemoteFrame remote_frame3(proxyC);

DidNavigateFrame(child3, host3);

// Make sure the first two subframes and the third subframe are placed in
Expand All @@ -2454,8 +2470,8 @@ TEST_P(RenderFrameHostManagerTest, PageFocusPropagatesToSubframeProcesses) {
main_test_rfh()->GetRenderWidgetHost()->Focus();
base::RunLoop().RunUntilIdle();
VerifyPageFocusMessage(main_test_rfh()->GetRenderWidgetHost(), true);
EXPECT_TRUE(remote_frame1.IsPageFocused());
EXPECT_TRUE(remote_frame3.IsPageFocused());
EXPECT_TRUE(proxy_observer.IsPageFocused(proxyB));
EXPECT_TRUE(proxy_observer.IsPageFocused(proxyC));

// Similarly, simulate focus loss on main page, and verify that the focus
// message was sent to all processes.
Expand All @@ -2465,8 +2481,8 @@ TEST_P(RenderFrameHostManagerTest, PageFocusPropagatesToSubframeProcesses) {
main_test_rfh()->GetRenderWidgetHost()->Blur();
base::RunLoop().RunUntilIdle();
VerifyPageFocusMessage(main_test_rfh()->GetRenderWidgetHost(), false);
EXPECT_FALSE(remote_frame1.IsPageFocused());
EXPECT_FALSE(remote_frame3.IsPageFocused());
EXPECT_FALSE(proxy_observer.IsPageFocused(proxyB));
EXPECT_FALSE(proxy_observer.IsPageFocused(proxyC));
}

// Check that page-level focus state is preserved across subframe navigations.
Expand All @@ -2480,6 +2496,9 @@ TEST_P(RenderFrameHostManagerTest,
if (!AreAllSitesIsolatedForTesting())
return;

// Start monitoring RenderFrameProxyHost.
PageFocusProxyObserver proxy_observer;

const GURL kUrlA("http://a.com/");
const GURL kUrlB("http://b.com/");
const GURL kUrlC("http://c.com/");
Expand Down Expand Up @@ -2529,17 +2548,14 @@ TEST_P(RenderFrameHostManagerTest,
root->render_manager()->GetRenderFrameProxyHost(hostC->GetSiteInstance());
EXPECT_TRUE(proxyC);

// Create PageFocusRemoteFrame to intercept SetPageFocus to RemoteFrame.
PageFocusRemoteFrame remote_frame(proxyC);

DidNavigateFrame(child, hostC);

base::RunLoop().RunUntilIdle();

// Since the B->C navigation happened while the current page was focused,
// page focus should propagate to the new subframe process. Check that
// process C received the proper focus message.
EXPECT_TRUE(remote_frame.IsPageFocused());
EXPECT_TRUE(proxy_observer.IsPageFocused(proxyC));
}

// Checks that a restore navigation to a WebUI works.
Expand Down Expand Up @@ -2996,17 +3012,14 @@ TEST_P(RenderFrameHostManagerTest, NavigateCrossSiteBetweenWebUIs) {

// This class intercepts RenderFrameProxyHost creations, and overrides their
// respective blink::mojom::RemoteFrame instances.
class InsecureRequestPolicyProxyObserver {
class InsecureRequestPolicyProxyObserver
: public RenderFrameProxyHost::TestObserver {
public:
InsecureRequestPolicyProxyObserver() {
RenderFrameProxyHost::SetCreatedCallbackForTesting(
base::BindRepeating(&InsecureRequestPolicyProxyObserver::
RenderFrameProxyHostCreatedCallback,
base::Unretained(this)));
RenderFrameProxyHost::SetObserverForTesting(this);
}
~InsecureRequestPolicyProxyObserver() {
RenderFrameProxyHost::SetCreatedCallbackForTesting(
RenderFrameProxyHost::CreatedCallback());
~InsecureRequestPolicyProxyObserver() override {
RenderFrameProxyHost::SetObserverForTesting(nullptr);
}
blink::mojom::InsecureRequestPolicy GetRequestPolicy(
RenderFrameProxyHost* proxy_host) {
Expand Down Expand Up @@ -3034,7 +3047,7 @@ class InsecureRequestPolicyProxyObserver {
blink::mojom::InsecureRequestPolicy enforce_insecure_request_policy_;
};

void RenderFrameProxyHostCreatedCallback(RenderFrameProxyHost* proxy_host) {
void OnCreated(RenderFrameProxyHost* proxy_host) override {
remote_frames_[proxy_host] = std::make_unique<RemoteFrame>(proxy_host);
}

Expand Down Expand Up @@ -3126,16 +3139,14 @@ TEST_P(RenderFrameHostManagerTestWithSiteIsolation,
// This class intercepts RenderFrameProxyHost creations, and overrides their
// respective blink::mojom::RemoteFrame instances, so that it can watch the
// start and stop loading states.
class StartStopLoadingProxyObserver {
class StartStopLoadingProxyObserver
: public RenderFrameProxyHost::TestObserver {
public:
StartStopLoadingProxyObserver() {
RenderFrameProxyHost::SetCreatedCallbackForTesting(base::BindRepeating(
&StartStopLoadingProxyObserver::RenderFrameProxyHostCreatedCallback,
base::Unretained(this)));
RenderFrameProxyHost::SetObserverForTesting(this);
}
~StartStopLoadingProxyObserver() {
RenderFrameProxyHost::SetCreatedCallbackForTesting(
RenderFrameProxyHost::CreatedCallback());
~StartStopLoadingProxyObserver() override {
RenderFrameProxyHost::SetObserverForTesting(nullptr);
}
bool IsLoading(RenderFrameProxyHost* proxy) {
return remote_frames_[proxy]->is_loading();
Expand All @@ -3155,7 +3166,7 @@ class StartStopLoadingProxyObserver {
bool is_loading_ = false;
};

void RenderFrameProxyHostCreatedCallback(RenderFrameProxyHost* proxy_host) {
void OnCreated(RenderFrameProxyHost* proxy_host) override {
remote_frames_[proxy_host] = std::make_unique<Remote>(proxy_host);
}

Expand Down Expand Up @@ -3408,20 +3419,18 @@ class AdStatusInterceptingRemoteFrame : public content::FakeRemoteFrame {
};

class RenderFrameHostManagerAdTaggingSignalTest
: public RenderFrameHostManagerTest {
: public RenderFrameHostManagerTest,
public RenderFrameProxyHost::TestObserver {
public:
RenderFrameHostManagerAdTaggingSignalTest() {
RenderFrameProxyHost::SetCreatedCallbackForTesting(base::BindRepeating(
&RenderFrameHostManagerAdTaggingSignalTest::OnProxyHostCreated,
base::Unretained(this)));
RenderFrameProxyHost::SetObserverForTesting(this);
}

~RenderFrameHostManagerAdTaggingSignalTest() override {
RenderFrameProxyHost::SetCreatedCallbackForTesting(
RenderFrameProxyHost::CreatedCallback());
RenderFrameProxyHost::SetObserverForTesting(nullptr);
}

void OnProxyHostCreated(RenderFrameProxyHost* proxy_host) {
void OnCreated(RenderFrameProxyHost* proxy_host) override {
auto fake_remote_frame =
std::make_unique<AdStatusInterceptingRemoteFrame>();
fake_remote_frame->Init(proxy_host->GetRemoteAssociatedInterfacesTesting());
Expand Down
72 changes: 27 additions & 45 deletions content/browser/renderer_host/render_frame_proxy_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,7 @@ namespace content {

namespace {

RenderFrameProxyHost::CreatedCallback& GetProxyHostCreatedCallback() {
static base::NoDestructor<RenderFrameProxyHost::CreatedCallback> s_callback;
return *s_callback;
}

RenderFrameProxyHost::CreatedCallback& GetProxyHostDeletedCallback() {
static base::NoDestructor<RenderFrameProxyHost::DeletedCallback> s_callback;
return *s_callback;
}

RenderFrameProxyHost::BindRemoteFrameCallback& GetBindRemoteFrameCallback() {
static base::NoDestructor<RenderFrameProxyHost::BindRemoteFrameCallback>
s_callback;
return *s_callback;
}
RenderFrameProxyHost::TestObserver* g_observer_for_testing = nullptr;

// The (process id, routing id) pair that identifies one RenderFrameProxy.
typedef std::pair<int32_t, int32_t> RenderFrameProxyHostID;
Expand Down Expand Up @@ -113,21 +99,10 @@ bool ShouldRecordPostMessageIncomingPageUkmEvent(
} // namespace

// static
void RenderFrameProxyHost::SetCreatedCallbackForTesting(
const CreatedCallback& created_callback) {
GetProxyHostCreatedCallback() = created_callback;
}

// static
void RenderFrameProxyHost::SetDeletedCallbackForTesting(
const DeletedCallback& deleted_callback) {
GetProxyHostDeletedCallback() = deleted_callback;
}

// static
void RenderFrameProxyHost::SetBindRemoteFrameCallbackForTesting(
const BindRemoteFrameCallback& bind_callback) {
GetBindRemoteFrameCallback() = bind_callback;
void RenderFrameProxyHost::SetObserverForTesting(TestObserver* observer) {
// Prevent clobbering by previously set TestObserver.
DCHECK(!observer || (observer && !g_observer_for_testing));
g_observer_for_testing = observer;
}

// static
Expand Down Expand Up @@ -197,13 +172,13 @@ RenderFrameProxyHost::RenderFrameProxyHost(
std::make_unique<CrossProcessFrameConnector>(this);
}

if (!GetProxyHostCreatedCallback().is_null())
GetProxyHostCreatedCallback().Run(this);
if (g_observer_for_testing)
g_observer_for_testing->OnCreated(this);
}

RenderFrameProxyHost::~RenderFrameProxyHost() {
if (!GetProxyHostDeletedCallback().is_null())
GetProxyHostDeletedCallback().Run(this);
if (g_observer_for_testing)
g_observer_for_testing->OnDeleted(this);

if (GetProcess()->IsInitializedAndNotDead()) {
// TODO(nasko): For now, don't send this IPC for top-level frames, as
Expand Down Expand Up @@ -306,7 +281,7 @@ bool RenderFrameProxyHost::InitRenderFrameProxy() {
frame_tree_node_->tree_scope_type(),
frame_tree_node_->current_replication_state().Clone(),
frame_tree_node_->devtools_frame_token(),
BindAndPassRemoteMainFrameInterfaces());
CreateAndBindRemoteMainFrameInterfaces());

SetRenderFrameProxyCreated(true);

Expand Down Expand Up @@ -795,21 +770,28 @@ RenderFrameProxyHost::BindRemoteMainFrameReceiverForTesting() {
}

mojom::RemoteMainFrameInterfacesPtr
RenderFrameProxyHost::BindAndPassRemoteMainFrameInterfaces() {
RenderFrameProxyHost::CreateAndBindRemoteMainFrameInterfaces() {
auto params = mojom::RemoteMainFrameInterfaces::New();
BindRemoteMainFrameInterfaces(
params->main_frame.InitWithNewEndpointAndPassRemote(),
params->main_frame_host.InitWithNewEndpointAndPassReceiver());
return params;
}

void RenderFrameProxyHost::BindRemoteMainFrameInterfaces(
mojo::PendingAssociatedRemote<blink::mojom::RemoteMainFrame>
remote_main_frame,
mojo::PendingAssociatedReceiver<blink::mojom::RemoteMainFrameHost>
remote_main_frame_host_receiver) {
DCHECK(!remote_main_frame_.is_bound());
DCHECK(!remote_main_frame_host_receiver_.is_bound());

auto params = mojom::RemoteMainFrameInterfaces::New();
params->main_frame = remote_main_frame_.BindNewEndpointAndPassReceiver();
remote_main_frame_.Bind(std::move(remote_main_frame));
remote_main_frame_host_receiver_.Bind(
params->main_frame_host.InitWithNewEndpointAndPassReceiver());
std::move(remote_main_frame_host_receiver));

// This callback is only for testing which needs to intercept RemoteMainFrame
// interfaces.
if (!GetBindRemoteFrameCallback().is_null())
GetBindRemoteFrameCallback().Run(this);

return params;
if (g_observer_for_testing)
g_observer_for_testing->OnRemoteMainFrameBound(this);
}

void RenderFrameProxyHost::InvalidateMojoConnection() {
Expand Down

0 comments on commit 9d7385c

Please sign in to comment.