• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Chromium Authors
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 "components/metrics/content/content_stability_metrics_provider.h"
6 
7 #include <string>
8 
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/functional/callback.h"
12 #include "base/metrics/histogram.h"
13 #include "base/test/metrics/histogram_tester.h"
14 #include "build/build_config.h"
15 #include "components/metrics/content/extensions_helper.h"
16 #include "components/prefs/testing_pref_service.h"
17 #include "components/variations/hashing.h"
18 #include "content/public/browser/browser_child_process_observer.h"
19 #include "content/public/browser/child_process_data.h"
20 #include "content/public/browser/service_process_host.h"
21 #include "content/public/common/content_switches.h"
22 #include "content/public/test/browser_test.h"
23 #include "content/public/test/browser_test_base.h"
24 #include "content/public/test/content_browser_test.h"
25 #include "content/public/test/content_browser_test_utils.h"
26 #include "content/public/test/test_service.mojom.h"
27 #include "sandbox/policy/mojom/sandbox.mojom.h"
28 
29 #if BUILDFLAG(IS_WIN)
30 #include <windows.h>
31 
32 #include "sandbox/win/src/sandbox_types.h"
33 #endif
34 
35 namespace content {
36 
37 template <>
GetServiceSandboxType()38 sandbox::mojom::Sandbox GetServiceSandboxType<content::mojom::TestService>() {
39   // On Windows, the sandbox does not like having a different binary name
40   // 'non_existent_path' from the browser process, so set no sandbox here.
41 #if BUILDFLAG(IS_WIN)
42   return sandbox::mojom::Sandbox::kNoSandbox;
43 #else
44   return sandbox::mojom::Sandbox::kService;
45 #endif
46 }
47 
48 }  // namespace content
49 
50 namespace metrics {
51 
52 class ContentStabilityProviderBrowserTest
53     : public content::ContentBrowserTest,
54       content::BrowserChildProcessObserver {
55  public:
56   // Either the process launched, or did not launch. Both cause the run_loop to
57   // terminate.
BrowserChildProcessLaunchFailed(const content::ChildProcessData & data,const content::ChildProcessTerminationInfo & info)58   void BrowserChildProcessLaunchFailed(
59       const content::ChildProcessData& data,
60       const content::ChildProcessTerminationInfo& info) override {
61     if (data.metrics_name == content::mojom::TestService::Name_)
62       std::move(done_closure_).Run();
63   }
64 
BrowserChildProcessLaunchedAndConnected(const content::ChildProcessData & data)65   void BrowserChildProcessLaunchedAndConnected(
66       const content::ChildProcessData& data) override {
67     if (data.metrics_name == content::mojom::TestService::Name_)
68       std::move(done_closure_).Run();
69   }
70 
71  protected:
AddObserver()72   void AddObserver() { content::BrowserChildProcessObserver::Add(this); }
73 
RemoveObserver()74   void RemoveObserver() { content::BrowserChildProcessObserver::Remove(this); }
75 
76   base::OnceClosure done_closure_;
77   TestingPrefServiceSimple prefs_;
78 };
79 
IN_PROC_BROWSER_TEST_F(ContentStabilityProviderBrowserTest,FailedUtilityProcessLaunches)80 IN_PROC_BROWSER_TEST_F(ContentStabilityProviderBrowserTest,
81                        FailedUtilityProcessLaunches) {
82   base::RunLoop run_loop;
83   done_closure_ = run_loop.QuitClosure();
84   AddObserver();
85 
86   ContentStabilityMetricsProvider provider(&prefs_, nullptr);
87   base::HistogramTester histogram_tester;
88 
89   // Simulate a catastrophic utility process launch failure by specifying a bad
90   // path.
91   base::CommandLine::ForCurrentProcess()->AppendSwitchPath(
92       switches::kBrowserSubprocessPath,
93       base::FilePath(FILE_PATH_LITERAL("non_existent_path")));
94   mojo::Remote<content::mojom::TestService> test_service;
95   content::ServiceProcessHost::Launch(
96       test_service.BindNewPipeAndPassReceiver());
97 
98   // run_loop runs until either the process launches or fails to launch.
99   run_loop.Run();
100 
101   RemoveObserver();
102 
103   histogram_tester.ExpectUniqueSample(
104       "ChildProcess.LaunchFailed.UtilityProcessHash",
105       variations::HashName(content::mojom::TestService::Name_), 1);
106 #if BUILDFLAG(IS_WIN)
107   int expected_error_code =
108       sandbox::SBOX_ERROR_CANNOT_LAUNCH_UNSANDBOXED_PROCESS;
109 #else
110   int expected_error_code =
111       1003;  // content::LaunchResultCode::LAUNCH_RESULT_FAILURE.
112 #endif
113   histogram_tester.ExpectUniqueSample(
114       "ChildProcess.LaunchFailed.UtilityProcessErrorCode", expected_error_code,
115       1);
116 
117 #if BUILDFLAG(IS_WIN)
118   // Last Error is only recorded on Windows.
119   histogram_tester.ExpectUniqueSample("ChildProcess.LaunchFailed.WinLastError",
120                                       DWORD{ERROR_FILE_NOT_FOUND}, 1);
121 #endif
122 }
123 
124 }  // namespace metrics
125