1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef WIN32 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <windows.h> 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#else 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <pthread.h> 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <algorithm> 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <ostream> 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "url/gurl.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "url/url_canon_stdstring.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "url/url_util.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static std::string* empty_string = NULL; 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static GURL* empty_gurl = NULL; 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef WIN32 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Returns a static reference to an empty string for returning a reference 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// when there is no underlying string. 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::string& EmptyStringForGURL() { 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Avoid static object construction/destruction on startup/shutdown. 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!empty_string) { 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Create the string. Be careful that we don't break in the case that this 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // is being called from multiple threads. Statics are not threadsafe. 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string* new_empty_string = new std::string; 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (InterlockedCompareExchangePointer( 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reinterpret_cast<PVOID*>(&empty_string), new_empty_string, NULL)) { 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The old value was non-NULL, so no replacement was done. Another 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // thread did the initialization out from under us. 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delete new_empty_string; 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return *empty_string; 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#else 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static pthread_once_t empty_string_once = PTHREAD_ONCE_INIT; 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static pthread_once_t empty_gurl_once = PTHREAD_ONCE_INIT; 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EmptyStringForGURLOnce(void) { 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) empty_string = new std::string; 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::string& EmptyStringForGURL() { 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Avoid static object construction/destruction on startup/shutdown. 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pthread_once(&empty_string_once, EmptyStringForGURLOnce); 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return *empty_string; 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // WIN32 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)GURL::GURL() : is_valid_(false) { 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL::GURL(const GURL& other) 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : spec_(other.spec_), 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_valid_(other.is_valid_), 701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parsed_(other.parsed_) { 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (other.inner_url_) 721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) inner_url_.reset(new GURL(*other.inner_url_)); 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Valid filesystem urls should always have an inner_url_. 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!is_valid_ || !SchemeIsFileSystem() || inner_url_); 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)GURL::GURL(const std::string& url_string) { 78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) InitCanonical(url_string, true); 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)GURL::GURL(const base::string16& url_string) { 82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) InitCanonical(url_string, true); 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)GURL::GURL(const std::string& url_string, RetainWhiteSpaceSelector) { 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) InitCanonical(url_string, false); 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 890529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochGURL::GURL(const char* canonical_spec, 900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch size_t canonical_spec_len, 910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const url::Parsed& parsed, 920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch bool is_valid) 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : spec_(canonical_spec, canonical_spec_len), 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_valid_(is_valid), 951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parsed_(parsed) { 96558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch InitializeFromCanonicalSpec(); 97558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 98558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 990529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochGURL::GURL(std::string canonical_spec, const url::Parsed& parsed, bool is_valid) 100558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch : is_valid_(is_valid), 1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parsed_(parsed) { 102558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch spec_.swap(canonical_spec); 103558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch InitializeFromCanonicalSpec(); 104558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 105558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)template<typename STR> 107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void GURL::InitCanonical(const STR& input_spec, bool trim_path_end) { 108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Reserve enough room in the output for the input, plus some extra so that 109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // we have room if we have to escape a few things without reallocating. 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) spec_.reserve(input_spec.size() + 32); 1110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url::StdStringCanonOutput output(&spec_); 1120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch is_valid_ = url::Canonicalize( 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) input_spec.data(), static_cast<int>(input_spec.length()), trim_path_end, 114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) NULL, &output, &parsed_); 115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) output.Complete(); // Must be done before using string. 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (is_valid_ && SchemeIsFileSystem()) { 118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) inner_url_.reset(new GURL(spec_.data(), parsed_.Length(), 119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *parsed_.inner_parsed(), true)); 120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 123558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid GURL::InitializeFromCanonicalSpec() { 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (is_valid_ && SchemeIsFileSystem()) { 1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) inner_url_.reset( 1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new GURL(spec_.data(), parsed_.Length(), 1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) *parsed_.inner_parsed(), true)); 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifndef NDEBUG 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // For testing purposes, check that the parsed canonical URL is identical to 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // what we would have produced. Skip checking for invalid URLs have no meaning 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // and we can't always canonicalize then reproducabely. 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (is_valid_) { 1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url::Component scheme; 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // We can't do this check on the inner_url of a filesystem URL, as 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // canonical_spec actually points to the start of the outer URL, so we'd 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // end up with infinite recursion in this constructor. 1390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!url::FindAndCompareScheme(spec_.data(), spec_.length(), 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) url::kFileSystemScheme, &scheme) || 141558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch scheme.begin == parsed_.scheme.begin) { 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // We need to retain trailing whitespace on path URLs, as the |parsed_| 143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // spec we originally received may legitimately contain trailing white- 144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // space on the path or components e.g. if the #ref has been 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // removed from a "foo:hello #ref" URL (see http://crbug.com/291747). 146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) GURL test_url(spec_, RETAIN_TRAILING_PATH_WHITEPACE); 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.is_valid_ == is_valid_); 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.spec_ == spec_); 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.parsed_.scheme == parsed_.scheme); 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.parsed_.username == parsed_.username); 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.parsed_.password == parsed_.password); 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.parsed_.host == parsed_.host); 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.parsed_.port == parsed_.port); 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.parsed_.path == parsed_.path); 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.parsed_.query == parsed_.query); 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(test_url.parsed_.ref == parsed_.ref); 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL::~GURL() { 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)GURL& GURL::operator=(GURL other) { 1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Swap(&other); 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return *this; 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::string& GURL::spec() const { 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (is_valid_ || spec_.empty()) 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return spec_; 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(false) << "Trying to get the spec of an invalid URL!"; 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return EmptyStringForGURL(); 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GURL::Resolve(const std::string& relative) const { 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ResolveWithCharsetConverter(relative, NULL); 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)GURL GURL::Resolve(const base::string16& relative) const { 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ResolveWithCharsetConverter(relative, NULL); 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Note: code duplicated below (it's inconvenient to use a template here). 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GURL::ResolveWithCharsetConverter( 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& relative, 1900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url::CharsetConverter* charset_converter) const { 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Not allowed for invalid URLs. 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_valid_) 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(); 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL result; 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Reserve enough room in the output for the input, plus some extra so that 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // we have room if we have to escape a few things without reallocating. 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.spec_.reserve(spec_.size() + 32); 2000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url::StdStringCanonOutput output(&result.spec_); 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!url::ResolveRelative(spec_.data(), static_cast<int>(spec_.length()), 2030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parsed_, relative.data(), 2040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch static_cast<int>(relative.length()), 2050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch charset_converter, &output, &result.parsed_)) { 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Error resolving, return an empty URL. 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(); 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output.Complete(); 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.is_valid_ = true; 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (result.SchemeIsFileSystem()) { 2131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) result.inner_url_.reset( 2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new GURL(result.spec_.data(), result.parsed_.Length(), 2151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) *result.parsed_.inner_parsed(), true)); 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Note: code duplicated above (it's inconvenient to use a template here). 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GURL::ResolveWithCharsetConverter( 2227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::string16& relative, 2230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url::CharsetConverter* charset_converter) const { 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Not allowed for invalid URLs. 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_valid_) 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(); 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL result; 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Reserve enough room in the output for the input, plus some extra so that 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // we have room if we have to escape a few things without reallocating. 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.spec_.reserve(spec_.size() + 32); 2330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url::StdStringCanonOutput output(&result.spec_); 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!url::ResolveRelative(spec_.data(), static_cast<int>(spec_.length()), 2360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parsed_, relative.data(), 2370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch static_cast<int>(relative.length()), 2380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch charset_converter, &output, &result.parsed_)) { 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Error resolving, return an empty URL. 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(); 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output.Complete(); 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.is_valid_ = true; 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (result.SchemeIsFileSystem()) { 2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) result.inner_url_.reset( 2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new GURL(result.spec_.data(), result.parsed_.Length(), 2481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) *result.parsed_.inner_parsed(), true)); 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Note: code duplicated below (it's inconvenient to use a template here). 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GURL::ReplaceComponents( 2550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const url::Replacements<char>& replacements) const { 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL result; 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Not allowed for invalid URLs. 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_valid_) 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(); 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Reserve enough room in the output for the input, plus some extra so that 263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // we have room if we have to escape a few things without reallocating. 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.spec_.reserve(spec_.size() + 32); 2650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url::StdStringCanonOutput output(&result.spec_); 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch result.is_valid_ = url::ReplaceComponents( 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) spec_.data(), static_cast<int>(spec_.length()), parsed_, replacements, 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NULL, &output, &result.parsed_); 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output.Complete(); 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (result.is_valid_ && result.SchemeIsFileSystem()) { 2731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) result.inner_url_.reset(new GURL(spec_.data(), result.parsed_.Length(), 2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) *result.parsed_.inner_parsed(), true)); 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Note: code duplicated above (it's inconvenient to use a template here). 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GURL::ReplaceComponents( 2810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const url::Replacements<base::char16>& replacements) const { 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL result; 283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Not allowed for invalid URLs. 285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_valid_) 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(); 287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Reserve enough room in the output for the input, plus some extra so that 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // we have room if we have to escape a few things without reallocating. 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result.spec_.reserve(spec_.size() + 32); 2910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url::StdStringCanonOutput output(&result.spec_); 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch result.is_valid_ = url::ReplaceComponents( 294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) spec_.data(), static_cast<int>(spec_.length()), parsed_, replacements, 295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NULL, &output, &result.parsed_); 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output.Complete(); 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (result.is_valid_ && result.SchemeIsFileSystem()) { 2991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) result.inner_url_.reset(new GURL(spec_.data(), result.parsed_.Length(), 3001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) *result.parsed_.inner_parsed(), true)); 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GURL::GetOrigin() const { 306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // This doesn't make sense for invalid or nonstandard URLs, so return 307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the empty URL 308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_valid_ || !IsStandard()) 309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(); 310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (SchemeIsFileSystem()) 312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return inner_url_->GetOrigin(); 313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url::Replacements<char> replacements; 315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) replacements.ClearUsername(); 316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) replacements.ClearPassword(); 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) replacements.ClearPath(); 318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) replacements.ClearQuery(); 319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) replacements.ClearRef(); 320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ReplaceComponents(replacements); 322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 32423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)GURL GURL::GetAsReferrer() const { 32523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!is_valid_ || 32623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) (!has_ref() && !has_username() && !has_password())) 32723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return GURL(*this); 32823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 3290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url::Replacements<char> replacements; 33023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) replacements.ClearRef(); 33123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) replacements.ClearUsername(); 33223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) replacements.ClearPassword(); 33323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return ReplaceComponents(replacements); 33423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 33523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GURL::GetWithEmptyPath() const { 337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // This doesn't make sense for invalid or nonstandard URLs, so return 338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the empty URL. 339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_valid_ || !IsStandard()) 340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GURL(); 341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We could optimize this since we know that the URL is canonical, and we are 343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // appending a canonical path, so avoiding re-parsing. 344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL other(*this); 345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (parsed_.path.len == 0) 346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return other; 347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Clear everything after the path. 349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) other.parsed_.query.reset(); 350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) other.parsed_.ref.reset(); 351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Set the path, since the path is longer than one, we can just set the 353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // first character and resize. 354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) other.spec_[other.parsed_.path.begin] = '/'; 355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) other.parsed_.path.len = 1; 356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) other.spec_.resize(other.parsed_.path.begin + 1); 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return other; 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool GURL::IsStandard() const { 3610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return url::IsStandard(spec_.data(), parsed_.scheme); 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool GURL::SchemeIs(const char* lower_ascii_scheme) const { 365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (parsed_.scheme.len <= 0) 366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return lower_ascii_scheme == NULL; 3670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return url::LowerCaseEqualsASCII(spec_.data() + parsed_.scheme.begin, 3680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch spec_.data() + parsed_.scheme.end(), 3690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch lower_ascii_scheme); 370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool GURL::SchemeIsHTTPOrHTTPS() const { 37346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return SchemeIs(url::kHttpScheme) || SchemeIs(url::kHttpsScheme); 3743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 3753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool GURL::SchemeIsWSOrWSS() const { 37746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return SchemeIs(url::kWsScheme) || SchemeIs(url::kWssScheme); 378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int GURL::IntPort() const { 381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (parsed_.port.is_nonempty()) 3820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return url::ParsePort(spec_.data(), parsed_.port); 3830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return url::PORT_UNSPECIFIED; 384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int GURL::EffectiveIntPort() const { 387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int int_port = IntPort(); 3880529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (int_port == url::PORT_UNSPECIFIED && IsStandard()) 3890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return url::DefaultPortForScheme(spec_.data() + parsed_.scheme.begin, 3900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parsed_.scheme.len); 391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return int_port; 392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string GURL::ExtractFileName() const { 3950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url::Component file_component; 3960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url::ExtractFileName(spec_.data(), parsed_.path, &file_component); 397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ComponentString(file_component); 398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string GURL::PathForRequest() const { 401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(parsed_.path.len > 0) << "Canonical path for requests should be non-empty"; 402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (parsed_.ref.len >= 0) { 403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Clip off the reference when it exists. The reference starts after the # 404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // sign, so we have to subtract one to also remove it. 405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(spec_, parsed_.path.begin, 406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) parsed_.ref.begin - parsed_.path.begin - 1); 407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Compute the actual path length, rather than depending on the spec's 409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // terminator. If we're an inner_url, our spec continues on into our outer 410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // url's path/query/ref. 411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int path_len = parsed_.path.len; 412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (parsed_.query.is_valid()) 413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) path_len = parsed_.query.end() - parsed_.path.begin; 414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(spec_, parsed_.path.begin, path_len); 416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string GURL::HostNoBrackets() const { 419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If host looks like an IPv6 literal, strip the square brackets. 4200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url::Component h(parsed_.host); 421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (h.len >= 2 && spec_[h.begin] == '[' && spec_[h.end() - 1] == ']') { 422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) h.begin++; 423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) h.len -= 2; 424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return ComponentString(h); 426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)std::string GURL::GetContent() const { 4291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return is_valid_ ? ComponentString(parsed_.GetContent()) : std::string(); 4301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 4311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool GURL::HostIsIPAddress() const { 433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_valid_ || spec_.empty()) 434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url::RawCanonOutputT<char, 128> ignored_output; 4370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url::CanonHostInfo host_info; 4380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch url::CanonicalizeIPAddress(spec_.c_str(), parsed_.host, &ignored_output, 4390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch &host_info); 440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return host_info.IsIPAddress(); 441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifdef WIN32 444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const GURL& GURL::EmptyGURL() { 446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Avoid static object construction/destruction on startup/shutdown. 447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!empty_gurl) { 448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Create the string. Be careful that we don't break in the case that this 449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // is being called from multiple threads. 450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL* new_empty_gurl = new GURL; 451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (InterlockedCompareExchangePointer( 452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reinterpret_cast<PVOID*>(&empty_gurl), new_empty_gurl, NULL)) { 453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The old value was non-NULL, so no replacement was done. Another 454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // thread did the initialization out from under us. 455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) delete new_empty_gurl; 456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return *empty_gurl; 459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#else 462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void EmptyGURLOnce(void) { 464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) empty_gurl = new GURL; 465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const GURL& GURL::EmptyGURL() { 468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Avoid static object construction/destruction on startup/shutdown. 469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pthread_once(&empty_gurl_once, EmptyGURLOnce); 470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return *empty_gurl; 471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // WIN32 474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool GURL::DomainIs(const char* lower_ascii_domain, 476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int domain_len) const { 477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Return false if this URL is not valid or domain is empty. 478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!is_valid_ || !domain_len) 479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // FileSystem URLs have empty parsed_.host, so check this first. 482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (SchemeIsFileSystem() && inner_url_) 483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return inner_url_->DomainIs(lower_ascii_domain, domain_len); 484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!parsed_.host.is_nonempty()) 486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check whether the host name is end with a dot. If yes, treat it 489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the same as no-dot unless the input comparison domain is end 490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // with dot. 491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* last_pos = spec_.data() + parsed_.host.end() - 1; 492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int host_len = parsed_.host.len; 493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if ('.' == *last_pos && '.' != lower_ascii_domain[domain_len - 1]) { 494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) last_pos--; 495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) host_len--; 496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Return false if host's length is less than domain's length. 499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (host_len < domain_len) 500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Compare this url whether belong specific domain. 503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const char* start_pos = spec_.data() + parsed_.host.begin + 504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) host_len - domain_len; 505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!url::LowerCaseEqualsASCII(start_pos, 5070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch last_pos + 1, 5080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch lower_ascii_domain, 5090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch lower_ascii_domain + domain_len)) 510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Check whether host has right domain start with dot, make sure we got 513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // right domain range. For example www.google.com has domain 514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // "google.com" but www.iamnotgoogle.com does not. 515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if ('.' != lower_ascii_domain[0] && host_len > domain_len && 516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) '.' != *(start_pos - 1)) 517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void GURL::Swap(GURL* other) { 523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) spec_.swap(other->spec_); 524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::swap(is_valid_, other->is_valid_); 525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::swap(parsed_, other->parsed_); 5261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) inner_url_.swap(other->inner_url_); 527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::ostream& operator<<(std::ostream& out, const GURL& url) { 530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return out << url.possibly_invalid_spec(); 531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 532