import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1048131 - Remove MOZ_CAPTIVEDETECT and enable captive portal detector for all products. r=mcmanus (d2b2980c1)
- Bug 1048131 - Implement CaptivePortalService using nsICaptivePortalDetector r=mcmanus (d62c390d4)
- Bug 1048131 - Make some network events trigger a captive portal recheck r=mcmanus (8c19273f0)
- Bug 1166910 - Gecko changes for adding referrer attribute. r=hsivonen (46676ae77)
- Bug 1166910 - Referrer attribute for img tag. r=ckerschb, r=hsivonen, r=bz (f833f3e6c)
- Bug 1174913 - anchor and area referrer attributes. r=ckerschb, r=bz (f99a956be) (backend parts only)
- missing bits of Bug 1210302 - Part 1: Rename nsINetUtil.parseContentType() to parseResponseContentType(); r=mcmanus (eb8fba336)
- Bug 1210302 - Part 2: Rename NS_ParseContentType to NS_ParseResponseContentType; r=mcmanus,sicking (74f4cd98d)
- remaining bits of Bug 1210302 - Part 3: Add a NS_ParseRequestContentType API; r=mcmanus,sicking (56477b434)
- pointer style (ca5142301)
- Bug 1172109 - Name some anonymous structs to help out the analysis, r=terrence (775d17318)
- Bug 1173042 - Remove unused GCChunkSet and chunk hashing functions; r=ehoogeveen (357e0887d)
- Bug 1177778 - Allow HeapPtr destruction while shutting down the GC r=terrence (793654cb2)
- Bug 1181306 - Skip compacting phase when finishing an incremental GC non-incrementally r=terrence (7547c11ad)
- Bug 1162961 - Fix logspam in mochitest-dt by passing the URL along in network progress events;r=past (3b4c9048f)
- Bug 1149235 part 1. Move nsScriptLoadRequest into nsScriptLoader.h. r=sicking (df56a3e9d)
- Bug 1149235 part 2. Switch to using linked lists for nsScriptLoadRequest. r=sicking (7a0536b53)
- Bug 1149235 part 3. Store async requests in the scriptloader in two lists, so we don't have to grovel about looking for loaded ones. r=sicking (db45689c6)
- Bug 1154598. Keep better track of our script requests. r=smaug (a2232a237)
- Bug 1157995 - Tell the cycle collector about Navigator::mMediaDevices. r=smaug (9a9147bdf)
- Bug 1181619. Make sure we've entered a microtask before we call nsJSUtils::EvaluateString, and put those microtasks outside the relevant AutoEntryScripts so we report any possible exceptions before doing the microtask checkpoint. r=bholley (851e371ac)
This commit is contained in:
2021-06-02 10:13:46 +08:00
parent 0285c0cb3b
commit 7254e4308f
65 changed files with 1551 additions and 571 deletions
+122 -108
View File
@@ -51,7 +51,6 @@
#include "ImportManager.h"
#include "mozilla/dom/EncodingUtils.h"
#include "mozilla/CORSMode.h"
#include "mozilla/Attributes.h"
#include "mozilla/unused.h"
@@ -60,70 +59,41 @@ static PRLogModuleInfo* gCspPRLog;
using namespace mozilla;
using namespace mozilla::dom;
//////////////////////////////////////////////////////////////
// Per-request data structure
//////////////////////////////////////////////////////////////
class nsScriptLoadRequest final : public nsISupports {
~nsScriptLoadRequest()
{
js_free(mScriptTextBuf);
}
public:
nsScriptLoadRequest(nsIScriptElement* aElement,
uint32_t aVersion,
CORSMode aCORSMode)
: mElement(aElement),
mLoading(true),
mIsInline(true),
mHasSourceMapURL(false),
mScriptTextBuf(nullptr),
mScriptTextLength(0),
mJSVersion(aVersion),
mLineNo(1),
mCORSMode(aCORSMode),
mReferrerPolicy(mozilla::net::RP_Default)
{
}
NS_DECL_THREADSAFE_ISUPPORTS
void FireScriptAvailable(nsresult aResult)
{
mElement->ScriptAvailable(aResult, mElement, mIsInline, mURI, mLineNo);
}
void FireScriptEvaluated(nsresult aResult)
{
mElement->ScriptEvaluated(aResult, mElement, mIsInline);
}
bool IsPreload()
{
return mElement == nullptr;
}
nsCOMPtr<nsIScriptElement> mElement;
bool mLoading; // Are we still waiting for a load to complete?
bool mIsInline; // Is the script inline or loaded?
bool mHasSourceMapURL; // Does the HTTP header have a source map url?
nsString mSourceMapURL; // Holds source map url for loaded scripts
char16_t* mScriptTextBuf; // Holds script text for non-inline scripts. Don't
size_t mScriptTextLength; // use nsString so we can give ownership to jsapi.
uint32_t mJSVersion;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIPrincipal> mOriginPrincipal;
nsAutoCString mURL; // Keep the URI's filename alive during off thread parsing.
int32_t mLineNo;
const CORSMode mCORSMode;
mozilla::net::ReferrerPolicy mReferrerPolicy;
};
// The nsScriptLoadRequest is passed as the context to necko, and thus
// it needs to be threadsafe. Necko won't do anything with this
// context, but it will AddRef and Release it on other threads.
NS_IMPL_ISUPPORTS0(nsScriptLoadRequest)
nsScriptLoadRequestList::~nsScriptLoadRequestList()
{
Clear();
}
void
nsScriptLoadRequestList::Clear()
{
while (!isEmpty()) {
nsRefPtr<nsScriptLoadRequest> first = StealFirst();
first->Cancel();
// And just let it go out of scope and die.
}
}
#ifdef DEBUG
bool
nsScriptLoadRequestList::Contains(nsScriptLoadRequest* aElem)
{
for (nsScriptLoadRequest* req = getFirst();
req; req = req->getNext()) {
if (req == aElem) {
return true;
}
}
return false;
}
#endif // DEBUG
//////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////
@@ -149,20 +119,30 @@ nsScriptLoader::~nsScriptLoader()
mParserBlockingRequest->FireScriptAvailable(NS_ERROR_ABORT);
}
for (uint32_t i = 0; i < mXSLTRequests.Length(); i++) {
mXSLTRequests[i]->FireScriptAvailable(NS_ERROR_ABORT);
for (nsScriptLoadRequest* req = mXSLTRequests.getFirst(); req;
req = req->getNext()) {
req->FireScriptAvailable(NS_ERROR_ABORT);
}
for (uint32_t i = 0; i < mDeferRequests.Length(); i++) {
mDeferRequests[i]->FireScriptAvailable(NS_ERROR_ABORT);
for (nsScriptLoadRequest* req = mDeferRequests.getFirst(); req;
req = req->getNext()) {
req->FireScriptAvailable(NS_ERROR_ABORT);
}
for (uint32_t i = 0; i < mAsyncRequests.Length(); i++) {
mAsyncRequests[i]->FireScriptAvailable(NS_ERROR_ABORT);
for (nsScriptLoadRequest* req = mLoadingAsyncRequests.getFirst(); req;
req = req->getNext()) {
req->FireScriptAvailable(NS_ERROR_ABORT);
}
for (uint32_t i = 0; i < mNonAsyncExternalScriptInsertedRequests.Length(); i++) {
mNonAsyncExternalScriptInsertedRequests[i]->FireScriptAvailable(NS_ERROR_ABORT);
for (nsScriptLoadRequest* req = mLoadedAsyncRequests.getFirst(); req;
req = req->getNext()) {
req->FireScriptAvailable(NS_ERROR_ABORT);
}
for(nsScriptLoadRequest* req = mNonAsyncExternalScriptInsertedRequests.getFirst();
req;
req = req->getNext()) {
req->FireScriptAvailable(NS_ERROR_ABORT);
}
// Unblock the kids, in case any of them moved to a different document
@@ -667,11 +647,14 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
request->mJSVersion = version;
if (aElement->GetScriptAsync()) {
mAsyncRequests.AppendElement(request);
request->mIsAsync = true;
if (!request->mLoading) {
mLoadedAsyncRequests.AppendElement(request);
// The script is available already. Run it ASAP when the event
// loop gets a chance to spin.
ProcessPendingRequestsAsync();
} else {
mLoadingAsyncRequests.AppendElement(request);
}
return false;
}
@@ -679,6 +662,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// Violate the HTML5 spec in order to make LABjs and the "order" plug-in
// for RequireJS work with their Gecko-sniffed code path. See
// http://lists.w3.org/Archives/Public/public-html/2010Oct/0088.html
request->mIsNonAsyncScriptInserted = true;
mNonAsyncExternalScriptInsertedRequests.AppendElement(request);
if (!request->mLoading) {
// The script is available already. Run it ASAP when the event
@@ -707,6 +691,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// Need to maintain order for XSLT-inserted scripts
NS_ASSERTION(!mParserBlockingRequest,
"Parser-blocking scripts and XSLT scripts in the same doc!");
request->mIsXSLT = true;
mXSLTRequests.AppendElement(request);
if (!request->mLoading) {
// The script is available already. Run it ASAP when the event
@@ -727,7 +712,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// Web page.
NS_ASSERTION(!mParserBlockingRequest,
"There can be only one parser-blocking script at a time");
NS_ASSERTION(mXSLTRequests.IsEmpty(),
NS_ASSERTION(mXSLTRequests.isEmpty(),
"Parser-blocking scripts and XSLT scripts in the same doc!");
mParserBlockingRequest = request;
ProcessPendingRequestsAsync();
@@ -737,7 +722,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// The script will be run when it loads or the style sheet loads.
NS_ASSERTION(!mParserBlockingRequest,
"There can be only one parser-blocking script at a time");
NS_ASSERTION(mXSLTRequests.IsEmpty(),
NS_ASSERTION(mXSLTRequests.isEmpty(),
"Parser-blocking scripts and XSLT scripts in the same doc!");
mParserBlockingRequest = request;
return true;
@@ -763,7 +748,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
request->mLineNo = aElement->GetScriptLineNumber();
if (aElement->GetParserCreated() == FROM_PARSER_XSLT &&
(!ReadyToExecuteScripts() || !mXSLTRequests.IsEmpty())) {
(!ReadyToExecuteScripts() || !mXSLTRequests.isEmpty())) {
// Need to maintain order for XSLT-inserted scripts
NS_ASSERTION(!mParserBlockingRequest,
"Parser-blocking scripts and XSLT scripts in the same doc!");
@@ -782,7 +767,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
NS_ASSERTION(!mParserBlockingRequest,
"There can be only one parser-blocking script at a time");
mParserBlockingRequest = request;
NS_ASSERTION(mXSLTRequests.IsEmpty(),
NS_ASSERTION(mXSLTRequests.isEmpty(),
"Parser-blocking scripts and XSLT scripts in the same doc!");
return true;
}
@@ -1148,6 +1133,7 @@ nsScriptLoader::EvaluateScript(nsScriptLoadRequest* aRequest,
// New script entry point required, due to the "Create a script" sub-step of
// http://www.whatwg.org/specs/web-apps/current-work/#execute-the-script-block
nsAutoMicroTask mt;
AutoEntryScript entryScript(globalObject, "<script> element", true,
context->GetNativeContext());
entryScript.TakeOwnershipOfErrorReporting();
@@ -1207,39 +1193,30 @@ nsScriptLoader::ProcessPendingRequests()
}
while (ReadyToExecuteScripts() &&
!mXSLTRequests.IsEmpty() &&
!mXSLTRequests[0]->mLoading) {
request.swap(mXSLTRequests[0]);
mXSLTRequests.RemoveElementAt(0);
!mXSLTRequests.isEmpty() &&
!mXSLTRequests.getFirst()->mLoading) {
request = mXSLTRequests.StealFirst();
ProcessRequest(request);
}
uint32_t i = 0;
while (mEnabled && i < mAsyncRequests.Length()) {
if (!mAsyncRequests[i]->mLoading) {
request.swap(mAsyncRequests[i]);
mAsyncRequests.RemoveElementAt(i);
ProcessRequest(request);
continue;
}
++i;
while (mEnabled && !mLoadedAsyncRequests.isEmpty()) {
request = mLoadedAsyncRequests.StealFirst();
ProcessRequest(request);
}
while (mEnabled && !mNonAsyncExternalScriptInsertedRequests.IsEmpty() &&
!mNonAsyncExternalScriptInsertedRequests[0]->mLoading) {
while (mEnabled && !mNonAsyncExternalScriptInsertedRequests.isEmpty() &&
!mNonAsyncExternalScriptInsertedRequests.getFirst()->mLoading) {
// Violate the HTML5 spec and execute these in the insertion order in
// order to make LABjs and the "order" plug-in for RequireJS work with
// their Gecko-sniffed code path. See
// http://lists.w3.org/Archives/Public/public-html/2010Oct/0088.html
request.swap(mNonAsyncExternalScriptInsertedRequests[0]);
mNonAsyncExternalScriptInsertedRequests.RemoveElementAt(0);
request = mNonAsyncExternalScriptInsertedRequests.StealFirst();
ProcessRequest(request);
}
if (mDocumentParsingDone && mXSLTRequests.IsEmpty()) {
while (!mDeferRequests.IsEmpty() && !mDeferRequests[0]->mLoading) {
request.swap(mDeferRequests[0]);
mDeferRequests.RemoveElementAt(0);
if (mDocumentParsingDone && mXSLTRequests.isEmpty()) {
while (!mDeferRequests.isEmpty() && !mDeferRequests.getFirst()->mLoading) {
request = mDeferRequests.StealFirst();
ProcessRequest(request);
}
}
@@ -1251,9 +1228,10 @@ nsScriptLoader::ProcessPendingRequests()
}
if (mDocumentParsingDone && mDocument &&
!mParserBlockingRequest && mAsyncRequests.IsEmpty() &&
mNonAsyncExternalScriptInsertedRequests.IsEmpty() &&
mXSLTRequests.IsEmpty() && mDeferRequests.IsEmpty()) {
!mParserBlockingRequest && mLoadingAsyncRequests.isEmpty() &&
mLoadedAsyncRequests.isEmpty() &&
mNonAsyncExternalScriptInsertedRequests.isEmpty() &&
mXSLTRequests.isEmpty() && mDeferRequests.isEmpty()) {
if (MaybeRemovedDeferRequests()) {
return ProcessPendingRequests();
}
@@ -1459,11 +1437,27 @@ nsScriptLoader::OnStreamComplete(nsIStreamLoader* aLoader,
mDocument->AddBlockedTrackingNode(cont);
}
if (mDeferRequests.RemoveElement(request) ||
mAsyncRequests.RemoveElement(request) ||
mNonAsyncExternalScriptInsertedRequests.RemoveElement(request) ||
mXSLTRequests.RemoveElement(request)) {
FireScriptAvailable(rv, request);
if (request->mIsDefer) {
if (request->isInList()) {
nsRefPtr<nsScriptLoadRequest> req = mDeferRequests.Steal(request);
FireScriptAvailable(rv, req);
}
} else if (request->mIsAsync) {
if (request->isInList()) {
nsRefPtr<nsScriptLoadRequest> req = mLoadingAsyncRequests.Steal(request);
FireScriptAvailable(rv, req);
}
} else if (request->mIsNonAsyncScriptInserted) {
if (request->isInList()) {
nsRefPtr<nsScriptLoadRequest> req =
mNonAsyncExternalScriptInsertedRequests.Steal(request);
FireScriptAvailable(rv, req);
}
} else if (request->mIsXSLT) {
if (request->isInList()) {
nsRefPtr<nsScriptLoadRequest> req = mXSLTRequests.Steal(request);
FireScriptAvailable(rv, req);
}
} else if (mParserBlockingRequest == request) {
mParserBlockingRequest = nullptr;
UnblockParser(request);
@@ -1507,6 +1501,10 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
return aStatus;
}
if (aRequest->IsCanceled()) {
return NS_BINDING_ABORTED;
}
// If we don't have a document, then we need to abort further
// evaluation.
if (!mDocument) {
@@ -1570,7 +1568,7 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
// so if you see this assertion it is likely something else that is
// wrong, especially if you see it more than once.
NS_ASSERTION(mDeferRequests.Contains(aRequest) ||
mAsyncRequests.Contains(aRequest) ||
mLoadingAsyncRequests.Contains(aRequest) ||
mNonAsyncExternalScriptInsertedRequests.Contains(aRequest) ||
mXSLTRequests.Contains(aRequest) ||
mPreloads.Contains(aRequest, PreloadRequestComparator()) ||
@@ -1580,6 +1578,17 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
// Mark this as loaded
aRequest->mLoading = false;
// And if it's async, move it to the loaded list. aRequest->mIsAsync really
// _should_ be in a list, but the consequences if it's not are bad enough we
// want to avoid trying to move it if it's not.
if (aRequest->mIsAsync) {
MOZ_ASSERT(aRequest->isInList());
if (aRequest->isInList()) {
nsRefPtr<nsScriptLoadRequest> req = mLoadingAsyncRequests.Steal(aRequest);
mLoadedAsyncRequests.AppendElement(req);
}
}
return NS_OK;
}
@@ -1594,10 +1603,14 @@ nsScriptLoader::ParsingComplete(bool aTerminated)
mDeferEnabled = false;
if (aTerminated) {
mDeferRequests.Clear();
mAsyncRequests.Clear();
mLoadingAsyncRequests.Clear();
mLoadedAsyncRequests.Clear();
mNonAsyncExternalScriptInsertedRequests.Clear();
mXSLTRequests.Clear();
mParserBlockingRequest = nullptr;
if (mParserBlockingRequest) {
mParserBlockingRequest->Cancel();
mParserBlockingRequest = nullptr;
}
}
// Have to call this even if aTerminated so we'll correctly unblock
@@ -1638,9 +1651,10 @@ nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
void
nsScriptLoader::AddDeferRequest(nsScriptLoadRequest* aRequest)
{
aRequest->mIsDefer = true;
mDeferRequests.AppendElement(aRequest);
if (mDeferEnabled && mDeferRequests.Length() == 1 && mDocument &&
!mBlockingDOMContentLoaded) {
if (mDeferEnabled && aRequest == mDeferRequests.getFirst() &&
mDocument && !mBlockingDOMContentLoaded) {
MOZ_ASSERT(mDocument->GetReadyStateEnum() == nsIDocument::READYSTATE_LOADING);
mBlockingDOMContentLoaded = true;
mDocument->BlockDOMContentLoaded();
@@ -1650,7 +1664,7 @@ nsScriptLoader::AddDeferRequest(nsScriptLoadRequest* aRequest)
bool
nsScriptLoader::MaybeRemovedDeferRequests()
{
if (mDeferRequests.Length() == 0 && mDocument &&
if (mDeferRequests.isEmpty() && mDocument &&
mBlockingDOMContentLoaded) {
mBlockingDOMContentLoaded = false;
mDocument->UnblockDOMContentLoaded();