Commit 8bbf58d6 authored by Dmitry Gozman's avatar Dmitry Gozman Committed by Commit Bot

Disconnected DevToolsPipeHandler closes the browser

When the browser is controlled remotely over the pipe,
and the pipe is disconnected, there is no way left to
control the browser. Every pipe client tries to kill
the browser at that point. Instead, we can just shutdown
normally, leaving no core dumps.

Change-Id: Ib03a727930b00f48a6869c12c66c86072d45b5b9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2536354
Commit-Queue: Dmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarAndrey Kosyakov <caseq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#827457}
parent ce8dfd02
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/devtools/protocol/target_handler.h" #include "chrome/browser/devtools/protocol/target_handler.h"
#include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/policy/developer_tools_policy_handler.h" #include "chrome/browser/policy/developer_tools_policy_handler.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager.h"
...@@ -29,6 +30,7 @@ ...@@ -29,6 +30,7 @@
#include "components/guest_view/browser/guest_view_base.h" #include "components/guest_view/browser/guest_view_base.h"
#include "components/keep_alive_registry/keep_alive_types.h" #include "components/keep_alive_registry/keep_alive_types.h"
#include "components/keep_alive_registry/scoped_keep_alive.h" #include "components/keep_alive_registry/scoped_keep_alive.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_agent_host_client_channel.h" #include "content/public/browser/devtools_agent_host_client_channel.h"
#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_frame_host.h"
...@@ -336,8 +338,15 @@ void ChromeDevToolsManagerDelegate::ResetAndroidDeviceManagerForTesting() { ...@@ -336,8 +338,15 @@ void ChromeDevToolsManagerDelegate::ResetAndroidDeviceManagerForTesting() {
device_discovery_.reset(); device_discovery_.reset();
} }
void ChromeDevToolsManagerDelegate::BrowserCloseRequested() { // static
// Do not keep the application running anymore, we got an explicit request void ChromeDevToolsManagerDelegate::CloseBrowserSoon() {
// to close. content::GetUIThreadTaskRunner({})->PostTask(
keep_alive_.reset(); FROM_HERE, base::BindOnce([]() {
if (GetInstance()) {
// Do not keep the application running anymore, we got an explicit
// request to close.
GetInstance()->keep_alive_.reset();
}
chrome::ExitIgnoreUnloadHandlers();
}));
} }
...@@ -54,7 +54,8 @@ class ChromeDevToolsManagerDelegate : public content::DevToolsManagerDelegate { ...@@ -54,7 +54,8 @@ class ChromeDevToolsManagerDelegate : public content::DevToolsManagerDelegate {
std::vector<content::BrowserContext*> GetBrowserContexts() override; std::vector<content::BrowserContext*> GetBrowserContexts() override;
content::BrowserContext* GetDefaultBrowserContext() override; content::BrowserContext* GetDefaultBrowserContext() override;
void BrowserCloseRequested(); // Closes browser soon, not in the current task.
static void CloseBrowserSoon();
private: private:
friend class DevToolsManagerDelegateTest; friend class DevToolsManagerDelegateTest;
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include "chrome/app/chrome_command_ids.h" #include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/devtools/chrome_devtools_manager_delegate.h" #include "chrome/browser/devtools/chrome_devtools_manager_delegate.h"
#include "chrome/browser/devtools/devtools_dock_tile.h" #include "chrome/browser/devtools/devtools_dock_tile.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/browser_window.h"
...@@ -113,12 +112,7 @@ Response BrowserHandler::GetWindowBounds( ...@@ -113,12 +112,7 @@ Response BrowserHandler::GetWindowBounds(
} }
Response BrowserHandler::Close() { Response BrowserHandler::Close() {
content::GetUIThreadTaskRunner({})->PostTask( ChromeDevToolsManagerDelegate::CloseBrowserSoon();
FROM_HERE, base::BindOnce([]() {
if (ChromeDevToolsManagerDelegate::GetInstance())
ChromeDevToolsManagerDelegate::GetInstance()->BrowserCloseRequested();
chrome::ExitIgnoreUnloadHandlers();
}));
return Response::Success(); return Response::Success();
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/path_service.h" #include "base/path_service.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/devtools/chrome_devtools_manager_delegate.h"
#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
...@@ -91,7 +92,8 @@ RemoteDebuggingServer::RemoteDebuggingServer() { ...@@ -91,7 +92,8 @@ RemoteDebuggingServer::RemoteDebuggingServer() {
const base::CommandLine& command_line = const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess(); *base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kRemoteDebuggingPipe)) { if (command_line.HasSwitch(switches::kRemoteDebuggingPipe)) {
content::DevToolsAgentHost::StartRemoteDebuggingPipeHandler(); content::DevToolsAgentHost::StartRemoteDebuggingPipeHandler(
base::BindOnce(&ChromeDevToolsManagerDelegate::CloseBrowserSoon));
return; return;
} }
......
...@@ -29,9 +29,11 @@ void DevToolsAgentHost::StartRemoteDebuggingServer( ...@@ -29,9 +29,11 @@ void DevToolsAgentHost::StartRemoteDebuggingServer(
} }
// static // static
void DevToolsAgentHost::StartRemoteDebuggingPipeHandler() { void DevToolsAgentHost::StartRemoteDebuggingPipeHandler(
base::OnceClosure on_disconnect) {
DevToolsManager* manager = DevToolsManager::GetInstance(); DevToolsManager* manager = DevToolsManager::GetInstance();
manager->SetPipeHandler(std::make_unique<DevToolsPipeHandler>()); manager->SetPipeHandler(
std::make_unique<DevToolsPipeHandler>(std::move(on_disconnect)));
} }
// static // static
......
...@@ -142,8 +142,12 @@ class PipeReaderBase : public PipeIOBase { ...@@ -142,8 +142,12 @@ class PipeReaderBase : public PipeIOBase {
bool had_error = size_read <= 0; bool had_error = size_read <= 0;
#endif #endif
if (had_error) { if (had_error) {
if (!shutting_down_.IsSet()) if (!shutting_down_.IsSet()) {
LOG(ERROR) << "Connection terminated while reading from pipe"; LOG(ERROR) << "Connection terminated while reading from pipe";
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&DevToolsPipeHandler::OnDisconnect,
devtools_handler_));
}
return 0; return 0;
} }
bytes_read += size_read; bytes_read += size_read;
...@@ -341,8 +345,10 @@ class PipeReaderCBOR : public PipeReaderBase { ...@@ -341,8 +345,10 @@ class PipeReaderCBOR : public PipeReaderBase {
// DevToolsPipeHandler --------------------------------------------------- // DevToolsPipeHandler ---------------------------------------------------
DevToolsPipeHandler::DevToolsPipeHandler() DevToolsPipeHandler::DevToolsPipeHandler(base::OnceClosure on_disconnect)
: read_fd_(kReadFD), write_fd_(kWriteFD) { : on_disconnect_(std::move(on_disconnect)),
read_fd_(kReadFD),
write_fd_(kWriteFD) {
browser_target_ = DevToolsAgentHost::CreateForBrowser( browser_target_ = DevToolsAgentHost::CreateForBrowser(
nullptr, DevToolsAgentHost::CreateServerSocketCallback()); nullptr, DevToolsAgentHost::CreateServerSocketCallback());
browser_target_->AttachClient(this); browser_target_->AttachClient(this);
...@@ -393,7 +399,10 @@ void DevToolsPipeHandler::HandleMessage(std::vector<uint8_t> message) { ...@@ -393,7 +399,10 @@ void DevToolsPipeHandler::HandleMessage(std::vector<uint8_t> message) {
browser_target_->DispatchProtocolMessage(this, message); browser_target_->DispatchProtocolMessage(this, message);
} }
void DevToolsPipeHandler::DetachFromTarget() {} void DevToolsPipeHandler::OnDisconnect() {
if (on_disconnect_)
std::move(on_disconnect_).Run();
}
void DevToolsPipeHandler::DispatchProtocolMessage( void DevToolsPipeHandler::DispatchProtocolMessage(
DevToolsAgentHost* agent_host, DevToolsAgentHost* agent_host,
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_PIPE_HANDLER_H_ #ifndef CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_PIPE_HANDLER_H_
#define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_PIPE_HANDLER_H_ #define CONTENT_BROWSER_DEVTOOLS_DEVTOOLS_PIPE_HANDLER_H_
#include "base/callback.h"
#include "base/containers/span.h" #include "base/containers/span.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
...@@ -17,11 +18,11 @@ class PipeWriterBase; ...@@ -17,11 +18,11 @@ class PipeWriterBase;
class DevToolsPipeHandler : public DevToolsAgentHostClient { class DevToolsPipeHandler : public DevToolsAgentHostClient {
public: public:
DevToolsPipeHandler(); explicit DevToolsPipeHandler(base::OnceClosure on_disconnect);
~DevToolsPipeHandler() override; ~DevToolsPipeHandler() override;
void HandleMessage(std::vector<uint8_t> message); void HandleMessage(std::vector<uint8_t> message);
void DetachFromTarget(); void OnDisconnect();
// DevToolsAgentHostClient overrides // DevToolsAgentHostClient overrides
void DispatchProtocolMessage(DevToolsAgentHost* agent_host, void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
...@@ -40,6 +41,7 @@ class DevToolsPipeHandler : public DevToolsAgentHostClient { ...@@ -40,6 +41,7 @@ class DevToolsPipeHandler : public DevToolsAgentHostClient {
}; };
ProtocolMode mode_; ProtocolMode mode_;
base::OnceClosure on_disconnect_;
std::unique_ptr<PipeReaderBase> pipe_reader_; std::unique_ptr<PipeReaderBase> pipe_reader_;
std::unique_ptr<PipeWriterBase> pipe_writer_; std::unique_ptr<PipeWriterBase> pipe_writer_;
......
...@@ -113,7 +113,7 @@ class CONTENT_EXPORT DevToolsAgentHost ...@@ -113,7 +113,7 @@ class CONTENT_EXPORT DevToolsAgentHost
// Starts remote debugging for browser target for the given fd=3 // Starts remote debugging for browser target for the given fd=3
// for reading and fd=4 for writing remote debugging messages. // for reading and fd=4 for writing remote debugging messages.
static void StartRemoteDebuggingPipeHandler(); static void StartRemoteDebuggingPipeHandler(base::OnceClosure on_disconnect);
static void StopRemoteDebuggingPipeHandler(); static void StopRemoteDebuggingPipeHandler();
// Observer is notified about changes in DevToolsAgentHosts. // Observer is notified about changes in DevToolsAgentHosts.
......
...@@ -165,7 +165,7 @@ void ShellDevToolsManagerDelegate::StartHttpHandler( ...@@ -165,7 +165,7 @@ void ShellDevToolsManagerDelegate::StartHttpHandler(
const base::CommandLine& command_line = const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess(); *base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kRemoteDebuggingPipe)) if (command_line.HasSwitch(switches::kRemoteDebuggingPipe))
DevToolsAgentHost::StartRemoteDebuggingPipeHandler(); DevToolsAgentHost::StartRemoteDebuggingPipeHandler(base::OnceClosure());
} }
// static // static
......
...@@ -20,7 +20,7 @@ HeadlessBrowserMainParts::~HeadlessBrowserMainParts() = default; ...@@ -20,7 +20,7 @@ HeadlessBrowserMainParts::~HeadlessBrowserMainParts() = default;
void HeadlessBrowserMainParts::PreMainMessageLoopRun() { void HeadlessBrowserMainParts::PreMainMessageLoopRun() {
if (browser_->options()->DevtoolsServerEnabled()) { if (browser_->options()->DevtoolsServerEnabled()) {
StartLocalDevToolsHttpHandler(browser_->options()); StartLocalDevToolsHttpHandler(browser_);
devtools_http_handler_started_ = true; devtools_http_handler_started_ = true;
} }
browser_->PlatformInitialize(); browser_->PlatformInitialize();
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_socket_factory.h" #include "content/public/browser/devtools_socket_factory.h"
#include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_entry.h"
...@@ -124,11 +126,20 @@ class DummyTCPServerSocketFactory : public content::DevToolsSocketFactory { ...@@ -124,11 +126,20 @@ class DummyTCPServerSocketFactory : public content::DevToolsSocketFactory {
DISALLOW_COPY_AND_ASSIGN(DummyTCPServerSocketFactory); DISALLOW_COPY_AND_ASSIGN(DummyTCPServerSocketFactory);
}; };
#endif // defined(OS_POSIX) #endif // defined(OS_POSIX)
void PostTaskToCloseBrowser(base::WeakPtr<HeadlessBrowserImpl> browser) {
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&HeadlessBrowserImpl::Shutdown, browser));
}
} // namespace } // namespace
void StartLocalDevToolsHttpHandler(HeadlessBrowser::Options* options) { void StartLocalDevToolsHttpHandler(HeadlessBrowserImpl* browser) {
if (options->devtools_pipe_enabled) HeadlessBrowser::Options* options = browser->options();
content::DevToolsAgentHost::StartRemoteDebuggingPipeHandler(); if (options->devtools_pipe_enabled) {
content::DevToolsAgentHost::StartRemoteDebuggingPipeHandler(
base::BindOnce(&PostTaskToCloseBrowser, browser->GetWeakPtr()));
}
if (options->devtools_endpoint.IsEmpty()) if (options->devtools_endpoint.IsEmpty())
return; return;
......
...@@ -7,13 +7,13 @@ ...@@ -7,13 +7,13 @@
#include <memory> #include <memory>
#include "headless/public/headless_browser.h" #include "headless/lib/browser/headless_browser_impl.h"
namespace headless { namespace headless {
// Starts a DevTools HTTP handler on the loopback interface on the port // Starts a DevTools HTTP handler on the loopback interface on the port
// configured by HeadlessBrowser::Options. // configured by HeadlessBrowser::Options.
void StartLocalDevToolsHttpHandler(HeadlessBrowser::Options* options); void StartLocalDevToolsHttpHandler(HeadlessBrowserImpl* browser);
void StopLocalDevToolsHttpHandler(); void StopLocalDevToolsHttpHandler();
} // namespace headless } // namespace headless
......
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