blob: 186ef33a6d4324cf3ff93309f0e7433d151ce6ef [file] [log] [blame]
// Copyright 2019 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 "chrome/browser/ui/webui/sandbox/sandbox_handler.h"
#include <utility>
#include "base/bind.h"
#include "base/numerics/safe_conversions.h"
#include "base/task/post_task.h"
#include "base/values.h"
#include "content/public/browser/browser_child_process_host_iterator.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/sandbox_type.h"
#include "content/public/browser/web_ui.h"
#include "content/public/common/process_type.h"
#include "services/service_manager/sandbox/win/sandbox_win.h"
using content::BrowserChildProcessHostIterator;
using content::ChildProcessData;
using content::RenderProcessHost;
namespace sandbox_handler {
namespace {
// This only includes OS_WIN included SandboxType values.
std::string GetSandboxTypeInEnglish(content::SandboxType sandbox_type) {
switch (sandbox_type) {
case content::SandboxType::kNoSandbox:
return "Unsandboxed";
case content::SandboxType::kNoSandboxAndElevatedPrivileges:
return "Unsandboxed (Elevated)";
case content::SandboxType::kXrCompositing:
return "XR Compositing";
case content::SandboxType::kRenderer:
return "Renderer";
case content::SandboxType::kUtility:
return "Utility";
case content::SandboxType::kGpu:
return "GPU";
case content::SandboxType::kPpapi:
return "PPAPI";
case content::SandboxType::kNetwork:
return "Network";
case content::SandboxType::kCdm:
return "CDM";
case content::SandboxType::kPrintCompositor:
return "Print Compositor";
case content::SandboxType::kAudio:
return "Audio";
case content::SandboxType::kSpeechRecognition:
return "Speech Recognition";
case content::SandboxType::kProxyResolver:
return "Proxy Resolver";
case content::SandboxType::kPdfConversion:
return "PDF Conversion";
case content::SandboxType::kSharingService:
return "Sharing";
case content::SandboxType::kVideoCapture:
return "Video Capture";
}
}
base::Value FetchBrowserChildProcesses() {
// The |BrowserChildProcessHostIterator| must only be used on the IO thread.
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
base::Value browser_processes(base::Value::Type::LIST);
for (BrowserChildProcessHostIterator itr; !itr.Done(); ++itr) {
const ChildProcessData& process_data = itr.GetData();
// Only add processes that have already started, i.e. with valid handles.
if (!process_data.GetProcess().IsValid())
continue;
base::Value proc(base::Value::Type::DICTIONARY);
proc.SetPath("processId", base::Value(base::strict_cast<double>(
process_data.GetProcess().Pid())));
proc.SetPath("processType",
base::Value(content::GetProcessTypeNameInEnglish(
process_data.process_type)));
proc.SetPath("name", base::Value(process_data.name));
proc.SetPath("metricsName", base::Value(process_data.metrics_name));
proc.SetPath(
"sandboxType",
base::Value(GetSandboxTypeInEnglish(process_data.sandbox_type)));
browser_processes.Append(std::move(proc));
}
return browser_processes;
}
base::Value FetchRenderHostProcesses() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
base::Value renderer_processes(base::Value::Type::LIST);
for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
!it.IsAtEnd(); it.Advance()) {
RenderProcessHost* host = it.GetCurrentValue();
// Skip processes that might not have started yet.
if (!host->GetProcess().IsValid())
continue;
base::Value proc(base::Value::Type::DICTIONARY);
proc.SetPath(
"processId",
base::Value(base::strict_cast<double>(host->GetProcess().Pid())));
renderer_processes.Append(std::move(proc));
}
return renderer_processes;
}
} // namespace
SandboxHandler::SandboxHandler() = default;
SandboxHandler::~SandboxHandler() = default;
void SandboxHandler::RegisterMessages() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
web_ui()->RegisterMessageCallback(
"requestSandboxDiagnostics",
base::BindRepeating(&SandboxHandler::HandleRequestSandboxDiagnostics,
base::Unretained(this)));
}
void SandboxHandler::HandleRequestSandboxDiagnostics(
const base::ListValue* args) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
CHECK_EQ(1U, args->GetList().size());
sandbox_diagnostics_callback_id_ = args->GetList()[0].Clone();
AllowJavascript();
base::PostTaskAndReplyWithResult(
FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&FetchBrowserChildProcesses),
base::BindOnce(&SandboxHandler::FetchBrowserChildProcessesCompleted,
weak_ptr_factory_.GetWeakPtr()));
}
void SandboxHandler::FetchBrowserChildProcessesCompleted(
base::Value browser_processes) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
browser_processes_ = std::move(browser_processes);
service_manager::SandboxWin::GetPolicyDiagnostics(
base::BindOnce(&SandboxHandler::FetchSandboxDiagnosticsCompleted,
weak_ptr_factory_.GetWeakPtr()));
}
// This runs nested inside SandboxWin so we get out quickly.
void SandboxHandler::FetchSandboxDiagnosticsCompleted(
base::Value sandbox_policies) {
sandbox_policies_ = std::move(sandbox_policies);
base::PostTask(FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&SandboxHandler::GetRendererProcessesAndFinish,
weak_ptr_factory_.GetWeakPtr()));
}
void SandboxHandler::GetRendererProcessesAndFinish() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
auto renderer_processes = FetchRenderHostProcesses();
base::Value results(base::Value::Type::DICTIONARY);
results.SetPath("browser", std::move(browser_processes_));
results.SetPath("policies", std::move(sandbox_policies_));
results.SetPath("renderer", std::move(renderer_processes));
ResolveJavascriptCallback(sandbox_diagnostics_callback_id_,
std::move(results));
}
} // namespace sandbox_handler