Bug 1556489 - P12. Move code into static utility method. r=nika

We will need access to this method in a following change.

Differential Revision: https://phabricator.services.mozilla.com/D40969
This commit is contained in:
Matt Woodrow 2019-08-06 21:58:26 +10:00 коммит произвёл Jean-Yves Avenard
Родитель b43fd91ea2
Коммит 747652aa04
2 изменённых файлов: 362 добавлений и 295 удалений

Просмотреть файл

@ -9761,6 +9761,329 @@ static bool IsConsideredSameOriginForUIR(nsIPrincipal* aTriggeringPrincipal,
return aTriggeringPrincipal->Equals(tmpResultPrincipal);
}
/* static */ bool nsDocShell::CreateChannelForLoadState(
nsDocShellLoadState* aLoadState, LoadInfo* aLoadInfo,
nsIInterfaceRequestor* aCallbacks, nsDocShell* aDocShell,
const nsString* aInitiatorType, nsLoadFlags aLoadFlags, uint32_t aLoadType,
uint32_t aCacheKey, bool aIsActive, bool aIsTopLevelDoc, nsresult& aRv,
nsIChannel** aChannel) {
nsCOMPtr<nsIChannel> channel;
nsAutoString srcdoc;
bool isSrcdoc = aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
if (isSrcdoc) {
srcdoc = aLoadState->SrcdocData();
} else {
srcdoc = VoidString();
}
nsIURI* baseURI = aLoadState->BaseURI();
if (!isSrcdoc) {
aRv = NS_NewChannelInternal(getter_AddRefs(channel), aLoadState->URI(),
aLoadInfo,
nullptr, // PerformanceStorage
nullptr, // loadGroup
aCallbacks, aLoadFlags);
if (NS_FAILED(aRv)) {
if (aRv == NS_ERROR_UNKNOWN_PROTOCOL && aDocShell) {
// This is a uri with a protocol scheme we don't know how
// to handle. Embedders might still be interested in
// handling the load, though, so we fire a notification
// before throwing the load away.
bool abort = false;
nsresult rv = aDocShell->mContentListener->OnStartURIOpen(
aLoadState->URI(), &abort);
if (NS_SUCCEEDED(rv) && abort) {
// Hey, they're handling the load for us! How convenient!
aRv = NS_OK;
return false;
}
}
return false;
}
if (baseURI) {
nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel);
if (vsc) {
aRv = vsc->SetBaseURI(baseURI);
MOZ_ASSERT(NS_SUCCEEDED(aRv));
}
}
} else if (SchemeIsViewSource(aLoadState->URI())) {
nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance();
if (!vsh) {
aRv = NS_ERROR_FAILURE;
return false;
}
aRv = vsh->NewSrcdocChannel(aLoadState->URI(), baseURI, srcdoc, aLoadInfo,
getter_AddRefs(channel));
} else {
aRv = NS_NewInputStreamChannelInternal(
getter_AddRefs(channel), aLoadState->URI(), srcdoc,
NS_LITERAL_CSTRING("text/html"), aLoadInfo, true);
NS_ENSURE_SUCCESS(aRv, false);
nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
MOZ_ASSERT(isc);
isc->SetBaseURI(baseURI);
}
nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp();
if (csp) {
// Navigational requests that are same origin need to be upgraded in case
// upgrade-insecure-requests is present.
bool upgradeInsecureRequests = false;
csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
if (upgradeInsecureRequests) {
// only upgrade if the navigation is same origin
nsCOMPtr<nsIPrincipal> resultPrincipal;
aRv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
channel, getter_AddRefs(resultPrincipal));
NS_ENSURE_SUCCESS(aRv, false);
if (IsConsideredSameOriginForUIR(aLoadState->TriggeringPrincipal(),
resultPrincipal)) {
aLoadInfo->SetUpgradeInsecureRequests();
}
}
// For document loads we store the CSP that potentially needs to
// be inherited by the new document, e.g. in case we are loading
// an opaque origin like a data: URI. The actual inheritance
// check happens within Document::InitCSP().
// Please create an actual copy of the CSP (do not share the same
// reference) otherwise a Meta CSP of an opaque origin will
// incorrectly be propagated to the embedding document.
RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get()));
aLoadInfo->SetCSPToInherit(cspToInherit);
}
nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
do_QueryInterface(channel);
if (appCacheChannel) {
// Any document load should not inherit application cache.
appCacheChannel->SetInheritApplicationCache(false);
// Loads with the correct permissions should check for a matching
// application cache.
if (GeckoProcessType_Default != XRE_GetProcessType()) {
// Permission will be checked in the parent process
appCacheChannel->SetChooseApplicationCache(true);
} else if (aDocShell) {
// TODO: Figure out how to handle this in the parent,
// on behalf of a content process.
nsCOMPtr<nsIScriptSecurityManager> secMan =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
if (secMan) {
nsCOMPtr<nsIPrincipal> principal;
secMan->GetDocShellContentPrincipal(aLoadState->URI(), aDocShell,
getter_AddRefs(principal));
appCacheChannel->SetChooseApplicationCache(
NS_ShouldCheckAppCache(principal));
}
}
}
// hack
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
do_QueryInterface(channel));
nsCOMPtr<nsIURI> referrer;
nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
if (referrerInfo) {
referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
}
if (httpChannelInternal) {
if (aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES)) {
aRv = httpChannelInternal->SetThirdPartyFlags(
nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
MOZ_ASSERT(NS_SUCCEEDED(aRv));
}
if (aLoadState->FirstParty()) {
aRv = httpChannelInternal->SetDocumentURI(aLoadState->URI());
MOZ_ASSERT(NS_SUCCEEDED(aRv));
} else {
aRv = httpChannelInternal->SetDocumentURI(referrer);
MOZ_ASSERT(NS_SUCCEEDED(aRv));
}
aRv = httpChannelInternal->SetRedirectMode(
nsIHttpChannelInternal::REDIRECT_MODE_MANUAL);
MOZ_ASSERT(NS_SUCCEEDED(aRv));
}
nsCOMPtr<nsIURI> rpURI;
aLoadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI));
Maybe<nsCOMPtr<nsIURI>> originalResultPrincipalURI;
aLoadState->GetMaybeResultPrincipalURI(originalResultPrincipalURI);
if (originalResultPrincipalURI &&
(!aLoadState->KeepResultPrincipalURIIfSet() || !rpURI)) {
// Unconditionally override, we want the replay to be equal to what has
// been captured.
aLoadInfo->SetResultPrincipalURI(originalResultPrincipalURI.ref());
}
if (httpChannel) {
if (aLoadState->HeadersStream()) {
aRv = AddHeadersToChannel(aLoadState->HeadersStream(), httpChannel);
}
// Set the referrer explicitly
// Referrer is currenly only set for link clicks here.
if (referrerInfo) {
aRv = httpChannel->SetReferrerInfo(referrerInfo);
MOZ_ASSERT(NS_SUCCEEDED(aRv));
}
}
// Mark the http channel as UrgentStart for top level document loading
// in active tab.
if (aIsActive) {
if (httpChannel && aIsTopLevelDoc) {
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
if (cos) {
cos->AddClassFlags(nsIClassOfService::UrgentStart);
}
}
}
channel.forget(aChannel);
return true;
}
/* static */ nsresult nsDocShell::ConfigureChannel(
nsIChannel* aChannel, nsDocShellLoadState* aLoadState,
const nsString* aInitiatorType, uint32_t aLoadType, uint32_t aCacheKey) {
nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel));
if (props) {
nsCOMPtr<nsIURI> referrer;
nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
if (referrerInfo) {
referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
}
// save true referrer for those who need it (e.g. xpinstall whitelisting)
// Currently only http and ftp channels support this.
props->SetPropertyAsInterface(
NS_LITERAL_STRING("docshell.internalReferrer"), referrer);
}
nsresult rv = NS_OK;
if (aLoadState->OriginalURI()) {
aChannel->SetOriginalURI(aLoadState->OriginalURI());
// The LOAD_REPLACE flag and its handling here will be removed as part
// of bug 1319110. For now preserve its restoration here to not break
// any code expecting it being set specially on redirected channels.
// If the flag has originally been set to change result of
// NS_GetFinalChannelURI it won't have any effect and also won't cause
// any harm.
if (aLoadState->LoadReplace()) {
uint32_t loadFlags;
aChannel->GetLoadFlags(&loadFlags);
NS_ENSURE_SUCCESS(rv, rv);
aChannel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE);
}
} else {
aChannel->SetOriginalURI(aLoadState->URI());
}
const nsACString& typeHint = aLoadState->TypeHint();
if (!typeHint.IsVoid()) {
aChannel->SetContentType(typeHint);
}
const nsAString& fileName = aLoadState->FileName();
if (!fileName.IsVoid()) {
rv = aChannel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT);
NS_ENSURE_SUCCESS(rv, rv);
if (!fileName.IsEmpty()) {
rv = aChannel->SetContentDispositionFilename(fileName);
NS_ENSURE_SUCCESS(rv, rv);
}
}
nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(aChannel));
// figure out if we need to set the post data stream on the channel...
if (aLoadState->PostDataStream()) {
nsCOMPtr<nsIFormPOSTActionChannel> postChannel(do_QueryInterface(aChannel));
if (postChannel) {
// XXX it's a bit of a hack to rewind the postdata stream here but
// it has to be done in case the post data is being reused multiple
// times.
nsCOMPtr<nsISeekableStream> postDataSeekable =
do_QueryInterface(aLoadState->PostDataStream());
if (postDataSeekable) {
rv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
NS_ENSURE_SUCCESS(rv, rv);
}
// we really need to have a content type associated with this stream!!
postChannel->SetUploadStream(aLoadState->PostDataStream(), EmptyCString(),
-1);
}
/* If there is a valid postdata *and* it is a History Load,
* set up the cache key on the channel, to retrieve the
* data *only* from the cache. If it is a normal reload, the
* cache is free to go to the server for updated postdata.
*/
if (cacheChannel && aCacheKey != 0) {
if (aLoadType == LOAD_HISTORY ||
aLoadType == LOAD_RELOAD_CHARSET_CHANGE) {
cacheChannel->SetCacheKey(aCacheKey);
uint32_t loadFlags;
if (NS_SUCCEEDED(aChannel->GetLoadFlags(&loadFlags))) {
aChannel->SetLoadFlags(loadFlags |
nsICachingChannel::LOAD_ONLY_FROM_CACHE);
}
} else if (aLoadType == LOAD_RELOAD_NORMAL) {
cacheChannel->SetCacheKey(aCacheKey);
}
}
} else {
/* If there is no postdata, set the cache key on the channel, and
* do not set the LOAD_ONLY_FROM_CACHE flag, so that the channel
* will be free to get it from net if it is not found in cache.
* New cache may use it creatively on CGI pages with GET
* method and even on those that say "no-cache"
*/
if (aLoadType == LOAD_HISTORY || aLoadType == LOAD_RELOAD_NORMAL ||
aLoadType == LOAD_RELOAD_CHARSET_CHANGE ||
aLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE ||
aLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE) {
if (cacheChannel && aCacheKey != 0) {
cacheChannel->SetCacheKey(aCacheKey);
}
}
}
nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(aChannel);
if (scriptChannel) {
// Allow execution against our context if the principals match
scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
}
if (aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_FIRST_LOAD)) {
nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(aChannel);
if (props) {
props->SetPropertyAsBool(NS_LITERAL_STRING("docshell.newWindowTarget"),
true);
}
}
// TODO: What should we do with this?
nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(aChannel));
if (timedChannel) {
timedChannel->SetTimingEnabled(true);
if (aInitiatorType) {
timedChannel->SetInitiatorType(*aInitiatorType);
}
}
return rv;
}
nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
bool aLoadFromExternal, nsIDocShell** aDocShell,
nsIRequest** aRequest) {
@ -9845,21 +10168,14 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
// open a channel for the url
nsCOMPtr<nsIChannel> channel;
nsAutoString srcdoc;
bool isSrcdoc = aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
if (isSrcdoc) {
srcdoc = aLoadState->SrcdocData();
} else {
srcdoc = VoidString();
}
// If we have a pending channel, use the channel we've already created here.
// We don't need to set up load flags for our channel, as it has already been
// created.
nsCOMPtr<nsIChildChannel> pendingChannel =
aLoadState->GetPendingRedirectedChannel();
if (pendingChannel) {
MOZ_ASSERT(!isSrcdoc, "pending channel for srcdoc load?");
MOZ_ASSERT(!aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC),
"pending channel for srcdoc load?");
channel = do_QueryInterface(pendingChannel);
MOZ_ASSERT(channel, "nsIChildChannel isn't a nsIChannel?");
@ -9954,6 +10270,7 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
bool inheritAttrs = false, inheritPrincipal = false;
if (aLoadState->PrincipalToInherit()) {
bool isSrcdoc = aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_IS_SRCDOC);
inheritAttrs = nsContentUtils::ChannelShouldInheritPrincipal(
aLoadState->PrincipalToInherit(), aLoadState->URI(),
true, // aInheritForAboutBlank
@ -10045,143 +10362,40 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
loadInfo->SetIsFormSubmission(true);
}
nsIURI* baseURI = aLoadState->BaseURI();
if (!isSrcdoc) {
rv = NS_NewChannelInternal(
getter_AddRefs(channel), aLoadState->URI(), loadInfo,
nullptr, // PerformanceStorage
nullptr, // loadGroup
static_cast<nsIInterfaceRequestor*>(this), loadFlags);
/* Get the cache Key from SH */
uint32_t cacheKey = 0;
if (mLSHE) {
cacheKey = mLSHE->GetCacheKey();
} else if (mOSHE) { // for reload cases
cacheKey = mOSHE->GetCacheKey();
}
if (NS_FAILED(rv)) {
if (rv == NS_ERROR_UNKNOWN_PROTOCOL) {
// This is a uri with a protocol scheme we don't know how
// to handle. Embedders might still be interested in
// handling the load, though, so we fire a notification
// before throwing the load away.
bool abort = false;
nsresult rv2 =
mContentListener->OnStartURIOpen(aLoadState->URI(), &abort);
if (NS_SUCCEEDED(rv2) && abort) {
// Hey, they're handling the load for us! How convenient!
return NS_OK;
const nsString* initiatorType = nullptr;
nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
if (IsFrame() && win) {
nsCOMPtr<Element> frameElement = win->GetFrameElementInternal();
if (frameElement) {
initiatorType = &frameElement->LocalName();
}
}
bool isActive =
mIsActive || (mLoadType & (LOAD_CMD_NORMAL | LOAD_CMD_HISTORY));
if (!CreateChannelForLoadState(
aLoadState, loadInfo, this, this, initiatorType, loadFlags, mLoadType,
cacheKey, isActive, isTopLevelDoc, rv, getter_AddRefs(channel))) {
return rv;
}
if (baseURI) {
nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel);
if (vsc) {
rv = vsc->SetBaseURI(baseURI);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
}
} else if (SchemeIsViewSource(aLoadState->URI())) {
nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance();
NS_ENSURE_TRUE(vsh, NS_ERROR_FAILURE);
rv = vsh->NewSrcdocChannel(aLoadState->URI(), baseURI, srcdoc, loadInfo,
getter_AddRefs(channel));
} else {
rv = NS_NewInputStreamChannelInternal(
getter_AddRefs(channel), aLoadState->URI(), srcdoc,
NS_LITERAL_CSTRING("text/html"), loadInfo, true);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
MOZ_ASSERT(isc);
isc->SetBaseURI(baseURI);
}
nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp();
if (csp) {
// Navigational requests that are same origin need to be upgraded in case
// upgrade-insecure-requests is present.
bool upgradeInsecureRequests = false;
csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
if (upgradeInsecureRequests) {
// only upgrade if the navigation is same origin
nsCOMPtr<nsIPrincipal> resultPrincipal;
rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
channel, getter_AddRefs(resultPrincipal));
NS_ENSURE_SUCCESS(rv, rv);
if (IsConsideredSameOriginForUIR(aLoadState->TriggeringPrincipal(),
resultPrincipal)) {
loadInfo->SetUpgradeInsecureRequests();
}
}
// For document loads we store the CSP that potentially needs to
// be inherited by the new document, e.g. in case we are loading
// an opaque origin like a data: URI. The actual inheritance
// check happens within Document::InitCSP().
// Please create an actual copy of the CSP (do not share the same
// reference) otherwise a Meta CSP of an opaque origin will
// incorrectly be propagated to the embedding document.
RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get()));
loadInfo->SetCSPToInherit(cspToInherit);
}
nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
do_QueryInterface(channel);
if (appCacheChannel) {
// Any document load should not inherit application cache.
appCacheChannel->SetInheritApplicationCache(false);
// Loads with the correct permissions should check for a matching
// application cache.
if (GeckoProcessType_Default != XRE_GetProcessType()) {
// Permission will be checked in the parent process
appCacheChannel->SetChooseApplicationCache(true);
} else {
nsCOMPtr<nsIScriptSecurityManager> secMan =
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
if (secMan) {
nsCOMPtr<nsIPrincipal> principal;
secMan->GetDocShellContentPrincipal(aLoadState->URI(), this,
getter_AddRefs(principal));
appCacheChannel->SetChooseApplicationCache(
NS_ShouldCheckAppCache(principal));
}
}
}
// Make sure to give the caller a channel if we managed to create one
// This is important for correct error page/session history interaction
if (aRequest) {
NS_ADDREF(*aRequest = channel);
}
if (aLoadState->OriginalURI()) {
channel->SetOriginalURI(aLoadState->OriginalURI());
// The LOAD_REPLACE flag and its handling here will be removed as part
// of bug 1319110. For now preserve its restoration here to not break
// any code expecting it being set specially on redirected channels.
// If the flag has originally been set to change result of
// NS_GetFinalChannelURI it won't have any effect and also won't cause
// any harm.
if (aLoadState->LoadReplace()) {
uint32_t loadFlags;
channel->GetLoadFlags(&loadFlags);
rv =
ConfigureChannel(channel, aLoadState, initiatorType, mLoadType, cacheKey);
NS_ENSURE_SUCCESS(rv, rv);
channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE);
}
} else {
channel->SetOriginalURI(aLoadState->URI());
}
nsCOMPtr<nsIURI> rpURI;
loadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI));
Maybe<nsCOMPtr<nsIURI>> originalResultPrincipalURI;
aLoadState->GetMaybeResultPrincipalURI(originalResultPrincipalURI);
if (originalResultPrincipalURI &&
(!aLoadState->KeepResultPrincipalURIIfSet() || !rpURI)) {
// Unconditionally override, we want the replay to be equal to what has
// been captured.
loadInfo->SetResultPrincipalURI(originalResultPrincipalURI.ref());
}
const nsACString& typeHint = aLoadState->TypeHint();
if (!typeHint.IsVoid()) {
@ -10191,16 +10405,6 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
mContentTypeHint.Truncate();
}
const nsAString& fileName = aLoadState->FileName();
if (!fileName.IsVoid()) {
rv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT);
NS_ENSURE_SUCCESS(rv, rv);
if (!fileName.IsEmpty()) {
rv = channel->SetContentDispositionFilename(fileName);
NS_ENSURE_SUCCESS(rv, rv);
}
}
if (mLoadType == LOAD_NORMAL_ALLOW_MIXED_CONTENT ||
mLoadType == LOAD_RELOAD_ALLOW_MIXED_CONTENT) {
rv = SetMixedContentChannel(channel);
@ -10221,158 +10425,6 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
}
}
// hack
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
do_QueryInterface(channel));
nsCOMPtr<nsIURI> referrer;
nsIReferrerInfo* referrerInfo = aLoadState->GetReferrerInfo();
if (referrerInfo) {
referrerInfo->GetOriginalReferrer(getter_AddRefs(referrer));
}
if (httpChannelInternal) {
if (aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES)) {
rv = httpChannelInternal->SetThirdPartyFlags(
nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
if (aLoadState->FirstParty()) {
rv = httpChannelInternal->SetDocumentURI(aLoadState->URI());
MOZ_ASSERT(NS_SUCCEEDED(rv));
} else {
rv = httpChannelInternal->SetDocumentURI(referrer);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
rv = httpChannelInternal->SetRedirectMode(
nsIHttpChannelInternal::REDIRECT_MODE_MANUAL);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
Unused << rv; // Keep Coverity happy
nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(channel));
if (props) {
// save true referrer for those who need it (e.g. xpinstall whitelisting)
// Currently only http and ftp channels support this.
props->SetPropertyAsInterface(
NS_LITERAL_STRING("docshell.internalReferrer"), referrer);
}
nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(channel));
/* Get the cache Key from SH */
uint32_t cacheKey = 0;
if (cacheChannel) {
if (mLSHE) {
cacheKey = mLSHE->GetCacheKey();
} else if (mOSHE) { // for reload cases
cacheKey = mOSHE->GetCacheKey();
}
}
// figure out if we need to set the post data stream on the channel...
if (aLoadState->PostDataStream()) {
nsCOMPtr<nsIFormPOSTActionChannel> postChannel(do_QueryInterface(channel));
if (postChannel) {
// XXX it's a bit of a hack to rewind the postdata stream here but
// it has to be done in case the post data is being reused multiple
// times.
nsCOMPtr<nsISeekableStream> postDataSeekable =
do_QueryInterface(aLoadState->PostDataStream());
if (postDataSeekable) {
rv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
NS_ENSURE_SUCCESS(rv, rv);
}
// we really need to have a content type associated with this stream!!
postChannel->SetUploadStream(aLoadState->PostDataStream(), EmptyCString(),
-1);
}
/* If there is a valid postdata *and* it is a History Load,
* set up the cache key on the channel, to retrieve the
* data *only* from the cache. If it is a normal reload, the
* cache is free to go to the server for updated postdata.
*/
if (cacheChannel && cacheKey != 0) {
if (mLoadType == LOAD_HISTORY ||
mLoadType == LOAD_RELOAD_CHARSET_CHANGE) {
cacheChannel->SetCacheKey(cacheKey);
uint32_t loadFlags;
if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))) {
channel->SetLoadFlags(loadFlags |
nsICachingChannel::LOAD_ONLY_FROM_CACHE);
}
} else if (mLoadType == LOAD_RELOAD_NORMAL) {
cacheChannel->SetCacheKey(cacheKey);
}
}
} else {
/* If there is no postdata, set the cache key on the channel, and
* do not set the LOAD_ONLY_FROM_CACHE flag, so that the channel
* will be free to get it from net if it is not found in cache.
* New cache may use it creatively on CGI pages with GET
* method and even on those that say "no-cache"
*/
if (mLoadType == LOAD_HISTORY || mLoadType == LOAD_RELOAD_NORMAL ||
mLoadType == LOAD_RELOAD_CHARSET_CHANGE ||
mLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE ||
mLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE) {
if (cacheChannel && cacheKey != 0) {
cacheChannel->SetCacheKey(cacheKey);
}
}
}
if (httpChannel) {
if (aLoadState->HeadersStream()) {
rv = AddHeadersToChannel(aLoadState->HeadersStream(), httpChannel);
}
// Set the referrer explicitly
// Referrer is currenly only set for link clicks here.
if (referrerInfo) {
rv = httpChannel->SetReferrerInfo(referrerInfo);
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
}
nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel);
if (scriptChannel) {
// Allow execution against our context if the principals match
scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
}
if (aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_FIRST_LOAD)) {
nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(channel);
if (props) {
props->SetPropertyAsBool(NS_LITERAL_STRING("docshell.newWindowTarget"),
true);
}
}
nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(channel));
if (timedChannel) {
timedChannel->SetTimingEnabled(true);
nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
if (IsFrame() && win) {
nsCOMPtr<Element> frameElement = win->GetFrameElementInternal();
if (frameElement) {
timedChannel->SetInitiatorType(frameElement->LocalName());
}
}
}
// Mark the http channel as UrgentStart for top level document loading
// in active tab.
if (mIsActive || (mLoadType & (LOAD_CMD_NORMAL | LOAD_CMD_HISTORY))) {
if (httpChannel && isTopLevelDoc) {
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
if (cos) {
cos->AddClassFlags(nsIClassOfService::UrgentStart);
}
}
}
rv = DoChannelLoad(
channel, uriLoader,
aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER));

Просмотреть файл

@ -71,6 +71,9 @@ class ClientInfo;
class ClientSource;
class EventTarget;
} // namespace dom
namespace net {
class LoadInfo;
} // namespace net
} // namespace mozilla
class nsIContentViewer;
@ -476,6 +479,18 @@ class nsDocShell final : public nsDocLoader,
nsresult CreateContentViewerForActor(
mozilla::dom::WindowGlobalChild* aWindowActor);
static bool CreateChannelForLoadState(
nsDocShellLoadState* aLoadState, mozilla::net::LoadInfo* aLoadInfo,
nsIInterfaceRequestor* aCallbacks, nsDocShell* aDocShell,
const nsString* aInitiatorType, nsLoadFlags aLoadFlags,
uint32_t aLoadType, uint32_t aCacheKey, bool aIsActive,
bool aIsTopLevelDoc, nsresult& rv, nsIChannel** aChannel);
static nsresult ConfigureChannel(nsIChannel* aChannel,
nsDocShellLoadState* aLoadState,
const nsString* aInitiatorType,
uint32_t aLoadType, uint32_t aCacheKey);
private: // member functions
friend class nsDSURIContentListener;
friend class FramingChecker;