172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_url_handler.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_about_handler.h" 972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/extensions/extension_web_ui.h" 1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/webui/chrome_web_ui_factory.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/url_constants.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/webui/web_ui.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Handles rewriting view-source URLs for what we'll actually load. 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool HandleViewSource(GURL* url, Profile* profile) { 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url->SchemeIs(chrome::kViewSourceScheme)) { 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Load the inner URL instead. 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *url = GURL(url->path()); 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Bug 26129: limit view-source to view the content and not any 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // other kind of 'active' url scheme like 'javascript' or 'data'. 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const char* const allowed_sub_schemes[] = { 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chrome::kHttpScheme, chrome::kHttpsScheme, chrome::kFtpScheme, 26513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch chrome::kChromeDevToolsScheme, chrome::kChromeUIScheme, 27513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch chrome::kFileScheme 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool is_sub_scheme_allowed = false; 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < arraysize(allowed_sub_schemes); i++) { 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url->SchemeIs(allowed_sub_schemes[i])) { 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch is_sub_scheme_allowed = true; 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!is_sub_scheme_allowed) { 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *url = GURL(chrome::kAboutBlankURL); 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Turns a non view-source URL into the corresponding view-source URL. 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool ReverseViewSource(GURL* url, Profile* profile) { 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // No action necessary if the URL is already view-source: 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url->SchemeIs(chrome::kViewSourceScheme)) 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_canon::Replacements<char> repl; 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch repl.SetScheme(chrome::kViewSourceScheme, 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_parse::Component(0, strlen(chrome::kViewSourceScheme))); 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch repl.SetPath(url->spec().c_str(), 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_parse::Component(0, url->spec().size())); 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *url = url->ReplaceComponents(repl); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 6372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Handles rewriting Web UI URLs. 6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic bool HandleWebUI(GURL* url, Profile* profile) { 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!ChromeWebUIFactory::GetInstance()->UseWebUIForURL(profile, *url)) 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Special case the new tab page. In older versions of Chrome, the new tab 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // page was hosted at chrome-internal:<blah>. This might be in people's saved 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // sessions or bookmarks, so we say any URL with that scheme triggers the new 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // tab page. 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url->SchemeIs(chrome::kChromeInternalScheme)) { 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Rewrite it with the proper new tab URL. 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *url = GURL(chrome::kChromeUINewTabURL); 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::vector<BrowserURLHandler::HandlerPair> BrowserURLHandler::url_handlers_; 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserURLHandler::InitURLHandlers() { 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!url_handlers_.empty()) 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 8772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Visual Studio 2010 has problems converting NULL to the null pointer for 8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // std::pair. See http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair 8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // It will work if we pass nullptr. 9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(_MSC_VER) && _MSC_VER >= 1600 9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen URLHandler null_handler = nullptr; 9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#else 9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen URLHandler null_handler = NULL; 9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif 9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add the default URL handlers. 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_handlers_.push_back( 9872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen HandlerPair(&ExtensionWebUI::HandleChromeURLOverride, null_handler)); 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // about: 10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen url_handlers_.push_back(HandlerPair(&WillHandleBrowserAboutURL, 10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen null_handler)); 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // chrome: & friends. 10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen url_handlers_.push_back(HandlerPair(&HandleWebUI, null_handler)); 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // view-source: 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_handlers_.push_back(HandlerPair(&HandleViewSource, &ReverseViewSource)); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserURLHandler::RewriteURLIfNecessary(GURL* url, Profile* profile, 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool* reverse_on_redirect) { 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url_handlers_.empty()) 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch InitURLHandlers(); 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < url_handlers_.size(); ++i) { 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((*url_handlers_[i].first)(url, profile)) { 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *reverse_on_redirect = (url_handlers_[i].second != NULL); 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BrowserURLHandler::ReverseURLRewrite( 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL* url, const GURL& original, Profile* profile) { 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < url_handlers_.size(); ++i) { 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL test_url(original); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((*url_handlers_[i].first)(&test_url, profile)) { 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url_handlers_[i].second) 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (*url_handlers_[i].second)(url, profile); 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 135