| OLD | NEW |
| 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 #ifdef WIN32 | 5 #ifdef WIN32 |
| 6 #include <windows.h> | 6 #include <windows.h> |
| 7 #else | 7 #else |
| 8 #include <pthread.h> | 8 #include <pthread.h> |
| 9 #endif | 9 #endif |
| 10 | 10 |
| 11 #include <algorithm> | 11 #include <algorithm> |
| 12 #include <ostream> | 12 #include <ostream> |
| 13 | 13 |
| 14 #include "url/gurl.h" | 14 #include "url/gurl.h" |
| 15 | 15 |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "url/url_canon_stdstring.h" | 17 #include "url/url_canon_stdstring.h" |
| 18 #include "url/url_util.h" | 18 #include "url/url_util.h" |
| 19 | 19 |
| 20 namespace { | 20 namespace { |
| 21 | 21 |
| 22 // External template that can handle initialization of either character type. | |
| 23 // The input spec is given, and the canonical version will be placed in | |
| 24 // |*canonical|, along with the parsing of the canonical spec in |*parsed|. | |
| 25 template<typename STR> | |
| 26 bool InitCanonical(const STR& input_spec, | |
| 27 std::string* canonical, | |
| 28 url_parse::Parsed* parsed) { | |
| 29 // Reserve enough room in the output for the input, plus some extra so that | |
| 30 // we have room if we have to escape a few things without reallocating. | |
| 31 canonical->reserve(input_spec.size() + 32); | |
| 32 url_canon::StdStringCanonOutput output(canonical); | |
| 33 bool success = url_util::Canonicalize( | |
| 34 input_spec.data(), static_cast<int>(input_spec.length()), | |
| 35 NULL, &output, parsed); | |
| 36 | |
| 37 output.Complete(); // Must be done before using string. | |
| 38 return success; | |
| 39 } | |
| 40 | |
| 41 static std::string* empty_string = NULL; | 22 static std::string* empty_string = NULL; |
| 42 static GURL* empty_gurl = NULL; | 23 static GURL* empty_gurl = NULL; |
| 43 | 24 |
| 44 #ifdef WIN32 | 25 #ifdef WIN32 |
| 45 | 26 |
| 46 // Returns a static reference to an empty string for returning a reference | 27 // Returns a static reference to an empty string for returning a reference |
| 47 // when there is no underlying string. | 28 // when there is no underlying string. |
| 48 const std::string& EmptyStringForGURL() { | 29 const std::string& EmptyStringForGURL() { |
| 49 // Avoid static object construction/destruction on startup/shutdown. | 30 // Avoid static object construction/destruction on startup/shutdown. |
| 50 if (!empty_string) { | 31 if (!empty_string) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 : spec_(other.spec_), | 68 : spec_(other.spec_), |
| 88 is_valid_(other.is_valid_), | 69 is_valid_(other.is_valid_), |
| 89 parsed_(other.parsed_) { | 70 parsed_(other.parsed_) { |
| 90 if (other.inner_url_) | 71 if (other.inner_url_) |
| 91 inner_url_.reset(new GURL(*other.inner_url_)); | 72 inner_url_.reset(new GURL(*other.inner_url_)); |
| 92 // Valid filesystem urls should always have an inner_url_. | 73 // Valid filesystem urls should always have an inner_url_. |
| 93 DCHECK(!is_valid_ || !SchemeIsFileSystem() || inner_url_); | 74 DCHECK(!is_valid_ || !SchemeIsFileSystem() || inner_url_); |
| 94 } | 75 } |
| 95 | 76 |
| 96 GURL::GURL(const std::string& url_string) { | 77 GURL::GURL(const std::string& url_string) { |
| 97 is_valid_ = InitCanonical(url_string, &spec_, &parsed_); | 78 InitCanonical(url_string, true); |
| 98 if (is_valid_ && SchemeIsFileSystem()) { | |
| 99 inner_url_.reset( | |
| 100 new GURL(spec_.data(), parsed_.Length(), | |
| 101 *parsed_.inner_parsed(), true)); | |
| 102 } | |
| 103 } | 79 } |
| 104 | 80 |
| 105 GURL::GURL(const base::string16& url_string) { | 81 GURL::GURL(const base::string16& url_string) { |
| 106 is_valid_ = InitCanonical(url_string, &spec_, &parsed_); | 82 InitCanonical(url_string, true); |
| 107 if (is_valid_ && SchemeIsFileSystem()) { | 83 } |
| 108 inner_url_.reset( | 84 |
| 109 new GURL(spec_.data(), parsed_.Length(), | 85 GURL::GURL(const std::string& url_string, RetainWhiteSpaceSelector) { |
| 110 *parsed_.inner_parsed(), true)); | 86 InitCanonical(url_string, false); |
| 111 } | |
| 112 } | 87 } |
| 113 | 88 |
| 114 GURL::GURL(const char* canonical_spec, size_t canonical_spec_len, | 89 GURL::GURL(const char* canonical_spec, size_t canonical_spec_len, |
| 115 const url_parse::Parsed& parsed, bool is_valid) | 90 const url_parse::Parsed& parsed, bool is_valid) |
| 116 : spec_(canonical_spec, canonical_spec_len), | 91 : spec_(canonical_spec, canonical_spec_len), |
| 117 is_valid_(is_valid), | 92 is_valid_(is_valid), |
| 118 parsed_(parsed) { | 93 parsed_(parsed) { |
| 119 InitializeFromCanonicalSpec(); | 94 InitializeFromCanonicalSpec(); |
| 120 } | 95 } |
| 121 | 96 |
| 122 GURL::GURL(std::string canonical_spec, | 97 GURL::GURL(std::string canonical_spec, |
| 123 const url_parse::Parsed& parsed, bool is_valid) | 98 const url_parse::Parsed& parsed, bool is_valid) |
| 124 : is_valid_(is_valid), | 99 : is_valid_(is_valid), |
| 125 parsed_(parsed) { | 100 parsed_(parsed) { |
| 126 spec_.swap(canonical_spec); | 101 spec_.swap(canonical_spec); |
| 127 InitializeFromCanonicalSpec(); | 102 InitializeFromCanonicalSpec(); |
| 128 } | 103 } |
| 129 | 104 |
| 105 template<typename STR> |
| 106 void GURL::InitCanonical(const STR& input_spec, bool trim_path_end) { |
| 107 // Reserve enough room in the output for the input, plus some extra so that |
| 108 // we have room if we have to escape a few things without reallocating. |
| 109 spec_.reserve(input_spec.size() + 32); |
| 110 url_canon::StdStringCanonOutput output(&spec_); |
| 111 is_valid_ = url_util::Canonicalize( |
| 112 input_spec.data(), static_cast<int>(input_spec.length()), trim_path_end, |
| 113 NULL, &output, &parsed_); |
| 114 |
| 115 output.Complete(); // Must be done before using string. |
| 116 if (is_valid_ && SchemeIsFileSystem()) { |
| 117 inner_url_.reset(new GURL(spec_.data(), parsed_.Length(), |
| 118 *parsed_.inner_parsed(), true)); |
| 119 } |
| 120 } |
| 121 |
| 130 void GURL::InitializeFromCanonicalSpec() { | 122 void GURL::InitializeFromCanonicalSpec() { |
| 131 if (is_valid_ && SchemeIsFileSystem()) { | 123 if (is_valid_ && SchemeIsFileSystem()) { |
| 132 inner_url_.reset( | 124 inner_url_.reset( |
| 133 new GURL(spec_.data(), parsed_.Length(), | 125 new GURL(spec_.data(), parsed_.Length(), |
| 134 *parsed_.inner_parsed(), true)); | 126 *parsed_.inner_parsed(), true)); |
| 135 } | 127 } |
| 136 | 128 |
| 137 #ifndef NDEBUG | 129 #ifndef NDEBUG |
| 138 // For testing purposes, check that the parsed canonical URL is identical to | 130 // For testing purposes, check that the parsed canonical URL is identical to |
| 139 // what we would have produced. Skip checking for invalid URLs have no meaning | 131 // what we would have produced. Skip checking for invalid URLs have no meaning |
| 140 // and we can't always canonicalize then reproducabely. | 132 // and we can't always canonicalize then reproducabely. |
| 141 if (is_valid_) { | 133 if (is_valid_) { |
| 142 url_parse::Component scheme; | 134 url_parse::Component scheme; |
| 135 // We can't do this check on the inner_url of a filesystem URL, as |
| 136 // canonical_spec actually points to the start of the outer URL, so we'd |
| 137 // end up with infinite recursion in this constructor. |
| 143 if (!url_util::FindAndCompareScheme(spec_.data(), spec_.length(), | 138 if (!url_util::FindAndCompareScheme(spec_.data(), spec_.length(), |
| 144 "filesystem", &scheme) || | 139 "filesystem", &scheme) || |
| 145 scheme.begin == parsed_.scheme.begin) { | 140 scheme.begin == parsed_.scheme.begin) { |
| 146 // We can't do this check on the inner_url of a filesystem URL, as | 141 // We need to retain trailing whitespace on path URLs, as the |parsed_| |
| 147 // canonical_spec actually points to the start of the outer URL, so we'd | 142 // spec we originally received may legitimately contain trailing white- |
| 148 // end up with infinite recursion in this constructor. | 143 // space on the path or components e.g. if the #ref has been |
| 149 GURL test_url(spec_); | 144 // removed from a "foo:hello #ref" URL (see http://crbug.com/291747). |
| 145 GURL test_url(spec_, RETAIN_TRAILING_PATH_WHITEPACE); |
| 150 | 146 |
| 151 DCHECK(test_url.is_valid_ == is_valid_); | 147 DCHECK(test_url.is_valid_ == is_valid_); |
| 152 DCHECK(test_url.spec_ == spec_); | 148 DCHECK(test_url.spec_ == spec_); |
| 153 | 149 |
| 154 DCHECK(test_url.parsed_.scheme == parsed_.scheme); | 150 DCHECK(test_url.parsed_.scheme == parsed_.scheme); |
| 155 DCHECK(test_url.parsed_.username == parsed_.username); | 151 DCHECK(test_url.parsed_.username == parsed_.username); |
| 156 DCHECK(test_url.parsed_.password == parsed_.password); | 152 DCHECK(test_url.parsed_.password == parsed_.password); |
| 157 DCHECK(test_url.parsed_.host == parsed_.host); | 153 DCHECK(test_url.parsed_.host == parsed_.host); |
| 158 DCHECK(test_url.parsed_.port == parsed_.port); | 154 DCHECK(test_url.parsed_.port == parsed_.port); |
| 159 DCHECK(test_url.parsed_.path == parsed_.path); | 155 DCHECK(test_url.parsed_.path == parsed_.path); |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 void GURL::Swap(GURL* other) { | 505 void GURL::Swap(GURL* other) { |
| 510 spec_.swap(other->spec_); | 506 spec_.swap(other->spec_); |
| 511 std::swap(is_valid_, other->is_valid_); | 507 std::swap(is_valid_, other->is_valid_); |
| 512 std::swap(parsed_, other->parsed_); | 508 std::swap(parsed_, other->parsed_); |
| 513 inner_url_.swap(other->inner_url_); | 509 inner_url_.swap(other->inner_url_); |
| 514 } | 510 } |
| 515 | 511 |
| 516 std::ostream& operator<<(std::ostream& out, const GURL& url) { | 512 std::ostream& operator<<(std::ostream& out, const GURL& url) { |
| 517 return out << url.possibly_invalid_spec(); | 513 return out << url.possibly_invalid_spec(); |
| 518 } | 514 } |
| OLD | NEW |