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

Side by Side Diff: chrome/common/extensions/url_pattern.cc

Issue 7229012: Use extension match pattern syntax in content settings extension API (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: initialize port Created 9 years, 5 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 | Annotate | Revision Log
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 "chrome/common/extensions/url_pattern.h" 5 #include "chrome/common/extensions/url_pattern.h"
6 6
7 #include "base/string_number_conversions.h"
7 #include "base/string_piece.h" 8 #include "base/string_piece.h"
8 #include "base/string_split.h" 9 #include "base/string_split.h"
9 #include "base/string_util.h" 10 #include "base/string_util.h"
10 #include "chrome/common/url_constants.h" 11 #include "chrome/common/url_constants.h"
11 #include "googleurl/src/gurl.h" 12 #include "googleurl/src/gurl.h"
12 #include "googleurl/src/url_util.h" 13 #include "googleurl/src/url_util.h"
13 14
14 const char URLPattern::kAllUrlsPattern[] = "<all_urls>"; 15 const char URLPattern::kAllUrlsPattern[] = "<all_urls>";
15 16
16 namespace { 17 namespace {
(...skipping 24 matching lines...) Expand all
41 42
42 const char* kParseSuccess = "Success."; 43 const char* kParseSuccess = "Success.";
43 const char* kParseErrorMissingSchemeSeparator = "Missing scheme separator."; 44 const char* kParseErrorMissingSchemeSeparator = "Missing scheme separator.";
44 const char* kParseErrorInvalidScheme = "Invalid scheme."; 45 const char* kParseErrorInvalidScheme = "Invalid scheme.";
45 const char* kParseErrorWrongSchemeType = "Wrong scheme type."; 46 const char* kParseErrorWrongSchemeType = "Wrong scheme type.";
46 const char* kParseErrorEmptyHost = "Host can not be empty."; 47 const char* kParseErrorEmptyHost = "Host can not be empty.";
47 const char* kParseErrorInvalidHostWildcard = "Invalid host wildcard."; 48 const char* kParseErrorInvalidHostWildcard = "Invalid host wildcard.";
48 const char* kParseErrorEmptyPath = "Empty path."; 49 const char* kParseErrorEmptyPath = "Empty path.";
49 const char* kParseErrorHasColon = 50 const char* kParseErrorHasColon =
50 "Ports are not supported in URL patterns. ':' may not be used in a host."; 51 "Ports are not supported in URL patterns. ':' may not be used in a host.";
52 const char* kParseErrorInvalidPort =
53 "Invalid port.";
51 54
52 // Message explaining each URLPattern::ParseResult. 55 // Message explaining each URLPattern::ParseResult.
53 const char* kParseResultMessages[] = { 56 const char* kParseResultMessages[] = {
54 kParseSuccess, 57 kParseSuccess,
55 kParseErrorMissingSchemeSeparator, 58 kParseErrorMissingSchemeSeparator,
56 kParseErrorInvalidScheme, 59 kParseErrorInvalidScheme,
57 kParseErrorWrongSchemeType, 60 kParseErrorWrongSchemeType,
58 kParseErrorEmptyHost, 61 kParseErrorEmptyHost,
59 kParseErrorInvalidHostWildcard, 62 kParseErrorInvalidHostWildcard,
60 kParseErrorEmptyPath, 63 kParseErrorEmptyPath,
61 kParseErrorHasColon 64 kParseErrorHasColon,
65 kParseErrorInvalidPort,
62 }; 66 };
63 67
64 COMPILE_ASSERT(URLPattern::NUM_PARSE_RESULTS == arraysize(kParseResultMessages), 68 COMPILE_ASSERT(URLPattern::NUM_PARSE_RESULTS == arraysize(kParseResultMessages),
65 must_add_message_for_each_parse_result); 69 must_add_message_for_each_parse_result);
66 70
67 const char kPathSeparator[] = "/"; 71 const char kPathSeparator[] = "/";
68 72
69 bool IsStandardScheme(const std::string& scheme) { 73 bool IsStandardScheme(const std::string& scheme) {
70 // "*" gets the same treatment as a standard scheme. 74 // "*" gets the same treatment as a standard scheme.
71 if (scheme == "*") 75 if (scheme == "*")
72 return true; 76 return true;
73 77
74 return url_util::IsStandard(scheme.c_str(), 78 return url_util::IsStandard(scheme.c_str(),
75 url_parse::Component(0, static_cast<int>(scheme.length()))); 79 url_parse::Component(0, static_cast<int>(scheme.length())));
76 } 80 }
77 81
82 bool IsValidPortForScheme(const std::string scheme, const std::string& port) {
83 if (port == "*")
84 return true;
85
86 // Only accept non-wildcard ports if the scheme uses ports.
87 if (url_canon::DefaultPortForScheme(scheme.c_str(), scheme.length()) ==
88 url_parse::PORT_UNSPECIFIED) {
89 return false;
90 }
91
92 int parsed_port = url_parse::PORT_UNSPECIFIED;
93 if (!base::StringToInt(port, &parsed_port))
94 return false;
95 return (parsed_port >= 0) && (parsed_port < 65536);
96 }
97
78 } // namespace 98 } // namespace
79 99
80 URLPattern::URLPattern() 100 URLPattern::URLPattern()
81 : valid_schemes_(SCHEME_NONE), 101 : valid_schemes_(SCHEME_NONE),
82 match_all_urls_(false), 102 match_all_urls_(false),
83 match_subdomains_(false) {} 103 match_subdomains_(false),
104 port_("*") {}
84 105
85 URLPattern::URLPattern(int valid_schemes) 106 URLPattern::URLPattern(int valid_schemes)
86 : valid_schemes_(valid_schemes), match_all_urls_(false), 107 : valid_schemes_(valid_schemes),
87 match_subdomains_(false) {} 108 match_all_urls_(false),
109 match_subdomains_(false),
110 port_("*") {}
88 111
89 URLPattern::URLPattern(int valid_schemes, const std::string& pattern) 112 URLPattern::URLPattern(int valid_schemes, const std::string& pattern)
90 : valid_schemes_(valid_schemes), match_all_urls_(false), 113 : valid_schemes_(valid_schemes),
91 match_subdomains_(false) { 114 match_all_urls_(false),
115 match_subdomains_(false),
116 port_("*") {
92 117
93 // Strict error checking is used, because this constructor is only 118 // Strict error checking is used, because this constructor is only
94 // appropriate when we know |pattern| is valid. 119 // appropriate when we know |pattern| is valid.
95 if (PARSE_SUCCESS != Parse(pattern, PARSE_STRICT)) 120 if (PARSE_SUCCESS != Parse(pattern, ERROR_ON_PORTS))
96 NOTREACHED() << "URLPattern is invalid: " << pattern; 121 NOTREACHED() << "URLPattern is invalid: " << pattern;
97 } 122 }
98 123
99 URLPattern::~URLPattern() { 124 URLPattern::~URLPattern() {
100 } 125 }
101 126
102 URLPattern::ParseResult URLPattern::Parse(const std::string& pattern, 127 URLPattern::ParseResult URLPattern::Parse(const std::string& pattern,
103 ParseOption strictness) { 128 ParseOption strictness) {
104 CHECK(strictness == PARSE_LENIENT ||
105 strictness == PARSE_STRICT);
106
107 // Special case pattern to match every valid URL. 129 // Special case pattern to match every valid URL.
108 if (pattern == kAllUrlsPattern) { 130 if (pattern == kAllUrlsPattern) {
109 match_all_urls_ = true; 131 match_all_urls_ = true;
110 match_subdomains_ = true; 132 match_subdomains_ = true;
111 scheme_ = "*"; 133 scheme_ = "*";
112 host_.clear(); 134 host_.clear();
113 SetPath("/*"); 135 SetPath("/*");
114 return PARSE_SUCCESS; 136 return PARSE_SUCCESS;
115 } 137 }
116 138
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 // The first component can optionally be '*' to match all subdomains. 195 // The first component can optionally be '*' to match all subdomains.
174 std::vector<std::string> host_components; 196 std::vector<std::string> host_components;
175 base::SplitString(host_, '.', &host_components); 197 base::SplitString(host_, '.', &host_components);
176 if (host_components[0] == "*") { 198 if (host_components[0] == "*") {
177 match_subdomains_ = true; 199 match_subdomains_ = true;
178 host_components.erase(host_components.begin(), 200 host_components.erase(host_components.begin(),
179 host_components.begin() + 1); 201 host_components.begin() + 1);
180 } 202 }
181 host_ = JoinString(host_components, '.'); 203 host_ = JoinString(host_components, '.');
182 204
183 // No other '*' can occur in the host, though. This isn't necessary, but is
184 // done as a convenience to developers who might otherwise be confused and
185 // think '*' works as a glob in the host.
186 if (host_.find('*') != std::string::npos)
187 return PARSE_ERROR_INVALID_HOST_WILDCARD;
188
189 path_start_pos = host_end_pos; 205 path_start_pos = host_end_pos;
190 } 206 }
191 207
192 SetPath(pattern.substr(path_start_pos)); 208 SetPath(pattern.substr(path_start_pos));
193 209
194 if (strictness == PARSE_STRICT && host_.find(':') != std::string::npos) 210 size_t port_pos = host_.find(':');
195 return PARSE_ERROR_HAS_COLON; 211 if (port_pos != std::string::npos) {
212 switch (strictness) {
213 case USE_PORTS: {
214 if (!SetPort(host_.substr(port_pos + 1)))
215 return PARSE_ERROR_INVALID_PORT;
216 host_ = host_.substr(0, port_pos);
217 break;
218 }
219 case ERROR_ON_PORTS: {
220 return PARSE_ERROR_HAS_COLON;
221 }
222 case IGNORE_PORTS: {
223 // Do nothing, i.e. leave the colon in the host.
224 }
225 }
226 }
227
228 // No other '*' can occur in the host, though. This isn't necessary, but is
229 // done as a convenience to developers who might otherwise be confused and
230 // think '*' works as a glob in the host.
231 if (host_.find('*') != std::string::npos)
232 return PARSE_ERROR_INVALID_HOST_WILDCARD;
196 233
197 return PARSE_SUCCESS; 234 return PARSE_SUCCESS;
198 } 235 }
199 236
200 bool URLPattern::SetScheme(const std::string& scheme) { 237 bool URLPattern::SetScheme(const std::string& scheme) {
201 scheme_ = scheme; 238 scheme_ = scheme;
202 if (scheme_ == "*") { 239 if (scheme_ == "*") {
203 valid_schemes_ &= (SCHEME_HTTP | SCHEME_HTTPS); 240 valid_schemes_ &= (SCHEME_HTTP | SCHEME_HTTPS);
204 } else if (!IsValidScheme(scheme_)) { 241 } else if (!IsValidScheme(scheme_)) {
205 return false; 242 return false;
(...skipping 13 matching lines...) Expand all
219 return false; 256 return false;
220 } 257 }
221 258
222 void URLPattern::SetPath(const std::string& path) { 259 void URLPattern::SetPath(const std::string& path) {
223 path_ = path; 260 path_ = path;
224 path_escaped_ = path_; 261 path_escaped_ = path_;
225 ReplaceSubstringsAfterOffset(&path_escaped_, 0, "\\", "\\\\"); 262 ReplaceSubstringsAfterOffset(&path_escaped_, 0, "\\", "\\\\");
226 ReplaceSubstringsAfterOffset(&path_escaped_, 0, "?", "\\?"); 263 ReplaceSubstringsAfterOffset(&path_escaped_, 0, "?", "\\?");
227 } 264 }
228 265
266 bool URLPattern::SetPort(const std::string& port) {
267 if (IsValidPortForScheme(scheme_, port)) {
268 port_ = port;
269 return true;
270 }
271 return false;
272 }
273
229 bool URLPattern::MatchesURL(const GURL &test) const { 274 bool URLPattern::MatchesURL(const GURL &test) const {
230 if (!MatchesScheme(test.scheme())) 275 if (!MatchesScheme(test.scheme()))
231 return false; 276 return false;
232 277
233 if (match_all_urls_) 278 if (match_all_urls_)
234 return true; 279 return true;
235 280
236 // Ignore hostname if scheme is file://. 281 // Ignore hostname if scheme is file://.
237 if (scheme_ != chrome::kFileScheme && !MatchesHost(test)) 282 if (scheme_ != chrome::kFileScheme && !MatchesHost(test))
238 return false; 283 return false;
239 284
240 if (!MatchesPath(test.PathForRequest())) 285 if (!MatchesPath(test.PathForRequest()))
241 return false; 286 return false;
242 287
288 if (!MatchesPort(test.EffectiveIntPort()))
289 return false;
290
243 return true; 291 return true;
244 } 292 }
245 293
246 bool URLPattern::MatchesScheme(const std::string& test) const { 294 bool URLPattern::MatchesScheme(const std::string& test) const {
247 if (!IsValidScheme(test)) 295 if (!IsValidScheme(test))
248 return false; 296 return false;
249 297
250 return scheme_ == "*" || test == scheme_; 298 return scheme_ == "*" || test == scheme_;
251 } 299 }
252 300
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 return test.host()[test.host().length() - host_.length() - 1] == '.'; 337 return test.host()[test.host().length() - host_.length() - 1] == '.';
290 } 338 }
291 339
292 bool URLPattern::MatchesPath(const std::string& test) const { 340 bool URLPattern::MatchesPath(const std::string& test) const {
293 if (!MatchPattern(test, path_escaped_)) 341 if (!MatchPattern(test, path_escaped_))
294 return false; 342 return false;
295 343
296 return true; 344 return true;
297 } 345 }
298 346
347 bool URLPattern::MatchesPort(int port) const {
348 if (port == url_parse::PORT_INVALID)
349 return false;
350
351 return port_ == "*" || port_ == base::IntToString(port);
352 }
353
299 std::string URLPattern::GetAsString() const { 354 std::string URLPattern::GetAsString() const {
300 if (match_all_urls_) 355 if (match_all_urls_)
301 return kAllUrlsPattern; 356 return kAllUrlsPattern;
302 357
303 bool standard_scheme = IsStandardScheme(scheme_); 358 bool standard_scheme = IsStandardScheme(scheme_);
304 359
305 std::string spec = scheme_ + 360 std::string spec = scheme_ +
306 (standard_scheme ? chrome::kStandardSchemeSeparator : ":"); 361 (standard_scheme ? chrome::kStandardSchemeSeparator : ":");
307 362
308 if (scheme_ != chrome::kFileScheme && standard_scheme) { 363 if (scheme_ != chrome::kFileScheme && standard_scheme) {
309 if (match_subdomains_) { 364 if (match_subdomains_) {
310 spec += "*"; 365 spec += "*";
311 if (!host_.empty()) 366 if (!host_.empty())
312 spec += "."; 367 spec += ".";
313 } 368 }
314 369
315 if (!host_.empty()) 370 if (!host_.empty())
316 spec += host_; 371 spec += host_;
372
373 if (port_ != "*") {
374 spec += ":";
375 spec += port_;
376 }
317 } 377 }
318 378
319 if (!path_.empty()) 379 if (!path_.empty())
320 spec += path_; 380 spec += path_;
321 381
322 return spec; 382 return spec;
323 } 383 }
324 384
325 bool URLPattern::OverlapsWith(const URLPattern& other) const { 385 bool URLPattern::OverlapsWith(const URLPattern& other) const {
326 if (!MatchesAnyScheme(other.GetExplicitSchemes()) && 386 if (!MatchesAnyScheme(other.GetExplicitSchemes()) &&
327 !other.MatchesAnyScheme(GetExplicitSchemes())) { 387 !other.MatchesAnyScheme(GetExplicitSchemes())) {
328 return false; 388 return false;
329 } 389 }
330 390
331 if (!MatchesHost(other.host()) && !other.MatchesHost(host_)) 391 if (!MatchesHost(other.host()) && !other.MatchesHost(host_))
332 return false; 392 return false;
333 393
394 if (port_ != "*" && other.port() != "*" && port_ != other.port())
395 return false;
396
334 // We currently only use OverlapsWith() for the patterns inside 397 // We currently only use OverlapsWith() for the patterns inside
335 // URLPatternSet. In those cases, we know that the path will have only a 398 // URLPatternSet. In those cases, we know that the path will have only a
336 // single wildcard at the end. This makes figuring out overlap much easier. It 399 // single wildcard at the end. This makes figuring out overlap much easier. It
337 // seems like there is probably a computer-sciency way to solve the general 400 // seems like there is probably a computer-sciency way to solve the general
338 // case, but we don't need that yet. 401 // case, but we don't need that yet.
339 DCHECK(path_.find('*') == path_.size() - 1); 402 DCHECK(path_.find('*') == path_.size() - 1);
340 DCHECK(other.path().find('*') == other.path().size() - 1); 403 DCHECK(other.path().find('*') == other.path().size() - 1);
341 404
342 if (!MatchesPath(other.path().substr(0, other.path().size() - 1)) && 405 if (!MatchesPath(other.path().substr(0, other.path().size() - 1)) &&
343 !other.MatchesPath(path_.substr(0, path_.size() - 1))) 406 !other.MatchesPath(path_.substr(0, path_.size() - 1)))
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 } 450 }
388 451
389 return result; 452 return result;
390 } 453 }
391 454
392 // static 455 // static
393 const char* URLPattern::GetParseResultString( 456 const char* URLPattern::GetParseResultString(
394 URLPattern::ParseResult parse_result) { 457 URLPattern::ParseResult parse_result) {
395 return kParseResultMessages[parse_result]; 458 return kParseResultMessages[parse_result];
396 } 459 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698