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