Index: third_party/WebKit/Source/core/frame/History.cpp |
diff --git a/third_party/WebKit/Source/core/frame/History.cpp b/third_party/WebKit/Source/core/frame/History.cpp |
index 12d05442e572d7873a67bd7671ecd10920453509..c870118ee4b941fd0acf4d87ad46e3dd8433bc01 100644 |
--- a/third_party/WebKit/Source/core/frame/History.cpp |
+++ b/third_party/WebKit/Source/core/frame/History.cpp |
@@ -43,6 +43,27 @@ |
namespace blink { |
+namespace { |
+ |
+bool equalIgnoringPathQueryAndFragment(const KURL& a, const KURL& b) |
+{ |
+ int aLength = a.pathStart(); |
+ int bLength = b.pathStart(); |
+ |
+ if (aLength != bLength) |
+ return false; |
+ |
+ const String& aString = a.string(); |
+ const String& bString = b.string(); |
+ for (int i = 0; i < aLength; ++i) { |
+ if (aString[i] != bString[i]) |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+} // namespace |
+ |
History::History(LocalFrame* frame) |
: DOMWindowProperty(frame) |
, m_lastStateObjectRequested(nullptr) |
@@ -162,15 +183,38 @@ KURL History::urlForState(const String& urlString) |
return KURL(document->baseURL(), urlString); |
} |
+bool History::canChangeToUrl(const KURL& url) |
+{ |
+ if (!url.isValid()) |
Mike West
2015/12/08 17:34:59
Nit: Can you assert that you have `m_frame` and `m
robwu
2015/12/08 20:31:47
This is already implied by the existing code. `m_f
|
+ return false; |
+ |
+ Document* document = m_frame->document(); |
+ SecurityOrigin* origin = document->securityOrigin(); |
+ if (origin->isGrantedUniversalAccess()) |
+ return true; |
+ |
+ if (origin->isUnique()) |
+ return false; |
+ |
+ if (!equalIgnoringPathQueryAndFragment(url, document->url())) |
+ return false; |
+ |
+ RefPtr<SecurityOrigin> requestedOrigin = SecurityOrigin::create(url); |
+ if (requestedOrigin->isUnique() || !requestedOrigin->isSameSchemeHostPort(origin)) |
+ return false; |
+ |
+ return true; |
+} |
+ |
void History::stateObjectAdded(PassRefPtr<SerializedScriptValue> data, const String& /* title */, const String& urlString, HistoryScrollRestorationType restorationType, FrameLoadType type, ExceptionState& exceptionState) |
{ |
if (!m_frame || !m_frame->page() || !m_frame->loader().documentLoader()) |
return; |
KURL fullURL = urlForState(urlString); |
- if (!fullURL.isValid() || !m_frame->document()->securityOrigin()->canRequest(fullURL)) { |
+ if (!canChangeToUrl(fullURL)) { |
// We can safely expose the URL to JavaScript, as a) no redirection takes place: JavaScript already had this URL, b) JavaScript can only access a same-origin History object. |
- exceptionState.throwSecurityError("A history state object with URL '" + fullURL.elidedString() + "' cannot be created in a document with origin '" + m_frame->document()->securityOrigin()->toString() + "'."); |
+ exceptionState.throwSecurityError("A history state object with URL '" + fullURL.elidedString() + "' cannot be created in a document with origin '" + m_frame->document()->securityOrigin()->toString() + "' and URL '" + m_frame->document()->url().elidedString() + "'."); |
return; |
} |