| // Copyright 2019 The Chromium Authors |
| // 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/functional/bind.h" |
| #include "base/numerics/safe_conversions.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/web_ui.h" |
| #include "content/public/common/process_type.h" |
| #include "sandbox/policy/features.h" |
| #include "sandbox/policy/win/sandbox_win.h" |
| |
| using content::BrowserChildProcessHostIterator; |
| using content::ChildProcessData; |
| using content::RenderProcessHost; |
| |
| namespace sandbox_handler { |
| namespace { |
| |
| base::Value::List FetchBrowserChildProcesses() { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| base::Value::List browser_processes; |
| |
| 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::Dict proc; |
| proc.Set("processId", |
| base::strict_cast<double>(process_data.GetProcess().Pid())); |
| proc.Set("processType", |
| content::GetProcessTypeNameInEnglish(process_data.process_type)); |
| proc.Set("name", process_data.name); |
| proc.Set("metricsName", process_data.metrics_name); |
| proc.Set("sandboxType", |
| sandbox::policy::SandboxWin::GetSandboxTypeInEnglish( |
| process_data.sandbox_type)); |
| browser_processes.Append(std::move(proc)); |
| } |
| |
| return browser_processes; |
| } |
| |
| base::Value::List FetchRenderHostProcesses() { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| base::Value::List renderer_processes; |
| |
| 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::Dict proc; |
| proc.Set("processId", base::strict_cast<double>(host->GetProcess().Pid())); |
| renderer_processes.Append(std::move(proc)); |
| } |
| |
| return renderer_processes; |
| } |
| |
| base::Value::Dict FeatureToValue(const base::Feature& feature) { |
| base::Value::Dict feature_info; |
| feature_info.Set("name", feature.name); |
| feature_info.Set("enabled", base::FeatureList::IsEnabled(feature)); |
| return feature_info; |
| } |
| |
| base::Value::List FetchSandboxFeatures() { |
| base::Value::List features; |
| features.Append( |
| FeatureToValue(sandbox::policy::features::kNetworkServiceSandbox)); |
| features.Append( |
| FeatureToValue(sandbox::policy::features::kRendererAppContainer)); |
| features.Append(FeatureToValue( |
| sandbox::policy::features::kWinSboxDisableExtensionPoints)); |
| features.Append( |
| FeatureToValue(sandbox::policy::features::kWinSboxZeroAppShim)); |
| features.Append( |
| FeatureToValue(sandbox::policy::features::kWinSboxNoFakeGdiInit)); |
| features.Append(FeatureToValue( |
| sandbox::policy::features::kWinSboxRestrictCoreSharingOnRenderer)); |
| features.Append( |
| FeatureToValue(sandbox::policy::features::kEnableCsrssLockdown)); |
| return features; |
| } |
| |
| } // 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::Value::List& args) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| |
| CHECK_EQ(1U, args.size()); |
| sandbox_diagnostics_callback_id_ = args[0].Clone(); |
| |
| AllowJavascript(); |
| |
| browser_processes_ = FetchBrowserChildProcesses(); |
| |
| sandbox::policy::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); |
| content::GetUIThreadTaskRunner({})->PostTask( |
| FROM_HERE, base::BindOnce(&SandboxHandler::GetRendererProcessesAndFinish, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void SandboxHandler::GetRendererProcessesAndFinish() { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| |
| auto renderer_processes = FetchRenderHostProcesses(); |
| base::Value::Dict results; |
| results.Set("browser", std::move(browser_processes_)); |
| results.Set("policies", std::move(sandbox_policies_)); |
| results.Set("renderer", std::move(renderer_processes)); |
| results.Set("features", FetchSandboxFeatures()); |
| ResolveJavascriptCallback(sandbox_diagnostics_callback_id_, |
| std::move(results)); |
| } |
| |
| } // namespace sandbox_handler |