Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / frame_host / debug_urls.cc
blob04e134b6754e1b1f72195b72ce3c5941081746a1
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"
7 #if defined(SYZYASAN)
8 #include <windows.h>
9 #endif
11 #include <vector>
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"
23 #include "url/gurl.h"
25 #if defined(ENABLE_PLUGINS)
26 #include "content/browser/ppapi_plugin_process_host.h"
27 #endif
29 namespace content {
31 namespace {
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";
38 #if defined(SYZYASAN)
39 const char kAsanCorruptHeapBlock[] = "/browser-corrupt-heap-block";
40 const char kAsanCorruptHeap[] = "/browser-corrupt-heap";
41 #endif
43 #if defined(KASKO)
44 // Define the Kasko debug URLs.
45 const char kKaskoCrashDomain[] = "kasko";
46 const char kKaskoSendReport[] = "/send-report";
47 #endif
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) {
58 if (crash)
59 (*iter)->Send(new PpapiMsg_Crash());
60 else
61 (*iter)->Send(new PpapiMsg_Hang());
63 #endif
66 bool IsKaskoDebugURL(const GURL& url) {
67 #if defined(KASKO)
68 return (url.is_valid() && url.SchemeIs(kChromeUIScheme) &&
69 url.DomainIs(kKaskoCrashDomain, sizeof(kKaskoCrashDomain) - 1) &&
70 url.path() == kKaskoSendReport);
71 #else
72 return false;
73 #endif
76 void HandleKaskoDebugURL() {
77 #if defined(KASKO)
78 // Signature of an enhanced crash reporting function.
79 typedef void(__cdecl * ReportCrashWithProtobufPtr)(EXCEPTION_POINTERS*,
80 const char*);
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.");
88 else
89 NOTREACHED();
90 #else
91 NOTIMPLEMENTED();
92 #endif
95 bool IsAsanDebugURL(const GURL& url) {
96 #if defined(SYZYASAN)
97 if (!base::debug::IsBinaryInstrumented())
98 return false;
99 #endif
101 if (!(url.is_valid() && url.SchemeIs(kChromeUIScheme) &&
102 url.DomainIs(kAsanCrashDomain, sizeof(kAsanCrashDomain) - 1) &&
103 url.has_path())) {
104 return false;
107 if (url.path() == kAsanHeapOverflow || url.path() == kAsanHeapUnderflow ||
108 url.path() == kAsanUseAfterFree) {
109 return true;
112 #if defined(SYZYASAN)
113 if (url.path() == kAsanCorruptHeapBlock || url.path() == kAsanCorruptHeap)
114 return true;
115 #endif
117 return false;
120 bool HandleAsanDebugURL(const GURL& url) {
121 #if defined(SYZYASAN)
122 if (!base::debug::IsBinaryInstrumented())
123 return false;
125 if (url.path() == kAsanCorruptHeapBlock) {
126 base::debug::AsanCorruptHeapBlock();
127 return true;
128 } else if (url.path() == kAsanCorruptHeap) {
129 base::debug::AsanCorruptHeap();
130 return true;
132 #endif
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();
141 } else {
142 return false;
144 #endif
146 return true;
150 } // namespace
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)
162 return false;
164 if (IsAsanDebugURL(url))
165 return HandleAsanDebugURL(url);
167 if (IsKaskoDebugURL(url)) {
168 HandleKaskoDebugURL();
169 return true;
172 if (url == GURL(kChromeUIBrowserCrashURL)) {
173 // Induce an intentional crash in the browser process.
174 CHECK(false);
175 return true;
178 if (url == GURL(kChromeUIGpuCleanURL)) {
179 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
180 if (shim)
181 shim->SimulateRemoveAllContext();
182 return true;
185 if (url == GURL(kChromeUIGpuCrashURL)) {
186 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
187 if (shim)
188 shim->SimulateCrash();
189 return true;
192 if (url == GURL(kChromeUIGpuHangURL)) {
193 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
194 if (shim)
195 shim->SimulateHang();
196 return true;
199 if (url == GURL(kChromeUIPpapiFlashCrashURL) ||
200 url == GURL(kChromeUIPpapiFlashHangURL)) {
201 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
202 base::Bind(&HandlePpapiFlashDebugURL, url));
203 return true;
206 return false;
209 bool IsRendererDebugURL(const GURL& url) {
210 if (!url.is_valid())
211 return false;
213 if (url.SchemeIs(url::kJavaScriptScheme))
214 return true;
216 return url == GURL(kChromeUICrashURL) ||
217 url == GURL(kChromeUIDumpURL) ||
218 url == GURL(kChromeUIKillURL) ||
219 url == GURL(kChromeUIHangURL) ||
220 url == GURL(kChromeUIShorthangURL);
223 } // namespace content