blob: 854ffd73f802e9f584f7b476fff3fedfe091eb2c [file] [log] [blame]
// Copyright 2016 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/ui/toolbar/chrome_location_bar_model_delegate.h"
#include "base/check.h"
#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
#include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/search.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/ssl/security_state_tab_helper.h"
#include "chrome/browser/ui/login/login_tab_helper.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "components/google/core/common/google_util.h"
#include "components/offline_pages/buildflags/buildflags.h"
#include "components/omnibox/browser/autocomplete_input.h"
#include "components/omnibox/browser/omnibox_prefs.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "components/search/ntp_features.h"
#include "components/security_interstitials/content/security_interstitial_tab_helper.h"
#include "components/security_state/core/security_state.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h"
#include "extensions/common/constants.h"
#if !defined(OS_ANDROID)
#include "components/omnibox/browser/vector_icons.h" // nogncheck
#endif // !defined(OS_ANDROID)
#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
#include "chrome/browser/offline_pages/offline_page_utils.h"
#endif // BUILDFLAG(ENABLE_OFFLINE_PAGES)
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "extensions/browser/extension_registry.h"
// Id for extension that enables users to report sites to Safe Browsing.
const char kPreventElisionExtensionId[] = "jknemblkbdhdcpllfgbfekkdciegfboi";
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
ChromeLocationBarModelDelegate::ChromeLocationBarModelDelegate() {}
ChromeLocationBarModelDelegate::~ChromeLocationBarModelDelegate() {}
content::NavigationEntry* ChromeLocationBarModelDelegate::GetNavigationEntry()
const {
content::NavigationController* controller = GetNavigationController();
return controller ? controller->GetVisibleEntry() : nullptr;
}
std::u16string
ChromeLocationBarModelDelegate::FormattedStringWithEquivalentMeaning(
const GURL& url,
const std::u16string& formatted_url) const {
return AutocompleteInput::FormattedStringWithEquivalentMeaning(
url, formatted_url, ChromeAutocompleteSchemeClassifier(GetProfile()),
nullptr);
}
bool ChromeLocationBarModelDelegate::GetURL(GURL* url) const {
DCHECK(url);
content::NavigationEntry* entry = GetNavigationEntry();
if (!entry)
return false;
*url = entry->GetVirtualURL();
return true;
}
bool ChromeLocationBarModelDelegate::ShouldPreventElision() {
if (GetElisionConfig() != ELISION_CONFIG_DEFAULT) {
return true;
}
return false;
}
bool ChromeLocationBarModelDelegate::ShouldDisplayURL() const {
// Note: The order here is important.
// - The WebUI test must come before the extension scheme test because there
// can be WebUIs that have extension schemes (e.g. the bookmark manager). In
// that case, we should prefer what the WebUI instance says.
// - The view-source test must come before the NTP test because of the case
// of view-source:chrome://newtab, which should display its URL despite what
// chrome://newtab says.
content::NavigationEntry* entry = GetNavigationEntry();
if (!entry)
return true;
security_interstitials::SecurityInterstitialTabHelper*
security_interstitial_tab_helper =
security_interstitials::SecurityInterstitialTabHelper::
FromWebContents(GetActiveWebContents());
if (security_interstitial_tab_helper &&
security_interstitial_tab_helper->IsDisplayingInterstitial())
return security_interstitial_tab_helper->ShouldDisplayURL();
LoginTabHelper* login_tab_helper =
LoginTabHelper::FromWebContents(GetActiveWebContents());
if (login_tab_helper && login_tab_helper->IsShowingPrompt())
return login_tab_helper->ShouldDisplayURL();
if (entry->IsViewSourceMode())
return true;
const auto is_ntp = [](const GURL& url) {
return url.SchemeIs(content::kChromeUIScheme) &&
url.host() == chrome::kChromeUINewTabHost;
};
GURL url = entry->GetURL();
if (is_ntp(entry->GetVirtualURL()) || is_ntp(url))
return false;
Profile* profile = GetProfile();
return !profile || !search::IsInstantNTPURL(url, profile);
}
security_state::SecurityLevel ChromeLocationBarModelDelegate::GetSecurityLevel()
const {
content::WebContents* web_contents = GetActiveWebContents();
// If there is no active WebContents (which can happen during toolbar
// initialization), assume no security style.
if (!web_contents) {
return security_state::NONE;
}
auto* helper = SecurityStateTabHelper::FromWebContents(web_contents);
return helper->GetSecurityLevel();
}
std::unique_ptr<security_state::VisibleSecurityState>
ChromeLocationBarModelDelegate::GetVisibleSecurityState() const {
content::WebContents* web_contents = GetActiveWebContents();
// If there is no active WebContents (which can happen during toolbar
// initialization), assume no security info.
if (!web_contents) {
return std::make_unique<security_state::VisibleSecurityState>();
}
auto* helper = SecurityStateTabHelper::FromWebContents(web_contents);
return helper->GetVisibleSecurityState();
}
scoped_refptr<net::X509Certificate>
ChromeLocationBarModelDelegate::GetCertificate() const {
content::NavigationEntry* entry = GetNavigationEntry();
if (!entry)
return scoped_refptr<net::X509Certificate>();
return entry->GetSSL().certificate;
}
const gfx::VectorIcon* ChromeLocationBarModelDelegate::GetVectorIconOverride()
const {
#if !defined(OS_ANDROID)
GURL url;
GetURL(&url);
if (url.SchemeIs(content::kChromeUIScheme))
return &omnibox::kProductIcon;
if (url.SchemeIs(extensions::kExtensionScheme))
return &omnibox::kExtensionAppIcon;
#endif
return nullptr;
}
bool ChromeLocationBarModelDelegate::IsOfflinePage() const {
#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
content::WebContents* web_contents = GetActiveWebContents();
return web_contents &&
offline_pages::OfflinePageUtils::GetOfflinePageFromWebContents(
web_contents);
#else
return false;
#endif
}
bool ChromeLocationBarModelDelegate::IsNewTabPage() const {
content::NavigationEntry* const entry = GetNavigationEntry();
if (!entry)
return false;
Profile* const profile = GetProfile();
if (!profile)
return false;
if (!search::DefaultSearchProviderIsGoogle(profile))
return false;
GURL ntp_url(chrome::kChromeUINewTabPageURL);
return ntp_url.scheme_piece() == entry->GetURL().scheme_piece() &&
ntp_url.host_piece() == entry->GetURL().host_piece();
}
bool ChromeLocationBarModelDelegate::IsNewTabPageURL(const GURL& url) const {
return url.spec() == chrome::kChromeUINewTabURL;
}
bool ChromeLocationBarModelDelegate::IsHomePage(const GURL& url) const {
Profile* const profile = GetProfile();
if (!profile)
return false;
return url.spec() == profile->GetPrefs()->GetString(prefs::kHomePage);
}
content::NavigationController*
ChromeLocationBarModelDelegate::GetNavigationController() const {
// This |current_tab| can be null during the initialization of the toolbar
// during window creation (i.e. before any tabs have been added to the
// window).
content::WebContents* current_tab = GetActiveWebContents();
return current_tab ? &current_tab->GetController() : nullptr;
}
Profile* ChromeLocationBarModelDelegate::GetProfile() const {
content::NavigationController* controller = GetNavigationController();
return controller
? Profile::FromBrowserContext(controller->GetBrowserContext())
: nullptr;
}
ChromeLocationBarModelDelegate::ElisionConfig
ChromeLocationBarModelDelegate::GetElisionConfig() const {
Profile* const profile = GetProfile();
if (profile &&
profile->GetPrefs()->GetBoolean(omnibox::kPreventUrlElisionsInOmnibox)) {
return ELISION_CONFIG_TURNED_OFF_BY_PREF;
}
#if BUILDFLAG(ENABLE_EXTENSIONS)
if (profile && extensions::ExtensionRegistry::Get(profile)
->enabled_extensions()
.Contains(kPreventElisionExtensionId)) {
return ELISION_CONFIG_TURNED_OFF_BY_EXTENSION;
}
#endif
return ELISION_CONFIG_DEFAULT;
}
AutocompleteClassifier*
ChromeLocationBarModelDelegate::GetAutocompleteClassifier() {
Profile* const profile = GetProfile();
return profile ? AutocompleteClassifierFactory::GetForProfile(profile)
: nullptr;
}
TemplateURLService* ChromeLocationBarModelDelegate::GetTemplateURLService() {
Profile* const profile = GetProfile();
return profile ? TemplateURLServiceFactory::GetForProfile(profile) : nullptr;
}
// static
void ChromeLocationBarModelDelegate::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterBooleanPref(omnibox::kPreventUrlElisionsInOmnibox, false);
}