Commit a9da3b0b authored by abarth@webkit.org's avatar abarth@webkit.org

FrameLoader::shouldAllowNavigation uses Frame for context rather than Document

https://bugs.webkit.org/show_bug.cgi?id=81020

Reviewed by Eric Seidel.

Source/WebCore:

The vast majority of security checks in the browser should use a
ScriptExecutionContext (aka a Document) to designate "who" is
attempting to perform a given action.  Unfortunately,
shouldAllowNavigation was using a Frame to designate "who" is
attempting the navigation.

In cases when the executing script is "inactive" (i.e., belongs to a
document that is not currently displayed in a Frame), using the Frame
can cause us to grant the script the privileges of the document that's
currently displayed in the Frame rather than the one that contains the
script.

This patch moves shouldAllowNavigation from FrameLoader to Document
(and renames it to canNavigate), effectively change the context object
from a Frame to a Document.

Test: http/tests/security/frameNavigation/inactive-function-in-popup-navigate-child.html

* bindings/generic/BindingSecurity.h:
(BindingSecurity):
(WebCore):
* bindings/v8/V8Utilities.cpp:
(WebCore):
* bindings/v8/V8Utilities.h:
(WebCore):
    - Deletes unused code.
* dom/Document.cpp:
(WebCore::canAccessAncestor):
(WebCore):
(WebCore::Document::canNavigate):
    - canNavigate is copied from FrameLoader::shouldAllowNavigation.
      I've added a null-check bailout if the document is inactive.
* dom/Document.h:
(Document):
* loader/FormState.cpp:
(WebCore::FormState::FormState):
(WebCore::FormState::create):
* loader/FormState.h:
(WebCore):
(FormState):
(WebCore::FormState::sourceDocument):
* loader/FormSubmission.cpp:
(WebCore::FormSubmission::create):
    - Changes the context object from Frame to Document.
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::submitForm):
(WebCore::FrameLoader::loadFrameRequest):
(WebCore):
(WebCore::FrameLoader::findFrameForNavigation):
    - FrameLoader::findFrameForNavigation still incorrectly uses Frame
      as the context object, but that's a bug for another patch.
(WebCore::createWindow):
* loader/FrameLoader.h:
(FrameLoader):
* loader/NavigationScheduler.cpp:
(WebCore::ScheduledFormSubmission::fire):
* page/DOMWindow.cpp:
(WebCore::DOMWindow::close):
(WebCore::DOMWindow::setLocation):
(WebCore::DOMWindow::open):
* page/History.cpp:
(WebCore::History::go):

Source/WebKit/mac:

Update call site to new function name.

* WebCoreSupport/WebFrameLoaderClient.mm:
(WebFrameLoaderClient::dispatchWillSubmitForm):

Source/WebKit/win:

Update call site to new function name.

* WebFrame.cpp:
(WebFrame::dispatchWillSubmitForm):

Source/WebKit2:

Update call site to new function name.

* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchWillSubmitForm):

LayoutTests:

Test that a script from an inactive document doesn't inherit the
navigation privileges of the document that currently occupies the
frame.

