blob: cc80c53d946423146d6a49efadf6bc97893da3d8 [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"
Julie Jeongeun Kim29cb9cb72019-09-17 02:58:3520#include "mojo/public/cpp/bindings/remote.h"
amistrydc1c91062016-05-12 00:59:5221
Will Harrisffe746632018-06-07 05:16:2922#if defined(OS_MACOSX) || defined(OS_LINUX)
23#include <sys/wait.h>
24#endif
25
26#if defined(OS_WIN)
27#include <windows.h>
28#endif // OS_WIN
29
amistrydc1c91062016-05-12 00:59:5230namespace content {
31
Will Harrisffe746632018-06-07 05:16:2932namespace {
33
34const char kTestProcessName[] = "test_process";
35
36} // namespace
37
38class UtilityProcessHostBrowserTest : public BrowserChildProcessObserver,
39 public ContentBrowserTest {
amistrydc1c91062016-05-12 00:59:5240 public:
Will Harrisffe746632018-06-07 05:16:2941 void RunUtilityProcess(bool elevated, bool crash) {
42 DCHECK_CURRENTLY_ON(BrowserThread::UI);
43 BrowserChildProcessObserver::Add(this);
Will Harrisffe746632018-06-07 05:16:2944 has_crashed = false;
amistrydc1c91062016-05-12 00:59:5245 base::RunLoop run_loop;
Will Harrisffe746632018-06-07 05:16:2946 done_closure_ =
47 base::BindOnce(&UtilityProcessHostBrowserTest::DoneRunning,
48 base::Unretained(this), run_loop.QuitClosure(), crash);
Sami Kyostila8e4d5a92019-08-02 12:45:0549 base::PostTask(
Eric Seckler8652dcd52018-09-20 10:42:2850 FROM_HERE, {BrowserThread::IO},
tzike2aca992017-09-05 08:50:5451 base::BindOnce(
Jay Civelli14aced2a2018-03-14 23:44:3352 &UtilityProcessHostBrowserTest::RunUtilityProcessOnIOThread,
Will Harrisffe746632018-06-07 05:16:2953 base::Unretained(this), elevated, crash));
amistrydc1c91062016-05-12 00:59:5254 run_loop.Run();
55 }
56
57 protected:
Will Harrisffe746632018-06-07 05:16:2958 void DoneRunning(base::OnceClosure quit_closure, bool expect_crashed) {
59 DCHECK_CURRENTLY_ON(BrowserThread::UI);
60 BrowserChildProcessObserver::Remove(this);
Will Harrisffe746632018-06-07 05:16:2961 EXPECT_EQ(expect_crashed, has_crashed);
62 std::move(quit_closure).Run();
63 }
64
65 void RunUtilityProcessOnIOThread(bool elevated, bool crash) {
66 DCHECK_CURRENTLY_ON(BrowserThread::IO);
Clark DuValla6a3233f2019-06-12 18:56:0267 UtilityProcessHost* host = new UtilityProcessHost();
amistrydc1c91062016-05-12 00:59:5268 host->SetName(base::ASCIIToUTF16("TestProcess"));
Will Harrisffe746632018-06-07 05:16:2969 host->SetMetricsName(kTestProcessName);
amistryb6138912016-05-31 01:54:1270#if defined(OS_WIN)
71 if (elevated)
Jay Civelli0c7f3bfb2017-11-07 16:41:2272 host->SetSandboxType(service_manager::SandboxType::
73 SANDBOX_TYPE_NO_SANDBOX_AND_ELEVATED_PRIVILEGES);
amistryb6138912016-05-31 01:54:1274#endif
amistrydc1c91062016-05-12 00:59:5275 EXPECT_TRUE(host->Start());
76
Julie Jeongeun Kim29cb9cb72019-09-17 02:58:3577 BindInterface(host, service_.BindNewPipeAndPassReceiver());
Will Harrisffe746632018-06-07 05:16:2978 if (crash) {
79 service_->DoCrashImmediately(
80 base::BindOnce(&UtilityProcessHostBrowserTest::OnSomethingOnIOThread,
81 base::Unretained(this), crash));
82 } else {
83 service_->DoSomething(
84 base::BindOnce(&UtilityProcessHostBrowserTest::OnSomethingOnIOThread,
85 base::Unretained(this), crash));
86 }
amistrydc1c91062016-05-12 00:59:5287 }
88
Will Harrisffe746632018-06-07 05:16:2989 void ResetServiceOnIOThread() {
90 DCHECK_CURRENTLY_ON(BrowserThread::IO);
amistrydc1c91062016-05-12 00:59:5291 service_.reset();
Will Harrisffe746632018-06-07 05:16:2992 }
93
94 void OnSomethingOnIOThread(bool expect_crash) {
95 DCHECK_CURRENTLY_ON(BrowserThread::IO);
96 // If service crashes then this never gets called.
97 ASSERT_EQ(false, expect_crash);
98 ResetServiceOnIOThread();
Sami Kyostila8e4d5a92019-08-02 12:45:0599 base::PostTask(FROM_HERE, {BrowserThread::UI}, std::move(done_closure_));
amistrydc1c91062016-05-12 00:59:52100 }
101
Julie Jeongeun Kim29cb9cb72019-09-17 02:58:35102 mojo::Remote<mojom::TestService> 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;
Sami Kyostila8e4d5a92019-08-02 12:45:05136 base::PostTask(
Eric Seckler8652dcd52018-09-20 10:42:28137 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