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";
44 // Define the Kasko debug URLs.
45 const char kKaskoCrashDomain
[] = "kasko";
46 const char kKaskoSendReport
[] = "/send-report";
49 void HandlePpapiFlashDebugURL(const GURL
& url
) {
50 #if defined(ENABLE_PLUGINS)
51 bool crash
= url
== GURL(kChromeUIPpapiFlashCrashURL
);
53 std::vector
<PpapiPluginProcessHost
*> hosts
;
54 PpapiPluginProcessHost::FindByName(
55 base::UTF8ToUTF16(kFlashPluginName
), &hosts
);
56 for (std::vector
<PpapiPluginProcessHost
*>::iterator iter
= hosts
.begin();
57 iter
!= hosts
.end(); ++iter
) {
59 (*iter
)->Send(new PpapiMsg_Crash());
61 (*iter
)->Send(new PpapiMsg_Hang());
66 bool IsKaskoDebugURL(const GURL
& url
) {
68 return (url
.is_valid() && url
.SchemeIs(kChromeUIScheme
) &&
69 url
.DomainIs(kKaskoCrashDomain
, sizeof(kKaskoCrashDomain
) - 1) &&
70 url
.path() == kKaskoSendReport
);
76 void HandleKaskoDebugURL() {
78 // Signature of an enhanced crash reporting function.
79 typedef void(__cdecl
* ReportCrashWithProtobufPtr
)(EXCEPTION_POINTERS
*,
82 HMODULE exe_hmodule
= ::GetModuleHandle(NULL
);
83 ReportCrashWithProtobufPtr report_crash_with_protobuf
=
84 reinterpret_cast<ReportCrashWithProtobufPtr
>(
85 ::GetProcAddress(exe_hmodule
, "ReportCrashWithProtobuf"));
86 if (report_crash_with_protobuf
)
87 report_crash_with_protobuf(NULL
, "Invoked from debug url.");
95 bool IsAsanDebugURL(const GURL
& url
) {
97 if (!base::debug::IsBinaryInstrumented())
101 if (!(url
.is_valid() && url
.SchemeIs(kChromeUIScheme
) &&
102 url
.DomainIs(kAsanCrashDomain
, sizeof(kAsanCrashDomain
) - 1) &&
107 if (url
.path() == kAsanHeapOverflow
|| url
.path() == kAsanHeapUnderflow
||
108 url
.path() == kAsanUseAfterFree
) {
112 #if defined(SYZYASAN)
113 if (url
.path() == kAsanCorruptHeapBlock
|| url
.path() == kAsanCorruptHeap
)
120 bool HandleAsanDebugURL(const GURL
& url
) {
121 #if defined(SYZYASAN)
122 if (!base::debug::IsBinaryInstrumented())
125 if (url
.path() == kAsanCorruptHeapBlock
) {
126 base::debug::AsanCorruptHeapBlock();
128 } else if (url
.path() == kAsanCorruptHeap
) {
129 base::debug::AsanCorruptHeap();
134 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
135 if (url
.path() == kAsanHeapOverflow
) {
136 base::debug::AsanHeapOverflow();
137 } else if (url
.path() == kAsanHeapUnderflow
) {
138 base::debug::AsanHeapUnderflow();
139 } else if (url
.path() == kAsanUseAfterFree
) {
140 base::debug::AsanHeapUseAfterFree();
152 bool HandleDebugURL(const GURL
& url
, ui::PageTransition transition
) {
153 // Ensure that the user explicitly navigated to this URL, unless
154 // kEnableGpuBenchmarking is enabled by Telemetry.
155 bool is_telemetry_navigation
=
156 base::CommandLine::ForCurrentProcess()->HasSwitch(
157 cc::switches::kEnableGpuBenchmarking
) &&
158 (transition
& ui::PAGE_TRANSITION_TYPED
);
160 if (!(transition
& ui::PAGE_TRANSITION_FROM_ADDRESS_BAR
) &&
161 !is_telemetry_navigation
)
164 if (IsAsanDebugURL(url
))
165 return HandleAsanDebugURL(url
);
167 if (IsKaskoDebugURL(url
)) {
168 HandleKaskoDebugURL();
172 if (url
== GURL(kChromeUIBrowserCrashURL
)) {
173 // Induce an intentional crash in the browser process.
178 if (url
== GURL(kChromeUIGpuCleanURL
)) {
179 GpuProcessHostUIShim
* shim
= GpuProcessHostUIShim::GetOneInstance();
181 shim
->SimulateRemoveAllContext();
185 if (url
== GURL(kChromeUIGpuCrashURL
)) {
186 GpuProcessHostUIShim
* shim
= GpuProcessHostUIShim::GetOneInstance();
188 shim
->SimulateCrash();
192 if (url
== GURL(kChromeUIGpuHangURL
)) {
193 GpuProcessHostUIShim
* shim
= GpuProcessHostUIShim::GetOneInstance();
195 shim
->SimulateHang();
199 if (url
== GURL(kChromeUIPpapiFlashCrashURL
) ||
200 url
== GURL(kChromeUIPpapiFlashHangURL
)) {
201 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
202 base::Bind(&HandlePpapiFlashDebugURL
, url
));
209 bool IsRendererDebugURL(const GURL
& url
) {
213 if (url
.SchemeIs(url::kJavaScriptScheme
))
216 return url
== GURL(kChromeUICrashURL
) ||
217 url
== GURL(kChromeUIDumpURL
) ||
218 url
== GURL(kChromeUIKillURL
) ||
219 url
== GURL(kChromeUIHangURL
) ||
220 url
== GURL(kChromeUIShorthangURL
);
223 } // namespace content