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

Side by Side Diff: net/http/http_auth_cache.cc

Issue 1151843002: DO NOT LAND Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: More. Created 5 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "net/http/http_auth_cache.h" 5 #include "net/http/http_auth_cache.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/strings/string_util.h" 9 #include "base/strings/string_util.h"
10 10
(...skipping 23 matching lines...) Expand all
34 34
35 // Return true if |path| is a subpath of |container|. In other words, is 35 // Return true if |path| is a subpath of |container|. In other words, is
36 // |container| an ancestor of |path|? 36 // |container| an ancestor of |path|?
37 bool IsEnclosingPath(const std::string& container, const std::string& path) { 37 bool IsEnclosingPath(const std::string& container, const std::string& path) {
38 DCHECK(container.empty() || *(container.end() - 1) == '/'); 38 DCHECK(container.empty() || *(container.end() - 1) == '/');
39 return ((container.empty() && path.empty()) || 39 return ((container.empty() && path.empty()) ||
40 (!container.empty() && StartsWithASCII(path, container, true))); 40 (!container.empty() && StartsWithASCII(path, container, true)));
41 } 41 }
42 42
43 // Debug helper to check that |origin| arguments are properly formed. 43 // Debug helper to check that |origin| arguments are properly formed.
44 void CheckOriginIsValid(const GURL& origin) { 44 void CheckOriginIsValid(const url::Origin& origin) {
45 DCHECK(origin.is_valid()); 45 DCHECK(!origin.unique());
46 // Note that the scheme may be FTP when we're using a HTTP proxy. 46 DCHECK(origin.SchemeIs("http") || origin.SchemeIs("https") ||
47 DCHECK(origin.SchemeIsHTTPOrHTTPS() || origin.SchemeIs("ftp") || 47 // Note that the scheme may be FTP when we're using a HTTP proxy.
48 origin.SchemeIsWSOrWSS()); 48 origin.SchemeIs("ftp") || origin.SchemeIs("ws") ||
49 DCHECK(origin.GetOrigin() == origin); 49 origin.SchemeIs("wss"));
Ryan Sleevi 2015/05/22 02:50:03 These all make me sad, because they all are strict
50 } 50 }
51 51
52 // Functor used by remove_if. 52 // Functor used by remove_if.
53 struct IsEnclosedBy { 53 struct IsEnclosedBy {
54 explicit IsEnclosedBy(const std::string& path) : path(path) { } 54 explicit IsEnclosedBy(const std::string& path) : path(path) { }
55 bool operator() (const std::string& x) const { 55 bool operator() (const std::string& x) const {
56 return IsEnclosingPath(path, x); 56 return IsEnclosingPath(path, x);
57 } 57 }
58 const std::string& path; 58 const std::string& path;
59 }; 59 };
(...skipping 10 matching lines...) Expand all
70 70
71 namespace net { 71 namespace net {
72 72
73 HttpAuthCache::HttpAuthCache() { 73 HttpAuthCache::HttpAuthCache() {
74 } 74 }
75 75
76 HttpAuthCache::~HttpAuthCache() { 76 HttpAuthCache::~HttpAuthCache() {
77 } 77 }
78 78
79 // Performance: O(n), where n is the number of realm entries. 79 // Performance: O(n), where n is the number of realm entries.
80 HttpAuthCache::Entry* HttpAuthCache::Lookup(const GURL& origin, 80 HttpAuthCache::Entry* HttpAuthCache::Lookup(const url::Origin& origin,
81 const std::string& realm, 81 const std::string& realm,
82 HttpAuth::Scheme scheme) { 82 HttpAuth::Scheme scheme) {
83 CheckOriginIsValid(origin); 83 CheckOriginIsValid(origin);
84 84
85 int entries_examined = 0; 85 int entries_examined = 0;
86 // Linear scan through the realm entries. 86 // Linear scan through the realm entries.
87 for (EntryList::iterator it = entries_.begin(); it != entries_.end(); ++it) { 87 for (EntryList::iterator it = entries_.begin(); it != entries_.end(); ++it) {
88 ++entries_examined; 88 ++entries_examined;
89 if (it->origin() == origin && it->realm() == realm && 89 if (it->origin() == origin && it->realm() == realm &&
90 it->scheme() == scheme) { 90 it->scheme() == scheme) {
91 it->last_use_time_ = base::TimeTicks::Now(); 91 it->last_use_time_ = base::TimeTicks::Now();
92 RecordLookupPosition(entries_examined); 92 RecordLookupPosition(entries_examined);
93 return &(*it); 93 return &(*it);
94 } 94 }
95 } 95 }
96 RecordLookupPosition(0); 96 RecordLookupPosition(0);
97 return NULL; // No realm entry found. 97 return NULL; // No realm entry found.
98 } 98 }
99 99
100 // Performance: O(n*m), where n is the number of realm entries, m is the number 100 // Performance: O(n*m), where n is the number of realm entries, m is the number
101 // of path entries per realm. Both n amd m are expected to be small; m is 101 // of path entries per realm. Both n amd m are expected to be small; m is
102 // kept small because AddPath() only keeps the shallowest entry. 102 // kept small because AddPath() only keeps the shallowest entry.
103 HttpAuthCache::Entry* HttpAuthCache::LookupByPath(const GURL& origin, 103 HttpAuthCache::Entry* HttpAuthCache::LookupByPath(const url::Origin& origin,
104 const std::string& path) { 104 const std::string& path) {
105 HttpAuthCache::Entry* best_match = NULL; 105 HttpAuthCache::Entry* best_match = NULL;
106 size_t best_match_length = 0; 106 size_t best_match_length = 0;
107 int best_match_position = 0; 107 int best_match_position = 0;
108 CheckOriginIsValid(origin); 108 CheckOriginIsValid(origin);
109 CheckPathIsValid(path); 109 CheckPathIsValid(path);
110 110
111 // RFC 2617 section 2: 111 // RFC 2617 section 2:
112 // A client SHOULD assume that all paths at or deeper than the depth of 112 // A client SHOULD assume that all paths at or deeper than the depth of
113 // the last symbolic element in the path field of the Request-URI also are 113 // the last symbolic element in the path field of the Request-URI also are
(...skipping 11 matching lines...) Expand all
125 best_match_length = len; 125 best_match_length = len;
126 best_match_position = entries_examined; 126 best_match_position = entries_examined;
127 } 127 }
128 } 128 }
129 if (best_match) 129 if (best_match)
130 best_match->last_use_time_ = base::TimeTicks::Now(); 130 best_match->last_use_time_ = base::TimeTicks::Now();
131 RecordLookupByPathPosition(best_match_position); 131 RecordLookupByPathPosition(best_match_position);
132 return best_match; 132 return best_match;
133 } 133 }
134 134
135 HttpAuthCache::Entry* HttpAuthCache::Add(const GURL& origin, 135 HttpAuthCache::Entry* HttpAuthCache::Add(const url::Origin& origin,
136 const std::string& realm, 136 const std::string& realm,
137 HttpAuth::Scheme scheme, 137 HttpAuth::Scheme scheme,
138 const std::string& auth_challenge, 138 const std::string& auth_challenge,
139 const AuthCredentials& credentials, 139 const AuthCredentials& credentials,
140 const std::string& path) { 140 const std::string& path) {
141 CheckOriginIsValid(origin); 141 CheckOriginIsValid(origin);
142 CheckPathIsValid(path); 142 CheckPathIsValid(path);
143 143
144 base::TimeTicks now = base::TimeTicks::Now(); 144 base::TimeTicks now = base::TimeTicks::Now();
145 145
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 195
196 void HttpAuthCache::Entry::AddPath(const std::string& path) { 196 void HttpAuthCache::Entry::AddPath(const std::string& path) {
197 std::string parent_dir = GetParentDirectory(path); 197 std::string parent_dir = GetParentDirectory(path);
198 if (!HasEnclosingPath(parent_dir, NULL)) { 198 if (!HasEnclosingPath(parent_dir, NULL)) {
199 // Remove any entries that have been subsumed by the new entry. 199 // Remove any entries that have been subsumed by the new entry.
200 paths_.remove_if(IsEnclosedBy(parent_dir)); 200 paths_.remove_if(IsEnclosedBy(parent_dir));
201 201
202 bool evicted = false; 202 bool evicted = false;
203 // Failsafe to prevent unbounded memory growth of the cache. 203 // Failsafe to prevent unbounded memory growth of the cache.
204 if (paths_.size() >= kMaxNumPathsPerRealmEntry) { 204 if (paths_.size() >= kMaxNumPathsPerRealmEntry) {
205 LOG(WARNING) << "Num path entries for " << origin() 205 LOG(WARNING) << "Num path entries for " << origin().string()
206 << " has grown too large -- evicting"; 206 << " has grown too large -- evicting";
207 paths_.pop_back(); 207 paths_.pop_back();
208 evicted = true; 208 evicted = true;
209 } 209 }
210 UMA_HISTOGRAM_BOOLEAN("Net.HttpAuthCacheAddPathEvicted", evicted); 210 UMA_HISTOGRAM_BOOLEAN("Net.HttpAuthCacheAddPathEvicted", evicted);
211 211
212 // Add new path. 212 // Add new path.
213 paths_.push_front(parent_dir); 213 paths_.push_front(parent_dir);
214 } 214 }
215 } 215 }
216 216
217 bool HttpAuthCache::Entry::HasEnclosingPath(const std::string& dir, 217 bool HttpAuthCache::Entry::HasEnclosingPath(const std::string& dir,
218 size_t* path_len) { 218 size_t* path_len) {
219 DCHECK(GetParentDirectory(dir) == dir); 219 DCHECK(GetParentDirectory(dir) == dir);
220 for (PathList::const_iterator it = paths_.begin(); it != paths_.end(); 220 for (PathList::const_iterator it = paths_.begin(); it != paths_.end();
221 ++it) { 221 ++it) {
222 if (IsEnclosingPath(*it, dir)) { 222 if (IsEnclosingPath(*it, dir)) {
223 // No element of paths_ may enclose any other element. 223 // No element of paths_ may enclose any other element.
224 // Therefore this path is the tightest bound. Important because 224 // Therefore this path is the tightest bound. Important because
225 // the length returned is used to determine the cache entry that 225 // the length returned is used to determine the cache entry that
226 // has the closest enclosing path in LookupByPath(). 226 // has the closest enclosing path in LookupByPath().
227 if (path_len) 227 if (path_len)
228 *path_len = it->length(); 228 *path_len = it->length();
229 return true; 229 return true;
230 } 230 }
231 } 231 }
232 return false; 232 return false;
233 } 233 }
234 234
235 bool HttpAuthCache::Remove(const GURL& origin, 235 bool HttpAuthCache::Remove(const url::Origin& origin,
236 const std::string& realm, 236 const std::string& realm,
237 HttpAuth::Scheme scheme, 237 HttpAuth::Scheme scheme,
238 const AuthCredentials& credentials) { 238 const AuthCredentials& credentials) {
239 for (EntryList::iterator it = entries_.begin(); it != entries_.end(); ++it) { 239 for (EntryList::iterator it = entries_.begin(); it != entries_.end(); ++it) {
240 if (it->origin() == origin && it->realm() == realm && 240 if (it->origin() == origin && it->realm() == realm &&
241 it->scheme() == scheme) { 241 it->scheme() == scheme) {
242 if (credentials.Equals(it->credentials())) { 242 if (credentials.Equals(it->credentials())) {
243 entries_.erase(it); 243 entries_.erase(it);
244 return true; 244 return true;
245 } 245 }
246 return false; 246 return false;
247 } 247 }
248 } 248 }
249 return false; 249 return false;
250 } 250 }
251 251
252 void HttpAuthCache::Clear() { 252 void HttpAuthCache::Clear() {
253 entries_.clear(); 253 entries_.clear();
254 } 254 }
255 255
256 bool HttpAuthCache::UpdateStaleChallenge(const GURL& origin, 256 bool HttpAuthCache::UpdateStaleChallenge(const url::Origin& origin,
257 const std::string& realm, 257 const std::string& realm,
258 HttpAuth::Scheme scheme, 258 HttpAuth::Scheme scheme,
259 const std::string& auth_challenge) { 259 const std::string& auth_challenge) {
260 HttpAuthCache::Entry* entry = Lookup(origin, realm, scheme); 260 HttpAuthCache::Entry* entry = Lookup(origin, realm, scheme);
261 if (!entry) 261 if (!entry)
262 return false; 262 return false;
263 entry->UpdateStaleChallenge(auth_challenge); 263 entry->UpdateStaleChallenge(auth_challenge);
264 entry->last_use_time_ = base::TimeTicks::Now(); 264 entry->last_use_time_ = base::TimeTicks::Now();
265 return true; 265 return true;
266 } 266 }
267 267
268 void HttpAuthCache::UpdateAllFrom(const HttpAuthCache& other) { 268 void HttpAuthCache::UpdateAllFrom(const HttpAuthCache& other) {
269 for (EntryList::const_iterator it = other.entries_.begin(); 269 for (EntryList::const_iterator it = other.entries_.begin();
270 it != other.entries_.end(); ++it) { 270 it != other.entries_.end(); ++it) {
271 // Add an Entry with one of the original entry's paths. 271 // Add an Entry with one of the original entry's paths.
272 DCHECK(it->paths_.size() > 0); 272 DCHECK(it->paths_.size() > 0);
273 Entry* entry = Add(it->origin(), it->realm(), it->scheme(), 273 Entry* entry = Add(it->origin(), it->realm(), it->scheme(),
274 it->auth_challenge(), it->credentials(), 274 it->auth_challenge(), it->credentials(),
275 it->paths_.back()); 275 it->paths_.back());
276 // Copy all other paths. 276 // Copy all other paths.
277 for (Entry::PathList::const_reverse_iterator it2 = ++it->paths_.rbegin(); 277 for (Entry::PathList::const_reverse_iterator it2 = ++it->paths_.rbegin();
278 it2 != it->paths_.rend(); ++it2) 278 it2 != it->paths_.rend(); ++it2)
279 entry->AddPath(*it2); 279 entry->AddPath(*it2);
280 // Copy nonce count (for digest authentication). 280 // Copy nonce count (for digest authentication).
281 entry->nonce_count_ = it->nonce_count_; 281 entry->nonce_count_ = it->nonce_count_;
282 } 282 }
283 } 283 }
284 284
285 } // namespace net 285 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698