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