mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 974018: Implement nsIRedirectHistory (r=mayhemer)
This commit is contained in:
parent
bb25d1dd44
commit
d12c20c0b3
@ -78,6 +78,7 @@ XPIDL_SOURCES += [
|
||||
'nsIProxyInfo.idl',
|
||||
'nsIRandomGenerator.idl',
|
||||
'nsIRedirectChannelRegistrar.idl',
|
||||
'nsIRedirectHistory.idl',
|
||||
'nsIRedirectResultListener.idl',
|
||||
'nsIRequest.idl',
|
||||
'nsIRequestObserver.idl',
|
||||
|
25
netwerk/base/public/nsIRedirectHistory.idl
Normal file
25
netwerk/base/public/nsIRedirectHistory.idl
Normal file
@ -0,0 +1,25 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/**
|
||||
* Allows keeping track of channel redirects. Currently nsHttpChannel is the
|
||||
* only implementor.
|
||||
*/
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIArray;
|
||||
interface nsIPrincipal;
|
||||
|
||||
[scriptable, uuid(ab87eabf-d0c4-40a9-b4b2-a1191108d4c0)]
|
||||
interface nsIRedirectHistory : nsISupports
|
||||
{
|
||||
/**
|
||||
* An array of nsIPrincipal that store the redirects associated with this
|
||||
* channel. This array is filled whether or not the channel has ever been
|
||||
* opened. The last element of the array is associated with the most recent
|
||||
* channel.
|
||||
*/
|
||||
readonly attribute nsIArray redirects;
|
||||
};
|
@ -19,6 +19,7 @@
|
||||
#include "nsITimedChannel.h"
|
||||
#include "nsIEncodedChannel.h"
|
||||
#include "nsIApplicationCacheChannel.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsStreamListenerWrapper.h"
|
||||
#include "nsISecurityConsoleMessage.h"
|
||||
@ -160,6 +161,7 @@ NS_INTERFACE_MAP_BEGIN(HttpBaseChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIEncodedChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRedirectHistory)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIUploadChannel2)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
|
||||
@ -1588,6 +1590,13 @@ HttpBaseChannel::SetResponseTimeoutEnabled(bool aEnable)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::AddRedirect(nsIPrincipal *aRedirect)
|
||||
{
|
||||
mRedirects.AppendObject(aRedirect);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpBaseChannel::nsISupportsPriority
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1654,6 +1663,60 @@ HttpBaseChannel::GetEntityID(nsACString& aEntityID)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIPrincipal *
|
||||
HttpBaseChannel::GetPrincipal(bool requireAppId)
|
||||
{
|
||||
if (mPrincipal) {
|
||||
if (requireAppId && mPrincipal->GetUnknownAppId()) {
|
||||
LOG(("HttpBaseChannel::GetPrincipal: No app id [this=%p]", this));
|
||||
return nullptr;
|
||||
}
|
||||
return mPrincipal;
|
||||
}
|
||||
|
||||
nsIScriptSecurityManager *securityManager =
|
||||
nsContentUtils::GetSecurityManager();
|
||||
|
||||
if (!securityManager) {
|
||||
LOG(("HttpBaseChannel::GetPrincipal: No security manager [this=%p]",
|
||||
this));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
securityManager->GetChannelPrincipal(this, getter_AddRefs(mPrincipal));
|
||||
if (!mPrincipal) {
|
||||
LOG(("HttpBaseChannel::GetPrincipal: No channel principal [this=%p]",
|
||||
this));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// principals with unknown app ids do not work with the permission manager
|
||||
if (requireAppId && mPrincipal->GetUnknownAppId()) {
|
||||
LOG(("HttpBaseChannel::GetPrincipal: No app id [this=%p]", this));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return mPrincipal;
|
||||
}
|
||||
|
||||
// nsIRedirectHistory
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::GetRedirects(nsIArray * *aRedirects)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMutableArray> redirects =
|
||||
do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (int i = 0; i < mRedirects.Count(); ++i) {
|
||||
rv = redirects->AppendElement(mRedirects[i], false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
*aRedirects = redirects;
|
||||
NS_IF_ADDREF(*aRedirects);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel::nsITraceableChannel
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1899,6 +1962,25 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
|
||||
"[this=%p] transferring chain of redirect cache-keys", this));
|
||||
httpInternal->SetCacheKeysRedirectChain(mRedirectedCachekeys.forget());
|
||||
}
|
||||
// Transfer existing redirect information. Add all of our existing
|
||||
// redirects to the new channel.
|
||||
for (int32_t i = 0; i < mRedirects.Count(); ++i) {
|
||||
#ifdef PR_LOGGING
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
mRedirects[i]->GetURI(getter_AddRefs(uri));
|
||||
nsCString spec;
|
||||
uri->GetSpec(spec);
|
||||
LOG(("HttpBaseChannel::SetupReplacementChannel adding redirect %s "
|
||||
"[this=%p]", spec.get(), this));
|
||||
#endif
|
||||
httpInternal->AddRedirect(mRedirects[i]);
|
||||
}
|
||||
|
||||
// Add our own principal to the redirect information on the new channel. If
|
||||
// the redirect is vetoed, then newChannel->AsyncOpen won't be called.
|
||||
// However, the new channel's redirect chain will still be complete.
|
||||
nsCOMPtr<nsIPrincipal> principal = GetPrincipal(false);
|
||||
httpInternal->AddRedirect(principal);
|
||||
}
|
||||
|
||||
// transfer application cache information
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsHttpHandler.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIRedirectHistory.h"
|
||||
#include "nsIUploadChannel.h"
|
||||
#include "nsIUploadChannel2.h"
|
||||
#include "nsIProgressEventSink.h"
|
||||
@ -53,6 +54,7 @@ class HttpBaseChannel : public nsHashPropertyBag
|
||||
, public nsIEncodedChannel
|
||||
, public nsIHttpChannel
|
||||
, public nsIHttpChannelInternal
|
||||
, public nsIRedirectHistory
|
||||
, public nsIUploadChannel
|
||||
, public nsIUploadChannel2
|
||||
, public nsISupportsPriority
|
||||
@ -67,6 +69,7 @@ public:
|
||||
NS_DECL_NSIUPLOADCHANNEL2
|
||||
NS_DECL_NSITRACEABLECHANNEL
|
||||
NS_DECL_NSITIMEDCHANNEL
|
||||
NS_DECL_NSIREDIRECTHISTORY
|
||||
|
||||
HttpBaseChannel();
|
||||
virtual ~HttpBaseChannel();
|
||||
@ -161,6 +164,7 @@ public:
|
||||
NS_IMETHOD TakeAllSecurityMessages(nsCOMArray<nsISecurityConsoleMessage> &aMessages);
|
||||
NS_IMETHOD GetResponseTimeoutEnabled(bool *aEnable);
|
||||
NS_IMETHOD SetResponseTimeoutEnabled(bool aEnable);
|
||||
NS_IMETHOD AddRedirect(nsIPrincipal *aRedirect);
|
||||
|
||||
inline void CleanRedirectCacheChainIfNecessary()
|
||||
{
|
||||
@ -215,7 +219,7 @@ public: /* Necko internal use only... */
|
||||
nsHttpRequestHead::ParsedMethodType method);
|
||||
|
||||
protected:
|
||||
nsCOMArray<nsISecurityConsoleMessage> mSecurityConsoleMessages;
|
||||
nsCOMArray<nsISecurityConsoleMessage> mSecurityConsoleMessages;
|
||||
|
||||
// Handle notifying listener, removing from loadgroup if request failed.
|
||||
void DoNotifyListener();
|
||||
@ -250,6 +254,11 @@ protected:
|
||||
// Checks whether or not aURI and mOriginalURI share the same domain.
|
||||
bool SameOriginWithOriginalUri(nsIURI *aURI);
|
||||
|
||||
// GetPrincipal
|
||||
// Returns the channel principal. If requireAppId is true, then returns
|
||||
// null if the principal has unknown appId.
|
||||
nsIPrincipal *GetPrincipal(bool requireAppId);
|
||||
|
||||
friend class PrivateBrowsingChannel<HttpBaseChannel>;
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
@ -321,6 +330,8 @@ protected:
|
||||
|
||||
nsCOMPtr<nsIURI> mAPIRedirectToURI;
|
||||
nsAutoPtr<nsTArray<nsCString> > mRedirectedCachekeys;
|
||||
// Redirects added by previous channels.
|
||||
nsCOMArray<nsIPrincipal> mRedirects;
|
||||
|
||||
uint32_t mProxyResolveFlags;
|
||||
nsCOMPtr<nsIURI> mProxyURI;
|
||||
@ -351,6 +362,8 @@ protected:
|
||||
// copied from the transaction before we null out mTransaction
|
||||
// so that the timing can still be queried from OnStopRequest
|
||||
TimingStruct mTransactionTimings;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
};
|
||||
|
||||
// Share some code while working around C++'s absurd inability to handle casting
|
||||
|
@ -613,7 +613,7 @@ nsHttpChannel::RetrieveSSLOptions()
|
||||
if (!IsHTTPS() || mPrivateBrowsing)
|
||||
return;
|
||||
|
||||
nsIPrincipal *principal = GetPrincipal();
|
||||
nsIPrincipal *principal = GetPrincipal(true);
|
||||
if (!principal)
|
||||
return;
|
||||
|
||||
@ -1172,7 +1172,7 @@ nsHttpChannel::ProcessSSLInformation()
|
||||
|
||||
int16_t kea = ssl->GetKEAUsed();
|
||||
|
||||
nsIPrincipal *principal = GetPrincipal();
|
||||
nsIPrincipal *principal = GetPrincipal(true);
|
||||
if (!principal)
|
||||
return;
|
||||
|
||||
@ -4235,7 +4235,8 @@ nsHttpChannel::ContinueProcessRedirection(nsresult rv)
|
||||
{
|
||||
AutoRedirectVetoNotifier notifier(this);
|
||||
|
||||
LOG(("ContinueProcessRedirection [rv=%x]\n", rv));
|
||||
LOG(("nsHttpChannel::ContinueProcessRedirection [rv=%x,this=%p]\n", rv,
|
||||
this));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
@ -6131,30 +6132,6 @@ nsHttpChannel::UpdateAggregateCallbacks()
|
||||
mTransaction->SetSecurityCallbacks(callbacks);
|
||||
}
|
||||
|
||||
nsIPrincipal *
|
||||
nsHttpChannel::GetPrincipal()
|
||||
{
|
||||
if (mPrincipal)
|
||||
return mPrincipal;
|
||||
|
||||
nsIScriptSecurityManager *securityManager =
|
||||
nsContentUtils::GetSecurityManager();
|
||||
|
||||
if (!securityManager)
|
||||
return nullptr;
|
||||
|
||||
securityManager->GetChannelPrincipal(this, getter_AddRefs(mPrincipal));
|
||||
if (!mPrincipal)
|
||||
return nullptr;
|
||||
|
||||
// principals with unknown app ids do not work with the permission manager
|
||||
if (mPrincipal->GetUnknownAppId())
|
||||
mPrincipal = nullptr;
|
||||
|
||||
return mPrincipal;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::SetLoadGroup(nsILoadGroup *aLoadGroup)
|
||||
{
|
||||
|
@ -424,8 +424,6 @@ private: // cache telemetry
|
||||
bool mDidReval;
|
||||
|
||||
private:
|
||||
nsIPrincipal *GetPrincipal();
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
bool mForcePending;
|
||||
};
|
||||
|
||||
|
@ -13,12 +13,13 @@ class nsCString;
|
||||
[ptr] native StringArray(nsTArray<nsCString>);
|
||||
[ref] native securityMessagesArray(nsCOMArray<nsISecurityConsoleMessage>);
|
||||
|
||||
interface nsISocketTransport;
|
||||
interface nsIAsyncInputStream;
|
||||
interface nsIAsyncOutputStream;
|
||||
interface nsIURI;
|
||||
interface nsIPrincipal;
|
||||
interface nsIProxyInfo;
|
||||
interface nsISecurityConsoleMessage;
|
||||
interface nsISocketTransport;
|
||||
interface nsIURI;
|
||||
|
||||
/**
|
||||
* The callback interface for nsIHttpChannelInternal::HTTPUpgrade()
|
||||
@ -37,7 +38,7 @@ interface nsIHttpUpgradeListener : nsISupports
|
||||
* using any feature exposed by this interface, be aware that this interface
|
||||
* will change and you will be broken. You have been warned.
|
||||
*/
|
||||
[scriptable, uuid(b733194f-6751-4876-a444-bca4ba3f2fcb)]
|
||||
[scriptable, uuid(a4bf4fc5-b5a9-4098-bd20-409d71bf18e6)]
|
||||
interface nsIHttpChannelInternal : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -192,4 +193,10 @@ interface nsIHttpChannelInternal : nsISupports
|
||||
* May return null when redirectTo() has not been called.
|
||||
*/
|
||||
readonly attribute nsIURI apiRedirectToURI;
|
||||
|
||||
/**
|
||||
* Add a new nsIPrincipal to the redirect chain. This is the only way to
|
||||
* write to nsIRedirectHistory.redirects.
|
||||
*/
|
||||
void addRedirect(in nsIPrincipal aPrincipal);
|
||||
};
|
||||
|
63
netwerk/test/unit/test_redirect_history.js
Normal file
63
netwerk/test/unit/test_redirect_history.js
Normal file
@ -0,0 +1,63 @@
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "URL", function() {
|
||||
return "http://localhost:" + httpServer.identity.primaryPort;
|
||||
});
|
||||
|
||||
var httpServer = null;
|
||||
var randomPath = "/redirect/" + Math.random();
|
||||
var redirects = [];
|
||||
const numRedirects = 10;
|
||||
|
||||
function make_channel(url, callback, ctx) {
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
return ios.newChannel(url, "", null);
|
||||
}
|
||||
|
||||
const responseBody = "response body";
|
||||
|
||||
function contentHandler(request, response)
|
||||
{
|
||||
response.setHeader("Content-Type", "text/plain");
|
||||
response.bodyOutputStream.write(responseBody, responseBody.length);
|
||||
}
|
||||
|
||||
function finish_test(request, buffer)
|
||||
{
|
||||
do_check_eq(buffer, responseBody);
|
||||
let chan = request.QueryInterface(Ci.nsIRedirectHistory);
|
||||
do_check_eq(numRedirects - 1, chan.redirects.length);
|
||||
for (let i = 0; i < numRedirects - 1; ++i) {
|
||||
let principal = chan.redirects.queryElementAt(i, Ci.nsIPrincipal);
|
||||
do_check_eq(URL + redirects[i], principal.URI.spec);
|
||||
}
|
||||
httpServer.stop(do_test_finished);
|
||||
}
|
||||
|
||||
function redirectHandler(index, request, response) {
|
||||
response.setStatusLine(request.httpVersion, 301, "Moved");
|
||||
let path = redirects[index + 1];
|
||||
response.setHeader("Location", URL + path, false);
|
||||
}
|
||||
|
||||
function run_test()
|
||||
{
|
||||
httpServer = new HttpServer();
|
||||
for (let i = 0; i < numRedirects; ++i) {
|
||||
var randomPath = "/redirect/" + Math.random();
|
||||
redirects.push(randomPath);
|
||||
if (i < numRedirects - 1) {
|
||||
httpServer.registerPathHandler(randomPath, redirectHandler.bind(this, i));
|
||||
} else {
|
||||
// The last one doesn't redirect
|
||||
httpServer.registerPathHandler(redirects[numRedirects - 1],
|
||||
contentHandler);
|
||||
}
|
||||
}
|
||||
httpServer.start(-1);
|
||||
|
||||
var chan = make_channel(URL + redirects[0]);
|
||||
chan.asyncOpen(new ChannelListener(finish_test, null), null);
|
||||
do_test_pending();
|
||||
}
|
@ -324,3 +324,4 @@ skip-if = os == "android"
|
||||
[test_signature_extraction.js]
|
||||
run-if = os == "win"
|
||||
[test_udp_multicast.js]
|
||||
[test_redirect_history.js]
|
||||
|
7
netwerk/test/unit_ipc/test_redirect_history_wrap.js
Normal file
7
netwerk/test/unit_ipc/test_redirect_history_wrap.js
Normal file
@ -0,0 +1,7 @@
|
||||
//
|
||||
// Run test script in content process instead of chrome (xpcshell's default)
|
||||
//
|
||||
|
||||
function run_test() {
|
||||
run_test_in_child("../unit/test_redirect_history.js");
|
||||
}
|
@ -32,3 +32,4 @@ skip-if = true
|
||||
[test_simple_wrap.js]
|
||||
[test_xmlhttprequest_wrap.js]
|
||||
[test_XHR_redirects.js]
|
||||
[test_redirect_history_wrap.js]
|
||||
|
Loading…
Reference in New Issue
Block a user