[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / content / browser / frame_host / debug_urls.cc
blob21e6bd25052a47ac999d5911b9225e265a9e3860
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 "base/synchronization/waitable_event.h"
18 #include "base/threading/thread_restrictions.h"
19 #include "cc/base/switches.h"
20 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/common/content_constants.h"
23 #include "content/public/common/url_constants.h"
24 #include "ppapi/proxy/ppapi_messages.h"
25 #include "url/gurl.h"
27 #if defined(ENABLE_PLUGINS)
28 #include "content/browser/ppapi_plugin_process_host.h"
29 #endif
31 namespace content {
33 namespace {
35 // Define the Asan debug URLs.
36 const char kAsanCrashDomain[] = "crash";
37 const char kAsanHeapOverflow[] = "/browser-heap-overflow";
38 const char kAsanHeapUnderflow[] = "/browser-heap-underflow";
39 const char kAsanUseAfterFree[] = "/browser-use-after-free";
40 #if defined(SYZYASAN)
41 const char kAsanCorruptHeapBlock[] = "/browser-corrupt-heap-block";
42 const char kAsanCorruptHeap[] = "/browser-corrupt-heap";
43 #endif
45 #if defined(KASKO)
46 // Define the Kasko debug URLs.
47 const char kKaskoCrashDomain[] = "kasko";
48 const char kKaskoSendReport[] = "/send-report";
49 #endif
51 void HandlePpapiFlashDebugURL(const GURL& url) {
52 #if defined(ENABLE_PLUGINS)
53 bool crash = url == GURL(kChromeUIPpapiFlashCrashURL);
55 std::vector<PpapiPluginProcessHost*> hosts;
56 PpapiPluginProcessHost::FindByName(
57 base::UTF8ToUTF16(kFlashPluginName), &hosts);
58 for (std::vector<PpapiPluginProcessHost*>::iterator iter = hosts.begin();
59 iter != hosts.end(); ++iter) {
60 if (crash)
61 (*iter)->Send(new PpapiMsg_Crash());
62 else
63 (*iter)->Send(new PpapiMsg_Hang());
65 #endif
68 bool IsKaskoDebugURL(const GURL& url) {
69 #if defined(KASKO)
70 return (url.is_valid() && url.SchemeIs(kChromeUIScheme) &&
71 url.DomainIs(kKaskoCrashDomain) &&
72 url.path() == kKaskoSendReport);
73 #else
74 return false;
75 #endif
78 void HandleKaskoDebugURL() {
79 #if defined(KASKO)
80 // Signature of an enhanced crash reporting function.
81 typedef void(__cdecl * ReportCrashWithProtobufPtr)(EXCEPTION_POINTERS*,
82 const char*);
84 HMODULE exe_hmodule = ::GetModuleHandle(NULL);
85 ReportCrashWithProtobufPtr report_crash_with_protobuf =
86 reinterpret_cast<ReportCrashWithProtobufPtr>(
87 ::GetProcAddress(exe_hmodule, "ReportCrashWithProtobuf"));
88 if (report_crash_with_protobuf)
89 report_crash_with_protobuf(NULL, "Invoked from debug url.");
90 else
91 NOTREACHED();
92 #else
93 NOTIMPLEMENTED();
94 #endif
97 bool IsAsanDebugURL(const GURL& url) {
98 #if defined(SYZYASAN)
99 if (!base::debug::IsBinaryInstrumented())
100 return false;
101 #endif
103 if (!(url.is_valid() && url.SchemeIs(kChromeUIScheme) &&
104 url.DomainIs(kAsanCrashDomain) &&
105 url.has_path())) {
106 return false;
109 if (url.path() == kAsanHeapOverflow || url.path() == kAsanHeapUnderflow ||
110 url.path() == kAsanUseAfterFree) {
111 return true;
114 #if defined(SYZYASAN)
115 if (url.path() == kAsanCorruptHeapBlock || url.path() == kAsanCorruptHeap)
116 return true;
117 #endif
119 return false;
122 bool HandleAsanDebugURL(const GURL& url) {
123 #if defined(SYZYASAN)
124 if (!base::debug::IsBinaryInstrumented())
125 return false;
127 if (url.path() == kAsanCorruptHeapBlock) {
128 base::debug::AsanCorruptHeapBlock();
129 return true;
130 } else if (url.path() == kAsanCorruptHeap) {
131 base::debug::AsanCorruptHeap();
132 return true;
134 #endif
136 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
137 if (url.path() == kAsanHeapOverflow) {
138 base::debug::AsanHeapOverflow();
139 } else if (url.path() == kAsanHeapUnderflow) {
140 base::debug::AsanHeapUnderflow();
141 } else if (url.path() == kAsanUseAfterFree) {
142 base::debug::AsanHeapUseAfterFree();
143 } else {
144 return false;
146 #endif
148 return true;
152 } // namespace
154 class ScopedAllowWaitForDebugURL {
155 private:
156 base::ThreadRestrictions::ScopedAllowWait wait;
159 bool HandleDebugURL(const GURL& url, ui::PageTransition transition) {
160 // Ensure that the user explicitly navigated to this URL, unless
161 // kEnableGpuBenchmarking is enabled by Telemetry.
162 bool is_telemetry_navigation =
163 base::CommandLine::ForCurrentProcess()->HasSwitch(
164 cc::switches::kEnableGpuBenchmarking) &&
165 (transition & ui::PAGE_TRANSITION_TYPED);
167 if (!(transition & ui::PAGE_TRANSITION_FROM_ADDRESS_BAR) &&
168 !is_telemetry_navigation)
169 return false;
171 if (IsAsanDebugURL(url))
172 return HandleAsanDebugURL(url);
174 if (IsKaskoDebugURL(url)) {
175 HandleKaskoDebugURL();
176 return true;
179 if (url == GURL(kChromeUIBrowserCrashURL)) {
180 // Induce an intentional crash in the browser process.
181 CHECK(false);
182 return true;
185 if (url == GURL(kChromeUIBrowserUIHang)) {
186 ScopedAllowWaitForDebugURL allow_wait;
187 base::WaitableEvent(false, false).Wait();
188 return true;
191 if (url == GURL(kChromeUIGpuCleanURL)) {
192 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
193 if (shim)
194 shim->SimulateRemoveAllContext();
195 return true;
198 if (url == GURL(kChromeUIGpuCrashURL)) {
199 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
200 if (shim)
201 shim->SimulateCrash();
202 return true;
205 if (url == GURL(kChromeUIGpuHangURL)) {
206 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
207 if (shim)
208 shim->SimulateHang();
209 return true;
212 if (url == GURL(kChromeUIPpapiFlashCrashURL) ||
213 url == GURL(kChromeUIPpapiFlashHangURL)) {
214 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
215 base::Bind(&HandlePpapiFlashDebugURL, url));
216 return true;
219 return false;
222 bool IsRendererDebugURL(const GURL& url) {
223 if (!url.is_valid())
224 return false;
226 if (url.SchemeIs(url::kJavaScriptScheme))
227 return true;
229 return url == GURL(kChromeUIBadCastCrashURL) ||
230 url == GURL(kChromeUICrashURL) ||
231 url == GURL(kChromeUIDumpURL) ||
232 url == GURL(kChromeUIKillURL) ||
233 url == GURL(kChromeUIHangURL) ||
234 url == GURL(kChromeUIShorthangURL);
237 } // namespace content