diff options
author | palmer <palmer@chromium.org> | 2015-06-03 16:50:43 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-06-03 23:51:15 +0000 |
commit | d72cc48699ed600c26911b0061f44aa9cfc39e62 (patch) | |
tree | 8de3e4fcc2b0b1d08b3174c3f3e13ff2471fe96a | |
parent | 44417446b0c1a0081d4fe45bef0cd840e046fc83 (diff) | |
download | chromium_src-d72cc48699ed600c26911b0061f44aa9cfc39e62.zip chromium_src-d72cc48699ed600c26911b0061f44aa9cfc39e62.tar.gz chromium_src-d72cc48699ed600c26911b0061f44aa9cfc39e62.tar.bz2 |
Create FormatUrlForSecurityDisplay helper function.
FormatUrlForSecurityDisplay provides a canonical, concise, human-friendly
display for origins.
Based heavily on earlier work by dewittj and felt. Thanks!
BUG=402698
Review URL: https://codereview.chromium.org/1147363005
Cr-Commit-Position: refs/heads/master@{#332736}
-rw-r--r-- | chrome/browser/ui/content_settings/content_setting_bubble_model.cc | 19 | ||||
-rw-r--r-- | chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc | 29 | ||||
-rw-r--r-- | chrome/browser/ui/elide_url.cc | 43 | ||||
-rw-r--r-- | chrome/browser/ui/elide_url.h | 16 | ||||
-rw-r--r-- | chrome/browser/ui/elide_url_unittest.cc | 119 |
5 files changed, 206 insertions, 20 deletions
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc index bdc7df7..9c16972 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc @@ -21,6 +21,7 @@ #include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/collected_cookies_infobar_delegate.h" #include "chrome/browser/ui/content_settings/content_setting_bubble_model_delegate.h" +#include "chrome/browser/ui/elide_url.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/render_messages.h" @@ -38,7 +39,6 @@ #include "content/public/common/origin_util.h" #include "grit/components_strings.h" #include "grit/theme_resources.h" -#include "net/base/net_util.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/resources/grit/ui_resources.h" @@ -274,12 +274,8 @@ bool ContentSettingSingleRadioGroup::settings_changed() const { // content type and setting the default value based on the content setting. void ContentSettingSingleRadioGroup::SetRadioGroup() { GURL url = web_contents()->GetURL(); - base::string16 display_host; - net::AppendFormattedHost( - url, - profile()->GetPrefs()->GetString(prefs::kAcceptLanguages), - &display_host); - + base::string16 display_host = FormatUrlForSecurityDisplay( + url, profile()->GetPrefs()->GetString(prefs::kAcceptLanguages)); if (display_host.empty()) display_host = base::ASCIIToUTF16(url.spec()); @@ -558,7 +554,7 @@ ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel( ->GetBlockedPopupRequests(); for (const std::pair<int32, GURL>& blocked_popup : blocked_popups) { std::string title(blocked_popup.second.spec()); - // The popup may not have a valid URL. + // The pop-up may not have a valid URL. if (title.empty()) title = l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE); ListItem popup_item(ui::ResourceBundle::GetSharedInstance().GetImageNamed( @@ -685,11 +681,8 @@ void ContentSettingMediaStreamBubbleModel::SetRadioGroup() { RadioGroup radio_group; radio_group.url = url; - base::string16 display_host_utf16; - net::AppendFormattedHost( - url, - profile()->GetPrefs()->GetString(prefs::kAcceptLanguages), - &display_host_utf16); + base::string16 display_host_utf16 = FormatUrlForSecurityDisplay( + url, profile()->GetPrefs()->GetString(prefs::kAcceptLanguages)); std::string display_host(base::UTF16ToUTF8(display_host_utf16)); if (display_host.empty()) display_host = url.spec(); diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc index df3602d..961332f 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc @@ -13,6 +13,7 @@ #include "chrome/browser/media/media_stream_capture_indicator.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h" +#include "chrome/browser/ui/elide_url.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" @@ -153,7 +154,9 @@ TEST_F(ContentSettingBubbleModelTest, MediastreamMicAndCamera) { EXPECT_EQ(bubble_content.radio_group.radio_items[0], l10n_util::GetStringFUTF8( IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION, - base::UTF8ToUTF16(request_host))); + FormatUrlForSecurityDisplay(security_origin, + profile()->GetPrefs()->GetString( + prefs::kAcceptLanguages)))); EXPECT_EQ(bubble_content.radio_group.radio_items[1], l10n_util::GetStringUTF8( IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK)); @@ -536,7 +539,9 @@ TEST_F(ContentSettingBubbleModelTest, MediastreamMic) { EXPECT_EQ(bubble_content.radio_group.radio_items[0], l10n_util::GetStringFUTF8( IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION, - base::UTF8ToUTF16(request_host))); + FormatUrlForSecurityDisplay(security_origin, + profile()->GetPrefs()->GetString( + prefs::kAcceptLanguages)))); EXPECT_EQ(bubble_content.radio_group.radio_items[1], l10n_util::GetStringUTF8( IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK)); @@ -568,7 +573,9 @@ TEST_F(ContentSettingBubbleModelTest, MediastreamMic) { EXPECT_EQ(new_bubble_content.radio_group.radio_items[0], l10n_util::GetStringFUTF8( IDS_BLOCKED_MEDIASTREAM_MIC_ASK, - base::UTF8ToUTF16(request_host))); + FormatUrlForSecurityDisplay(security_origin, + profile()->GetPrefs()->GetString( + prefs::kAcceptLanguages)))); EXPECT_EQ(new_bubble_content.radio_group.radio_items[1], l10n_util::GetStringUTF8( IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION)); @@ -611,7 +618,9 @@ TEST_F(ContentSettingBubbleModelTest, MediastreamCamera) { EXPECT_EQ(bubble_content.radio_group.radio_items[0], l10n_util::GetStringFUTF8( IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION, - base::UTF8ToUTF16(request_host))); + FormatUrlForSecurityDisplay(security_origin, + profile()->GetPrefs()->GetString( + prefs::kAcceptLanguages)))); EXPECT_EQ(bubble_content.radio_group.radio_items[1], l10n_util::GetStringUTF8( IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK)); @@ -643,7 +652,9 @@ TEST_F(ContentSettingBubbleModelTest, MediastreamCamera) { EXPECT_EQ(new_bubble_content.radio_group.radio_items[0], l10n_util::GetStringFUTF8( IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK, - base::UTF8ToUTF16(request_host))); + FormatUrlForSecurityDisplay(security_origin, + profile()->GetPrefs()->GetString( + prefs::kAcceptLanguages)))); EXPECT_EQ(new_bubble_content.radio_group.radio_items[1], l10n_util::GetStringUTF8( IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION)); @@ -688,7 +699,9 @@ TEST_F(ContentSettingBubbleModelTest, AccumulateMediastreamMicAndCamera) { EXPECT_EQ(bubble_content.radio_group.radio_items[0], l10n_util::GetStringFUTF8( IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION, - base::UTF8ToUTF16(request_host))); + FormatUrlForSecurityDisplay(security_origin, + profile()->GetPrefs()->GetString( + prefs::kAcceptLanguages)))); EXPECT_EQ(bubble_content.radio_group.radio_items[1], l10n_util::GetStringUTF8( IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK)); @@ -718,7 +731,9 @@ TEST_F(ContentSettingBubbleModelTest, AccumulateMediastreamMicAndCamera) { EXPECT_EQ(new_bubble_content.radio_group.radio_items[0], l10n_util::GetStringFUTF8( IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION, - base::UTF8ToUTF16(request_host))); + FormatUrlForSecurityDisplay(security_origin, + profile()->GetPrefs()->GetString( + prefs::kAcceptLanguages)))); EXPECT_EQ(new_bubble_content.radio_group.radio_items[1], l10n_util::GetStringUTF8( IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK)); diff --git a/chrome/browser/ui/elide_url.cc b/chrome/browser/ui/elide_url.cc index 88b393c..afa6d7a 100644 --- a/chrome/browser/ui/elide_url.cc +++ b/chrome/browser/ui/elide_url.cc @@ -13,6 +13,7 @@ #include "ui/gfx/text_elider.h" #include "ui/gfx/text_utils.h" #include "url/gurl.h" +#include "url/url_constants.h" using base::UTF8ToUTF16; using gfx::ElideText; @@ -301,3 +302,45 @@ base::string16 ElideHost(const GURL& url, url_subdomain, font_list, subdomain_width, gfx::ELIDE_HEAD); return elided_subdomain + url_domain; } + +base::string16 FormatUrlForSecurityDisplay(const GURL& url, + const std::string& languages) { + if (!url.is_valid() || url.is_empty() || !url.IsStandard()) + return net::FormatUrl(url, languages); + + const base::string16 colon(base::ASCIIToUTF16(":")); + const base::string16 scheme_separator( + base::ASCIIToUTF16(url::kStandardSchemeSeparator)); + + if (url.SchemeIsFile()) { + return base::ASCIIToUTF16(url::kFileScheme) + scheme_separator + + base::UTF8ToUTF16(url.path()); + } + + if (url.SchemeIsFileSystem()) { + const GURL* inner_url = url.inner_url(); + if (inner_url->SchemeIsFile()) { + return base::ASCIIToUTF16(url::kFileSystemScheme) + colon + + FormatUrlForSecurityDisplay(*inner_url, languages) + + base::UTF8ToUTF16(url.path()); + } + return base::ASCIIToUTF16(url::kFileSystemScheme) + colon + + FormatUrlForSecurityDisplay(*inner_url, languages); + } + + const GURL origin = url.GetOrigin(); + const std::string& scheme = origin.scheme(); + const std::string& host = origin.host(); + + base::string16 result = base::UTF8ToUTF16(scheme); + result += scheme_separator; + result += base::UTF8ToUTF16(host); + + const int port = origin.IntPort(); + const int default_port = url::DefaultPortForScheme(origin.scheme().c_str(), + origin.scheme().length()); + if (port != url::PORT_UNSPECIFIED && port != default_port) + result += colon + base::UTF8ToUTF16(origin.port()); + + return result; +} diff --git a/chrome/browser/ui/elide_url.h b/chrome/browser/ui/elide_url.h index bd5321a..b68267c 100644 --- a/chrome/browser/ui/elide_url.h +++ b/chrome/browser/ui/elide_url.h @@ -45,4 +45,20 @@ base::string16 ElideHost(const GURL& host_url, const gfx::FontList& font_list, float available_pixel_width); +// This is a convenience function for formatting a URL in a concise and +// human-friendly way, to help users make security-related decisions (or in +// other circumstances when people need to distinguish sites, origins, or +// otherwise-simplified URLs from each other). +// +// Internationalized domain names (IDN) may be presented in Unicode if +// |languages| accepts the Unicode representation (see |net::FormatUrl| for more +// details on the algorithm). +// +// - Omits the path for standard schemes, excepting file and filesystem. +// - Omits the port if it is the default for the scheme. +// +// Do not use this for URLs which will be parsed or sent to other applications. +base::string16 FormatUrlForSecurityDisplay(const GURL& origin, + const std::string& languages); + #endif // CHROME_BROWSER_UI_ELIDE_URL_H_ diff --git a/chrome/browser/ui/elide_url_unittest.cc b/chrome/browser/ui/elide_url_unittest.cc index a2cec9e..312d8ed 100644 --- a/chrome/browser/ui/elide_url_unittest.cc +++ b/chrome/browser/ui/elide_url_unittest.cc @@ -204,4 +204,123 @@ TEST(TextEliderTest, TestHostEliding) { ElideHost(GURL("http://foo.bar"), gfx::FontList(), 2)); } +TEST(TextEliderTest, FormatUrlForSecurityDisplay) { + struct OriginTestData { + const char* const description; + const char* const input; + const wchar_t* const output; + }; + + const OriginTestData tests[] = { + {"Empty URL", "", L""}, + {"HTTP URL", "http://www.google.com/", L"http://www.google.com"}, + {"HTTPS URL", "https://www.google.com/", L"https://www.google.com"}, + {"Standard HTTP port", + "http://www.google.com:80/", + L"http://www.google.com"}, + {"Standard HTTPS port", + "https://www.google.com:443/", + L"https://www.google.com"}, + {"Standard HTTP port, IDN Chinese", + "http://\xe4\xb8\xad\xe5\x9b\xbd.icom.museum:80", + L"http://xn--fiqs8s.icom.museum"}, + {"HTTP URL, IDN Hebrew (RTL)", + "http://" + "\xd7\x90\xd7\x99\xd7\xa7\xd7\x95\xd7\xb4\xd7\x9d." + "\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c.museum/", + L"http://xn--4dbklr2c8d.xn--4dbrk0ce.museum"}, + {"HTTP URL with query string, IDN Arabic (RTL)", + "http://\xd9\x85\xd8\xb5\xd8\xb1.icom.museum/foo.html?yes=no", + L"http://xn--wgbh1c.icom.museum"}, + {"Non-standard HTTP port", + "http://www.google.com:9000/", + L"http://www.google.com:9000"}, + {"Non-standard HTTPS port", + "https://www.google.com:9000/", + L"https://www.google.com:9000"}, + {"File URI", + "file:///usr/example/file.html", + L"file:///usr/example/file.html"}, + {"File URI with hostname", + "file://localhost/usr/example/file.html", + L"file:///usr/example/file.html"}, + {"UNC File URI 1", + "file:///CONTOSO/accounting/money.xls", + L"file:///CONTOSO/accounting/money.xls"}, + {"UNC File URI 2", + "file:///C:/Program%20Files/Music/Web%20Sys/main.html?REQUEST=RADIO", + L"file:///C:/Program%20Files/Music/Web%20Sys/main.html"}, + {"HTTP URL with path", + "http://www.google.com/test.html", + L"http://www.google.com"}, + {"HTTPS URL with path", + "https://www.google.com/test.html", + L"https://www.google.com"}, + {"Unusual secure scheme (wss)", + "wss://www.google.com/", + L"wss://www.google.com"}, + {"Unusual non-secure scheme (gopher)", + "gopher://www.google.com/", + L"gopher://www.google.com"}, + {"Unlisted scheme (chrome)", "chrome://version", L"chrome://version"}, + {"HTTP IP address", "http://173.194.65.103", L"http://173.194.65.103"}, + {"HTTPS IP address", "https://173.194.65.103", L"https://173.194.65.103"}, + {"HTTP IPv6 address", + "http://[FE80:0000:0000:0000:0202:B3FF:FE1E:8329]/", + L"http://[fe80::202:b3ff:fe1e:8329]"}, + {"HTTPS IPv6 address with port", + "https://[2001:db8:0:1]:443/", + L"https://[2001:db8:0:1]"}, + {"HTTPS IP address, non-default port", + "https://173.194.65.103:8443", + L"https://173.194.65.103:8443"}, + {"HTTP filesystem: URL with path", + "filesystem:http://www.google.com/temporary/test.html", + L"filesystem:http://www.google.com"}, + {"File filesystem: URL with path", + "filesystem:file://localhost/temporary/stuff/test.html?z=fun&goat=billy", + L"filesystem:file:///temporary/stuff/test.html"}, + {"Invalid scheme 1", + "twelve://www.cyber.org/wow.php", + L"twelve://www.cyber.org/wow.php"}, + {"Invalid scheme 2", + "://www.cyber.org/wow.php", + L"://www.cyber.org/wow.php"}, + {"Invalid host 1", "https://www.cyber../wow.php", L"https://www.cyber.."}, + {"Invalid host 2", "https://www...cyber/wow.php", L"https://www...cyber"}, + {"Invalid port 1", + "https://173.194.65.103:000", + L"https://173.194.65.103:0"}, + {"Invalid port 2", + "https://173.194.65.103:gruffle", + L"https://173.194.65.103:gruffle"}, + {"Invalid port 3", + "https://173.194.65.103:/hello.aspx", + L"https://173.194.65.103"}, + {"Trailing dot in DNS name", + "https://www.example.com./get/goat", + L"https://www.example.com."}, + {"Blob URL", + "blob:http%3A//www.html5rocks.com/4d4ff040-6d61-4446-86d3-13ca07ec9ab9", + L"blob:http%3A//www.html5rocks.com/" + L"4d4ff040-6d61-4446-86d3-13ca07ec9ab9"}, + }; + + const char languages[] = "zh-TW,en-US,en,am,ar-EG,ar"; + for (size_t i = 0; i < arraysize(tests); ++i) { + base::string16 formatted = + FormatUrlForSecurityDisplay(GURL(tests[i].input), std::string()); + EXPECT_EQ(base::WideToUTF16(tests[i].output), formatted) + << tests[i].description; + base::string16 formatted_with_languages = + FormatUrlForSecurityDisplay(GURL(tests[i].input), languages); + EXPECT_EQ(base::WideToUTF16(tests[i].output), formatted_with_languages) + << tests[i].description; + } + + base::string16 formatted = FormatUrlForSecurityDisplay(GURL(), std::string()); + EXPECT_EQ(base::string16(), formatted) + << "Explicitly test the 0-argument GURL constructor"; +} + } // namespace |