Commit f39e5aff authored by palmer's avatar palmer Committed by Commit bot

Create net::FormatOriginForDisplay helper function.

net::FormatOriginForDisplay provides a canonical, concise, human-friendly
display for origins. It supports callers in any higher-layer module.

Based heavily on earlier work by dewittj and felt. Thanks!

BUG=402698
TBR=thakis,brettw

Review URL: https://codereview.chromium.org/1133943002

Cr-Commit-Position: refs/heads/master@{#330254}
parent 68208a4c
......@@ -15,10 +15,10 @@ namespace base {
// These convert between UTF-8, -16, and -32 strings. They are potentially slow,
// so avoid unnecessary conversions. The low-level versions return a boolean
// indicating whether the conversion was 100% valid. In this case, it will still
// do the best it can and put the result in the output buffer. The versions that
// return strings ignore this error and just return the best conversion
// possible.
// indicating whether the conversion was 100% valid. In case the conversion is
// not 100% valid, these functions will still do the best they can and put the
// result in the output buffer. The versions that return strings ignore this
// error and just return the best conversion possible.
BASE_EXPORT bool WideToUTF8(const wchar_t* src, size_t src_len,
std::string* output);
BASE_EXPORT std::string WideToUTF8(const std::wstring& wide);
......@@ -39,7 +39,7 @@ BASE_EXPORT bool UTF16ToUTF8(const char16* src, size_t src_len,
std::string* output);
BASE_EXPORT std::string UTF16ToUTF8(const string16& utf16);
// This converts an ASCII string, typically a hardcoded constant, to a UTF16
// This converts an ASCII string, typically a hardcoded constant, to a UTF-16
// string.
BASE_EXPORT string16 ASCIIToUTF16(const StringPiece& ascii);
......
......@@ -58,7 +58,7 @@ static const size_t kIPv6AddressSize = 16;
static const size_t kBluetoothAddressSize = 6;
#endif
// Nothing is ommitted.
// Nothing is omitted.
NET_EXPORT extern const FormatUrlType kFormatUrlOmitNothing;
// If set, any username and password are removed.
......@@ -71,13 +71,13 @@ NET_EXPORT extern const FormatUrlType kFormatUrlOmitHTTP;
// meaningful for non-file "standard" URLs.
NET_EXPORT extern const FormatUrlType kFormatUrlOmitTrailingSlashOnBareHostname;
// Convenience for omitting all unecessary types.
// Convenience for omitting all unnecessary types.
NET_EXPORT extern const FormatUrlType kFormatUrlOmitAll;
// Returns the number of explicitly allowed ports; for testing.
NET_EXPORT_PRIVATE extern size_t GetCountOfExplicitlyAllowedPorts();
// Splits an input of the form <host>[":"<port>] into its consitituent parts.
// Splits an input of the form <host>[":"<port>] into its constituent parts.
// Saves the result into |*host| and |*port|. If the input did not have
// the optional port, sets |*port| to -1.
// Returns true if the parsing was successful, false otherwise.
......@@ -105,13 +105,13 @@ NET_EXPORT std::string GetHostAndPort(const GURL& url);
NET_EXPORT_PRIVATE std::string GetHostAndOptionalPort(const GURL& url);
// Returns true if |hostname| contains a non-registerable or non-assignable
// domain name (eg: a gTLD that has not been assigned by IANA) or an IP address
// that falls in an IANA-reserved range.
// domain name (e.g.: a gTLD that has not been assigned by IANA) or an IP
// address that falls in an IANA-reserved range.
NET_EXPORT bool IsHostnameNonUnique(const std::string& hostname);
// Returns true if an IP address hostname is in a range reserved by the IANA.
// Works with both IPv4 and IPv6 addresses, and only compares against a given
// protocols's reserved ranges.
// protocol's reserved ranges.
NET_EXPORT bool IsIPAddressReserved(const IPAddressNumber& address);
// Convenience struct for when you need a |struct sockaddr|.
......@@ -339,6 +339,26 @@ inline base::string16 FormatUrl(const GURL& url, const std::string& languages) {
NULL, NULL, NULL);
}
// This is a convenience function for formatting a URL as an origin in a concise
// and human-friendly way. Use this instead of |FormatUrl| when the reader needs
// only to understand the origin (rather than the entire URL).
//
// - 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.
//
// Callers should only set |omit_scheme| to true when it is safe to do so: in
// contexts where the origin is known to be secure or is always secure by
// necessity. As examples:
//
// display = FormatOriginForDisplay(url, ..., url.SchemeIsCryptographic());
//
// display = FormatOriginForDisplay(url, ..., IsOriginSecure(url));
NET_EXPORT base::string16 FormatOriginForDisplay(const GURL& origin,
const std::string& languages,
bool omit_scheme);
// Returns whether FormatUrl() would strip a trailing slash from |url|, given a
// format flag including kFormatUrlOmitTrailingSlashOnBareHostname.
NET_EXPORT bool CanStripTrailingSlash(const GURL& url);
......@@ -441,7 +461,7 @@ NET_EXPORT_PRIVATE bool IsLocalhost(const std::string& host);
NET_EXPORT_PRIVATE bool IsLocalhostTLD(const std::string& host);
// Returns true if the url's host is a Google server. This should only be used
// Returns true if the URL's host is a Google server. This should only be used
// for histograms and shouldn't be used to affect behavior.
NET_EXPORT_PRIVATE bool HasGoogleHost(const GURL& url);
......
......@@ -797,7 +797,7 @@ base::string16 FormatUrlWithAdjustments(
// after stripping the prefix. The only thing necessary is to add an
// adjustment to reflect the stripped prefix.
adjustments->insert(adjustments->begin(),
base::OffsetAdjuster::Adjustment(0, kHTTPSize, 0));
base::OffsetAdjuster::Adjustment(0, kHTTPSize, 0));
if (prefix_end)
*prefix_end -= kHTTPSize;
......@@ -829,4 +829,46 @@ base::string16 FormatUrl(const GURL& url,
return result;
}
base::string16 FormatOriginForDisplay(const GURL& url,
const std::string& languages,
bool omit_scheme) {
if (!url.IsStandard())
return FormatUrl(url, languages);
if (url.SchemeIsFile()) {
// TODO(palmer): Determine whether to encode this policy in GURL::GetOrigin.
return (omit_scheme ? base::ASCIIToUTF16("")
: base::ASCIIToUTF16("file://")) +
base::UTF8ToUTF16(url.path());
}
if (url.SchemeIsFileSystem()) {
// TODO(palmer): Determine whether to encode this policy in GURL::GetOrigin.
const GURL inner_url(url.spec().substr(strlen("filesystem:")));
return base::ASCIIToUTF16("filesystem:") +
FormatOriginForDisplay(inner_url, languages, omit_scheme);
}
const GURL origin = url.GetOrigin();
const std::string& scheme = origin.scheme();
const std::string& host = origin.host();
if (scheme.empty() || host.empty())
return FormatUrl(url, languages);
base::string16 result;
if (!omit_scheme)
result = base::UTF8ToUTF16(scheme) + base::ASCIIToUTF16("://");
result += base::UTF8ToUTF16(host);
const int port = origin.IntPort();
const int default_port = url::DefaultPortForScheme(origin.scheme().c_str(),
origin.scheme().length());
if (origin.port().length() > 0 && port != 0 && port != default_port)
result += base::ASCIIToUTF16(":") + base::UTF8ToUTF16(origin.port());
return result;
}
} // namespace net
......@@ -364,6 +364,14 @@ struct UrlTestData {
size_t prefix_len;
};
struct OriginTestData {
const char* description;
const char* input;
const char* languages;
const bool omit_scheme;
const wchar_t* output;
};
// A helper for IDN*{Fast,Slow}.
// Append "::<language list>" to |expected| and |actual| to make it
// easy to tell which sub-case fails without debugging.
......@@ -1081,4 +1089,175 @@ TEST(NetUtilTest, FormatUrlWithOffsets) {
UnescapeRule::NORMAL, omit_all_offsets);
}
TEST(NetUtilTest, FormatOriginForDisplay) {
const OriginTestData tests[] = {
{"Empty URL", "", "", false, L""},
{"HTTP URL, no omit scheme",
"http://www.google.com/",
"",
false,
L"http://www.google.com"},
{"HTTP URL, omit scheme",
"http://www.google.com/",
"",
true,
L"www.google.com"},
{"HTTPS URL, no omit scheme",
"https://www.google.com/",
"",
false,
L"https://www.google.com"},
{"HTTPS URL, omit scheme",
"https://www.google.com/",
"",
true,
L"www.google.com"},
{"Standard HTTP port",
"http://www.google.com:80/",
"",
false,
L"http://www.google.com"},
{"Standard HTTPS port",
"https://www.google.com:443/",
"",
false,
L"https://www.google.com"},
{"Non-standard HTTP port",
"http://www.google.com:9000/",
"",
false,
L"http://www.google.com:9000"},
{"Non-standard HTTPS port",
"https://www.google.com:9000/",
"",
false,
L"https://www.google.com:9000"},
{"File URI, omit scheme",
"file:///usr/example/file.html",
"",
true,
L"/usr/example/file.html"},
{"File URI, no omit scheme",
"file:///usr/example/file.html",
"",
false,
L"file:///usr/example/file.html"},
{"File URI with hostname, omit scheme",
"file://localhost/usr/example/file.html",
"",
true,
L"/usr/example/file.html"},
{"File URI with hostname, no omit scheme",
"file://localhost/usr/example/file.html",
"",
false,
L"file:///usr/example/file.html"},
{"HTTP URL with path",
"http://www.google.com/test.html",
"",
false,
L"http://www.google.com"},
{"HTTPS URL with path",
"https://www.google.com/test.html",
"",
false,
L"https://www.google.com"},
{"Unusual secure scheme (wss)",
"wss://www.google.com/",
"",
false,
L"wss://www.google.com"},
{"Unusual non-secure scheme (gopher)",
"gopher://www.google.com/",
"",
false,
L"gopher://www.google.com"},
{"Unlisted scheme (chrome)",
"chrome://version",
"",
false,
L"chrome://version"},
{"HTTP IP address",
"http://173.194.65.103",
"",
false,
L"http://173.194.65.103"},
{"HTTPS IP address",
"https://173.194.65.103",
"",
false,
L"https://173.194.65.103"},
{"HTTPS IP address, non-default port",
"https://173.194.65.103:8443",
"",
false,
L"https://173.194.65.103:8443"},
{"HTTPS IP address, omit scheme",
"https://173.194.65.103",
"",
true,
L"173.194.65.103"},
{"HTTP filesystem: URL with path",
"filesystem:http://www.google.com/temporary/test.html",
"",
false,
L"filesystem:http://www.google.com"},
{"HTTP filesystem: URL with path, omit scheme",
"filesystem:http://www.google.com/persistent/test.html",
"",
true,
L"filesystem:www.google.com"},
{"File filesystem: URL with path",
"filesystem:file://localhost/temporary/stuff/test.html?z=fun&goat=billy",
"",
false,
L"filesystem:file:///temporary/stuff/test.html"},
{"File filesystem: URL with path, omit scheme",
"filesystem:file://cyber.com/persistent/stuff/test.html?y=z#abc",
"",
true,
L"filesystem:/persistent/stuff/test.html"},
{"Invalid scheme 1",
"twelve://www.cyber.org/wow.php",
"",
false,
L"twelve://www.cyber.org/wow.php"},
{"Invalid scheme 2",
"://www.cyber.org/wow.php",
"",
false,
L"://www.cyber.org/wow.php"},
{"Invalid host 1",
"https://www.cyber../wow.php",
"",
false,
L"https://www.cyber.."},
{"Invalid host 2",
"https://www...cyber/wow.php",
"",
false,
L"https://www...cyber"},
{"Invalid port 1",
"https://173.194.65.103:000",
"",
false,
L"https://173.194.65.103"},
{"Invalid port 2",
"https://173.194.65.103:gruffle",
"",
false,
L"https://173.194.65.103:gruffle"},
{"Invalid port 3",
"https://173.194.65.103:/hello.aspx",
"",
false,
L"https://173.194.65.103"},
};
for (size_t i = 0; i < arraysize(tests); ++i) {
base::string16 formatted = FormatOriginForDisplay(
GURL(tests[i].input), tests[i].languages, tests[i].omit_scheme);
EXPECT_EQ(WideToUTF16(tests[i].output), formatted) << tests[i].description;
}
}
} // namespace net
......@@ -198,6 +198,10 @@ class URL_EXPORT GURL {
// scheme. Standard schemes have an authority and a path section. This
// includes file: and filesystem:, which some callers may want to filter out
// explicitly by calling SchemeIsFile[System].
//
// TODO(palmer): Determine whether GURL::IsStandard should return false for
// filesystem: URLs.
// https://code.google.com/p/chromium/issues/detail?id=487399
bool IsStandard() const;
// Returns true if the given parameter (should be lower-case ASCII to match
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment