зеркало из https://github.com/mozilla/gecko-dev.git
bug 792438 part 1 - identify css and head-based-js as dedicated network resources r=bz
This commit is contained in:
Родитель
3e1b783f24
Коммит
aef0638b1c
|
@ -24,6 +24,7 @@
|
|||
#include "nsIPrincipal.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIScriptElement.h"
|
||||
#include "nsIDOMHTMLScriptElement.h"
|
||||
#include "nsIDocShell.h"
|
||||
|
@ -257,7 +258,8 @@ nsScriptLoader::ShouldLoadScript(nsIDocument* aDocument,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType)
|
||||
nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
|
||||
bool aScriptFromHead)
|
||||
{
|
||||
nsISupports *context = aRequest->mElement.get()
|
||||
? static_cast<nsISupports *>(aRequest->mElement.get())
|
||||
|
@ -302,6 +304,15 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType)
|
|||
channelPolicy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIScriptElement *script = aRequest->mElement;
|
||||
if (aScriptFromHead &&
|
||||
!(script && (script->GetScriptAsync() || script->GetScriptDeferred()))) {
|
||||
nsCOMPtr<nsIHttpChannelInternal>
|
||||
internalHttpChannel(do_QueryInterface(channel));
|
||||
if (internalHttpChannel)
|
||||
internalHttpChannel->SetLoadAsBlocking(true);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
|
||||
if (httpChannel) {
|
||||
// HTTP content negotation has little value in this context.
|
||||
|
@ -518,7 +529,10 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
|
|||
request->mURI = scriptURI;
|
||||
request->mIsInline = false;
|
||||
request->mLoading = true;
|
||||
rv = StartLoad(request, type);
|
||||
|
||||
// set aScriptFromHead to false so we don't treat non preloaded scripts as
|
||||
// blockers for full page load. See bug 792438.
|
||||
rv = StartLoad(request, type, false);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Asynchronously report the load failure
|
||||
NS_DispatchToCurrentThread(
|
||||
|
@ -1236,7 +1250,8 @@ nsScriptLoader::ParsingComplete(bool aTerminated)
|
|||
void
|
||||
nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
|
||||
const nsAString &aType,
|
||||
const nsAString &aCrossOrigin)
|
||||
const nsAString &aCrossOrigin,
|
||||
bool aScriptFromHead)
|
||||
{
|
||||
// Check to see if scripts has been turned off.
|
||||
if (!mEnabled || !mDocument->IsScriptEnabled()) {
|
||||
|
@ -1249,7 +1264,7 @@ nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
|
|||
request->mURI = aURI;
|
||||
request->mIsInline = false;
|
||||
request->mLoading = true;
|
||||
nsresult rv = StartLoad(request, aType);
|
||||
nsresult rv = StartLoad(request, aType, aScriptFromHead);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -200,10 +200,12 @@ public:
|
|||
* @param aType The type parameter for the script.
|
||||
* @param aCrossOrigin The crossorigin attribute for the script.
|
||||
* Void if not present.
|
||||
* @param aScriptFromHead Whether or not the script was a child of head
|
||||
*/
|
||||
virtual void PreloadURI(nsIURI *aURI, const nsAString &aCharset,
|
||||
const nsAString &aType,
|
||||
const nsAString &aCrossOrigin);
|
||||
const nsAString &aCrossOrigin,
|
||||
bool aScriptFromHead);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -228,7 +230,8 @@ private:
|
|||
/**
|
||||
* Start a load for aRequest's URI.
|
||||
*/
|
||||
nsresult StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType);
|
||||
nsresult StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
|
||||
bool aScriptFromHead);
|
||||
|
||||
/**
|
||||
* Process any pending requests asynchronously (i.e. off an event) if there
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "nsStreamListenerWrapper.h"
|
||||
|
@ -2964,6 +2965,15 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
|
|||
// the channel slow by default for pipeline purposes
|
||||
AddLoadFlags(mChannel, nsIRequest::INHIBIT_PIPELINE);
|
||||
|
||||
nsCOMPtr<nsIHttpChannelInternal>
|
||||
internalHttpChannel(do_QueryInterface(mChannel));
|
||||
if (internalHttpChannel) {
|
||||
// we never let XHR be blocked by head CSS/JS loads to avoid
|
||||
// potential deadlock where server generation of CSS/JS requires
|
||||
// an XHR signal.
|
||||
internalHttpChannel->SetLoadUnblocked(true);
|
||||
}
|
||||
|
||||
if (!IsSystemXHR()) {
|
||||
// Always create a nsCORSListenerProxy here even if it's
|
||||
// a same-origin request right now, since it could be redirected.
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsIAtom.h"
|
||||
|
@ -1502,6 +1503,11 @@ Loader::LoadSheet(SheetLoadData* aLoadData, StyleSheetState aSheetState)
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannelInternal>
|
||||
internalHttpChannel(do_QueryInterface(channel));
|
||||
if (internalHttpChannel)
|
||||
internalHttpChannel->SetLoadAsBlocking(!aLoadData->mWasAlternate);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
|
||||
if (httpChannel) {
|
||||
// send a minimal Accept header for text/css
|
||||
|
|
|
@ -49,6 +49,8 @@ HttpBaseChannel::HttpBaseChannel()
|
|||
, mTracingEnabled(true)
|
||||
, mTimingEnabled(false)
|
||||
, mAllowSpdy(true)
|
||||
, mLoadAsBlocking(false)
|
||||
, mLoadUnblocked(false)
|
||||
, mSuspendCount(0)
|
||||
, mProxyResolveFlags(0)
|
||||
, mContentDispositionHint(UINT32_MAX)
|
||||
|
@ -1354,6 +1356,36 @@ HttpBaseChannel::SetAllowSpdy(bool aAllowSpdy)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::GetLoadAsBlocking(bool *aLoadAsBlocking)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLoadAsBlocking);
|
||||
*aLoadAsBlocking = mLoadAsBlocking;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::SetLoadAsBlocking(bool aLoadAsBlocking)
|
||||
{
|
||||
mLoadAsBlocking = aLoadAsBlocking;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::GetLoadUnblocked(bool *aLoadUnblocked)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLoadUnblocked);
|
||||
*aLoadUnblocked = mLoadUnblocked;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::SetLoadUnblocked(bool aLoadUnblocked)
|
||||
{
|
||||
mLoadUnblocked = aLoadUnblocked;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpBaseChannel::nsISupportsPriority
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -142,6 +142,10 @@ public:
|
|||
NS_IMETHOD GetRemotePort(int32_t* port);
|
||||
NS_IMETHOD GetAllowSpdy(bool *aAllowSpdy);
|
||||
NS_IMETHOD SetAllowSpdy(bool aAllowSpdy);
|
||||
NS_IMETHOD GetLoadAsBlocking(bool *aLoadAsBlocking);
|
||||
NS_IMETHOD SetLoadAsBlocking(bool aLoadAsBlocking);
|
||||
NS_IMETHOD GetLoadUnblocked(bool *aLoadUnblocked);
|
||||
NS_IMETHOD SetLoadUnblocked(bool aLoadUnblocked);
|
||||
|
||||
inline void CleanRedirectCacheChainIfNecessary()
|
||||
{
|
||||
|
@ -274,6 +278,8 @@ protected:
|
|||
// True if timing collection is enabled
|
||||
uint32_t mTimingEnabled : 1;
|
||||
uint32_t mAllowSpdy : 1;
|
||||
uint32_t mLoadAsBlocking : 1;
|
||||
uint32_t mLoadUnblocked : 1;
|
||||
|
||||
// Current suspension depth for this channel object
|
||||
uint32_t mSuspendCount;
|
||||
|
|
|
@ -34,7 +34,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(9363fd96-af59-47e8-bddf-1d5e91acd336)]
|
||||
[scriptable, uuid(74d13d41-85cd-490f-9942-300d0c01c726)]
|
||||
interface nsIHttpChannelInternal : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -156,4 +156,19 @@ interface nsIHttpChannelInternal : nsISupports
|
|||
*/
|
||||
attribute boolean allowSpdy;
|
||||
|
||||
/**
|
||||
* Set (e.g., by the docshell) to indicate whether or not the channel
|
||||
* corresponds to content that should be given a degree of network exclusivity
|
||||
* with respect to other members of its load group.
|
||||
* Examples are js from the HTML head and css which are latency
|
||||
* sensitive and should not compete with images for bandwidth. Default false.
|
||||
*/
|
||||
attribute boolean loadAsBlocking;
|
||||
|
||||
/**
|
||||
* If set, this channel will load in parallel with the rest of the load
|
||||
* group even if a blocking subset of the group would normally be given
|
||||
* exclusivity. Default false.
|
||||
*/
|
||||
attribute boolean loadUnblocked;
|
||||
};
|
||||
|
|
|
@ -2079,6 +2079,12 @@ WebSocketChannel::SetupRequest()
|
|||
nsIRequest::LOAD_BYPASS_CACHE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// we never let websockets be blocked by head CSS/JS loads to avoid
|
||||
// potential deadlock where server generation of CSS/JS requires
|
||||
// an XHR signal.
|
||||
rv = mChannel->SetLoadUnblocked(true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// draft-ietf-hybi-thewebsocketprotocol-07 illustrates Upgrade: websocket
|
||||
// in lower case, so go with that. It is technically case insensitive.
|
||||
rv = mChannel->HTTPUpgrade(NS_LITERAL_CSTRING("websocket"), this);
|
||||
|
|
|
@ -32,7 +32,11 @@ nsHtml5SpeculativeLoad::Perform(nsHtml5TreeOpExecutor* aExecutor)
|
|||
break;
|
||||
case eSpeculativeLoadScript:
|
||||
aExecutor->PreloadScript(mUrl, mCharset, mTypeOrCharsetSource,
|
||||
mCrossOrigin);
|
||||
mCrossOrigin, false);
|
||||
break;
|
||||
case eSpeculativeLoadScriptFromHead:
|
||||
aExecutor->PreloadScript(mUrl, mCharset, mTypeOrCharsetSource,
|
||||
mCrossOrigin, true);
|
||||
break;
|
||||
case eSpeculativeLoadStyle:
|
||||
aExecutor->PreloadStyle(mUrl, mCharset, mCrossOrigin);
|
||||
|
|
|
@ -16,6 +16,7 @@ enum eHtml5SpeculativeLoad {
|
|||
eSpeculativeLoadBase,
|
||||
eSpeculativeLoadImage,
|
||||
eSpeculativeLoadScript,
|
||||
eSpeculativeLoadScriptFromHead,
|
||||
eSpeculativeLoadStyle,
|
||||
eSpeculativeLoadManifest,
|
||||
eSpeculativeLoadSetDocumentCharset
|
||||
|
@ -45,10 +46,12 @@ class nsHtml5SpeculativeLoad {
|
|||
inline void InitScript(const nsAString& aUrl,
|
||||
const nsAString& aCharset,
|
||||
const nsAString& aType,
|
||||
const nsAString& aCrossOrigin) {
|
||||
const nsAString& aCrossOrigin,
|
||||
bool aParserInHead) {
|
||||
NS_PRECONDITION(mOpCode == eSpeculativeLoadUninitialized,
|
||||
"Trying to reinitialize a speculative load!");
|
||||
mOpCode = eSpeculativeLoadScript;
|
||||
mOpCode = aParserInHead ?
|
||||
eSpeculativeLoadScriptFromHead : eSpeculativeLoadScript;
|
||||
mUrl.Assign(aUrl);
|
||||
mCharset.Assign(aCharset);
|
||||
mTypeOrCharsetSource.Assign(aType);
|
||||
|
@ -108,7 +111,7 @@ class nsHtml5SpeculativeLoad {
|
|||
eHtml5SpeculativeLoad mOpCode;
|
||||
nsString mUrl;
|
||||
/**
|
||||
* If mOpCode is eSpeculativeLoadStyle or eSpeculativeLoadScript
|
||||
* If mOpCode is eSpeculativeLoadStyle or eSpeculativeLoadScript[FromHead]
|
||||
* then this is the value of the "charset" attribute. For
|
||||
* eSpeculativeLoadSetDocumentCharset it is the charset that the
|
||||
* document's charset is being set to. Otherwise it's empty.
|
||||
|
@ -122,7 +125,7 @@ class nsHtml5SpeculativeLoad {
|
|||
*/
|
||||
nsString mTypeOrCharsetSource;
|
||||
/**
|
||||
* If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadScript,
|
||||
* If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadScript[FromHead],
|
||||
* this is the value of the "crossorigin" attribute. If the
|
||||
* attribute is not set, this will be a void string.
|
||||
*/
|
||||
|
|
|
@ -93,7 +93,8 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, nsHtml5Htm
|
|||
InitScript(*url,
|
||||
(charset) ? *charset : EmptyString(),
|
||||
(type) ? *type : EmptyString(),
|
||||
(crossOrigin) ? *crossOrigin : NullString());
|
||||
(crossOrigin) ? *crossOrigin : NullString(),
|
||||
mode == NS_HTML5TREE_BUILDER_IN_HEAD);
|
||||
mCurrentHtmlScriptIsAsyncOrDefer =
|
||||
aAttributes->contains(nsHtml5AttributeName::ATTR_ASYNC) ||
|
||||
aAttributes->contains(nsHtml5AttributeName::ATTR_DEFER);
|
||||
|
@ -158,7 +159,8 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName, nsHtml5Htm
|
|||
InitScript(*url,
|
||||
EmptyString(),
|
||||
(type) ? *type : EmptyString(),
|
||||
(crossOrigin) ? *crossOrigin : NullString());
|
||||
(crossOrigin) ? *crossOrigin : NullString(),
|
||||
mode == NS_HTML5TREE_BUILDER_IN_HEAD);
|
||||
}
|
||||
} else if (nsHtml5Atoms::style == aName) {
|
||||
nsHtml5TreeOperation* treeOp = mOpQueue.AppendElement();
|
||||
|
|
|
@ -1043,13 +1043,15 @@ void
|
|||
nsHtml5TreeOpExecutor::PreloadScript(const nsAString& aURL,
|
||||
const nsAString& aCharset,
|
||||
const nsAString& aType,
|
||||
const nsAString& aCrossOrigin)
|
||||
const nsAString& aCrossOrigin,
|
||||
bool aScriptFromHead)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYet(aURL);
|
||||
if (!uri) {
|
||||
return;
|
||||
}
|
||||
mDocument->ScriptLoader()->PreloadURI(uri, aCharset, aType, aCrossOrigin);
|
||||
mDocument->ScriptLoader()->PreloadURI(uri, aCharset, aType, aCrossOrigin,
|
||||
aScriptFromHead);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -393,7 +393,8 @@ class nsHtml5TreeOpExecutor : public nsContentSink,
|
|||
void PreloadScript(const nsAString& aURL,
|
||||
const nsAString& aCharset,
|
||||
const nsAString& aType,
|
||||
const nsAString& aCrossOrigin);
|
||||
const nsAString& aCrossOrigin,
|
||||
bool aScriptFromHead);
|
||||
|
||||
void PreloadStyle(const nsAString& aURL, const nsAString& aCharset,
|
||||
const nsAString& aCrossOrigin);
|
||||
|
|
Загрузка…
Ссылка в новой задаче