rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 1 | // 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" |
Gabriel Charette | 078e366 | 2017-08-28 22:59:04 | [diff] [blame] | 7 | #include "base/run_loop.h" |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 8 | #include "content/browser/web_contents/web_contents_impl.h" |
| 9 | #include "content/public/browser/web_contents_binding_set.h" |
| 10 | #include "content/public/test/browser_test_utils.h" |
| 11 | #include "content/public/test/content_browser_test.h" |
| 12 | #include "content/public/test/content_browser_test_utils.h" |
Ken Rockot | 59f7dd7 | 2017-05-31 16:00:00 | [diff] [blame] | 13 | #include "content/public/test/test_utils.h" |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 14 | #include "content/public/test/web_contents_binding_set_test_binder.h" |
| 15 | #include "content/shell/browser/shell.h" |
| 16 | #include "content/test/test_browser_associated_interfaces.mojom.h" |
Ken Rockot | 59f7dd7 | 2017-05-31 16:00:00 | [diff] [blame] | 17 | #include "net/dns/mock_host_resolver.h" |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 18 | |
| 19 | namespace content { |
| 20 | |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 21 | namespace { |
| 22 | |
Ken Rockot | 59f7dd7 | 2017-05-31 16:00:00 | [diff] [blame] | 23 | const char kTestHost1[] = "foo.com"; |
| 24 | const char kTestHost2[] = "bar.com"; |
| 25 | |
| 26 | class WebContentsBindingSetBrowserTest : public ContentBrowserTest { |
| 27 | public: |
| 28 | void SetUpOnMainThread() override { |
| 29 | host_resolver()->AddRule(kTestHost1, "127.0.0.1"); |
| 30 | host_resolver()->AddRule(kTestHost2, "127.0.0.1"); |
| 31 | } |
| 32 | }; |
| 33 | |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 34 | class TestInterfaceBinder : public WebContentsBindingSetTestBinder< |
| 35 | mojom::BrowserAssociatedInterfaceTestDriver> { |
| 36 | public: |
| 37 | explicit TestInterfaceBinder(const base::Closure& bind_callback) |
| 38 | : bind_callback_(bind_callback) {} |
| 39 | ~TestInterfaceBinder() override {} |
| 40 | |
| 41 | void BindRequest(RenderFrameHost* frame_host, |
| 42 | mojom::BrowserAssociatedInterfaceTestDriverAssociatedRequest |
| 43 | request) override { |
| 44 | bind_callback_.Run(); |
| 45 | } |
| 46 | |
| 47 | private: |
| 48 | const base::Closure bind_callback_; |
| 49 | |
| 50 | DISALLOW_COPY_AND_ASSIGN(TestInterfaceBinder); |
| 51 | }; |
| 52 | |
Ken Rockot | 59f7dd7 | 2017-05-31 16:00:00 | [diff] [blame] | 53 | class TestFrameInterfaceBinder : public mojom::WebContentsFrameBindingSetTest { |
| 54 | public: |
| 55 | explicit TestFrameInterfaceBinder(WebContents* web_contents) |
| 56 | : bindings_(web_contents, this) {} |
| 57 | ~TestFrameInterfaceBinder() override {} |
| 58 | |
| 59 | private: |
| 60 | // mojom::WebContentsFrameBindingSetTest: |
| 61 | void Ping(PingCallback callback) override { NOTREACHED(); } |
| 62 | |
| 63 | WebContentsFrameBindingSet<mojom::WebContentsFrameBindingSetTest> bindings_; |
| 64 | }; |
| 65 | |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 66 | } // namespace |
| 67 | |
| 68 | IN_PROC_BROWSER_TEST_F(WebContentsBindingSetBrowserTest, OverrideForTesting) { |
| 69 | NavigateToURL(shell(), GURL("data:text/html,ho hum")); |
| 70 | |
| 71 | // Ensure that we can add a WebContentsFrameBindingSet and then override its |
| 72 | // request handler. |
rockot | 8bbad22 | 2017-03-22 04:34:05 | [diff] [blame] | 73 | auto* web_contents = shell()->web_contents(); |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 74 | WebContentsFrameBindingSet<mojom::BrowserAssociatedInterfaceTestDriver> |
| 75 | frame_bindings(web_contents, nullptr); |
| 76 | |
| 77 | // Now override the binder for this interface. It quits |run_loop| whenever |
| 78 | // an incoming interface request is received. |
| 79 | base::RunLoop run_loop; |
rockot | 8bbad22 | 2017-03-22 04:34:05 | [diff] [blame] | 80 | WebContentsBindingSet::GetForWebContents< |
| 81 | mojom::BrowserAssociatedInterfaceTestDriver>(web_contents) |
| 82 | ->SetBinderForTesting( |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 83 | base::MakeUnique<TestInterfaceBinder>(run_loop.QuitClosure())); |
| 84 | |
| 85 | // Simulate an inbound request for the test interface. This should get routed |
| 86 | // to the overriding binder and allow the test to complete. |
| 87 | mojom::BrowserAssociatedInterfaceTestDriverAssociatedPtr override_client; |
rockot | 8bbad22 | 2017-03-22 04:34:05 | [diff] [blame] | 88 | static_cast<WebContentsImpl*>(web_contents) |
| 89 | ->OnAssociatedInterfaceRequest( |
| 90 | web_contents->GetMainFrame(), |
| 91 | mojom::BrowserAssociatedInterfaceTestDriver::Name_, |
| 92 | mojo::MakeIsolatedRequest(&override_client).PassHandle()); |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 93 | run_loop.Run(); |
| 94 | } |
| 95 | |
Ken Rockot | 59f7dd7 | 2017-05-31 16:00:00 | [diff] [blame] | 96 | IN_PROC_BROWSER_TEST_F(WebContentsBindingSetBrowserTest, CloseOnFrameDeletion) { |
| 97 | EXPECT_TRUE(embedded_test_server()->Start()); |
| 98 | EXPECT_TRUE(NavigateToURL( |
| 99 | shell(), embedded_test_server()->GetURL(kTestHost1, "/hello.html"))); |
| 100 | |
| 101 | // Simulate an inbound request on the navigated main frame. |
| 102 | auto* web_contents = shell()->web_contents(); |
| 103 | TestFrameInterfaceBinder binder(web_contents); |
| 104 | mojom::WebContentsFrameBindingSetTestAssociatedPtr override_client; |
| 105 | static_cast<WebContentsImpl*>(web_contents) |
| 106 | ->OnAssociatedInterfaceRequest( |
| 107 | web_contents->GetMainFrame(), |
| 108 | mojom::WebContentsFrameBindingSetTest::Name_, |
| 109 | mojo::MakeIsolatedRequest(&override_client).PassHandle()); |
| 110 | |
| 111 | base::RunLoop run_loop; |
| 112 | override_client.set_connection_error_handler(run_loop.QuitClosure()); |
| 113 | |
| 114 | // Now navigate the WebContents elsewhere, eventually tearing down the old |
| 115 | // main frame. |
| 116 | RenderFrameDeletedObserver deleted_observer(web_contents->GetMainFrame()); |
| 117 | EXPECT_TRUE(NavigateToURL( |
| 118 | shell(), embedded_test_server()->GetURL(kTestHost2, "/title2.html"))); |
| 119 | deleted_observer.WaitUntilDeleted(); |
| 120 | |
| 121 | // Verify that this message never reaches the binding for the old frame. If it |
| 122 | // does, the impl will hit a DCHECK. The RunLoop terminates when the client is |
| 123 | // disconnected. |
tzik | e2aca99 | 2017-09-05 08:50:54 | [diff] [blame^] | 124 | override_client->Ping(base::BindOnce([] {})); |
Ken Rockot | 59f7dd7 | 2017-05-31 16:00:00 | [diff] [blame] | 125 | run_loop.Run(); |
| 126 | } |
| 127 | |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 128 | } // namespace content |