Chromium Code Reviews| 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 : isolated_web_contents_(nullptr), | |
| 264 isolated_devtools_client_(HeadlessDevToolsClient::Create()) { | |
|
alex clarke (OOO till 29th)
2016/06/09 09:15:08
Can we call these web_contents2_ & devtools_client
Sami
2016/06/09 11:14:39
Agreed, that matches the description above too.
| |
| 265 EXPECT_TRUE(embedded_test_server()->Start()); | |
| 266 } | |
| 267 | |
| 268 // HeadlessWebContentsObserver implementation: | |
| 269 void DevToolsTargetReady() override { | |
| 270 if (!isolated_web_contents_) { | |
| 271 browser_context_ = browser()->CreateBrowserContextBuilder().Build(); | |
| 272 isolated_web_contents_ = browser() | |
| 273 ->CreateWebContentsBuilder() | |
| 274 .SetBrowserContext(browser_context_.get()) | |
| 275 .Build(); | |
| 276 isolated_web_contents_->AddObserver(this); | |
| 277 return; | |
| 278 } | |
| 279 | |
| 280 isolated_web_contents_->GetDevToolsTarget()->AttachClient( | |
| 281 isolated_devtools_client_.get()); | |
| 282 HeadlessAsyncDevTooledBrowserTest::DevToolsTargetReady(); | |
| 283 } | |
| 284 | |
| 285 void RunDevTooledTest() override { | |
| 286 load_observer_.reset(new LoadObserver( | |
| 287 devtools_client_.get(), | |
| 288 base::Bind(&HeadlessBrowserContextIsolationTest::OnFirstLoadComplete, | |
| 289 base::Unretained(this)))); | |
| 290 devtools_client_->GetPage()->Navigate( | |
| 291 embedded_test_server()->GetURL("/hello.html").spec()); | |
| 292 } | |
| 293 | |
| 294 void OnFirstLoadComplete() { | |
| 295 EXPECT_TRUE(load_observer_->navigation_succeeded()); | |
| 296 load_observer_.reset(new LoadObserver( | |
| 297 isolated_devtools_client_.get(), | |
| 298 base::Bind(&HeadlessBrowserContextIsolationTest::OnSecondLoadComplete, | |
| 299 base::Unretained(this)))); | |
| 300 isolated_devtools_client_->GetPage()->Navigate( | |
| 301 embedded_test_server()->GetURL("/hello.html").spec()); | |
| 302 } | |
| 303 | |
| 304 void OnSecondLoadComplete() { | |
| 305 EXPECT_TRUE(load_observer_->navigation_succeeded()); | |
| 306 load_observer_.reset(); | |
| 307 | |
| 308 devtools_client_->GetRuntime()->Evaluate( | |
| 309 base::StringPrintf("document.cookie = '%s'", kMainPageCookie), | |
| 310 base::Bind(&HeadlessBrowserContextIsolationTest::OnFirstSetCookieResult, | |
| 311 base::Unretained(this))); | |
| 312 } | |
| 313 | |
| 314 void OnFirstSetCookieResult(std::unique_ptr<runtime::EvaluateResult> result) { | |
| 315 std::string cookie; | |
| 316 EXPECT_TRUE(result->GetResult()->GetValue()->GetAsString(&cookie)); | |
| 317 EXPECT_EQ(kMainPageCookie, cookie); | |
| 318 | |
| 319 isolated_devtools_client_->GetRuntime()->Evaluate( | |
| 320 base::StringPrintf("document.cookie = '%s'", kIsolatedPageCookie), | |
| 321 base::Bind( | |
| 322 &HeadlessBrowserContextIsolationTest::OnSecondSetCookieResult, | |
| 323 base::Unretained(this))); | |
| 324 } | |
| 325 | |
| 326 void OnSecondSetCookieResult( | |
| 327 std::unique_ptr<runtime::EvaluateResult> result) { | |
| 328 std::string cookie; | |
| 329 EXPECT_TRUE(result->GetResult()->GetValue()->GetAsString(&cookie)); | |
| 330 EXPECT_EQ(kIsolatedPageCookie, cookie); | |
| 331 | |
| 332 devtools_client_->GetRuntime()->Evaluate( | |
| 333 "document.cookie", | |
| 334 base::Bind(&HeadlessBrowserContextIsolationTest::OnFirstGetCookieResult, | |
| 335 base::Unretained(this))); | |
| 336 } | |
| 337 | |
| 338 void OnFirstGetCookieResult(std::unique_ptr<runtime::EvaluateResult> result) { | |
| 339 std::string cookie; | |
| 340 EXPECT_TRUE(result->GetResult()->GetValue()->GetAsString(&cookie)); | |
| 341 EXPECT_EQ(kMainPageCookie, cookie); | |
| 342 | |
| 343 isolated_devtools_client_->GetRuntime()->Evaluate( | |
| 344 "document.cookie", | |
| 345 base::Bind( | |
| 346 &HeadlessBrowserContextIsolationTest::OnSecondGetCookieResult, | |
| 347 base::Unretained(this))); | |
| 348 } | |
| 349 | |
| 350 void OnSecondGetCookieResult( | |
| 351 std::unique_ptr<runtime::EvaluateResult> result) { | |
| 352 std::string cookie; | |
| 353 EXPECT_TRUE(result->GetResult()->GetValue()->GetAsString(&cookie)); | |
| 354 EXPECT_EQ(kIsolatedPageCookie, cookie); | |
| 355 FinishTest(); | |
| 356 } | |
| 357 | |
| 358 void FinishTest() { | |
| 359 isolated_web_contents_->RemoveObserver(this); | |
| 360 isolated_web_contents_->Close(); | |
| 361 browser_context_.reset(); | |
| 362 FinishAsynchronousTest(); | |
| 363 } | |
| 364 | |
| 365 private: | |
| 366 std::unique_ptr<HeadlessBrowserContext> browser_context_; | |
| 367 HeadlessWebContents* isolated_web_contents_; | |
| 368 std::unique_ptr<HeadlessDevToolsClient> isolated_devtools_client_; | |
| 369 std::unique_ptr<LoadObserver> load_observer_; | |
| 370 }; | |
| 371 | |
| 372 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessBrowserContextIsolationTest); | |
| 373 | |
| 223 } // namespace headless | 374 } // namespace headless |
| OLD | NEW |