| 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 #include <string> | 6 #include <string> |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/json/json_writer.h" | |
| 11 #include "content/public/test/browser_test.h" | 10 #include "content/public/test/browser_test.h" |
| 12 #include "headless/public/devtools/domains/page.h" | 11 #include "headless/public/devtools/domains/page.h" |
| 13 #include "headless/public/devtools/domains/runtime.h" | 12 #include "headless/public/devtools/domains/runtime.h" |
| 14 #include "headless/public/devtools/domains/security.h" | 13 #include "headless/public/devtools/domains/security.h" |
| 15 #include "headless/public/headless_browser.h" | 14 #include "headless/public/headless_browser.h" |
| 16 #include "headless/public/headless_devtools_client.h" | 15 #include "headless/public/headless_devtools_client.h" |
| 17 #include "headless/public/headless_tab_socket.h" | 16 #include "headless/public/headless_tab_socket.h" |
| 18 #include "headless/public/headless_web_contents.h" | 17 #include "headless/public/headless_web_contents.h" |
| 19 #include "headless/test/headless_browser_test.h" | 18 #include "headless/test/headless_browser_test.h" |
| 20 #include "printing/features/features.h" | 19 #include "printing/features/features.h" |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 | 287 |
| 289 devtools_client_->GetSecurity()->GetExperimental()->Disable( | 288 devtools_client_->GetSecurity()->GetExperimental()->Disable( |
| 290 security::DisableParams::Builder().Build()); | 289 security::DisableParams::Builder().Build()); |
| 291 devtools_client_->GetSecurity()->GetExperimental()->RemoveObserver(this); | 290 devtools_client_->GetSecurity()->GetExperimental()->RemoveObserver(this); |
| 292 FinishAsynchronousTest(); | 291 FinishAsynchronousTest(); |
| 293 } | 292 } |
| 294 }; | 293 }; |
| 295 | 294 |
| 296 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessWebContentsSecurityTest); | 295 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessWebContentsSecurityTest); |
| 297 | 296 |
| 298 class GetHeadlessTabSocketButNoTabSocket | 297 class HeadlessTabSocketTest : public HeadlessAsyncDevTooledBrowserTest, |
| 299 : public HeadlessAsyncDevTooledBrowserTest { | 298 public HeadlessTabSocket::Listener { |
| 300 public: | 299 public: |
| 301 void SetUp() override { | 300 void SetUp() override { |
| 302 options()->mojo_service_names.insert("headless::TabSocket"); | 301 options()->mojo_service_names.insert("headless::TabSocket"); |
| 303 HeadlessAsyncDevTooledBrowserTest::SetUp(); | 302 HeadlessAsyncDevTooledBrowserTest::SetUp(); |
| 304 } | 303 } |
| 305 | 304 |
| 306 void RunDevTooledTest() override { | 305 void RunDevTooledTest() override { |
| 307 ASSERT_THAT(web_contents_->GetHeadlessTabSocket(), testing::IsNull()); | |
| 308 FinishAsynchronousTest(); | |
| 309 } | |
| 310 | |
| 311 HeadlessWebContents::Builder::TabSocketType GetTabSocketType() override { | |
| 312 return HeadlessWebContents::Builder::TabSocketType::NONE; | |
| 313 } | |
| 314 }; | |
| 315 | |
| 316 HEADLESS_ASYNC_DEVTOOLED_TEST_F(GetHeadlessTabSocketButNoTabSocket); | |
| 317 | |
| 318 class HeadlessMainWorldTabSocketTest : public HeadlessAsyncDevTooledBrowserTest, | |
| 319 public HeadlessTabSocket::Listener { | |
| 320 public: | |
| 321 void SetUp() override { | |
| 322 options()->mojo_service_names.insert("headless::TabSocket"); | |
| 323 HeadlessAsyncDevTooledBrowserTest::SetUp(); | |
| 324 } | |
| 325 | |
| 326 void RunDevTooledTest() override { | |
| 327 devtools_client_->GetRuntime()->Evaluate( | 306 devtools_client_->GetRuntime()->Evaluate( |
| 328 R"(window.TabSocket.onmessage = | 307 R"(window.TabSocket.onmessage = |
| 329 function(message) { | 308 function(event) { |
| 330 window.TabSocket.send('Embedder sent us: ' + message); | 309 window.TabSocket.send( |
| 310 'Embedder sent us: ' + event.detail.message); |
| 331 }; | 311 }; |
| 332 )"); | 312 )"); |
| 333 | 313 |
| 334 HeadlessTabSocket* headless_tab_socket = | 314 HeadlessTabSocket* headless_tab_socket = |
| 335 web_contents_->GetHeadlessTabSocket(); | 315 web_contents_->GetHeadlessTabSocket(); |
| 336 DCHECK(headless_tab_socket); | 316 DCHECK(headless_tab_socket); |
| 337 | 317 |
| 338 headless_tab_socket->SendMessageToTab("Hello"); | 318 headless_tab_socket->SendMessageToTab("Hello"); |
| 339 headless_tab_socket->SetListener(this); | 319 headless_tab_socket->SetListener(this); |
| 340 } | 320 } |
| 341 | 321 |
| 342 void OnMessageFromTab(const std::string& message) override { | 322 void OnMessageFromTab(const std::string& message) override { |
| 343 EXPECT_EQ("Embedder sent us: Hello", message); | 323 EXPECT_EQ("Embedder sent us: Hello", message); |
| 344 FinishAsynchronousTest(); | 324 FinishAsynchronousTest(); |
| 345 } | 325 } |
| 346 | 326 |
| 347 HeadlessWebContents::Builder::TabSocketType GetTabSocketType() override { | 327 bool GetCreateTabSocket() override { return true; } |
| 348 return HeadlessWebContents::Builder::TabSocketType::MAIN_WORLD; | |
| 349 } | |
| 350 }; | 328 }; |
| 351 | 329 |
| 352 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessMainWorldTabSocketTest); | 330 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessTabSocketTest); |
| 353 | |
| 354 class HeadlessMainWorldTabSocketNotThereTest | |
| 355 : public HeadlessAsyncDevTooledBrowserTest, | |
| 356 public HeadlessTabSocket::Listener { | |
| 357 public: | |
| 358 void SetUp() override { | |
| 359 options()->mojo_service_names.insert("headless::TabSocket"); | |
| 360 HeadlessAsyncDevTooledBrowserTest::SetUp(); | |
| 361 } | |
| 362 | |
| 363 void RunDevTooledTest() override { | |
| 364 // We expect this to fail because the TabSocket is being injected into | |
| 365 // isolated worlds. | |
| 366 devtools_client_->GetRuntime()->Evaluate( | |
| 367 "window.TabSocket.send('This should not work!');", | |
| 368 base::Bind(&HeadlessMainWorldTabSocketNotThereTest::EvaluateResult, | |
| 369 base::Unretained(this))); | |
| 370 | |
| 371 HeadlessTabSocket* headless_tab_socket = | |
| 372 web_contents_->GetHeadlessTabSocket(); | |
| 373 DCHECK(headless_tab_socket); | |
| 374 | |
| 375 headless_tab_socket->SetListener(this); | |
| 376 } | |
| 377 | |
| 378 void EvaluateResult(std::unique_ptr<runtime::EvaluateResult> result) { | |
| 379 EXPECT_TRUE(result->HasExceptionDetails()); | |
| 380 FinishAsynchronousTest(); | |
| 381 } | |
| 382 | |
| 383 void OnMessageFromTab(const std::string&) override { | |
| 384 FAIL() << "Should not receive a message from the tab!"; | |
| 385 FinishAsynchronousTest(); | |
| 386 } | |
| 387 | |
| 388 HeadlessWebContents::Builder::TabSocketType GetTabSocketType() override { | |
| 389 return HeadlessWebContents::Builder::TabSocketType::ISOLATED_WORLD; | |
| 390 } | |
| 391 }; | |
| 392 | |
| 393 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessMainWorldTabSocketNotThereTest); | |
| 394 | |
| 395 class HeadlessIsolatedWorldTabSocketTest | |
| 396 : public HeadlessAsyncDevTooledBrowserTest, | |
| 397 public HeadlessTabSocket::Listener, | |
| 398 public runtime::Observer { | |
| 399 public: | |
| 400 void SetUp() override { | |
| 401 options()->mojo_service_names.insert("headless::TabSocket"); | |
| 402 HeadlessAsyncDevTooledBrowserTest::SetUp(); | |
| 403 } | |
| 404 | |
| 405 void RunDevTooledTest() override { | |
| 406 devtools_client_->GetRuntime()->AddObserver(this); | |
| 407 devtools_client_->GetRuntime()->Enable(); | |
| 408 | |
| 409 devtools_client_->GetPage()->GetExperimental()->GetResourceTree( | |
| 410 page::GetResourceTreeParams::Builder().Build(), | |
| 411 base::Bind(&HeadlessIsolatedWorldTabSocketTest::OnResourceTree, | |
| 412 base::Unretained(this))); | |
| 413 | |
| 414 HeadlessTabSocket* headless_tab_socket = | |
| 415 web_contents_->GetHeadlessTabSocket(); | |
| 416 DCHECK(headless_tab_socket); | |
| 417 headless_tab_socket->SendMessageToTab("Hello!!!"); | |
| 418 headless_tab_socket->SetListener(this); | |
| 419 } | |
| 420 | |
| 421 void OnResourceTree(std::unique_ptr<page::GetResourceTreeResult> result) { | |
| 422 main_frame_id_ = result->GetFrameTree()->GetFrame()->GetId(); | |
| 423 devtools_client_->GetPage()->GetExperimental()->CreateIsolatedWorld( | |
| 424 page::CreateIsolatedWorldParams::Builder() | |
| 425 .SetFrameId(main_frame_id_) | |
| 426 .Build()); | |
| 427 } | |
| 428 | |
| 429 void OnExecutionContextCreated( | |
| 430 const runtime::ExecutionContextCreatedParams& params) override { | |
| 431 const base::DictionaryValue* dictionary; | |
| 432 std::string frame_id; | |
| 433 bool is_main_world; | |
| 434 // If the isolated world was created then eval some script in it. | |
| 435 if (params.GetContext()->HasAuxData() && | |
| 436 params.GetContext()->GetAuxData()->GetAsDictionary(&dictionary) && | |
| 437 dictionary->GetString("frameId", &frame_id) && | |
| 438 frame_id == main_frame_id_ && | |
| 439 dictionary->GetBoolean("isDefault", &is_main_world) && !is_main_world) { | |
| 440 devtools_client_->GetRuntime()->Evaluate( | |
| 441 runtime::EvaluateParams::Builder() | |
| 442 .SetExpression( | |
| 443 R"(window.TabSocket.onmessage = | |
| 444 function(message) { | |
| 445 TabSocket.send('Embedder sent us: ' + message); | |
| 446 }; | |
| 447 )") | |
| 448 .SetContextId(params.GetContext()->GetId()) | |
| 449 .Build()); | |
| 450 } | |
| 451 } | |
| 452 | |
| 453 void OnMessageFromTab(const std::string& message) override { | |
| 454 EXPECT_EQ("Embedder sent us: Hello!!!", message); | |
| 455 FinishAsynchronousTest(); | |
| 456 } | |
| 457 | |
| 458 HeadlessWebContents::Builder::TabSocketType GetTabSocketType() override { | |
| 459 return HeadlessWebContents::Builder::TabSocketType::ISOLATED_WORLD; | |
| 460 } | |
| 461 | |
| 462 private: | |
| 463 std::string main_frame_id_; | |
| 464 }; | |
| 465 | |
| 466 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessIsolatedWorldTabSocketTest); | |
| 467 | |
| 468 class HeadlessIsolatedWorldTabSocketNotThereTest | |
| 469 : public HeadlessAsyncDevTooledBrowserTest, | |
| 470 public HeadlessTabSocket::Listener, | |
| 471 public runtime::Observer { | |
| 472 public: | |
| 473 void SetUp() override { | |
| 474 options()->mojo_service_names.insert("headless::TabSocket"); | |
| 475 HeadlessAsyncDevTooledBrowserTest::SetUp(); | |
| 476 } | |
| 477 | |
| 478 void RunDevTooledTest() override { | |
| 479 devtools_client_->GetRuntime()->AddObserver(this); | |
| 480 devtools_client_->GetRuntime()->Enable(); | |
| 481 | |
| 482 devtools_client_->GetPage()->GetExperimental()->GetResourceTree( | |
| 483 page::GetResourceTreeParams::Builder().Build(), | |
| 484 base::Bind(&HeadlessIsolatedWorldTabSocketNotThereTest::OnResourceTree, | |
| 485 base::Unretained(this))); | |
| 486 | |
| 487 HeadlessTabSocket* headless_tab_socket = | |
| 488 web_contents_->GetHeadlessTabSocket(); | |
| 489 DCHECK(headless_tab_socket); | |
| 490 headless_tab_socket->SendMessageToTab("Hello!!!"); | |
| 491 headless_tab_socket->SetListener(this); | |
| 492 } | |
| 493 | |
| 494 void OnResourceTree(std::unique_ptr<page::GetResourceTreeResult> result) { | |
| 495 main_frame_id_ = result->GetFrameTree()->GetFrame()->GetId(); | |
| 496 devtools_client_->GetPage()->GetExperimental()->CreateIsolatedWorld( | |
| 497 page::CreateIsolatedWorldParams::Builder() | |
| 498 .SetFrameId(main_frame_id_) | |
| 499 .Build()); | |
| 500 } | |
| 501 | |
| 502 void OnExecutionContextCreated( | |
| 503 const runtime::ExecutionContextCreatedParams& params) override { | |
| 504 const base::DictionaryValue* dictionary; | |
| 505 std::string frame_id; | |
| 506 bool is_main_world; | |
| 507 // If the isolated world was created then eval some script in it. | |
| 508 if (params.GetContext()->HasAuxData() && | |
| 509 params.GetContext()->GetAuxData()->GetAsDictionary(&dictionary) && | |
| 510 dictionary->GetString("frameId", &frame_id) && | |
| 511 frame_id == main_frame_id_ && | |
| 512 dictionary->GetBoolean("isDefault", &is_main_world) && !is_main_world) { | |
| 513 // We expect this to fail because the TabSocket is being injected into the | |
| 514 // main world. | |
| 515 devtools_client_->GetRuntime()->Evaluate( | |
| 516 runtime::EvaluateParams::Builder() | |
| 517 .SetExpression("window.TabSocket.send('This should not work!');") | |
| 518 .SetContextId(params.GetContext()->GetId()) | |
| 519 .Build(), | |
| 520 base::Bind( | |
| 521 &HeadlessIsolatedWorldTabSocketNotThereTest::EvaluateResult, | |
| 522 base::Unretained(this))); | |
| 523 } | |
| 524 } | |
| 525 | |
| 526 void EvaluateResult(std::unique_ptr<runtime::EvaluateResult> result) { | |
| 527 EXPECT_TRUE(result->HasExceptionDetails()); | |
| 528 FinishAsynchronousTest(); | |
| 529 } | |
| 530 | |
| 531 void OnMessageFromTab(const std::string&) override { | |
| 532 FAIL() << "Should not receive a message from the tab!"; | |
| 533 FinishAsynchronousTest(); | |
| 534 } | |
| 535 | |
| 536 HeadlessWebContents::Builder::TabSocketType GetTabSocketType() override { | |
| 537 return HeadlessWebContents::Builder::TabSocketType::MAIN_WORLD; | |
| 538 } | |
| 539 | |
| 540 private: | |
| 541 std::string main_frame_id_; | |
| 542 }; | |
| 543 | |
| 544 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessIsolatedWorldTabSocketNotThereTest); | |
| 545 | 331 |
| 546 } // namespace headless | 332 } // namespace headless |
| OLD | NEW |