blob: 09d3746e174765c8133a4299acb53babf348fc09 [file] [log] [blame]
miguelgdbcfb122015-07-23 10:45:111// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
rsleevi24f64dc22015-08-07 21:39:215#include "components/url_formatter/elide_url.h"
miguelgdbcfb122015-07-23 10:45:116
avi5dd91f82015-12-25 22:30:467#include <stddef.h>
8
avi5dd91f82015-12-25 22:30:469#include "base/macros.h"
gabf64a25e2017-05-12 19:42:5610#include "base/message_loop/message_loop.h"
kulshince612eb2016-06-29 18:46:5111#include "base/run_loop.h"
miguelgdbcfb122015-07-23 10:45:1112#include "base/strings/utf_string_conversions.h"
avi5dd91f82015-12-25 22:30:4613#include "build/build_config.h"
Christopher Grant6871e1212017-10-09 15:47:5014#include "components/url_formatter/url_formatter.h"
15#include "net/base/escape.h"
miguelgdbcfb122015-07-23 10:45:1116#include "testing/gtest/include/gtest/gtest.h"
Christopher Grant6871e1212017-10-09 15:47:5017#include "ui/gfx/font_list.h"
18#include "ui/gfx/text_elider.h"
19#include "ui/gfx/text_utils.h"
miguelgdbcfb122015-07-23 10:45:1120#include "url/gurl.h"
juncaicb63cac2016-05-13 00:41:5921#include "url/origin.h"
miguelgdbcfb122015-07-23 10:45:1122
miguelgdbcfb122015-07-23 10:45:1123namespace {
24
Christopher Grant6871e1212017-10-09 15:47:5025enum ElisionMethod {
26 kMethodOriginal,
27 kMethodSimple,
28};
29
miguelgdbcfb122015-07-23 10:45:1130struct Testcase {
31 const std::string input;
32 const std::string output;
33};
34
Christopher Grant5ed8d112017-09-12 20:00:0635struct ProgressiveTestcase {
36 const std::string input;
37 const std::vector<std::string> output;
38};
39
Christopher Grant6871e1212017-10-09 15:47:5040struct UrlComponent {
41 url::Parsed::ComponentType type;
42 int begin;
43 int len;
44};
45
46struct ParsingTestcase {
47 const std::string input;
48 const std::string output;
49 const std::vector<UrlComponent> components;
50};
51
Trent Apted3bef7a32018-01-23 05:39:0752// Returns the width of a utf8 or utf16 string using the BROWSER typesetter and
53// default UI font, or the provided |font_list|.
54float GetWidth(const std::string& utf8,
55 const gfx::FontList& font_list = gfx::FontList()) {
56 return gfx::GetStringWidthF(base::UTF8ToUTF16(utf8), font_list,
57 gfx::Typesetter::BROWSER);
58}
59float GetWidth(const base::string16& utf16,
60 const gfx::FontList& font_list = gfx::FontList()) {
61 return gfx::GetStringWidthF(utf16, font_list, gfx::Typesetter::BROWSER);
62}
63
Christopher Grantbd541e52017-10-13 20:59:4164base::string16 FormatAndElideUrlSimple(const GURL& url,
65 const gfx::FontList& font_list,
66 float available_pixel_width,
67 url::Parsed* parsed) {
68 const base::string16 url_string = url_formatter::FormatUrl(
69 url, url_formatter::kFormatUrlOmitDefaults, net::UnescapeRule::SPACES,
70 parsed, nullptr, nullptr);
71 return url_formatter::ElideUrlSimple(url, url_string, font_list,
72 available_pixel_width, parsed);
73}
74
Christopher Grant6871e1212017-10-09 15:47:5075base::string16 Elide(const GURL& url,
76 const gfx::FontList& font_list,
77 float available_width,
78 ElisionMethod method) {
79 switch (method) {
80 case kMethodSimple: {
81 url::Parsed parsed;
Christopher Grantbd541e52017-10-13 20:59:4182 return FormatAndElideUrlSimple(url, font_list, available_width, &parsed);
Christopher Grant6871e1212017-10-09 15:47:5083 }
84#if !defined(OS_ANDROID)
85 case kMethodOriginal:
Trent Apted3bef7a32018-01-23 05:39:0786 // Test with the BROWSER typesetter, since that's what the only consumer
87 // on Mac wants (and it makes no difference on other platforms).
88 return url_formatter::ElideUrl(url, font_list, available_width,
89 gfx::Typesetter::BROWSER);
Christopher Grant6871e1212017-10-09 15:47:5090#endif
91 default:
92 NOTREACHED();
93 return base::string16();
94 }
95}
96
97url::Component* GetComponent(url::Parsed* parsed,
98 url::Parsed::ComponentType type) {
99 switch (type) {
100 case url::Parsed::SCHEME:
101 return &parsed->scheme;
102 case url::Parsed::USERNAME:
103 return &parsed->username;
104 case url::Parsed::PASSWORD:
105 return &parsed->password;
106 case url::Parsed::HOST:
107 return &parsed->host;
108 case url::Parsed::PORT:
109 return &parsed->port;
110 case url::Parsed::PATH:
111 return &parsed->path;
112 case url::Parsed::QUERY:
113 return &parsed->query;
114 case url::Parsed::REF:
115 return &parsed->ref;
116 default:
117 NOTREACHED();
118 return nullptr;
119 }
120}
121
Christopher Grant5ed8d112017-09-12 20:00:06122// Verify that one or more URLs passes through an explicit sequence of elided
123// strings as available space progressively decreases. This helps ensure that
124// transitional corner cases are handled properly. To be tolerant of
125// character-width variation across platforms, the test allows a limited number
126// of expected strings to be skipped mid-run. The first and last expected
127// strings must be matched. If the algorithm produces a string that isn't in the
128// expected string list, the test fill fail. Example test expectations:
129//
130// google.com/intl/en/.../ads/ <-- Must match.
131// google.com/intl/.../ads/
132// google.com/.../ads/
133// google.com/intl... <- Elider can skip this, in case the 'l' does not fit.
134// google.com/int...
135// google.com/in... <- Must match.
136//
137void RunProgressiveElisionTest(
Christopher Grant6871e1212017-10-09 15:47:50138 const std::vector<ProgressiveTestcase>& testcases,
139 ElisionMethod method) {
Christopher Grant5ed8d112017-09-12 20:00:06140 const gfx::FontList font_list;
141 for (const auto& testcase : testcases) {
142 SCOPED_TRACE("Eliding " + testcase.input);
143 const GURL url(testcase.input);
144
145 // Occasionally, a parsed URL can grow in length before elision, such as
146 // when parsing a Windows file path with missing slashes.
147 ASSERT_FALSE(testcase.output.empty());
Trent Apted3bef7a32018-01-23 05:39:07148 float width = std::max(GetWidth(testcase.input, font_list),
149 GetWidth(testcase.output.front(), font_list));
Christopher Grant5ed8d112017-09-12 20:00:06150
151 // Ideally, this test would iterate through all available field widths on a
152 // per-pixel basis, but this is slow. Instead, compute the next input field
153 // width as slightly less than the previous elided string. This approach
154 // misses coverage in cases where a smaller available width generates a
155 // longer string than some other larger available width, but the tradeoff
156 // feels acceptable.
157 int mismatches = 0;
158 const int kMaxConsecutiveMismatches = 3;
159 for (size_t i = 0; i < testcase.output.size(); i++) {
160 const auto& expected = testcase.output[i];
161 base::string16 expected_utf16 = base::UTF8ToUTF16(expected);
Christopher Grant6871e1212017-10-09 15:47:50162 base::string16 elided = Elide(url, font_list, width, method);
Christopher Grant5ed8d112017-09-12 20:00:06163 if (expected_utf16 != elided) {
164 if (i > 0 && i < testcase.output.size() - 1 &&
165 mismatches < kMaxConsecutiveMismatches) {
166 mismatches++;
167 continue;
168 }
169 EXPECT_EQ(expected_utf16, elided);
170 break;
171 }
172 mismatches = 0;
Trent Apted3bef7a32018-01-23 05:39:07173 float new_width = GetWidth(elided, font_list);
Christopher Grant5ed8d112017-09-12 20:00:06174 // Elision rounds fractional available widths up.
175 EXPECT_LE(new_width, std::ceil(width)) << " at " << elided;
176 width = new_width - 1.0f;
177 }
178 }
179}
180
Christopher Grant6871e1212017-10-09 15:47:50181#if !defined(OS_ANDROID)
182
183void RunElisionTest(const std::vector<Testcase>& testcases) {
184 const gfx::FontList font_list;
185 for (const auto& testcase : testcases) {
186 SCOPED_TRACE("Eliding " + testcase.input);
187 const GURL url(testcase.input);
Trent Apted3bef7a32018-01-23 05:39:07188 const float available_width = GetWidth(testcase.output, font_list);
Christopher Grant6871e1212017-10-09 15:47:50189 EXPECT_EQ(base::UTF8ToUTF16(testcase.output),
Trent Apted3bef7a32018-01-23 05:39:07190 url_formatter::ElideUrl(url, font_list, available_width,
191 gfx::Typesetter::BROWSER));
Christopher Grant6871e1212017-10-09 15:47:50192 }
193}
194
miguelgdbcfb122015-07-23 10:45:11195// Test eliding of commonplace URLs.
Trent Apted3bef7a32018-01-23 05:39:07196TEST(TextEliderTest, TestGeneralEliding) {
rsleevi24f64dc22015-08-07 21:39:21197 const std::string kEllipsisStr(gfx::kEllipsis);
Christopher Grant5ed8d112017-09-12 20:00:06198 const std::vector<ProgressiveTestcase> progressive_testcases = {
199 // Elide a non-www URL (www URLs are handled differently). In this first
200 // case, elide down to nothing to test the terminal cases.
201 {"http://xyz.google.com/foo?bar",
202 {
203 /* clang-format off */
204 "xyz.google.com/foo?bar",
205 "xyz.google.com/foo?b" + kEllipsisStr,
206 "xyz.google.com/foo?" + kEllipsisStr,
207 "xyz.google.com/foo" + kEllipsisStr,
208 "xyz.google.com/fo" + kEllipsisStr,
209 "xyz.google.com/f" + kEllipsisStr,
210 kEllipsisStr + "google.com/foo" + kEllipsisStr,
211 kEllipsisStr + "google.com/fo" + kEllipsisStr,
212 kEllipsisStr + "google.com/f" + kEllipsisStr,
213 kEllipsisStr + "google.com/" + kEllipsisStr,
214 kEllipsisStr + "google.com" + kEllipsisStr,
215 kEllipsisStr + "google.co" + kEllipsisStr,
216 kEllipsisStr + "google.c" + kEllipsisStr,
217 kEllipsisStr + "google." + kEllipsisStr,
218 kEllipsisStr + "google" + kEllipsisStr,
219 kEllipsisStr + "googl" + kEllipsisStr,
220 kEllipsisStr + "goog" + kEllipsisStr,
221 kEllipsisStr + "goo" + kEllipsisStr,
222 kEllipsisStr + "go" + kEllipsisStr,
223 kEllipsisStr + "g" + kEllipsisStr,
224 kEllipsisStr + kEllipsisStr,
225 kEllipsisStr,
226 ""
227 /* clang-format on */
228 }},
229 // The trailing directory name is preserved
miguelgdbcfb122015-07-23 10:45:11230 {"http://www.google.com/intl/en/ads/",
Christopher Grant5ed8d112017-09-12 20:00:06231 {
232 /* clang-format off */
233 "www.google.com/intl/en/ads/",
234 "google.com/intl/en/ads/",
235 "google.com/intl/" + kEllipsisStr + "/ads/",
236 "google.com/" + kEllipsisStr + "/ads/",
237 "google.com/" + kEllipsisStr + "/ad" + kEllipsisStr,
238 "google.com/" + kEllipsisStr + "/a" + kEllipsisStr,
239 "google.com/intl/e" + kEllipsisStr,
240 "google.com/intl/" + kEllipsisStr,
241 "google.com/intl" + kEllipsisStr,
242 "google.com/int" + kEllipsisStr,
243 "google.com/in" + kEllipsisStr,
244 "google.com/i" + kEllipsisStr,
245 "google.com/" + kEllipsisStr,
246 "google.com" + kEllipsisStr,
247 "google.co" + kEllipsisStr,
248 "google.c" + kEllipsisStr,
249 "google." + kEllipsisStr,
250 "google" + kEllipsisStr,
251 "googl" + kEllipsisStr,
252 /* clang-format on */
253 }},
254 // Subdomain is completely elided if the last path element doesn't fit.
miguelgdbcfb122015-07-23 10:45:11255 {"https://subdomain.foo.com/bar/filename.html",
Christopher Grant5ed8d112017-09-12 20:00:06256 {
257 /* clang-format off */
258 "https://subdomain.foo.com/bar/filename.html",
259 "subdomain.foo.com/bar/filename.html",
260 "subdomain.foo.com/" + kEllipsisStr + "/filename.html",
261 kEllipsisStr + "foo.com/bar/filename.html",
262 kEllipsisStr + "foo.com/" + kEllipsisStr + "/filename.html",
263 /* clang-format on */
264 }},
265 // Path eliding works when a query is present.
266 {"http://www.g.com/subdir/ads/?query",
267 {
268 /* clang-format off */
269 "www.g.com/subdir/ads/?query",
270 "www.g.com/subdir/ads/?que" + kEllipsisStr,
271 "www.g.com/subdir/ads/?qu" + kEllipsisStr,
272 "www.g.com/subdir/ads/?q" + kEllipsisStr,
273 "www.g.com/subdir/ads/?" + kEllipsisStr,
274 "www.g.com/subdir/ads/" + kEllipsisStr,
275 "www.g.com/subdir/ads" + kEllipsisStr,
276 "www.g.com/subdir/ad" + kEllipsisStr,
277 /* clang-format on */
278 }},
miguelgdbcfb122015-07-23 10:45:11279 };
Christopher Grant6871e1212017-10-09 15:47:50280 RunProgressiveElisionTest(progressive_testcases, kMethodOriginal);
miguelgdbcfb122015-07-23 10:45:11281}
282
283// When there is very little space available, the elision code will shorten
284// both path AND file name to an ellipsis - ".../...". To avoid this result,
285// there is a hack in place that simply treats them as one string in this
286// case.
287TEST(TextEliderTest, TestTrailingEllipsisSlashEllipsisHack) {
rsleevi24f64dc22015-08-07 21:39:21288 const std::string kEllipsisStr(gfx::kEllipsis);
miguelgdbcfb122015-07-23 10:45:11289
290 // Very little space, would cause double ellipsis.
291 gfx::FontList font_list;
292 GURL url("http://battersbox.com/directory/foo/peter_paul_and_mary.html");
Trent Apted3bef7a32018-01-23 05:39:07293 float available_width = GetWidth(
294 "battersbox.com/" + kEllipsisStr + "/" + kEllipsisStr, font_list);
miguelgdbcfb122015-07-23 10:45:11295
296 // Create the expected string, after elision. Depending on font size, the
297 // directory might become /dir... or /di... or/d... - it never should be
298 // shorter than that. (If it is, the font considers d... to be longer
299 // than .../... - that should never happen).
Trent Apted3bef7a32018-01-23 05:39:07300 ASSERT_GT(GetWidth(kEllipsisStr + "/" + kEllipsisStr, font_list),
301 GetWidth("d" + kEllipsisStr, font_list));
miguelgdbcfb122015-07-23 10:45:11302 GURL long_url("http://battersbox.com/directorynameisreallylongtoforcetrunc");
rsleevi24f64dc22015-08-07 21:39:21303 base::string16 expected = url_formatter::ElideUrl(
Trent Apted3bef7a32018-01-23 05:39:07304 long_url, font_list, available_width, gfx::Typesetter::BROWSER);
miguelgdbcfb122015-07-23 10:45:11305 // Ensure that the expected result still contains part of the directory name.
306 ASSERT_GT(expected.length(), std::string("battersbox.com/d").length());
Trent Apted3bef7a32018-01-23 05:39:07307 EXPECT_EQ(expected, url_formatter::ElideUrl(url, font_list, available_width,
308 gfx::Typesetter::BROWSER));
miguelgdbcfb122015-07-23 10:45:11309
Matt Giuca49fcda172017-08-29 07:16:12310 // Regression test for https://crbug.com/756717. An empty path, eliding to a
311 // width in between the full domain ("www.angelfire.lycos.com") and a bit
312 // longer than the ETLD+1 ("…lycos.com…/…UV"). This previously crashed due to
313 // the path being empty.
314 url = GURL("http://www.angelfire.lycos.com/");
Trent Apted3bef7a32018-01-23 05:39:07315 available_width = GetWidth(kEllipsisStr + "angelfire.lycos.com", font_list);
Matt Giuca49fcda172017-08-29 07:16:12316 EXPECT_EQ(base::UTF8ToUTF16(kEllipsisStr + "lycos.com"),
Trent Apted3bef7a32018-01-23 05:39:07317 url_formatter::ElideUrl(url, font_list, available_width,
318 gfx::Typesetter::BROWSER));
Matt Giuca49fcda172017-08-29 07:16:12319
miguelgdbcfb122015-07-23 10:45:11320 // More space available - elide directories, partially elide filename.
Christopher Grant5ed8d112017-09-12 20:00:06321 const std::vector<Testcase> testcases = {
miguelgdbcfb122015-07-23 10:45:11322 {"http://battersbox.com/directory/foo/peter_paul_and_mary.html",
323 "battersbox.com/" + kEllipsisStr + "/peter" + kEllipsisStr},
324 };
Christopher Grant5ed8d112017-09-12 20:00:06325 RunElisionTest(testcases);
miguelgdbcfb122015-07-23 10:45:11326}
327
328// Test eliding of empty strings, URLs with ports, passwords, queries, etc.
Christopher Grant5ed8d112017-09-12 20:00:06329TEST(TextEliderTest, TestElisionSpecialCases) {
kulshince612eb2016-06-29 18:46:51330#if defined(OS_WIN)
331 // Needed to bypass DCHECK in GetFallbackFont.
332 base::MessageLoopForUI message_loop;
333#endif
rsleevi24f64dc22015-08-07 21:39:21334 const std::string kEllipsisStr(gfx::kEllipsis);
Christopher Grant5ed8d112017-09-12 20:00:06335 const std::vector<Testcase> testcases = {
Matt Giuca49fcda172017-08-29 07:16:12336 // URL with "www" subdomain (gets removed specially).
337 {"http://www.google.com/foo?bar", "www.google.com/foo?bar"},
338 {"http://www.google.com/foo?bar", "google.com/foo?bar"},
339
Matt Giuca51f68cc2017-07-07 01:34:57340 // URL with no path.
Matt Giuca49fcda172017-08-29 07:16:12341 {"http://xyz.google.com", kEllipsisStr + "google.com"},
342 {"https://xyz.google.com", kEllipsisStr + "google.com"},
Matt Giuca51f68cc2017-07-07 01:34:57343
miguelgdbcfb122015-07-23 10:45:11344 {"http://a.b.com/pathname/c?d", "a.b.com/" + kEllipsisStr + "/c?d"},
345 {"", ""},
346 {"http://foo.bar..example.com...hello/test/filename.html",
347 "foo.bar..example.com...hello/" + kEllipsisStr + "/filename.html"},
348 {"http://foo.bar../", "foo.bar.."},
349 {"http://xn--1lq90i.cn/foo", "\xe5\x8c\x97\xe4\xba\xac.cn/foo"},
350 {"http://me:[email protected]:99/foo?bar#baz",
351 "secrethost.com:99/foo?bar#baz"},
352 {"http://me:mypass@ss%xxfdsf.com/foo", "ss%25xxfdsf.com/foo"},
353 {"mailto:[email protected]", "mailto:[email protected]"},
354 {"javascript:click(0)", "javascript:click(0)"},
355 {"https://chess.eecs.berkeley.edu:4430/login/arbitfilename",
356 "chess.eecs.berkeley.edu:4430/login/arbitfilename"},
357 {"https://chess.eecs.berkeley.edu:4430/login/arbitfilename",
358 kEllipsisStr + "berkeley.edu:4430/" + kEllipsisStr + "/arbitfilename"},
359
360 // Unescaping.
Eric Lawrence03f9a902017-12-16 04:48:11361 {"http://www/%E4%BD%A0%E5%A5%BD?"
362 "q=%E4%BD%A0%E5%A5%BD#\xe4\xbd\xa0\xe4\xbd\xa0\xe4\xbd\xa0",
363 "www/\xe4\xbd\xa0\xe5\xa5\xbd?q=\xe4\xbd\xa0\xe5\xa5\xbd#\xe4\xbd\xa0" +
Mike Westf8f6ed52017-10-09 20:58:50364 kEllipsisStr},
miguelgdbcfb122015-07-23 10:45:11365
366 // Invalid unescaping for path. The ref will always be valid UTF-8. We
Christopher Grant5ed8d112017-09-12 20:00:06367 // don't bother to do too many edge cases, since these are handled by the
368 // escaper unittest.
miguelgdbcfb122015-07-23 10:45:11369 {"http://www/%E4%A0%E5%A5%BD?q=%E4%BD%A0%E5%A5%BD#\xe4\xbd\xa0",
Eric Lawrence03f9a902017-12-16 04:48:11370 "www/%E4%A0%E5%A5%BD?q=\xe4\xbd\xa0\xe5\xa5\xbd#\xe4\xbd\xa0"},
miguelgdbcfb122015-07-23 10:45:11371 };
372
Christopher Grant5ed8d112017-09-12 20:00:06373 RunElisionTest(testcases);
miguelgdbcfb122015-07-23 10:45:11374}
375
376// Test eliding of file: URLs.
Trent Apted3bef7a32018-01-23 05:39:07377TEST(TextEliderTest, TestFileURLEliding) {
rsleevi24f64dc22015-08-07 21:39:21378 const std::string kEllipsisStr(gfx::kEllipsis);
Christopher Grant5ed8d112017-09-12 20:00:06379 const std::vector<ProgressiveTestcase> progressive_testcases = {
miguelgdbcfb122015-07-23 10:45:11380 {"file:///C:/path1/path2/path3/filename",
Christopher Grant5ed8d112017-09-12 20:00:06381 {
382 /* clang-format off */
383 "file:///C:/path1/path2/path3/filename",
384 "C:/path1/path2/path3/filename",
385 "C:/path1/path2/" + kEllipsisStr + "/filename",
386 /* clang-format on */
387 }},
miguelgdbcfb122015-07-23 10:45:11388// GURL parses "file:///C:path" differently on windows than it does on posix.
389#if defined(OS_WIN)
390 {"file:///C:path1/path2/path3/filename",
Christopher Grant5ed8d112017-09-12 20:00:06391 {
392 /* clang-format off */
393 "file:///C:/path1/path2/path3/filename",
394 "C:/path1/path2/path3/filename",
395 "C:/path1/path2/" + kEllipsisStr + "/filename",
396 "C:/path1/" + kEllipsisStr + "/filename",
397 "C:/" + kEllipsisStr + "/filename",
398 /* clang-format on */
399 }},
miguelgdbcfb122015-07-23 10:45:11400#endif // defined(OS_WIN)
Christopher Grant5ed8d112017-09-12 20:00:06401 {"file://filer/foo/bar/file",
402 {
403 /* clang-format off */
404 "file://filer/foo/bar/file",
405 "filer/foo/bar/file",
406 "filer/foo/" + kEllipsisStr + "/file",
407 "filer/" + kEllipsisStr + "/file",
408 "filer/foo" + kEllipsisStr,
409 "filer/fo" + kEllipsisStr,
410 "filer/f" + kEllipsisStr,
411 "filer/" + kEllipsisStr,
412 "filer" + kEllipsisStr,
413 "file" + kEllipsisStr,
414 /* clang-format on */
415 }},
miguelgdbcfb122015-07-23 10:45:11416 };
417
Christopher Grant6871e1212017-10-09 15:47:50418 RunProgressiveElisionTest(progressive_testcases, kMethodOriginal);
Christopher Grant5ed8d112017-09-12 20:00:06419
420 const std::vector<Testcase> testcases = {
421 // Eliding file URLs with nothing after the ':' shouldn't crash.
422 {"file:///aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:", "aaa" + kEllipsisStr},
423 {"file:///aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:/", "aaa" + kEllipsisStr},
424 };
425 RunElisionTest(testcases);
miguelgdbcfb122015-07-23 10:45:11426}
427
428TEST(TextEliderTest, TestHostEliding) {
rsleevi24f64dc22015-08-07 21:39:21429 const std::string kEllipsisStr(gfx::kEllipsis);
miguelgdbcfb122015-07-23 10:45:11430 Testcase testcases[] = {
pkl2affa912017-02-22 15:23:20431 {"http://google.com", "google.com"},
432 {"http://reallyreallyreallylongdomainname.com",
433 "reallyreallyreallylongdomainname.com"},
434 {"http://foo", "foo"},
435 {"http://foo.bar", "foo.bar"},
pkl2affa912017-02-22 15:23:20436 {"http://subdomain.google.com", kEllipsisStr + ".google.com"},
437 {"http://a.b.c.d.e.f.com", kEllipsisStr + "f.com"},
438 {"http://subdomain.foo.bar", kEllipsisStr + "in.foo.bar"},
439 {"http://subdomain.reallylongdomainname.com",
440 kEllipsisStr + "ain.reallylongdomainname.com"},
441 {"http://a.b.c.d.e.f.com", kEllipsisStr + ".e.f.com"},
442 // IDN - Greek alpha.beta.gamma.delta.epsilon.zeta.com
443 {"http://xn--mxa.xn--nxa.xn--oxa.xn--pxa.xn--qxa.xn--rxa.com",
444 kEllipsisStr + ".\xCE\xB5.\xCE\xB6.com"},
miguelgdbcfb122015-07-23 10:45:11445 };
446
447 for (size_t i = 0; i < arraysize(testcases); ++i) {
Trent Apted3bef7a32018-01-23 05:39:07448 // Note this does not use GetWidth(), so typesetting will be done with
449 // gfx::Typesetter::DEFAULT. ElideHost() supports either typesetter on Mac.
rsleevi24f64dc22015-08-07 21:39:21450 const float available_width = gfx::GetStringWidthF(
451 base::UTF8ToUTF16(testcases[i].output), gfx::FontList());
452 EXPECT_EQ(base::UTF8ToUTF16(testcases[i].output),
453 url_formatter::ElideHost(GURL(testcases[i].input),
454 gfx::FontList(), available_width));
miguelgdbcfb122015-07-23 10:45:11455 }
456
457 // Trying to elide to a really short length will still keep the full TLD+1
458 EXPECT_EQ(
459 base::ASCIIToUTF16("google.com"),
rsleevi24f64dc22015-08-07 21:39:21460 url_formatter::ElideHost(GURL("http://google.com"), gfx::FontList(), 2));
miguelgdbcfb122015-07-23 10:45:11461 EXPECT_EQ(base::UTF8ToUTF16(kEllipsisStr + ".google.com"),
rsleevi24f64dc22015-08-07 21:39:21462 url_formatter::ElideHost(GURL("http://subdomain.google.com"),
463 gfx::FontList(), 2));
miguelgdbcfb122015-07-23 10:45:11464 EXPECT_EQ(
465 base::ASCIIToUTF16("foo.bar"),
rsleevi24f64dc22015-08-07 21:39:21466 url_formatter::ElideHost(GURL("http://foo.bar"), gfx::FontList(), 2));
miguelgdbcfb122015-07-23 10:45:11467}
468
469#endif // !defined(OS_ANDROID)
470
juncaicb63cac2016-05-13 00:41:59471struct OriginTestData {
472 const char* const description;
473 const char* const input;
474 const wchar_t* const output;
475 const wchar_t* const output_omit_web_scheme;
476 const wchar_t* const output_omit_cryptographic_scheme;
477};
478
479// Common test data for both FormatUrlForSecurityDisplay() and
480// FormatOriginForSecurityDisplay()
481const OriginTestData common_tests[] = {
482 {"Empty URL", "", L"", L"", L""},
483 {"HTTP URL", "http://www.google.com/", L"http://www.google.com",
484 L"www.google.com", L"http://www.google.com"},
485 {"HTTPS URL", "https://www.google.com/", L"https://www.google.com",
486 L"www.google.com", L"www.google.com"},
487 {"Standard HTTP port", "http://www.google.com:80/",
488 L"http://www.google.com", L"www.google.com", L"http://www.google.com"},
489 {"Standard HTTPS port", "https://www.google.com:443/",
490 L"https://www.google.com", L"www.google.com", L"www.google.com"},
491 {"Standard HTTP port, IDN Chinese",
492 "http://\xe4\xb8\xad\xe5\x9b\xbd.icom.museum:80",
jshin78809c4d82016-10-06 20:15:45493 L"http://\x4e2d\x56fd.icom.museum", L"\x4e2d\x56fd.icom.museum",
494 L"http://\x4e2d\x56fd.icom.museum"},
juncaicb63cac2016-05-13 00:41:59495 {"HTTP URL, IDN Hebrew (RTL)",
496 "http://"
497 "\xd7\x90\xd7\x99\xd7\xa7\xd7\x95\xd7\xb4\xd7\x9d."
498 "\xd7\x99\xd7\xa9\xd7\xa8\xd7\x90\xd7\x9c.museum/",
499 L"http://xn--4dbklr2c8d.xn--4dbrk0ce.museum",
500 L"xn--4dbklr2c8d.xn--4dbrk0ce.museum",
501 L"http://xn--4dbklr2c8d.xn--4dbrk0ce.museum"},
502 {"HTTP URL with query string, IDN Arabic (RTL)",
503 "http://\xd9\x85\xd8\xb5\xd8\xb1.icom.museum/foo.html?yes=no",
504 L"http://xn--wgbh1c.icom.museum", L"xn--wgbh1c.icom.museum",
505 L"http://xn--wgbh1c.icom.museum"},
506 {"Non-standard HTTP port", "http://www.google.com:9000/",
507 L"http://www.google.com:9000", L"www.google.com:9000",
508 L"http://www.google.com:9000"},
509 {"Non-standard HTTPS port", "https://www.google.com:9000/",
510 L"https://www.google.com:9000", L"www.google.com:9000",
511 L"www.google.com:9000"},
512 {"HTTP URL with path", "http://www.google.com/test.html",
513 L"http://www.google.com", L"www.google.com", L"http://www.google.com"},
514 {"HTTPS URL with path", "https://www.google.com/test.html",
515 L"https://www.google.com", L"www.google.com", L"www.google.com"},
516 {"Unusual secure scheme (wss)", "wss://www.google.com/",
517 L"wss://www.google.com", L"wss://www.google.com", L"www.google.com"},
518 {"Unusual non-secure scheme (gopher)", "gopher://www.google.com/",
519 L"gopher://www.google.com", L"gopher://www.google.com",
520 L"gopher://www.google.com"},
521 {"Unlisted scheme (chrome)", "chrome://version", L"chrome://version",
522 L"chrome://version", L"chrome://version"},
523 {"HTTP IP address", "http://173.194.65.103", L"http://173.194.65.103",
524 L"173.194.65.103", L"http://173.194.65.103"},
525 {"HTTPS IP address", "https://173.194.65.103", L"https://173.194.65.103",
526 L"173.194.65.103", L"173.194.65.103"},
527 {"HTTP IPv6 address", "http://[FE80:0000:0000:0000:0202:B3FF:FE1E:8329]/",
528 L"http://[fe80::202:b3ff:fe1e:8329]", L"[fe80::202:b3ff:fe1e:8329]",
529 L"http://[fe80::202:b3ff:fe1e:8329]"},
530 {"HTTPs IPv6 address", "https://[FE80:0000:0000:0000:0202:B3FF:FE1E:8329]/",
531 L"https://[fe80::202:b3ff:fe1e:8329]", L"[fe80::202:b3ff:fe1e:8329]",
532 L"[fe80::202:b3ff:fe1e:8329]"},
533 {"HTTP IPv6 address with port",
534 "http://[FE80:0000:0000:0000:0202:B3FF:FE1E:8329]:80/",
535 L"http://[fe80::202:b3ff:fe1e:8329]", L"[fe80::202:b3ff:fe1e:8329]",
536 L"http://[fe80::202:b3ff:fe1e:8329]"},
537 {"HTTPs IPv6 address with port",
538 "https://[FE80:0000:0000:0000:0202:B3FF:FE1E:8329]:443/",
539 L"https://[fe80::202:b3ff:fe1e:8329]", L"[fe80::202:b3ff:fe1e:8329]",
540 L"[fe80::202:b3ff:fe1e:8329]"},
541 {"HTTPS IP address, non-default port", "https://173.194.65.103:8443",
542 L"https://173.194.65.103:8443", L"173.194.65.103:8443",
543 L"173.194.65.103:8443"},
544 {"Invalid host 1", "https://www.cyber../wow.php", L"https://www.cyber..",
545 L"www.cyber..", L"www.cyber.."},
546 {"Invalid host 2", "https://www...cyber/wow.php", L"https://www...cyber",
547 L"www...cyber", L"www...cyber"},
548 {"Invalid port 3", "https://173.194.65.103:/hello.aspx",
549 L"https://173.194.65.103", L"173.194.65.103", L"173.194.65.103"},
550 {"Trailing dot in DNS name", "https://www.example.com./get/goat",
551 L"https://www.example.com.", L"www.example.com.", L"www.example.com."}};
552
miguelgdbcfb122015-07-23 10:45:11553TEST(TextEliderTest, FormatUrlForSecurityDisplay) {
juncaicb63cac2016-05-13 00:41:59554 for (size_t i = 0; i < arraysize(common_tests); ++i) {
555 base::string16 formatted =
556 url_formatter::FormatUrlForSecurityDisplay(GURL(common_tests[i].input));
557 EXPECT_EQ(base::WideToUTF16(common_tests[i].output), formatted)
558 << common_tests[i].description;
559
560 base::string16 formatted_omit_web_scheme =
561 url_formatter::FormatUrlForSecurityDisplay(
562 GURL(common_tests[i].input),
563 url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
564 EXPECT_EQ(base::WideToUTF16(common_tests[i].output_omit_web_scheme),
565 formatted_omit_web_scheme)
566 << common_tests[i].description;
567
568 base::string16 formatted_omit_cryptographic_scheme =
569 url_formatter::FormatUrlForSecurityDisplay(
570 GURL(common_tests[i].input),
571 url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC);
572 EXPECT_EQ(
573 base::WideToUTF16(common_tests[i].output_omit_cryptographic_scheme),
574 formatted_omit_cryptographic_scheme)
575 << common_tests[i].description;
576 }
miguelgdbcfb122015-07-23 10:45:11577
578 const OriginTestData tests[] = {
miguelgdbcfb122015-07-23 10:45:11579 {"File URI", "file:///usr/example/file.html",
benwells2337b8102016-04-20 01:53:53580 L"file:///usr/example/file.html", L"file:///usr/example/file.html",
581 L"file:///usr/example/file.html"},
miguelgdbcfb122015-07-23 10:45:11582 {"File URI with hostname", "file://localhost/usr/example/file.html",
benwells2337b8102016-04-20 01:53:53583 L"file:///usr/example/file.html", L"file:///usr/example/file.html",
584 L"file:///usr/example/file.html"},
miguelgdbcfb122015-07-23 10:45:11585 {"UNC File URI 1", "file:///CONTOSO/accounting/money.xls",
palmer153af982015-09-15 02:04:19586 L"file:///CONTOSO/accounting/money.xls",
benwells2337b8102016-04-20 01:53:53587 L"file:///CONTOSO/accounting/money.xls",
miguelgdbcfb122015-07-23 10:45:11588 L"file:///CONTOSO/accounting/money.xls"},
589 {"UNC File URI 2",
590 "file:///C:/Program%20Files/Music/Web%20Sys/main.html?REQUEST=RADIO",
palmer153af982015-09-15 02:04:19591 L"file:///C:/Program%20Files/Music/Web%20Sys/main.html",
benwells2337b8102016-04-20 01:53:53592 L"file:///C:/Program%20Files/Music/Web%20Sys/main.html",
miguelgdbcfb122015-07-23 10:45:11593 L"file:///C:/Program%20Files/Music/Web%20Sys/main.html"},
benwells2337b8102016-04-20 01:53:53594 {"Invalid IPv6 address", "https://[2001:db8:0:1]/",
595 L"https://[2001:db8:0:1]", L"https://[2001:db8:0:1]",
596 L"https://[2001:db8:0:1]"},
miguelgdbcfb122015-07-23 10:45:11597 {"HTTP filesystem: URL with path",
598 "filesystem:http://www.google.com/temporary/test.html",
benwells2337b8102016-04-20 01:53:53599 L"filesystem:http://www.google.com", L"filesystem:http://www.google.com",
miguelgdbcfb122015-07-23 10:45:11600 L"filesystem:http://www.google.com"},
601 {"File filesystem: URL with path",
juncaicb63cac2016-05-13 00:41:59602 "filesystem:file://localhost/temporary/stuff/"
603 "test.html?z=fun&goat=billy",
palmer153af982015-09-15 02:04:19604 L"filesystem:file:///temporary/stuff/test.html",
benwells2337b8102016-04-20 01:53:53605 L"filesystem:file:///temporary/stuff/test.html",
miguelgdbcfb122015-07-23 10:45:11606 L"filesystem:file:///temporary/stuff/test.html"},
607 {"Invalid scheme 1", "twelve://www.cyber.org/wow.php",
benwells2337b8102016-04-20 01:53:53608 L"twelve://www.cyber.org/wow.php", L"twelve://www.cyber.org/wow.php",
609 L"twelve://www.cyber.org/wow.php"},
miguelgdbcfb122015-07-23 10:45:11610 {"Invalid scheme 2", "://www.cyber.org/wow.php",
benwells2337b8102016-04-20 01:53:53611 L"://www.cyber.org/wow.php", L"://www.cyber.org/wow.php",
612 L"://www.cyber.org/wow.php"},
miguelgdbcfb122015-07-23 10:45:11613 {"Invalid port 1", "https://173.194.65.103:000",
benwells2337b8102016-04-20 01:53:53614 L"https://173.194.65.103:0", L"173.194.65.103:0", L"173.194.65.103:0"},
miguelgdbcfb122015-07-23 10:45:11615 {"Invalid port 2", "https://173.194.65.103:gruffle",
benwells2337b8102016-04-20 01:53:53616 L"https://173.194.65.103:gruffle", L"https://173.194.65.103:gruffle",
617 L"https://173.194.65.103:gruffle"},
miguelgdbcfb122015-07-23 10:45:11618 {"Blob URL",
nick1b17dc32016-04-15 21:34:04619 "blob:http://www.html5rocks.com/4d4ff040-6d61-4446-86d3-13ca07ec9ab9",
620 L"blob:http://www.html5rocks.com/"
palmer153af982015-09-15 02:04:19621 L"4d4ff040-6d61-4446-86d3-13ca07ec9ab9",
nick1b17dc32016-04-15 21:34:04622 L"blob:http://www.html5rocks.com/"
benwells2337b8102016-04-20 01:53:53623 L"4d4ff040-6d61-4446-86d3-13ca07ec9ab9",
624 L"blob:http://www.html5rocks.com/"
palmer153af982015-09-15 02:04:19625 L"4d4ff040-6d61-4446-86d3-13ca07ec9ab9"}};
miguelgdbcfb122015-07-23 10:45:11626
miguelgdbcfb122015-07-23 10:45:11627 for (size_t i = 0; i < arraysize(tests); ++i) {
jshin1fb76462016-04-05 22:13:03628 base::string16 formatted =
629 url_formatter::FormatUrlForSecurityDisplay(GURL(tests[i].input));
miguelgdbcfb122015-07-23 10:45:11630 EXPECT_EQ(base::WideToUTF16(tests[i].output), formatted)
631 << tests[i].description;
palmer153af982015-09-15 02:04:19632
benwells2337b8102016-04-20 01:53:53633 base::string16 formatted_omit_web_scheme =
634 url_formatter::FormatUrlForSecurityDisplay(
635 GURL(tests[i].input),
636 url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
637 EXPECT_EQ(base::WideToUTF16(tests[i].output_omit_web_scheme),
638 formatted_omit_web_scheme)
639 << tests[i].description;
640
641 base::string16 formatted_omit_cryptographic_scheme =
642 url_formatter::FormatUrlForSecurityDisplay(
643 GURL(tests[i].input),
644 url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC);
645 EXPECT_EQ(base::WideToUTF16(tests[i].output_omit_cryptographic_scheme),
646 formatted_omit_cryptographic_scheme)
palmer153af982015-09-15 02:04:19647 << tests[i].description;
miguelgdbcfb122015-07-23 10:45:11648 }
649
juncaicb63cac2016-05-13 00:41:59650 base::string16 formatted = url_formatter::FormatUrlForSecurityDisplay(GURL());
miguelgdbcfb122015-07-23 10:45:11651 EXPECT_EQ(base::string16(), formatted)
652 << "Explicitly test the 0-argument GURL constructor";
palmer153af982015-09-15 02:04:19653
654 base::string16 formatted_omit_scheme =
benwells2337b8102016-04-20 01:53:53655 url_formatter::FormatUrlForSecurityDisplay(
656 GURL(), url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
657 EXPECT_EQ(base::string16(), formatted_omit_scheme)
658 << "Explicitly test the 0-argument GURL constructor";
659
660 formatted_omit_scheme = url_formatter::FormatUrlForSecurityDisplay(
661 GURL(), url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC);
palmer153af982015-09-15 02:04:19662 EXPECT_EQ(base::string16(), formatted_omit_scheme)
663 << "Explicitly test the 0-argument GURL constructor";
miguelgdbcfb122015-07-23 10:45:11664}
665
juncaicb63cac2016-05-13 00:41:59666TEST(TextEliderTest, FormatOriginForSecurityDisplay) {
667 for (size_t i = 0; i < arraysize(common_tests); ++i) {
668 base::string16 formatted = url_formatter::FormatOriginForSecurityDisplay(
Daniel Cheng88186bd52017-10-20 08:14:46669 url::Origin::Create(GURL(common_tests[i].input)));
juncaicb63cac2016-05-13 00:41:59670 EXPECT_EQ(base::WideToUTF16(common_tests[i].output), formatted)
671 << common_tests[i].description;
672
673 base::string16 formatted_omit_web_scheme =
674 url_formatter::FormatOriginForSecurityDisplay(
Daniel Cheng88186bd52017-10-20 08:14:46675 url::Origin::Create(GURL(common_tests[i].input)),
juncaicb63cac2016-05-13 00:41:59676 url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
677 EXPECT_EQ(base::WideToUTF16(common_tests[i].output_omit_web_scheme),
678 formatted_omit_web_scheme)
679 << common_tests[i].description;
680
681 base::string16 formatted_omit_cryptographic_scheme =
682 url_formatter::FormatOriginForSecurityDisplay(
Daniel Cheng88186bd52017-10-20 08:14:46683 url::Origin::Create(GURL(common_tests[i].input)),
juncaicb63cac2016-05-13 00:41:59684 url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC);
685 EXPECT_EQ(
686 base::WideToUTF16(common_tests[i].output_omit_cryptographic_scheme),
687 formatted_omit_cryptographic_scheme)
688 << common_tests[i].description;
689 }
690
691 const OriginTestData tests[] = {
692 {"File URI", "file:///usr/example/file.html", L"file://", L"file://",
693 L"file://"},
694 {"File URI with hostname", "file://localhost/usr/example/file.html",
695 L"file://localhost", L"file://localhost", L"file://localhost"},
696 {"UNC File URI 1", "file:///CONTOSO/accounting/money.xls", L"file://",
697 L"file://", L"file://"},
698 {"UNC File URI 2",
699 "file:///C:/Program%20Files/Music/Web%20Sys/main.html?REQUEST=RADIO",
700 L"file://", L"file://", L"file://"},
701 {"Invalid IPv6 address", "https://[2001:db8:0:1]/", L"", L"", L""},
702 {"HTTP filesystem: URL with path",
703 "filesystem:http://www.google.com/temporary/test.html",
704 L"http://www.google.com", L"www.google.com", L"http://www.google.com"},
705 {"File filesystem: URL with path",
706 "filesystem:file://localhost/temporary/stuff/test.html?z=fun&goat=billy",
707 L"file://", L"file://", L"file://"},
708 {"Invalid scheme 1", "twelve://www.cyber.org/wow.php", L"", L"", L""},
709 {"Invalid scheme 2", "://www.cyber.org/wow.php", L"", L"", L""},
710 {"Invalid port 1", "https://173.194.65.103:000", L"", L"", L""},
711 {"Invalid port 2", "https://173.194.65.103:gruffle", L"", L"", L""},
712 {"Blob URL",
713 "blob:http://www.html5rocks.com/4d4ff040-6d61-4446-86d3-13ca07ec9ab9",
714 L"http://www.html5rocks.com", L"www.html5rocks.com",
715 L"http://www.html5rocks.com"}};
716
717 for (size_t i = 0; i < arraysize(tests); ++i) {
718 base::string16 formatted = url_formatter::FormatOriginForSecurityDisplay(
Daniel Cheng88186bd52017-10-20 08:14:46719 url::Origin::Create(GURL(tests[i].input)));
juncaicb63cac2016-05-13 00:41:59720 EXPECT_EQ(base::WideToUTF16(tests[i].output), formatted)
721 << tests[i].description;
722
723 base::string16 formatted_omit_web_scheme =
724 url_formatter::FormatOriginForSecurityDisplay(
Daniel Cheng88186bd52017-10-20 08:14:46725 url::Origin::Create(GURL(tests[i].input)),
juncaicb63cac2016-05-13 00:41:59726 url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
727 EXPECT_EQ(base::WideToUTF16(tests[i].output_omit_web_scheme),
728 formatted_omit_web_scheme)
729 << tests[i].description;
730
731 base::string16 formatted_omit_cryptographic_scheme =
732 url_formatter::FormatOriginForSecurityDisplay(
Daniel Cheng88186bd52017-10-20 08:14:46733 url::Origin::Create(GURL(tests[i].input)),
juncaicb63cac2016-05-13 00:41:59734 url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC);
735 EXPECT_EQ(base::WideToUTF16(tests[i].output_omit_cryptographic_scheme),
736 formatted_omit_cryptographic_scheme)
737 << tests[i].description;
738 }
739
Daniel Cheng88186bd52017-10-20 08:14:46740 base::string16 formatted = url_formatter::FormatOriginForSecurityDisplay(
741 url::Origin::Create(GURL()));
juncaicb63cac2016-05-13 00:41:59742 EXPECT_EQ(base::string16(), formatted)
743 << "Explicitly test the url::Origin which takes an empty, invalid URL";
744
745 base::string16 formatted_omit_scheme =
746 url_formatter::FormatOriginForSecurityDisplay(
Daniel Cheng88186bd52017-10-20 08:14:46747 url::Origin::Create(GURL()),
juncaicb63cac2016-05-13 00:41:59748 url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS);
749 EXPECT_EQ(base::string16(), formatted_omit_scheme)
750 << "Explicitly test the url::Origin which takes an empty, invalid URL";
751
752 formatted_omit_scheme = url_formatter::FormatOriginForSecurityDisplay(
Daniel Cheng88186bd52017-10-20 08:14:46753 url::Origin::Create(GURL()),
754 url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC);
juncaicb63cac2016-05-13 00:41:59755 EXPECT_EQ(base::string16(), formatted_omit_scheme)
756 << "Explicitly test the url::Origin which takes an empty, invalid URL";
757}
758
Trent Apted3bef7a32018-01-23 05:39:07759TEST(TextEliderTest, TestSimpleElisionMethod) {
Christopher Grant6871e1212017-10-09 15:47:50760 const std::string kEllipsisStr(gfx::kEllipsis);
761 const std::vector<ProgressiveTestcase> testcases = {
762 {"https://www.abc.com/def/",
763 {
764 /* clang-format off */
765 {"https://www.abc.com/def/"},
766 {"https://www.abc.com/d" + kEllipsisStr},
767 {"https://www.abc.com/" + kEllipsisStr},
768 {"www.abc.com/def/"},
769 {"www.abc.com/d" + kEllipsisStr},
770 {"www.abc.com/" + kEllipsisStr},
771 {kEllipsisStr + "ww.abc.com/" + kEllipsisStr},
772 {kEllipsisStr + "w.abc.com/" + kEllipsisStr},
773 {kEllipsisStr + ".abc.com/" + kEllipsisStr},
774 {kEllipsisStr + "abc.com/" + kEllipsisStr},
775 {kEllipsisStr + "bc.com/" + kEllipsisStr},
776 {kEllipsisStr + "c.com/" + kEllipsisStr},
777 {kEllipsisStr + ".com/" + kEllipsisStr},
778 {kEllipsisStr + "com/" + kEllipsisStr},
779 {kEllipsisStr + "om/" + kEllipsisStr},
780 {kEllipsisStr + "m/" + kEllipsisStr},
781 {kEllipsisStr + "/" + kEllipsisStr},
782 {kEllipsisStr},
783 {""},
784 /* clang-format on */
785 }},
786 {"file://fs/file",
787 {
788 /* clang-format off */
789 "file://fs/file",
790 "file://fs/fi" + kEllipsisStr,
791 "file://fs/f" + kEllipsisStr,
792 "file://fs/" + kEllipsisStr,
793 "file://fs" + kEllipsisStr,
794 "file://f" + kEllipsisStr,
795 "file://" + kEllipsisStr,
796 "file:/" + kEllipsisStr,
797 "file:" + kEllipsisStr,
798 "file" + kEllipsisStr,
799 "fil" + kEllipsisStr,
800 "fi" + kEllipsisStr,
801 "f" + kEllipsisStr,
802 kEllipsisStr,
803 "",
804 /* clang-format on */
805 }},
806 };
807 RunProgressiveElisionTest(testcases, kMethodSimple);
808}
809
810// Verify that the secure elision method returns URL component data that
811// correctly represents the elided URL.
812void RunElisionParsingTest(const std::vector<ParsingTestcase>& testcases) {
813 const gfx::FontList font_list;
814 for (const auto& testcase : testcases) {
815 SCOPED_TRACE(testcase.input + " to " + testcase.output);
816
817 const GURL url(testcase.input);
Trent Apted3bef7a32018-01-23 05:39:07818 const float available_width = GetWidth(testcase.output, font_list);
Christopher Grant6871e1212017-10-09 15:47:50819
820 url::Parsed parsed;
821 auto elided =
Christopher Grantbd541e52017-10-13 20:59:41822 FormatAndElideUrlSimple(url, font_list, available_width, &parsed);
Christopher Grant6871e1212017-10-09 15:47:50823 EXPECT_EQ(base::UTF8ToUTF16(testcase.output), elided);
824
825 // Build an expected Parsed struct from the sparse test expectations.
826 url::Parsed expected;
827 for (const auto& expectation : testcase.components) {
828 url::Component* component = GetComponent(&expected, expectation.type);
829 component->begin = expectation.begin;
830 component->len = expectation.len;
831 }
832
833 const std::vector<url::Parsed::ComponentType> kComponents = {
834 url::Parsed::SCHEME, url::Parsed::USERNAME, url::Parsed::PASSWORD,
835 url::Parsed::HOST, url::Parsed::PORT, url::Parsed::PATH,
836 url::Parsed::QUERY, url::Parsed::REF,
837 };
838 for (const auto& type : kComponents) {
839 EXPECT_EQ(GetComponent(&expected, type)->begin,
840 GetComponent(&parsed, type)->begin)
841 << " in component " << type;
842 EXPECT_EQ(GetComponent(&expected, type)->len,
843 GetComponent(&parsed, type)->len)
844 << " in component " << type;
845 }
846 }
847}
848
849// Verify that during elision, the parsed URL components are properly modified.
Trent Apted3bef7a32018-01-23 05:39:07850TEST(TextEliderTest, TestElisionParsingAdjustments) {
Christopher Grant6871e1212017-10-09 15:47:50851 const std::string kEllipsisStr(gfx::kEllipsis);
852 const std::vector<ParsingTestcase> testcases = {
853 // HTTPS with path.
854 {"https://www.google.com/intl/en/ads/",
855 "https://www.google.com/intl/en/ads/",
856 {{url::Parsed::ComponentType::SCHEME, 0, 5},
857 {url::Parsed::ComponentType::HOST, 8, 14},
858 {url::Parsed::ComponentType::PATH, 22, 13}}},
859 {"https://www.google.com/intl/en/ads/",
860 "https://www.google.com/intl/en/a" + kEllipsisStr,
861 {{url::Parsed::ComponentType::SCHEME, 0, 5},
862 {url::Parsed::ComponentType::HOST, 8, 14},
863 {url::Parsed::ComponentType::PATH, 22, 11}}},
864 {"https://www.google.com/intl/en/ads/",
865 "https://www.google.com/" + kEllipsisStr,
866 {{url::Parsed::ComponentType::SCHEME, 0, 5},
867 {url::Parsed::ComponentType::HOST, 8, 14},
868 {url::Parsed::ComponentType::PATH, 22, 2}}},
869 {"https://www.google.com/intl/en/ads/",
870 kEllipsisStr + "google.com/" + kEllipsisStr,
871 {{url::Parsed::ComponentType::HOST, 0, 11},
872 {url::Parsed::ComponentType::PATH, 11, 2}}},
873 {"https://www.google.com/intl/en/ads/",
874 kEllipsisStr,
875 {{url::Parsed::ComponentType::PATH, 0, 1}}},
876 // HTTPS with no path.
877 {"https://www.google.com/",
878 "www.google.com",
879 {{url::Parsed::ComponentType::HOST, 0, 14}}},
880 {"https://www.google.com/",
881 kEllipsisStr,
882 {{url::Parsed::ComponentType::HOST, 0, 1}}},
883 // HTTP with no path.
884 {"http://www.google.com/",
885 "www.google.com",
886 {{url::Parsed::ComponentType::HOST, 0, 14}}},
887 // File URLs.
888 {"file:///C:/path1/path2",
889 "file:///C:/path1/" + kEllipsisStr,
890 {{url::Parsed::ComponentType::SCHEME, 0, 4},
891 {url::Parsed::ComponentType::PATH, 7, 11}}},
892 {"file:///C:/path1/path2",
893 "fi" + kEllipsisStr,
894 {{url::Parsed::ComponentType::SCHEME, 0, 3}}},
895 {"file:///C:/path1/path2",
896 kEllipsisStr,
897 {{url::Parsed::ComponentType::SCHEME, 0, 1}}},
898 // RTL URL.
899 {"http://127.0.0.1/ا/http://attack.com‬",
900 kEllipsisStr + "7.0.0.1/" + kEllipsisStr,
901 {{url::Parsed::ComponentType::HOST, 0, 8},
902 {url::Parsed::ComponentType::PATH, 8, 2}}},
903 };
904
905 RunElisionParsingTest(testcases);
906}
907
miguelgdbcfb122015-07-23 10:45:11908} // namespace