1// Copyright (c) 2011 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 "chrome/browser/browser_url_handler.h" 6 7#include "base/string_util.h" 8#include "chrome/browser/browser_about_handler.h" 9#include "chrome/browser/extensions/extension_web_ui.h" 10#include "chrome/browser/profiles/profile.h" 11#include "chrome/browser/ui/webui/chrome_web_ui_factory.h" 12#include "chrome/common/url_constants.h" 13#include "content/browser/webui/web_ui.h" 14#include "googleurl/src/gurl.h" 15 16// Handles rewriting view-source URLs for what we'll actually load. 17static bool HandleViewSource(GURL* url, Profile* profile) { 18 if (url->SchemeIs(chrome::kViewSourceScheme)) { 19 // Load the inner URL instead. 20 *url = GURL(url->path()); 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 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(chrome::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. 49static bool ReverseViewSource(GURL* url, Profile* profile) { 50 // No action necessary if the URL is already view-source: 51 if (url->SchemeIs(chrome::kViewSourceScheme)) 52 return false; 53 54 url_canon::Replacements<char> repl; 55 repl.SetScheme(chrome::kViewSourceScheme, 56 url_parse::Component(0, strlen(chrome::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// Handles rewriting Web UI URLs. 64static bool HandleWebUI(GURL* url, Profile* profile) { 65 if (!ChromeWebUIFactory::GetInstance()->UseWebUIForURL(profile, *url)) 66 return false; 67 68 // Special case the new tab page. In older versions of Chrome, the new tab 69 // page was hosted at chrome-internal:<blah>. This might be in people's saved 70 // sessions or bookmarks, so we say any URL with that scheme triggers the new 71 // tab page. 72 if (url->SchemeIs(chrome::kChromeInternalScheme)) { 73 // Rewrite it with the proper new tab URL. 74 *url = GURL(chrome::kChromeUINewTabURL); 75 } 76 77 return true; 78} 79 80std::vector<BrowserURLHandler::HandlerPair> BrowserURLHandler::url_handlers_; 81 82// static 83void BrowserURLHandler::InitURLHandlers() { 84 if (!url_handlers_.empty()) 85 return; 86 87 // Visual Studio 2010 has problems converting NULL to the null pointer for 88 // std::pair. See http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair 89 // It will work if we pass nullptr. 90#if defined(_MSC_VER) && _MSC_VER >= 1600 91 URLHandler null_handler = nullptr; 92#else 93 URLHandler null_handler = NULL; 94#endif 95 96 // Add the default URL handlers. 97 url_handlers_.push_back( 98 HandlerPair(&ExtensionWebUI::HandleChromeURLOverride, null_handler)); 99 // about: 100 url_handlers_.push_back(HandlerPair(&WillHandleBrowserAboutURL, 101 null_handler)); 102 // chrome: & friends. 103 url_handlers_.push_back(HandlerPair(&HandleWebUI, null_handler)); 104 // view-source: 105 url_handlers_.push_back(HandlerPair(&HandleViewSource, &ReverseViewSource)); 106} 107 108// static 109void BrowserURLHandler::RewriteURLIfNecessary(GURL* url, Profile* profile, 110 bool* reverse_on_redirect) { 111 if (url_handlers_.empty()) 112 InitURLHandlers(); 113 for (size_t i = 0; i < url_handlers_.size(); ++i) { 114 if ((*url_handlers_[i].first)(url, profile)) { 115 *reverse_on_redirect = (url_handlers_[i].second != NULL); 116 return; 117 } 118 } 119} 120 121// static 122bool BrowserURLHandler::ReverseURLRewrite( 123 GURL* url, const GURL& original, Profile* profile) { 124 for (size_t i = 0; i < url_handlers_.size(); ++i) { 125 GURL test_url(original); 126 if ((*url_handlers_[i].first)(&test_url, profile)) { 127 if (url_handlers_[i].second) 128 return (*url_handlers_[i].second)(url, profile); 129 else 130 return false; 131 } 132 } 133 return false; 134} 135