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. 17 static 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. 49 static 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. 64 static 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 80 std::vector<BrowserURLHandler::HandlerPair> BrowserURLHandler::url_handlers_; 81 82 // static 83 void 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 109 void 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 122 bool 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