1 // Copyright 2013 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.
5 #include "content/browser/frame_host/debug_urls.h"
13 #include "base/command_line.h"
14 #include "base/debug/asan_invalid_access.h"
15 #include "base/debug/profiler.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "cc/base/switches.h"
18 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/common/content_constants.h"
21 #include "content/public/common/url_constants.h"
22 #include "ppapi/proxy/ppapi_messages.h"
25 #if defined(ENABLE_PLUGINS)
26 #include "content/browser/ppapi_plugin_process_host.h"
33 // Define the Asan debug URLs.
34 const char kAsanCrashDomain
[] = "crash";
35 const char kAsanHeapOverflow
[] = "/browser-heap-overflow";
36 const char kAsanHeapUnderflow
[] = "/browser-heap-underflow";
37 const char kAsanUseAfterFree
[] = "/browser-use-after-free";
39 const char kAsanCorruptHeapBlock
[] = "/browser-corrupt-heap-block";
40 const char kAsanCorruptHeap
[] = "/browser-corrupt-heap";
42 // Define the Kasko debug URLs.
43 const char kKaskoCrashDomain
[] = "kasko";
44 const char kKaskoSendReport
[] = "/send-report";
47 void HandlePpapiFlashDebugURL(const GURL
& url
) {
48 #if defined(ENABLE_PLUGINS)
49 bool crash
= url
== GURL(kChromeUIPpapiFlashCrashURL
);
51 std::vector
<PpapiPluginProcessHost
*> hosts
;
52 PpapiPluginProcessHost::FindByName(
53 base::UTF8ToUTF16(kFlashPluginName
), &hosts
);
54 for (std::vector
<PpapiPluginProcessHost
*>::iterator iter
= hosts
.begin();
55 iter
!= hosts
.end(); ++iter
) {
57 (*iter
)->Send(new PpapiMsg_Crash());
59 (*iter
)->Send(new PpapiMsg_Hang());
64 bool IsKaskoDebugURL(const GURL
& url
) {
66 return (url
.is_valid() && url
.SchemeIs(kChromeUIScheme
) &&
67 url
.DomainIs(kKaskoCrashDomain
, sizeof(kKaskoCrashDomain
) - 1) &&
68 url
.path() == kKaskoSendReport
);
74 void HandleKaskoDebugURL() {
76 // Signature of an enhanced crash reporting function.
77 typedef void(__cdecl
* ReportCrashWithProtobufPtr
)(EXCEPTION_POINTERS
*,
80 HMODULE exe_hmodule
= ::GetModuleHandle(NULL
);
81 ReportCrashWithProtobufPtr report_crash_with_protobuf
=
82 reinterpret_cast<ReportCrashWithProtobufPtr
>(
83 ::GetProcAddress(exe_hmodule
, "ReportCrashWithProtobuf"));
84 if (report_crash_with_protobuf
)
85 report_crash_with_protobuf(NULL
, "Invoked from debug url.");
93 bool IsAsanDebugURL(const GURL
& url
) {
95 if (!base::debug::IsBinaryInstrumented())
99 if (!(url
.is_valid() && url
.SchemeIs(kChromeUIScheme
) &&
100 url
.DomainIs(kAsanCrashDomain
, sizeof(kAsanCrashDomain
) - 1) &&
105 if (url
.path() == kAsanHeapOverflow
|| url
.path() == kAsanHeapUnderflow
||
106 url
.path() == kAsanUseAfterFree
) {
110 #if defined(SYZYASAN)
111 if (url
.path() == kAsanCorruptHeapBlock
|| url
.path() == kAsanCorruptHeap
)
118 bool HandleAsanDebugURL(const GURL
& url
) {
119 #if defined(SYZYASAN)
120 if (!base::debug::IsBinaryInstrumented())
123 if (url
.path() == kAsanCorruptHeapBlock
) {
124 base::debug::AsanCorruptHeapBlock();
126 } else if (url
.path() == kAsanCorruptHeap
) {
127 base::debug::AsanCorruptHeap();
132 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
133 if (url
.path() == kAsanHeapOverflow
) {
134 base::debug::AsanHeapOverflow();
135 } else if (url
.path() == kAsanHeapUnderflow
) {
136 base::debug::AsanHeapUnderflow();
137 } else if (url
.path() == kAsanUseAfterFree
) {
138 base::debug::AsanHeapUseAfterFree();
150 bool HandleDebugURL(const GURL
& url
, ui::PageTransition transition
) {
151 // Ensure that the user explicitly navigated to this URL, unless
152 // kEnableGpuBenchmarking is enabled by Telemetry.
153 bool is_telemetry_navigation
=
154 base::CommandLine::ForCurrentProcess()->HasSwitch(
155 cc::switches::kEnableGpuBenchmarking
) &&
156 (transition
& ui::PAGE_TRANSITION_TYPED
);
158 if (!(transition
& ui::PAGE_TRANSITION_FROM_ADDRESS_BAR
) &&
159 !is_telemetry_navigation
)
162 if (IsAsanDebugURL(url
))
163 return HandleAsanDebugURL(url
);
165 if (IsKaskoDebugURL(url
)) {
166 HandleKaskoDebugURL();
170 if (url
== GURL(kChromeUIBrowserCrashURL
)) {
171 // Induce an intentional crash in the browser process.
176 if (url
== GURL(kChromeUIGpuCleanURL
)) {
177 GpuProcessHostUIShim
* shim
= GpuProcessHostUIShim::GetOneInstance();
179 shim
->SimulateRemoveAllContext();
183 if (url
== GURL(kChromeUIGpuCrashURL
)) {
184 GpuProcessHostUIShim
* shim
= GpuProcessHostUIShim::GetOneInstance();
186 shim
->SimulateCrash();
190 if (url
== GURL(kChromeUIGpuHangURL
)) {
191 GpuProcessHostUIShim
* shim
= GpuProcessHostUIShim::GetOneInstance();
193 shim
->SimulateHang();
197 if (url
== GURL(kChromeUIPpapiFlashCrashURL
) ||
198 url
== GURL(kChromeUIPpapiFlashHangURL
)) {
199 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
200 base::Bind(&HandlePpapiFlashDebugURL
, url
));
207 bool IsRendererDebugURL(const GURL
& url
) {
211 if (url
.SchemeIs(url::kJavaScriptScheme
))
214 return url
== GURL(kChromeUICrashURL
) ||
215 url
== GURL(kChromeUIDumpURL
) ||
216 url
== GURL(kChromeUIKillURL
) ||
217 url
== GURL(kChromeUIHangURL
) ||
218 url
== GURL(kChromeUIShorthangURL
);
221 } // namespace content