| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/base64.h" |
| #include "content/public/test/browser_test.h" |
| #include "headless/public/devtools/domains/page.h" |
| #include "headless/public/devtools/domains/runtime.h" |
| #include "headless/public/devtools/domains/security.h" |
| #include "headless/public/headless_browser.h" |
| #include "headless/public/headless_devtools_client.h" |
| #include "headless/public/headless_tab_socket.h" |
| #include "headless/public/headless_web_contents.h" |
| #include "headless/test/headless_browser_test.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/skia/include/core/SkBitmap.h" |
| #include "third_party/skia/include/core/SkColor.h" |
| #include "ui/gfx/codec/png_codec.h" |
| #include "ui/gfx/geometry/size.h" |
| #include "url/gurl.h" |
| |
| using testing::UnorderedElementsAre; |
| |
| namespace headless { |
| |
| class HeadlessWebContentsTest : public HeadlessBrowserTest {}; |
| |
| IN_PROC_BROWSER_TEST_F(HeadlessWebContentsTest, Navigation) { |
| EXPECT_TRUE(embedded_test_server()->Start()); |
| |
| HeadlessBrowserContext* browser_context = |
| browser()->CreateBrowserContextBuilder().Build(); |
| |
| HeadlessWebContents* web_contents = |
| browser_context->CreateWebContentsBuilder() |
| .SetInitialURL(embedded_test_server()->GetURL("/hello.html")) |
| .Build(); |
| EXPECT_TRUE(WaitForLoad(web_contents)); |
| |
| EXPECT_THAT(browser_context->GetAllWebContents(), |
| UnorderedElementsAre(web_contents)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(HeadlessWebContentsTest, WindowOpen) { |
| EXPECT_TRUE(embedded_test_server()->Start()); |
| |
| HeadlessBrowserContext* browser_context = |
| browser()->CreateBrowserContextBuilder().Build(); |
| |
| HeadlessWebContents* web_contents = |
| browser_context->CreateWebContentsBuilder() |
| .SetInitialURL(embedded_test_server()->GetURL("/window_open.html")) |
| .Build(); |
| EXPECT_TRUE(WaitForLoad(web_contents)); |
| |
| EXPECT_EQ(static_cast<size_t>(2), |
| browser_context->GetAllWebContents().size()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(HeadlessWebContentsTest, Focus) { |
| EXPECT_TRUE(embedded_test_server()->Start()); |
| |
| HeadlessBrowserContext* browser_context = |
| browser()->CreateBrowserContextBuilder().Build(); |
| |
| HeadlessWebContents* web_contents = |
| browser_context->CreateWebContentsBuilder() |
| .SetInitialURL(embedded_test_server()->GetURL("/hello.html")) |
| .Build(); |
| EXPECT_TRUE(WaitForLoad(web_contents)); |
| |
| bool result; |
| EXPECT_TRUE(EvaluateScript(web_contents, "document.hasFocus()") |
| ->GetResult() |
| ->GetValue() |
| ->GetAsBoolean(&result)); |
| EXPECT_TRUE(result); |
| |
| HeadlessWebContents* web_contents2 = |
| browser_context->CreateWebContentsBuilder() |
| .SetInitialURL(embedded_test_server()->GetURL("/hello.html")) |
| .Build(); |
| EXPECT_TRUE(WaitForLoad(web_contents2)); |
| |
| // Focus of different WebContents is independent. |
| EXPECT_TRUE(EvaluateScript(web_contents, "document.hasFocus()") |
| ->GetResult() |
| ->GetValue() |
| ->GetAsBoolean(&result)); |
| EXPECT_TRUE(result); |
| EXPECT_TRUE(EvaluateScript(web_contents2, "document.hasFocus()") |
| ->GetResult() |
| ->GetValue() |
| ->GetAsBoolean(&result)); |
| EXPECT_TRUE(result); |
| } |
| |
| namespace { |
| bool DecodePNG(std::string base64_data, SkBitmap* bitmap) { |
| std::string png_data; |
| if (!base::Base64Decode(base64_data, &png_data)) |
| return false; |
| return gfx::PNGCodec::Decode( |
| reinterpret_cast<unsigned const char*>(png_data.data()), png_data.size(), |
| bitmap); |
| } |
| } // namespace |
| |
| // Parameter specifies whether --disable-gpu should be used. |
| class HeadlessWebContentsScreenshotTest |
| : public HeadlessAsyncDevTooledBrowserTest, |
| public ::testing::WithParamInterface<bool> { |
| public: |
| void SetUp() override { |
| EnablePixelOutput(); |
| if (GetParam()) |
| UseSoftwareCompositing(); |
| HeadlessAsyncDevTooledBrowserTest::SetUp(); |
| } |
| |
| void RunDevTooledTest() override { |
| std::unique_ptr<runtime::EvaluateParams> params = |
| runtime::EvaluateParams::Builder() |
| .SetExpression("document.body.style.background = '#0000ff'") |
| .Build(); |
| devtools_client_->GetRuntime()->Evaluate( |
| std::move(params), |
| base::Bind(&HeadlessWebContentsScreenshotTest::OnPageSetupCompleted, |
| base::Unretained(this))); |
| } |
| |
| void OnPageSetupCompleted(std::unique_ptr<runtime::EvaluateResult> result) { |
| devtools_client_->GetPage()->GetExperimental()->CaptureScreenshot( |
| page::CaptureScreenshotParams::Builder().SetFromSurface(true).Build(), |
| base::Bind(&HeadlessWebContentsScreenshotTest::OnScreenshotCaptured, |
| base::Unretained(this))); |
| } |
| |
| void OnScreenshotCaptured( |
| std::unique_ptr<page::CaptureScreenshotResult> result) { |
| std::string base64 = result->GetData(); |
| EXPECT_LT(0U, base64.length()); |
| SkBitmap result_bitmap; |
| EXPECT_TRUE(DecodePNG(base64, &result_bitmap)); |
| |
| EXPECT_EQ(800, result_bitmap.width()); |
| EXPECT_EQ(600, result_bitmap.height()); |
| SkColor actual_color = result_bitmap.getColor(400, 300); |
| SkColor expected_color = SkColorSetRGB(0x00, 0x00, 0xff); |
| EXPECT_EQ(expected_color, actual_color); |
| FinishAsynchronousTest(); |
| } |
| }; |
| |
| HEADLESS_ASYNC_DEVTOOLED_TEST_P(HeadlessWebContentsScreenshotTest); |
| |
| // Instantiate test case for both software and gpu compositing modes. |
| INSTANTIATE_TEST_CASE_P(HeadlessWebContentsScreenshotTests, |
| HeadlessWebContentsScreenshotTest, |
| ::testing::Bool()); |
| |
| class HeadlessWebContentsSecurityTest |
| : public HeadlessAsyncDevTooledBrowserTest, |
| public security::ExperimentalObserver { |
| public: |
| void RunDevTooledTest() override { |
| devtools_client_->GetSecurity()->GetExperimental()->AddObserver(this); |
| devtools_client_->GetSecurity()->GetExperimental()->Enable( |
| security::EnableParams::Builder().Build()); |
| } |
| |
| void OnSecurityStateChanged( |
| const security::SecurityStateChangedParams& params) override { |
| EXPECT_EQ(security::SecurityState::NEUTRAL, params.GetSecurityState()); |
| |
| devtools_client_->GetSecurity()->GetExperimental()->Disable( |
| security::DisableParams::Builder().Build()); |
| devtools_client_->GetSecurity()->GetExperimental()->RemoveObserver(this); |
| FinishAsynchronousTest(); |
| } |
| }; |
| |
| HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessWebContentsSecurityTest); |
| |
| class HeadlessTabSocketTest : public HeadlessAsyncDevTooledBrowserTest, |
| public HeadlessTabSocket::Listener { |
| public: |
| void RunDevTooledTest() override { |
| devtools_client_->GetRuntime()->Evaluate( |
| R"(window.TabSocket.onmessage = |
| function(event) { |
| window.TabSocket.send( |
| 'Embedder sent us: ' + event.detail.message); |
| }; |
| )"); |
| |
| HeadlessTabSocket* headless_tab_socket = |
| web_contents_->GetHeadlessTabSocket(); |
| DCHECK(headless_tab_socket); |
| |
| headless_tab_socket->SendMessageToTab("Hello"); |
| headless_tab_socket->SetListener(this); |
| } |
| |
| void OnMessageFromTab(const std::string& message) override { |
| EXPECT_EQ("Embedder sent us: Hello", message); |
| FinishAsynchronousTest(); |
| } |
| |
| bool GetCreateTabSocket() override { return true; } |
| }; |
| |
| HEADLESS_ASYNC_DEVTOOLED_TEST_F(HeadlessTabSocketTest); |
| |
| } // namespace headless |