Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_utils.cc
blob59748ee3a83df3fdf75bb8310dfa923af4d4e831
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/service_worker/service_worker_utils.h"
7 #include <string>
9 #include "base/logging.h"
10 #include "base/strings/string_util.h"
12 namespace content {
14 namespace {
16 bool PathContainsDisallowedCharacter(const GURL& url) {
17 std::string path = url.path();
18 DCHECK(base::IsStringUTF8(path));
20 // We should avoid these escaped characters in the path component because
21 // these can be handled differently depending on server implementation.
22 if (path.find("%2f") != std::string::npos ||
23 path.find("%2F") != std::string::npos) {
24 return true;
26 if (path.find("%5c") != std::string::npos ||
27 path.find("%5C") != std::string::npos) {
28 return true;
30 return false;
33 } // namespace
35 // static
36 bool ServiceWorkerUtils::ScopeMatches(const GURL& scope, const GURL& url) {
37 DCHECK(!scope.has_ref());
38 DCHECK(!url.has_ref());
39 return StartsWithASCII(url.spec(), scope.spec(), true);
42 // static
43 bool ServiceWorkerUtils::IsPathRestrictionSatisfied(
44 const GURL& scope,
45 const GURL& script_url,
46 const std::string* service_worker_allowed_header_value,
47 std::string* error_message) {
48 DCHECK(scope.is_valid());
49 DCHECK(!scope.has_ref());
50 DCHECK(script_url.is_valid());
51 DCHECK(!script_url.has_ref());
52 DCHECK(error_message);
54 if (ContainsDisallowedCharacter(scope, script_url, error_message))
55 return false;
57 std::string max_scope_string;
58 if (service_worker_allowed_header_value) {
59 GURL max_scope = script_url.Resolve(*service_worker_allowed_header_value);
60 if (!max_scope.is_valid()) {
61 *error_message = "An invalid Service-Worker-Allowed header value ('";
62 error_message->append(*service_worker_allowed_header_value);
63 error_message->append("') was received when fetching the script.");
64 return false;
66 max_scope_string = max_scope.path();
67 } else {
68 max_scope_string = script_url.Resolve(".").path();
71 std::string scope_string = scope.path();
72 if (!StartsWithASCII(scope_string, max_scope_string, true)) {
73 *error_message = "The path of the provided scope ('";
74 error_message->append(scope_string);
75 error_message->append("') is not under the max scope allowed (");
76 if (service_worker_allowed_header_value)
77 error_message->append("set by Service-Worker-Allowed: ");
78 error_message->append("'");
79 error_message->append(max_scope_string);
80 error_message->append(
81 "'). Adjust the scope, move the Service Worker script, or use the "
82 "Service-Worker-Allowed HTTP header to allow the scope.");
83 return false;
85 return true;
88 // static
89 bool ServiceWorkerUtils::ContainsDisallowedCharacter(
90 const GURL& scope,
91 const GURL& script_url,
92 std::string* error_message) {
93 if (PathContainsDisallowedCharacter(scope) ||
94 PathContainsDisallowedCharacter(script_url)) {
95 *error_message = "The provided scope ('";
96 error_message->append(scope.spec());
97 error_message->append("') or scriptURL ('");
98 error_message->append(script_url.spec());
99 error_message->append("') includes a disallowed escape character.");
100 return true;
102 return false;
105 bool LongestScopeMatcher::MatchLongest(const GURL& scope) {
106 if (!ServiceWorkerUtils::ScopeMatches(scope, url_))
107 return false;
108 if (match_.is_empty() || match_.spec().size() < scope.spec().size()) {
109 match_ = scope;
110 return true;
112 return false;
115 } // namespace content