Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(742)

Side by Side Diff: app/gfx/text_elider.cc

Issue 115346: Convert Punycode domains to Unicode in URLs shown in the followings:... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « app/gfx/text_elider.h ('k') | chrome/browser/autocomplete/autocomplete.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "app/gfx/font.h" 5 #include "app/gfx/font.h"
6 #include "app/gfx/text_elider.h" 6 #include "app/gfx/text_elider.h"
7 #include "base/file_path.h" 7 #include "base/file_path.h"
8 #include "base/string_util.h" 8 #include "base/string_util.h"
9 #include "base/sys_string_conversions.h" 9 #include "base/sys_string_conversions.h"
10 #include "googleurl/src/gurl.h" 10 #include "googleurl/src/gurl.h"
11 #include "net/base/escape.h" 11 #include "net/base/escape.h"
12 #include "net/base/net_util.h" 12 #include "net/base/net_util.h"
13 #include "net/base/registry_controlled_domain.h" 13 #include "net/base/registry_controlled_domain.h"
14 14
15 const wchar_t kEllipsis[] = L"\x2026"; 15 const wchar_t kEllipsis[] = L"\x2026";
16 16
17 namespace gfx { 17 namespace gfx {
18 18
19 // Appends the given part of the original URL to the output string formatted for
20 // the user. The given parsed structure will be updated. The host name formatter
21 // also takes the same accept languages component as ElideURL. |new_parsed| may
22 // be null.
23 static void AppendFormattedHost(const GURL& url,
24 const std::wstring& languages,
25 std::wstring* output,
26 url_parse::Parsed* new_parsed);
27
28 // Calls the unescaper for the substring |in_component| inside of the URL
29 // |spec|. The decoded string will be appended to |output| and the resulting
30 // range will be filled into |out_component|.
31 static void AppendFormattedComponent(const std::string& spec,
32 const url_parse::Component& in_component,
33 std::wstring* output,
34 url_parse::Component* out_component);
35
36 // This function takes a GURL object and elides it. It returns a string 19 // This function takes a GURL object and elides it. It returns a string
37 // which composed of parts from subdomain, domain, path, filename and query. 20 // which composed of parts from subdomain, domain, path, filename and query.
38 // A "..." is added automatically at the end if the elided string is bigger 21 // A "..." is added automatically at the end if the elided string is bigger
39 // than the available pixel width. For available pixel width = 0, a formatted, 22 // than the available pixel width. For available pixel width = 0, a formatted,
40 // but un-elided, string is returned. 23 // but un-elided, string is returned.
41 // 24 //
42 // TODO(pkasting): http://b/119635 This whole function gets 25 // TODO(pkasting): http://b/119635 This whole function gets
43 // kerning/ligatures/etc. issues potentially wrong by assuming that the width of 26 // kerning/ligatures/etc. issues potentially wrong by assuming that the width of
44 // a rendered string is always the sum of the widths of its substrings. Also I 27 // a rendered string is always the sum of the widths of its substrings. Also I
45 // suspect it could be made simpler. 28 // suspect it could be made simpler.
46 std::wstring ElideUrl(const GURL& url, 29 std::wstring ElideUrl(const GURL& url,
47 const gfx::Font& font, 30 const gfx::Font& font,
48 int available_pixel_width, 31 int available_pixel_width,
49 const std::wstring& languages) { 32 const std::wstring& languages) {
50 // Get a formatted string and corresponding parsing of the url. 33 // Get a formatted string and corresponding parsing of the url.
51 url_parse::Parsed parsed; 34 url_parse::Parsed parsed;
52 std::wstring url_string = GetCleanStringFromUrl(url, languages, &parsed, 35 std::wstring url_string =
53 NULL); 36 net::FormatUrl(url, languages, true, true, &parsed, NULL);
54 if (available_pixel_width <= 0) 37 if (available_pixel_width <= 0)
55 return url_string; 38 return url_string;
56 39
57 // If non-standard or not file type, return plain eliding. 40 // If non-standard or not file type, return plain eliding.
58 if (!(url.SchemeIsFile() || url.IsStandard())) 41 if (!(url.SchemeIsFile() || url.IsStandard()))
59 return ElideText(url_string, font, available_pixel_width); 42 return ElideText(url_string, font, available_pixel_width);
60 43
61 // Now start eliding url_string to fit within available pixel width. 44 // Now start eliding url_string to fit within available pixel width.
62 // Fist pass - check to see whether entire url_string fits. 45 // Fist pass - check to see whether entire url_string fits.
63 int pixel_width_url_string = font.GetStringWidth(url_string); 46 int pixel_width_url_string = font.GetStringWidth(url_string);
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 if (lo == guess) 314 if (lo == guess)
332 break; 315 break;
333 lo = guess; 316 lo = guess;
334 } 317 }
335 guess = (lo + hi) / 2; 318 guess = (lo + hi) / 2;
336 } 319 }
337 320
338 return text.substr(0, lo) + kEllipsis; 321 return text.substr(0, lo) + kEllipsis;
339 } 322 }
340 323
341 void AppendFormattedHost(const GURL& url,
342 const std::wstring& languages,
343 std::wstring* output,
344 url_parse::Parsed* new_parsed) {
345 const url_parse::Component& host =
346 url.parsed_for_possibly_invalid_spec().host;
347
348 if (host.is_nonempty()) {
349 // Handle possible IDN in the host name.
350 if (new_parsed)
351 new_parsed->host.begin = static_cast<int>(output->length());
352
353 const std::string& spec = url.possibly_invalid_spec();
354 DCHECK(host.begin >= 0 &&
355 ((spec.length() == 0 && host.begin == 0) ||
356 host.begin < static_cast<int>(spec.length())));
357 net::IDNToUnicode(&spec[host.begin], host.len, languages, output);
358
359 if (new_parsed) {
360 new_parsed->host.len =
361 static_cast<int>(output->length()) - new_parsed->host.begin;
362 }
363 } else if (new_parsed) {
364 new_parsed->host.reset();
365 }
366 }
367
368 void AppendFormattedComponent(const std::string& spec,
369 const url_parse::Component& in_component,
370 std::wstring* output,
371 url_parse::Component* out_component) {
372 if (in_component.is_nonempty()) {
373 out_component->begin = static_cast<int>(output->length());
374
375 output->append(UnescapeAndDecodeUTF8URLComponent(
376 spec.substr(in_component.begin, in_component.len),
377 UnescapeRule::NORMAL));
378
379 out_component->len =
380 static_cast<int>(output->length()) - out_component->begin;
381 } else {
382 out_component->reset();
383 }
384 }
385
386 std::wstring GetCleanStringFromUrl(const GURL& url,
387 const std::wstring& languages,
388 url_parse::Parsed* new_parsed,
389 size_t* prefix_end) {
390 url_parse::Parsed parsed_temp;
391 if (!new_parsed)
392 new_parsed = &parsed_temp;
393
394 std::wstring url_string;
395
396 // Check for empty URLs or 0 available text width.
397 if (url.is_empty()) {
398 if (prefix_end)
399 *prefix_end = 0;
400 return url_string;
401 }
402
403 // We handle both valid and invalid URLs (this will give us the spec
404 // regardless of validity).
405 const std::string& spec = url.possibly_invalid_spec();
406 const url_parse::Parsed& parsed = url.parsed_for_possibly_invalid_spec();
407
408 // Construct a new URL with the username and password fields removed. We
409 // don't want to display those to the user since they can be used for
410 // attacks, e.g. "http://google.com:search@evil.ru/"
411 //
412 // Copy everything before the host name we want (the scheme and the
413 // separators), minus the username start we computed above. These are ASCII.
414 int pre_end = parsed.CountCharactersBefore(
415 url_parse::Parsed::USERNAME, true);
416 for (int i = 0; i < pre_end; ++i)
417 url_string.push_back(spec[i]);
418 if (prefix_end)
419 *prefix_end = static_cast<size_t>(pre_end);
420 new_parsed->scheme = parsed.scheme;
421 new_parsed->username.reset();
422 new_parsed->password.reset();
423
424 AppendFormattedHost(url, languages, &url_string, new_parsed);
425
426 // Port.
427 if (parsed.port.is_nonempty()) {
428 url_string.push_back(':');
429 for (int i = parsed.port.begin; i < parsed.port.end(); ++i)
430 url_string.push_back(spec[i]);
431 }
432
433 // Path and query both get the same general unescape & convert treatment.
434 AppendFormattedComponent(spec, parsed.path, &url_string, &new_parsed->path);
435 if (parsed.query.is_valid())
436 url_string.push_back('?');
437 AppendFormattedComponent(spec, parsed.query, &url_string, &new_parsed->query);
438
439 // Reference is stored in valid, unescaped UTF-8, so we can just convert.
440 if (parsed.ref.is_valid()) {
441 url_string.push_back('#');
442 if (parsed.ref.len > 0)
443 url_string.append(UTF8ToWide(std::string(&spec[parsed.ref.begin],
444 parsed.ref.len)));
445 }
446
447 return url_string;
448 }
449
450 SortedDisplayURL::SortedDisplayURL(const GURL& url, 324 SortedDisplayURL::SortedDisplayURL(const GURL& url,
451 const std::wstring& languages) { 325 const std::wstring& languages) {
452 std::wstring host; 326 std::wstring host;
453 AppendFormattedHost(url, languages, &host, NULL); 327 net::AppendFormattedHost(url, languages, &host, NULL);
454 sort_host_ = WideToUTF16Hack(host); 328 sort_host_ = WideToUTF16Hack(host);
455 string16 host_minus_www = WideToUTF16Hack(net::StripWWW(host)); 329 string16 host_minus_www = WideToUTF16Hack(net::StripWWW(host));
456 url_parse::Parsed parsed; 330 url_parse::Parsed parsed;
457 display_url_ = WideToUTF16Hack(GetCleanStringFromUrl(url, languages, 331 display_url_ = WideToUTF16Hack(net::FormatUrl(url, languages,
458 &parsed, &prefix_end_)); 332 true, true, &parsed, &prefix_end_));
459 if (sort_host_.length() > host_minus_www.length()) { 333 if (sort_host_.length() > host_minus_www.length()) {
460 prefix_end_ += sort_host_.length() - host_minus_www.length(); 334 prefix_end_ += sort_host_.length() - host_minus_www.length();
461 sort_host_.swap(host_minus_www); 335 sort_host_.swap(host_minus_www);
462 } 336 }
463 } 337 }
464 338
465 int SortedDisplayURL::Compare(const SortedDisplayURL& other, 339 int SortedDisplayURL::Compare(const SortedDisplayURL& other,
466 Collator* collator) const { 340 Collator* collator) const {
467 // Compare on hosts first. The host won't contain 'www.'. 341 // Compare on hosts first. The host won't contain 'www.'.
468 UErrorCode compare_status = U_ZERO_ERROR; 342 UErrorCode compare_status = U_ZERO_ERROR;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 string16 SortedDisplayURL::AfterHost() const { 380 string16 SortedDisplayURL::AfterHost() const {
507 size_t slash_index = display_url_.find(sort_host_, prefix_end_); 381 size_t slash_index = display_url_.find(sort_host_, prefix_end_);
508 if (slash_index == string16::npos) { 382 if (slash_index == string16::npos) {
509 NOTREACHED(); 383 NOTREACHED();
510 return string16(); 384 return string16();
511 } 385 }
512 return display_url_.substr(slash_index + sort_host_.length()); 386 return display_url_.substr(slash_index + sort_host_.length());
513 } 387 }
514 388
515 } // namespace gfx. 389 } // namespace gfx.
OLDNEW
« no previous file with comments | « app/gfx/text_elider.h ('k') | chrome/browser/autocomplete/autocomplete.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698