summaryrefslogtreecommitdiffstats
path: root/chrome/browser/browser_url_handler.cc
blob: 4234ea278acecc86fbed9e52138156010ef282ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/browser_url_handler.h"

#include "base/string_util.h"
#include "chrome/browser/browser_about_handler.h"
#include "chrome/browser/extensions/extension_web_ui.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/url_constants.h"
#include "content/browser/webui/web_ui_factory.h"
#include "googleurl/src/gurl.h"

// Handles rewriting view-source URLs for what we'll actually load.
static bool HandleViewSource(GURL* url, Profile* profile) {
  if (url->SchemeIs(chrome::kViewSourceScheme)) {
    // Load the inner URL instead.
    *url = GURL(url->path());

    // Bug 26129: limit view-source to view the content and not any
    // other kind of 'active' url scheme like 'javascript' or 'data'.
    static const char* const allowed_sub_schemes[] = {
      chrome::kHttpScheme, chrome::kHttpsScheme, chrome::kFtpScheme,
      chrome::kChromeDevToolsScheme, chrome::kChromeUIScheme,
      chrome::kFileScheme
    };

    bool is_sub_scheme_allowed = false;
    for (size_t i = 0; i < arraysize(allowed_sub_schemes); i++) {
      if (url->SchemeIs(allowed_sub_schemes[i])) {
        is_sub_scheme_allowed = true;
        break;
      }
    }

    if (!is_sub_scheme_allowed) {
      *url = GURL(chrome::kAboutBlankURL);
      return false;
    }

    return true;
  }
  return false;
}

// Turns a non view-source URL into the corresponding view-source URL.
static bool ReverseViewSource(GURL* url, Profile* profile) {
  // No action necessary if the URL is already view-source:
  if (url->SchemeIs(chrome::kViewSourceScheme))
    return false;

  url_canon::Replacements<char> repl;
  repl.SetScheme(chrome::kViewSourceScheme,
      url_parse::Component(0, strlen(chrome::kViewSourceScheme)));
  repl.SetPath(url->spec().c_str(),
      url_parse::Component(0, url->spec().size()));
  *url = url->ReplaceComponents(repl);
  return true;
}

// Handles rewriting Web UI URLs.
static bool HandleWebUI(GURL* url, Profile* profile) {
  if (!WebUIFactory::UseWebUIForURL(profile, *url))
    return false;

  // Special case the new tab page. In older versions of Chrome, the new tab
  // page was hosted at chrome-internal:<blah>. This might be in people's saved
  // sessions or bookmarks, so we say any URL with that scheme triggers the new
  // tab page.
  if (url->SchemeIs(chrome::kChromeInternalScheme)) {
    // Rewrite it with the proper new tab URL.
    *url = GURL(chrome::kChromeUINewTabURL);
  }

  return true;
}

std::vector<BrowserURLHandler::HandlerPair> BrowserURLHandler::url_handlers_;

// static
void BrowserURLHandler::InitURLHandlers() {
  if (!url_handlers_.empty())
    return;

  // Visual Studio 2010 has problems converting NULL to the null pointer for
  // std::pair.  See http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair
  // It will work if we pass nullptr.
#if defined(_MSC_VER) && _MSC_VER >= 1600
  URLHandler null_handler = nullptr;
#else
  URLHandler null_handler = NULL;
#endif

  // Add the default URL handlers.
  url_handlers_.push_back(
      HandlerPair(&ExtensionWebUI::HandleChromeURLOverride, null_handler));
  // about:
  url_handlers_.push_back(HandlerPair(&WillHandleBrowserAboutURL,
                                      null_handler));
  // chrome: & friends.
  url_handlers_.push_back(HandlerPair(&HandleWebUI, null_handler));
  // view-source:
  url_handlers_.push_back(HandlerPair(&HandleViewSource, &ReverseViewSource));
}

// static
void BrowserURLHandler::RewriteURLIfNecessary(GURL* url, Profile* profile,
                                              bool* reverse_on_redirect) {
  if (url_handlers_.empty())
    InitURLHandlers();
  for (size_t i = 0; i < url_handlers_.size(); ++i) {
    if ((*url_handlers_[i].first)(url, profile)) {
      *reverse_on_redirect = (url_handlers_[i].second != NULL);
      return;
    }
  }
}

// static
bool BrowserURLHandler::ReverseURLRewrite(
    GURL* url, const GURL& original, Profile* profile) {
  for (size_t i = 0; i < url_handlers_.size(); ++i) {
    GURL test_url(original);
    if ((*url_handlers_[i].first)(&test_url, profile)) {
      if (url_handlers_[i].second)
        return (*url_handlers_[i].second)(url, profile);
      else
        return false;
    }
  }
  return false;
}