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/frame_host/debug_urls.h" 9#include "content/browser/webui/web_ui_impl.h" 10#include "content/public/browser/content_browser_client.h" 11#include "content/public/common/url_constants.h" 12#include "url/gurl.h" 13 14namespace content { 15 16// Handles rewriting view-source URLs for what we'll actually load. 17static bool HandleViewSource(GURL* url, 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 default_allowed_sub_schemes[] = { 25 url::kHttpScheme, 26 url::kHttpsScheme, 27 url::kFtpScheme, 28 kChromeDevToolsScheme, 29 kChromeUIScheme, 30 url::kFileScheme, 31 url::kFileSystemScheme 32 }; 33 34 // Merge all the schemes for which view-source is allowed by default, with 35 // the WebUI schemes defined by the ContentBrowserClient. 36 std::vector<std::string> all_allowed_sub_schemes; 37 for (size_t i = 0; i < arraysize(default_allowed_sub_schemes); ++i) 38 all_allowed_sub_schemes.push_back(default_allowed_sub_schemes[i]); 39 GetContentClient()->browser()->GetAdditionalWebUISchemes( 40 &all_allowed_sub_schemes); 41 42 bool is_sub_scheme_allowed = false; 43 for (size_t i = 0; i < all_allowed_sub_schemes.size(); ++i) { 44 if (url->SchemeIs(all_allowed_sub_schemes[i].c_str())) { 45 is_sub_scheme_allowed = true; 46 break; 47 } 48 } 49 50 if (!is_sub_scheme_allowed) { 51 *url = GURL(url::kAboutBlankURL); 52 return false; 53 } 54 55 return true; 56 } 57 return false; 58} 59 60// Turns a non view-source URL into the corresponding view-source URL. 61static bool ReverseViewSource(GURL* url, BrowserContext* browser_context) { 62 // No action necessary if the URL is already view-source: 63 if (url->SchemeIs(kViewSourceScheme)) 64 return false; 65 66 url::Replacements<char> repl; 67 repl.SetScheme(kViewSourceScheme, 68 url::Component(0, strlen(kViewSourceScheme))); 69 repl.SetPath(url->spec().c_str(), url::Component(0, url->spec().size())); 70 *url = url->ReplaceComponents(repl); 71 return true; 72} 73 74static bool DebugURLHandler(GURL* url, BrowserContext* browser_context) { 75 // Circumvent processing URLs that the renderer process will handle. 76 return IsRendererDebugURL(*url); 77} 78 79// static 80BrowserURLHandler* BrowserURLHandler::GetInstance() { 81 return BrowserURLHandlerImpl::GetInstance(); 82} 83 84// static 85BrowserURLHandler::URLHandler BrowserURLHandler::null_handler() { 86 // Required for VS2010: http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair 87 return NULL; 88} 89 90// static 91BrowserURLHandlerImpl* BrowserURLHandlerImpl::GetInstance() { 92 return Singleton<BrowserURLHandlerImpl>::get(); 93} 94 95BrowserURLHandlerImpl::BrowserURLHandlerImpl() { 96 AddHandlerPair(&DebugURLHandler, BrowserURLHandlerImpl::null_handler()); 97 98 GetContentClient()->browser()->BrowserURLHandlerCreated(this); 99 100 // view-source: 101 AddHandlerPair(&HandleViewSource, &ReverseViewSource); 102} 103 104BrowserURLHandlerImpl::~BrowserURLHandlerImpl() { 105} 106 107void BrowserURLHandlerImpl::AddHandlerPair(URLHandler handler, 108 URLHandler reverse_handler) { 109 url_handlers_.push_back(HandlerPair(handler, reverse_handler)); 110} 111 112void BrowserURLHandlerImpl::RewriteURLIfNecessary( 113 GURL* url, 114 BrowserContext* browser_context, 115 bool* reverse_on_redirect) { 116 for (size_t i = 0; i < url_handlers_.size(); ++i) { 117 URLHandler handler = *url_handlers_[i].first; 118 if (handler && handler(url, browser_context)) { 119 *reverse_on_redirect = (url_handlers_[i].second != NULL); 120 return; 121 } 122 } 123} 124 125bool BrowserURLHandlerImpl::ReverseURLRewrite( 126 GURL* url, const GURL& original, BrowserContext* browser_context) { 127 for (size_t i = 0; i < url_handlers_.size(); ++i) { 128 URLHandler reverse_rewriter = *url_handlers_[i].second; 129 if (reverse_rewriter) { 130 GURL test_url(original); 131 URLHandler handler = *url_handlers_[i].first; 132 if (!handler) { 133 if (reverse_rewriter(url, browser_context)) 134 return true; 135 } else if (handler(&test_url, browser_context)) { 136 return reverse_rewriter(url, browser_context); 137 } 138 } 139 } 140 return false; 141} 142 143} // namespace content 144