Home | History | Annotate | Download | only in toolbar
      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 
     32 namespace {
     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.
     38 int 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 
     84 OriginChipInfo::OriginChipInfo(
     85     extensions::IconImage::Observer* owner,
     86     Profile* profile)
     87     : owner_(owner),
     88       profile_(profile) {}
     89 
     90 OriginChipInfo::~OriginChipInfo() {}
     91 
     92 bool 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 
    153 base::string16 OriginChipInfo::Tooltip() const {
    154   return base::UTF8ToUTF16(displayed_url_.spec());
    155 }
    156 
    157 // static
    158 bool 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
    171 base::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