summaryrefslogtreecommitdiffstats
path: root/chrome/browser/browser_about_handler.cc
blob: ee99796afc67815d87a269b00c35631ae6fc885c (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
134
135
136
137
// Copyright (c) 2012 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_about_handler.h"

#include <string>

#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
#include "components/url_formatter/url_fixer.h"

bool FixupBrowserAboutURL(GURL* url,
                          content::BrowserContext* browser_context) {
  // Ensure that any cleanup done by FixupURL happens before the rewriting
  // phase that determines the virtual URL, by including it in an initial
  // URLHandler.  This prevents minor changes from producing a virtual URL,
  // which could lead to a URL spoof.
  *url = url_formatter::FixupURL(url->possibly_invalid_spec(), std::string());
  return true;
}

bool WillHandleBrowserAboutURL(GURL* url,
                               content::BrowserContext* browser_context) {
  // TODO(msw): Eliminate "about:*" constants and literals from code and tests,
  //            then hopefully we can remove this forced fixup.
  FixupBrowserAboutURL(url, browser_context);

  // Check that about: URLs are fixed up to chrome: by url_formatter::FixupURL.
  DCHECK((*url == GURL(url::kAboutBlankURL)) ||
         !url->SchemeIs(url::kAboutScheme));

  // Only handle chrome://foo/, url_formatter::FixupURL translates about:foo.
  if (!url->SchemeIs(content::kChromeUIScheme))
    return false;

  std::string host(url->host());
  std::string path;
  // Replace about with chrome-urls.
  if (host == chrome::kChromeUIAboutHost)
    host = chrome::kChromeUIChromeURLsHost;
  // Replace cache with view-http-cache.
  if (host == chrome::kChromeUICacheHost) {
    host = content::kChromeUINetworkViewCacheHost;
  // Replace sync with sync-internals (for legacy reasons).
  } else if (host == chrome::kChromeUISyncHost) {
    host = chrome::kChromeUISyncInternalsHost;
  // Redirect chrome://extensions.
  } else if (host == chrome::kChromeUIExtensionsHost) {
    // If the material design extensions page is enabled, it gets its own host.
    // Otherwise, it's handled by the uber settings page.
    if (::switches::MdExtensionsEnabled()) {
      host = chrome::kChromeUIExtensionsHost;
      path = url->path();
    } else {
      host = chrome::kChromeUIUberHost;
      path = chrome::kChromeUIExtensionsHost + url->path();
    }
  // Redirect chrome://settings/extensions (legacy URL).
  } else if (host == chrome::kChromeUISettingsHost &&
      url->path() == std::string("/") + chrome::kExtensionsSubPage) {
    host = chrome::kChromeUIUberHost;
    path = chrome::kChromeUIExtensionsHost;
  // Redirect chrome://history.
  } else if (host == chrome::kChromeUIHistoryHost) {
    // Material design history is handled on the top-level chrome://history
    // host.
    if (base::FeatureList::IsEnabled(features::kMaterialDesignHistoryFeature)) {
      host = chrome::kChromeUIHistoryHost;
      path = url->path();
    } else {
#if defined(OS_ANDROID)
      // On Android, redirect directly to chrome://history-frame since
      // uber page is unsupported.
      host = chrome::kChromeUIHistoryFrameHost;
#else
      host = chrome::kChromeUIUberHost;
      path = chrome::kChromeUIHistoryHost + url->path();
#endif
    }
  // Redirect chrome://settings
  } else if (host == chrome::kChromeUISettingsHost) {
    if (::switches::AboutInSettingsEnabled()) {
      host = chrome::kChromeUISettingsFrameHost;
    } else {
      host = chrome::kChromeUIUberHost;
      path = chrome::kChromeUISettingsHost + url->path();
    }
  // Redirect chrome://help
  } else if (host == chrome::kChromeUIHelpHost) {
    if (::switches::AboutInSettingsEnabled()) {
      host = chrome::kChromeUISettingsFrameHost;
      if (url->path().empty() || url->path() == "/")
        path = chrome::kChromeUIHelpHost;
    } else {
      host = chrome::kChromeUIUberHost;
      path = chrome::kChromeUIHelpHost + url->path();
    }
  }

  GURL::Replacements replacements;
  replacements.SetHostStr(host);
  if (!path.empty())
    replacements.SetPathStr(path);
  *url = url->ReplaceComponents(replacements);

  // Having re-written the URL, make the chrome: handler process it.
  return false;
}

bool HandleNonNavigationAboutURL(const GURL& url) {
  const std::string spec(url.spec());

  if (base::LowerCaseEqualsASCII(spec, chrome::kChromeUIRestartURL)) {
    // Call AttemptRestart after chrome::Navigate() completes to avoid access of
    // gtk objects after they are destroyed by BrowserWindowGtk::Close().
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::Bind(&chrome::AttemptRestart));
    return true;
  } else if (base::LowerCaseEqualsASCII(spec, chrome::kChromeUIQuitURL)) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::Bind(&chrome::AttemptExit));
    return true;
  }

  return false;
}