diff options
author | ericu@google.com <ericu@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-24 16:56:58 +0000 |
---|---|---|
committer | ericu@google.com <ericu@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-24 16:56:58 +0000 |
commit | 932df839a6562730cd741f24fc469606d9d9ffb7 (patch) | |
tree | 2c244f93639d2c0f50e6e917cc01ea33fd637a43 /chrome/common | |
parent | 3bfc16cf47deae24f43b3967edf769112a674482 (diff) | |
download | chromium_src-932df839a6562730cd741f24fc469606d9d9ffb7.zip chromium_src-932df839a6562730cd741f24fc469606d9d9ffb7.tar.gz chromium_src-932df839a6562730cd741f24fc469606d9d9ffb7.tar.bz2 |
Add full support for filesystem URLs.
BUG=114484
TEST=existing filesystem tests don't break
Review URL: https://chromiumcodereview.appspot.com/7811006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@128753 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common')
-rw-r--r-- | chrome/common/content_settings_pattern.cc | 64 | ||||
-rw-r--r-- | chrome/common/content_settings_pattern_unittest.cc | 61 | ||||
-rw-r--r-- | chrome/common/extensions/extension.cc | 19 | ||||
-rw-r--r-- | chrome/common/extensions/extension_manifests_unittest.cc | 1 | ||||
-rw-r--r-- | chrome/common/extensions/url_pattern.cc | 26 | ||||
-rw-r--r-- | chrome/common/extensions/url_pattern.h | 16 | ||||
-rw-r--r-- | chrome/common/extensions/url_pattern_unittest.cc | 24 |
7 files changed, 179 insertions, 32 deletions
diff --git a/chrome/common/content_settings_pattern.cc b/chrome/common/content_settings_pattern.cc index 8008cba..8feef19 100644 --- a/chrome/common/content_settings_pattern.cc +++ b/chrome/common/content_settings_pattern.cc @@ -313,28 +313,33 @@ ContentSettingsPattern ContentSettingsPattern::FromURL( scoped_ptr<ContentSettingsPattern::BuilderInterface> builder( ContentSettingsPattern::CreateBuilder(false)); - if (url.SchemeIsFile()) { - builder->WithScheme(url.scheme())->WithPath(url.path()); + const GURL* local_url = &url; + if (url.SchemeIsFileSystem() && url.inner_url()) { + local_url = url.inner_url(); + } + if (local_url->SchemeIsFile()) { + builder->WithScheme(local_url->scheme())->WithPath(local_url->path()); } else { // Please keep the order of the ifs below as URLs with an IP as host can // also have a "http" scheme. - if (url.HostIsIPAddress()) { - builder->WithScheme(url.scheme())->WithHost(url.host()); - } else if (url.SchemeIs(chrome::kHttpScheme)) { - builder->WithSchemeWildcard()->WithDomainWildcard()->WithHost(url.host()); - } else if (url.SchemeIs(chrome::kHttpsScheme)) { - builder->WithScheme(url.scheme())->WithDomainWildcard()->WithHost( - url.host()); + if (local_url->HostIsIPAddress()) { + builder->WithScheme(local_url->scheme())->WithHost(local_url->host()); + } else if (local_url->SchemeIs(chrome::kHttpScheme)) { + builder->WithSchemeWildcard()->WithDomainWildcard()->WithHost( + local_url->host()); + } else if (local_url->SchemeIs(chrome::kHttpsScheme)) { + builder->WithScheme(local_url->scheme())->WithDomainWildcard()->WithHost( + local_url->host()); } else { // Unsupported scheme } - if (url.port().empty()) { - if (url.SchemeIs(chrome::kHttpsScheme)) + if (local_url->port().empty()) { + if (local_url->SchemeIs(chrome::kHttpsScheme)) builder->WithPort(GetDefaultPort(chrome::kHttpsScheme)); else builder->WithPortWildcard(); } else { - builder->WithPort(url.port()); + builder->WithPort(local_url->port()); } } return builder->Build(); @@ -346,14 +351,18 @@ ContentSettingsPattern ContentSettingsPattern::FromURLNoWildcard( scoped_ptr<ContentSettingsPattern::BuilderInterface> builder( ContentSettingsPattern::CreateBuilder(false)); - if (url.SchemeIsFile()) { - builder->WithScheme(url.scheme())->WithPath(url.path()); + const GURL* local_url = &url; + if (url.SchemeIsFileSystem() && url.inner_url()) { + local_url = url.inner_url(); + } + if (local_url->SchemeIsFile()) { + builder->WithScheme(local_url->scheme())->WithPath(local_url->path()); } else { - builder->WithScheme(url.scheme())->WithHost(url.host()); - if (url.port().empty()) { - builder->WithPort(GetDefaultPort(url.scheme())); + builder->WithScheme(local_url->scheme())->WithHost(local_url->host()); + if (local_url->port().empty()) { + builder->WithPort(GetDefaultPort(local_url->scheme())); } else { - builder->WithPort(url.port()); + builder->WithPort(local_url->port()); } } return builder->Build(); @@ -414,8 +423,13 @@ bool ContentSettingsPattern::Matches( if (!is_valid_) return false; + const GURL* local_url = &url; + if (url.SchemeIsFileSystem() && url.inner_url()) { + local_url = url.inner_url(); + } + // Match the scheme part. - const std::string scheme(url.scheme()); + const std::string scheme(local_url->scheme()); if (!parts_.is_scheme_wildcard && parts_.scheme != scheme) { return false; @@ -423,11 +437,17 @@ bool ContentSettingsPattern::Matches( // File URLs have no host. Matches if the pattern has the path wildcard set, // or if the path in the URL is identical to the one in the pattern. + // For filesystem:file URLs, the path used is the filesystem type, so all + // filesystem:file:///temporary/... are equivalent. + // TODO(markusheintz): Content settings should be defined for all files on + // a machine. Unless there is a good use case for supporting paths for file + // patterns, stop supporting path for file patterns. if (!parts_.is_scheme_wildcard && scheme == chrome::kFileScheme) - return parts_.is_path_wildcard || parts_.path == std::string(url.path()); + return parts_.is_path_wildcard || + parts_.path == std::string(local_url->path()); // Match the host part. - const std::string host(net::TrimEndingDot(url.host())); + const std::string host(net::TrimEndingDot(local_url->host())); if (!parts_.has_domain_wildcard) { if (parts_.host != host) return false; @@ -441,7 +461,7 @@ bool ContentSettingsPattern::Matches( return true; // Match the port part. - std::string port(url.port()); + std::string port(local_url->port()); // Use the default port if the port string is empty. GURL returns an empty // string if no port at all was specified or if the default port was diff --git a/chrome/common/content_settings_pattern_unittest.cc b/chrome/common/content_settings_pattern_unittest.cc index f0eeca5..bd79338 100644 --- a/chrome/common/content_settings_pattern_unittest.cc +++ b/chrome/common/content_settings_pattern_unittest.cc @@ -73,6 +73,7 @@ TEST(ContentSettingsPatternTest, FromURL) { pattern = ContentSettingsPattern::FromURL(GURL("https://www.google.com:443")); EXPECT_TRUE(pattern.Matches(GURL("https://www.google.com"))); + EXPECT_TRUE(pattern.Matches(GURL("https://foo.www.google.com"))); EXPECT_TRUE(pattern.Matches(GURL("https://www.google.com:443"))); EXPECT_FALSE(pattern.Matches(GURL("https://www.google.com:444"))); EXPECT_FALSE(pattern.Matches(GURL("http://www.google.com:443"))); @@ -89,6 +90,49 @@ TEST(ContentSettingsPatternTest, FromURL) { EXPECT_EQ("file:///foo/bar.html", pattern.ToString()); } +TEST(ContentSettingsPatternTest, FilesystemUrls) { + ContentSettingsPattern pattern = + ContentSettingsPattern::FromURL(GURL("http://www.google.com")); + EXPECT_TRUE(pattern.Matches( + GURL("filesystem:http://www.google.com/temporary/"))); + EXPECT_TRUE(pattern.Matches( + GURL("filesystem:http://foo.www.google.com/temporary/"))); + EXPECT_TRUE(pattern.Matches( + GURL("filesystem:http://www.google.com:80/temporary/"))); + EXPECT_TRUE(pattern.Matches( + GURL("filesystem:http://www.google.com:81/temporary/"))); + + pattern = ContentSettingsPattern::FromURL(GURL("https://www.google.com")); + EXPECT_TRUE(pattern.Matches( + GURL("filesystem:https://www.google.com/temporary/"))); + EXPECT_TRUE(pattern.Matches( + GURL("filesystem:https://www.google.com:443/temporary/"))); + EXPECT_TRUE(pattern.Matches( + GURL("filesystem:https://foo.www.google.com/temporary/"))); + EXPECT_FALSE(pattern.Matches( + GURL("filesystem:https://www.google.com:81/temporary/"))); + + // A pattern from a filesystem URLs is equivalent to a pattern from the inner + // URL of the filesystem URL. + ContentSettingsPattern pattern2 = ContentSettingsPattern::FromURL( + GURL("filesystem:https://www.google.com/temporary/")); + EXPECT_EQ(ContentSettingsPattern::IDENTITY, pattern.Compare(pattern2)); + + EXPECT_STREQ("https://[*.]www.google.com:443", pattern2.ToString().c_str()); + + pattern = + ContentSettingsPattern::FromURL( + GURL("filesystem:file:///temporary/foo/bar")); + EXPECT_TRUE(pattern.Matches(GURL("filesystem:file:///temporary/"))); + EXPECT_TRUE(pattern.Matches(GURL("filesystem:file:///temporary/test.txt"))); + EXPECT_TRUE(pattern.Matches(GURL("file:///temporary"))); + EXPECT_FALSE(pattern.Matches(GURL("file://foo/bar"))); + pattern2 = + ContentSettingsPattern::FromURL( + GURL("filesystem:file:///persistent/foo2/bar2")); + EXPECT_EQ(ContentSettingsPattern::IDENTITY, pattern.Compare(pattern2)); +} + TEST(ContentSettingsPatternTest, FromURLNoWildcard) { // If no port is specifed GURLs always use the default port for the schemes // HTTP and HTTPS. Hence a GURL always carries a port specification either @@ -114,8 +158,21 @@ TEST(ContentSettingsPatternTest, FromURLNoWildcard) { EXPECT_TRUE(pattern.Matches(GURL("https://www.example.com"))); EXPECT_FALSE(pattern.Matches(GURL("http://foo.www.example.com"))); - pattern = ContentSettingsPattern::FromURLNoWildcard( - GURL("https://www.example.com")); + // Pattern for filesystem URLs + pattern = + ContentSettingsPattern::FromURLNoWildcard( + GURL("filesystem:http://www.google.com/temporary/")); + EXPECT_TRUE(pattern.IsValid()); + EXPECT_TRUE(pattern.Matches(GURL("http://www.google.com"))); + EXPECT_FALSE(pattern.Matches(GURL("http://foo.www.google.com"))); + EXPECT_TRUE(pattern.Matches( + GURL("filesystem:http://www.google.com/persistent/"))); + EXPECT_FALSE(pattern.Matches( + GURL("filesystem:https://www.google.com/persistent/"))); + EXPECT_FALSE(pattern.Matches( + GURL("filesystem:https://www.google.com:81/temporary/"))); + EXPECT_FALSE(pattern.Matches( + GURL("filesystem:https://foo.www.google.com/temporary/"))); } TEST(ContentSettingsPatternTest, Wildcard) { diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc index a57b8e1..d5d2e1e 100644 --- a/chrome/common/extensions/extension.cc +++ b/chrome/common/extensions/extension.cc @@ -2326,16 +2326,27 @@ FileBrowserHandler* Extension::LoadFileBrowserHandler( return NULL; } StringToLowerASCII(&filter); - URLPattern pattern(URLPattern::SCHEME_FILESYSTEM); + if (!StartsWithASCII(filter, + std::string(chrome::kFileSystemScheme) + ':', + true)) { + *error = ExtensionErrorUtils::FormatErrorMessageUTF16( + errors::kInvalidURLPatternError, filter); + return NULL; + } + // The user inputs filesystem:*; we don't actually implement scheme + // wildcards in URLPattern, so transform to what will match correctly. + filter.replace(0, 11, "chrome-extension://*/"); + URLPattern pattern(URLPattern::SCHEME_EXTENSION); + pattern.set_partial_filesystem_support_hack(true); if (pattern.Parse(filter) != URLPattern::PARSE_SUCCESS) { *error = ExtensionErrorUtils::FormatErrorMessageUTF16( errors::kInvalidURLPatternError, filter); return NULL; } std::string path = pattern.path(); - bool allowed = path == "*" || path == "*.*" || - (path.compare(0, 2, "*.") == 0 && - path.find_first_of('*', 2) == std::string::npos); + bool allowed = path == "/*" || path == "/*.*" || + (path.compare(0, 3, "/*.") == 0 && + path.find_first_of('*', 3) == std::string::npos); if (!allowed) { *error = ExtensionErrorUtils::FormatErrorMessageUTF16( errors::kInvalidURLPatternError, filter); diff --git a/chrome/common/extensions/extension_manifests_unittest.cc b/chrome/common/extensions/extension_manifests_unittest.cc index 94fd1cd..7cfd038 100644 --- a/chrome/common/extensions/extension_manifests_unittest.cc +++ b/chrome/common/extensions/extension_manifests_unittest.cc @@ -1004,6 +1004,7 @@ TEST_F(ExtensionManifestTest, FileBrowserHandlers) { scoped_refptr<Extension> extension( LoadAndExpectSuccess("filebrowser_valid.json")); + ASSERT_TRUE(extension.get()); ASSERT_TRUE(extension->file_browser_handlers() != NULL); ASSERT_EQ(extension->file_browser_handlers()->size(), 1U); const FileBrowserHandler* action = diff --git a/chrome/common/extensions/url_pattern.cc b/chrome/common/extensions/url_pattern.cc index ac64811..c0b04b7 100644 --- a/chrome/common/extensions/url_pattern.cc +++ b/chrome/common/extensions/url_pattern.cc @@ -97,12 +97,14 @@ bool IsValidPortForScheme(const std::string scheme, const std::string& port) { URLPattern::URLPattern() : valid_schemes_(SCHEME_NONE), match_all_urls_(false), + partial_filesystem_support_hack_(false), match_subdomains_(false), port_("*") {} URLPattern::URLPattern(int valid_schemes) : valid_schemes_(valid_schemes), match_all_urls_(false), + partial_filesystem_support_hack_(false), match_subdomains_(false), port_("*") {} @@ -111,6 +113,7 @@ URLPattern::URLPattern(int valid_schemes, const std::string& pattern) // appropriate when we know |pattern| is valid. : valid_schemes_(valid_schemes), match_all_urls_(false), + partial_filesystem_support_hack_(false), match_subdomains_(false), port_("*") { if (PARSE_SUCCESS != Parse(pattern)) @@ -295,14 +298,27 @@ bool URLPattern::SetPort(const std::string& port) { } bool URLPattern::MatchesURL(const GURL& test) const { - if (!MatchesScheme(test.scheme())) + const GURL* test_url = &test; + bool has_inner_url = test.inner_url() != NULL; + + if (partial_filesystem_support_hack_ != has_inner_url) + return false; + + if (has_inner_url) + test_url = test.inner_url(); + + if (!MatchesScheme(test_url->scheme())) return false; if (match_all_urls_) return true; - return MatchesSecurityOriginHelper(test) && - MatchesPath(test.PathForRequest()); + std::string path_for_request = test.PathForRequest(); + if (has_inner_url) + path_for_request = test_url->path() + path_for_request; + + return MatchesSecurityOriginHelper(*test_url) && + MatchesPath(path_for_request); } bool URLPattern::MatchesSecurityOrigin(const GURL& test) const { @@ -433,6 +449,10 @@ bool URLPattern::OverlapsWith(const URLPattern& other) const { DCHECK(path_.find('*') == path_.size() - 1); DCHECK(other.path().find('*') == other.path().size() - 1); + if (partial_filesystem_support_hack_ != + other.partial_filesystem_support_hack()) + return false; + if (!MatchesPath(other.path().substr(0, other.path().size() - 1)) && !other.MatchesPath(path_.substr(0, path_.size() - 1))) return false; diff --git a/chrome/common/extensions/url_pattern.h b/chrome/common/extensions/url_pattern.h index 6a83c01..3cde957 100644 --- a/chrome/common/extensions/url_pattern.h +++ b/chrome/common/extensions/url_pattern.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. #ifndef CHROME_COMMON_EXTENSIONS_URL_PATTERN_H_ @@ -119,6 +119,15 @@ class URLPattern { bool match_all_urls() const { return match_all_urls_; } void SetMatchAllURLs(bool val); + // Returns true if this pattern matches inner URLs of filesystem: URLs only. + // Returns false if this pattern matches only non-filesystem URLs. + bool partial_filesystem_support_hack() const { + return partial_filesystem_support_hack_; + } + void set_partial_filesystem_support_hack(bool val) { + partial_filesystem_support_hack_ = val; + } + // Sets the scheme for pattern matches. This can be a single '*' if the // pattern matches all valid schemes (as defined by the valid_schemes_ // property). Returns false on failure (if the scheme is not valid). @@ -204,6 +213,11 @@ class URLPattern { // True if this is a special-case "<all_urls>" pattern. bool match_all_urls_; + // True if we're trying to match against the inner URL of a filesystem URL; + // this is a temporary hack so as not to break ChromeOS as we work on full + // support. + bool partial_filesystem_support_hack_; + // The scheme for the pattern. std::string scheme_; diff --git a/chrome/common/extensions/url_pattern_unittest.cc b/chrome/common/extensions/url_pattern_unittest.cc index 3996b99..10dff3d 100644 --- a/chrome/common/extensions/url_pattern_unittest.cc +++ b/chrome/common/extensions/url_pattern_unittest.cc @@ -110,6 +110,11 @@ TEST(ExtensionURLPatternTest, Match2) { EXPECT_TRUE(pattern.MatchesURL(GURL("https://www.google.com/foobar"))); EXPECT_FALSE(pattern.MatchesURL(GURL("http://www.google.com/foo"))); EXPECT_FALSE(pattern.MatchesURL(GURL("https://www.google.com/"))); + EXPECT_FALSE(pattern.MatchesURL( + GURL("filesystem:https://www.google.com/foobar/"))); + pattern.set_partial_filesystem_support_hack(true); + EXPECT_TRUE(pattern.MatchesURL( + GURL("filesystem:https://www.google.com/foobar/bas"))); } // subdomains @@ -127,6 +132,11 @@ TEST(URLPatternTest, Match3) { EXPECT_TRUE(pattern.MatchesURL( GURL("http://monkey.images.google.com/foooobar"))); EXPECT_FALSE(pattern.MatchesURL(GURL("http://yahoo.com/foobar"))); + EXPECT_FALSE(pattern.MatchesURL( + GURL("filesystem:http://google.com/foobar/"))); + pattern.set_partial_filesystem_support_hack(true); + EXPECT_FALSE(pattern.MatchesURL( + GURL("filesystem:http://google.com/temporary/foobar"))); } // glob escaping @@ -226,6 +236,7 @@ TEST(ExtensionURLPatternTest, Match11) { EXPECT_TRUE(pattern.MatchesScheme("http")); EXPECT_TRUE(pattern.MatchesScheme("https")); EXPECT_TRUE(pattern.MatchesScheme("file")); + EXPECT_TRUE(pattern.MatchesScheme("filesystem")); EXPECT_TRUE(pattern.MatchesScheme("chrome-extension")); EXPECT_TRUE(pattern.match_subdomains()); EXPECT_TRUE(pattern.match_all_urls()); @@ -257,6 +268,7 @@ TEST(ExtensionURLPatternTest, Match12) { EXPECT_TRUE(pattern.MatchesScheme("http")); EXPECT_TRUE(pattern.MatchesScheme("https")); EXPECT_TRUE(pattern.MatchesScheme("file")); + EXPECT_TRUE(pattern.MatchesScheme("filesystem")); EXPECT_TRUE(pattern.MatchesScheme("javascript")); EXPECT_TRUE(pattern.MatchesScheme("data")); EXPECT_TRUE(pattern.MatchesScheme("about")); @@ -368,6 +380,11 @@ TEST(ExtensionURLPatternTest, Match17) { EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.example.com:80/foo"))); EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.example.com/foo"))); EXPECT_FALSE(pattern.MatchesURL(GURL("http://www.example.com:8080/foo"))); + EXPECT_FALSE(pattern.MatchesURL( + GURL("filesystem:http://www.example.com:8080/foo/"))); + EXPECT_FALSE(pattern.MatchesURL(GURL("filesystem:http://www.example.com/f/foo"))); + pattern.set_partial_filesystem_support_hack(true); + EXPECT_FALSE(pattern.MatchesURL(GURL("filesystem:http://www.example.com/f/foo"))); } // Explicit port wildcard @@ -384,6 +401,8 @@ TEST(ExtensionURLPatternTest, Match18) { EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.example.com:80/foo"))); EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.example.com/foo"))); EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.example.com:8080/foo"))); + EXPECT_FALSE(pattern.MatchesURL( + GURL("filesystem:http://www.example.com:8080/foo/"))); } // chrome-extension:// @@ -402,6 +421,11 @@ TEST(ExtensionURLPatternTest, Match19) { EXPECT_TRUE(pattern.MatchesURL( GURL("chrome-extension://ftw/https://google.com"))); EXPECT_FALSE(pattern.MatchesURL(GURL("chrome-extension://foobar"))); + EXPECT_FALSE(pattern.MatchesURL( + GURL("filesystem:chrome-extension://ftw/t/file.txt"))); + pattern.set_partial_filesystem_support_hack(true); + EXPECT_TRUE(pattern.MatchesURL( + GURL("filesystem:chrome-extension://ftw/t/file.txt"))); }; static const struct GetAsStringPatterns { |