summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpalmer <palmer@chromium.org>2015-06-03 16:50:43 -0700
committerCommit bot <commit-bot@chromium.org>2015-06-03 23:51:15 +0000
commitd72cc48699ed600c26911b0061f44aa9cfc39e62 (patch)
tree8de3e4fcc2b0b1d08b3174c3f3e13ff2471fe96a
parent44417446b0c1a0081d4fe45bef0cd840e046fc83 (diff)
downloadchromium_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.cc19
-rw-r--r--chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc29
-rw-r--r--chrome/browser/ui/elide_url.cc43
-rw-r--r--chrome/browser/ui/elide_url.h16
-rw-r--r--chrome/browser/ui/elide_url_unittest.cc119
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