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" |
| 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 Rockot | 59f7dd7 | 2017-05-31 16:00:00 | [diff] [blame^] | 12 | #include "content/public/test/test_utils.h" |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 13 | #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 Rockot | 59f7dd7 | 2017-05-31 16:00:00 | [diff] [blame^] | 16 | #include "net/dns/mock_host_resolver.h" |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 17 | |
| 18 | namespace content { |
| 19 | |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 20 | namespace { |
| 21 | |
Ken Rockot | 59f7dd7 | 2017-05-31 16:00:00 | [diff] [blame^] | 22 | const char kTestHost1[] = "foo.com"; |
| 23 | const char kTestHost2[] = "bar.com"; |
| 24 | |
| 25 | class 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 | |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 33 | class 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 Rockot | 59f7dd7 | 2017-05-31 16:00:00 | [diff] [blame^] | 52 | class 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 | |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 65 | } // namespace |
| 66 | |
| 67 | IN_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. |
rockot | 8bbad22 | 2017-03-22 04:34:05 | [diff] [blame] | 72 | auto* web_contents = shell()->web_contents(); |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 73 | 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; |
rockot | 8bbad22 | 2017-03-22 04:34:05 | [diff] [blame] | 79 | WebContentsBindingSet::GetForWebContents< |
| 80 | mojom::BrowserAssociatedInterfaceTestDriver>(web_contents) |
| 81 | ->SetBinderForTesting( |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 82 | 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; |
rockot | 8bbad22 | 2017-03-22 04:34:05 | [diff] [blame] | 87 | static_cast<WebContentsImpl*>(web_contents) |
| 88 | ->OnAssociatedInterfaceRequest( |
| 89 | web_contents->GetMainFrame(), |
| 90 | mojom::BrowserAssociatedInterfaceTestDriver::Name_, |
| 91 | mojo::MakeIsolatedRequest(&override_client).PassHandle()); |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 92 | run_loop.Run(); |
| 93 | } |
| 94 | |
Ken Rockot | 59f7dd7 | 2017-05-31 16:00:00 | [diff] [blame^] | 95 | IN_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 | |
rockot | 96c63e3 | 2017-03-20 23:23:03 | [diff] [blame] | 127 | } // namespace content |