1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/location_bar/origin_chip_info.h" 6 7#include <string> 8 9#include "base/prefs/pref_service.h" 10#include "base/strings/string_util.h" 11#include "base/strings/utf_string_conversions.h" 12#include "chrome/browser/extensions/extension_service.h" 13#include "chrome/browser/extensions/extension_util.h" 14#include "chrome/browser/profiles/profile.h" 15#include "chrome/browser/safe_browsing/client_side_detection_host.h" 16#include "chrome/browser/safe_browsing/safe_browsing_tab_observer.h" 17#include "chrome/browser/ui/toolbar/toolbar_model.h" 18#include "chrome/common/extensions/extension_constants.h" 19#include "chrome/common/pref_names.h" 20#include "chrome/common/url_constants.h" 21#include "chrome/grit/chromium_strings.h" 22#include "chrome/grit/generated_resources.h" 23#include "content/public/browser/web_contents.h" 24#include "extensions/browser/extension_icon_image.h" 25#include "extensions/browser/extension_system.h" 26#include "extensions/common/constants.h" 27#include "extensions/common/manifest_handlers/icons_handler.h" 28#include "grit/components_strings.h" 29#include "grit/theme_resources.h" 30#include "net/base/net_util.h" 31#include "ui/base/l10n/l10n_util.h" 32#include "url/gurl.h" 33 34namespace { 35 36// For selected kChromeUIScheme and url::kAboutScheme, return the string 37// resource 38// number for the title of the page. If we don't have a specialized title, 39// returns -1. 40int StringForChromeHost(const GURL& url) { 41 DCHECK(url.is_empty() || url.SchemeIs(content::kChromeUIScheme)); 42 43 if (url.is_empty()) 44 return IDS_NEW_TAB_TITLE; 45 46 // TODO(gbillock): Just get the page title and special case exceptions? 47 std::string host = url.host(); 48 if (host == chrome::kChromeUIAppLauncherPageHost) 49 return IDS_APP_DEFAULT_PAGE_NAME; 50 if (host == chrome::kChromeUIBookmarksHost) 51 return IDS_BOOKMARK_MANAGER_TITLE; 52 if (host == chrome::kChromeUIComponentsHost) 53 return IDS_COMPONENTS_TITLE; 54 if (host == chrome::kChromeUICrashesHost) 55 return IDS_CRASHES_TITLE; 56#if defined(ENABLE_SERVICE_DISCOVERY) 57 if (host == chrome::kChromeUIDevicesHost) 58 return IDS_LOCAL_DISCOVERY_DEVICES_PAGE_TITLE; 59#endif // ENABLE_SERVICE_DISCOVERY 60 if (host == chrome::kChromeUIDownloadsHost) 61 return IDS_DOWNLOAD_TITLE; 62 if (host == chrome::kChromeUIExtensionsHost) 63 return IDS_MANAGE_EXTENSIONS_SETTING_WINDOWS_TITLE; 64 if (host == chrome::kChromeUIHelpHost) 65 return IDS_ABOUT_TITLE; 66 if (host == chrome::kChromeUIHistoryHost) 67 return IDS_HISTORY_TITLE; 68 if (host == chrome::kChromeUINewTabHost) 69 return IDS_NEW_TAB_TITLE; 70 if (host == chrome::kChromeUIPluginsHost) 71 return IDS_PLUGINS_TITLE; 72 if (host == chrome::kChromeUIPolicyHost) 73 return IDS_POLICY_TITLE; 74#if defined(ENABLE_FULL_PRINTING) 75 if (host == chrome::kChromeUIPrintHost) 76 return IDS_PRINT_PREVIEW_TITLE; 77#endif // ENABLE_FULL_PRINTING 78 if (host == chrome::kChromeUISettingsHost) 79 return IDS_SETTINGS_TITLE; 80 if (host == chrome::kChromeUIVersionHost) 81 return IDS_ABOUT_VERSION_TITLE; 82 83 return -1; 84} 85 86} // namespace 87 88OriginChipInfo::OriginChipInfo(extensions::IconImage::Observer* owner, 89 Profile* profile) 90 : owner_(owner), 91 profile_(profile), 92 security_level_(ToolbarModel::NONE), 93 is_url_malware_(false), 94 icon_(IDR_PRODUCT_LOGO_16) { 95} 96 97OriginChipInfo::~OriginChipInfo() { 98} 99 100bool OriginChipInfo::Update(const content::WebContents* web_contents, 101 const ToolbarModel* toolbar_model) { 102 GURL displayed_url = toolbar_model->GetURL(); 103 ToolbarModel::SecurityLevel security_level = 104 toolbar_model->GetSecurityLevel(true); 105 bool is_url_malware = OriginChip::IsMalware(displayed_url, web_contents); 106 107 if ((displayed_url_ == displayed_url) && 108 (security_level_ == security_level) && 109 (is_url_malware_ == is_url_malware)) 110 return false; 111 112 displayed_url_ = displayed_url; 113 security_level_ = security_level; 114 is_url_malware_ = is_url_malware; 115 116 label_ = OriginChip::LabelFromURLForProfile(displayed_url, profile_); 117 if (security_level_ == ToolbarModel::EV_SECURE) { 118 label_ = l10n_util::GetStringFUTF16(IDS_SITE_CHIP_EV_SSL_LABEL, 119 toolbar_model->GetEVCertName(), 120 label_); 121 } 122 123 124 if (displayed_url_.SchemeIs(extensions::kExtensionScheme)) { 125 const extensions::Extension* extension = 126 extensions::ExtensionSystem::Get(profile_)->extension_service()-> 127 extensions()->GetExtensionOrAppByURL(displayed_url_); 128 129 if (extension) { 130 icon_ = IDR_EXTENSIONS_FAVICON; 131 extension_icon_image_.reset( 132 new extensions::IconImage(profile_, 133 extension, 134 extensions::IconsInfo::GetIcons(extension), 135 extension_misc::EXTENSION_ICON_BITTY, 136 extensions::util::GetDefaultAppIcon(), 137 owner_)); 138 139 // Forces load of the image. 140 extension_icon_image_->image_skia().GetRepresentation(1.0f); 141 if (!extension_icon_image_->image_skia().image_reps().empty()) 142 owner_->OnExtensionIconImageChanged(extension_icon_image_.get()); 143 144 return true; 145 } 146 } 147 148 if (extension_icon_image_) { 149 extension_icon_image_.reset(); 150 owner_->OnExtensionIconImageChanged(NULL); 151 } 152 153 icon_ = (displayed_url_.is_empty() || 154 displayed_url_.SchemeIs(content::kChromeUIScheme)) ? 155 IDR_PRODUCT_LOGO_16 : 156 toolbar_model->GetIconForSecurityLevel(security_level_); 157 158 return true; 159} 160 161base::string16 OriginChipInfo::Tooltip() const { 162 return base::UTF8ToUTF16(displayed_url_.spec()); 163} 164 165// static 166bool OriginChip::IsMalware(const GURL& url, const content::WebContents* tab) { 167 DCHECK(tab); 168 169 if (tab->GetURL() != url) 170 return false; 171 172 const safe_browsing::SafeBrowsingTabObserver* sb_observer = 173 safe_browsing::SafeBrowsingTabObserver::FromWebContents(tab); 174 return sb_observer && sb_observer->DidPageReceiveSafeBrowsingMatch(); 175} 176 177// static 178base::string16 OriginChip::LabelFromURLForProfile(const GURL& provided_url, 179 Profile* profile) { 180 // First, strip view-source: if it appears. Note that GetContent removes 181 // "view-source:" but leaves the original scheme (http, https, ftp, etc). 182 GURL url(provided_url); 183 if (url.SchemeIs(content::kViewSourceScheme)) 184 url = GURL(url.GetContent()); 185 186 // About scheme pages. Currently all about: URLs other than about:blank 187 // redirect to chrome: URLs, so this only affects about:blank. 188 if (url.SchemeIs(url::kAboutScheme)) 189 return base::UTF8ToUTF16(url.spec()); 190 191 // Chrome built-in pages. 192 if (url.is_empty() || url.SchemeIs(content::kChromeUIScheme)) { 193 int string_ref = StringForChromeHost(url); 194 return l10n_util::GetStringUTF16( 195 (string_ref == -1) ? IDS_SHORT_PRODUCT_NAME : string_ref); 196 } 197 198 // For chrome-extension URLs, return the extension name. 199 if (url.SchemeIs(extensions::kExtensionScheme)) { 200 ExtensionService* service = 201 extensions::ExtensionSystem::Get(profile)->extension_service(); 202 const extensions::Extension* extension = 203 service->extensions()->GetExtensionOrAppByURL(url); 204 return extension ? 205 base::UTF8ToUTF16(extension->name()) : base::UTF8ToUTF16(url.host()); 206 } 207 208 if (url.SchemeIsHTTPOrHTTPS() || url.SchemeIs(url::kFtpScheme)) { 209 // See ToolbarModelImpl::GetText(). Does not pay attention to any user 210 // edits, and uses GetURL/net::FormatUrl -- We don't really care about 211 // length or the autocomplete parser. 212 // TODO(gbillock): This uses an algorithm very similar to GetText, which 213 // is probably too conservative. Try out just using a simpler mechanism of 214 // StripWWW() and IDNToUnicode(). 215 std::string languages; 216 if (profile) 217 languages = profile->GetPrefs()->GetString(prefs::kAcceptLanguages); 218 219 // TODO(macourteau): Extract the bits we care about from FormatUrl to 220 // format |url.host()| instead of this. 221 base::string16 formatted = net::FormatUrl(url.GetOrigin(), languages, 222 net::kFormatUrlOmitAll, net::UnescapeRule::NORMAL, NULL, NULL, NULL); 223 // Remove scheme, "www.", and trailing "/". 224 if (StartsWith(formatted, base::ASCIIToUTF16("http://"), false)) 225 formatted = formatted.substr(7); 226 else if (StartsWith(formatted, base::ASCIIToUTF16("https://"), false)) 227 formatted = formatted.substr(8); 228 else if (StartsWith(formatted, base::ASCIIToUTF16("ftp://"), false)) 229 formatted = formatted.substr(6); 230 if (StartsWith(formatted, base::ASCIIToUTF16("www."), false)) 231 formatted = formatted.substr(4); 232 if (EndsWith(formatted, base::ASCIIToUTF16("/"), false)) 233 formatted = formatted.substr(0, formatted.size() - 1); 234 return formatted; 235 } 236 237 // These internal-ish debugging-style schemes we don't expect users 238 // to see. In these cases, the site chip will display the first 239 // part of the full URL. 240 if (url.SchemeIs(chrome::kChromeNativeScheme) || 241 url.SchemeIs(url::kBlobScheme) || 242 url.SchemeIs(content::kChromeDevToolsScheme) || 243 url.SchemeIs(url::kDataScheme) || 244 url.SchemeIs(url::kFileScheme) || 245 url.SchemeIs(url::kFileSystemScheme) || 246 url.SchemeIs(content::kGuestScheme) || 247 url.SchemeIs(url::kJavaScriptScheme) || 248 url.SchemeIs(url::kMailToScheme) || 249 url.SchemeIs(content::kMetadataScheme) || 250 url.SchemeIs(content::kSwappedOutScheme)) { 251 std::string truncated_url; 252 base::TruncateUTF8ToByteSize(url.spec(), 1000, &truncated_url); 253 return base::UTF8ToUTF16(truncated_url); 254 } 255 256#if defined(OS_CHROMEOS) 257 if (url.SchemeIs(chrome::kCrosScheme) || 258 url.SchemeIs(chrome::kExternalFileScheme)) 259 return base::UTF8ToUTF16(url.spec()); 260#endif 261 262 // If all else fails, return the hostname. 263 return base::UTF8ToUTF16(url.host()); 264} 265