* http/tests/security/frameNavigation/inactive-function-in-popup-navigate-child-expected.txt: Added.
* http/tests/security/frameNavigation/inactive-function-in-popup-navigate-child.html: Added.
* http/tests/security/frameNavigation/resources/fail.html: Added.
* http/tests/security/frameNavigation/resources/iframe-with-inner-frame-on-foreign-domain.html:
* http/tests/security/frameNavigation/resources/popup-ready-to-navigate-child.html: Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@112184 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 6c3df0ac
2012-03-26 Adam Barth <abarth@webkit.org>
FrameLoader::shouldAllowNavigation uses Frame for context rather than Document
https://bugs.webkit.org/show_bug.cgi?id=81020
Reviewed by Eric Seidel.
Test that a script from an inactive document doesn't inherit the
navigation privileges of the document that currently occupies the
frame.
* http/tests/security/frameNavigation/inactive-function-in-popup-navigate-child-expected.txt: Added.
* http/tests/security/frameNavigation/inactive-function-in-popup-navigate-child.html: Added.
* http/tests/security/frameNavigation/resources/fail.html: Added.
* http/tests/security/frameNavigation/resources/iframe-with-inner-frame-on-foreign-domain.html:
* http/tests/security/frameNavigation/resources/popup-ready-to-navigate-child.html: Added.
2012-03-26 Ojan Vafai <ojan@chromium.org>
More Chromium rebaselines for assorted failing tests. Almost all of the differences
This test passes if it doesn't alert "FAIL".
ready
iframe-with-inner-frame-on-foreign-domain-LOADED
Attempting navigation...
<!DOCTYPE html>
<html>
<head>
<script>
if (window.layoutTestController) {
layoutTestController.dumpAsText();
layoutTestController.waitUntilDone();
layoutTestController.setCanOpenWindows();
layoutTestController.setCloseRemainingWindowsWhenComplete(true);
}
function log(msg) {
var div = document.createElement("div");
div.appendChild(document.createTextNode(msg));
document.getElementById("console").appendChild(div);
}
window.onload = function() {
window.popup = window.open("resources/popup-ready-to-navigate-child.html", "target");
}
window.addEventListener("message", function(e) {
log(e.data);
if (e.data == "ready") {
window.savedFunction = popup.go;
popup.location = "http://127.0.0.1:8080/security/frameNavigation/resources/iframe-with-inner-frame-on-foreign-domain.html";
return;
}
if (e.data = "iframe-with-inner-frame-on-foreign-domain-LOADED") {
log("Attempting navigation...");
window.savedFunction();
setTimeout(function() {
// Unfortunately, there's no way to receive positive confirmation
// that the navigation failed, so we just complete the test
// asynchronously.
if (window.layoutTestController)
layoutTestController.notifyDone();
}, 0);
return;
}
}, false);
</script>
</head>
<body>
This test passes if it doesn't alert "FAIL".
<div id="console"></div>
</body>
</html>
......@@ -4,6 +4,8 @@
function loaded()
{
document.getElementsByTagName('h4')[0].innerHTML = document.domain;
if (top.opener)
top.opener.postMessage("iframe-with-inner-frame-on-foreign-domain-LOADED", "*");
}
</script>
</head>
......
<script>
function go() {
window.frames[0].location = "http://127.0.0.1:8000/security/frameNavigation/resources/fail.html";
}
opener.postMessage("ready", "*");
</script>
2012-03-26 Adam Barth <abarth@webkit.org>
FrameLoader::shouldAllowNavigation uses Frame for context rather than Document
https://bugs.webkit.org/show_bug.cgi?id=81020
Reviewed by Eric Seidel.
The vast majority of security checks in the browser should use a
ScriptExecutionContext (aka a Document) to designate "who" is
attempting to perform a given action. Unfortunately,
shouldAllowNavigation was using a Frame to designate "who" is
attempting the navigation.
In cases when the executing script is "inactive" (i.e., belongs to a
document that is not currently displayed in a Frame), using the Frame
can cause us to grant the script the privileges of the document that's
currently displayed in the Frame rather than the one that contains the
script.
This patch moves shouldAllowNavigation from FrameLoader to Document
(and renames it to canNavigate), effectively change the context object
from a Frame to a Document.
Test: http/tests/security/frameNavigation/inactive-function-in-popup-navigate-child.html
* bindings/generic/BindingSecurity.h:
(BindingSecurity):
(WebCore):
* bindings/v8/V8Utilities.cpp:
(WebCore):
* bindings/v8/V8Utilities.h:
(WebCore):
- Deletes unused code.
* dom/Document.cpp:
(WebCore::canAccessAncestor):
(WebCore):
(WebCore::Document::canNavigate):
- canNavigate is copied from FrameLoader::shouldAllowNavigation.
I've added a null-check bailout if the document is inactive.
* dom/Document.h:
(Document):
* loader/FormState.cpp:
(WebCore::FormState::FormState):
(WebCore::FormState::create):
* loader/FormState.h:
(WebCore):
(FormState):
(WebCore::FormState::sourceDocument):
* loader/FormSubmission.cpp:
(WebCore::FormSubmission::create):
- Changes the context object from Frame to Document.
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::submitForm):
(WebCore::FrameLoader::loadFrameRequest):
(WebCore):
(WebCore::FrameLoader::findFrameForNavigation):
- FrameLoader::findFrameForNavigation still incorrectly uses Frame
as the context object, but that's a bug for another patch.
(WebCore::createWindow):
* loader/FrameLoader.h:
(FrameLoader):
* loader/NavigationScheduler.cpp:
(WebCore::ScheduledFormSubmission::fire):
* page/DOMWindow.cpp:
(WebCore::DOMWindow::close):
(WebCore::DOMWindow::setLocation):
(WebCore::DOMWindow::open):
* page/History.cpp:
(WebCore::History::go):
2012-03-26 Vangelis Kokkevis <vangelis@chromium.org>
[chromium] Simplify and fix CCLayerSorter
......@@ -32,6 +32,8 @@
#define BindingSecurity_h
#include "BindingSecurityBase.h"
#include "DOMWindow.h"
#include "Document.h"
#include "Element.h"
#include "Frame.h"
#include "GenericBinding.h"
......@@ -61,8 +63,6 @@ public:
static bool allowSettingFrameSrcToJavascriptUrl(State<Binding>*, HTMLFrameElementBase*, const String& value);
static bool allowSettingSrcToJavascriptURL(State<Binding>*, Element*, const String& name, const String& value);
static bool shouldAllowNavigation(State<Binding>*, Frame*);
private:
explicit BindingSecurity() {}
~BindingSecurity();
......@@ -145,13 +145,6 @@ bool BindingSecurity<Binding>::allowSettingSrcToJavascriptURL(State<Binding>* st
return true;
}
template <class Binding>
bool BindingSecurity<Binding>::shouldAllowNavigation(State<Binding>* state, Frame* frame)
{
Frame* activeFrame = state->activeFrame();
return activeFrame && activeFrame->loader()->shouldAllowNavigation(frame);
}
}
#endif // BindingSecurity_h
......@@ -184,11 +184,6 @@ Frame* callingOrEnteredFrame()
return V8BindingState::Only()->activeFrame();
}
bool shouldAllowNavigation(Frame* frame)
{
return V8BindingSecurity::shouldAllowNavigation(V8BindingState::Only(), frame);
}
KURL completeURL(const String& relativeURL)
{
return completeURL(V8BindingState::Only(), relativeURL);
......
......@@ -56,7 +56,6 @@ namespace WebCore {
// Combo create/remove, for generated event-handler-setter bindings:
void transferHiddenDependency(v8::Handle<v8::Object>, EventListener* oldValue, v8::Local<v8::Value> newValue, int cacheIndex);
bool shouldAllowNavigation(Frame*);
KURL completeURL(const String& relativeURL);
ScriptExecutionContext* getScriptExecutionContext();
......
......@@ -346,6 +346,34 @@ static bool disableRangeMutation(Page* page)
#endif
}
static bool canAccessAncestor(const SecurityOrigin* activeSecurityOrigin, Frame* targetFrame)
{
// targetFrame can be 0 when we're trying to navigate a top-level frame
// that has a 0 opener.
if (!targetFrame)
return false;
const bool isLocalActiveOrigin = activeSecurityOrigin->isLocal();
for (Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree()->parent()) {
Document* ancestorDocument = ancestorFrame->document();
// FIXME: Should be an ASSERT? Frames should alway have documents.
if (!ancestorDocument)
return true;
const SecurityOrigin* ancestorSecurityOrigin = ancestorDocument->securityOrigin();
if (activeSecurityOrigin->canAccess(ancestorSecurityOrigin))
return true;
// Allow file URL descendant navigation even when allowFileAccessFromFileURLs is false.
// FIXME: It's a bit strange to special-case local origins here. Should we be doing
// something more general instead?
if (isLocalActiveOrigin && ancestorSecurityOrigin->isLocal())
return true;
}
return false;
}
static HashSet<Document*>* documentsThatNeedStyleRecalc = 0;
class DocumentWeakReference : public ThreadSafeRefCounted<DocumentWeakReference> {
......@@ -2590,6 +2618,61 @@ void Document::disableEval()
frame()->script()->disableEval();
}
bool Document::canNavigate(Frame* targetFrame)
{
// The navigation change is safe if the active document is:
// - in the same security origin as the target or one of the target's
// ancestors.
//
// Or the target frame is:
// - a top-level frame in the frame hierarchy and the active frame can
// navigate the target frame's opener per above or it is the opener of
// the target frame.
if (!m_frame)
return false;
// FIXME: Do we actually ever call this function without a targetFrame?
if (!targetFrame)
return true;
// Performance optimization.
// FIXME: Delete this code. It seems very unlikely that this affects performance.
if (m_frame == targetFrame)
return true;
// Let a document navigate window.top so that it can framebust.
if (!isSandboxed(SandboxTopNavigation) && targetFrame == m_frame->tree()->top())
return true;
// A sandboxed frame can only navigate itself and its descendants.
if (isSandboxed(SandboxNavigation) && !targetFrame->tree()->isDescendantOf(m_frame))
return false;
// Let a frame navigate its opener if the opener is a top-level window.
if (!targetFrame->tree()->parent() && m_frame->loader()->opener() == targetFrame)
return true;
// For top-level windows, check the opener.
// FIXME: Can this check be combined with the previous check?
if (!targetFrame->tree()->parent() && canAccessAncestor(securityOrigin(), targetFrame->loader()->opener()))
return true;
// In general, check the frame's ancestors.
if (canAccessAncestor(securityOrigin(), targetFrame))
return true;
Document* targetDocument = targetFrame->document();
// FIXME: this error message should contain more specifics of why the navigation change is not allowed.
String message = "Unsafe JavaScript attempt to initiate a navigation change for frame with URL " +
targetDocument->url().string() + " from frame with URL " + url().string() + ".\n";
// FIXME: should we print to the console of the activeFrame as well?
targetFrame->domWindow()->printErrorMessage(message);
return false;
}
CSSStyleSheet* Document::pageUserSheet()
{
if (m_pageUserSheet)
......
......@@ -621,6 +621,8 @@ public:
virtual void disableEval();
bool canNavigate(Frame* targetFrame);
CSSStyleSheet* pageUserSheet();
void clearPageUserSheet();
void updatePageUserSheet();
......
......@@ -29,22 +29,22 @@
#include "config.h"
#include "FormState.h"
#include "Frame.h"
#include "Document.h"
#include "HTMLFormElement.h"
namespace WebCore {
inline FormState::FormState(PassRefPtr<HTMLFormElement> form, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Frame> sourceFrame, FormSubmissionTrigger formSubmissionTrigger)
inline FormState::FormState(PassRefPtr<HTMLFormElement> form, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Document> sourceDocument, FormSubmissionTrigger formSubmissionTrigger)
: m_form(form)
, m_sourceFrame(sourceFrame)
, m_sourceDocument(sourceDocument)
, m_formSubmissionTrigger(formSubmissionTrigger)
{
m_textFieldValues.swap(textFieldValuesToAdopt);
}
PassRefPtr<FormState> FormState::create(PassRefPtr<HTMLFormElement> form, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Frame> sourceFrame, FormSubmissionTrigger formSubmissionTrigger)
PassRefPtr<FormState> FormState::create(PassRefPtr<HTMLFormElement> form, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Document> sourceDocument, FormSubmissionTrigger formSubmissionTrigger)
{
return adoptRef(new FormState(form, textFieldValuesToAdopt, sourceFrame, formSubmissionTrigger));
return adoptRef(new FormState(form, textFieldValuesToAdopt, sourceDocument, formSubmissionTrigger));
}
}
......@@ -34,7 +34,7 @@
namespace WebCore {
class Frame;
class Document;
class HTMLFormElement;
enum FormSubmissionTrigger {
......@@ -46,19 +46,19 @@ namespace WebCore {
class FormState : public RefCounted<FormState> {
public:
static PassRefPtr<FormState> create(PassRefPtr<HTMLFormElement>, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Frame>, FormSubmissionTrigger);
static PassRefPtr<FormState> create(PassRefPtr<HTMLFormElement>, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Document>, FormSubmissionTrigger);
HTMLFormElement* form() const { return m_form.get(); }
const StringPairVector& textFieldValues() const { return m_textFieldValues; }
Frame* sourceFrame() const { return m_sourceFrame.get(); }
Document* sourceDocument() const { return m_sourceDocument.get(); }
FormSubmissionTrigger formSubmissionTrigger() const { return m_formSubmissionTrigger; }
private:
FormState(PassRefPtr<HTMLFormElement>, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Frame>, FormSubmissionTrigger);
FormState(PassRefPtr<HTMLFormElement>, StringPairVector& textFieldValuesToAdopt, PassRefPtr<Document>, FormSubmissionTrigger);
RefPtr<HTMLFormElement> m_form;
StringPairVector m_textFieldValues;
RefPtr<Frame> m_sourceFrame;
RefPtr<Document> m_sourceDocument;
FormSubmissionTrigger m_formSubmissionTrigger;
};
......
......@@ -216,7 +216,7 @@ PassRefPtr<FormSubmission> FormSubmission::create(HTMLFormElement* form, const A
formData->setIdentifier(generateFormDataIdentifier());
formData->setContainsPasswordData(containsPasswordData);
String targetOrBaseTarget = copiedAttributes.target().isEmpty() ? document->baseTarget() : copiedAttributes.target();
RefPtr<FormState> formState = FormState::create(form, formValues, document->frame(), trigger);
RefPtr<FormState> formState = FormState::create(form, formValues, document, trigger);
return adoptRef(new FormSubmission(copiedAttributes.method(), actionURL, targetOrBaseTarget, encodingType, formState.release(), formData.release(), boundary, lockHistory, event));
}
......
......@@ -294,7 +294,7 @@ void FrameLoader::submitForm(PassRefPtr<FormSubmission> submission)
// FIXME: Find a good spot for these.
ASSERT(submission->data());
ASSERT(submission->state());
ASSERT(submission->state()->sourceFrame() == m_frame);
ASSERT(!submission->state()->sourceDocument()->frame() || submission->state()->sourceDocument()->frame() == m_frame);
if (!m_frame->page())
return;
......@@ -313,7 +313,7 @@ void FrameLoader::submitForm(PassRefPtr<FormSubmission> submission)
}
Frame* targetFrame = m_frame->tree()->find(submission->target());
if (!shouldAllowNavigation(targetFrame))
if (!submission->state()->sourceDocument()->canNavigate(targetFrame))
return;
if (!targetFrame) {
if (!DOMWindow::allowPopUp(m_frame) && !ScriptController::processingUserGesture())
......@@ -1172,7 +1172,9 @@ void FrameLoader::loadFrameRequest(const FrameLoadRequest& request, bool lockHis
// FIXME: It's possible this targetFrame will not be the same frame that was targeted by the actual
// load if frame names have changed.
Frame* sourceFrame = formState ? formState->sourceFrame() : m_frame;
Frame* sourceFrame = formState ? formState->sourceDocument()->frame() : m_frame;
if (!sourceFrame)
sourceFrame = m_frame;
Frame* targetFrame = sourceFrame->loader()->findFrameForNavigation(request.frameName());
if (targetFrame && targetFrame != sourceFrame) {
if (Page* page = targetFrame->page())
......@@ -1498,86 +1500,6 @@ void FrameLoader::reload(bool endToEndReload)
loadWithDocumentLoader(loader.get(), endToEndReload ? FrameLoadTypeReloadFromOrigin : FrameLoadTypeReload, 0);
}
static bool canAccessAncestor(const SecurityOrigin* activeSecurityOrigin, Frame* targetFrame)
{
// targetFrame can be NULL when we're trying to navigate a top-level frame
// that has a NULL opener.
if (!targetFrame)
return false;
const bool isLocalActiveOrigin = activeSecurityOrigin->isLocal();
for (Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree()->parent()) {
Document* ancestorDocument = ancestorFrame->document();
if (!ancestorDocument)
return true;
const SecurityOrigin* ancestorSecurityOrigin = ancestorDocument->securityOrigin();
if (activeSecurityOrigin->canAccess(ancestorSecurityOrigin))
return true;
// Allow file URL descendant navigation even when allowFileAccessFromFileURLs is false.
if (isLocalActiveOrigin && ancestorSecurityOrigin->isLocal())
return true;
}
return false;
}
bool FrameLoader::shouldAllowNavigation(Frame* targetFrame) const
{
// The navigation change is safe if the active frame is:
// - in the same security origin as the target or one of the target's
// ancestors.
//
// Or the target frame is:
// - a top-level frame in the frame hierarchy and the active frame can
// navigate the target frame's opener per above or it is the opener of
// the target frame.
if (!targetFrame)
return true;
// Performance optimization.
if (m_frame == targetFrame)
return true;
// Let a frame navigate the top-level window that contains it. This is
// important to allow because it lets a site "frame-bust" (escape from a
// frame created by another web site).
if (!isDocumentSandboxed(m_frame, SandboxTopNavigation) && targetFrame == m_frame->tree()->top())
return true;
// A sandboxed frame can only navigate itself and its descendants.
if (isDocumentSandboxed(m_frame, SandboxNavigation) && !targetFrame->tree()->isDescendantOf(m_frame))
return false;
// Let a frame navigate its opener if the opener is a top-level window.
if (!targetFrame->tree()->parent() && m_frame->loader()->opener() == targetFrame)
return true;
Document* activeDocument = m_frame->document();
ASSERT(activeDocument);
const SecurityOrigin* activeSecurityOrigin = activeDocument->securityOrigin();
// For top-level windows, check the opener.
if (!targetFrame->tree()->parent() && canAccessAncestor(activeSecurityOrigin, targetFrame->loader()->opener()))
return true;
// In general, check the frame's ancestors.
if (canAccessAncestor(activeSecurityOrigin, targetFrame))
return true;
Document* targetDocument = targetFrame->document();
// FIXME: this error message should contain more specifics of why the navigation change is not allowed.
String message = "Unsafe JavaScript attempt to initiate a navigation change for frame with URL " +
targetDocument->url().string() + " from frame with URL " + activeDocument->url().string() + ".\n";
// FIXME: should we print to the console of the activeFrame as well?
targetFrame->domWindow()->printErrorMessage(message);
return false;
}
void FrameLoader::stopAllLoaders(ClearProvisionalItemPolicy clearProvisionalItemPolicy)
{
ASSERT(!m_frame->document() || !m_frame->document()->inPageCache());
......@@ -3043,7 +2965,10 @@ void FrameLoader::checkDidPerformFirstNavigation()
Frame* FrameLoader::findFrameForNavigation(const AtomicString& name)
{
Frame* frame = m_frame->tree()->find(name);
if (!shouldAllowNavigation(frame))
// FIXME: We calling canNavigate on the Document that's requesting the
// navigation, not based on the document that happens to be displayed in
// this Frame.
if (!m_frame->document()->canNavigate(frame))
return 0;
return frame;
}
......@@ -3306,7 +3231,7 @@ Frame* createWindow(Frame* openerFrame, Frame* lookupFrame, const FrameLoadReque
if (!request.frameName().isEmpty() && request.frameName() != "_blank") {
Frame* frame = lookupFrame->tree()->find(request.frameName());
if (frame && openerFrame->loader()->shouldAllowNavigation(frame)) {
if (frame && openerFrame->document()->canNavigate(frame)) {
if (Page* page = frame->page())
page->chrome()->focus();
created = false;
......
......@@ -248,7 +248,6 @@ public:
FrameLoaderStateMachine* stateMachine() const { return &m_stateMachine; }
bool shouldAllowNavigation(Frame* targetFrame) const;
Frame* findFrameForNavigation(const AtomicString& name);
void applyUserAgent(ResourceRequest&);
......
......@@ -227,10 +227,10 @@ public:
// Now that the timer has fired, we need to repeat the security check which normally is done when
// selecting a target, in case conditions have changed. Other code paths avoid this by targeting
// without leaving a time window. If we fail the check just silently drop the form submission.
Frame* requestingFrame = m_submission->state()->sourceFrame();
if (!requestingFrame->loader()->shouldAllowNavigation(frame))
Document* requestingDocument = m_submission->state()->sourceDocument();
if (!requestingDocument->canNavigate(frame))
return;
FrameLoadRequest frameRequest(requestingFrame->document()->securityOrigin());
FrameLoadRequest frameRequest(requestingDocument->document()->securityOrigin());
m_submission->populateFrameLoadRequest(frameRequest);
frame->loader()->loadFrameRequest(frameRequest, lockHistory(), lockBackForwardList(), m_submission->event(), m_submission->state(), MaybeSendReferrer);
}
......
......@@ -905,11 +905,11 @@ void DOMWindow::close(ScriptExecutionContext* context)
if (context) {
ASSERT(isMainThread());
Frame* activeFrame = static_cast<Document*>(context)->frame();
if (!activeFrame)
Document* activeDocument = static_cast<Document*>(context);
if (!activeDocument)
return;
if (!activeFrame->loader()->shouldAllowNavigation(m_frame))
if (!activeDocument->canNavigate(m_frame))
return;
}
......@@ -1647,11 +1647,11 @@ void DOMWindow::setLocation(const String& urlString, DOMWindow* activeWindow, DO
if (!isCurrentlyDisplayedInFrame())
return;
Frame* activeFrame = activeWindow->frame();
if (!activeFrame)
Document* activeDocument = activeWindow->document();
if (!activeDocument)
return;
if (!activeFrame->loader()->shouldAllowNavigation(m_frame))
if (!activeDocument->canNavigate(m_frame))
return;
Frame* firstFrame = firstWindow->frame();
......@@ -1666,8 +1666,9 @@ void DOMWindow::setLocation(const String& urlString, DOMWindow* activeWindow, DO
return;
// We want a new history item if we are processing a user gesture.
m_frame->navigationScheduler()->scheduleLocationChange(activeFrame->document()->securityOrigin(),
completedURL, activeFrame->loader()->outgoingReferrer(),
m_frame->navigationScheduler()->scheduleLocationChange(activeDocument->securityOrigin(),
// FIXME: What if activeDocument()->frame() is 0?
completedURL, activeDocument->frame()->loader()->outgoingReferrer(),
locking != LockHistoryBasedOnGestureState || !ScriptController::processingUserGesture(),
locking != LockHistoryBasedOnGestureState);
}
......@@ -1774,8 +1775,8 @@ PassRefPtr<DOMWindow> DOMWindow::open(const String& urlString, const AtomicStrin
{
if (!isCurrentlyDisplayedInFrame())
return 0;
Frame* activeFrame = activeWindow->frame();
if (!activeFrame)
Document* activeDocument = activeWindow->document();
if (!activeDocument)
return 0;
Frame* firstFrame = firstWindow->frame();
if (!firstFrame)
......@@ -1800,7 +1801,7 @@ PassRefPtr<DOMWindow> DOMWindow::open(const String& urlString, const AtomicStrin
targetFrame = m_frame;
}
if (targetFrame) {
if (!activeFrame->loader()->shouldAllowNavigation(targetFrame))
if (!activeDocument->canNavigate(targetFrame))
return 0;
KURL completedURL = firstFrame->document()->completeURL(urlString);
......@@ -1815,7 +1816,7 @@ PassRefPtr<DOMWindow> DOMWindow::open(const String& urlString, const AtomicStrin
// determine the outgoing referrer. We replicate that behavior here.
bool lockHistory = !ScriptController::processingUserGesture();
targetFrame->navigationScheduler()->scheduleLocationChange(
activeFrame->document()->securityOrigin(),
activeDocument->securityOrigin(),
completedURL,
firstFrame->loader()->outgoingReferrer(),
lockHistory,
......
......@@ -116,11 +116,11 @@ void History::go(ScriptExecutionContext* context, int distance)
return;
ASSERT(isMainThread());
Frame* activeFrame = static_cast<Document*>(context)->frame();
if (!activeFrame)
Document* activeDocument = static_cast<Document*>(context);
if (!activeDocument)
return;
if (!activeFrame->loader()->shouldAllowNavigation(m_frame))
if (!activeDocument->canNavigate(m_frame))
return;
m_frame->navigationScheduler()->scheduleHistoryNavigation(distance);
......