blob: 5dda8c37598afe751c543690061eb51e573e850e [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2013 The Chromium Authors
[email protected]8bf1048012012-02-08 01:22:182// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
danakjc492bf82020-09-09 20:02:445#include "content/browser/renderer_host/debug_urls.h"
[email protected]8bf1048012012-02-08 01:22:186
[email protected]029bd942013-01-22 08:30:337#include <vector>
8
[email protected]47752982014-07-29 08:01:439#include "base/command_line.h"
Bruce Dawson5ece13c2024-02-29 20:37:3410#include "base/compiler_specific.h"
James Cook1e618b6032024-06-21 23:13:3711#include "base/debug/alias.h"
[email protected]b4b34792014-06-14 08:29:3712#include "base/debug/asan_invalid_access.h"
13#include "base/debug/profiler.h"
Avi Drissmanadac21992023-01-11 23:46:3914#include "base/functional/bind.h"
Peter Boströmb41d6ee2024-11-20 15:49:3915#include "base/immediate_crash.h"
Sebastien Marchandbb331f592019-12-04 17:59:0316#include "base/memory/memory_pressure_listener.h"
Peter Collingbourne6ce4b212019-02-15 22:19:5017#include "base/sanitizer_buildflags.h"
[email protected]74ebfb12013-06-07 20:48:0018#include "base/strings/utf_string_conversions.h"
erikwright811f1b02015-04-17 18:58:3619#include "base/synchronization/waitable_event.h"
erikwrightcf61cd792015-04-23 14:35:2020#include "base/threading/thread_restrictions.h"
Sigurdur Asgeirsson69d0bcd2018-03-29 21:50:5121#include "build/build_config.h"
[email protected]47752982014-07-29 08:01:4322#include "cc/base/switches.h"
sadrulb428f6b2017-03-03 19:28:3223#include "content/browser/gpu/gpu_process_host.h"
Eric Seckler8652dcd52018-09-20 10:42:2824#include "content/public/browser/browser_task_traits.h"
[email protected]029bd942013-01-22 08:30:3325#include "content/public/browser/browser_thread.h"
[email protected]73270292013-08-09 03:48:0726#include "content/public/common/content_constants.h"
[email protected]8bf1048012012-02-08 01:22:1827#include "content/public/common/url_constants.h"
Gyuyoung Kim107c2a02021-04-13 01:49:3028#include "third_party/blink/public/common/chrome_debug_urls.h"
[email protected]707e1c42013-07-09 21:18:5829#include "url/gurl.h"
[email protected]8bf1048012012-02-08 01:22:1830
Xiaohan Wang7f8052e02022-01-14 18:44:2831#if BUILDFLAG(IS_WIN)
Will Harriseb4a6ff2018-07-25 18:36:5232#include "base/debug/invalid_access_win.h"
33#endif
34
[email protected]8bf1048012012-02-08 01:22:1835namespace content {
36
pmonette3955a4f2016-01-29 22:24:3737class ScopedAllowWaitForDebugURL {
38 private:
Etienne Pierre-dorayaffab0d2018-11-12 15:51:1139 base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope wait;
pmonette3955a4f2016-01-29 22:24:3740};
41
[email protected]029bd942013-01-22 08:30:3342namespace {
43
[email protected]b4b34792014-06-14 08:29:3744// Define the Asan debug URLs.
45const char kAsanCrashDomain[] = "crash";
46const char kAsanHeapOverflow[] = "/browser-heap-overflow";
47const char kAsanHeapUnderflow[] = "/browser-heap-underflow";
48const char kAsanUseAfterFree[] = "/browser-use-after-free";
Sigurdur Asgeirsson69d0bcd2018-03-29 21:50:5149
Xiaohan Wang7f8052e02022-01-14 18:44:2850#if BUILDFLAG(IS_WIN)
[email protected]b4b34792014-06-14 08:29:3751const char kAsanCorruptHeapBlock[] = "/browser-corrupt-heap-block";
52const char kAsanCorruptHeap[] = "/browser-corrupt-heap";
erikwright3d483052015-03-06 13:14:4453#endif
erikwright420a0902015-02-26 21:16:1754
Emmanuel Arias Soto9e159652025-05-16 07:53:5555// The conditions here must stay in sync with |HandleAsanDebugURL|.
[email protected]b4b34792014-06-14 08:29:3756bool IsAsanDebugURL(const GURL& url) {
[email protected]b4b34792014-06-14 08:29:3757 if (!(url.is_valid() && url.SchemeIs(kChromeUIScheme) &&
Aran Gilman37d11632019-10-08 23:07:1558 url.DomainIs(kAsanCrashDomain) && url.has_path())) {
[email protected]b4b34792014-06-14 08:29:3759 return false;
60 }
61
csharrison88b3b712016-11-14 23:12:3562 if (url.path_piece() == kAsanHeapOverflow ||
63 url.path_piece() == kAsanHeapUnderflow ||
64 url.path_piece() == kAsanUseAfterFree) {
[email protected]b4b34792014-06-14 08:29:3765 return true;
66 }
67
Xiaohan Wang7f8052e02022-01-14 18:44:2868#if BUILDFLAG(IS_WIN)
csharrison88b3b712016-11-14 23:12:3569 if (url.path_piece() == kAsanCorruptHeapBlock ||
70 url.path_piece() == kAsanCorruptHeap) {
[email protected]b4b34792014-06-14 08:29:3771 return true;
csharrison88b3b712016-11-14 23:12:3572 }
[email protected]b4b34792014-06-14 08:29:3773#endif
74
75 return false;
76}
77
Emmanuel Arias Soto9e159652025-05-16 07:53:5578// The URLs handled here must exactly match those that return true from
79// |IsAsanDebugURL|.
80void HandleAsanDebugURL(const GURL& url) {
81 CHECK(IsAsanDebugURL(url));
Peter Collingbourne6ce4b212019-02-15 22:19:5082#if defined(ADDRESS_SANITIZER) || BUILDFLAG(IS_HWASAN)
Xiaohan Wang7f8052e02022-01-14 18:44:2883#if BUILDFLAG(IS_WIN)
csharrison88b3b712016-11-14 23:12:3584 if (url.path_piece() == kAsanCorruptHeapBlock) {
[email protected]b4b34792014-06-14 08:29:3785 base::debug::AsanCorruptHeapBlock();
Emmanuel Arias Soto9e159652025-05-16 07:53:5586 return;
87 }
88 if (url.path_piece() == kAsanCorruptHeap) {
[email protected]b4b34792014-06-14 08:29:3789 base::debug::AsanCorruptHeap();
Emmanuel Arias Soto9e159652025-05-16 07:53:5590 return;
[email protected]b4b34792014-06-14 08:29:3791 }
Xiaohan Wangbe7c526a2022-01-15 14:34:5192#endif // BUILDFLAG(IS_WIN)
[email protected]b4b34792014-06-14 08:29:3793
csharrison88b3b712016-11-14 23:12:3594 if (url.path_piece() == kAsanHeapOverflow) {
[email protected]b4b34792014-06-14 08:29:3795 base::debug::AsanHeapOverflow();
Emmanuel Arias Soto9e159652025-05-16 07:53:5596 return;
97 }
98 if (url.path_piece() == kAsanHeapUnderflow) {
[email protected]b4b34792014-06-14 08:29:3799 base::debug::AsanHeapUnderflow();
Emmanuel Arias Soto9e159652025-05-16 07:53:55100 return;
101 }
102 if (url.path_piece() == kAsanUseAfterFree) {
[email protected]b4b34792014-06-14 08:29:37103 base::debug::AsanHeapUseAfterFree();
Emmanuel Arias Soto9e159652025-05-16 07:53:55104 return;
[email protected]b4b34792014-06-14 08:29:37105 }
106#endif
[email protected]b4b34792014-06-14 08:29:37107}
108
Bruce Dawson5ece13c2024-02-29 20:37:34109NOINLINE void HangCurrentThread() {
pmonette3955a4f2016-01-29 22:24:37110 ScopedAllowWaitForDebugURL allow_wait;
gabd6f9bff2016-06-02 13:48:20111 base::WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
112 base::WaitableEvent::InitialState::NOT_SIGNALED)
113 .Wait();
pmonette3955a4f2016-01-29 22:24:37114}
[email protected]b4b34792014-06-14 08:29:37115
Bruce Dawson5ece13c2024-02-29 20:37:34116NOINLINE void CrashBrowserProcessIntentionally() {
James Cook1e618b6032024-06-21 23:13:37117 // Don't fold so that crash reports will clearly show this method. This helps
118 // with crash triage.
119 NO_CODE_FOLDING();
Bruce Dawson5ece13c2024-02-29 20:37:34120 // Induce an intentional crash in the browser process.
Peter Boströmb41d6ee2024-11-20 15:49:39121 base::ImmediateCrash();
Bruce Dawson5ece13c2024-02-29 20:37:34122}
123
[email protected]029bd942013-01-22 08:30:33124} // namespace
125
Emmanuel Arias Soto9e159652025-05-16 07:53:55126// The conditions here must stay in sync with |HandleDebugURL|.
127bool IsDebugURL(const GURL& url) {
128 if (!(url.is_valid() && url.SchemeIs(kChromeUIScheme))) {
129 return false;
130 }
131
132 if (IsAsanDebugURL(url)) {
133 return true;
134 }
135
136 if (url == blink::kChromeUIBrowserCrashURL ||
137 url == blink::kChromeUIBrowserDcheckURL ||
138#if BUILDFLAG(IS_WIN)
139 url == blink::kChromeUIBrowserHeapCorruptionURL ||
140#endif
141 url == blink::kChromeUIBrowserUIHang ||
142 url == blink::kChromeUIDelayedBrowserUIHang ||
143 url == blink::kChromeUIGpuCleanURL ||
144 url == blink::kChromeUIGpuCrashURL ||
145#if BUILDFLAG(IS_ANDROID)
146 url == blink::kChromeUIGpuJavaCrashURL ||
147#endif
148 url == blink::kChromeUIGpuHangURL ||
149 url == blink::kChromeUIMemoryPressureCriticalURL ||
150 url == blink::kChromeUIMemoryPressureModerateURL) {
151 return true;
152 }
153
154 return false;
155}
156
157// The URLs handled here must exactly match those that return true from
158// |IsDebugURL|.
159void HandleDebugURL(const GURL& url,
Ian Vollick9dda0522019-09-11 02:24:29160 ui::PageTransition transition,
161 bool is_explicit_navigation) {
Emmanuel Arias Soto9e159652025-05-16 07:53:55162 CHECK(IsDebugURL(url));
Ian Vollick9dda0522019-09-11 02:24:29163 // We want to handle the debug URL if the user explicitly navigated to this
164 // URL, unless kEnableGpuBenchmarking is enabled by Telemetry.
[email protected]479278702014-08-11 20:32:09165 bool is_telemetry_navigation =
166 base::CommandLine::ForCurrentProcess()->HasSwitch(
Peter Kasting6e6af3c2024-10-15 00:13:18167 switches::kEnableGpuBenchmarking) &&
vmiura20fa51a32015-10-27 21:39:34168 (PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_TYPED));
Emmanuel Arias Soto9e159652025-05-16 07:53:55169 if (!is_explicit_navigation && !is_telemetry_navigation) {
170 return;
[email protected]8bf1048012012-02-08 01:22:18171 }
172
Emmanuel Arias Soto9e159652025-05-16 07:53:55173 if (IsAsanDebugURL(url)) {
174 HandleAsanDebugURL(url);
175 return;
176 }
177 if (url == blink::kChromeUIBrowserCrashURL) {
178 CrashBrowserProcessIntentionally();
179 return;
180 }
Peter Boströmd0320702022-05-17 19:16:31181 if (url == blink::kChromeUIBrowserDcheckURL) {
182 // Induce an intentional DCHECK in the browser process. This is used to
183 // see if a DCHECK will bring down the current process (is FATAL).
184 DCHECK(false);
Emmanuel Arias Soto9e159652025-05-16 07:53:55185 return;
Peter Boströmd0320702022-05-17 19:16:31186 }
Xiaohan Wang7f8052e02022-01-14 18:44:28187#if BUILDFLAG(IS_WIN)
Gyuyoung Kim107c2a02021-04-13 01:49:30188 if (url == blink::kChromeUIBrowserHeapCorruptionURL) {
Will Harriseb4a6ff2018-07-25 18:36:52189 // Induce an intentional heap corruption in the browser process.
190 base::debug::win::TerminateWithHeapCorruption();
Will Harriseb4a6ff2018-07-25 18:36:52191 }
192#endif
Gyuyoung Kim107c2a02021-04-13 01:49:30193 if (url == blink::kChromeUIBrowserUIHang) {
pmonette3955a4f2016-01-29 22:24:37194 HangCurrentThread();
Emmanuel Arias Soto9e159652025-05-16 07:53:55195 return;
pmonette3955a4f2016-01-29 22:24:37196 }
Gyuyoung Kim107c2a02021-04-13 01:49:30197 if (url == blink::kChromeUIDelayedBrowserUIHang) {
pmonette3955a4f2016-01-29 22:24:37198 // Webdriver-safe url to hang the ui thread. Webdriver waits for the onload
199 // event in javascript which needs a little more time to fire.
Gabriel Charettee7cdc5cd2020-05-27 23:35:05200 GetUIThreadTaskRunner({})->PostDelayedTask(
Peter Kastinge5a38ed2021-10-02 03:06:35201 FROM_HERE, base::BindOnce(&HangCurrentThread), base::Seconds(2));
Emmanuel Arias Soto9e159652025-05-16 07:53:55202 return;
erikwright811f1b02015-04-17 18:58:36203 }
Gyuyoung Kim107c2a02021-04-13 01:49:30204 if (url == blink::kChromeUIGpuCleanURL) {
Thiabaud Engelbrechte7ed1652023-06-04 21:42:35205 auto* host = GpuProcessHost::Get();
206 if (host) {
207 host->gpu_service()->DestroyAllChannels();
208 }
Emmanuel Arias Soto9e159652025-05-16 07:53:55209 return;
[email protected]8bf1048012012-02-08 01:22:18210 }
Gyuyoung Kim107c2a02021-04-13 01:49:30211 if (url == blink::kChromeUIGpuCrashURL) {
Thiabaud Engelbrechte7ed1652023-06-04 21:42:35212 auto* host = GpuProcessHost::Get();
213 if (host) {
214 host->gpu_service()->Crash();
215 }
Emmanuel Arias Soto9e159652025-05-16 07:53:55216 return;
[email protected]8bf1048012012-02-08 01:22:18217 }
Xiaohan Wang7f8052e02022-01-14 18:44:28218#if BUILDFLAG(IS_ANDROID)
Gyuyoung Kim107c2a02021-04-13 01:49:30219 if (url == blink::kChromeUIGpuJavaCrashURL) {
Thiabaud Engelbrechte7ed1652023-06-04 21:42:35220 auto* host = GpuProcessHost::Get();
221 if (host) {
222 host->gpu_service()->ThrowJavaException();
223 }
Emmanuel Arias Soto9e159652025-05-16 07:53:55224 return;
boliu7a81c2522017-02-03 03:41:04225 }
226#endif
Gyuyoung Kim107c2a02021-04-13 01:49:30227 if (url == blink::kChromeUIGpuHangURL) {
Thiabaud Engelbrechte7ed1652023-06-04 21:42:35228 auto* host = GpuProcessHost::Get();
229 if (host) {
230 host->gpu_service()->Hang();
231 }
Emmanuel Arias Soto9e159652025-05-16 07:53:55232 return;
[email protected]8bf1048012012-02-08 01:22:18233 }
Gyuyoung Kim107c2a02021-04-13 01:49:30234 if (url == blink::kChromeUIMemoryPressureCriticalURL) {
Sebastien Marchandbb331f592019-12-04 17:59:03235 base::MemoryPressureListener::NotifyMemoryPressure(
236 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
Emmanuel Arias Soto9e159652025-05-16 07:53:55237 return;
Sebastien Marchandbb331f592019-12-04 17:59:03238 }
Gyuyoung Kim107c2a02021-04-13 01:49:30239 if (url == blink::kChromeUIMemoryPressureModerateURL) {
Sebastien Marchandbb331f592019-12-04 17:59:03240 base::MemoryPressureListener::NotifyMemoryPressure(
241 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
Emmanuel Arias Soto9e159652025-05-16 07:53:55242 return;
Sebastien Marchandbb331f592019-12-04 17:59:03243 }
[email protected]8bf1048012012-02-08 01:22:18244}
245
[email protected]8bf1048012012-02-08 01:22:18246} // namespace content