[GFX] Add hostname elider. Add ability to elide strings at the beginning.
[email protected]
Review URL: https://codereview.chromium.org/144513002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@248726 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/ui/elide_url.cc b/chrome/browser/ui/elide_url.cc
index 1ce9ce571..ba48aae64 100644
--- a/chrome/browser/ui/elide_url.cc
+++ b/chrome/browser/ui/elide_url.cc
@@ -21,6 +21,8 @@
namespace {
+const base::char16 kDot = '.';
+
// Build a path from the first |num_components| elements in |path_elements|.
// Prepends |path_prefix|, appends |filename|, inserts ellipsis if appropriate.
base::string16 BuildPathFromComponents(
@@ -67,6 +69,39 @@
return base::string16();
}
+// Splits the hostname in the |url| into sub-strings for the full hostname,
+// the domain (TLD+1), and the subdomain (everything leading the domain).
+void SplitHost(const GURL& url,
+ base::string16* url_host,
+ base::string16* url_domain,
+ base::string16* url_subdomain) {
+ // Get Host.
+ *url_host = UTF8ToUTF16(url.host());
+
+ // Get domain and registry information from the URL.
+ *url_domain = UTF8ToUTF16(
+ net::registry_controlled_domains::GetDomainAndRegistry(
+ url, net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES));
+ if (url_domain->empty())
+ *url_domain = *url_host;
+
+ // Add port if required.
+ if (!url.port().empty()) {
+ *url_host += UTF8ToUTF16(":" + url.port());
+ *url_domain += UTF8ToUTF16(":" + url.port());
+ }
+
+ // Get sub domain.
+ const size_t domain_start_index = url_host->find(*url_domain);
+ base::string16 kWwwPrefix = UTF8ToUTF16("www.");
+ if (domain_start_index != base::string16::npos)
+ *url_subdomain = url_host->substr(0, domain_start_index);
+ if ((*url_subdomain == kWwwPrefix || url_subdomain->empty() ||
+ url.SchemeIsFile())) {
+ url_subdomain->clear();
+ }
+}
+
} // namespace
// TODO(pkasting): http://crbug.com/77883 This whole function gets
@@ -109,32 +144,10 @@
return ElideText(url_string, font_list, available_pixel_width,
gfx::ELIDE_AT_END);
- // Get Host.
- base::string16 url_host = UTF8ToUTF16(url.host());
-
- // Get domain and registry information from the URL.
- base::string16 url_domain = UTF8ToUTF16(
- net::registry_controlled_domains::GetDomainAndRegistry(
- url, net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES));
- if (url_domain.empty())
- url_domain = url_host;
-
- // Add port if required.
- if (!url.port().empty()) {
- url_host += UTF8ToUTF16(":" + url.port());
- url_domain += UTF8ToUTF16(":" + url.port());
- }
-
- // Get sub domain.
+ base::string16 url_host;
+ base::string16 url_domain;
base::string16 url_subdomain;
- const size_t domain_start_index = url_host.find(url_domain);
- if (domain_start_index != base::string16::npos)
- url_subdomain = url_host.substr(0, domain_start_index);
- const base::string16 kWwwPrefix = UTF8ToUTF16("www.");
- if ((url_subdomain == kWwwPrefix || url_subdomain.empty() ||
- url.SchemeIsFile())) {
- url_subdomain.clear();
- }
+ SplitHost(url, &url_host, &url_domain, &url_subdomain);
// If this is a file type, the path is now defined as everything after ":".
// For example, "C:/aa/aa/bb", the path is "/aa/bb/cc". Interesting, the
@@ -265,3 +278,27 @@
gfx::ELIDE_AT_END);
}
+base::string16 ElideHost(const GURL& url,
+ const gfx::FontList& font_list,
+ float available_pixel_width) {
+ base::string16 url_host;
+ base::string16 url_domain;
+ base::string16 url_subdomain;
+ SplitHost(url, &url_host, &url_domain, &url_subdomain);
+
+ const float pixel_width_url_host = GetStringWidthF(url_host, font_list);
+ if (available_pixel_width >= pixel_width_url_host)
+ return url_host;
+
+ if (url_subdomain.empty())
+ return url_domain;
+
+ const float pixel_width_url_domain = GetStringWidthF(url_domain, font_list);
+ float subdomain_width = available_pixel_width - pixel_width_url_domain;
+ if (subdomain_width <= 0)
+ return base::string16(kEllipsisUTF16) + kDot + url_domain;
+
+ base::string16 elided_subdomain = ElideText(
+ url_subdomain, font_list, subdomain_width, gfx::ELIDE_AT_BEGINNING);
+ return elided_subdomain + url_domain;
+}
diff --git a/chrome/browser/ui/elide_url.h b/chrome/browser/ui/elide_url.h
index 4842281b..3bf6263f 100644
--- a/chrome/browser/ui/elide_url.h
+++ b/chrome/browser/ui/elide_url.h
@@ -36,4 +36,13 @@
float available_pixel_width,
const std::string& languages);
+// This function takes a GURL object and elides the host to fit within
+// the given width. The function will never elide past the TLD+1 point,
+// but after that, will leading-elide the domain name to fit the width.
+// Example: http://sub.domain.com ---> "...domain.com", or "s...domain.com"
+// depending on the width.
+base::string16 ElideHost(const GURL& host_url,
+ const gfx::FontList& font_list,
+ float available_pixel_width);
+
#endif // CHROME_BROWSER_UI_ELIDE_URL_H_
diff --git a/chrome/browser/ui/tests/elide_url_unittest.cc b/chrome/browser/ui/tests/elide_url_unittest.cc
index 8d32109..56826ead 100644
--- a/chrome/browser/ui/tests/elide_url_unittest.cc
+++ b/chrome/browser/ui/tests/elide_url_unittest.cc
@@ -161,4 +161,41 @@
RunUrlTest(testcases, arraysize(testcases));
}
+TEST(TextEliderTest, TestHostEliding) {
+ const std::string kEllipsisStr(kEllipsis);
+ Testcase testcases[] = {
+ {"http://google.com", "google.com"},
+ {"http://subdomain.google.com", kEllipsisStr + ".google.com"},
+ {"http://reallyreallyreallylongdomainname.com",
+ "reallyreallyreallylongdomainname.com"},
+ {"http://a.b.c.d.e.f.com", kEllipsisStr + "f.com"},
+ {"http://foo", "foo"},
+ {"http://foo.bar", "foo.bar"},
+ {"http://subdomain.foo.bar", kEllipsisStr + "in.foo.bar"},
+// IOS width calculations are off by a letter from other platforms for
+// some strings from other platforms, probably for strings with too
+// many kerned letters on the default font set.
+#if !defined(OS_IOS)
+ {"http://subdomain.reallylongdomainname.com",
+ kEllipsisStr + "ain.reallylongdomainname.com"},
+ {"http://a.b.c.d.e.f.com", kEllipsisStr + ".e.f.com"},
+#endif
+ };
+
+ for (size_t i = 0; i < arraysize(testcases); ++i) {
+ const float available_width =
+ GetStringWidthF(UTF8ToUTF16(testcases[i].output), gfx::FontList());
+ EXPECT_EQ(UTF8ToUTF16(testcases[i].output), ElideHost(
+ GURL(testcases[i].input), gfx::FontList(), available_width));
+ }
+
+ // Trying to elide to a really short length will still keep the full TLD+1
+ EXPECT_EQ(base::ASCIIToUTF16("google.com"),
+ ElideHost(GURL("http://google.com"), gfx::FontList(), 2));
+ EXPECT_EQ(base::UTF8ToUTF16(kEllipsisStr + ".google.com"),
+ ElideHost(GURL("http://subdomain.google.com"), gfx::FontList(), 2));
+ EXPECT_EQ(base::ASCIIToUTF16("foo.bar"),
+ ElideHost(GURL("http://foo.bar"), gfx::FontList(), 2));
+}
+
} // namespace