blob: 0c9fd3085d56d44a97ec2e34cb29f0057ae0be6f [file] [log] [blame]
amistrydc1c91062016-05-12 00:59:521// Copyright 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/bind.h"
6#include "base/run_loop.h"
7#include "base/strings/utf_string_conversions.h"
Eric Seckler8652dcd52018-09-20 10:42:288#include "base/task/post_task.h"
Jay Civelli14aced2a2018-03-14 23:44:339#include "build/build_config.h"
10#include "content/browser/utility_process_host.h"
Will Harrisffe746632018-06-07 05:16:2911#include "content/public/browser/browser_child_process_observer.h"
Eric Seckler8652dcd52018-09-20 10:42:2812#include "content/public/browser/browser_task_traits.h"
amistrydc1c91062016-05-12 00:59:5213#include "content/public/browser/browser_thread.h"
Will Harrisffe746632018-06-07 05:16:2914#include "content/public/browser/child_process_data.h"
15#include "content/public/browser/child_process_termination_info.h"
Jay Civelli14aced2a2018-03-14 23:44:3316#include "content/public/common/bind_interface_helpers.h"
amistrydc1c91062016-05-12 00:59:5217#include "content/public/test/content_browser_test.h"
18#include "content/public/test/content_browser_test_utils.h"
benff461632016-10-06 14:27:3319#include "content/public/test/test_service.mojom.h"
amistrydc1c91062016-05-12 00:59:5220
Will Harrisffe746632018-06-07 05:16:2921#if defined(OS_MACOSX) || defined(OS_LINUX)
22#include <sys/wait.h>
23#endif
24
25#if defined(OS_WIN)
26#include <windows.h>
27#endif // OS_WIN
28
amistrydc1c91062016-05-12 00:59:5229namespace content {
30
Will Harrisffe746632018-06-07 05:16:2931namespace {
32
33const char kTestProcessName[] = "test_process";
34
35} // namespace
36
37class UtilityProcessHostBrowserTest : public BrowserChildProcessObserver,
38 public ContentBrowserTest {
amistrydc1c91062016-05-12 00:59:5239 public:
Will Harrisffe746632018-06-07 05:16:2940 void RunUtilityProcess(bool elevated, bool crash) {
41 DCHECK_CURRENTLY_ON(BrowserThread::UI);
42 BrowserChildProcessObserver::Add(this);
Will Harrisffe746632018-06-07 05:16:2943 has_crashed = false;
amistrydc1c91062016-05-12 00:59:5244 base::RunLoop run_loop;
Will Harrisffe746632018-06-07 05:16:2945 done_closure_ =
46 base::BindOnce(&UtilityProcessHostBrowserTest::DoneRunning,
47 base::Unretained(this), run_loop.QuitClosure(), crash);
Eric Seckler8652dcd52018-09-20 10:42:2848 base::PostTaskWithTraits(
49 FROM_HERE, {BrowserThread::IO},
tzike2aca992017-09-05 08:50:5450 base::BindOnce(
Jay Civelli14aced2a2018-03-14 23:44:3351 &UtilityProcessHostBrowserTest::RunUtilityProcessOnIOThread,
Will Harrisffe746632018-06-07 05:16:2952 base::Unretained(this), elevated, crash));
amistrydc1c91062016-05-12 00:59:5253 run_loop.Run();
54 }
55
56 protected:
Will Harrisffe746632018-06-07 05:16:2957 void DoneRunning(base::OnceClosure quit_closure, bool expect_crashed) {
58 DCHECK_CURRENTLY_ON(BrowserThread::UI);
59 BrowserChildProcessObserver::Remove(this);
Will Harrisffe746632018-06-07 05:16:2960 EXPECT_EQ(expect_crashed, has_crashed);
61 std::move(quit_closure).Run();
62 }
63
64 void RunUtilityProcessOnIOThread(bool elevated, bool crash) {
65 DCHECK_CURRENTLY_ON(BrowserThread::IO);
Clark DuValla6a3233f2019-06-12 18:56:0266 UtilityProcessHost* host = new UtilityProcessHost();
amistrydc1c91062016-05-12 00:59:5267 host->SetName(base::ASCIIToUTF16("TestProcess"));
Will Harrisffe746632018-06-07 05:16:2968 host->SetMetricsName(kTestProcessName);
amistryb6138912016-05-31 01:54:1269#if defined(OS_WIN)
70 if (elevated)
Jay Civelli0c7f3bfb2017-11-07 16:41:2271 host->SetSandboxType(service_manager::SandboxType::
72 SANDBOX_TYPE_NO_SANDBOX_AND_ELEVATED_PRIVILEGES);
amistryb6138912016-05-31 01:54:1273#endif
amistrydc1c91062016-05-12 00:59:5274 EXPECT_TRUE(host->Start());
75
bena06f7d62017-04-04 20:48:5276 BindInterface(host, &service_);
Will Harrisffe746632018-06-07 05:16:2977 if (crash) {
78 service_->DoCrashImmediately(
79 base::BindOnce(&UtilityProcessHostBrowserTest::OnSomethingOnIOThread,
80 base::Unretained(this), crash));
81 } else {
82 service_->DoSomething(
83 base::BindOnce(&UtilityProcessHostBrowserTest::OnSomethingOnIOThread,
84 base::Unretained(this), crash));
85 }
amistrydc1c91062016-05-12 00:59:5286 }
87
Will Harrisffe746632018-06-07 05:16:2988 void ResetServiceOnIOThread() {
89 DCHECK_CURRENTLY_ON(BrowserThread::IO);
amistrydc1c91062016-05-12 00:59:5290 service_.reset();
Will Harrisffe746632018-06-07 05:16:2991 }
92
93 void OnSomethingOnIOThread(bool expect_crash) {
94 DCHECK_CURRENTLY_ON(BrowserThread::IO);
95 // If service crashes then this never gets called.
96 ASSERT_EQ(false, expect_crash);
97 ResetServiceOnIOThread();
Eric Seckler8652dcd52018-09-20 10:42:2898 base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
99 std::move(done_closure_));
amistrydc1c91062016-05-12 00:59:52100 }
101
benff461632016-10-06 14:27:33102 mojom::TestServicePtr service_;
Will Harrisffe746632018-06-07 05:16:29103 base::OnceClosure done_closure_;
104
105 // Access on UI thread.
Will Harrisffe746632018-06-07 05:16:29106 bool has_crashed;
107
108 private:
109 // content::BrowserChildProcessObserver implementation:
110 void BrowserChildProcessKilled(
111 const ChildProcessData& data,
112 const ChildProcessTerminationInfo& info) override {
113 DCHECK_CURRENTLY_ON(BrowserThread::UI);
114#if defined(OS_ANDROID)
115 // Android does not send crash notifications but sends kills. See comment in
116 // browser_child_process_observer.h.
117 BrowserChildProcessCrashed(data, info);
118#else
119 FAIL() << "Killed notifications should only happen on Android.";
120#endif
121 }
122
123 void BrowserChildProcessCrashed(
124 const ChildProcessData& data,
125 const ChildProcessTerminationInfo& info) override {
126 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Will Harrisffe746632018-06-07 05:16:29127#if defined(OS_WIN)
Reid Klecknerc55cd142019-07-23 00:38:17128 EXPECT_EQ(EXCEPTION_BREAKPOINT, DWORD{info.exit_code});
129#elif defined(OS_MACOSX) || defined(OS_LINUX)
Will Harrisffe746632018-06-07 05:16:29130 EXPECT_TRUE(WIFSIGNALED(info.exit_code));
131 EXPECT_EQ(SIGTRAP, WTERMSIG(info.exit_code));
132#endif
133 EXPECT_EQ(kTestProcessName, data.metrics_name);
134 EXPECT_EQ(false, has_crashed);
135 has_crashed = true;
Eric Seckler8652dcd52018-09-20 10:42:28136 base::PostTaskWithTraits(
137 FROM_HERE, {BrowserThread::IO},
Will Harrisffe746632018-06-07 05:16:29138 base::BindOnce(&UtilityProcessHostBrowserTest::ResetServiceOnIOThread,
139 base::Unretained(this)));
140 std::move(done_closure_).Run();
141 }
amistrydc1c91062016-05-12 00:59:52142};
143
Jay Civelli14aced2a2018-03-14 23:44:33144IN_PROC_BROWSER_TEST_F(UtilityProcessHostBrowserTest, LaunchProcess) {
Will Harrisffe746632018-06-07 05:16:29145 RunUtilityProcess(false, false);
146}
147
Will Harrisc67f8bc2018-10-19 21:04:37148IN_PROC_BROWSER_TEST_F(UtilityProcessHostBrowserTest, LaunchProcessAndCrash) {
Will Harrisffe746632018-06-07 05:16:29149 RunUtilityProcess(false, true);
amistrydc1c91062016-05-12 00:59:52150}
151
amistryb6138912016-05-31 01:54:12152#if defined(OS_WIN)
Vasilii Sukhanov96369af2019-01-31 13:38:33153// Times out. crbug.com/927298.
154IN_PROC_BROWSER_TEST_F(UtilityProcessHostBrowserTest,
155 DISABLED_LaunchElevatedProcess) {
Will Harrisffe746632018-06-07 05:16:29156 RunUtilityProcess(true, false);
157}
158
159// Disabled because currently this causes a WER dialog to appear.
160IN_PROC_BROWSER_TEST_F(UtilityProcessHostBrowserTest,
161 LaunchElevatedProcessAndCrash_DISABLED) {
162 RunUtilityProcess(true, true);
amistryb6138912016-05-31 01:54:12163}
164#endif
165
amistrydc1c91062016-05-12 00:59:52166} // namespace content