favicon_url_parser.cc 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Copyright 2013 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. #include "components/favicon_base/favicon_url_parser.h"
  5. #include "base/notreached.h"
  6. #include "base/strings/string_number_conversions.h"
  7. #include "components/favicon_base/favicon_types.h"
  8. #include "net/base/url_util.h"
  9. #include "ui/base/webui/web_ui_util.h"
  10. #include "ui/gfx/favicon_size.h"
  11. namespace chrome {
  12. namespace {
  13. // Returns true if |search| is a substring of |path| which starts at
  14. // |start_index|.
  15. bool HasSubstringAt(const std::string& path,
  16. size_t start_index,
  17. const std::string& search) {
  18. return path.compare(start_index, search.length(), search) == 0;
  19. }
  20. // Parse with legacy FaviconUrlFormat::kFavicon format.
  21. bool ParseFaviconPathWithLegacyFormat(const std::string& path,
  22. chrome::ParsedFaviconPath* parsed) {
  23. // Parameters which can be used in chrome://favicon path. See file
  24. // "favicon_url_parser.h" for a description of what each one does.
  25. const char kIconURLParameter[] = "iconurl/";
  26. const char kSizeParameter[] = "size/";
  27. *parsed = chrome::ParsedFaviconPath();
  28. if (path.empty())
  29. return false;
  30. size_t parsed_index = 0;
  31. if (HasSubstringAt(path, parsed_index, kSizeParameter)) {
  32. parsed_index += strlen(kSizeParameter);
  33. size_t slash = path.find("/", parsed_index);
  34. if (slash == std::string::npos)
  35. return false;
  36. size_t scale_delimiter = path.find("@", parsed_index);
  37. std::string size_str;
  38. std::string scale_str;
  39. if (scale_delimiter == std::string::npos) {
  40. // Support the legacy size format of 'size/aa/' where 'aa' is the desired
  41. // size in DIP for the sake of not regressing the extensions which use it.
  42. size_str = path.substr(parsed_index, slash - parsed_index);
  43. } else {
  44. size_str = path.substr(parsed_index, scale_delimiter - parsed_index);
  45. scale_str = path.substr(scale_delimiter + 1,
  46. slash - scale_delimiter - 1);
  47. }
  48. if (!base::StringToInt(size_str, &parsed->size_in_dip))
  49. return false;
  50. if (!scale_str.empty())
  51. webui::ParseScaleFactor(scale_str, &parsed->device_scale_factor);
  52. parsed_index = slash + 1;
  53. }
  54. if (HasSubstringAt(path, parsed_index, kIconURLParameter)) {
  55. parsed_index += strlen(kIconURLParameter);
  56. parsed->icon_url = path.substr(parsed_index);
  57. } else {
  58. parsed->page_url = path.substr(parsed_index);
  59. }
  60. // The parsed index needs to be returned in order to allow Instant Extended
  61. // to translate favicon URLs using advanced parameters.
  62. // Example:
  63. // "chrome-search://favicon/size/16@2x/<renderer-id>/<most-visited-id>"
  64. // would be translated to:
  65. // "chrome-search://favicon/size/16@2x/<most-visited-item-with-given-id>".
  66. parsed->path_index = parsed_index;
  67. return true;
  68. }
  69. // Parse with FaviconUrlFormat::kFavicon2 format.
  70. bool ParseFaviconPathWithFavicon2Format(const std::string& path,
  71. chrome::ParsedFaviconPath* parsed) {
  72. if (path.empty())
  73. return false;
  74. GURL query_url = GURL("chrome://favicon2/").Resolve(path);
  75. *parsed = chrome::ParsedFaviconPath();
  76. for (net::QueryIterator it(query_url); !it.IsAtEnd(); it.Advance()) {
  77. const base::StringPiece key = it.GetKey();
  78. // Note: each of these keys can be used in chrome://favicon2 path. See file
  79. // "favicon_url_parser.h" for a description of what each one does.
  80. if (key == "allowGoogleServerFallback") {
  81. const std::string val = it.GetUnescapedValue();
  82. if (!(val == "0" || val == "1"))
  83. return false;
  84. parsed->allow_favicon_server_fallback = val == "1";
  85. } else if (key == "showFallbackMonogram") {
  86. parsed->show_fallback_monogram = true;
  87. } else if (key == "iconUrl") {
  88. parsed->icon_url = it.GetUnescapedValue();
  89. } else if (key == "pageUrl") {
  90. parsed->page_url = it.GetUnescapedValue();
  91. } else if (key == "scaleFactor" &&
  92. !webui::ParseScaleFactor(it.GetUnescapedValue(),
  93. &parsed->device_scale_factor)) {
  94. return false;
  95. } else if (key == "size" && !base::StringToInt(it.GetUnescapedValue(),
  96. &parsed->size_in_dip)) {
  97. return false;
  98. }
  99. }
  100. if (parsed->page_url.empty() && parsed->icon_url.empty())
  101. return false;
  102. if (parsed->allow_favicon_server_fallback && parsed->page_url.empty()) {
  103. // Since the server is queried by page url, we'll fail if no non-empty page
  104. // url is provided and the fallback parameter is still set to true.
  105. NOTIMPLEMENTED();
  106. return false;
  107. }
  108. return true;
  109. }
  110. } // namespace
  111. ParsedFaviconPath::ParsedFaviconPath() = default;
  112. ParsedFaviconPath::ParsedFaviconPath(const ParsedFaviconPath& other) = default;
  113. ParsedFaviconPath& ParsedFaviconPath::operator=(
  114. const ParsedFaviconPath& other) = default;
  115. bool ParseFaviconPath(const std::string& path,
  116. FaviconUrlFormat format,
  117. ParsedFaviconPath* parsed) {
  118. switch (format) {
  119. case FaviconUrlFormat::kFaviconLegacy:
  120. return ParseFaviconPathWithLegacyFormat(path, parsed);
  121. case FaviconUrlFormat::kFavicon2:
  122. return ParseFaviconPathWithFavicon2Format(path, parsed);
  123. }
  124. NOTREACHED();
  125. return false;
  126. }
  127. } // namespace chrome