зеркало из https://github.com/mozilla/pjs.git
Bug 583288 (2/2) - Let forms using DELETE and PUT HTTP method when submitting. r=jst,sicking a2.0=sicking
This commit is contained in:
Родитель
af33f56356
Коммит
a21f5dcc0b
|
@ -44,8 +44,10 @@ class nsIFormControl;
|
|||
class nsISimpleEnumerator;
|
||||
class nsIURI;
|
||||
|
||||
#define NS_FORM_METHOD_GET 0
|
||||
#define NS_FORM_METHOD_POST 1
|
||||
#define NS_FORM_METHOD_GET 0
|
||||
#define NS_FORM_METHOD_POST 1
|
||||
#define NS_FORM_METHOD_PUT 2
|
||||
#define NS_FORM_METHOD_DELETE 3
|
||||
#define NS_FORM_ENCTYPE_URLENCODED 0
|
||||
#define NS_FORM_ENCTYPE_MULTIPART 1
|
||||
#define NS_FORM_ENCTYPE_TEXTPLAIN 2
|
||||
|
|
|
@ -39,8 +39,10 @@
|
|||
#define nsFormSubmissionConstants_h__
|
||||
|
||||
static const nsAttrValue::EnumTable kFormMethodTable[] = {
|
||||
{ "get", NS_FORM_METHOD_GET },
|
||||
{ "post", NS_FORM_METHOD_POST },
|
||||
{ "get", NS_FORM_METHOD_GET },
|
||||
{ "post", NS_FORM_METHOD_POST },
|
||||
{ "put", NS_FORM_METHOD_PUT },
|
||||
{ "delete", NS_FORM_METHOD_DELETE },
|
||||
{ 0 }
|
||||
};
|
||||
// Default method is 'get'.
|
||||
|
|
|
@ -508,6 +508,19 @@ public:
|
|||
*/
|
||||
NS_HIDDEN_(nsresult) GetURIAttr(nsIAtom* aAttr, nsIAtom* aBaseAttr, nsAString& aResult);
|
||||
|
||||
/**
|
||||
* Helper method for NS_IMPL_ENUM_ATTR_DEFAULT_VALUE.
|
||||
* Gets the enum value string of an attribute and using a default value if
|
||||
* the attribute is missing or the string is an invalid enum value.
|
||||
*
|
||||
* @param aType the name of the attribute.
|
||||
* @param aDefault the default value if the attribute is missing or invalid.
|
||||
* @param aResult string corresponding to the value [out].
|
||||
*/
|
||||
NS_HIDDEN_(nsresult) GetEnumAttr(nsIAtom* aAttr,
|
||||
const char* aDefault,
|
||||
nsAString& aResult);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Add/remove this element to the documents name cache
|
||||
|
@ -694,19 +707,6 @@ protected:
|
|||
*/
|
||||
NS_HIDDEN_(nsresult) GetURIListAttr(nsIAtom* aAttr, nsAString& aResult);
|
||||
|
||||
/**
|
||||
* Helper method for NS_IMPL_ENUM_ATTR_DEFAULT_VALUE.
|
||||
* Gets the enum value string of an attribute and using a default value if
|
||||
* the attribute is missing or the string is an invalid enum value.
|
||||
*
|
||||
* @param aType the name of the attribute.
|
||||
* @param aDefault the default value if the attribute is missing or invalid.
|
||||
* @param aResult string corresponding to the value [out].
|
||||
*/
|
||||
NS_HIDDEN_(nsresult) GetEnumAttr(nsIAtom* aAttr,
|
||||
const char* aDefault,
|
||||
nsAString& aResult);
|
||||
|
||||
/**
|
||||
* Locates the nsIEditor associated with this node. In general this is
|
||||
* equivalent to GetEditorInternal(), but for designmode or contenteditable,
|
||||
|
|
|
@ -878,11 +878,25 @@ nsHTMLFormElement::SubmitSubmission(nsFormSubmission* aFormSubmission)
|
|||
getter_AddRefs(postDataStream));
|
||||
NS_ENSURE_SUBMIT_SUCCESS(rv);
|
||||
|
||||
nsAutoString method;
|
||||
if (originatingElement &&
|
||||
originatingElement->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::formmethod)) {
|
||||
if (!originatingElement->IsHTML()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
static_cast<nsGenericHTMLElement*>(originatingElement)->
|
||||
GetEnumAttr(nsGkAtoms::formmethod, kFormDefaultMethod->tag, method);
|
||||
} else {
|
||||
GetEnumAttr(nsGkAtoms::method, kFormDefaultMethod->tag, method);
|
||||
}
|
||||
|
||||
rv = linkHandler->OnLinkClickSync(this, actionURI,
|
||||
target.get(),
|
||||
postDataStream, nsnull,
|
||||
getter_AddRefs(docShell),
|
||||
getter_AddRefs(mSubmittingRequest));
|
||||
getter_AddRefs(mSubmittingRequest),
|
||||
NS_LossyConvertUTF16toASCII(method).get());
|
||||
NS_ENSURE_SUBMIT_SUCCESS(rv);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
function handleRequest(request, response)
|
||||
{
|
||||
// Redirect to another domain.
|
||||
// Using 307 to keep the method.
|
||||
response.setStatusLine(null, 307, "Temp");
|
||||
response.setHeader("Location",
|
||||
"http://example.org:80/tests/content/html/content/test/583288_submit_server.sjs");
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
function handleRequest(request, response)
|
||||
{
|
||||
// Send the HTTP method.
|
||||
response.write(request.method);
|
||||
}
|
|
@ -212,6 +212,11 @@ _TEST_FILES = \
|
|||
test_bug590353-1.html \
|
||||
test_bug590353-2.html \
|
||||
test_bug593689.html \
|
||||
test_bug583288-1.html \
|
||||
test_bug583288-2.html \
|
||||
test_bug583288-3.html \
|
||||
583288_submit_server.sjs \
|
||||
583288_redirect_server.sjs \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=583288
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 583288</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body onload='runTests();'>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=583288">Mozilla Bug 583288</a>
|
||||
<p id="display"></p>
|
||||
<style>
|
||||
iframe { width: 70px; height: 40px;}
|
||||
</style>
|
||||
<!--<div id="content" style="display: none">-->
|
||||
<div id="content">
|
||||
<iframe name='get' id='get'></iframe>
|
||||
<iframe name='post' id='post'></iframe>
|
||||
<iframe name='put' id='put'></iframe>
|
||||
<iframe name='del' id='del'></iframe>
|
||||
<iframe name='get2' id='get2'></iframe>
|
||||
<iframe name='post2' id='post2'></iframe>
|
||||
<iframe name='put2' id='put2'></iframe>
|
||||
<iframe name='del2' id='del2'></iframe>
|
||||
|
||||
<form action="583288_submit_server.sjs" target='get' method='get'>
|
||||
</form>
|
||||
<form action="583288_submit_server.sjs" target='post' method='post'>
|
||||
</form>
|
||||
<form action="583288_submit_server.sjs" target='put' method='put'>
|
||||
</form>
|
||||
<form action="583288_submit_server.sjs" target='del' method='delete'>
|
||||
</form>
|
||||
|
||||
<form action="583288_submit_server.sjs">
|
||||
<input type='submit' id='iget' value='get' formtarget='get2' formmethod='get'>
|
||||
</form>
|
||||
<form action="583288_submit_server.sjs">
|
||||
<input type='submit' id='ipost' value='post' formtarget='post2' formmethod='post'>
|
||||
</form>
|
||||
<form action="583288_submit_server.sjs">
|
||||
<input type='submit' id='iput' value='put' formtarget='put2' formmethod='put'>
|
||||
</form>
|
||||
<form action="583288_submit_server.sjs">
|
||||
<input type='submit' id='idel' value='delete' formtarget='del2' formmethod='delete'>
|
||||
</form>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 583288 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var gTestResults = {
|
||||
get: "GET",
|
||||
get2: "GET",
|
||||
post: "POST",
|
||||
post2: "POST",
|
||||
put: "PUT",
|
||||
put2: "PUT",
|
||||
del: "DELETE",
|
||||
del2: "DELETE",
|
||||
};
|
||||
|
||||
var gPendingLoad = 0; // Has to be set after depending on the frames number.
|
||||
|
||||
function runTests()
|
||||
{
|
||||
// We add a load event for the frames which will be called when the forms
|
||||
// will be submitted.
|
||||
var frames = [ document.getElementById('get'),
|
||||
document.getElementById('get2'),
|
||||
document.getElementById('post'),
|
||||
document.getElementById('post2'),
|
||||
document.getElementById('put'),
|
||||
document.getElementById('put2'),
|
||||
document.getElementById('del'),
|
||||
document.getElementById('del2'),
|
||||
];
|
||||
gPendingLoad = frames.length;
|
||||
|
||||
for (var i=0; i<frames.length; ++i) {
|
||||
frames[i].setAttribute('onload', "frameLoaded(this);");
|
||||
}
|
||||
|
||||
// The four first forms can be submitted with .submit().
|
||||
for (var i=0; i<4; ++i) {
|
||||
document.forms[i].submit();
|
||||
}
|
||||
|
||||
/**
|
||||
* We are going to focus each element before interacting with them so we are
|
||||
* sure they will be visible in the iframe.
|
||||
* Considering we are using synthesizeKey that may be not required.
|
||||
*
|
||||
* Focusing the first element (id='iget') is launching the tests.
|
||||
*/
|
||||
document.getElementById('iget').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
document.getElementById('ipost').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('ipost').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
document.getElementById('iput').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('iput').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
document.getElementById('idel').focus();
|
||||
}, false);
|
||||
|
||||
document.getElementById('idel').addEventListener('focus', function(aEvent) {
|
||||
aEvent.target.removeEventListener('focus', arguments.callee, false);
|
||||
synthesizeKey("VK_RETURN", {});
|
||||
}, false);
|
||||
|
||||
document.getElementById('iget').focus();
|
||||
}
|
||||
|
||||
function frameLoaded(aFrame) {
|
||||
// Check if formaction/action has the correct behavior.
|
||||
is(aFrame.contentDocument.documentElement.textContent, gTestResults[aFrame.name],
|
||||
"the method used during the form submission should be " +
|
||||
gTestResults[aFrame.name]);
|
||||
|
||||
if (--gPendingLoad == 0) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,99 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=583288
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 583288</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body onload='runTests();'>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=583288">Mozilla Bug 583288</a>
|
||||
<p id="display"></p>
|
||||
<style>
|
||||
iframe { width: 70px; height: 40px;}
|
||||
</style>
|
||||
<!--<div id="content" style="display: none">-->
|
||||
<div id="content">
|
||||
<iframe name='get' id='get'></iframe>
|
||||
<iframe name='post' id='post'></iframe>
|
||||
<iframe name='put' id='put'></iframe>
|
||||
<iframe name='del' id='del'></iframe>
|
||||
|
||||
<form action="http://example.org:80/tests/content/html/content/test/583288_submit_server.sjs" target='get' method='get'>
|
||||
</form>
|
||||
<form action="http://example.org:80/tests/content/html/content/test/583288_submit_server.sjs" target='post' method='post'>
|
||||
</form>
|
||||
<form action="http://example.org:80/tests/content/html/content/test/583288_submit_server.sjs" target='put' method='put'>
|
||||
</form>
|
||||
<form action="http://example.org:80/tests/content/html/content/test/583288_submit_server.sjs" target='del' method='delete'>
|
||||
</form>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 583288 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var gLoaded = 0;
|
||||
|
||||
function runTests()
|
||||
{
|
||||
// We add a load event for the frames which will be called when the forms
|
||||
// will be submitted.
|
||||
var frames = [ document.getElementById('get'),
|
||||
document.getElementById('post'),
|
||||
document.getElementById('put'),
|
||||
document.getElementById('del'),
|
||||
];
|
||||
|
||||
for (var i=0; i<2; ++i) {
|
||||
frames[i].setAttribute('onload', "frameShouldLoad();");
|
||||
}
|
||||
for (var i=2; i<4; ++i) {
|
||||
frames[i].setAttribute('onload', "frameShouldNotLoad();");
|
||||
}
|
||||
|
||||
// The four forms can be submitted with .submit().
|
||||
// Submitting those which should be blocked so we can considering if the the
|
||||
// last ones are submitted, that means the firsts were blocked.
|
||||
for (var i=3; i>=0; --i) {
|
||||
document.forms[i].submit();
|
||||
}
|
||||
|
||||
// After the two first succefull submissions, we are going to stop the test.
|
||||
// The expected successfull submissions have been requested at the end so we
|
||||
// expect them at the end. So if the two firsts ones didn't show up, we are
|
||||
// assuming they have been blocked.
|
||||
// Unfortunately, it doesn't sound like there is a better way to test that.
|
||||
// The worst thing that can happen here is to have a random green (if the
|
||||
// first two submissions were not blocked but came after the last two).
|
||||
}
|
||||
|
||||
function frameShouldLoad() {
|
||||
ok(true, "The form submission should succeed.");
|
||||
if (++gLoaded == 2) {
|
||||
finished();
|
||||
}
|
||||
}
|
||||
|
||||
function frameShouldNotLoad() {
|
||||
ok(false, "The form submission should have been blocked");
|
||||
if (++gLoaded == 2) {
|
||||
finished();
|
||||
}
|
||||
}
|
||||
|
||||
function finished()
|
||||
{
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,85 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=583288
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 583288</title>
|
||||
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body onload='runTests();'>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=583288">Mozilla Bug 583288</a>
|
||||
<p id="display"></p>
|
||||
<style>
|
||||
iframe { width: 70px; height: 40px;}
|
||||
</style>
|
||||
<!--<div id="content" style="display: none">-->
|
||||
<div id="content">
|
||||
<iframe name='get' id='get'></iframe>
|
||||
<iframe name='post' id='post'></iframe>
|
||||
<iframe name='put' id='put'></iframe>
|
||||
<iframe name='del' id='del'></iframe>
|
||||
|
||||
<form action="583288_redirect_server.sjs" target='get' method='get'>
|
||||
</form>
|
||||
<form action="583288_redirect_server.sjs" target='post' method='post'>
|
||||
</form>
|
||||
<form action="583288_redirect_server.sjs" target='put' method='put'>
|
||||
</form>
|
||||
<form action="583288_redirect_server.sjs" target='del' method='delete'>
|
||||
</form>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 583288 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var gTestResults = {
|
||||
get: "GET",
|
||||
post: "POST",
|
||||
put: "",
|
||||
del: "",
|
||||
};
|
||||
|
||||
var gPendingLoad = 0; // Has to be set after depending on the frames number.
|
||||
|
||||
function runTests()
|
||||
{
|
||||
// We add a load event for the frames which will be called when the forms
|
||||
// will be submitted.
|
||||
var frames = [ document.getElementById('get'),
|
||||
document.getElementById('post'),
|
||||
document.getElementById('put'),
|
||||
document.getElementById('del'),
|
||||
];
|
||||
gPendingLoad = frames.length;
|
||||
|
||||
for (var i=0; i<gPendingLoad; ++i) {
|
||||
frames[i].setAttribute('onload', "frameLoaded(this);");
|
||||
}
|
||||
|
||||
// The four forms can be submitted with .submit().
|
||||
for (var i=0; i<4; ++i) {
|
||||
document.forms[i].submit();
|
||||
}
|
||||
}
|
||||
|
||||
function frameLoaded(aFrame) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
is(aFrame.contentDocument.documentElement.textContent, gTestResults[aFrame.name],
|
||||
"cross-origin submission with redirection should work");
|
||||
|
||||
if (--gPendingLoad == 0) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -30,11 +30,9 @@ var methodTestData = [
|
|||
// Default value.
|
||||
[ "get" ],
|
||||
// Valid values.
|
||||
[ "get", "post" ],
|
||||
[ "get", "post", "put", "delete" ],
|
||||
// Invalid values.
|
||||
[ "", " ", "foo" ],
|
||||
// TODO values, see bug 583289 and bug 583288.
|
||||
[ "delete", "put" ],
|
||||
];
|
||||
|
||||
function checkAttribute(form, attrName, idlName, data)
|
||||
|
|
|
@ -1412,7 +1412,8 @@ nsDocShell::LoadURI(nsIURI * aURI,
|
|||
nsnull, // No SHEntry
|
||||
aFirstParty,
|
||||
nsnull, // No nsIDocShell
|
||||
nsnull); // No nsIRequest
|
||||
nsnull, // No nsIRequest
|
||||
nsnull); // Use default HTTP method
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -4095,7 +4096,7 @@ nsDocShell::LoadErrorPage(nsIURI *aURI, const PRUnichar *aURL,
|
|||
return InternalLoad(errorPageURI, nsnull, nsnull,
|
||||
INTERNAL_LOAD_FLAGS_INHERIT_OWNER, nsnull, nsnull,
|
||||
nsnull, nsnull, LOAD_ERROR_PAGE,
|
||||
nsnull, PR_TRUE, nsnull, nsnull);
|
||||
nsnull, PR_TRUE, nsnull, nsnull, nsnull);
|
||||
}
|
||||
|
||||
|
||||
|
@ -4159,7 +4160,8 @@ nsDocShell::Reload(PRUint32 aReloadFlags)
|
|||
nsnull, // No SHEntry
|
||||
PR_TRUE,
|
||||
nsnull, // No nsIDocShell
|
||||
nsnull); // No nsIRequest
|
||||
nsnull, // No nsIRequest
|
||||
nsnull); // Use default HTTP method
|
||||
}
|
||||
|
||||
|
||||
|
@ -5869,7 +5871,7 @@ nsDocShell::OnLocationChange(nsIWebProgress * aProgress,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsresult
|
||||
nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
|
||||
nsIChannel* aNewChannel,
|
||||
PRUint32 aRedirectFlags,
|
||||
|
@ -5878,13 +5880,44 @@ nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
|
|||
NS_ASSERTION(aStateFlags & STATE_REDIRECTING,
|
||||
"Calling OnRedirectStateChange when there is no redirect");
|
||||
if (!(aStateFlags & STATE_IS_DOCUMENT))
|
||||
return; // not a toplevel document
|
||||
return NS_OK; // not a toplevel document
|
||||
|
||||
nsCOMPtr<nsIURI> oldURI, newURI;
|
||||
aOldChannel->GetURI(getter_AddRefs(oldURI));
|
||||
aNewChannel->GetURI(getter_AddRefs(newURI));
|
||||
if (!oldURI || !newURI) {
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// HTTP channel with unsafe methods should not be redirected to a cross-domain.
|
||||
if (!ChannelIsSafeMethod(aNewChannel)) {
|
||||
// This code is very similar to the code of nsSameOriginChecker in
|
||||
// nsContentUtils but we can't use nsSameOriginChecker because it
|
||||
// needs to use a channel callback (which we already use).
|
||||
// If nsSameOriginChecker happens to not use a channel callback
|
||||
// anymore, this code would be a good candidate for refactoring.
|
||||
nsCOMPtr<nsIPrincipal> oldPrincipal;
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
|
||||
|
||||
rv = secMan->GetChannelPrincipal(aOldChannel,
|
||||
getter_AddRefs(oldPrincipal));
|
||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||
|
||||
NS_ASSERTION(oldPrincipal, "oldPrincipal should not be null!");
|
||||
|
||||
nsCOMPtr<nsIURI> newOriginalURI;
|
||||
aNewChannel->GetOriginalURI(getter_AddRefs(newOriginalURI));
|
||||
|
||||
rv = oldPrincipal->CheckMayLoad(newURI, PR_FALSE);
|
||||
if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
|
||||
rv = oldPrincipal->CheckMayLoad(newOriginalURI, PR_FALSE);
|
||||
}
|
||||
|
||||
// The requested tried to be redirected, we have to cancel it.
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Below a URI visit is saved (see AddURIVisit method doc).
|
||||
|
@ -5935,6 +5968,8 @@ nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
|
|||
mLoadType = LOAD_NORMAL_REPLACE;
|
||||
SetHistoryEntry(&mLSHE, nsnull);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -6306,7 +6341,8 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress,
|
|||
nsnull, // No SHEntry
|
||||
PR_TRUE, // first party site
|
||||
nsnull, // No nsIDocShell
|
||||
nsnull); // No nsIRequest
|
||||
nsnull, // No nsIRequest
|
||||
nsnull); // Use default HTTP method
|
||||
}
|
||||
else {
|
||||
DisplayLoadError(aStatus, url, nsnull, aChannel);
|
||||
|
@ -7750,7 +7786,7 @@ public:
|
|||
return mDocShell->InternalLoad(mURI, mReferrer, mOwner, mFlags,
|
||||
nsnull, mTypeHint.get(),
|
||||
mPostData, mHeadersData, mLoadType,
|
||||
mSHEntry, mFirstParty, nsnull, nsnull);
|
||||
mSHEntry, mFirstParty, nsnull, nsnull, nsnull);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -7784,7 +7820,8 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||
nsISHEntry * aSHEntry,
|
||||
PRBool aFirstParty,
|
||||
nsIDocShell** aDocShell,
|
||||
nsIRequest** aRequest)
|
||||
nsIRequest** aRequest,
|
||||
const char* aHttpMethod)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
@ -7986,7 +8023,8 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||
aSHEntry,
|
||||
aFirstParty,
|
||||
aDocShell,
|
||||
aRequest);
|
||||
aRequest,
|
||||
aHttpMethod);
|
||||
if (rv == NS_ERROR_NO_CONTENT) {
|
||||
// XXXbz except we never reach this code!
|
||||
if (isNewWindow) {
|
||||
|
@ -8421,7 +8459,8 @@ nsDocShell::InternalLoad(nsIURI * aURI,
|
|||
aDocShell, getter_AddRefs(req),
|
||||
(aFlags & INTERNAL_LOAD_FLAGS_FIRST_LOAD) != 0,
|
||||
(aFlags & INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER) != 0,
|
||||
(aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES) != 0);
|
||||
(aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES) != 0,
|
||||
aHttpMethod);
|
||||
if (req && aRequest)
|
||||
NS_ADDREF(*aRequest = req);
|
||||
|
||||
|
@ -8502,7 +8541,8 @@ nsDocShell::DoURILoad(nsIURI * aURI,
|
|||
nsIRequest ** aRequest,
|
||||
PRBool aIsNewWindowTarget,
|
||||
PRBool aBypassClassifier,
|
||||
PRBool aForceAllowCookies)
|
||||
PRBool aForceAllowCookies,
|
||||
const char* aHttpMethod)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIURILoader> uriLoader;
|
||||
|
@ -8685,6 +8725,20 @@ nsDocShell::DoURILoad(nsIURI * aURI,
|
|||
// Referrer is currenly only set for link clicks here.
|
||||
httpChannel->SetReferrer(aReferrerURI);
|
||||
}
|
||||
|
||||
// If a specific HTTP method has been requested, set it.
|
||||
if (aHttpMethod) {
|
||||
// Tell the cache it _has_ to open a cache entry.
|
||||
PRUint32 loadFlags;
|
||||
if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))) {
|
||||
channel->SetLoadFlags(loadFlags | nsICachingChannel::FORCE_OPEN_CACHE_ENTRY);
|
||||
}
|
||||
|
||||
// The method name have to be correct.
|
||||
// Otherwise SetRequestMethod will return a failure.
|
||||
rv = httpChannel->SetRequestMethod(nsDependentCString(aHttpMethod));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Set the owner of the channel, but only for channels that can't
|
||||
|
@ -8735,6 +8789,14 @@ nsDocShell::DoURILoad(nsIURI * aURI,
|
|||
}
|
||||
}
|
||||
|
||||
// If a specific HTTP channel has been set and it is not a safe method,
|
||||
// we should prevent cross-origin requests.
|
||||
if (aHttpMethod && ownerPrincipal && !ChannelIsSafeMethod(channel)) {
|
||||
if (NS_FAILED(ownerPrincipal->CheckMayLoad(aURI, PR_FALSE))) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel);
|
||||
if (scriptChannel) {
|
||||
// Allow execution against our context if the principals match
|
||||
|
@ -9946,7 +10008,8 @@ nsDocShell::LoadHistoryEntry(nsISHEntry * aEntry, PRUint32 aLoadType)
|
|||
aEntry, // SHEntry
|
||||
PR_TRUE,
|
||||
nsnull, // No nsIDocShell
|
||||
nsnull); // No nsIRequest
|
||||
nsnull, // No nsIRequest
|
||||
nsnull); // Use default HTTP method
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -10359,6 +10422,7 @@ NS_IMETHODIMP nsDocShell::MakeEditable(PRBool inWaitForUriLoad)
|
|||
return mEditorData->MakeEditable(inWaitForUriLoad);
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
nsDocShell::ChannelIsPost(nsIChannel* aChannel)
|
||||
{
|
||||
|
@ -10372,6 +10436,21 @@ nsDocShell::ChannelIsPost(nsIChannel* aChannel)
|
|||
return method.Equals("POST");
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
nsDocShell::ChannelIsSafeMethod(nsIChannel* aChannel)
|
||||
{
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
|
||||
if (!httpChannel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCAutoString method;
|
||||
httpChannel->GetRequestMethod(method);
|
||||
return method.Equals("GET") || method.Equals("POST") ||
|
||||
method.Equals("HEAD");
|
||||
}
|
||||
|
||||
void
|
||||
nsDocShell::ExtractLastVisit(nsIChannel* aChannel,
|
||||
nsIURI** aURI,
|
||||
|
@ -11302,7 +11381,8 @@ nsDocShell::OnLinkClickSync(nsIContent *aContent,
|
|||
nsIInputStream* aPostDataStream,
|
||||
nsIInputStream* aHeadersDataStream,
|
||||
nsIDocShell** aDocShell,
|
||||
nsIRequest** aRequest)
|
||||
nsIRequest** aRequest,
|
||||
const char* aHttpMethod)
|
||||
{
|
||||
// Initialize the DocShell / Request
|
||||
if (aDocShell) {
|
||||
|
@ -11378,7 +11458,8 @@ nsDocShell::OnLinkClickSync(nsIContent *aContent,
|
|||
nsnull, // No SHEntry
|
||||
PR_TRUE, // first party site
|
||||
aDocShell, // DocShell out-param
|
||||
aRequest); // Request out-param
|
||||
aRequest, // Request out-param
|
||||
aHttpMethod); // HTTP Method
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
DispatchPings(aContent, referer);
|
||||
}
|
||||
|
|
|
@ -243,7 +243,8 @@ public:
|
|||
nsIInputStream* aPostDataStream = 0,
|
||||
nsIInputStream* aHeadersDataStream = 0,
|
||||
nsIDocShell** aDocShell = 0,
|
||||
nsIRequest** aRequest = 0);
|
||||
nsIRequest** aRequest = 0,
|
||||
const char* aHttpMethod = 0);
|
||||
NS_IMETHOD OnOverLink(nsIContent* aContent,
|
||||
nsIURI* aURI,
|
||||
const PRUnichar* aTargetSpec);
|
||||
|
@ -325,7 +326,8 @@ protected:
|
|||
nsIRequest ** aRequest,
|
||||
PRBool aIsNewWindowTarget,
|
||||
PRBool aBypassClassifier,
|
||||
PRBool aForceAllowCookies);
|
||||
PRBool aForceAllowCookies,
|
||||
const char* aHttpMethod);
|
||||
NS_IMETHOD AddHeadersToChannel(nsIInputStream * aHeadersData,
|
||||
nsIChannel * aChannel);
|
||||
virtual nsresult DoChannelLoad(nsIChannel * aChannel,
|
||||
|
@ -434,10 +436,10 @@ protected:
|
|||
|
||||
// overridden from nsDocLoader, this provides more information than the
|
||||
// normal OnStateChange with flags STATE_REDIRECTING
|
||||
virtual void OnRedirectStateChange(nsIChannel* aOldChannel,
|
||||
nsIChannel* aNewChannel,
|
||||
PRUint32 aRedirectFlags,
|
||||
PRUint32 aStateFlags);
|
||||
virtual nsresult OnRedirectStateChange(nsIChannel* aOldChannel,
|
||||
nsIChannel* aNewChannel,
|
||||
PRUint32 aRedirectFlags,
|
||||
PRUint32 aStateFlags);
|
||||
|
||||
/**
|
||||
* Helper function that determines if channel is an HTTP POST.
|
||||
|
@ -447,7 +449,17 @@ protected:
|
|||
*
|
||||
* @return True iff channel is an HTTP post.
|
||||
*/
|
||||
bool ChannelIsPost(nsIChannel* aChannel);
|
||||
static bool ChannelIsPost(nsIChannel* aChannel);
|
||||
|
||||
/**
|
||||
* Helper function that determines if the HTTP channel has a safe method
|
||||
*
|
||||
* @param aChannel The channel to test
|
||||
*
|
||||
* @return Whether the channel has a safe HTTP method.
|
||||
* @note Will return false if the channel isn't an HTTP channel.
|
||||
*/
|
||||
static bool ChannelIsSafeMethod(nsIChannel* aChannel);
|
||||
|
||||
/**
|
||||
* Helper function that finds the last URI and its transition flags for a
|
||||
|
|
|
@ -71,7 +71,7 @@ interface nsIPrincipal;
|
|||
interface nsIWebBrowserPrint;
|
||||
interface nsIVariant;
|
||||
|
||||
[scriptable, uuid(74470127-87eb-4f79-8293-1616fe9cb689)]
|
||||
[scriptable, uuid(0e1e1ee5-5baa-4e27-98af-3197d70d0304)]
|
||||
interface nsIDocShell : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -155,6 +155,10 @@ interface nsIDocShell : nsISupports
|
|||
* @param aLoadFlags - Flags to modify load behaviour. Flags are defined
|
||||
* in nsIWebNavigation.
|
||||
* @param aSHEntry - Active Session History entry (if loading from SH)
|
||||
* @param firstParty -
|
||||
* @param aDocShell -
|
||||
* @param aRequest -
|
||||
* @param aHttpMethod - Force the HTTP channel to use a specific HTTP method
|
||||
*/
|
||||
[noscript]void internalLoad(in nsIURI aURI,
|
||||
in nsIURI aReferrer,
|
||||
|
@ -168,7 +172,8 @@ interface nsIDocShell : nsISupports
|
|||
in nsISHEntry aSHEntry,
|
||||
in boolean firstParty,
|
||||
out nsIDocShell aDocShell,
|
||||
out nsIRequest aRequest);
|
||||
out nsIRequest aRequest,
|
||||
in string aHttpMethod);
|
||||
|
||||
/**
|
||||
* Do either a history.pushState() or history.replaceState() operation,
|
||||
|
|
|
@ -1609,7 +1609,9 @@ NS_IMETHODIMP nsDocLoader::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
|
|||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
OnRedirectStateChange(aOldChannel, aNewChannel, aFlags, stateFlags);
|
||||
nsresult rv = OnRedirectStateChange(aOldChannel, aNewChannel, aFlags,
|
||||
stateFlags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
FireOnStateChange(this, aOldChannel, stateFlags, NS_OK);
|
||||
}
|
||||
|
||||
|
|
|
@ -69,11 +69,11 @@ struct nsListenerInfo;
|
|||
****************************************************************************/
|
||||
|
||||
#define NS_THIS_DOCLOADER_IMPL_CID \
|
||||
{ /* b4ec8387-98aa-4c08-93b6-6d23069c06f2 */ \
|
||||
0xb4ec8387, \
|
||||
0x98aa, \
|
||||
0x4c08, \
|
||||
{0x93, 0xb6, 0x6d, 0x23, 0x06, 0x9c, 0x06, 0xf2} \
|
||||
{ \
|
||||
0x306cae1f, \
|
||||
0x90ee, \
|
||||
0x4e51, \
|
||||
{0xaf, 0x27, 0x9c, 0x13, 0xde, 0xba, 0x91, 0xb6} \
|
||||
}
|
||||
|
||||
class nsDocLoader : public nsIDocumentLoader,
|
||||
|
@ -179,10 +179,12 @@ protected:
|
|||
// @param aRedirectFlags The flags being sent to OnStateChange that
|
||||
// indicate the type of redirect.
|
||||
// @param aStateFlags The channel flags normally sent to OnStateChange.
|
||||
virtual void OnRedirectStateChange(nsIChannel* aOldChannel,
|
||||
nsIChannel* aNewChannel,
|
||||
PRUint32 aRedirectFlags,
|
||||
PRUint32 aStateFlags) {}
|
||||
//
|
||||
// @return Something else than NS_OK if the redirection should be cancelled.
|
||||
virtual nsresult OnRedirectStateChange(nsIChannel* aOldChannel,
|
||||
nsIChannel* aNewChannel,
|
||||
PRUint32 aRedirectFlags,
|
||||
PRUint32 aStateFlags) { return NS_OK; }
|
||||
|
||||
void doStartDocumentLoad();
|
||||
void doStartURLLoad(nsIRequest *request);
|
||||
|
|
|
@ -48,7 +48,7 @@ class nsGUIEvent;
|
|||
|
||||
// Interface ID for nsILinkHandler
|
||||
#define NS_ILINKHANDLER_IID \
|
||||
{ 0x71627c30, 0xd3c5, 0x4ad0,{0xb5, 0x33, 0x6e, 0x01, 0x91, 0xf2, 0x79, 0x32}}
|
||||
{ 0x1fa72627, 0x646b, 0x4573,{0xb5, 0xc8, 0xb4, 0x65, 0xc6, 0x78, 0xd4, 0x9d}}
|
||||
|
||||
/**
|
||||
* Interface used for handling clicks on links
|
||||
|
@ -87,6 +87,7 @@ public:
|
|||
* @param aHeadersDataStream ???
|
||||
* @param aDocShell (out-param) the DocShell that the request was opened on
|
||||
* @param aRequest the request that was opened
|
||||
* @param aHttpMethod forces the http channel to use a specific method
|
||||
*/
|
||||
NS_IMETHOD OnLinkClickSync(nsIContent* aContent,
|
||||
nsIURI* aURI,
|
||||
|
@ -94,7 +95,8 @@ public:
|
|||
nsIInputStream* aPostDataStream = 0,
|
||||
nsIInputStream* aHeadersDataStream = 0,
|
||||
nsIDocShell** aDocShell = 0,
|
||||
nsIRequest** aRequest = 0) = 0;
|
||||
nsIRequest** aRequest = 0,
|
||||
const char* aHttpMethod = 0) = 0;
|
||||
|
||||
/**
|
||||
* Process a mouse-over a link.
|
||||
|
|
Загрузка…
Ссылка в новой задаче