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

Side by Side Diff: url/url_util.cc

Issue 2492753002: [WIP] [url_utils] Implement a contiguous SchemeSet to replace vector<SchemeWithType>
Patch Set: separate SchemeSet for blink migration Created 4 years 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
« no previous file with comments | « url/scheme_set.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 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 "url/url_util.h" 5 #include "url/url_util.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <string.h> 8 #include <string.h>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/debug/leak_annotations.h" 11 #include "base/debug/leak_annotations.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
14 #include "url/scheme_set.h"
14 #include "url/url_canon_internal.h" 15 #include "url/url_canon_internal.h"
15 #include "url/url_file.h" 16 #include "url/url_file.h"
16 #include "url/url_util_internal.h" 17 #include "url/url_util_internal.h"
17 18
18 namespace url { 19 namespace url {
19 20
20 namespace { 21 namespace {
21 22
22 const int kNumStandardURLSchemes = 10; 23 const int kNumStandardURLSchemes = 10;
23 const SchemeWithType kStandardURLSchemes[kNumStandardURLSchemes] = { 24 const SchemeWithType kStandardURLSchemes[kNumStandardURLSchemes] = {
(...skipping 13 matching lines...) Expand all
37 }; 38 };
38 39
39 const int kNumReferrerURLSchemes = 4; 40 const int kNumReferrerURLSchemes = 4;
40 const SchemeWithType kReferrerURLSchemes[kNumReferrerURLSchemes] = { 41 const SchemeWithType kReferrerURLSchemes[kNumReferrerURLSchemes] = {
41 {kHttpScheme, SCHEME_WITH_PORT}, 42 {kHttpScheme, SCHEME_WITH_PORT},
42 {kHttpsScheme, SCHEME_WITH_PORT}, 43 {kHttpsScheme, SCHEME_WITH_PORT},
43 {kHttpSuboriginScheme, SCHEME_WITH_PORT}, 44 {kHttpSuboriginScheme, SCHEME_WITH_PORT},
44 {kHttpsSuboriginScheme, SCHEME_WITH_PORT}, 45 {kHttpsSuboriginScheme, SCHEME_WITH_PORT},
45 }; 46 };
46 47
48 class SchemeWithTypeSet {
49 public:
50 SchemeWithTypeSet() {}
51
52 void add(const SchemeWithType& scheme_with_type) {
53 schemes_.add(scheme_with_type.scheme);
54 types_.push_back(scheme_with_type.type);
55 }
56
57 // Returns true and sets |type| to the SchemeType of the given scheme
58 // identified by |scheme| within |spec| if in |schemes|.
59 template <typename STR>
60 bool contains(base::BasicStringPiece<STR> scheme, SchemeType* type) {
61 size_t index = schemes_.find(scheme);
62 if (index == SchemeSet::npos)
63 return false;
64 if (type)
65 *type = types_[index];
66 return true;
67 }
68
69 private:
70 // Types and schemes must remain in-order with each other.
71 std::vector<SchemeType> types_;
72 SchemeSet schemes_;
73
74 DISALLOW_COPY_AND_ASSIGN(SchemeWithTypeSet);
75 };
76
47 // Lists of the currently installed standard and referrer schemes. These lists 77 // Lists of the currently installed standard and referrer schemes. These lists
48 // are lazily initialized by InitStandardSchemes and InitReferrerSchemes and are 78 // are lazily initialized by InitStandardSchemes and InitReferrerSchemes and are
49 // leaked on shutdown to prevent any destructors from being called that will 79 // leaked on shutdown to prevent any destructors from being called that will
50 // slow us down or cause problems. 80 // slow us down or cause problems.
51 std::vector<SchemeWithType>* standard_schemes = nullptr; 81 SchemeWithTypeSet* standard_schemes = nullptr;
52 std::vector<SchemeWithType>* referrer_schemes = nullptr; 82 SchemeWithTypeSet* referrer_schemes = nullptr;
53 83
54 // See the LockSchemeRegistries declaration in the header. 84 // See the LockSchemeRegistries declaration in the header.
55 bool scheme_registries_locked = false; 85 bool scheme_registries_locked = false;
56 86
57 // This template converts a given character type to the corresponding 87 // This template converts a given character type to the corresponding
58 // StringPiece type. 88 // StringPiece type.
59 template<typename CHAR> struct CharToStringPiece { 89 template<typename CHAR> struct CharToStringPiece {
60 }; 90 };
61 template<> struct CharToStringPiece<char> { 91 template<> struct CharToStringPiece<char> {
62 typedef base::StringPiece Piece; 92 typedef base::StringPiece Piece;
63 }; 93 };
64 template<> struct CharToStringPiece<base::char16> { 94 template<> struct CharToStringPiece<base::char16> {
65 typedef base::StringPiece16 Piece; 95 typedef base::StringPiece16 Piece;
66 }; 96 };
67 97
68 void InitSchemes(std::vector<SchemeWithType>** schemes, 98 void InitSchemes(SchemeWithTypeSet** schemes,
69 const SchemeWithType* initial_schemes, 99 const SchemeWithType* initial_schemes,
70 size_t size) { 100 size_t size) {
71 if (*schemes) 101 if (*schemes)
72 return; 102 return;
73 *schemes = new std::vector<SchemeWithType>(size); 103 *schemes = new SchemeWithTypeSet();
74 for (size_t i = 0; i < size; i++) { 104 for (size_t i = 0; i < size; i++) {
75 (*schemes)->push_back(initial_schemes[i]); 105 (*schemes)->add(initial_schemes[i]);
76 } 106 }
77 } 107 }
78 108
79 // Ensures that the standard_schemes list is initialized, does nothing if 109 // Ensures that the standard_schemes list is initialized, does nothing if
80 // it already has values. 110 // it already has values.
81 void InitStandardSchemes() { 111 void InitStandardSchemes() {
82 InitSchemes(&standard_schemes, kStandardURLSchemes, kNumStandardURLSchemes); 112 InitSchemes(&standard_schemes, kStandardURLSchemes, kNumStandardURLSchemes);
83 } 113 }
84 114
85 // Ensures that the referrer_schemes list is initialized, does nothing if 115 // Ensures that the referrer_schemes list is initialized, does nothing if
86 // it already has values. 116 // it already has values.
87 void InitReferrerSchemes() { 117 void InitReferrerSchemes() {
88 InitSchemes(&referrer_schemes, kReferrerURLSchemes, kNumReferrerURLSchemes); 118 InitSchemes(&referrer_schemes, kReferrerURLSchemes, kNumReferrerURLSchemes);
89 } 119 }
90 120
91 // Given a string and a range inside the string, compares it to the given 121 // Given a string and a range inside the string, compares it to the given
92 // lower-case |compare_to| buffer. 122 // lower-case |compare_to| buffer.
93 template<typename CHAR> 123 template<typename CHAR>
94 inline bool DoCompareSchemeComponent(const CHAR* spec, 124 inline bool DoCompareSchemeComponent(const CHAR* spec,
95 const Component& component, 125 const Component& component,
96 const char* compare_to) { 126 const char* compare_to) {
97 if (!component.is_nonempty()) 127 if (!component.is_nonempty())
98 return compare_to[0] == 0; // When component is empty, match empty scheme. 128 return compare_to[0] == 0; // When component is empty, match empty scheme.
99 return base::LowerCaseEqualsASCII( 129 return base::LowerCaseEqualsASCII(
100 typename CharToStringPiece<CHAR>::Piece( 130 typename CharToStringPiece<CHAR>::Piece(
101 &spec[component.begin], component.len), 131 &spec[component.begin], component.len),
102 compare_to); 132 compare_to);
103 } 133 }
104 134
105 // Returns true and sets |type| to the SchemeType of the given scheme
106 // identified by |scheme| within |spec| if in |schemes|.
107 template<typename CHAR>
108 bool DoIsInSchemes(const CHAR* spec,
109 const Component& scheme,
110 SchemeType* type,
111 const std::vector<SchemeWithType>& schemes) {
112 if (!scheme.is_nonempty())
113 return false; // Empty or invalid schemes are non-standard.
114
115 for (const SchemeWithType& scheme_with_type : schemes) {
116 if (base::LowerCaseEqualsASCII(typename CharToStringPiece<CHAR>::Piece(
117 &spec[scheme.begin], scheme.len),
118 scheme_with_type.scheme)) {
119 *type = scheme_with_type.type;
120 return true;
121 }
122 }
123 return false;
124 }
125
126 template<typename CHAR> 135 template<typename CHAR>
127 bool DoIsStandard(const CHAR* spec, const Component& scheme, SchemeType* type) { 136 bool DoIsStandard(const CHAR* spec, const Component& scheme, SchemeType* type) {
128 InitStandardSchemes(); 137 InitStandardSchemes();
129 return DoIsInSchemes(spec, scheme, type, *standard_schemes); 138 return standard_schemes->contains(
139 typename CharToStringPiece<CHAR>::Piece(&spec[scheme.begin], scheme.len),
140 type);
130 } 141 }
131 142
132 143
133 template<typename CHAR> 144 template<typename CHAR>
134 bool DoFindAndCompareScheme(const CHAR* str, 145 bool DoFindAndCompareScheme(const CHAR* str,
135 int str_len, 146 int str_len,
136 const char* compare, 147 const char* compare,
137 Component* found_scheme) { 148 Component* found_scheme) {
138 // Before extracting scheme, canonicalize the URL to remove any whitespace. 149 // Before extracting scheme, canonicalize the URL to remove any whitespace.
139 // This matches the canonicalization done in DoCanonicalize function. 150 // This matches the canonicalization done in DoCanonicalize function.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 } 199 }
189 #endif 200 #endif
190 201
191 Component scheme; 202 Component scheme;
192 if (!ExtractScheme(spec, spec_len, &scheme)) 203 if (!ExtractScheme(spec, spec_len, &scheme))
193 return false; 204 return false;
194 205
195 // This is the parsed version of the input URL, we have to canonicalize it 206 // This is the parsed version of the input URL, we have to canonicalize it
196 // before storing it in our object. 207 // before storing it in our object.
197 bool success; 208 bool success;
198 SchemeType unused_scheme_type = SCHEME_WITH_PORT;
199 if (DoCompareSchemeComponent(spec, scheme, url::kFileScheme)) { 209 if (DoCompareSchemeComponent(spec, scheme, url::kFileScheme)) {
200 // File URLs are special. 210 // File URLs are special.
201 ParseFileURL(spec, spec_len, &parsed_input); 211 ParseFileURL(spec, spec_len, &parsed_input);
202 success = CanonicalizeFileURL(spec, spec_len, parsed_input, 212 success = CanonicalizeFileURL(spec, spec_len, parsed_input,
203 charset_converter, output, output_parsed); 213 charset_converter, output, output_parsed);
204 } else if (DoCompareSchemeComponent(spec, scheme, url::kFileSystemScheme)) { 214 } else if (DoCompareSchemeComponent(spec, scheme, url::kFileSystemScheme)) {
205 // Filesystem URLs are special. 215 // Filesystem URLs are special.
206 ParseFileSystemURL(spec, spec_len, &parsed_input); 216 ParseFileSystemURL(spec, spec_len, &parsed_input);
207 success = CanonicalizeFileSystemURL(spec, spec_len, parsed_input, 217 success = CanonicalizeFileSystemURL(spec, spec_len, parsed_input,
208 charset_converter, output, 218 charset_converter, output,
209 output_parsed); 219 output_parsed);
210 220
211 } else if (DoIsStandard(spec, scheme, &unused_scheme_type)) { 221 } else if (DoIsStandard(spec, scheme, nullptr)) {
212 // All "normal" URLs. 222 // All "normal" URLs.
213 ParseStandardURL(spec, spec_len, &parsed_input); 223 ParseStandardURL(spec, spec_len, &parsed_input);
214 success = CanonicalizeStandardURL(spec, spec_len, parsed_input, 224 success = CanonicalizeStandardURL(spec, spec_len, parsed_input,
215 charset_converter, output, output_parsed); 225 charset_converter, output, output_parsed);
216 226
217 } else if (DoCompareSchemeComponent(spec, scheme, url::kMailToScheme)) { 227 } else if (DoCompareSchemeComponent(spec, scheme, url::kMailToScheme)) {
218 // Mailto URLs are treated like standard URLs, with only a scheme, path, 228 // Mailto URLs are treated like standard URLs, with only a scheme, path,
219 // and query. 229 // and query.
220 ParseMailtoURL(spec, spec_len, &parsed_input); 230 ParseMailtoURL(spec, spec_len, &parsed_input);
221 success = CanonicalizeMailtoURL(spec, spec_len, parsed_input, output, 231 success = CanonicalizeMailtoURL(spec, spec_len, parsed_input, output,
(...skipping 28 matching lines...) Expand all
250 bool base_is_hierarchical = false; 260 bool base_is_hierarchical = false;
251 if (base_spec && 261 if (base_spec &&
252 base_parsed.scheme.is_nonempty()) { 262 base_parsed.scheme.is_nonempty()) {
253 int after_scheme = base_parsed.scheme.end() + 1; // Skip past the colon. 263 int after_scheme = base_parsed.scheme.end() + 1; // Skip past the colon.
254 int num_slashes = CountConsecutiveSlashes(base_spec, after_scheme, 264 int num_slashes = CountConsecutiveSlashes(base_spec, after_scheme,
255 base_spec_len); 265 base_spec_len);
256 base_is_authority_based = num_slashes > 1; 266 base_is_authority_based = num_slashes > 1;
257 base_is_hierarchical = num_slashes > 0; 267 base_is_hierarchical = num_slashes > 0;
258 } 268 }
259 269
260 SchemeType unused_scheme_type = SCHEME_WITH_PORT;
261 bool standard_base_scheme = 270 bool standard_base_scheme =
262 base_parsed.scheme.is_nonempty() && 271 base_parsed.scheme.is_nonempty() &&
263 DoIsStandard(base_spec, base_parsed.scheme, &unused_scheme_type); 272 DoIsStandard(base_spec, base_parsed.scheme, nullptr);
264 273
265 bool is_relative; 274 bool is_relative;
266 Component relative_component; 275 Component relative_component;
267 if (!IsRelativeURL(base_spec, base_parsed, relative, relative_length, 276 if (!IsRelativeURL(base_spec, base_parsed, relative, relative_length,
268 (base_is_hierarchical || standard_base_scheme), 277 (base_is_hierarchical || standard_base_scheme),
269 &is_relative, &relative_component)) { 278 &is_relative, &relative_component)) {
270 // Error resolving. 279 // Error resolving.
271 return false; 280 return false;
272 } 281 }
273 282
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 // If we get here, then we know the scheme doesn't need to be replaced, so can 383 // If we get here, then we know the scheme doesn't need to be replaced, so can
375 // just key off the scheme in the spec to know how to do the replacements. 384 // just key off the scheme in the spec to know how to do the replacements.
376 if (DoCompareSchemeComponent(spec, parsed.scheme, url::kFileScheme)) { 385 if (DoCompareSchemeComponent(spec, parsed.scheme, url::kFileScheme)) {
377 return ReplaceFileURL(spec, parsed, replacements, charset_converter, output, 386 return ReplaceFileURL(spec, parsed, replacements, charset_converter, output,
378 out_parsed); 387 out_parsed);
379 } 388 }
380 if (DoCompareSchemeComponent(spec, parsed.scheme, url::kFileSystemScheme)) { 389 if (DoCompareSchemeComponent(spec, parsed.scheme, url::kFileSystemScheme)) {
381 return ReplaceFileSystemURL(spec, parsed, replacements, charset_converter, 390 return ReplaceFileSystemURL(spec, parsed, replacements, charset_converter,
382 output, out_parsed); 391 output, out_parsed);
383 } 392 }
384 SchemeType unused_scheme_type = SCHEME_WITH_PORT; 393 if (DoIsStandard(spec, parsed.scheme, nullptr)) {
385 if (DoIsStandard(spec, parsed.scheme, &unused_scheme_type)) {
386 return ReplaceStandardURL(spec, parsed, replacements, charset_converter, 394 return ReplaceStandardURL(spec, parsed, replacements, charset_converter,
387 output, out_parsed); 395 output, out_parsed);
388 } 396 }
389 if (DoCompareSchemeComponent(spec, parsed.scheme, url::kMailToScheme)) { 397 if (DoCompareSchemeComponent(spec, parsed.scheme, url::kMailToScheme)) {
390 return ReplaceMailtoURL(spec, parsed, replacements, output, out_parsed); 398 return ReplaceMailtoURL(spec, parsed, replacements, output, out_parsed);
391 } 399 }
392 400
393 // Default is a path URL. 401 // Default is a path URL.
394 return ReplacePathURL(spec, parsed, replacements, output, out_parsed); 402 return ReplacePathURL(spec, parsed, replacements, output, out_parsed);
395 } 403 }
396 404
397 void DoAddScheme(const char* new_scheme, 405 void DoAddScheme(const char* new_scheme,
398 SchemeType type, 406 SchemeType type,
399 std::vector<SchemeWithType>* schemes) { 407 SchemeWithTypeSet* schemes) {
400 DCHECK(schemes); 408 DCHECK(schemes);
401 // If this assert triggers, it means you've called Add*Scheme after 409 // If this assert triggers, it means you've called Add*Scheme after
402 // LockSchemeRegistries has been called (see the header file for 410 // LockSchemeRegistries has been called (see the header file for
403 // LockSchemeRegistries for more). 411 // LockSchemeRegistries for more).
404 // 412 //
405 // This normally means you're trying to set up a new scheme too late in your 413 // This normally means you're trying to set up a new scheme too late in your
406 // application's init process. Locate where your app does this initialization 414 // application's init process. Locate where your app does this initialization
407 // and calls LockSchemeRegistries, and add your new scheme there. 415 // and calls LockSchemeRegistries, and add your new scheme there.
408 DCHECK(!scheme_registries_locked) 416 DCHECK(!scheme_registries_locked)
409 << "Trying to add a scheme after the lists have been locked."; 417 << "Trying to add a scheme after the lists have been locked.";
410 418
411 size_t scheme_len = strlen(new_scheme); 419 size_t scheme_len = strlen(new_scheme);
412 if (scheme_len == 0) 420 if (scheme_len == 0)
413 return; 421 return;
414 422
415 // Duplicate the scheme into a new buffer and add it to the list of standard
416 // schemes. This pointer will be leaked on shutdown.
417 char* dup_scheme = new char[scheme_len + 1];
418 ANNOTATE_LEAKING_OBJECT_PTR(dup_scheme);
419 memcpy(dup_scheme, new_scheme, scheme_len + 1);
420
421 SchemeWithType scheme_with_type; 423 SchemeWithType scheme_with_type;
422 scheme_with_type.scheme = dup_scheme; 424 scheme_with_type.scheme = new_scheme;
423 scheme_with_type.type = type; 425 scheme_with_type.type = type;
424 schemes->push_back(scheme_with_type); 426 schemes->add(scheme_with_type);
425 } 427 }
426 428
427 } // namespace 429 } // namespace
428 430
429 void Initialize() { 431 void Initialize() {
430 InitStandardSchemes(); 432 InitStandardSchemes();
431 InitReferrerSchemes(); 433 InitReferrerSchemes();
432 } 434 }
433 435
434 void Shutdown() { 436 void Shutdown() {
(...skipping 15 matching lines...) Expand all
450 void AddReferrerScheme(const char* new_scheme, SchemeType type) { 452 void AddReferrerScheme(const char* new_scheme, SchemeType type) {
451 InitReferrerSchemes(); 453 InitReferrerSchemes();
452 DoAddScheme(new_scheme, type, referrer_schemes); 454 DoAddScheme(new_scheme, type, referrer_schemes);
453 } 455 }
454 456
455 void LockSchemeRegistries() { 457 void LockSchemeRegistries() {
456 scheme_registries_locked = true; 458 scheme_registries_locked = true;
457 } 459 }
458 460
459 bool IsStandard(const char* spec, const Component& scheme) { 461 bool IsStandard(const char* spec, const Component& scheme) {
460 SchemeType unused_scheme_type; 462 return DoIsStandard(spec, scheme, nullptr);
461 return DoIsStandard(spec, scheme, &unused_scheme_type);
462 } 463 }
463 464
464 bool GetStandardSchemeType(const char* spec, 465 bool GetStandardSchemeType(const char* spec,
465 const Component& scheme, 466 const Component& scheme,
466 SchemeType* type) { 467 SchemeType* type) {
467 return DoIsStandard(spec, scheme, type); 468 return DoIsStandard(spec, scheme, type);
468 } 469 }
469 470
470 bool IsStandard(const base::char16* spec, const Component& scheme) { 471 bool IsStandard(const base::char16* spec, const Component& scheme) {
471 SchemeType unused_scheme_type; 472 return DoIsStandard(spec, scheme, nullptr);
472 return DoIsStandard(spec, scheme, &unused_scheme_type);
473 } 473 }
474 474
475 bool IsReferrerScheme(const char* spec, const Component& scheme) { 475 bool IsReferrerScheme(const char* spec, const Component& scheme) {
476 InitReferrerSchemes(); 476 InitReferrerSchemes();
477 SchemeType unused_scheme_type; 477 return referrer_schemes->contains(
478 return DoIsInSchemes(spec, scheme, &unused_scheme_type, *referrer_schemes); 478 base::StringPiece(&spec[scheme.begin], scheme.len), nullptr);
479 } 479 }
480 480
481 bool FindAndCompareScheme(const char* str, 481 bool FindAndCompareScheme(const char* str,
482 int str_len, 482 int str_len,
483 const char* compare, 483 const char* compare,
484 Component* found_scheme) { 484 Component* found_scheme) {
485 return DoFindAndCompareScheme(str, str_len, compare, found_scheme); 485 return DoFindAndCompareScheme(str, str_len, compare, found_scheme);
486 } 486 }
487 487
488 bool FindAndCompareScheme(const base::char16* str, 488 bool FindAndCompareScheme(const base::char16* str,
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 return DoCompareSchemeComponent(spec, component, compare_to); 663 return DoCompareSchemeComponent(spec, component, compare_to);
664 } 664 }
665 665
666 bool CompareSchemeComponent(const base::char16* spec, 666 bool CompareSchemeComponent(const base::char16* spec,
667 const Component& component, 667 const Component& component,
668 const char* compare_to) { 668 const char* compare_to) {
669 return DoCompareSchemeComponent(spec, component, compare_to); 669 return DoCompareSchemeComponent(spec, component, compare_to);
670 } 670 }
671 671
672 } // namespace url 672 } // namespace url
OLDNEW
« no previous file with comments | « url/scheme_set.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698