| 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/types.h" | 12 #include "headless/public/domains/types.h" |
| 11 #include "headless/public/headless_browser.h" | 13 #include "headless/public/headless_browser.h" |
| 14 #include "headless/public/headless_browser_context.h" |
| 15 #include "headless/public/headless_devtools_client.h" |
| 16 #include "headless/public/headless_devtools_target.h" |
| 12 #include "headless/public/headless_web_contents.h" | 17 #include "headless/public/headless_web_contents.h" |
| 13 #include "headless/test/headless_browser_test.h" | 18 #include "headless/test/headless_browser_test.h" |
| 14 #include "net/base/io_buffer.h" | 19 #include "net/base/io_buffer.h" |
| 15 #include "net/http/http_response_headers.h" | 20 #include "net/http/http_response_headers.h" |
| 16 #include "net/test/spawned_test_server/spawned_test_server.h" | 21 #include "net/test/spawned_test_server/spawned_test_server.h" |
| 17 #include "net/url_request/url_request_job.h" | 22 #include "net/url_request/url_request_job.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
| 19 #include "ui/gfx/geometry/size.h" | 24 #include "ui/gfx/geometry/size.h" |
| 20 | 25 |
| 21 namespace headless { | 26 namespace headless { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 net::URLRequestJob* TestProtocolHandler::MaybeCreateJob( | 93 net::URLRequestJob* TestProtocolHandler::MaybeCreateJob( |
| 89 net::URLRequest* request, | 94 net::URLRequest* request, |
| 90 net::NetworkDelegate* network_delegate) const { | 95 net::NetworkDelegate* network_delegate) const { |
| 91 return new TestURLRequestJob(request, network_delegate, body_); | 96 return new TestURLRequestJob(request, network_delegate, body_); |
| 92 } | 97 } |
| 93 | 98 |
| 94 } // namespace | 99 } // namespace |
| 95 | 100 |
| 96 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, CreateAndDestroyWebContents) { | 101 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, CreateAndDestroyWebContents) { |
| 97 HeadlessWebContents* web_contents = | 102 HeadlessWebContents* web_contents = |
| 98 browser()->CreateWebContents(GURL("about:blank"), gfx::Size(800, 600)); | 103 browser()->CreateWebContentsBuilder().Build(); |
| 99 EXPECT_TRUE(web_contents); | 104 EXPECT_TRUE(web_contents); |
| 100 | 105 |
| 101 EXPECT_EQ(static_cast<size_t>(1), browser()->GetAllWebContents().size()); | 106 EXPECT_EQ(static_cast<size_t>(1), browser()->GetAllWebContents().size()); |
| 102 EXPECT_EQ(web_contents, browser()->GetAllWebContents()[0]); | 107 EXPECT_EQ(web_contents, browser()->GetAllWebContents()[0]); |
| 103 // TODO(skyostil): Verify viewport dimensions once we can. | 108 // TODO(skyostil): Verify viewport dimensions once we can. |
| 104 web_contents->Close(); | 109 web_contents->Close(); |
| 105 | 110 |
| 106 EXPECT_TRUE(browser()->GetAllWebContents().empty()); | 111 EXPECT_TRUE(browser()->GetAllWebContents().empty()); |
| 107 } | 112 } |
| 108 | 113 |
| 109 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, CreateWithBadURL) { | 114 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, CreateWithBadURL) { |
| 110 GURL bad_url("not_valid"); | 115 GURL bad_url("not_valid"); |
| 111 HeadlessWebContents* web_contents = | 116 HeadlessWebContents* web_contents = |
| 112 browser()->CreateWebContents(bad_url, gfx::Size(800, 600)); | 117 browser()->CreateWebContentsBuilder().SetInitialURL(bad_url).Build(); |
| 113 EXPECT_FALSE(web_contents); | 118 EXPECT_FALSE(web_contents); |
| 114 EXPECT_TRUE(browser()->GetAllWebContents().empty()); | 119 EXPECT_TRUE(browser()->GetAllWebContents().empty()); |
| 115 } | 120 } |
| 116 | 121 |
| 117 class HeadlessBrowserTestWithProxy : public HeadlessBrowserTest { | 122 class HeadlessBrowserTestWithProxy : public HeadlessBrowserTest { |
| 118 public: | 123 public: |
| 119 HeadlessBrowserTestWithProxy() | 124 HeadlessBrowserTestWithProxy() |
| 120 : proxy_server_(net::SpawnedTestServer::TYPE_HTTP, | 125 : proxy_server_(net::SpawnedTestServer::TYPE_HTTP, |
| 121 net::SpawnedTestServer::kLocalhost, | 126 net::SpawnedTestServer::kLocalhost, |
| 122 base::FilePath(FILE_PATH_LITERAL("headless/test/data"))) { | 127 base::FilePath(FILE_PATH_LITERAL("headless/test/data"))) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 141 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTestWithProxy, SetProxyServer) { | 146 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTestWithProxy, SetProxyServer) { |
| 142 HeadlessBrowser::Options::Builder builder; | 147 HeadlessBrowser::Options::Builder builder; |
| 143 builder.SetProxyServer(proxy_server()->host_port_pair()); | 148 builder.SetProxyServer(proxy_server()->host_port_pair()); |
| 144 SetBrowserOptions(builder.Build()); | 149 SetBrowserOptions(builder.Build()); |
| 145 | 150 |
| 146 // Load a page which doesn't actually exist, but for which the our proxy | 151 // Load a page which doesn't actually exist, but for which the our proxy |
| 147 // returns valid content anyway. | 152 // returns valid content anyway. |
| 148 // | 153 // |
| 149 // TODO(altimin): Currently this construction does not serve hello.html | 154 // TODO(altimin): Currently this construction does not serve hello.html |
| 150 // from headless/test/data as expected. We should fix this. | 155 // from headless/test/data as expected. We should fix this. |
| 151 HeadlessWebContents* web_contents = browser()->CreateWebContents( | 156 HeadlessWebContents* web_contents = |
| 152 GURL("http://not-an-actual-domain.tld/hello.html"), gfx::Size(800, 600)); | 157 browser() |
| 158 ->CreateWebContentsBuilder() |
| 159 .SetInitialURL(GURL("http://not-an-actual-domain.tld/hello.html")) |
| 160 .Build(); |
| 153 EXPECT_TRUE(WaitForLoad(web_contents)); | 161 EXPECT_TRUE(WaitForLoad(web_contents)); |
| 154 EXPECT_EQ(static_cast<size_t>(1), browser()->GetAllWebContents().size()); | 162 EXPECT_EQ(static_cast<size_t>(1), browser()->GetAllWebContents().size()); |
| 155 EXPECT_EQ(web_contents, browser()->GetAllWebContents()[0]); | 163 EXPECT_EQ(web_contents, browser()->GetAllWebContents()[0]); |
| 156 web_contents->Close(); | 164 web_contents->Close(); |
| 157 EXPECT_TRUE(browser()->GetAllWebContents().empty()); | 165 EXPECT_TRUE(browser()->GetAllWebContents().empty()); |
| 158 } | 166 } |
| 159 | 167 |
| 160 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, SetHostResolverRules) { | 168 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, SetHostResolverRules) { |
| 161 EXPECT_TRUE(embedded_test_server()->Start()); | 169 EXPECT_TRUE(embedded_test_server()->Start()); |
| 162 HeadlessBrowser::Options::Builder builder; | 170 HeadlessBrowser::Options::Builder builder; |
| 163 builder.SetHostResolverRules( | 171 builder.SetHostResolverRules( |
| 164 base::StringPrintf("MAP not-an-actual-domain.tld 127.0.0.1:%d", | 172 base::StringPrintf("MAP not-an-actual-domain.tld 127.0.0.1:%d", |
| 165 embedded_test_server()->host_port_pair().port())); | 173 embedded_test_server()->host_port_pair().port())); |
| 166 SetBrowserOptions(builder.Build()); | 174 SetBrowserOptions(builder.Build()); |
| 167 | 175 |
| 168 // Load a page which doesn't actually exist, but which is turned into a valid | 176 // Load a page which doesn't actually exist, but which is turned into a valid |
| 169 // address by our host resolver rules. | 177 // address by our host resolver rules. |
| 170 HeadlessWebContents* web_contents = browser()->CreateWebContents( | 178 HeadlessWebContents* web_contents = |
| 171 GURL("http://not-an-actual-domain.tld/hello.html"), gfx::Size(800, 600)); | 179 browser() |
| 180 ->CreateWebContentsBuilder() |
| 181 .SetInitialURL(GURL("http://not-an-actual-domain.tld/hello.html")) |
| 182 .Build(); |
| 172 EXPECT_TRUE(WaitForLoad(web_contents)); | 183 EXPECT_TRUE(WaitForLoad(web_contents)); |
| 173 } | 184 } |
| 174 | 185 |
| 175 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, HttpProtocolHandler) { | 186 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, HttpProtocolHandler) { |
| 176 const std::string kResponseBody = "<p>HTTP response body</p>"; | 187 const std::string kResponseBody = "<p>HTTP response body</p>"; |
| 177 ProtocolHandlerMap protocol_handlers; | 188 ProtocolHandlerMap protocol_handlers; |
| 178 protocol_handlers[url::kHttpScheme] = | 189 protocol_handlers[url::kHttpScheme] = |
| 179 base::WrapUnique(new TestProtocolHandler(kResponseBody)); | 190 base::WrapUnique(new TestProtocolHandler(kResponseBody)); |
| 180 | 191 |
| 181 HeadlessBrowser::Options::Builder builder; | 192 HeadlessBrowser::Options::Builder builder; |
| 182 builder.SetProtocolHandlers(std::move(protocol_handlers)); | 193 builder.SetProtocolHandlers(std::move(protocol_handlers)); |
| 183 SetBrowserOptions(builder.Build()); | 194 SetBrowserOptions(builder.Build()); |
| 184 | 195 |
| 185 // Load a page which doesn't actually exist, but which is fetched by our | 196 // Load a page which doesn't actually exist, but which is fetched by our |
| 186 // custom protocol handler. | 197 // custom protocol handler. |
| 187 HeadlessWebContents* web_contents = browser()->CreateWebContents( | 198 HeadlessWebContents* web_contents = |
| 188 GURL("http://not-an-actual-domain.tld/hello.html"), gfx::Size(800, 600)); | 199 browser() |
| 200 ->CreateWebContentsBuilder() |
| 201 .SetInitialURL(GURL("http://not-an-actual-domain.tld/hello.html")) |
| 202 .Build(); |
| 189 EXPECT_TRUE(WaitForLoad(web_contents)); | 203 EXPECT_TRUE(WaitForLoad(web_contents)); |
| 190 | 204 |
| 191 std::string inner_html; | 205 std::string inner_html; |
| 192 EXPECT_TRUE(EvaluateScript(web_contents, "document.body.innerHTML") | 206 EXPECT_TRUE(EvaluateScript(web_contents, "document.body.innerHTML") |
| 193 ->GetResult() | 207 ->GetResult() |
| 194 ->GetValue() | 208 ->GetValue() |
| 195 ->GetAsString(&inner_html)); | 209 ->GetAsString(&inner_html)); |
| 196 EXPECT_EQ(kResponseBody, inner_html); | 210 EXPECT_EQ(kResponseBody, inner_html); |
| 197 } | 211 } |
| 198 | 212 |
| 199 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, HttpsProtocolHandler) { | 213 IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, HttpsProtocolHandler) { |
| 200 const std::string kResponseBody = "<p>HTTPS response body</p>"; | 214 const std::string kResponseBody = "<p>HTTPS response body</p>"; |
| 201 ProtocolHandlerMap protocol_handlers; | 215 ProtocolHandlerMap protocol_handlers; |
| 202 protocol_handlers[url::kHttpsScheme] = | 216 protocol_handlers[url::kHttpsScheme] = |
| 203 base::WrapUnique(new TestProtocolHandler(kResponseBody)); | 217 base::WrapUnique(new TestProtocolHandler(kResponseBody)); |
| 204 | 218 |
| 205 HeadlessBrowser::Options::Builder builder; | 219 HeadlessBrowser::Options::Builder builder; |
| 206 builder.SetProtocolHandlers(std::move(protocol_handlers)); | 220 builder.SetProtocolHandlers(std::move(protocol_handlers)); |
| 207 SetBrowserOptions(builder.Build()); | 221 SetBrowserOptions(builder.Build()); |
| 208 | 222 |
| 209 // Load a page which doesn't actually exist, but which is fetched by our | 223 // Load a page which doesn't actually exist, but which is fetched by our |
| 210 // custom protocol handler. | 224 // custom protocol handler. |
| 211 HeadlessWebContents* web_contents = browser()->CreateWebContents( | 225 HeadlessWebContents* web_contents = |
| 212 GURL("https://not-an-actual-domain.tld/hello.html"), gfx::Size(800, 600)); | 226 browser() |
| 227 ->CreateWebContentsBuilder() |
| 228 .SetInitialURL(GURL("https://not-an-actual-domain.tld/hello.html")) |
| 229 .Build(); |
| 213 EXPECT_TRUE(WaitForLoad(web_contents)); | 230 EXPECT_TRUE(WaitForLoad(web_contents)); |
| 214 | 231 |
| 215 std::string inner_html; | 232 std::string inner_html; |
| 216 EXPECT_TRUE(EvaluateScript(web_contents, "document.body.innerHTML") | 233 EXPECT_TRUE(EvaluateScript(web_contents, "document.body.innerHTML") |
| 217 ->GetResult() | 234 ->GetResult() |
| 218 ->GetValue() | 235 ->GetValue() |
| 219 ->GetAsString(&inner_html)); | 236 ->GetAsString(&inner_html)); |
| 220 EXPECT_EQ(kResponseBody, inner_html); | 237 EXPECT_EQ(kResponseBody, inner_html); |
| 221 } | 238 } |
| 222 | 239 |
| 240 namespace { |
| 241 const char kMainPageCookie[] = "mood=quizzical"; |
| 242 const char kIsolatedPageCookie[] = "mood=quixotic"; |
| 243 } // namespace |
| 244 |
| 245 // 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 |
| 247 // cookies with the same name in both tabs. The steps are: |
| 248 // |
| 249 // 1. Wait for tab #1 to become ready for DevTools. |
| 250 // 2. Create tab #2 and wait for it to become ready for DevTools. |
| 251 // 3. Navigate tab #1 to the test page and wait for it to finish loading. |
| 252 // 4. Navigate tab #2 to the test page and wait for it to finish loading. |
| 253 // 5. Set a cookie in tab #1. |
| 254 // 6. Set the same cookie in tab #2 to a different value. |
| 255 // 7. Read the cookie in tab #1 and check that it has the first value. |
| 256 // 8. Read the cookie in tab #2 and check that it has the second value. |
| 257 // |
| 258 // If the tabs aren't properly isolated, step 7 will fail. |
| 259 class HeadlessBrowserContextIsolationTest |
| 260 : public HeadlessAsyncDevTooledBrowserTest { |
| 261 public: |
| 262 HeadlessBrowserContextIsolationTest() |
| 263 : web_contents2_(nullptr), |
| 264 devtools_client2_(HeadlessDevToolsClient::Create()) { |
| 265 EXPECT_TRUE(embedded_test_server()->Start()); |
| 266 } |
| 267 |
| 268 // HeadlessWebContentsObserver implementation: |
| 269 void DevToolsTargetReady() override { |
| 270 if (!web_contents2_) { |
| 271 browser_context_ = browser()->CreateBrowserContextBuilder().Build(); |
| 272 web_contents2_ = browser() |
| 273 ->CreateWebContentsBuilder() |
| 274 .SetBrowserContext(browser_context_.get()) |
| 275 .Build(); |
| 276 web_contents2_->AddObserver(this); |
| 277 return; |
| 278 } |
| 279 |
| 280 web_contents2_->GetDevToolsTarget()->AttachClient(devtools_client2_.get()); |
| 281 HeadlessAsyncDevTooledBrowserTest::DevToolsTargetReady(); |
| 282 } |
| 283 |
| 284 void RunDevTooledTest() override { |
| 285 load_observer_.reset(new LoadObserver( |
| 286 devtools_client_.get(), |
| 287 base::Bind(&HeadlessBrowserContextIsolationTest::OnFirstLoadComplete, |
| 288 base::Unretained(this)))); |
| 289 devtools_client_->GetPage()->Navigate( |
| 290 embedded_test_server()->GetURL("/hello.html").spec()); |
| 291 } |
| 292 |
| 293 void OnFirstLoadComplete() { |
| 294 EXPECT_TRUE(load_observer_->navigation_succeeded()); |
| 295 load_observer_.reset(new LoadObserver( |
| 296 devtools_client2_.get(), |
| 297 base::Bind(&HeadlessBrowserContextIsolationTest::OnSecondLoadComplete, |
| 298 base::Unretained(this)))); |
| 299 devtools_client2_->GetPage()->Navigate( |
| 300 embedded_test_server()->GetURL("/hello.html").spec()); |
| 301 } |
| 302 |
| 303 void OnSecondLoadComplete() { |
| 304 EXPECT_TRUE(load_observer_->navigation_succeeded()); |
| 305 load_observer_.reset(); |
| 306 |
| 307 devtools_client_->GetRuntime()->Evaluate( |
| 308 base::StringPrintf("document.cookie = '%s'", kMainPageCookie), |
| 309 base::Bind(&HeadlessBrowserContextIsolationTest::OnFirstSetCookieResult, |
| 310 base::Unretained(this))); |
| 311 } |
| 312 |
| 313 void OnFirstSetCookieResult(std::unique_ptr<runtime::EvaluateResult> result) { |
| 314 std::string cookie; |
| 315 EXPECT_TRUE(result->GetResult()->GetValue()->GetAsString(&cookie)); |
| 316 EXPECT_EQ(kMainPageCookie, cookie); |
| 317 |
| 318 devtools_client2_->GetRuntime()->Evaluate( |
| 319 base::StringPrintf("document.cookie = '%s'", kIsolatedPageCookie), |
| 320 base::Bind( |
| 321 &HeadlessBrowserContextIsolationTest::OnSecondSetCookieResult, |
| 322 base::Unretained(this))); |
| 323 } |
| 324 |
| 325 void OnSecondSetCookieResult( |
| 326 std::unique_ptr<runtime::EvaluateResult> result) { |
| 327 std::string cookie; |
| 328 EXPECT_TRUE(result->GetResult()->GetValue()->GetAsString(&cookie)); |
| 329 EXPECT_EQ(kIsolatedPageCookie, cookie); |
| 330 |
| 331 devtools_client_->GetRuntime()->Evaluate( |
| 332 "document.cookie", |
| 333 base::Bind(&HeadlessBrowserContextIsolationTest::OnFirstGetCookieResult, |
| 334 base::Unretained(this))); |
| 335 } |
| 336 |
| 337 void OnFirstGetCookieResult(std::unique_ptr<runtime::EvaluateResult> result) { |
| 338 std::string cookie; |
| 339 EXPECT_TRUE(result->GetResult()->GetValue()->GetAsString(&cookie)); |
| 340 EXPECT_EQ(kMainPageCookie, cookie); |
| 341 |
| 342 devtools_client2_->GetRuntime()->Evaluate( |
| 343 "document.cookie", |
| 344 base::Bind( |
| 345 &HeadlessBrowserContextIsolationTest::OnSecondGetCookieResult, |
| 346 base::Unretained(this))); |
| 347 } |
| 348 |
| 349 void OnSecondGetCookieResult( |
| 350 std::unique_ptr<runtime::EvaluateResult> result) { |
| 351 std::string cookie; |
| 352 EXPECT_TRUE(result->GetResult()->GetValue()->GetAsString(&cookie)); |
| 353 EXPECT_EQ(kIsolatedPageCookie, cookie); |
| 354 FinishTest(); |
| 355 } |
| 356 |
| 357 void FinishTest() { |
| 358 web_contents2_->RemoveObserver(this); |
| 359 web_contents2_->Close(); |
| 360 browser_context_.reset(); |
| 361 FinishAsynchronousTest(); |
| 362 } |
| 363 |
| 364 private: |
| 365 std::unique_ptr<HeadlessBrowserContext> browser_context_; |
| 366 HeadlessWebContents* web_contents2_; |
| 367 std::unique_ptr<HeadlessDevToolsClient> devtools_client2_; |
| 368 std::unique_ptr<LoadObserver> load_observer_; |
| 369 }; |
| 370 |
| 371 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessBrowserContextIsolationTest); |
| 372 |
| 223 } // namespace headless | 373 } // namespace headless |
| OLD | NEW |