| Index: chrome/common/extensions/url_pattern.cc
|
| diff --git a/chrome/common/extensions/url_pattern.cc b/chrome/common/extensions/url_pattern.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..bb32cb57f41e0d751dc25de4e01f19da47b721d9
|
| --- /dev/null
|
| +++ b/chrome/common/extensions/url_pattern.cc
|
| @@ -0,0 +1,128 @@
|
| +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/string_piece.h"
|
| +#include "base/string_util.h"
|
| +#include "chrome/common/extensions/url_pattern.h"
|
| +
|
| +// TODO(aa): Consider adding chrome-extension? What about more obscure ones
|
| +// like data: and javascript: ?
|
| +static const char* kValidSchemes[] = {
|
| + "http",
|
| + "https",
|
| + "file",
|
| + "ftp",
|
| + "chrome-ui"
|
| +};
|
| +
|
| +static const char kSchemeSeparator[] = "://";
|
| +static const char kPathSeparator[] = "/";
|
| +
|
| +static bool IsValidScheme(const std::string& scheme) {
|
| + for (size_t i = 0; i < arraysize(kValidSchemes); ++i) {
|
| + if (scheme == kValidSchemes[i])
|
| + return true;
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| +bool URLPattern::Parse(const std::string& pattern) {
|
| + size_t scheme_end_pos = pattern.find(kSchemeSeparator);
|
| + if (scheme_end_pos == std::string::npos)
|
| + return false;
|
| +
|
| + scheme_ = pattern.substr(0, scheme_end_pos);
|
| + if (!IsValidScheme(scheme_))
|
| + return false;
|
| +
|
| + size_t host_start_pos = scheme_end_pos + strlen(kSchemeSeparator);
|
| + if (host_start_pos >= pattern.length())
|
| + return false;
|
| +
|
| + // Parse out the host and path.
|
| + size_t path_start_pos = 0;
|
| +
|
| + // File URLs are special because they have no host. There are other schemes
|
| + // with the same structure, but we don't support them (yet).
|
| + if (scheme_ == "file") {
|
| + path_start_pos = host_start_pos;
|
| + } else {
|
| + size_t host_end_pos = pattern.find(kPathSeparator, host_start_pos);
|
| + if (host_end_pos == std::string::npos)
|
| + return false;
|
| +
|
| + host_ = pattern.substr(host_start_pos, host_end_pos - host_start_pos);
|
| +
|
| + // The first component can optionally be '*' to match all subdomains.
|
| + std::vector<std::string> host_components;
|
| + SplitString(host_, '.', &host_components);
|
| + if (host_components[0] == "*") {
|
| + match_subdomains_ = true;
|
| + host_components.erase(host_components.begin(),
|
| + host_components.begin() + 1);
|
| + }
|
| + host_ = JoinString(host_components, '.');
|
| +
|
| + // No other '*' can occur in the host, though. This isn't necessary, but is
|
| + // done as a convenience to developers who might otherwise be confused and
|
| + // think '*' works as a glob in the host.
|
| + if (host_.find('*') != std::string::npos)
|
| + return false;
|
| +
|
| + path_start_pos = host_end_pos;
|
| + }
|
| +
|
| + path_ = pattern.substr(path_start_pos);
|
| + return true;
|
| +}
|
| +
|
| +bool URLPattern::MatchesUrl(const GURL &test) {
|
| + if (test.scheme() != scheme_)
|
| + return false;
|
| +
|
| + if (!MatchesHost(test))
|
| + return false;
|
| +
|
| + if (!MatchesPath(test))
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool URLPattern::MatchesHost(const GURL& test) {
|
| + if (test.host() == host_)
|
| + return true;
|
| +
|
| + if (!match_subdomains_ || test.HostIsIPAddress())
|
| + return false;
|
| +
|
| + // If we're matching subdomains, and we have no host, that means the pattern
|
| + // was <scheme>://*/<whatever>, so we match anything.
|
| + if (host_.empty())
|
| + return true;
|
| +
|
| + // Check if the test host is a subdomain of our host.
|
| + if (test.host().length() <= (host_.length() + 1))
|
| + return false;
|
| +
|
| + if (test.host().compare(test.host().length() - host_.length(),
|
| + host_.length(), host_) != 0)
|
| + return false;
|
| +
|
| + return test.host()[test.host().length() - host_.length() - 1] == '.';
|
| +}
|
| +
|
| +bool URLPattern::MatchesPath(const GURL& test) {
|
| + if (path_escaped_.empty()) {
|
| + path_escaped_ = path_;
|
| + ReplaceSubstringsAfterOffset(&path_escaped_, 0, "\\", "\\\\");
|
| + ReplaceSubstringsAfterOffset(&path_escaped_, 0, "?", "\\?");
|
| + }
|
| +
|
| + if (!MatchPattern(test.PathForRequest(), path_escaped_))
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
|
|