debug_urls.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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.
4
5#include "content/browser/frame_host/debug_urls.h"
6
7#include <vector>
8
9#include "base/debug/asan_invalid_access.h"
10#include "base/debug/profiler.h"
11#include "base/strings/utf_string_conversions.h"
12#include "content/browser/gpu/gpu_process_host_ui_shim.h"
13#include "content/browser/ppapi_plugin_process_host.h"
14#include "content/public/browser/browser_thread.h"
15#include "content/public/common/content_constants.h"
16#include "content/public/common/url_constants.h"
17#include "ppapi/proxy/ppapi_messages.h"
18#include "url/gurl.h"
19
20namespace content {
21
22namespace {
23
24// Define the Asan debug URLs.
25const char kAsanCrashDomain[] = "crash";
26const char kAsanHeapOverflow[] = "/browser-heap-overflow";
27const char kAsanHeapUnderflow[] = "/browser-heap-underflow";
28const char kAsanUseAfterFree[] = "/browser-use-after-free";
29#if defined(SYZYASAN)
30const char kAsanCorruptHeapBlock[] = "/browser-corrupt-heap-block";
31const char kAsanCorruptHeap[] = "/browser-corrupt-heap";
32#endif
33
34void HandlePpapiFlashDebugURL(const GURL& url) {
35#if defined(ENABLE_PLUGINS)
36  bool crash = url == GURL(kChromeUIPpapiFlashCrashURL);
37
38  std::vector<PpapiPluginProcessHost*> hosts;
39  PpapiPluginProcessHost::FindByName(
40      base::UTF8ToUTF16(kFlashPluginName), &hosts);
41  for (std::vector<PpapiPluginProcessHost*>::iterator iter = hosts.begin();
42       iter != hosts.end(); ++iter) {
43    if (crash)
44      (*iter)->Send(new PpapiMsg_Crash());
45    else
46      (*iter)->Send(new PpapiMsg_Hang());
47  }
48#endif
49}
50
51bool IsAsanDebugURL(const GURL& url) {
52#if defined(SYZYASAN)
53  if (!base::debug::IsBinaryInstrumented())
54    return false;
55#endif
56
57  if (!(url.is_valid() && url.SchemeIs(kChromeUIScheme) &&
58        url.DomainIs(kAsanCrashDomain, sizeof(kAsanCrashDomain) - 1) &&
59        url.has_path())) {
60    return false;
61  }
62
63  if (url.path() == kAsanHeapOverflow || url.path() == kAsanHeapUnderflow ||
64      url.path() == kAsanUseAfterFree) {
65    return true;
66  }
67
68#if defined(SYZYASAN)
69  if (url.path() == kAsanCorruptHeapBlock || url.path() == kAsanCorruptHeap)
70    return true;
71#endif
72
73  return false;
74}
75
76bool HandleAsanDebugURL(const GURL& url) {
77#if defined(SYZYASAN)
78  if (!base::debug::IsBinaryInstrumented())
79    return false;
80
81  if (url.path() == kAsanCorruptHeapBlock) {
82    base::debug::AsanCorruptHeapBlock();
83    return true;
84  } else if (url.path() == kAsanCorruptHeap) {
85    base::debug::AsanCorruptHeap();
86    return true;
87  }
88#endif
89
90#if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
91  if (url.path() == kAsanHeapOverflow) {
92    base::debug::AsanHeapOverflow();
93  } else if (url.path() == kAsanHeapUnderflow) {
94    base::debug::AsanHeapUnderflow();
95  } else if (url.path() == kAsanUseAfterFree) {
96    base::debug::AsanHeapUseAfterFree();
97  } else {
98    return false;
99  }
100#endif
101
102  return true;
103}
104
105
106}  // namespace
107
108bool HandleDebugURL(const GURL& url, PageTransition transition) {
109  // Ensure that the user explicitly navigated to this URL.
110  if (!(transition & PAGE_TRANSITION_FROM_ADDRESS_BAR))
111    return false;
112
113  // NOTE: when you add handling of any URLs to this function, also
114  // update IsDebugURL, below.
115
116  if (IsAsanDebugURL(url))
117    return HandleAsanDebugURL(url);
118
119  if (url.host() == kChromeUIBrowserCrashHost) {
120    // Induce an intentional crash in the browser process.
121    CHECK(false);
122    return true;
123  }
124
125  if (url == GURL(kChromeUIGpuCleanURL)) {
126    GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
127    if (shim)
128      shim->SimulateRemoveAllContext();
129    return true;
130  }
131
132  if (url == GURL(kChromeUIGpuCrashURL)) {
133    GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
134    if (shim)
135      shim->SimulateCrash();
136    return true;
137  }
138
139  if (url == GURL(kChromeUIGpuHangURL)) {
140    GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance();
141    if (shim)
142      shim->SimulateHang();
143    return true;
144  }
145
146  if (url == GURL(kChromeUIPpapiFlashCrashURL) ||
147      url == GURL(kChromeUIPpapiFlashHangURL)) {
148    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
149                            base::Bind(&HandlePpapiFlashDebugURL, url));
150    return true;
151  }
152
153  return false;
154}
155
156bool IsDebugURL(const GURL& url) {
157  // NOTE: when you add any URLs to this list, also update
158  // HandleDebugURL, above.
159  return IsRendererDebugURL(url) || IsAsanDebugURL(url) ||
160      (url.is_valid() &&
161       (url.host() == kChromeUIBrowserCrashHost ||
162        url == GURL(kChromeUIGpuCleanURL) ||
163        url == GURL(kChromeUIGpuCrashURL) ||
164        url == GURL(kChromeUIGpuHangURL) ||
165        url == GURL(kChromeUIPpapiFlashCrashURL) ||
166        url == GURL(kChromeUIPpapiFlashHangURL)));
167}
168
169bool IsRendererDebugURL(const GURL& url) {
170  if (!url.is_valid())
171    return false;
172
173  if (url.SchemeIs(url::kJavaScriptScheme))
174    return true;
175
176  return url == GURL(kChromeUICrashURL) ||
177         url == GURL(kChromeUIKillURL) ||
178         url == GURL(kChromeUIHangURL) ||
179         url == GURL(kChromeUIShorthangURL);
180}
181
182}  // namespace content
183