blob: 63435d11a6b877fe7fc93205b9724158e2790f6f [file] [log] [blame]
rockot96c63e32017-03-20 23:23:031// Copyright 2017 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/macros.h"
6#include "base/memory/ptr_util.h"
7#include "content/browser/web_contents/web_contents_impl.h"
8#include "content/public/browser/web_contents_binding_set.h"
9#include "content/public/test/browser_test_utils.h"
10#include "content/public/test/content_browser_test.h"
11#include "content/public/test/content_browser_test_utils.h"
Ken Rockot59f7dd72017-05-31 16:00:0012#include "content/public/test/test_utils.h"
rockot96c63e32017-03-20 23:23:0313#include "content/public/test/web_contents_binding_set_test_binder.h"
14#include "content/shell/browser/shell.h"
15#include "content/test/test_browser_associated_interfaces.mojom.h"
Ken Rockot59f7dd72017-05-31 16:00:0016#include "net/dns/mock_host_resolver.h"
rockot96c63e32017-03-20 23:23:0317
18namespace content {
19
rockot96c63e32017-03-20 23:23:0320namespace {
21
Ken Rockot59f7dd72017-05-31 16:00:0022const char kTestHost1[] = "foo.com";
23const char kTestHost2[] = "bar.com";
24
25class WebContentsBindingSetBrowserTest : public ContentBrowserTest {
26 public:
27 void SetUpOnMainThread() override {
28 host_resolver()->AddRule(kTestHost1, "127.0.0.1");
29 host_resolver()->AddRule(kTestHost2, "127.0.0.1");
30 }
31};
32
rockot96c63e32017-03-20 23:23:0333class TestInterfaceBinder : public WebContentsBindingSetTestBinder<
34 mojom::BrowserAssociatedInterfaceTestDriver> {
35 public:
36 explicit TestInterfaceBinder(const base::Closure& bind_callback)
37 : bind_callback_(bind_callback) {}
38 ~TestInterfaceBinder() override {}
39
40 void BindRequest(RenderFrameHost* frame_host,
41 mojom::BrowserAssociatedInterfaceTestDriverAssociatedRequest
42 request) override {
43 bind_callback_.Run();
44 }
45
46 private:
47 const base::Closure bind_callback_;
48
49 DISALLOW_COPY_AND_ASSIGN(TestInterfaceBinder);
50};
51
Ken Rockot59f7dd72017-05-31 16:00:0052class TestFrameInterfaceBinder : public mojom::WebContentsFrameBindingSetTest {
53 public:
54 explicit TestFrameInterfaceBinder(WebContents* web_contents)
55 : bindings_(web_contents, this) {}
56 ~TestFrameInterfaceBinder() override {}
57
58 private:
59 // mojom::WebContentsFrameBindingSetTest:
60 void Ping(PingCallback callback) override { NOTREACHED(); }
61
62 WebContentsFrameBindingSet<mojom::WebContentsFrameBindingSetTest> bindings_;
63};
64
rockot96c63e32017-03-20 23:23:0365} // namespace
66
67IN_PROC_BROWSER_TEST_F(WebContentsBindingSetBrowserTest, OverrideForTesting) {
68 NavigateToURL(shell(), GURL("data:text/html,ho hum"));
69
70 // Ensure that we can add a WebContentsFrameBindingSet and then override its
71 // request handler.
rockot8bbad222017-03-22 04:34:0572 auto* web_contents = shell()->web_contents();
rockot96c63e32017-03-20 23:23:0373 WebContentsFrameBindingSet<mojom::BrowserAssociatedInterfaceTestDriver>
74 frame_bindings(web_contents, nullptr);
75
76 // Now override the binder for this interface. It quits |run_loop| whenever
77 // an incoming interface request is received.
78 base::RunLoop run_loop;
rockot8bbad222017-03-22 04:34:0579 WebContentsBindingSet::GetForWebContents<
80 mojom::BrowserAssociatedInterfaceTestDriver>(web_contents)
81 ->SetBinderForTesting(
rockot96c63e32017-03-20 23:23:0382 base::MakeUnique<TestInterfaceBinder>(run_loop.QuitClosure()));
83
84 // Simulate an inbound request for the test interface. This should get routed
85 // to the overriding binder and allow the test to complete.
86 mojom::BrowserAssociatedInterfaceTestDriverAssociatedPtr override_client;
rockot8bbad222017-03-22 04:34:0587 static_cast<WebContentsImpl*>(web_contents)
88 ->OnAssociatedInterfaceRequest(
89 web_contents->GetMainFrame(),
90 mojom::BrowserAssociatedInterfaceTestDriver::Name_,
91 mojo::MakeIsolatedRequest(&override_client).PassHandle());
rockot96c63e32017-03-20 23:23:0392 run_loop.Run();
93}
94
Ken Rockot59f7dd72017-05-31 16:00:0095IN_PROC_BROWSER_TEST_F(WebContentsBindingSetBrowserTest, CloseOnFrameDeletion) {
96 EXPECT_TRUE(embedded_test_server()->Start());
97 EXPECT_TRUE(NavigateToURL(
98 shell(), embedded_test_server()->GetURL(kTestHost1, "/hello.html")));
99
100 // Simulate an inbound request on the navigated main frame.
101 auto* web_contents = shell()->web_contents();
102 TestFrameInterfaceBinder binder(web_contents);
103 mojom::WebContentsFrameBindingSetTestAssociatedPtr override_client;
104 static_cast<WebContentsImpl*>(web_contents)
105 ->OnAssociatedInterfaceRequest(
106 web_contents->GetMainFrame(),
107 mojom::WebContentsFrameBindingSetTest::Name_,
108 mojo::MakeIsolatedRequest(&override_client).PassHandle());
109
110 base::RunLoop run_loop;
111 override_client.set_connection_error_handler(run_loop.QuitClosure());
112
113 // Now navigate the WebContents elsewhere, eventually tearing down the old
114 // main frame.
115 RenderFrameDeletedObserver deleted_observer(web_contents->GetMainFrame());
116 EXPECT_TRUE(NavigateToURL(
117 shell(), embedded_test_server()->GetURL(kTestHost2, "/title2.html")));
118 deleted_observer.WaitUntilDeleted();
119
120 // Verify that this message never reaches the binding for the old frame. If it
121 // does, the impl will hit a DCHECK. The RunLoop terminates when the client is
122 // disconnected.
123 override_client->Ping(base::Bind([] {}));
124 run_loop.Run();
125}
126
rockot96c63e32017-03-20 23:23:03127} // namespace content