Chromium Code Reviews| Index: Source/platform/weborigin/SecurityOrigin.cpp |
| diff --git a/Source/platform/weborigin/SecurityOrigin.cpp b/Source/platform/weborigin/SecurityOrigin.cpp |
| index b33955e0ec34ebf4481f60a5f19fd344f373f523..0c307ea5a27f0fb1de0d50b38adc297bb4379d49 100644 |
| --- a/Source/platform/weborigin/SecurityOrigin.cpp |
| +++ b/Source/platform/weborigin/SecurityOrigin.cpp |
| @@ -37,6 +37,7 @@ |
| #include "url/url_canon_ip.h" |
| #include "wtf/HexNumber.h" |
| #include "wtf/MainThread.h" |
| +#include "wtf/NotFound.h" |
| #include "wtf/StdLibExtras.h" |
| #include "wtf/text/StringBuilder.h" |
| @@ -62,6 +63,12 @@ static SecurityOrigin* cachedOrigin(const KURL& url) |
| return 0; |
| } |
| +static bool sameSuborigin(const SecurityOrigin* origin1, const SecurityOrigin* origin2) |
| +{ |
| + // If either origin has a suborigin set, both must have the same suborigin. |
| + return origin1->suboriginName() == origin2->suboriginName(); |
| +} |
| + |
| bool SecurityOrigin::shouldUseInnerURL(const KURL& url) |
| { |
| // FIXME: Blob URLs don't have inner URLs. Their form is "blob:<inner-origin>/<UUID>", so treating the part after "blob:" as a URL is incorrect. |
| @@ -116,6 +123,24 @@ static bool shouldTreatAsUniqueOrigin(const KURL& url) |
| return false; |
| } |
| +bool deserializeSuboriginAndProtocol(const String& oldProtocol, String& suboriginName, String& newProtocol) |
| +{ |
| + const char suboriginPrefix[] = "suborigin+"; |
| + if (!oldProtocol.startsWith(suboriginPrefix)) |
| + return false; |
| + |
| + size_t suboriginStart = strlen(suboriginPrefix); |
| + size_t protocolStart = oldProtocol.find('+', suboriginStart + 1); |
| + |
| + if (protocolStart == kNotFound) |
| + return false; |
| + |
| + suboriginName = oldProtocol.substring(suboriginStart, protocolStart - suboriginStart); |
| + newProtocol = oldProtocol.substring(protocolStart + 1); |
| + |
|
Mike West
2015/03/23 07:32:56
ASSERT that the runtime-enabled feature is enabled
jww
2015/04/11 02:52:36
I instead put a check at the top to make sure we o
|
| + return true; |
| +} |
| + |
| SecurityOrigin::SecurityOrigin(const KURL& url) |
| : m_protocol(url.protocol().isNull() ? "" : url.protocol().lower()) |
| , m_host(url.host().isNull() ? "" : url.host().lower()) |
| @@ -126,6 +151,11 @@ SecurityOrigin::SecurityOrigin(const KURL& url) |
| , m_enforceFilePathSeparation(false) |
| , m_needsDatabaseIdentifierQuirkForFiles(false) |
| { |
| + // Suborigins are serialized into the protocol, so extract it if necessary. |
| + String suboriginName; |
| + if (deserializeSuboriginAndProtocol(m_protocol, suboriginName, m_protocol)) |
|
Mike West
2015/03/23 07:32:55
A side-effect of lumping the suborigin into the pr
jww
2015/04/25 00:41:22
Agreed. For this original implementation, my idea
|
| + addSuborigin(suboriginName); |
| + |
| // document.domain starts as m_host, but can be set by the DOM. |
| m_domain = m_host; |
| @@ -158,6 +188,7 @@ SecurityOrigin::SecurityOrigin(const SecurityOrigin* other) |
| , m_host(other->m_host.isolatedCopy()) |
| , m_domain(other->m_domain.isolatedCopy()) |
| , m_filePath(other->m_filePath.isolatedCopy()) |
| + , m_suboriginName(other->m_suboriginName) |
| , m_port(other->m_port) |
| , m_isUnique(other->m_isUnique) |
| , m_universalAccess(other->m_universalAccess) |
| @@ -200,6 +231,15 @@ PassRefPtr<SecurityOrigin> SecurityOrigin::createUnique() |
| return origin.release(); |
| } |
| +void SecurityOrigin::addSuborigin(const String& suborigin) |
| +{ |
| + // Changing suborigins midstream is bad. Very bad. It should not happen. |
| + // This is, in fact, one of the very basic invariants that makes suborigins |
| + // an effective security tool. |
|
Mike West
2015/03/23 07:32:56
ASSERT that the runtime-enabled feature is enabled
jww
2015/04/11 02:52:36
Done.
|
| + RELEASE_ASSERT(m_suboriginName.isNull() || m_suboriginName == suborigin); |
|
Mike West
2015/03/23 07:32:55
When would the suborigin be set to itself? Could w
jww
2015/04/11 02:52:36
There are some cases, I believe during script exec
|
| + m_suboriginName = suborigin; |
|
Mike West
2015/03/23 07:32:55
Please add unit tests for this change. You can ver
jww
2015/04/11 02:52:36
Done.
|
| +} |
| + |
| PassRefPtr<SecurityOrigin> SecurityOrigin::isolatedCopy() const |
| { |
| return adoptRef(new SecurityOrigin(this)); |
| @@ -235,6 +275,9 @@ bool SecurityOrigin::canAccess(const SecurityOrigin* other) const |
| if (isUnique() || other->isUnique()) |
| return false; |
| + if (!sameSuborigin(this, other)) |
| + return false; |
|
Mike West
2015/03/23 07:32:56
Please add unit tests for this change.
jww
2015/04/11 02:52:36
Done.
|
| + |
| // Here are two cases where we should permit access: |
| // |
| // 1) Neither document has set document.domain. In this case, we insist |
| @@ -298,6 +341,9 @@ bool SecurityOrigin::canRequest(const KURL& url) const |
| if (targetOrigin->isUnique()) |
| return false; |
| + if (!sameSuborigin(this, targetOrigin.get())) |
|
Mike West
2015/03/23 07:32:55
Please add unit tests for this change.
It seems l
jww
2015/04/11 02:52:36
Added.
|
| + return false; |
| + |
| // We call isSameSchemeHostPort here instead of canAccess because we want |
| // to ignore document.domain effects. |
| if (isSameSchemeHostPort(targetOrigin.get())) |
| @@ -392,6 +438,8 @@ SecurityOrigin::Policy SecurityOrigin::canShowNotifications() const |
| return AlwaysAllow; |
| if (isUnique()) |
| return AlwaysDeny; |
| + if (hasSuborigin()) |
| + return AlwaysDeny; |
|
Mike West
2015/03/23 07:32:55
There's no test for this behavioral change. Please
jww
2015/04/11 02:52:36
Done.
|
| return Ask; |
| } |
| @@ -483,7 +531,14 @@ AtomicString SecurityOrigin::toRawAtomicString() const |
| inline void SecurityOrigin::buildRawString(StringBuilder& builder) const |
|
Mike West
2015/03/23 07:32:55
Please add unit tests for the new behavior here.
|
| { |
| - builder.reserveCapacity(m_protocol.length() + m_host.length() + 10); |
| + if (hasSuborigin()) { |
| + builder.reserveCapacity(11 + m_suboriginName.length() + m_protocol.length() + m_host.length() + 10); |
| + builder.appendLiteral("suborigin+"); |
| + builder.append(m_suboriginName); |
| + builder.append('+'); |
|
Mike West
2015/03/23 07:32:55
This is very strange syntax.
jww
2015/04/11 02:52:36
Initially I went with ':', but this causes all sor
|
| + } else { |
| + builder.reserveCapacity(m_protocol.length() + m_host.length() + 10); |
| + } |
| builder.append(m_protocol); |
| builder.appendLiteral("://"); |
| builder.append(m_host); |
| @@ -509,6 +564,9 @@ PassRefPtr<SecurityOrigin> SecurityOrigin::create(const String& protocol, const |
| bool SecurityOrigin::isSameSchemeHostPort(const SecurityOrigin* other) const |
| { |
| + if (!sameSuborigin(this, other)) |
|
Mike West
2015/03/23 07:32:55
Do we always want the suborigin check when doing a
jww
2015/04/11 02:52:36
Even while it's experimental? It won't be a subori
|
| + return false; |
| + |
| if (m_host != other->m_host) |
| return false; |