| Index: content/browser/frame_host/render_frame_host_manager_unittest.cc
|
| diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc
|
| index 768b59fd4fb469e06597dae1a3bf97d4a722f2ae..f534336b4128e1b5d5e5a19d19c066d4cea5516f 100644
|
| --- a/content/browser/frame_host/render_frame_host_manager_unittest.cc
|
| +++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc
|
| @@ -18,6 +18,7 @@
|
| #include "content/browser/site_instance_impl.h"
|
| #include "content/browser/webui/web_ui_controller_factory_registry.h"
|
| #include "content/common/frame_messages.h"
|
| +#include "content/common/input_messages.h"
|
| #include "content/common/site_isolation_policy.h"
|
| #include "content/common/view_messages.h"
|
| #include "content/public/browser/notification_details.h"
|
| @@ -2480,4 +2481,118 @@ TEST_F(RenderFrameHostManagerTest, TraverseComplexOpenerChain) {
|
| nodes_with_back_links.end());
|
| }
|
|
|
| +// Check that when a window is focused/blurred, the message that sets
|
| +// page-level focus updates is sent to each process involved in rendering the
|
| +// current page.
|
| +//
|
| +// TODO(alexmos): Move this test to FrameTree unit tests once NavigateToEntry
|
| +// is moved to a common place.
|
| +TEST_F(RenderFrameHostManagerTest, PageFocusPropagatesToSubframeProcesses) {
|
| + // This test only makes sense when cross-site subframes use separate
|
| + // processes.
|
| + if (!AreAllSitesIsolatedForTesting())
|
| + return;
|
| +
|
| + const GURL kUrlA("http://a.com/");
|
| + const GURL kUrlB("http://b.com/");
|
| + const GURL kUrlC("http://c.com/");
|
| +
|
| + // Set up a page at a.com with three subframes: two for b.com and one for
|
| + // c.com.
|
| + contents()->NavigateAndCommit(kUrlA);
|
| + main_test_rfh()->OnCreateChildFrame(
|
| + main_test_rfh()->GetProcess()->GetNextRoutingID(),
|
| + blink::WebTreeScopeType::Document, "frame1",
|
| + blink::WebSandboxFlags::None);
|
| + main_test_rfh()->OnCreateChildFrame(
|
| + main_test_rfh()->GetProcess()->GetNextRoutingID(),
|
| + blink::WebTreeScopeType::Document, "frame2",
|
| + blink::WebSandboxFlags::None);
|
| + main_test_rfh()->OnCreateChildFrame(
|
| + main_test_rfh()->GetProcess()->GetNextRoutingID(),
|
| + blink::WebTreeScopeType::Document, "frame3",
|
| + blink::WebSandboxFlags::None);
|
| +
|
| + FrameTreeNode* root = contents()->GetFrameTree()->root();
|
| + RenderFrameHostManager* child1 = root->child_at(0)->render_manager();
|
| + RenderFrameHostManager* child2 = root->child_at(1)->render_manager();
|
| + RenderFrameHostManager* child3 = root->child_at(2)->render_manager();
|
| +
|
| + // Navigate first two subframes to B.
|
| + NavigationEntryImpl entryB(nullptr /* instance */, -1 /* page_id */, kUrlB,
|
| + Referrer(kUrlA, blink::WebReferrerPolicyDefault),
|
| + base::string16() /* title */,
|
| + ui::PAGE_TRANSITION_LINK,
|
| + false /* is_renderer_init */);
|
| + TestRenderFrameHost* host1 =
|
| + static_cast<TestRenderFrameHost*>(NavigateToEntry(child1, entryB));
|
| + TestRenderFrameHost* host2 =
|
| + static_cast<TestRenderFrameHost*>(NavigateToEntry(child2, entryB));
|
| + child1->DidNavigateFrame(host1, true);
|
| + child2->DidNavigateFrame(host2, true);
|
| +
|
| + // Navigate the third subframe to C.
|
| + NavigationEntryImpl entryC(nullptr /* instance */, -1 /* page_id */, kUrlC,
|
| + Referrer(kUrlA, blink::WebReferrerPolicyDefault),
|
| + base::string16() /* title */,
|
| + ui::PAGE_TRANSITION_LINK,
|
| + false /* is_renderer_init */);
|
| + TestRenderFrameHost* host3 =
|
| + static_cast<TestRenderFrameHost*>(NavigateToEntry(child3, entryC));
|
| + child3->DidNavigateFrame(host3, true);
|
| +
|
| + // Make sure the first two subframes and the third subframe are placed in
|
| + // distinct processes.
|
| + EXPECT_NE(host1->GetProcess(), main_test_rfh()->GetProcess());
|
| + EXPECT_EQ(host1->GetProcess(), host2->GetProcess());
|
| + EXPECT_NE(host3->GetProcess(), main_test_rfh()->GetProcess());
|
| + EXPECT_NE(host3->GetProcess(), host1->GetProcess());
|
| +
|
| + // The main frame should have proxies for B and C.
|
| + RenderFrameProxyHost* proxyB =
|
| + root->render_manager()->GetRenderFrameProxyHost(host1->GetSiteInstance());
|
| + EXPECT_TRUE(proxyB);
|
| + RenderFrameProxyHost* proxyC =
|
| + root->render_manager()->GetRenderFrameProxyHost(host3->GetSiteInstance());
|
| + EXPECT_TRUE(proxyC);
|
| +
|
| + // Helper to check that the provided RenderProcessHost received exactly one
|
| + // page focus message with the provided focus and routing ID values.
|
| + auto verify_focus_message = [](MockRenderProcessHost* rph,
|
| + bool expected_focus,
|
| + int expected_routing_id) {
|
| + const IPC::Message* message =
|
| + rph->sink().GetUniqueMessageMatching(InputMsg_SetFocus::ID);
|
| + EXPECT_TRUE(message);
|
| + EXPECT_EQ(expected_routing_id, message->routing_id());
|
| + InputMsg_SetFocus::Param params;
|
| + EXPECT_TRUE(InputMsg_SetFocus::Read(message, ¶ms));
|
| + EXPECT_EQ(expected_focus, base::get<0>(params));
|
| + };
|
| +
|
| + // Focus the main page, and verify that the focus message was sent to all
|
| + // processes. The message to A should be sent through the main frame's
|
| + // RenderViewHost, and the message to B and C should be send through proxies
|
| + // that the main frame has for B and C.
|
| + main_test_rfh()->GetProcess()->sink().ClearMessages();
|
| + host1->GetProcess()->sink().ClearMessages();
|
| + host3->GetProcess()->sink().ClearMessages();
|
| + main_test_rfh()->GetRenderWidgetHost()->Focus();
|
| + verify_focus_message(main_test_rfh()->GetProcess(), true,
|
| + main_test_rfh()->GetRenderViewHost()->GetRoutingID());
|
| + verify_focus_message(host1->GetProcess(), true, proxyB->GetRoutingID());
|
| + verify_focus_message(host3->GetProcess(), true, proxyC->GetRoutingID());
|
| +
|
| + // Similarly, simulate focus loss on main page, and verify that the focus
|
| + // message was sent to all processes.
|
| + main_test_rfh()->GetProcess()->sink().ClearMessages();
|
| + host1->GetProcess()->sink().ClearMessages();
|
| + host3->GetProcess()->sink().ClearMessages();
|
| + main_test_rfh()->GetRenderWidgetHost()->Blur();
|
| + verify_focus_message(main_test_rfh()->GetProcess(), false,
|
| + main_test_rfh()->GetRenderViewHost()->GetRoutingID());
|
| + verify_focus_message(host1->GetProcess(), false, proxyB->GetRoutingID());
|
| + verify_focus_message(host3->GetProcess(), false, proxyC->GetRoutingID());
|
| +}
|
| +
|
| } // namespace content
|
|
|