blob: 956719c4f817f075bca2977707c4828761f92a85 [file]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/devtools/protocol/visual_debugger_handler.h"
#include <stddef.h>
#include <memory>
#include <utility>
#include <vector>
#include "base/check_op.h"
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_reader.h"
#include "base/system/sys_info.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/protocol/devtools_protocol_test_support.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/inspector_protocol/crdtp/dispatch.h"
namespace content {
namespace protocol {
namespace {
GpuProcessHost* GetGpuProcessHost(bool force_create) {
return GpuProcessHost::Get(GPU_PROCESS_KIND_SANDBOXED, force_create);
}
base::DictValue MakeFilterParams() {
base::DictValue selector;
selector.Set("anno", "");
base::DictValue filter;
filter.Set("selector", std::move(selector));
filter.Set("active", true);
base::ListValue filters;
filters.Append(std::move(filter));
base::DictValue filter_params;
filter_params.Set("filters", std::move(filters));
base::DictValue params;
params.Set("filter", std::move(filter_params));
return params;
}
} // namespace
class VisualDebuggerHandlerTest : public DevToolsProtocolTest {
public:
void SetUpOnMainThread() override {
DevToolsProtocolTest::SetUpOnMainThread();
set_agent_host_can_close();
NavigateToURLBlockUntilNavigationsComplete(
shell(), GURL("data:text/html,<body></body>"), 1);
Attach();
}
protected:
VisualDebuggerHandler* handler() {
auto* agent_host = static_cast<DevToolsAgentHostImpl*>(agent_host_.get());
std::vector<VisualDebuggerHandler*> handlers =
agent_host->HandlersByName<VisualDebuggerHandler>(
VisualDebugger::Metainfo::domainName);
CHECK_EQ(1u, handlers.size());
return handlers[0];
}
bool enabled() { return handler()->enabled_; }
void UseMockGpuProcessHostGetter() {
handler()->gpu_process_host_getter_for_testing_ =
gpu_process_host_getter_.Get();
}
void ExpectServerError() {
ASSERT_TRUE(error());
EXPECT_THAT(
error()->FindInt("code"),
testing::Optional(static_cast<int>(crdtp::DispatchCode::SERVER_ERROR)));
}
base::MockRepeatingCallback<GpuProcessHost*(bool)> gpu_process_host_getter_;
};
IN_PROC_BROWSER_TEST_F(VisualDebuggerHandlerTest, VisualDebuggerTest) {
ASSERT_TRUE(SendCommandSync("VisualDebugger.startStream"));
WaitForNotification("VisualDebugger.frameResponse", true);
ASSERT_TRUE(
SendCommandSync("VisualDebugger.filterStream", MakeFilterParams()));
ASSERT_TRUE(SendCommandSync("VisualDebugger.stopStream"));
EXPECT_FALSE(enabled());
}
IN_PROC_BROWSER_TEST_F(VisualDebuggerHandlerTest,
StartStreamFailsWhenGpuProcessIsUnavailable) {
UseMockGpuProcessHostGetter();
EXPECT_CALL(gpu_process_host_getter_, Run(true))
.WillOnce(testing::Return(nullptr));
ASSERT_FALSE(SendCommandSync("VisualDebugger.startStream"));
ExpectServerError();
EXPECT_FALSE(enabled());
testing::Mock::VerifyAndClearExpectations(&gpu_process_host_getter_);
EXPECT_CALL(gpu_process_host_getter_, Run(testing::_)).Times(0);
ASSERT_TRUE(SendCommandSync("VisualDebugger.stopStream"));
Detach();
}
IN_PROC_BROWSER_TEST_F(VisualDebuggerHandlerTest,
StartStreamCanRetryAfterGpuProcessFailure) {
UseMockGpuProcessHostGetter();
testing::InSequence sequence;
EXPECT_CALL(gpu_process_host_getter_, Run(true))
.WillOnce(testing::Return(nullptr));
EXPECT_CALL(gpu_process_host_getter_, Run(true)).WillOnce(GetGpuProcessHost);
EXPECT_CALL(gpu_process_host_getter_, Run(false))
.WillOnce(testing::Return(nullptr));
ASSERT_FALSE(SendCommandSync("VisualDebugger.startStream"));
ExpectServerError();
EXPECT_FALSE(enabled());
ASSERT_TRUE(SendCommandSync("VisualDebugger.startStream"));
EXPECT_TRUE(enabled());
ASSERT_TRUE(SendCommandSync("VisualDebugger.stopStream"));
EXPECT_FALSE(enabled());
}
IN_PROC_BROWSER_TEST_F(VisualDebuggerHandlerTest,
FailedRestartClearsEnabledState) {
UseMockGpuProcessHostGetter();
EXPECT_CALL(gpu_process_host_getter_, Run(true))
.WillOnce(GetGpuProcessHost)
.WillOnce(testing::Return(nullptr));
ASSERT_TRUE(SendCommandSync("VisualDebugger.startStream"));
EXPECT_TRUE(enabled());
ASSERT_FALSE(SendCommandSync("VisualDebugger.startStream"));
ExpectServerError();
EXPECT_FALSE(enabled());
testing::Mock::VerifyAndClearExpectations(&gpu_process_host_getter_);
EXPECT_CALL(gpu_process_host_getter_, Run(testing::_)).Times(0);
ASSERT_TRUE(SendCommandSync("VisualDebugger.stopStream"));
Detach();
}
IN_PROC_BROWSER_TEST_F(VisualDebuggerHandlerTest,
FilterStreamFailsWhenGpuProcessIsUnavailable) {
UseMockGpuProcessHostGetter();
EXPECT_CALL(gpu_process_host_getter_, Run(true))
.WillOnce(testing::Return(nullptr));
ASSERT_FALSE(
SendCommandSync("VisualDebugger.filterStream", MakeFilterParams()));
ExpectServerError();
EXPECT_FALSE(enabled());
testing::Mock::VerifyAndClearExpectations(&gpu_process_host_getter_);
EXPECT_CALL(gpu_process_host_getter_, Run(testing::_)).Times(0);
Detach();
}
IN_PROC_BROWSER_TEST_F(VisualDebuggerHandlerTest,
StopStreamSucceedsWhenGpuProcessIsUnavailable) {
UseMockGpuProcessHostGetter();
testing::InSequence sequence;
EXPECT_CALL(gpu_process_host_getter_, Run(true)).WillOnce(GetGpuProcessHost);
EXPECT_CALL(gpu_process_host_getter_, Run(false))
.WillOnce(testing::Return(nullptr));
ASSERT_TRUE(SendCommandSync("VisualDebugger.startStream"));
EXPECT_TRUE(enabled());
ASSERT_TRUE(SendCommandSync("VisualDebugger.stopStream"));
EXPECT_FALSE(enabled());
testing::Mock::VerifyAndClearExpectations(&gpu_process_host_getter_);
EXPECT_CALL(gpu_process_host_getter_, Run(testing::_)).Times(0);
ASSERT_TRUE(SendCommandSync("VisualDebugger.stopStream"));
Detach();
}
IN_PROC_BROWSER_TEST_F(VisualDebuggerHandlerTest,
DetachSucceedsWhenGpuProcessIsUnavailable) {
UseMockGpuProcessHostGetter();
testing::InSequence sequence;
EXPECT_CALL(gpu_process_host_getter_, Run(true)).WillOnce(GetGpuProcessHost);
EXPECT_CALL(gpu_process_host_getter_, Run(false))
.WillOnce(testing::Return(nullptr));
ASSERT_TRUE(SendCommandSync("VisualDebugger.startStream"));
EXPECT_TRUE(enabled());
Detach();
}
} // namespace protocol
} // namespace content