Home | History | Annotate | Download | only in browser
      1 // Copyright (c) 2012 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/browser_url_handler_impl.h"
      6 
      7 #include "base/strings/string_util.h"
      8 #include "content/browser/webui/web_ui_impl.h"
      9 #include "content/public/browser/content_browser_client.h"
     10 #include "content/public/common/url_constants.h"
     11 #include "url/gurl.h"
     12 
     13 namespace content {
     14 
     15 // Handles rewriting view-source URLs for what we'll actually load.
     16 static bool HandleViewSource(GURL* url,
     17                              BrowserContext* browser_context) {
     18   if (url->SchemeIs(kViewSourceScheme)) {
     19     // Load the inner URL instead.
     20     *url = GURL(url->GetContent());
     21 
     22     // Bug 26129: limit view-source to view the content and not any
     23     // other kind of 'active' url scheme like 'javascript' or 'data'.
     24     static const char* const allowed_sub_schemes[] = {
     25       chrome::kHttpScheme, chrome::kHttpsScheme, chrome::kFtpScheme,
     26       chrome::kChromeDevToolsScheme, chrome::kChromeUIScheme,
     27       chrome::kFileScheme, chrome::kFileSystemScheme
     28     };
     29 
     30     bool is_sub_scheme_allowed = false;
     31     for (size_t i = 0; i < arraysize(allowed_sub_schemes); i++) {
     32       if (url->SchemeIs(allowed_sub_schemes[i])) {
     33         is_sub_scheme_allowed = true;
     34         break;
     35       }
     36     }
     37 
     38     if (!is_sub_scheme_allowed) {
     39       *url = GURL(kAboutBlankURL);
     40       return false;
     41     }
     42 
     43     return true;
     44   }
     45   return false;
     46 }
     47 
     48 // Turns a non view-source URL into the corresponding view-source URL.
     49 static bool ReverseViewSource(GURL* url, BrowserContext* browser_context) {
     50   // No action necessary if the URL is already view-source:
     51   if (url->SchemeIs(kViewSourceScheme))
     52     return false;
     53 
     54   url_canon::Replacements<char> repl;
     55   repl.SetScheme(kViewSourceScheme,
     56                  url_parse::Component(0, strlen(kViewSourceScheme)));
     57   repl.SetPath(url->spec().c_str(),
     58       url_parse::Component(0, url->spec().size()));
     59   *url = url->ReplaceComponents(repl);
     60   return true;
     61 }
     62 
     63 static bool HandleDebugUrl(GURL* url, BrowserContext* browser_context) {
     64   // Circumvent processing URLs that the renderer process will handle.
     65   return *url == GURL(kChromeUICrashURL) ||
     66          *url == GURL(kChromeUIHangURL) ||
     67          *url == GURL(kChromeUIKillURL) ||
     68          *url == GURL(kChromeUIShorthangURL);
     69 }
     70 
     71 // static
     72 BrowserURLHandler* BrowserURLHandler::GetInstance() {
     73   return BrowserURLHandlerImpl::GetInstance();
     74 }
     75 
     76 // static
     77 BrowserURLHandler::URLHandler BrowserURLHandler::null_handler() {
     78   // Required for VS2010: http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair
     79   return NULL;
     80 }
     81 
     82 // static
     83 BrowserURLHandlerImpl* BrowserURLHandlerImpl::GetInstance() {
     84   return Singleton<BrowserURLHandlerImpl>::get();
     85 }
     86 
     87 BrowserURLHandlerImpl::BrowserURLHandlerImpl() {
     88   AddHandlerPair(&HandleDebugUrl, BrowserURLHandlerImpl::null_handler());
     89 
     90   GetContentClient()->browser()->BrowserURLHandlerCreated(this);
     91 
     92   // view-source:
     93   AddHandlerPair(&HandleViewSource, &ReverseViewSource);
     94 }
     95 
     96 BrowserURLHandlerImpl::~BrowserURLHandlerImpl() {
     97 }
     98 
     99 void BrowserURLHandlerImpl::AddHandlerPair(URLHandler handler,
    100                                            URLHandler reverse_handler) {
    101   url_handlers_.push_back(HandlerPair(handler, reverse_handler));
    102 }
    103 
    104 void BrowserURLHandlerImpl::RewriteURLIfNecessary(
    105     GURL* url,
    106     BrowserContext* browser_context,
    107     bool* reverse_on_redirect) {
    108   for (size_t i = 0; i < url_handlers_.size(); ++i) {
    109     URLHandler handler = *url_handlers_[i].first;
    110     if (handler && handler(url, browser_context)) {
    111       *reverse_on_redirect = (url_handlers_[i].second != NULL);
    112       return;
    113     }
    114   }
    115 }
    116 
    117 bool BrowserURLHandlerImpl::ReverseURLRewrite(
    118     GURL* url, const GURL& original, BrowserContext* browser_context) {
    119   for (size_t i = 0; i < url_handlers_.size(); ++i) {
    120     URLHandler reverse_rewriter = *url_handlers_[i].second;
    121     if (reverse_rewriter) {
    122       GURL test_url(original);
    123       URLHandler handler = *url_handlers_[i].first;
    124       if (!handler) {
    125         if (reverse_rewriter(url, browser_context))
    126           return true;
    127       } else if (handler(&test_url, browser_context)) {
    128         return reverse_rewriter(url, browser_context);
    129       }
    130     }
    131   }
    132   return false;
    133 }
    134 
    135 }  // namespace content
    136