Chromium Code Reviews| Index: third_party/WebKit/Source/core/frame/csp/CSPSource.cpp |
| diff --git a/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp b/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp |
| index 8f15383227bf8708b37b23f6073c0cd5387bf1cc..72073430887f74835c858c08d7fd65c3d6f7a9b4 100644 |
| --- a/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp |
| +++ b/third_party/WebKit/Source/core/frame/csp/CSPSource.cpp |
| @@ -42,17 +42,28 @@ bool CSPSource::matches(const KURL& url, |
| bool CSPSource::schemeMatches(const KURL& url) const { |
| if (m_scheme.isEmpty()) |
| return m_policy->protocolMatchesSelf(url); |
| - if (equalIgnoringCase(m_scheme, "http")) |
| - return equalIgnoringCase(url.protocol(), "http") || |
| - equalIgnoringCase(url.protocol(), "https"); |
| - if (equalIgnoringCase(m_scheme, "ws")) |
| - return equalIgnoringCase(url.protocol(), "ws") || |
| - equalIgnoringCase(url.protocol(), "wss"); |
| - return equalIgnoringCase(url.protocol(), m_scheme); |
| + return schemeMatches(url.protocol()); |
| +} |
| + |
| +bool CSPSource::schemeMatches(const String& protocol) const { |
| + // TODO(amalika): DCHECK schemes are lower case & remove calls to |
| + // equalIgnoringCase |
| + if (equalIgnoringCase(m_scheme, "http")) { |
| + return equalIgnoringCase(protocol, "http") || |
| + equalIgnoringCase(protocol, "https"); |
| + } |
| + if (equalIgnoringCase(m_scheme, "ws")) { |
| + return equalIgnoringCase(protocol, "ws") || |
| + equalIgnoringCase(protocol, "wss"); |
| + } |
| + return equalIgnoringCase(protocol, m_scheme); |
| } |
| bool CSPSource::hostMatches(const KURL& url) const { |
| - const String& host = url.host(); |
| + return hostMatches(url.host()); |
| +} |
| + |
| +bool CSPSource::hostMatches(const String& host) const { |
| Document* document = m_policy->document(); |
| bool match; |
| @@ -75,10 +86,14 @@ bool CSPSource::hostMatches(const KURL& url) const { |
| } |
| bool CSPSource::pathMatches(const KURL& url) const { |
| + return pathMatches(url.path()); |
| +} |
| + |
| +bool CSPSource::pathMatches(const String& urlPath) const { |
| if (m_path.isEmpty()) |
| return true; |
| - String path = decodeURLEscapeSequences(url.path()); |
| + String path = decodeURLEscapeSequences(urlPath); |
| if (m_path.endsWith("/")) |
| return path.startsWith(m_path); |
| @@ -87,28 +102,130 @@ bool CSPSource::pathMatches(const KURL& url) const { |
| } |
| bool CSPSource::portMatches(const KURL& url) const { |
| + return portMatches(url.port(), url.protocol()); |
| +} |
| + |
| +bool CSPSource::portMatches(int port, const String& protocol) const { |
| if (m_portWildcard == HasWildcard) |
| return true; |
| - int port = url.port(); |
| - |
| if (port == m_port) |
| return true; |
| if (m_port == 80 && |
| - (port == 443 || |
| - (port == 0 && defaultPortForProtocol(url.protocol()) == 443))) |
| + (port == 443 || (port == 0 && defaultPortForProtocol(protocol) == 443))) |
| return true; |
| if (!port) |
| - return isDefaultPortForProtocol(m_port, url.protocol()); |
| + return isDefaultPortForProtocol(m_port, protocol); |
| if (!m_port) |
| - return isDefaultPortForProtocol(port, url.protocol()); |
| + return isDefaultPortForProtocol(port, protocol); |
| + |
| + return false; |
| +} |
| + |
| +bool CSPSource::isSimilar(CSPSource* other) { |
| + bool schemesMatch = schemeMatches(other->m_scheme) || |
| + (equalIgnoringCase(m_scheme, "https") && |
|
Mike West
2016/10/26 11:40:29
Nit: DCHECK_EQ(m_scheme, m_scheme.lower()), and re
|
| + equalIgnoringCase(other->m_scheme, "http")) || |
| + (equalIgnoringCase(m_scheme, "wss") && |
| + equalIgnoringCase(other->m_scheme, "ws")); |
| + bool schemesOnly = isSchemeOnly() || other->isSchemeOnly(); |
| + bool hostsMatch = |
| + schemesOnly || equalIgnoringCase(m_host, other->m_host) || |
| + (m_hostWildcard == HasWildcard && hostMatches(other->m_host)) || |
| + (other->m_hostWildcard == HasWildcard && other->hostMatches(m_host)); |
|
Mike West
2016/10/26 11:40:29
Isn't the wildcard work done in `hostMatches()`? C
amalika
2016/10/27 09:50:47
Unfortunately, this does not work when both hosts
|
| + bool portsMatch = schemesOnly || m_portWildcard == HasWildcard || |
| + other->m_portWildcard == HasWildcard || |
| + portMatches(other->m_port, other->m_scheme); |
|
Mike West
2016/10/26 11:40:29
Isn't the wildcard work done in `portMatches()`?
amalika
2016/10/27 09:50:48
It does not work for when there are wildcards in b
|
| + bool pathsMatch = other->m_path.isEmpty() || other->m_path == "/" || |
|
Mike West
2016/10/26 11:40:29
Nit: This matches if `schemesOnly` too, right? If
|
| + pathMatches(other->m_path); |
| + if (schemesMatch && hostsMatch && portsMatch && pathsMatch) |
| + return true; |
| return false; |
| } |
| +CSPSource* CSPSource::getCommon(CSPSource* other) { |
| + if (!isSimilar(other)) |
| + return nullptr; |
| + |
| + bool preferABasedOnScheme = false; |
| + // If the schemes match but their lengths are not equal, that means one of the |
| + // schemes is 'https' or 'wss' |
| + if (m_scheme.length() != other->m_scheme.length()) { |
| + String aScheme = m_scheme.lower(); |
| + preferABasedOnScheme = |
| + aScheme.length() > 3 ? (aScheme == "https") : (aScheme == "wss"); |
| + } |
| + |
| + bool preferABasedOnPort = (m_port && !other->m_port); |
| + bool preferABasedOnPath = (!(m_path.isEmpty() || m_path == "/") && |
| + (other->m_path.isEmpty() || other->m_path == "/")); |
| + |
| + String scheme = preferABasedOnScheme ? m_scheme : other->m_scheme; |
| + String host = (m_hostWildcard == HasWildcard) ? other->m_host : m_host; |
| + String path = preferABasedOnPath ? m_path : other->m_path; |
| + int port = preferABasedOnPort ? m_port : other->m_port; |
| + WildcardDisposition hostWildcard = |
| + (m_hostWildcard == HasWildcard) ? other->m_hostWildcard : m_hostWildcard; |
| + WildcardDisposition portWildcard = |
| + (m_portWildcard == HasWildcard) ? other->m_portWildcard : m_portWildcard; |
| + return new CSPSource(m_policy, scheme, host, port, path, hostWildcard, |
| + portWildcard); |
| +} |
| + |
| +bool CSPSource::isSubsumed(CSPSource* other) { |
| + if (!isSimilar(other)) |
| + return false; |
| + |
| + if (other->isSchemeOnly()) { |
| + if (other->m_scheme.length() == m_scheme.length()) |
| + return true; |
| + return m_scheme.length() == 3 || m_scheme.length() == 5 ? true : false; |
| + } |
| + |
| + if (isSchemeOnly()) |
| + return false; |
| + |
| + if ((m_hostWildcard == HasWildcard && other->m_hostWildcard == NoWildcard) || |
| + (m_portWildcard == HasWildcard && other->m_portWildcard == NoWildcard)) { |
| + return false; |
| + } |
| + |
| + bool preferABasedOnScheme = false, preferBBasedOnScheme = false; |
| + // If the schemes match but their lengths are not equal, that means one of the |
| + // schemes is 'https' or 'wss' |
| + if (m_scheme.length() != other->m_scheme.length()) { |
| + String aScheme = m_scheme.lower(); |
| + preferABasedOnScheme = |
| + aScheme.length() > 3 ? (aScheme == "https") : (aScheme == "wss"); |
| + preferBBasedOnScheme = !preferABasedOnScheme; |
| + } |
| + |
| + bool preferABasedOnPort = (m_port && !other->m_port), |
| + preferBBasedOnPort = (!m_port && other->m_port); |
| + bool preferABasedOnPath = (!(m_path.isEmpty() || m_path == "/") && |
| + (other->m_path.isEmpty() || other->m_path == "/")), |
| + preferBBasedOnPath = |
| + ((m_path.isEmpty() || m_path == "/") && |
| + !(other->m_path.isEmpty() || other->m_path == "/")); |
| + |
| + bool preferA = |
| + preferABasedOnPort || preferABasedOnPath || preferABasedOnScheme; |
| + bool preferB = |
| + preferBBasedOnPort || preferBBasedOnPath || preferBBasedOnScheme; |
| + |
| + if (preferA & preferB) |
| + return false; |
| + |
| + if (preferA || preferB) |
| + return preferA ? true : false; |
| + |
| + return true; |
| +} |
| + |
| bool CSPSource::isSchemeOnly() const { |
| return m_host.isEmpty(); |
| } |