15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_about_handler.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/lifetime/application_lifetime.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_dialogs.h"
136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/url_fixer/url_fixer.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WillHandleBrowserAboutURL(GURL* url,
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               content::BrowserContext* browser_context) {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(msw): Eliminate "about:*" constants and literals from code and tests,
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //            then hopefully we can remove this forced fixup.
21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  *url = url_fixer::FixupURL(url->possibly_invalid_spec(), std::string());
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Check that about: URLs are fixed up to chrome: by url_fixer::FixupURL.
24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK((*url == GURL(url::kAboutBlankURL)) ||
25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)         !url->SchemeIs(url::kAboutScheme));
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Only handle chrome://foo/, url_fixer::FixupURL translates about:foo.
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!url->SchemeIs(content::kChromeUIScheme))
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string host(url->host());
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string path;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Replace about with chrome-urls.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host == chrome::kChromeUIAboutHost)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host = chrome::kChromeUIChromeURLsHost;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Replace cache with view-http-cache.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host == chrome::kChromeUICacheHost) {
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    host = content::kChromeUINetworkViewCacheHost;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Replace sync with sync-internals (for legacy reasons).
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (host == chrome::kChromeUISyncHost) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host = chrome::kChromeUISyncInternalsHost;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Redirect chrome://extensions.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (host == chrome::kChromeUIExtensionsHost) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host = chrome::kChromeUIUberHost;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path = chrome::kChromeUIExtensionsHost + url->path();
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Redirect chrome://settings/extensions (legacy URL).
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (host == chrome::kChromeUISettingsHost &&
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url->path() == std::string("/") + chrome::kExtensionsSubPage) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host = chrome::kChromeUIUberHost;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path = chrome::kChromeUIExtensionsHost;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Redirect chrome://history.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (host == chrome::kChromeUIHistoryHost) {
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_ANDROID)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // On Android, redirect directly to chrome://history-frame since
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // uber page is unsupported.
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    host = chrome::kChromeUIHistoryFrameHost;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host = chrome::kChromeUIUberHost;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    path = chrome::kChromeUIHistoryHost + url->path();
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Redirect chrome://settings
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (host == chrome::kChromeUISettingsHost) {
636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (::switches::AboutInSettingsEnabled()) {
646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      host = chrome::kChromeUISettingsFrameHost;
656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    } else {
666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      host = chrome::kChromeUIUberHost;
676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      path = chrome::kChromeUISettingsHost + url->path();
686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Redirect chrome://help
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (host == chrome::kChromeUIHelpHost) {
716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (::switches::AboutInSettingsEnabled()) {
726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      host = chrome::kChromeUISettingsFrameHost;
736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (url->path().empty() || url->path() == "/")
746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        path = chrome::kChromeUIHelpHost;
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    } else {
766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      host = chrome::kChromeUIUberHost;
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      path = chrome::kChromeUIHelpHost + url->path();
786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL::Replacements replacements;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  replacements.SetHostStr(host);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!path.empty())
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    replacements.SetPathStr(path);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *url = url->ReplaceComponents(replacements);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Having re-written the URL, make the chrome: handler process it.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HandleNonNavigationAboutURL(const GURL& url) {
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const std::string spec(url.spec());
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (LowerCaseEqualsASCII(spec, chrome::kChromeUIRestartURL)) {
95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Call AttemptRestart after chrome::Navigate() completes to avoid access of
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // gtk objects after they are destroyed by BrowserWindowGtk::Close().
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::MessageLoop::current()->PostTask(FROM_HERE,
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        base::Bind(&chrome::AttemptRestart));
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return true;
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else if (LowerCaseEqualsASCII(spec, chrome::kChromeUIQuitURL)) {
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::MessageLoop::current()->PostTask(FROM_HERE,
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        base::Bind(&chrome::AttemptExit));
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return true;
104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // chrome://ipc/ is currently buggy, so we disable it for official builds.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OFFICIAL_BUILD)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if (defined(OS_MACOSX) || defined(OS_WIN)) && defined(IPC_MESSAGE_LOG_ENABLED)
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (LowerCaseEqualsASCII(spec, chrome::kChromeUIIPCURL)) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Run the dialog. This will re-use the existing one if it's already up.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    chrome::ShowAboutIPCDialog();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OFFICIAL_BUILD
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
121