OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <memory> | 5 #include <memory> |
6 | 6 |
7 #include "base/memory/ptr_util.h" | 7 #include "base/memory/ptr_util.h" |
8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
9 #include "content/public/test/browser_test.h" | 9 #include "content/public/test/browser_test.h" |
10 #include "headless/public/domains/page.h" | |
11 #include "headless/public/domains/runtime.h" | 10 #include "headless/public/domains/runtime.h" |
12 #include "headless/public/domains/types.h" | |
13 #include "headless/public/headless_browser.h" | 11 #include "headless/public/headless_browser.h" |
14 #include "headless/public/headless_browser_context.h" | 12 #include "headless/public/headless_browser_context.h" |
15 #include "headless/public/headless_devtools_client.h" | 13 #include "headless/public/headless_devtools_client.h" |
16 #include "headless/public/headless_devtools_target.h" | 14 #include "headless/public/headless_devtools_target.h" |
17 #include "headless/public/headless_web_contents.h" | 15 #include "headless/public/headless_web_contents.h" |
18 #include "headless/test/headless_browser_test.h" | 16 #include "headless/test/headless_browser_test.h" |
| 17 #include "headless/test/test_protocol_handler.h" |
19 #include "net/base/io_buffer.h" | 18 #include "net/base/io_buffer.h" |
20 #include "net/http/http_response_headers.h" | 19 #include "net/http/http_response_headers.h" |
21 #include "net/test/spawned_test_server/spawned_test_server.h" | 20 #include "net/test/spawned_test_server/spawned_test_server.h" |
22 #include "net/url_request/url_request_job.h" | 21 #include "net/url_request/url_request_job.h" |
23 #include "testing/gtest/include/gtest/gtest.h" | 22 #include "testing/gtest/include/gtest/gtest.h" |
24 #include "ui/gfx/geometry/size.h" | 23 #include "ui/gfx/geometry/size.h" |
25 | 24 |
26 namespace headless { | 25 namespace headless { |
27 namespace { | 26 namespace { |
28 | |
29 class TestURLRequestJob : public net::URLRequestJob { | |
30 public: | |
31 TestURLRequestJob(net::URLRequest* request, | |
32 net::NetworkDelegate* network_delegate, | |
33 const std::string& body); | |
34 ~TestURLRequestJob() override {} | |
35 | |
36 // net::URLRequestJob implementation: | |
37 void Start() override; | |
38 void GetResponseInfo(net::HttpResponseInfo* info) override; | |
39 int ReadRawData(net::IOBuffer* buf, int buf_size) override; | |
40 | |
41 private: | |
42 scoped_refptr<net::StringIOBuffer> body_; | |
43 scoped_refptr<net::DrainableIOBuffer> src_buf_; | |
44 | |
45 DISALLOW_COPY_AND_ASSIGN(TestURLRequestJob); | |
46 }; | |
47 | |
48 TestURLRequestJob::TestURLRequestJob(net::URLRequest* request, | |
49 net::NetworkDelegate* network_delegate, | |
50 const std::string& body) | |
51 : net::URLRequestJob(request, network_delegate), | |
52 body_(new net::StringIOBuffer(body)), | |
53 src_buf_(new net::DrainableIOBuffer(body_.get(), body_->size())) {} | |
54 | |
55 void TestURLRequestJob::Start() { | |
56 NotifyHeadersComplete(); | |
57 } | |
58 | |
59 void TestURLRequestJob::GetResponseInfo(net::HttpResponseInfo* info) { | |
60 info->headers = | |
61 new net::HttpResponseHeaders("Content-Type: text/html\r\n\r\n"); | |
62 } | |
63 | |
64 int TestURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size) { | |
65 scoped_refptr<net::DrainableIOBuffer> dest_buf( | |
66 new net::DrainableIOBuffer(buf, buf_size)); | |
67 while (src_buf_->BytesRemaining() > 0 && dest_buf->BytesRemaining() > 0) { | |
68 *dest_buf->data() = *src_buf_->data(); | |
69 src_buf_->DidConsume(1); | |
70 dest_buf->DidConsume(1); | |
71 } | |
72 return dest_buf->BytesConsumed(); | |
73 } | |
74 | |
75 class TestProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { | |
76 public: | |
77 TestProtocolHandler(const std::string& body); | |
78 ~TestProtocolHandler() override {} | |
79 | |
80 net::URLRequestJob* MaybeCreateJob( | |
81 net::URLRequest* request, | |
82 net::NetworkDelegate* network_delegate) const override; | |
83 | |
84 private: | |
85 std::string body_; | |
86 | |
87 DISALLOW_COPY_AND_ASSIGN(TestProtocolHandler); | |
88 }; | |
89 | |
90 TestProtocolHandler::TestProtocolHandler(const std::string& body) | |
91 : body_(body) {} | |
92 | |
93 net::URLRequestJob* TestProtocolHandler::MaybeCreateJob( | |
94 net::URLRequest* request, | |
95 net::NetworkDelegate* network_delegate) const { | |
96 return new TestURLRequestJob(request, network_delegate, body_); | |
97 } | |
98 | |
99 } // namespace | |
100 | |
101 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, CreateAndDestroyWebContents) { | |
102 HeadlessWebContents* web_contents = | |
103 browser()->CreateWebContentsBuilder().Build(); | |
104 EXPECT_TRUE(web_contents); | |
105 | |
106 EXPECT_EQ(static_cast<size_t>(1), browser()->GetAllWebContents().size()); | |
107 EXPECT_EQ(web_contents, browser()->GetAllWebContents()[0]); | |
108 // TODO(skyostil): Verify viewport dimensions once we can. | |
109 web_contents->Close(); | |
110 | |
111 EXPECT_TRUE(browser()->GetAllWebContents().empty()); | |
112 } | |
113 | |
114 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, CreateWithBadURL) { | |
115 GURL bad_url("not_valid"); | |
116 HeadlessWebContents* web_contents = | |
117 browser()->CreateWebContentsBuilder().SetInitialURL(bad_url).Build(); | |
118 EXPECT_FALSE(web_contents); | |
119 EXPECT_TRUE(browser()->GetAllWebContents().empty()); | |
120 } | |
121 | |
122 class HeadlessBrowserTestWithProxy : public HeadlessBrowserTest { | |
123 public: | |
124 HeadlessBrowserTestWithProxy() | |
125 : proxy_server_(net::SpawnedTestServer::TYPE_HTTP, | |
126 net::SpawnedTestServer::kLocalhost, | |
127 base::FilePath(FILE_PATH_LITERAL("headless/test/data"))) { | |
128 } | |
129 | |
130 void SetUp() override { | |
131 ASSERT_TRUE(proxy_server_.Start()); | |
132 HeadlessBrowserTest::SetUp(); | |
133 } | |
134 | |
135 void TearDown() override { | |
136 proxy_server_.Stop(); | |
137 HeadlessBrowserTest::TearDown(); | |
138 } | |
139 | |
140 net::SpawnedTestServer* proxy_server() { return &proxy_server_; } | |
141 | |
142 private: | |
143 net::SpawnedTestServer proxy_server_; | |
144 }; | |
145 | |
146 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTestWithProxy, SetProxyServer) { | |
147 HeadlessBrowser::Options::Builder builder; | |
148 builder.SetProxyServer(proxy_server()->host_port_pair()); | |
149 SetBrowserOptions(builder.Build()); | |
150 | |
151 // Load a page which doesn't actually exist, but for which the our proxy | |
152 // returns valid content anyway. | |
153 // | |
154 // TODO(altimin): Currently this construction does not serve hello.html | |
155 // from headless/test/data as expected. We should fix this. | |
156 HeadlessWebContents* web_contents = | |
157 browser() | |
158 ->CreateWebContentsBuilder() | |
159 .SetInitialURL(GURL("http://not-an-actual-domain.tld/hello.html")) | |
160 .Build(); | |
161 EXPECT_TRUE(WaitForLoad(web_contents)); | |
162 EXPECT_EQ(static_cast<size_t>(1), browser()->GetAllWebContents().size()); | |
163 EXPECT_EQ(web_contents, browser()->GetAllWebContents()[0]); | |
164 web_contents->Close(); | |
165 EXPECT_TRUE(browser()->GetAllWebContents().empty()); | |
166 } | |
167 | |
168 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, SetHostResolverRules) { | |
169 EXPECT_TRUE(embedded_test_server()->Start()); | |
170 HeadlessBrowser::Options::Builder builder; | |
171 builder.SetHostResolverRules( | |
172 base::StringPrintf("MAP not-an-actual-domain.tld 127.0.0.1:%d", | |
173 embedded_test_server()->host_port_pair().port())); | |
174 SetBrowserOptions(builder.Build()); | |
175 | |
176 // Load a page which doesn't actually exist, but which is turned into a valid | |
177 // address by our host resolver rules. | |
178 HeadlessWebContents* web_contents = | |
179 browser() | |
180 ->CreateWebContentsBuilder() | |
181 .SetInitialURL(GURL("http://not-an-actual-domain.tld/hello.html")) | |
182 .Build(); | |
183 EXPECT_TRUE(WaitForLoad(web_contents)); | |
184 } | |
185 | |
186 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, HttpProtocolHandler) { | |
187 const std::string kResponseBody = "<p>HTTP response body</p>"; | |
188 ProtocolHandlerMap protocol_handlers; | |
189 protocol_handlers[url::kHttpScheme] = | |
190 base::WrapUnique(new TestProtocolHandler(kResponseBody)); | |
191 | |
192 HeadlessBrowser::Options::Builder builder; | |
193 builder.SetProtocolHandlers(std::move(protocol_handlers)); | |
194 SetBrowserOptions(builder.Build()); | |
195 | |
196 // Load a page which doesn't actually exist, but which is fetched by our | |
197 // custom protocol handler. | |
198 HeadlessWebContents* web_contents = | |
199 browser() | |
200 ->CreateWebContentsBuilder() | |
201 .SetInitialURL(GURL("http://not-an-actual-domain.tld/hello.html")) | |
202 .Build(); | |
203 EXPECT_TRUE(WaitForLoad(web_contents)); | |
204 | |
205 std::string inner_html; | |
206 EXPECT_TRUE(EvaluateScript(web_contents, "document.body.innerHTML") | |
207 ->GetResult() | |
208 ->GetValue() | |
209 ->GetAsString(&inner_html)); | |
210 EXPECT_EQ(kResponseBody, inner_html); | |
211 } | |
212 | |
213 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, HttpsProtocolHandler) { | |
214 const std::string kResponseBody = "<p>HTTPS response body</p>"; | |
215 ProtocolHandlerMap protocol_handlers; | |
216 protocol_handlers[url::kHttpsScheme] = | |
217 base::WrapUnique(new TestProtocolHandler(kResponseBody)); | |
218 | |
219 HeadlessBrowser::Options::Builder builder; | |
220 builder.SetProtocolHandlers(std::move(protocol_handlers)); | |
221 SetBrowserOptions(builder.Build()); | |
222 | |
223 // Load a page which doesn't actually exist, but which is fetched by our | |
224 // custom protocol handler. | |
225 HeadlessWebContents* web_contents = | |
226 browser() | |
227 ->CreateWebContentsBuilder() | |
228 .SetInitialURL(GURL("https://not-an-actual-domain.tld/hello.html")) | |
229 .Build(); | |
230 EXPECT_TRUE(WaitForLoad(web_contents)); | |
231 | |
232 std::string inner_html; | |
233 EXPECT_TRUE(EvaluateScript(web_contents, "document.body.innerHTML") | |
234 ->GetResult() | |
235 ->GetValue() | |
236 ->GetAsString(&inner_html)); | |
237 EXPECT_EQ(kResponseBody, inner_html); | |
238 } | |
239 | |
240 namespace { | |
241 const char kMainPageCookie[] = "mood=quizzical"; | 27 const char kMainPageCookie[] = "mood=quizzical"; |
242 const char kIsolatedPageCookie[] = "mood=quixotic"; | 28 const char kIsolatedPageCookie[] = "mood=quixotic"; |
243 } // namespace | 29 } // namespace |
244 | 30 |
245 // This test creates two tabs pointing to the same security origin in two | 31 // This test creates two tabs pointing to the same security origin in two |
246 // different browser contexts and checks that they are isolated by creating two | 32 // different browser contexts and checks that they are isolated by creating two |
247 // cookies with the same name in both tabs. The steps are: | 33 // cookies with the same name in both tabs. The steps are: |
248 // | 34 // |
249 // 1. Wait for tab #1 to become ready for DevTools. | 35 // 1. Wait for tab #1 to become ready for DevTools. |
250 // 2. Create tab #2 and wait for it to become ready for DevTools. | 36 // 2. Create tab #2 and wait for it to become ready for DevTools. |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 | 149 |
364 private: | 150 private: |
365 std::unique_ptr<HeadlessBrowserContext> browser_context_; | 151 std::unique_ptr<HeadlessBrowserContext> browser_context_; |
366 HeadlessWebContents* web_contents2_; | 152 HeadlessWebContents* web_contents2_; |
367 std::unique_ptr<HeadlessDevToolsClient> devtools_client2_; | 153 std::unique_ptr<HeadlessDevToolsClient> devtools_client2_; |
368 std::unique_ptr<LoadObserver> load_observer_; | 154 std::unique_ptr<LoadObserver> load_observer_; |
369 }; | 155 }; |
370 | 156 |
371 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessBrowserContextIsolationTest); | 157 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessBrowserContextIsolationTest); |
372 | 158 |
| 159 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, ContextProtocolHandler) { |
| 160 const std::string kResponseBody = "<p>HTTP response body</p>"; |
| 161 ProtocolHandlerMap protocol_handlers; |
| 162 protocol_handlers[url::kHttpScheme] = |
| 163 base::WrapUnique(new TestProtocolHandler(kResponseBody)); |
| 164 |
| 165 // Load a page which doesn't actually exist, but which is fetched by our |
| 166 // custom protocol handler. |
| 167 std::unique_ptr<HeadlessBrowserContext> browser_context = |
| 168 browser() |
| 169 ->CreateBrowserContextBuilder() |
| 170 .SetProtocolHandlers(std::move(protocol_handlers)) |
| 171 .Build(); |
| 172 HeadlessWebContents* web_contents = |
| 173 browser() |
| 174 ->CreateWebContentsBuilder() |
| 175 .SetInitialURL(GURL("http://not-an-actual-domain.tld/hello.html")) |
| 176 .SetBrowserContext(browser_context.get()) |
| 177 .Build(); |
| 178 EXPECT_TRUE(WaitForLoad(web_contents)); |
| 179 |
| 180 std::string inner_html; |
| 181 EXPECT_TRUE(EvaluateScript(web_contents, "document.body.innerHTML") |
| 182 ->GetResult() |
| 183 ->GetValue() |
| 184 ->GetAsString(&inner_html)); |
| 185 EXPECT_EQ(kResponseBody, inner_html); |
| 186 web_contents->Close(); |
| 187 |
| 188 // Loading the same non-existent page using a tab with the default context |
| 189 // should not work since the protocol handler only exists on the custom |
| 190 // context. |
| 191 web_contents = |
| 192 browser() |
| 193 ->CreateWebContentsBuilder() |
| 194 .SetInitialURL(GURL("http://not-an-actual-domain.tld/hello.html")) |
| 195 .Build(); |
| 196 EXPECT_TRUE(WaitForLoad(web_contents)); |
| 197 EXPECT_TRUE(EvaluateScript(web_contents, "document.body.innerHTML") |
| 198 ->GetResult() |
| 199 ->GetValue() |
| 200 ->GetAsString(&inner_html)); |
| 201 EXPECT_EQ("", inner_html); |
| 202 web_contents->Close(); |
| 203 } |
| 204 |
373 } // namespace headless | 205 } // namespace headless |
OLD | NEW |