Commit da1ee4ba authored by Sean Gilhuly's avatar Sean Gilhuly Committed by Commit Bot

Connect the Viz DevTools server

Create a server socket on the browser process and pass it to the viz
process, where the Viz DevTools server is created.

The server is enabled with the flag --enable-viz-devtools=<port>. If no
port is specified, the default 9229 is used.

Once running, you can connect to the server with the following url:
chrome-devtools://devtools/bundled/inspector.html?ws=localhost:9229/0

The viz devtools server should be connected on Android and when it runs
in-process, but these haven't been tested yet.

Bug: 816802
Change-Id: Ica6b98253b49e0658a680a71fa3fe7ad083610a9
Reviewed-on: https://chromium-review.googlesource.com/c/1309135
Commit-Queue: Sean Gilhuly <sgilhuly@chromium.org>
Reviewed-by: default avatarSadrul Chowdhury <sadrul@chromium.org>
Reviewed-by: default avatarkylechar <kylechar@chromium.org>
Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607754}
parent 86293fce
......@@ -2607,6 +2607,13 @@ ChromeContentBrowserClient::GetSystemSharedURLLoaderFactory() {
->GetSharedURLLoaderFactory();
}
network::mojom::NetworkContext*
ChromeContentBrowserClient::GetSystemNetworkContext() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(g_browser_process->system_network_context_manager());
return g_browser_process->system_network_context_manager()->GetContext();
}
std::string ChromeContentBrowserClient::GetGeolocationApiKey() {
return google_apis::GetAPIKey();
}
......
......@@ -265,6 +265,7 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient {
content::ResourceContext* context) override;
scoped_refptr<network::SharedURLLoaderFactory>
GetSystemSharedURLLoaderFactory() override;
network::mojom::NetworkContext* GetSystemNetworkContext() override;
std::string GetGeolocationApiKey() override;
#if defined(OS_ANDROID)
......
......@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//components/ui_devtools/devtools.gni")
import("//components/viz/viz.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
......@@ -64,6 +65,10 @@ viz_component("host") {
if (is_mac) {
deps += [ "//ui/accelerated_widget_mac" ]
}
if (use_viz_devtools) {
defines += [ "USE_VIZ_DEVTOOLS" ]
}
}
viz_source_set("unit_tests") {
......
......@@ -7,7 +7,6 @@
#include <utility>
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
......@@ -139,6 +138,15 @@ void VizMainWrapper::CreateGpuService(
}
}
#if defined(USE_VIZ_DEVTOOLS)
void VizMainWrapper::CreateVizDevTools(mojom::VizDevToolsParamsPtr params) {
if (viz_main_ptr_)
viz_main_ptr_->CreateVizDevTools(std::move(params));
else
viz_main_associated_ptr_->CreateVizDevTools(std::move(params));
}
#endif
void VizMainWrapper::CreateFrameSinkManager(
mojom::FrameSinkManagerParamsPtr params) {
if (viz_main_ptr_)
......@@ -256,6 +264,12 @@ void GpuHostImpl::ConnectFrameSinkManager(
viz_main_ptr_->CreateFrameSinkManager(std::move(params));
}
#if defined(USE_VIZ_DEVTOOLS)
void GpuHostImpl::ConnectVizDevTools(mojom::VizDevToolsParamsPtr params) {
viz_main_ptr_->CreateVizDevTools(std::move(params));
}
#endif
void GpuHostImpl::EstablishGpuChannel(int client_id,
uint64_t client_tracing_id,
bool is_gpu_host,
......
......@@ -58,6 +58,9 @@ class VIZ_HOST_EXPORT VizMainWrapper {
mojo::ScopedSharedBufferHandle activity_flags,
gfx::FontRenderParams::SubpixelRendering subpixel_rendering);
void CreateFrameSinkManager(mojom::FrameSinkManagerParamsPtr params);
#if defined(USE_VIZ_DEVTOOLS)
void CreateVizDevTools(mojom::VizDevToolsParamsPtr params);
#endif
private:
mojom::VizMainPtr viz_main_ptr_;
......@@ -165,6 +168,11 @@ class VIZ_HOST_EXPORT GpuHostImpl : public mojom::GpuHost {
void ConnectFrameSinkManager(mojom::FrameSinkManagerRequest request,
mojom::FrameSinkManagerClientPtrInfo client);
#if defined(USE_VIZ_DEVTOOLS)
// Connects to Viz DevTools running in the Viz service.
void ConnectVizDevTools(mojom::VizDevToolsParamsPtr params);
#endif
// Tells the GPU service to create a new channel for communication with a
// client. Once the GPU service responds asynchronously with the channel
// handle and GPUInfo, we call the callback.
......
......@@ -99,6 +99,19 @@ void VizCompositorThreadRunner::CreateFrameSinkManager(
base::Unretained(gpu_channel_manager)));
}
#if defined(USE_VIZ_DEVTOOLS)
void VizCompositorThreadRunner::CreateVizDevTools(
mojom::VizDevToolsParamsPtr params) {
// It is safe to use Unretained(this) because |this| owns the |task_runner_|,
// and will outlive it.
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&VizCompositorThreadRunner::CreateVizDevToolsOnCompositorThread,
base::Unretained(this), std::move(params)));
}
#endif
void VizCompositorThreadRunner::CleanupForShutdown(
base::OnceClosure cleanup_finished_callback) {
task_runner_->PostTaskAndReply(
......@@ -155,21 +168,28 @@ void VizCompositorThreadRunner::CreateFrameSinkManagerOnCompositorThread(
std::move(params->frame_sink_manager_client)));
#if defined(USE_VIZ_DEVTOOLS)
if (params->devtools_server_socket) {
InitVizDevToolsOnCompositorThread(
network::mojom::TCPServerSocketPtr(
std::move(params->devtools_server_socket)),
params->server_port);
}
if (pending_viz_dev_tools_params_)
InitVizDevToolsOnCompositorThread(std::move(pending_viz_dev_tools_params_));
#endif
}
#if defined(USE_VIZ_DEVTOOLS)
void VizCompositorThreadRunner::CreateVizDevToolsOnCompositorThread(
mojom::VizDevToolsParamsPtr params) {
if (!frame_sink_manager_) {
DCHECK(!pending_viz_dev_tools_params_);
pending_viz_dev_tools_params_ = std::move(params);
return;
}
InitVizDevToolsOnCompositorThread(std::move(params));
}
void VizCompositorThreadRunner::InitVizDevToolsOnCompositorThread(
network::mojom::TCPServerSocketPtr server_socket,
int port) {
mojom::VizDevToolsParamsPtr params) {
DCHECK(frame_sink_manager_);
devtools_server_ = ui_devtools::UiDevToolsServer::CreateForViz(
std::move(server_socket), port);
network::mojom::TCPServerSocketPtr(std::move(params->server_socket)),
params->server_port);
auto dom_agent =
std::make_unique<ui_devtools::DOMAgentViz>(frame_sink_manager_.get());
auto css_agent = std::make_unique<ui_devtools::CSSAgent>(dom_agent.get());
......
......@@ -67,6 +67,10 @@ class VizCompositorThreadRunner {
scoped_refptr<gpu::CommandBufferTaskExecutor> task_executor,
GpuServiceImpl* gpu_service);
#if defined(USE_VIZ_DEVTOOLS)
void CreateVizDevTools(mojom::VizDevToolsParamsPtr params);
#endif
// Performs cleanup on VizCompositorThread needed before forcing thread to
// shut down. Ensures VizCompositorThread teardown during the destructor
// doesn't block on PostTasks back to the GPU thread. After cleanup has
......@@ -86,9 +90,8 @@ class VizCompositorThreadRunner {
gpu::ImageFactory* image_factory,
gpu::GpuChannelManager* gpu_channel_manager);
#if defined(USE_VIZ_DEVTOOLS)
void InitVizDevToolsOnCompositorThread(
network::mojom::TCPServerSocketPtr server_socket,
int port);
void CreateVizDevToolsOnCompositorThread(mojom::VizDevToolsParamsPtr params);
void InitVizDevToolsOnCompositorThread(mojom::VizDevToolsParamsPtr params);
#endif
void CleanupForShutdownOnCompositorThread();
void TearDownOnCompositorThread();
......@@ -99,6 +102,10 @@ class VizCompositorThreadRunner {
std::unique_ptr<FrameSinkManagerImpl> frame_sink_manager_;
#if defined(USE_VIZ_DEVTOOLS)
std::unique_ptr<ui_devtools::UiDevToolsServer> devtools_server_;
// If the FrameSinkManager is not ready yet, then we stash the pending
// VizDevToolsParams.
mojom::VizDevToolsParamsPtr pending_viz_dev_tools_params_;
#endif
// End variables to be accessed only on |task_runner_|.
......
......@@ -271,6 +271,12 @@ void VizMainImpl::CreateFrameSinkManagerInternal(
std::move(params), task_executor_, gpu_service_.get());
}
void VizMainImpl::CreateVizDevTools(mojom::VizDevToolsParamsPtr params) {
#if defined(USE_VIZ_DEVTOOLS)
viz_compositor_thread_runner_->CreateVizDevTools(std::move(params));
#endif
}
void VizMainImpl::ExitProcess() {
DCHECK(gpu_thread_task_runner_->BelongsToCurrentThread());
......
......@@ -98,6 +98,7 @@ class VizMainImpl : public gpu::GpuSandboxHelper, public mojom::VizMain {
mojo::ScopedSharedBufferHandle activity_flags,
gfx::FontRenderParams::SubpixelRendering subpixel_rendering) override;
void CreateFrameSinkManager(mojom::FrameSinkManagerParamsPtr params) override;
void CreateVizDevTools(mojom::VizDevToolsParamsPtr params) override;
GpuServiceImpl* gpu_service() { return gpu_service_.get(); }
const GpuServiceImpl* gpu_service() const { return gpu_service_.get(); }
......
......@@ -8,6 +8,7 @@ import("//build/config/jumbo.gni")
import("//build/config/linux/pangocairo/pangocairo.gni")
import("//build/config/ui.gni")
import("//chromeos/assistant/assistant.gni")
import("//components/ui_devtools/devtools.gni")
import("//gpu/vulkan/features.gni")
import("//media/media_options.gni")
import("//net/features.gni")
......@@ -61,6 +62,7 @@ jumbo_source_set("browser") {
"//components/services/leveldb:lib",
"//components/tracing",
"//components/tracing:startup_tracing",
"//components/ui_devtools",
"//components/url_formatter",
"//components/variations",
"//components/viz/client",
......@@ -2513,6 +2515,14 @@ jumbo_source_set("browser") {
"net/reporting_service_proxy.h",
]
}
if (use_viz_devtools) {
sources += [
"gpu/viz_devtools_connector.cc",
"gpu/viz_devtools_connector.h",
]
defines += [ "USE_VIZ_DEVTOOLS" ]
}
}
buildflag_header("accessibility_buildflags") {
......
......@@ -7,6 +7,9 @@ specific_include_rules = {
"gpu_process_host\.cc": [
"+ui/ozone/public",
],
"viz_devtools_connector\.cc": [
"+components/ui_devtools",
],
"in_process_gpu_thread_browsertests\.cc": [
# Let's move in_process_gpu_thread* to
# content/browser/gpu to avoid this rule.
......
......@@ -849,6 +849,16 @@ bool GpuProcessHost::Init() {
this, std::make_unique<viz::VizMainWrapper>(std::move(viz_main_ptr)),
std::move(params));
#if defined(USE_VIZ_DEVTOOLS)
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableVizDevTools)) {
// Start creating a socket for the Viz DevTools server. If it is created
// before the FrameSinkManager, the socket will be stashed.
devtools_connector_ = std::make_unique<VizDevToolsConnector>();
devtools_connector_->ConnectVizDevTools();
}
#endif
#if defined(OS_MACOSX)
ca_transaction_gpu_coordinator_ = CATransactionGPUCoordinator::Create(this);
#endif
......
......@@ -39,6 +39,10 @@
#include "services/viz/privileged/interfaces/viz_main.mojom.h"
#include "url/gurl.h"
#if defined(USE_VIZ_DEVTOOLS)
#include "content/browser/gpu/viz_devtools_connector.h"
#endif
namespace base {
class Thread;
}
......@@ -234,6 +238,10 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
std::unique_ptr<viz::GpuHostImpl> gpu_host_;
#if defined(USE_VIZ_DEVTOOLS)
std::unique_ptr<VizDevToolsConnector> devtools_connector_;
#endif
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<GpuProcessHost> weak_ptr_factory_;
......
// Copyright 2018 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 "content/browser/gpu/viz_devtools_connector.h"
#include "base/task/post_task.h"
#include "components/ui_devtools/devtools_server.h"
#include "components/viz/common/switches.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
namespace content {
namespace {
void OnSocketCreated(base::OnceCallback<void(int, int)> callback,
int result,
const base::Optional<net::IPEndPoint>& local_addr) {
int port = 0;
if (local_addr)
port = local_addr->port();
base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
base::BindOnce(std::move(callback), result, port));
}
void CreateSocketOnUiThread(
network::mojom::TCPServerSocketRequest server_socket_request,
int port,
base::OnceCallback<void(int, int)> callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
ui_devtools::UiDevToolsServer::CreateTCPServerSocket(
std::move(server_socket_request),
GetContentClient()->browser()->GetSystemNetworkContext(), port,
ui_devtools::UiDevToolsServer::kVizDevtoolsServerTag,
base::BindOnce(&OnSocketCreated, std::move(callback)));
}
} // namespace
VizDevToolsConnector::VizDevToolsConnector() : weak_ptr_factory_(this) {}
VizDevToolsConnector::~VizDevToolsConnector() {}
void VizDevToolsConnector::ConnectVizDevTools() {
constexpr int kVizDevToolsDefaultPort = 9229;
network::mojom::TCPServerSocketPtr server_socket;
network::mojom::TCPServerSocketRequest server_socket_request =
mojo::MakeRequest(&server_socket);
int port = ui_devtools::UiDevToolsServer::GetUiDevToolsPort(
switches::kEnableVizDevTools, kVizDevToolsDefaultPort);
// Jump to the UI thread to get the network context, create the socket, then
// jump back to the IO thread to complete the callback.
base::PostTaskWithTraits(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&CreateSocketOnUiThread, std::move(server_socket_request), port,
base::BindOnce(&VizDevToolsConnector::OnVizDevToolsSocketCreated,
weak_ptr_factory_.GetWeakPtr(),
server_socket.PassInterface())));
}
void VizDevToolsConnector::OnVizDevToolsSocketCreated(
network::mojom::TCPServerSocketPtrInfo socket,
int result,
int port) {
viz::mojom::VizDevToolsParamsPtr params =
viz::mojom::VizDevToolsParams::New();
params->server_socket = std::move(socket);
params->server_port = port;
auto* gpu_process_host = GpuProcessHost::Get();
if (gpu_process_host)
gpu_process_host->gpu_host()->ConnectVizDevTools(std::move(params));
}
} // namespace content
// Copyright 2018 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.
#ifndef CONTENT_BROWSER_GPU_VIZ_DEVTOOLS_CONNECTOR_H_
#define CONTENT_BROWSER_GPU_VIZ_DEVTOOLS_CONNECTOR_H_
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "services/network/public/mojom/tcp_socket.mojom.h"
namespace content {
// Creates a TCP server socket, and uses it to connect the viz devtools server
// on the gpu process.
class CONTENT_EXPORT VizDevToolsConnector {
public:
VizDevToolsConnector();
~VizDevToolsConnector();
void ConnectVizDevTools();
private:
void OnVizDevToolsSocketCreated(network::mojom::TCPServerSocketPtrInfo socket,
int result,
int port);
base::WeakPtrFactory<VizDevToolsConnector> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(VizDevToolsConnector);
};
} // namespace content
#endif // CONTENT_BROWSER_GPU_VIZ_DEVTOOLS_CONNECTOR_H_
......@@ -423,6 +423,11 @@ ContentBrowserClient::GetSystemSharedURLLoaderFactory() {
return nullptr;
}
network::mojom::NetworkContext*
ContentBrowserClient::GetSystemNetworkContext() {
return nullptr;
}
std::string ContentBrowserClient::GetGeolocationApiKey() {
return std::string();
}
......
......@@ -657,6 +657,11 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual scoped_refptr<network::SharedURLLoaderFactory>
GetSystemSharedURLLoaderFactory();
// Returns the system network context. This shouldn't be used to create a
// URLLoaderFactory, instead use GetSystemSharedURLLoaderFactory(). Must be
// called on the UI thread. The default implementation returns nullptr.
virtual network::mojom::NetworkContext* GetSystemNetworkContext();
// Allows an embedder to provide a Google API Key to use for network
// geolocation queries.
// * May be called from any thread.
......
......@@ -2,7 +2,6 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//components/ui_devtools/devtools.gni")
import("//mojo/public/tools/bindings/mojom.gni")
mojom("interfaces") {
......@@ -18,11 +17,6 @@ mojom("interfaces") {
"//services/viz/public/interfaces",
"//ui/gfx/mojo",
]
enabled_features = []
if (use_viz_devtools) {
enabled_features += [ "use_viz_devtools" ]
}
}
source_set("unit_tests") {
......
......@@ -28,16 +28,13 @@ struct FrameSinkManagerParams {
// Viz to host interface.
FrameSinkManagerClient frame_sink_manager_client;
};
// Optional socket for viz devtools server, which is used to observe the
// FrameSinkManager in the viz compositor. This will be null unless the flag
// --enable-viz-devtools is used. If present, the server will be created on
// the viz process using this socket.
[EnableIf=use_viz_devtools]
network.mojom.TCPServerSocket? devtools_server_socket;
struct VizDevToolsParams {
// Socket for viz devtools server.
network.mojom.TCPServerSocket server_socket;
// Port the devtools server socket is bound to.
[EnableIf=use_viz_devtools]
uint16 server_port;
};
......@@ -50,4 +47,9 @@ interface VizMain {
discardable_memory.mojom.DiscardableSharedMemoryManager discardable_memory_manager,
handle<shared_buffer>? activity_flags,
gfx.mojom.SubpixelRendering subpixel_rendering);
// The viz devtools server is for use by developers to observe the
// FrameSinkManager in the viz compositor. This is only called if the flag
// --enable-viz-devtools is used.
CreateVizDevTools(VizDevToolsParams params);
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment