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" |
10 #include "content/public/test/browser_test.h" | 11 #include "content/public/test/browser_test.h" |
11 #include "headless/public/devtools/domains/page.h" | 12 #include "headless/public/devtools/domains/page.h" |
12 #include "headless/public/devtools/domains/runtime.h" | 13 #include "headless/public/devtools/domains/runtime.h" |
13 #include "headless/public/devtools/domains/security.h" | 14 #include "headless/public/devtools/domains/security.h" |
14 #include "headless/public/headless_browser.h" | 15 #include "headless/public/headless_browser.h" |
15 #include "headless/public/headless_devtools_client.h" | 16 #include "headless/public/headless_devtools_client.h" |
16 #include "headless/public/headless_tab_socket.h" | 17 #include "headless/public/headless_tab_socket.h" |
17 #include "headless/public/headless_web_contents.h" | 18 #include "headless/public/headless_web_contents.h" |
18 #include "headless/test/headless_browser_test.h" | 19 #include "headless/test/headless_browser_test.h" |
19 #include "printing/features/features.h" | 20 #include "printing/features/features.h" |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 | 288 |
288 devtools_client_->GetSecurity()->GetExperimental()->Disable( | 289 devtools_client_->GetSecurity()->GetExperimental()->Disable( |
289 security::DisableParams::Builder().Build()); | 290 security::DisableParams::Builder().Build()); |
290 devtools_client_->GetSecurity()->GetExperimental()->RemoveObserver(this); | 291 devtools_client_->GetSecurity()->GetExperimental()->RemoveObserver(this); |
291 FinishAsynchronousTest(); | 292 FinishAsynchronousTest(); |
292 } | 293 } |
293 }; | 294 }; |
294 | 295 |
295 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessWebContentsSecurityTest); | 296 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessWebContentsSecurityTest); |
296 | 297 |
297 class HeadlessTabSocketTest : public HeadlessAsyncDevTooledBrowserTest, | 298 class GetHeadlessTabSocketButNoTabSocket |
298 public HeadlessTabSocket::Listener { | 299 : public HeadlessAsyncDevTooledBrowserTest { |
299 public: | 300 public: |
300 void SetUp() override { | 301 void SetUp() override { |
301 options()->mojo_service_names.insert("headless::TabSocket"); | 302 options()->mojo_service_names.insert("headless::TabSocket"); |
| 303 HeadlessAsyncDevTooledBrowserTest::SetUp(); |
| 304 } |
| 305 |
| 306 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"); |
302 HeadlessAsyncDevTooledBrowserTest::SetUp(); | 323 HeadlessAsyncDevTooledBrowserTest::SetUp(); |
303 } | 324 } |
304 | 325 |
305 void RunDevTooledTest() override { | 326 void RunDevTooledTest() override { |
306 devtools_client_->GetRuntime()->Evaluate( | 327 devtools_client_->GetRuntime()->Evaluate( |
307 R"(window.TabSocket.onmessage = | 328 R"(window.TabSocket.onmessage = |
308 function(event) { | 329 function(message) { |
309 window.TabSocket.send( | 330 window.TabSocket.send('Embedder sent us: ' + message); |
310 'Embedder sent us: ' + event.detail.message); | |
311 }; | 331 }; |
312 )"); | 332 )"); |
313 | 333 |
314 HeadlessTabSocket* headless_tab_socket = | 334 HeadlessTabSocket* headless_tab_socket = |
315 web_contents_->GetHeadlessTabSocket(); | 335 web_contents_->GetHeadlessTabSocket(); |
316 DCHECK(headless_tab_socket); | 336 DCHECK(headless_tab_socket); |
317 | 337 |
318 headless_tab_socket->SendMessageToTab("Hello"); | 338 headless_tab_socket->SendMessageToTab("Hello"); |
319 headless_tab_socket->SetListener(this); | 339 headless_tab_socket->SetListener(this); |
320 } | 340 } |
321 | 341 |
322 void OnMessageFromTab(const std::string& message) override { | 342 void OnMessageFromTab(const std::string& message) override { |
323 EXPECT_EQ("Embedder sent us: Hello", message); | 343 EXPECT_EQ("Embedder sent us: Hello", message); |
324 FinishAsynchronousTest(); | 344 FinishAsynchronousTest(); |
325 } | 345 } |
326 | 346 |
327 bool GetCreateTabSocket() override { return true; } | 347 HeadlessWebContents::Builder::TabSocketType GetTabSocketType() override { |
328 }; | 348 return HeadlessWebContents::Builder::TabSocketType::MAIN_WORLD; |
329 | 349 } |
330 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessTabSocketTest); | 350 }; |
| 351 |
| 352 HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessMainWorldTabSocketTest); |
| 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); |
331 | 545 |
332 } // namespace headless | 546 } // namespace headless |
OLD | NEW |