diff options
author | sky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-01 17:55:36 +0000 |
---|---|---|
committer | sky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-01 17:55:36 +0000 |
commit | edfa0bd262d303da7ffe91783e0d3852100de9c5 (patch) | |
tree | 45ac25cc16ddef25c62e27802c90e0a699ceb659 /chrome/common | |
parent | 0a4cdc1a63bbadf71ffd70a596d78e4a042c97cb (diff) | |
download | chromium_src-edfa0bd262d303da7ffe91783e0d3852100de9c5.zip chromium_src-edfa0bd262d303da7ffe91783e0d3852100de9c5.tar.gz chromium_src-edfa0bd262d303da7ffe91783e0d3852100de9c5.tar.bz2 |
Adds gfx::DisplayURL, which maintains a string as to how a URL
should be displayed along with a function to compare two DisplayURLs
for visually ordering them. This will be used both for displaying URLs
in a table as well as sorting them.
BUG=2949
TEST=none
Review URL: http://codereview.chromium.org/6013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2764 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common')
-rw-r--r-- | chrome/common/gfx/url_elider.cc | 100 | ||||
-rw-r--r-- | chrome/common/gfx/url_elider.h | 41 | ||||
-rw-r--r-- | chrome/common/gfx/url_elider_unittest.cc | 47 |
3 files changed, 171 insertions, 17 deletions
diff --git a/chrome/common/gfx/url_elider.cc b/chrome/common/gfx/url_elider.cc index f21888e..1cc92ca 100644 --- a/chrome/common/gfx/url_elider.cc +++ b/chrome/common/gfx/url_elider.cc @@ -20,7 +20,8 @@ namespace gfx { // Appends the given part of the original URL to the output string formatted for // the user. The given parsed structure will be updated. The host name formatter -// also takes the same accept languages component as ElideURL. +// also takes the same accept languages component as ElideURL. |new_parsed| may +// be null. static void AppendFormattedHost(const GURL& url, const std::wstring& languages, std::wstring* output, @@ -36,10 +37,12 @@ static void AppendFormattedComponent(const std::string& spec, // A helper function to get Clean Url String from a GURL. The parsing of the // URL may change because various parts of the string will change lengths. The -// new parsing will be placed in the given out parameter. +// new parsing will be placed in the given out parameter. |prefix_end| is set +// to the end of the prefix (spec and separator characters before host). static std::wstring GetCleanStringFromUrl(const GURL& url, const std::wstring& languages, - url_parse::Parsed* new_parsed); + url_parse::Parsed* new_parsed, + size_t* prefix_end); // This function takes a GURL object and elides it. It returns a string // which composed of parts from subdomain, domain, path, filename and query. @@ -57,7 +60,8 @@ std::wstring ElideUrl(const GURL& url, const std::wstring& languages) { // Get a formatted string and corresponding parsing of the url. url_parse::Parsed parsed; - std::wstring url_string = GetCleanStringFromUrl(url, languages, &parsed); + std::wstring url_string = GetCleanStringFromUrl(url, languages, &parsed, + NULL); if (available_pixel_width <= 0) return url_string; @@ -325,7 +329,8 @@ void AppendFormattedHost(const GURL& url, if (host.is_nonempty()) { // Handle possible IDN in the host name. - new_parsed->host.begin = static_cast<int>(output->length()); + if (new_parsed) + new_parsed->host.begin = static_cast<int>(output->length()); const std::string& spec = url.possibly_invalid_spec(); DCHECK(host.begin >= 0 && @@ -333,9 +338,11 @@ void AppendFormattedHost(const GURL& url, host.begin < static_cast<int>(spec.length()))); net::IDNToUnicode(&spec[host.begin], host.len, languages, output); - new_parsed->host.len = - static_cast<int>(output->length()) - new_parsed->host.begin; - } else { + if (new_parsed) { + new_parsed->host.len = + static_cast<int>(output->length()) - new_parsed->host.begin; + } + } else if (new_parsed) { new_parsed->host.reset(); } } @@ -359,12 +366,16 @@ void AppendFormattedComponent(const std::string& spec, std::wstring GetCleanStringFromUrl(const GURL& url, const std::wstring& languages, - url_parse::Parsed* new_parsed) { + url_parse::Parsed* new_parsed, + size_t* prefix_end) { std::wstring url_string; // Check for empty URLs or 0 available text width. - if (url.is_empty()) + if (url.is_empty()) { + if (prefix_end) + *prefix_end = 0; return url_string; + } // We handle both valid and invalid URLs (this will give us the spec // regardless of validity). @@ -377,10 +388,12 @@ std::wstring GetCleanStringFromUrl(const GURL& url, // // Copy everything before the host name we want (the scheme and the // separators), minus the username start we computed above. These are ASCII. - int prefix_end = parsed.CountCharactersBefore( + int pre_end = parsed.CountCharactersBefore( url_parse::Parsed::USERNAME, true); - for (int i = 0; i < prefix_end; i++) + for (int i = 0; i < pre_end; i++) url_string.push_back(spec[i]); + if (prefix_end) + *prefix_end = static_cast<size_t>(pre_end); new_parsed->scheme = parsed.scheme; new_parsed->username.reset(); new_parsed->password.reset(); @@ -411,5 +424,66 @@ std::wstring GetCleanStringFromUrl(const GURL& url, return url_string; } -} // namespace gfx. +SortedDisplayURL::SortedDisplayURL(const GURL& url, + const std::wstring& languages) { + AppendFormattedHost(url, languages, &sort_host_, NULL); + std::wstring host_minus_www = net::StripWWW(sort_host_); + url_parse::Parsed parsed; + display_url_ = GetCleanStringFromUrl(url, languages, &parsed, &prefix_end_); + if (sort_host_.length() > host_minus_www.length()) { + prefix_end_ += sort_host_.length() - host_minus_www.length(); + sort_host_.swap(host_minus_www); + } +} +int SortedDisplayURL::Compare(const SortedDisplayURL& other, + Collator* collator) const { + // Compare on hosts first. The host won't contain 'www.'. + UErrorCode compare_status = U_ZERO_ERROR; + UCollationResult host_compare_result = collator->compare( + static_cast<const UChar*>(sort_host_.c_str()), + static_cast<int>(sort_host_.length()), + static_cast<const UChar*>(other.sort_host_.c_str()), + static_cast<int>(other.sort_host_.length()), + compare_status); + DCHECK(U_SUCCESS(compare_status)); + if (host_compare_result != 0) + return host_compare_result; + + // Hosts match, compare on the portion of the url after the host. + std::wstring path = this->AfterHost(); + std::wstring o_path = other.AfterHost(); + compare_status = U_ZERO_ERROR; + UCollationResult path_compare_result = collator->compare( + static_cast<const UChar*>(path.c_str()), + static_cast<int>(path.length()), + static_cast<const UChar*>(o_path.c_str()), + static_cast<int>(o_path.length()), + compare_status); + DCHECK(U_SUCCESS(compare_status)); + if (path_compare_result != 0) + return path_compare_result; + + // Hosts and paths match, compare on the complete url. This'll push the www. + // ones to the end. + compare_status = U_ZERO_ERROR; + UCollationResult display_url_compare_result = collator->compare( + static_cast<const UChar*>(display_url_.c_str()), + static_cast<int>(display_url_.length()), + static_cast<const UChar*>(other.display_url_.c_str()), + static_cast<int>(other.display_url_.length()), + compare_status); + DCHECK(U_SUCCESS(compare_status)); + return display_url_compare_result; +} + +std::wstring SortedDisplayURL::AfterHost() const { + size_t slash_index = display_url_.find(sort_host_, prefix_end_); + if (slash_index == std::wstring::npos) { + NOTREACHED(); + return std::wstring(); + } + return display_url_.substr(slash_index + sort_host_.length()); +} + +} // namespace gfx. diff --git a/chrome/common/gfx/url_elider.h b/chrome/common/gfx/url_elider.h index 85e5ddf..83815f0 100644 --- a/chrome/common/gfx/url_elider.h +++ b/chrome/common/gfx/url_elider.h @@ -2,9 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_COMMON_GFX_URL_ELIDER_H__ -#define CHROME_COMMON_GFX_URL_ELIDER_H__ +#ifndef CHROME_COMMON_GFX_URL_ELIDER_H_ +#define CHROME_COMMON_GFX_URL_ELIDER_H_ +#include <unicode/coll.h> +#include <unicode/uchar.h> #include <windows.h> #include "base/basictypes.h" @@ -30,7 +32,38 @@ std::wstring ElideText(const std::wstring& text, const ChromeFont& font, int available_pixel_width); -} // namespace gfx. +// SortedDisplayURL maintains a string from a URL suitable for display to the +// use. SortedDisplayURL also provides a function used for comparing two +// SortedDisplayURLs for use in visually ordering the SortedDisplayURLs. +// +// SortedDisplayURL is relatively cheap and supports value semantics. +class SortedDisplayURL { + public: + SortedDisplayURL(const GURL& url, const std::wstring& languages); + SortedDisplayURL() {} + + // Compares this SortedDisplayURL to |url| using |collator|. Returns a value + // < 0, = 1 or > 0 as to whether this url is less then, equal to or greater + // than the supplied url. + int Compare(const SortedDisplayURL& other, Collator* collator) const; + + // Returns the display string for the URL. + const std::wstring& display_url() const { return display_url_; } + + private: + // Returns everything after the host. This is used by Compare if the hosts + // match. + std::wstring AfterHost() const; -#endif // #ifndef CHROME_COMMON_GFX_URL_ELIDER_H__ + // Host name minus 'www.'. Used by Compare. + std::wstring sort_host_; + + // End of the prefix (spec and separator) in display_url_. + size_t prefix_end_; + + std::wstring display_url_; +}; + +} // namespace gfx. +#endif // #ifndef CHROME_COMMON_GFX_URL_ELIDER_H_ diff --git a/chrome/common/gfx/url_elider_unittest.cc b/chrome/common/gfx/url_elider_unittest.cc index b6ca38b..4f1a3c9 100644 --- a/chrome/common/gfx/url_elider_unittest.cc +++ b/chrome/common/gfx/url_elider_unittest.cc @@ -163,3 +163,50 @@ TEST(URLEliderTest, ElideTextLongStrings) { } } +// Verifies display_url is set correctly. +TEST(URLEliderTest, SortedDisplayURL) { + gfx::SortedDisplayURL d_url(GURL("http://www.google.com/"), std::wstring()); + EXPECT_EQ(L"http://www.google.com/", d_url.display_url()); +} + +// Verifies DisplayURL::Compare works correctly. +TEST(URLEliderTest, SortedDisplayURLCompare) { + UErrorCode create_status = U_ZERO_ERROR; + Collator* collator = Collator::createInstance(create_status); + if (!U_SUCCESS(create_status)) + return; + + struct TestData { + const std::string a; + const std::string b; + const int compare_result; + } tests[] = { + // IDN comparison. Hosts equal, so compares on path. + { "http://xn--1lq90i.cn/a", "http://xn--1lq90i.cn/b", -1}, + + // Because the host and after host match, this compares the full url. + { "http://www.x/b", "http://x/b", -1 }, + + // Because the host and after host match, this compares the full url. + { "http://www.a:1/b", "http://a:1/b", 1 }, + + // The hosts match, so these end up comparing on the after host portion. + { "http://www.x:0/b", "http://x:1/b", -1 }, + { "http://www.x/a", "http://x/b", -1 }, + { "http://x/b", "http://www.x/a", 1 }, + + // Trivial Equality. + { "http://a/", "http://a/", 0 }, + + // Compares just hosts. + { "http://www.a/", "http://b/", -1 }, + }; + + + for (size_t i = 0; i < arraysize(tests); ++i) { + gfx::SortedDisplayURL url1(GURL(tests[i].a), std::wstring()); + gfx::SortedDisplayURL url2(GURL(tests[i].b), std::wstring()); + EXPECT_EQ(tests[i].compare_result, url1.Compare(url2, collator)); + EXPECT_EQ(-tests[i].compare_result, -url1.Compare(url2, collator)); + } +} |