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

- Bug 1154563 - Drop the unused argument of WorkerPrivate::Close(); r=baku (366f353f9f)
- Bug 1178721 - Implement SuspendWorkersForWindow;r=khuey (a49bc9a306)
- Bug 1207490 - Part 6: Remove use of expression closure from browser/devtools/. r=vporof (1c4d153319)
- Bug 1198982: Don't fail the SW load for an importScripts failure. r=bkelly (948f5dca94)
- Bug 1160890 - Part 1: Remove unneeded code from ImportScripts(). r=smaug (e31f7c82eb)
- Bug 1160890 - Part 2: ImportScripts() should return muted errors with 3rd party scripts. r=smaug (347e54a605)
- Bug 1188141: Make Worker error events not bubble. r=baku (509fd46933)
- Bug 1160890, r=smaug (0ce3ee09d6)
- Bug 1208687: Only discard events from the outermost queue. r=ehsan (bce722c16b)
- Bug 949376 - MessageEvent::initMessageEvent, r=smaug (8878e51c91)
- Bug 1214772 - Part 2: Make FetchEvent inherit from ExtendableEvent; r=bzbarsky (edff91f7fb)
- Bug 1218131 - Mark FetchEvent.request as SameObject; r=bzbarsky (1f79b94838)
- Bug 1188545 - Add tests for service workers' lifetime management. r=nsm (9bac3b9f2d)
- Bug 1218135 - Remove FetchEvent.client; r=bzbarsky (e95e4e5326)
- Bug 1218151 - Make FetchEventInit.isReload default to false; r=bzbarsky (795d597a3b)
- Bug 1218621 - Keep the service worker alive while the promise passed to FetchEvent.respondWith() settles; r=catalinb (653633c136)
- Bug 1212636 - Add a better error message for the content corrupcted error caused by the Promise being passed to FetchEvent.respondWith; r=bkelly (d6ebabc2f2)
- Bug 1215140 P4 Make service worker respondWith() use channel ConsoleReportCollector. r=bz (0e07f364d4)
- Bug 1218499 - Make FetchEvent.request nullable; r=bzbarsky (850630ea6d)
- Bug 1179397 - Disallow FetchEvent.respondWith() when the dispatch flag is unset; r=jdm (2e57abf1c6)
- Bug 1215140 P5 Report the line number where respondWith() was called. r=bz (484e385ce3)
- Bug 1161239 - Emit a warning if the respondWith handler is resolved with a non-Object value; r=baku (cf2779f827)
- Bug 1181054 - Part 1: Move FormFillIterator and FormDataParser to FetchUtil.cpp; r=bkelly (9f62174f72)
- Bug 1181054 - Part 2: Refactor the code to extract an HTTP header from a buffer from FormDataParser; r=bkelly (7f57f76ce1)
- Bug 1181054 - Part 3: Correctly handle upload channels that have embedded body headers when dispatching a FetchEvent; r=bkelly (ebbfac4419)
-  ug 1181054 - Part 4: Make fetch-event.https.html pass; r=bkelly (b2d88a3f5b)
- Bug 1215140 P6 Update service worker interception error strings to include detailed parameters. r=bz (7918278f09)
- Bug 1219852 P1 Extract common JS values for rejected respondWith() promises. r=bz (12a6beed6c)
- Bug 1219852 P2 Report non-response values passed to FetchEvent.respondWith(). r=bz (69fdad9d5f)
- Bug 1207068 - Implement ExtendableMessageEvent interface. r=baku (29fd7c1c59)
- Bug 1224061: Make Event::InitEvent infallible. r=smaug Bug 1224061 followup to fix bustage. r=me on a CLOSED TREE IGNORE IDL (b4fc91b14b)
- Bug 1205109 - Make pushsubscriptionchange extendable. r=mt (abb45ac864)
- Bug 1207491 - Part 8: Remove use of expression closure from browser/omponents/nsBrowserContentHandler.js. r=Gijs (98dcb2cbee)
- Bug 1182571: Followup bustage fix from merge fail. CLOSED TREE (5062c88996)
- Bug 1213646: Allow URI_IS_UI_RESOURCE and safe about: URIs when SEC_ALLOW_CHROME is set. r=bz (6ca4e2322f)
- Bug 1191645 - Use channel->asycnOpen2 in dom/base/nsSyncLoadService.cpp. r=sicking (3fbd471f6b)
- Bug 1194526 - Use channel->asycnOpen2 in dom/base/nsScriptLoader.cpp (r=sicking) (7207efa45b)
- Bug 1084009 - Part 1/3 - Parse sync scripts off the main thread. r=smaug (72f4d5c749)
- Bug 1084009 - Part 2/3 - Only parse scripts off-main-thread on multicore systems. r=luke (ffb7e2270e)
- Bug 1209193 - Cache PR_GetNumberOfProcessors when checking to do off-main-thread script compilation. r=luke (c514373ad7)
- Bug 663570 - MetaCSP Part 7: CSP preload validation (r=bz) (5398116f85)
- Bug 1207863 - Fix ScopeIter iterating a strict eval frame that errored out before its CallObject was allocated. (r=jorendorff) (ae38882b7c)
- Bug 1223006 - Fix some typo in spidermonkey's comments. r=nbp (7d49536a0f)
- Bug 1223490 - Use stable hashing for InnerViewTable; r=jonco (12b4329982)
This commit is contained in:
2022-11-30 11:46:18 +08:00
parent 4f15bc133e
commit fb9b106168
162 changed files with 2859 additions and 1208 deletions
@@ -707,7 +707,7 @@ nsDefaultCommandLineHandler.prototype = {
}
}
var URLlist = urilist.filter(shouldLoadURI).map(function (u) u.spec);
var URLlist = urilist.filter(shouldLoadURI).map(u => u.spec);
if (URLlist.length) {
openWindow(null, gBrowserContentHandler.chromeURL, "_blank",
"chrome,dialog=no,all" + gBrowserContentHandler.getFeatures(cmdLine),
+2
View File
@@ -4991,6 +4991,7 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
case NS_ERROR_CLIENT_REQUEST_OPAQUE_INTERCEPTION:
case NS_ERROR_BAD_OPAQUE_REDIRECT_INTERCEPTION:
case NS_ERROR_INTERCEPTION_CANCELED:
case NS_ERROR_REJECTED_RESPONSE_INTERCEPTION:
// ServiceWorker intercepted request, but something went wrong.
nsContentUtils::MaybeReportInterceptionErrorToConsole(GetDocument(),
aError);
@@ -7683,6 +7684,7 @@ nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
aStatus == NS_ERROR_INTERCEPTED_USED_RESPONSE ||
aStatus == NS_ERROR_CLIENT_REQUEST_OPAQUE_INTERCEPTION ||
aStatus == NS_ERROR_INTERCEPTION_CANCELED ||
aStatus == NS_ERROR_REJECTED_RESPONSE_INTERCEPTION ||
NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY) {
// Errors to be shown for any frame
DisplayLoadError(aStatus, url, nullptr, aChannel);
+1 -5
View File
@@ -193,11 +193,7 @@ DOMRequest::FireEvent(const nsAString& aType, bool aBubble, bool aCancelable)
}
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
nsresult rv = event->InitEvent(aType, aBubble, aCancelable);
if (NS_FAILED(rv)) {
return;
}
event->InitEvent(aType, aBubble, aCancelable);
event->SetTrusted(true);
bool dummy;
+3 -18
View File
@@ -757,12 +757,7 @@ EventSource::AnnounceConnection()
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
// it doesn't bubble, and it isn't cancelable
rv = event->InitEvent(NS_LITERAL_STRING("open"), false, false);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to init the open event!!!");
return;
}
event->InitEvent(NS_LITERAL_STRING("open"), false, false);
event->SetTrusted(true);
rv = DispatchDOMEvent(nullptr, event, nullptr, nullptr);
@@ -813,12 +808,7 @@ EventSource::ReestablishConnection()
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
// it doesn't bubble, and it isn't cancelable
rv = event->InitEvent(NS_LITERAL_STRING("error"), false, false);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to init the error event!!!");
return;
}
event->InitEvent(NS_LITERAL_STRING("error"), false, false);
event->SetTrusted(true);
rv = DispatchDOMEvent(nullptr, event, nullptr, nullptr);
@@ -964,12 +954,7 @@ EventSource::FailConnection()
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
// it doesn't bubble, and it isn't cancelable
rv = event->InitEvent(NS_LITERAL_STRING("error"), false, false);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to init the error event!!!");
return;
}
event->InitEvent(NS_LITERAL_STRING("error"), false, false);
event->SetTrusted(true);
rv = DispatchDOMEvent(nullptr, event, nullptr, nullptr);
+1 -3
View File
@@ -1809,9 +1809,7 @@ WebSocket::CreateAndDispatchSimpleEvent(const nsAString& aName)
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
// it doesn't bubble, and it isn't cancelable
rv = event->InitEvent(aName, false, false);
NS_ENSURE_SUCCESS(rv, rv);
event->InitEvent(aName, false, false);
event->SetTrusted(true);
return DispatchDOMEvent(nullptr, event, nullptr, nullptr);
+3 -3
View File
@@ -3510,6 +3510,8 @@ nsContentUtils::MaybeReportInterceptionErrorToConsole(nsIDocument* aDocument,
messageName = "BadOpaqueRedirectInterception";
} else if (aError == NS_ERROR_INTERCEPTION_CANCELED) {
messageName = "InterceptionCanceled";
} else if (aError == NS_ERROR_REJECTED_RESPONSE_INTERCEPTION) {
messageName = "InterceptionRejectedResponse";
}
if (messageName) {
@@ -3799,9 +3801,7 @@ nsresult GetEventAndTarget(nsIDocument* aDoc, nsISupports* aTarget,
domDoc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
NS_ENSURE_SUCCESS(rv, rv);
rv = event->InitEvent(aEventName, aCanBubble, aCancelable);
NS_ENSURE_SUCCESS(rv, rv);
event->InitEvent(aEventName, aCanBubble, aCancelable);
event->SetTrusted(aTrusted);
rv = event->SetTarget(target);
+1 -3
View File
@@ -456,9 +456,7 @@ nsDOMDataChannel::OnSimpleEvent(nsISupports* aContext, const nsAString& aName)
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
rv = event->InitEvent(aName, false, false);
NS_ENSURE_SUCCESS(rv,rv);
event->InitEvent(aName, false, false);
event->SetTrusted(true);
return DispatchDOMEvent(nullptr, event, nullptr, nullptr);
+2 -2
View File
@@ -2198,7 +2198,7 @@ nsDOMWindowUtils::SuspendTimeouts()
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
window->SuspendTimeouts();
window->SuspendTimeouts(1, true, false);
return NS_OK;
}
@@ -2211,7 +2211,7 @@ nsDOMWindowUtils::ResumeTimeouts()
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
window->ResumeTimeouts();
window->ResumeTimeouts(true, false);
return NS_OK;
}
+24 -17
View File
@@ -11613,13 +11613,11 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
}
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
nsresult rv = event->InitEvent(
event->InitEvent(
!nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC)
? NETWORK_UPLOAD_EVENT_NAME
: NETWORK_DOWNLOAD_EVENT_NAME,
false, false);
NS_ENSURE_SUCCESS(rv, rv);
event->SetTrusted(true);
bool dummy;
@@ -11649,9 +11647,7 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
}
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
nsresult rv = event->InitEvent(NS_LITERAL_STRING("languagechange"), false, false);
NS_ENSURE_SUCCESS(rv, rv);
event->InitEvent(NS_LITERAL_STRING("languagechange"), false, false);
event->SetTrusted(true);
bool dummy;
@@ -13054,9 +13050,11 @@ nsGlobalWindow::RestoreWindowState(nsISupports *aState)
void
nsGlobalWindow::SuspendTimeouts(uint32_t aIncrease,
bool aFreezeChildren)
bool aFreezeChildren,
bool aFreezeWorkers)
{
FORWARD_TO_INNER_VOID(SuspendTimeouts, (aIncrease, aFreezeChildren));
FORWARD_TO_INNER_VOID(SuspendTimeouts,
(aIncrease, aFreezeChildren, aFreezeWorkers));
bool suspended = (mTimeoutsSuspendDepth != 0);
mTimeoutsSuspendDepth += aIncrease;
@@ -13069,8 +13067,12 @@ nsGlobalWindow::SuspendTimeouts(uint32_t aIncrease,
}
DisableGamepadUpdates();
// Freeze all of the workers for this window.
mozilla::dom::workers::FreezeWorkersForWindow(this);
// Freeze or suspend all of the workers for this window.
if (aFreezeWorkers) {
mozilla::dom::workers::FreezeWorkersForWindow(this);
} else {
mozilla::dom::workers::SuspendWorkersForWindow(this);
}
TimeStamp now = TimeStamp::Now();
for (nsTimeout *t = mTimeouts.getFirst(); t; t = t->getNext()) {
@@ -13126,7 +13128,7 @@ nsGlobalWindow::SuspendTimeouts(uint32_t aIncrease,
continue;
}
win->SuspendTimeouts(aIncrease, aFreezeChildren);
win->SuspendTimeouts(aIncrease, aFreezeChildren, aFreezeWorkers);
if (inner && aFreezeChildren) {
inner->Freeze();
@@ -13137,9 +13139,10 @@ nsGlobalWindow::SuspendTimeouts(uint32_t aIncrease,
}
nsresult
nsGlobalWindow::ResumeTimeouts(bool aThawChildren)
nsGlobalWindow::ResumeTimeouts(bool aThawChildren, bool aThawWorkers)
{
FORWARD_TO_INNER(ResumeTimeouts, (), NS_ERROR_NOT_INITIALIZED);
FORWARD_TO_INNER(ResumeTimeouts, (aThawChildren, aThawWorkers),
NS_ERROR_NOT_INITIALIZED);
NS_ASSERTION(mTimeoutsSuspendDepth, "Mismatched calls to ResumeTimeouts!");
--mTimeoutsSuspendDepth;
@@ -13157,11 +13160,15 @@ nsGlobalWindow::ResumeTimeouts(bool aThawChildren)
// Resume all of the AudioContexts for this window
for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
ErrorResult dummy;
unused << mAudioContexts[i]->Resume(dummy);
RefPtr<Promise> d = mAudioContexts[i]->Resume(dummy);
}
// Thaw all of the workers for this window.
mozilla::dom::workers::ThawWorkersForWindow(this);
// Thaw or resume all of the workers for this window.
if (aThawWorkers) {
mozilla::dom::workers::ThawWorkersForWindow(this);
} else {
mozilla::dom::workers::ResumeWorkersForWindow(this);
}
// Restore all of the timeouts, using the stored time remaining
// (stored in timeout->mTimeRemaining).
@@ -13240,7 +13247,7 @@ nsGlobalWindow::ResumeTimeouts(bool aThawChildren)
inner->Thaw();
}
rv = win->ResumeTimeouts(aThawChildren);
rv = win->ResumeTimeouts(aThawChildren, aThawWorkers);
NS_ENSURE_SUCCESS(rv, rv);
}
}
+4 -2
View File
@@ -443,8 +443,10 @@ public:
virtual already_AddRefed<nsISupports> SaveWindowState() override;
virtual nsresult RestoreWindowState(nsISupports *aState) override;
virtual void SuspendTimeouts(uint32_t aIncrease = 1,
bool aFreezeChildren = true) override;
virtual nsresult ResumeTimeouts(bool aThawChildren = true) override;
bool aFreezeChildren = true,
bool aFreezeWorkers = true) override;
virtual nsresult ResumeTimeouts(bool aThawChildren = true,
bool aThawWorkers = true) override;
virtual uint32_t TimeoutSuspendCount() override;
virtual nsresult FireDelayedDOMEvents() override;
virtual bool IsFrozen() const override
+4 -2
View File
@@ -309,10 +309,12 @@ public:
// Suspend timeouts in this window and in child windows.
virtual void SuspendTimeouts(uint32_t aIncrease = 1,
bool aFreezeChildren = true) = 0;
bool aFreezeChildren = true,
bool aFreezeWorkers = true) = 0;
// Resume suspended timeouts in this window and in child windows.
virtual nsresult ResumeTimeouts(bool aThawChildren = true) = 0;
virtual nsresult ResumeTimeouts(bool aThawChildren = true,
bool aThawWorkers = true) = 0;
virtual uint32_t TimeoutSuspendCount() = 0;
+1 -5
View File
@@ -482,11 +482,7 @@ nsPerformance::DispatchBufferFullEvent()
{
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
// it bubbles, and it isn't cancelable
nsresult rv = event->InitEvent(NS_LITERAL_STRING("resourcetimingbufferfull"),
true, false);
if (NS_FAILED(rv)) {
return;
}
event->InitEvent(NS_LITERAL_STRING("resourcetimingbufferfull"), true, false);
event->SetTrusted(true);
DispatchDOMEvent(nullptr, event, nullptr, nullptr);
}
+136 -52
View File
@@ -10,6 +10,7 @@
#include "nsScriptLoader.h"
#include "prsystem.h"
#include "jsapi.h"
#include "jsfriendapi.h"
#include "xpcpublic.h"
@@ -113,6 +114,7 @@ nsScriptLoadRequestList::Contains(nsScriptLoadRequest* aElem)
nsScriptLoader::nsScriptLoader(nsIDocument *aDocument)
: mDocument(aDocument),
mBlockerCount(0),
mNumberOfProcessors(0),
mEnabled(true),
mDeferEnabled(false),
mDocumentParsingDone(false),
@@ -273,30 +275,41 @@ nsScriptLoader::ShouldLoadScript(nsIDocument* aDocument,
return NS_OK;
}
class ContextMediator : public nsIStreamLoaderObserver
{
public:
explicit ContextMediator(nsScriptLoader *aScriptLoader, nsISupports *aContext)
: mScriptLoader(aScriptLoader)
, mContext(aContext) {}
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMLOADEROBSERVER
private:
virtual ~ContextMediator() {}
RefPtr<nsScriptLoader> mScriptLoader;
nsCOMPtr<nsISupports> mContext;
};
NS_IMPL_ISUPPORTS(ContextMediator, nsIStreamLoaderObserver)
NS_IMETHODIMP
ContextMediator::OnStreamComplete(nsIStreamLoader* aLoader,
nsISupports* aContext,
nsresult aStatus,
uint32_t aStringLen,
const uint8_t* aString)
{
// pass arguments through except for the aContext,
// we have to mediate and use mContext instead.
return mScriptLoader->OnStreamComplete(aLoader, mContext, aStatus,
aStringLen, aString);
}
nsresult
nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
bool aScriptFromHead)
{
nsISupports *context = aRequest->mElement.get()
? static_cast<nsISupports *>(aRequest->mElement.get())
: static_cast<nsISupports *>(mDocument);
nsresult rv = ShouldLoadScript(mDocument, context, aRequest->mURI, aType, aRequest->IsPreload());
if (NS_FAILED(rv)) {
return rv;
}
nsCOMPtr<nsILoadGroup> loadGroup = mDocument->GetDocumentLoadGroup();
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mDocument->MasterDocument()->GetWindow()));
if (!window) {
return NS_ERROR_NULL_POINTER;
}
nsIDocShell *docshell = window->GetDocShell();
nsCOMPtr<nsIInterfaceRequestor> prompter(do_QueryInterface(docshell));
// If this document is sandboxed without 'allow-scripts', abort.
if (mDocument->HasScriptsBlockedBySandbox()) {
return NS_OK;
@@ -305,17 +318,39 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
nsContentPolicyType contentPolicyType = aRequest->IsPreload()
? nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD
: nsIContentPolicy::TYPE_INTERNAL_SCRIPT;
nsCOMPtr<nsINode> context;
if (aRequest->mElement) {
context = do_QueryInterface(aRequest->mElement);
}
else {
context = mDocument;
}
nsCOMPtr<nsILoadGroup> loadGroup = mDocument->GetDocumentLoadGroup();
nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(mDocument->MasterDocument()->GetWindow()));
NS_ENSURE_TRUE(window, NS_ERROR_NULL_POINTER);
nsIDocShell *docshell = window->GetDocShell();
nsCOMPtr<nsIInterfaceRequestor> prompter(do_QueryInterface(docshell));
nsSecurityFlags securityFlags =
aRequest->mCORSMode == CORS_NONE
? nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL
: nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;
if (aRequest->mCORSMode == CORS_USE_CREDENTIALS) {
securityFlags |= nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS;
}
securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel),
aRequest->mURI,
mDocument,
nsILoadInfo::SEC_NORMAL,
contentPolicyType,
loadGroup,
prompter,
nsIRequest::LOAD_NORMAL |
nsIChannel::LOAD_CLASSIFY_URI);
nsresult rv = NS_NewChannel(getter_AddRefs(channel),
aRequest->mURI,
context,
securityFlags,
contentPolicyType,
loadGroup,
prompter,
nsIRequest::LOAD_NORMAL |
nsIChannel::LOAD_CLASSIFY_URI);
NS_ENSURE_SUCCESS(rv, rv);
@@ -354,26 +389,13 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType,
timedChannel->SetInitiatorType(NS_LITERAL_STRING("script"));
}
RefPtr<ContextMediator> mediator = new ContextMediator(this, aRequest);
nsCOMPtr<nsIStreamLoader> loader;
rv = NS_NewStreamLoader(getter_AddRefs(loader), this);
rv = NS_NewStreamLoader(getter_AddRefs(loader), mediator);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIStreamListener> listener = loader.get();
if (aRequest->mCORSMode != CORS_NONE) {
bool withCredentials = (aRequest->mCORSMode == CORS_USE_CREDENTIALS);
RefPtr<nsCORSListenerProxy> corsListener =
new nsCORSListenerProxy(listener, mDocument->NodePrincipal(),
withCredentials);
rv = corsListener->Init(channel, DataURIHandling::Allow);
NS_ENSURE_SUCCESS(rv, rv);
listener = corsListener;
}
rv = channel->AsyncOpen(listener, aRequest);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
return channel->AsyncOpen2(loader);
}
bool
@@ -561,7 +583,12 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
ourCORSMode == request->mCORSMode &&
ourRefPolicy == request->mReferrerPolicy) {
rv = CheckContentPolicy(mDocument, aElement, request->mURI, type, false);
NS_ENSURE_SUCCESS(rv, false);
if (NS_FAILED(rv)) {
// probably plans have changed; even though the preload was allowed seems
// like the actual load is not; let's cancel the preload request.
request->Cancel();
return false;
}
} else {
// Drop the preload
request = nullptr;
@@ -617,7 +644,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// loop gets a chance to spin.
// KVKV TODO: Instead of processing immediately, try off-thread-parsing
// it and only schedule a ProcessRequest if that fails.
// it and only schedule a pending ProcessRequest if that fails.
ProcessPendingRequestsAsync();
} else {
mLoadingAsyncRequests.AppendElement(request);
@@ -666,6 +693,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
}
return true;
}
if (request->IsDoneLoading() && ReadyToExecuteScripts()) {
// The request has already been loaded and there are no pending style
// sheets. If the script comes from the network stream, cheat for
@@ -684,6 +712,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
ProcessPendingRequestsAsync();
return true;
}
// The script hasn't loaded yet or there's a style sheet blocking it.
// The script will be run when it loads or the style sheet loads.
NS_ASSERTION(!mParserBlockingRequest,
@@ -782,6 +811,23 @@ nsScriptLoader::ProcessOffThreadRequest(nsScriptLoadRequest* aRequest)
{
MOZ_ASSERT(aRequest->mProgress == nsScriptLoadRequest::Progress_Compiling);
aRequest->mProgress = nsScriptLoadRequest::Progress_DoneCompiling;
if (aRequest == mParserBlockingRequest) {
if (!ReadyToExecuteScripts()) {
// If not ready to execute scripts, schedule an async call to
// ProcessPendingRequests to handle it.
ProcessPendingRequestsAsync();
return NS_OK;
}
// Same logic as in top of ProcessPendingRequests.
mParserBlockingRequest = nullptr;
UnblockParser(aRequest);
ProcessRequest(aRequest);
mDocument->UnblockOnload(false);
ContinueParserAsync(aRequest);
return NS_OK;
}
nsresult rv = ProcessRequest(aRequest);
mDocument->UnblockOnload(false);
return rv;
@@ -830,9 +876,10 @@ OffThreadScriptLoaderCallback(void *aToken, void *aCallbackData)
}
nsresult
nsScriptLoader::AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest)
nsScriptLoader::AttemptAsyncScriptCompile(nsScriptLoadRequest* aRequest)
{
if (!aRequest->mElement->GetScriptAsync() || aRequest->mIsInline) {
// Don't off-thread compile inline scripts.
if (aRequest->mIsInline) {
return NS_ERROR_FAILURE;
}
@@ -873,7 +920,8 @@ nsScriptLoader::AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest)
}
nsresult
nsScriptLoader::CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest)
nsScriptLoader::CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest,
bool* oCompiledOffThread)
{
NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
"Processing requests when running scripts is unsafe.");
@@ -882,8 +930,11 @@ nsScriptLoader::CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest)
NS_ASSERTION(!aRequest->InCompilingStage(),
"Candidate for off-thread compile is already in compiling stage.");
nsresult rv = AttemptAsyncScriptParse(aRequest);
nsresult rv = AttemptAsyncScriptCompile(aRequest);
if (rv != NS_ERROR_FAILURE) {
if (oCompiledOffThread && rv == NS_OK) {
*oCompiledOffThread = true;
}
return rv;
}
@@ -1174,8 +1225,12 @@ nsScriptLoader::ProcessPendingRequests()
mParserBlockingRequest->IsReadyToRun() &&
ReadyToExecuteScripts()) {
request.swap(mParserBlockingRequest);
bool offThreadCompiled = request->mProgress == nsScriptLoadRequest::Progress_DoneCompiling;
UnblockParser(request);
ProcessRequest(request);
if (offThreadCompiled) {
mDocument->UnblockOnload(false);
}
ContinueParserAsync(request);
}
@@ -1487,6 +1542,18 @@ nsScriptLoader::ContinueParserAsync(nsScriptLoadRequest* aParserBlockingRequest)
aParserBlockingRequest->mElement->ContinueParserAsync();
}
uint32_t
nsScriptLoader::NumberOfProcessors()
{
if (mNumberOfProcessors > 0)
return mNumberOfProcessors;
int32_t numProcs = PR_GetNumberOfProcessors();
if (numProcs > 0)
mNumberOfProcessors = numProcs;
return mNumberOfProcessors;
}
nsresult
nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
nsIStreamLoader* aLoader,
@@ -1575,6 +1642,23 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
// Mark this as loaded
aRequest->mProgress = nsScriptLoadRequest::Progress_DoneLoading;
// If this is currently blocking the parser, attempt to compile it off-main-thread.
if (aRequest == mParserBlockingRequest && (NumberOfProcessors() > 1)) {
nsresult rv = AttemptAsyncScriptCompile(aRequest);
if (rv == NS_OK) {
NS_ASSERTION(aRequest->mProgress == nsScriptLoadRequest::Progress_Compiling,
"Request should be off-thread compiling now.");
return NS_OK;
}
// If off-thread compile errored, return the error.
if (rv != NS_ERROR_FAILURE) {
return rv;
}
// If off-thread compile was rejected, continue with regular processing.
}
// 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.
+5 -2
View File
@@ -470,9 +470,10 @@ private:
return mEnabled && !mBlockerCount;
}
nsresult AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest);
nsresult AttemptAsyncScriptCompile(nsScriptLoadRequest* aRequest);
nsresult ProcessRequest(nsScriptLoadRequest* aRequest);
nsresult CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest);
nsresult CompileOffThreadOrProcessRequest(nsScriptLoadRequest* aRequest,
bool* oCompiledOffThread=nullptr);
void FireScriptAvailable(nsresult aResult,
nsScriptLoadRequest* aRequest);
void FireScriptEvaluated(nsresult aResult,
@@ -486,6 +487,7 @@ private:
JS::Handle<JSObject *> aScopeChain,
JS::CompileOptions *aOptions);
uint32_t NumberOfProcessors();
nsresult PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
nsIStreamLoader* aLoader,
nsresult aStatus,
@@ -529,6 +531,7 @@ private:
// XXXbz do we want to cycle-collect these or something? Not sure.
nsTArray< RefPtr<nsScriptLoader> > mPendingChildLoaders;
uint32_t mBlockerCount;
uint32_t mNumberOfProcessors;
bool mEnabled;
bool mDeferEnabled;
bool mDocumentParsingDone;
+24 -32
View File
@@ -23,7 +23,6 @@
#include "nsNetUtil.h"
#include "nsAutoPtr.h"
#include "nsStreamUtils.h"
#include "nsCORSListenerProxy.h"
#include <algorithm>
using mozilla::net::ReferrerPolicy;
@@ -42,7 +41,7 @@ public:
NS_DECL_ISUPPORTS
nsresult LoadDocument(nsIChannel* aChannel, nsIPrincipal *aLoaderPrincipal,
nsresult LoadDocument(nsIChannel* aChannel,
bool aChannelIsSync, bool aForceToXML,
ReferrerPolicy aReferrerPolicy,
nsIDOMDocument** aResult);
@@ -130,29 +129,29 @@ NS_IMPL_ISUPPORTS(nsSyncLoader,
nsresult
nsSyncLoader::LoadDocument(nsIChannel* aChannel,
nsIPrincipal *aLoaderPrincipal,
bool aChannelIsSync,
bool aForceToXML,
ReferrerPolicy aReferrerPolicy,
nsIDOMDocument **aResult)
{
NS_ENSURE_ARG(aChannel);
NS_ENSURE_ARG_POINTER(aResult);
*aResult = nullptr;
nsresult rv = NS_OK;
nsCOMPtr<nsIURI> loaderUri;
if (aLoaderPrincipal) {
aLoaderPrincipal->GetURI(getter_AddRefs(loaderUri));
}
mChannel = aChannel;
nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(mChannel);
if (http) {
http->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
NS_LITERAL_CSTRING("text/xml,application/xml,application/xhtml+xml,*/*;q=0.1"),
false);
if (loaderUri) {
http->SetReferrerWithPolicy(loaderUri, aReferrerPolicy);
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
if (loadInfo) {
nsCOMPtr<nsIURI> loaderUri;
loadInfo->TriggeringPrincipal()->GetURI(getter_AddRefs(loaderUri));
if (loaderUri) {
http->SetReferrerWithPolicy(loaderUri, aReferrerPolicy);
}
}
}
@@ -186,14 +185,6 @@ nsSyncLoader::LoadDocument(nsIChannel* aChannel,
listener.swap(forceListener);
}
if (aLoaderPrincipal) {
RefPtr<nsCORSListenerProxy> corsListener =
new nsCORSListenerProxy(listener, aLoaderPrincipal, false);
rv = corsListener->Init(mChannel, DataURIHandling::Disallow);
NS_ENSURE_SUCCESS(rv, rv);
listener = corsListener;
}
if (aChannelIsSync) {
rv = PushSyncStream(listener);
}
@@ -226,7 +217,7 @@ nsSyncLoader::PushAsyncStream(nsIStreamListener* aListener)
mAsyncLoadStatus = NS_OK;
// Start reading from the channel
nsresult rv = mChannel->AsyncOpen(this, nullptr);
nsresult rv = mChannel->AsyncOpen2(this);
if (NS_SUCCEEDED(rv)) {
// process events until we're finished.
@@ -254,7 +245,7 @@ nsresult
nsSyncLoader::PushSyncStream(nsIStreamListener* aListener)
{
nsCOMPtr<nsIInputStream> in;
nsresult rv = mChannel->Open(getter_AddRefs(in));
nsresult rv = mChannel->Open2(getter_AddRefs(in));
NS_ENSURE_SUCCESS(rv, rv);
mLoading = true;
@@ -309,8 +300,12 @@ nsSyncLoader::GetInterface(const nsIID & aIID,
/* static */
nsresult
nsSyncLoadService::LoadDocument(nsIURI *aURI, nsIPrincipal *aLoaderPrincipal,
nsILoadGroup *aLoadGroup, bool aForceToXML,
nsSyncLoadService::LoadDocument(nsIURI *aURI,
nsContentPolicyType aContentPolicyType,
nsIPrincipal *aLoaderPrincipal,
nsSecurityFlags aSecurityFlags,
nsILoadGroup *aLoadGroup,
bool aForceToXML,
ReferrerPolicy aReferrerPolicy,
nsIDOMDocument** aResult)
{
@@ -318,8 +313,8 @@ nsSyncLoadService::LoadDocument(nsIURI *aURI, nsIPrincipal *aLoaderPrincipal,
nsresult rv = NS_NewChannel(getter_AddRefs(channel),
aURI,
aLoaderPrincipal,
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_OTHER,
aSecurityFlags,
aContentPolicyType,
aLoadGroup);
NS_ENSURE_SUCCESS(rv, rv);
@@ -328,15 +323,12 @@ nsSyncLoadService::LoadDocument(nsIURI *aURI, nsIPrincipal *aLoaderPrincipal,
}
bool isChrome = false, isResource = false;
bool isSync = (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) &&
isChrome) ||
(NS_SUCCEEDED(aURI->SchemeIs("resource", &isResource)) &&
isResource);
bool isSync =
(NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome) ||
(NS_SUCCEEDED(aURI->SchemeIs("resource", &isResource)) && isResource);
RefPtr<nsSyncLoader> loader = new nsSyncLoader();
return loader->LoadDocument(channel, aLoaderPrincipal, isSync,
aForceToXML, aReferrerPolicy, aResult);
return loader->LoadDocument(channel, isSync, aForceToXML,
aReferrerPolicy, aResult);
}
/* static */
+9 -4
View File
@@ -29,17 +29,22 @@ public:
* Synchronously load the document from the specified URI.
*
* @param aURI URI to load the document from.
* @param aContentPolicyType contentPolicyType to be set on the channel
* @param aLoaderPrincipal Principal of loading document. For security
* checks and referrer header. May be null if no
* security checks should be done.
* checks and referrer header.
* @param aSecurityFlags securityFlags to be set on the channel
* @param aLoadGroup The loadgroup to use for loading the document.
* @param aForceToXML Whether to parse the document as XML, regardless of
* content type.
* @param referrerPolicy Referrer policy.
* @param aResult [out] The document loaded from the URI.
*/
static nsresult LoadDocument(nsIURI *aURI, nsIPrincipal *aLoaderPrincipal,
nsILoadGroup *aLoadGroup, bool aForceToXML,
static nsresult LoadDocument(nsIURI *aURI,
nsContentPolicyType aContentPolicyType,
nsIPrincipal *aLoaderPrincipal,
nsSecurityFlags aSecurityFlags,
nsILoadGroup *aLoadGroup,
bool aForceToXML,
mozilla::net::ReferrerPolicy aReferrerPolicy,
nsIDOMDocument** aResult);
-3
View File
@@ -2852,9 +2852,6 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
AddLoadFlags(mChannel, nsIChannel::LOAD_EXPLICIT_CREDENTIALS);
}
NS_ASSERTION(listener != this,
"Using an object as a listener that can't be exposed to JS");
// When we are sync loading, we need to bypass the local cache when it would
// otherwise block us waiting for exclusive access to the cache. If we don't
// do this, then we could dead lock in some cases (see bug 309424).
+6
View File
@@ -485,12 +485,18 @@ DOMInterfaces = {
'nativeType': 'mozilla::dom::workers::ExtendableEvent',
},
'ExtendableMessageEvent': {
'headerFile': 'mozilla/dom/ServiceWorkerEvents.h',
'nativeType': 'mozilla::dom::workers::ExtendableMessageEvent',
},
'FetchEvent': {
'headerFile': 'ServiceWorkerEvents.h',
'nativeType': 'mozilla::dom::workers::FetchEvent',
'binaryNames': {
'request': 'request_'
},
'implicitJSContext': [ 'respondWith' ],
},
'FileReader': {
+2 -8
View File
@@ -15994,7 +15994,7 @@ class CGEventMethod(CGNativeMember):
self.args.insert(0, Argument("JSContext*", "aCx"))
if not self.isInit:
self.args.insert(0, Argument("const GlobalObject&", "aGlobal"))
self.args.append(Argument('ErrorResult&', 'aRv'))
self.args.append(Argument('ErrorResult&', 'aRv'))
return constructorForNativeCaller + CGNativeMember.declare(self, cgClass)
def defineInit(self, cgClass):
@@ -16016,11 +16016,7 @@ class CGEventMethod(CGNativeMember):
self.body = fill(
"""
nsresult rv = InitEvent(${typeArg}, ${bubblesArg}, ${cancelableArg});
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return;
}
InitEvent(${typeArg}, ${bubblesArg}, ${cancelableArg});
${members}
""",
typeArg=self.args[0].name,
@@ -16028,8 +16024,6 @@ class CGEventMethod(CGNativeMember):
cancelableArg=self.args[2].name,
members=members)
self.args.append(Argument('ErrorResult&', 'aRv'))
return CGNativeMember.define(self, cgClass)
def define(self, cgClass):
+1 -1
View File
@@ -44,7 +44,7 @@ AnimationEvent::Constructor(const GlobalObject& aGlobal,
RefPtr<AnimationEvent> e = new AnimationEvent(t, nullptr, nullptr);
bool trusted = e->Init(t);
aRv = e->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
e->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
InternalAnimationEvent* internalEvent = e->mEvent->AsAnimationEvent();
internalEvent->animationName = aParam.mAnimationName;
+1 -2
View File
@@ -42,8 +42,7 @@ AsyncEventDispatcher::Run()
RefPtr<Event> event = mEvent ? mEvent->InternalDOMEvent() : nullptr;
if (!event) {
event = NS_NewDOMEvent(mTarget, nullptr, nullptr);
nsresult rv = event->InitEvent(mEventType, mBubbles, false);
NS_ENSURE_SUCCESS(rv, rv);
event->InitEvent(mEventType, mBubbles, false);
event->SetTrusted(true);
}
if (mOnlyChromeDispatch) {
+4 -9
View File
@@ -43,7 +43,7 @@ ClipboardEvent::InitClipboardEvent(const nsAString& aType,
// Null clipboardData is OK
ErrorResult rv;
InitClipboardEvent(aType, aCanBubble, aCancelable, clipboardData, rv);
InitClipboardEvent(aType, aCanBubble, aCancelable, clipboardData);
return rv.StealNSResult();
}
@@ -51,14 +51,9 @@ ClipboardEvent::InitClipboardEvent(const nsAString& aType,
void
ClipboardEvent::InitClipboardEvent(const nsAString& aType, bool aCanBubble,
bool aCancelable,
DataTransfer* aClipboardData,
ErrorResult& aError)
DataTransfer* aClipboardData)
{
aError = Event::InitEvent(aType, aCanBubble, aCancelable);
if (aError.Failed()) {
return;
}
Event::InitEvent(aType, aCanBubble, aCancelable);
mEvent->AsClipboardEvent()->clipboardData = aClipboardData;
}
@@ -85,7 +80,7 @@ ClipboardEvent::Constructor(const GlobalObject& aGlobal,
}
e->InitClipboardEvent(aType, aParam.mBubbles, aParam.mCancelable,
clipboardData, aRv);
clipboardData);
e->SetTrusted(trusted);
return e.forget();
}
+1 -2
View File
@@ -46,8 +46,7 @@ public:
void InitClipboardEvent(const nsAString& aType, bool aCanBubble,
bool aCancelable,
DataTransfer* aClipboardData,
ErrorResult& aError);
DataTransfer* aClipboardData);
protected:
~ClipboardEvent() {}
+1 -2
View File
@@ -51,8 +51,7 @@ CommandEvent::InitCommandEvent(const nsAString& aTypeArg,
bool aCancelableArg,
const nsAString& aCommand)
{
nsresult rv = Event::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
NS_ENSURE_SUCCESS(rv, rv);
Event::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
mEvent->AsCommandEvent()->command = do_GetAtom(aCommand);
return NS_OK;
+2 -3
View File
@@ -66,8 +66,7 @@ CustomEvent::InitCustomEvent(const nsAString& aType,
bool aCancelable,
nsIVariant* aDetail)
{
nsresult rv = Event::InitEvent(aType, aCanBubble, aCancelable);
NS_ENSURE_SUCCESS(rv, rv);
Event::InitEvent(aType, aCanBubble, aCancelable);
mDetail = aDetail;
return NS_OK;
}
@@ -89,7 +88,7 @@ CustomEvent::InitCustomEvent(JSContext* aCx,
aRv.Throw(NS_ERROR_FAILURE);
return;
}
aRv = InitCustomEvent(aType, aCanBubble, aCancelable, detail);
InitCustomEvent(aType, aCanBubble, aCancelable, detail);
}
NS_IMETHODIMP
+1 -2
View File
@@ -263,8 +263,7 @@ nsresult
DOMEventTargetHelper::DispatchTrustedEvent(const nsAString& aEventName)
{
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
nsresult rv = event->InitEvent(aEventName, false, false);
NS_ENSURE_SUCCESS(rv, rv);
event->InitEvent(aEventName, false, false);
return DispatchTrustedEvent(event);
}
+3 -10
View File
@@ -33,13 +33,9 @@ DeviceMotionEvent::InitDeviceMotionEvent(
const DeviceAccelerationInit& aAcceleration,
const DeviceAccelerationInit& aAccelIncludingGravity,
const DeviceRotationRateInit& aRotationRate,
Nullable<double> aInterval,
ErrorResult& aRv)
Nullable<double> aInterval)
{
aRv = Event::InitEvent(aType, aCanBubble, aCancelable);
if (aRv.Failed()) {
return;
}
Event::InitEvent(aType, aCanBubble, aCancelable);
mAcceleration = new DeviceAcceleration(this, aAcceleration.mX,
aAcceleration.mY,
@@ -64,10 +60,7 @@ DeviceMotionEvent::Constructor(const GlobalObject& aGlobal,
{
nsCOMPtr<EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
RefPtr<DeviceMotionEvent> e = new DeviceMotionEvent(t, nullptr, nullptr);
aRv = e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable);
if (aRv.Failed()) {
return nullptr;
}
e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable);
bool trusted = e->Init(t);
e->mAcceleration = new DeviceAcceleration(e,
+1 -2
View File
@@ -128,8 +128,7 @@ public:
const DeviceAccelerationInit& aAcceleration,
const DeviceAccelerationInit& aAccelerationIncludingGravity,
const DeviceRotationRateInit& aRotationRate,
Nullable<double> aInterval,
ErrorResult& aRv);
Nullable<double> aInterval);
static already_AddRefed<DeviceMotionEvent>
Constructor(const GlobalObject& aGlobal,
+4 -6
View File
@@ -414,7 +414,7 @@ Event::Constructor(const GlobalObject& aGlobal,
nsCOMPtr<mozilla::dom::EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
RefPtr<Event> e = new Event(t, nullptr, nullptr);
bool trusted = e->Init(t);
aRv = e->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
e->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
e->SetTrusted(trusted);
return e.forget();
}
@@ -572,13 +572,13 @@ Event::SetEventType(const nsAString& aEventTypeArg)
}
}
NS_IMETHODIMP
void
Event::InitEvent(const nsAString& aEventTypeArg,
bool aCanBubbleArg,
bool aCancelableArg)
{
// Make sure this event isn't already being dispatched.
NS_ENSURE_TRUE(!mEvent->mFlags.mIsBeingDispatched, NS_OK);
NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
if (IsTrusted()) {
// Ensure the caller is permitted to dispatch trusted DOM events.
@@ -600,7 +600,6 @@ Event::InitEvent(const nsAString& aEventTypeArg,
// re-dispatching it.
mEvent->target = nullptr;
mEvent->originalTarget = nullptr;
return NS_OK;
}
NS_IMETHODIMP
@@ -1195,8 +1194,7 @@ Event::Deserialize(const IPC::Message* aMsg, void** aIter)
bool trusted = false;
NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &trusted), false);
nsresult rv = InitEvent(type, bubbles, cancelable);
NS_ENSURE_SUCCESS(rv, false);
InitEvent(type, bubbles, cancelable);
SetTrusted(trusted);
return true;
+1 -7
View File
@@ -211,12 +211,6 @@ public:
double TimeStamp() const;
void InitEvent(const nsAString& aType, bool aBubbles, bool aCancelable,
ErrorResult& aRv)
{
aRv = InitEvent(aType, aBubbles, aCancelable);
}
EventTarget* GetOriginalTarget() const;
EventTarget* GetExplicitOriginalTarget() const;
EventTarget* GetComposedTarget() const;
@@ -316,7 +310,7 @@ private:
NS_IMETHOD StopPropagation(void) override { return _to StopPropagation(); } \
NS_IMETHOD StopCrossProcessForwarding(void) override { return _to StopCrossProcessForwarding(); } \
NS_IMETHOD PreventDefault(void) override { return _to PreventDefault(); } \
NS_IMETHOD InitEvent(const nsAString& eventTypeArg, bool canBubbleArg, bool cancelableArg) override { return _to InitEvent(eventTypeArg, canBubbleArg, cancelableArg); } \
void InitEvent(const nsAString& eventTypeArg, bool canBubbleArg, bool cancelableArg) override { _to InitEvent(eventTypeArg, canBubbleArg, cancelableArg); } \
NS_IMETHOD GetDefaultPrevented(bool* aDefaultPrevented) override { return _to GetDefaultPrevented(aDefaultPrevented); } \
NS_IMETHOD StopImmediatePropagation(void) override { return _to StopImmediatePropagation(); } \
NS_IMETHOD GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget) override { return _to GetOriginalTarget(aOriginalTarget); } \
+42 -21
View File
@@ -14,9 +14,6 @@
#include "jsapi.h"
#include "nsGlobalWindow.h" // So we can assign an nsGlobalWindow* to mWindowSource
#include "ServiceWorker.h"
#include "ServiceWorkerClient.h"
namespace mozilla {
namespace dom {
@@ -107,14 +104,12 @@ MessageEvent::GetSource(nsIDOMWindow** aSource)
}
void
MessageEvent::GetSource(Nullable<OwningWindowProxyOrMessagePortOrClient>& aValue) const
MessageEvent::GetSource(Nullable<OwningWindowProxyOrMessagePort>& aValue) const
{
if (mWindowSource) {
aValue.SetValue().SetAsWindowProxy() = mWindowSource;
} else if (mPortSource) {
aValue.SetValue().SetAsMessagePort() = mPortSource;
} else if (mClientSource) {
aValue.SetValue().SetAsClient() = mClientSource;
}
}
@@ -136,11 +131,7 @@ MessageEvent::Constructor(EventTarget* aEventTarget,
{
RefPtr<MessageEvent> event = new MessageEvent(aEventTarget, nullptr, nullptr);
aRv = event->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
if (aRv.Failed()) {
return nullptr;
}
event->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
bool trusted = event->Init(aEventTarget);
event->SetTrusted(trusted);
@@ -187,9 +178,7 @@ MessageEvent::InitMessageEvent(const nsAString& aType,
const nsAString& aLastEventId,
nsIDOMWindow* aSource)
{
nsresult rv = Event::InitEvent(aType, aCanBubble, aCancelable);
NS_ENSURE_SUCCESS(rv, rv);
Event::InitEvent(aType, aCanBubble, aCancelable);
mData = aData;
mozilla::HoldJSObjects(this);
mOrigin = aOrigin;
@@ -199,6 +188,44 @@ MessageEvent::InitMessageEvent(const nsAString& aType,
return NS_OK;
}
void
MessageEvent::InitMessageEvent(JSContext* aCx, const nsAString& aType,
bool aCanBubble, bool aCancelable,
JS::Handle<JS::Value> aData,
const nsAString& aOrigin,
const nsAString& aLastEventId,
const Nullable<WindowProxyOrMessagePort>& aSource,
const Nullable<Sequence<OwningNonNull<MessagePort>>>& aPorts)
{
Event::InitEvent(aType, aCanBubble, aCancelable);
mData = aData;
mozilla::HoldJSObjects(this);
mOrigin = aOrigin;
mLastEventId = aLastEventId;
mWindowSource = nullptr;
mPortSource = nullptr;
if (!aSource.IsNull()) {
if (aSource.Value().IsWindowProxy()) {
mWindowSource = aSource.Value().GetAsWindowProxy();
} else {
mPortSource = &aSource.Value().GetAsMessagePort();
}
}
mPorts = nullptr;
if (!aPorts.IsNull()) {
nsTArray<RefPtr<MessagePort>> ports;
for (uint32_t i = 0, len = aPorts.Value().Length(); i < len; ++i) {
ports.AppendElement(aPorts.Value()[i]);
}
mPorts = new MessagePortList(static_cast<Event*>(this), ports);
}
}
void
MessageEvent::SetPorts(MessagePortList* aPorts)
{
@@ -212,12 +239,6 @@ MessageEvent::SetSource(mozilla::dom::MessagePort* aPort)
mPortSource = aPort;
}
void
MessageEvent::SetSource(mozilla::dom::workers::ServiceWorkerClient* aClient)
{
mClientSource = aClient;
}
} // namespace dom
} // namespace mozilla
@@ -227,7 +248,7 @@ using namespace mozilla::dom;
already_AddRefed<MessageEvent>
NS_NewDOMMessageEvent(EventTarget* aOwner,
nsPresContext* aPresContext,
WidgetEvent* aEvent)
WidgetEvent* aEvent)
{
RefPtr<MessageEvent> it = new MessageEvent(aOwner, aPresContext, aEvent);
return it.forget();
+11 -12
View File
@@ -8,9 +8,10 @@
#define mozilla_dom_MessageEvent_h_
#include "mozilla/dom/Event.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/MessagePortList.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIDOMMessageEvent.h"
#include "mozilla/dom/MessagePortList.h"
namespace mozilla {
namespace dom {
@@ -18,13 +19,8 @@ namespace dom {
struct MessageEventInit;
class MessagePort;
class MessagePortList;
class OwningWindowProxyOrMessagePortOrClient;
namespace workers {
class ServiceWorkerClient;
} // namespace workers
class OwningWindowProxyOrMessagePort;
class WindowProxyOrMessagePort;
/**
* Implements the MessageEvent event, used for cross-document messaging and
@@ -54,7 +50,7 @@ public:
void GetData(JSContext* aCx, JS::MutableHandle<JS::Value> aData,
ErrorResult& aRv);
void GetSource(Nullable<OwningWindowProxyOrMessagePortOrClient>& aValue) const;
void GetSource(Nullable<OwningWindowProxyOrMessagePort>& aValue) const;
MessagePortList* GetPorts()
{
@@ -66,8 +62,6 @@ public:
// Non WebIDL methods
void SetSource(mozilla::dom::MessagePort* aPort);
void SetSource(workers::ServiceWorkerClient* aClient);
void SetSource(nsPIDOMWindow* aWindow)
{
mWindowSource = aWindow;
@@ -85,6 +79,12 @@ public:
const MessageEventInit& aEventInit,
ErrorResult& aRv);
void InitMessageEvent(JSContext* aCx, const nsAString& aType, bool aCanBubble,
bool aCancelable, JS::Handle<JS::Value> aData,
const nsAString& aOrigin, const nsAString& aLastEventId,
const Nullable<WindowProxyOrMessagePort>& aSource,
const Nullable<Sequence<OwningNonNull<MessagePort>>>& aPorts);
protected:
~MessageEvent();
@@ -94,7 +94,6 @@ private:
nsString mLastEventId;
nsCOMPtr<nsIDOMWindow> mWindowSource;
RefPtr<MessagePort> mPortSource;
RefPtr<workers::ServiceWorkerClient> mClientSource;
RefPtr<MessagePortList> mPorts;
};
+1 -2
View File
@@ -96,8 +96,7 @@ MutationEvent::InitMutationEvent(const nsAString& aTypeArg,
const nsAString& aAttrNameArg,
uint16_t aAttrChangeArg)
{
nsresult rv = Event::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
NS_ENSURE_SUCCESS(rv, rv);
Event::InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
InternalMutationEvent* mutation = mEvent->AsMutationEvent();
mutation->mRelatedNode = aRelatedNodeArg;
+3 -7
View File
@@ -29,7 +29,7 @@ SpeechRecognitionError::Constructor(const GlobalObject& aGlobal,
nsCOMPtr<mozilla::dom::EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
RefPtr<SpeechRecognitionError> e = new SpeechRecognitionError(t, nullptr, nullptr);
bool trusted = e->Init(t);
e->InitSpeechRecognitionError(aType, aParam.mBubbles, aParam.mCancelable, aParam.mError, aParam.mMessage, aRv);
e->InitSpeechRecognitionError(aType, aParam.mBubbles, aParam.mCancelable, aParam.mError, aParam.mMessage);
e->SetTrusted(trusted);
return e.forget();
}
@@ -39,15 +39,11 @@ SpeechRecognitionError::InitSpeechRecognitionError(const nsAString& aType,
bool aCanBubble,
bool aCancelable,
SpeechRecognitionErrorCode aError,
const nsAString& aMessage,
ErrorResult& aRv)
const nsAString& aMessage)
{
aRv = Event::InitEvent(aType, aCanBubble, aCancelable);
NS_ENSURE_TRUE_VOID(!aRv.Failed());
Event::InitEvent(aType, aCanBubble, aCancelable);
mError = aError;
mMessage = aMessage;
return;
}
} // namespace dom
+1 -2
View File
@@ -49,8 +49,7 @@ public:
bool aCanBubble,
bool aCancelable,
SpeechRecognitionErrorCode aError,
const nsAString& aMessage,
ErrorResult& aRv);
const nsAString& aMessage);
protected:
SpeechRecognitionErrorCode mError;
+2 -7
View File
@@ -85,14 +85,9 @@ StorageEvent::InitStorageEvent(const nsAString& aType, bool aCanBubble,
const nsAString& aOldValue,
const nsAString& aNewValue,
const nsAString& aURL,
DOMStorage* aStorageArea,
ErrorResult& aRv)
DOMStorage* aStorageArea)
{
aRv = InitEvent(aType, aCanBubble, aCancelable);
if (aRv.Failed()) {
return;
}
InitEvent(aType, aCanBubble, aCancelable);
mKey = aKey;
mOldValue = aOldValue;
mNewValue = aNewValue;
+1 -2
View File
@@ -57,8 +57,7 @@ public:
const nsAString& aOldValue,
const nsAString& aNewValue,
const nsAString& aURL,
DOMStorage* aStorageArea,
ErrorResult& aRv);
DOMStorage* aStorageArea);
void GetKey(nsString& aRetVal) const
{
+2 -7
View File
@@ -102,14 +102,9 @@ TouchEvent::InitTouchEvent(const nsAString& aType,
bool aMetaKey,
TouchList* aTouches,
TouchList* aTargetTouches,
TouchList* aChangedTouches,
ErrorResult& aRv)
TouchList* aChangedTouches)
{
aRv = UIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);
if (aRv.Failed()) {
return;
}
UIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);
mEvent->AsInputEvent()->InitBasicModifiers(aCtrlKey, aAltKey,
aShiftKey, aMetaKey);
mTouches = aTouches;
+1 -2
View File
@@ -115,8 +115,7 @@ public:
bool aMetaKey,
TouchList* aTouches,
TouchList* aTargetTouches,
TouchList* aChangedTouches,
ErrorResult& aRv);
TouchList* aChangedTouches);
static bool PrefEnabled(JSContext* aCx = nullptr,
JSObject* aGlobal = nullptr);
+1 -1
View File
@@ -44,7 +44,7 @@ TransitionEvent::Constructor(const GlobalObject& aGlobal,
RefPtr<TransitionEvent> e = new TransitionEvent(t, nullptr, nullptr);
bool trusted = e->Init(t);
aRv = e->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
e->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
InternalTransitionEvent* internalEvent = e->mEvent->AsTransitionEvent();
internalEvent->propertyName = aParam.mPropertyName;
+1 -3
View File
@@ -161,9 +161,7 @@ UIEvent::InitUIEvent(const nsAString& typeArg,
nsCOMPtr<nsPIDOMWindow> view = do_QueryInterface(viewArg);
NS_ENSURE_TRUE(view, NS_ERROR_INVALID_ARG);
}
nsresult rv = Event::InitEvent(typeArg, canBubbleArg, cancelableArg);
NS_ENSURE_SUCCESS(rv, rv);
Event::InitEvent(typeArg, canBubbleArg, cancelableArg);
mDetail = detailArg;
mView = viewArg;
+26 -13
View File
@@ -13,6 +13,23 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=848294
</head>
<body>
<script type="application/javascript">
function testMessageEvent(e, test) {
ok(e, "MessageEvent created");
is(e.type, 'message', 'MessageEvent.type is right');
is(e.data, 'data' in test ? test.data : undefined, 'MessageEvent.data is ok');
is(e.origin, 'origin' in test ? test.origin : '', 'MessageEvent.origin is ok');
is(e.lastEventId, 'lastEventId' in test ? test.lastEventId : '', 'MessageEvent.lastEventId is ok');
is(e.source, 'source' in test ? test.source : null, 'MessageEvent.source is ok');
if (test.ports != undefined) {
is(e.ports.length, test.ports.length, 'MessageEvent.ports is ok');
is(e.ports, e.ports, 'MessageEvent.ports is ok');
} else {
ok(!('ports' in test) || test.ports == null, 'MessageEvent.ports is ok');
}
}
function runTest() {
var channel = new MessageChannel();
@@ -33,20 +50,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=848294
var test = tests.shift();
var e = new MessageEvent('message', test);
ok(e, "MessageEvent created");
is(e.type, 'message', 'MessageEvent.type is right');
testMessageEvent(e, test);
is(e.data, 'data' in test ? test.data : undefined, 'MessageEvent.data is ok');
is(e.origin, 'origin' in test ? test.origin : '', 'MessageEvent.origin is ok');
is(e.lastEventId, 'lastEventId' in test ? test.lastEventId : '', 'MessageEvent.lastEventId is ok');
is(e.source, 'source' in test ? test.source : null, 'MessageEvent.source is ok');
if (test.ports != undefined) {
is(e.ports.length, test.ports.length, 'MessageEvent.ports is ok');
is(e.ports, e.ports, 'MessageEvent.ports is ok');
} else {
ok(!('ports' in test) || test.ports == null, 'MessageEvent.ports is ok');
}
e = new MessageEvent('message');
e.initMessageEvent('message', true, true,
'data' in test ? test.data : undefined,
'origin' in test ? test.origin : '',
'lastEventId' in test ? test.lastEventId : '',
'source' in test ? test.source : null,
'ports' in test ? test.ports : null);
testMessageEvent(e, test);
}
try {
-389
View File
@@ -454,395 +454,6 @@ ExtractFromURLSearchParams(const URLSearchParams& aParams,
aContentType = NS_LITERAL_CSTRING("application/x-www-form-urlencoded;charset=UTF-8");
return NS_NewStringInputStream(aStream, serialized);
}
class MOZ_STACK_CLASS FillFormIterator final
: public URLSearchParams::ForEachIterator
{
public:
explicit FillFormIterator(nsFormData* aFormData)
: mFormData(aFormData)
{
MOZ_ASSERT(aFormData);
}
bool URLParamsIterator(const nsString& aName,
const nsString& aValue) override
{
mFormData->Append(aName, aValue);
return true;
}
private:
nsFormData* mFormData;
};
/**
* A simple multipart/form-data parser as defined in RFC 2388 and RFC 2046.
* This does not respect any encoding specified per entry, using UTF-8
* throughout. This is as the Fetch spec states in the consume body algorithm.
* Borrows some things from Necko's nsMultiMixedConv, but is simpler since
* unlike Necko we do not have to deal with receiving incomplete chunks of data.
*
* This parser will fail the entire parse on any invalid entry, so it will
* never return a partially filled FormData.
* The content-disposition header is used to figure out the name and filename
* entries. The inclusion of the filename parameter decides if the entry is
* inserted into the nsFormData as a string or a File.
*
* File blobs are copies of the underlying data string since we cannot adopt
* char* chunks embedded within the larger body without significant effort.
* FIXME(nsm): Bug 1127552 - We should add telemetry to calls to formData() and
* friends to figure out if Fetch ends up copying big blobs to see if this is
* worth optimizing.
*/
class MOZ_STACK_CLASS FormDataParser
{
private:
RefPtr<nsFormData> mFormData;
nsCString mMimeType;
nsCString mData;
// Entry state, reset in START_PART.
nsCString mName;
nsCString mFilename;
nsCString mContentType;
enum
{
START_PART,
PARSE_HEADER,
PARSE_BODY,
} mState;
nsIGlobalObject* mParentObject;
// Reads over a boundary and sets start to the position after the end of the
// boundary. Returns false if no boundary is found immediately.
bool
PushOverBoundary(const nsACString& aBoundaryString,
nsACString::const_iterator& aStart,
nsACString::const_iterator& aEnd)
{
// We copy the end iterator to keep the original pointing to the real end
// of the string.
nsACString::const_iterator end(aEnd);
const char* beginning = aStart.get();
if (FindInReadable(aBoundaryString, aStart, end)) {
// We either should find the body immediately, or after 2 chars with the
// 2 chars being '-', everything else is failure.
if ((aStart.get() - beginning) == 0) {
aStart.advance(aBoundaryString.Length());
return true;
}
if ((aStart.get() - beginning) == 2) {
if (*(--aStart) == '-' && *(--aStart) == '-') {
aStart.advance(aBoundaryString.Length() + 2);
return true;
}
}
}
return false;
}
// Reads over a CRLF and positions start after it.
bool
PushOverLine(nsACString::const_iterator& aStart)
{
if (*aStart == nsCRT::CR && (aStart.size_forward() > 1) && *(++aStart) == nsCRT::LF) {
++aStart; // advance to after CRLF
return true;
}
return false;
}
bool
FindCRLF(nsACString::const_iterator& aStart,
nsACString::const_iterator& aEnd)
{
nsACString::const_iterator end(aEnd);
return FindInReadable(NS_LITERAL_CSTRING("\r\n"), aStart, end);
}
bool
ParseHeader(nsACString::const_iterator& aStart,
nsACString::const_iterator& aEnd,
bool* aWasEmptyHeader)
{
MOZ_ASSERT(aWasEmptyHeader);
// Set it to a valid value here so we don't forget later.
*aWasEmptyHeader = false;
const char* beginning = aStart.get();
nsACString::const_iterator end(aEnd);
if (!FindCRLF(aStart, end)) {
return false;
}
if (aStart.get() == beginning) {
*aWasEmptyHeader = true;
return true;
}
nsAutoCString header(beginning, aStart.get() - beginning);
nsACString::const_iterator headerStart, headerEnd;
header.BeginReading(headerStart);
header.EndReading(headerEnd);
if (!FindCharInReadable(':', headerStart, headerEnd)) {
return false;
}
nsAutoCString headerName(StringHead(header, headerStart.size_backward()));
headerName.CompressWhitespace();
if (!NS_IsValidHTTPToken(headerName)) {
return false;
}
nsAutoCString headerValue(Substring(++headerStart, headerEnd));
if (!NS_IsReasonableHTTPHeaderValue(headerValue)) {
return false;
}
headerValue.CompressWhitespace();
if (headerName.LowerCaseEqualsLiteral("content-disposition")) {
nsCCharSeparatedTokenizer tokenizer(headerValue, ';');
bool seenFormData = false;
while (tokenizer.hasMoreTokens()) {
const nsDependentCSubstring& token = tokenizer.nextToken();
if (token.IsEmpty()) {
continue;
}
if (token.EqualsLiteral("form-data")) {
seenFormData = true;
continue;
}
if (seenFormData &&
StringBeginsWith(token, NS_LITERAL_CSTRING("name="))) {
mName = StringTail(token, token.Length() - 5);
mName.Trim(" \"");
continue;
}
if (seenFormData &&
StringBeginsWith(token, NS_LITERAL_CSTRING("filename="))) {
mFilename = StringTail(token, token.Length() - 9);
mFilename.Trim(" \"");
continue;
}
}
if (mName.IsVoid()) {
// Could not parse a valid entry name.
return false;
}
} else if (headerName.LowerCaseEqualsLiteral("content-type")) {
mContentType = headerValue;
}
return true;
}
// The end of a body is marked by a CRLF followed by the boundary. So the
// CRLF is part of the boundary and not the body, but any prior CRLFs are
// part of the body. This will position the iterator at the beginning of the
// boundary (after the CRLF).
bool
ParseBody(const nsACString& aBoundaryString,
nsACString::const_iterator& aStart,
nsACString::const_iterator& aEnd)
{
const char* beginning = aStart.get();
// Find the boundary marking the end of the body.
nsACString::const_iterator end(aEnd);
if (!FindInReadable(aBoundaryString, aStart, end)) {
return false;
}
// We found a boundary, strip the just prior CRLF, and consider
// everything else the body section.
if (aStart.get() - beginning < 2) {
// Only the first entry can have a boundary right at the beginning. Even
// an empty body will have a CRLF before the boundary. So this is
// a failure.
return false;
}
// Check that there is a CRLF right before the boundary.
aStart.advance(-2);
// Skip optional hyphens.
if (*aStart == '-' && *(aStart.get()+1) == '-') {
if (aStart.get() - beginning < 2) {
return false;
}
aStart.advance(-2);
}
if (*aStart != nsCRT::CR || *(aStart.get()+1) != nsCRT::LF) {
return false;
}
nsAutoCString body(beginning, aStart.get() - beginning);
// Restore iterator to after the \r\n as we promised.
// We do not need to handle the extra hyphens case since our boundary
// parser in PushOverBoundary()
aStart.advance(2);
if (!mFormData) {
mFormData = new nsFormData();
}
NS_ConvertUTF8toUTF16 name(mName);
if (mFilename.IsVoid()) {
mFormData->Append(name, NS_ConvertUTF8toUTF16(body));
} else {
// Unfortunately we've to copy the data first since all our strings are
// going to free it. We also need fallible alloc, so we can't just use
// ToNewCString().
char* copy = static_cast<char*>(NS_Alloc(body.Length()));
if (!copy) {
NS_WARNING("Failed to copy File entry body.");
return false;
}
nsCString::const_iterator bodyIter, bodyEnd;
body.BeginReading(bodyIter);
body.EndReading(bodyEnd);
char *p = copy;
while (bodyIter != bodyEnd) {
*p++ = *bodyIter++;
}
p = nullptr;
RefPtr<Blob> file =
File::CreateMemoryFile(mParentObject,
reinterpret_cast<void *>(copy), body.Length(),
NS_ConvertUTF8toUTF16(mFilename),
NS_ConvertUTF8toUTF16(mContentType), /* aLastModifiedDate */ 0);
Optional<nsAString> dummy;
mFormData->Append(name, *file, dummy);
}
return true;
}
public:
FormDataParser(const nsACString& aMimeType, const nsACString& aData, nsIGlobalObject* aParent)
: mMimeType(aMimeType), mData(aData), mState(START_PART), mParentObject(aParent)
{
}
bool
Parse()
{
// Determine boundary from mimetype.
const char* boundaryId = nullptr;
boundaryId = strstr(mMimeType.BeginWriting(), "boundary");
if (!boundaryId) {
return false;
}
boundaryId = strchr(boundaryId, '=');
if (!boundaryId) {
return false;
}
// Skip over '='.
boundaryId++;
char *attrib = (char *) strchr(boundaryId, ';');
if (attrib) *attrib = '\0';
nsAutoCString boundaryString(boundaryId);
if (attrib) *attrib = ';';
boundaryString.Trim(" \"");
if (boundaryString.Length() == 0) {
return false;
}
nsACString::const_iterator start, end;
mData.BeginReading(start);
// This should ALWAYS point to the end of data.
// Helpers make copies.
mData.EndReading(end);
while (start != end) {
switch(mState) {
case START_PART:
mName.SetIsVoid(true);
mFilename.SetIsVoid(true);
mContentType = NS_LITERAL_CSTRING("text/plain");
// MUST start with boundary.
if (!PushOverBoundary(boundaryString, start, end)) {
return false;
}
if (start != end && *start == '-') {
// End of data.
if (!mFormData) {
mFormData = new nsFormData();
}
return true;
}
if (!PushOverLine(start)) {
return false;
}
mState = PARSE_HEADER;
break;
case PARSE_HEADER:
bool emptyHeader;
if (!ParseHeader(start, end, &emptyHeader)) {
return false;
}
if (!PushOverLine(start)) {
return false;
}
mState = emptyHeader ? PARSE_BODY : PARSE_HEADER;
break;
case PARSE_BODY:
if (mName.IsVoid()) {
NS_WARNING("No content-disposition header with a valid name was "
"found. Failing at body parse.");
return false;
}
if (!ParseBody(boundaryString, start, end)) {
return false;
}
mState = START_PART;
break;
default:
MOZ_CRASH("Invalid case");
}
}
NS_NOTREACHED("Should never reach here.");
return false;
}
already_AddRefed<nsFormData> FormData()
{
return mFormData.forget();
}
};
} // namespace
nsresult
+412
View File
@@ -122,6 +122,418 @@ FetchUtil::ConsumeBlob(nsISupports* aParent, const nsString& aMimeType,
return blob.forget();
}
static bool
FindCRLF(nsACString::const_iterator& aStart,
nsACString::const_iterator& aEnd)
{
nsACString::const_iterator end(aEnd);
return FindInReadable(NS_LITERAL_CSTRING("\r\n"), aStart, end);
}
// Reads over a CRLF and positions start after it.
static bool
PushOverLine(nsACString::const_iterator& aStart)
{
if (*aStart == nsCRT::CR && (aStart.size_forward() > 1) && *(++aStart) == nsCRT::LF) {
++aStart; // advance to after CRLF
return true;
}
return false;
}
// static
bool
FetchUtil::ExtractHeader(nsACString::const_iterator& aStart,
nsACString::const_iterator& aEnd,
nsCString& aHeaderName,
nsCString& aHeaderValue,
bool* aWasEmptyHeader)
{
MOZ_ASSERT(aWasEmptyHeader);
// Set it to a valid value here so we don't forget later.
*aWasEmptyHeader = false;
const char* beginning = aStart.get();
nsACString::const_iterator end(aEnd);
if (!FindCRLF(aStart, end)) {
return false;
}
if (aStart.get() == beginning) {
*aWasEmptyHeader = true;
return true;
}
nsAutoCString header(beginning, aStart.get() - beginning);
nsACString::const_iterator headerStart, headerEnd;
header.BeginReading(headerStart);
header.EndReading(headerEnd);
if (!FindCharInReadable(':', headerStart, headerEnd)) {
return false;
}
aHeaderName.Assign(StringHead(header, headerStart.size_backward()));
aHeaderName.CompressWhitespace();
if (!NS_IsValidHTTPToken(aHeaderName)) {
return false;
}
aHeaderValue.Assign(Substring(++headerStart, headerEnd));
if (!NS_IsReasonableHTTPHeaderValue(aHeaderValue)) {
return false;
}
aHeaderValue.CompressWhitespace();
return PushOverLine(aStart);
}
namespace {
class MOZ_STACK_CLASS FillFormIterator final
: public URLSearchParams::ForEachIterator
{
public:
explicit FillFormIterator(nsFormData* aFormData)
: mFormData(aFormData)
{
MOZ_ASSERT(aFormData);
}
bool URLParamsIterator(const nsString& aName,
const nsString& aValue) override
{
mFormData->Append(aName, aValue);
return true;
}
private:
nsFormData* mFormData;
};
/**
* A simple multipart/form-data parser as defined in RFC 2388 and RFC 2046.
* This does not respect any encoding specified per entry, using UTF-8
* throughout. This is as the Fetch spec states in the consume body algorithm.
* Borrows some things from Necko's nsMultiMixedConv, but is simpler since
* unlike Necko we do not have to deal with receiving incomplete chunks of data.
*
* This parser will fail the entire parse on any invalid entry, so it will
* never return a partially filled FormData.
* The content-disposition header is used to figure out the name and filename
* entries. The inclusion of the filename parameter decides if the entry is
* inserted into the nsFormData as a string or a File.
*
* File blobs are copies of the underlying data string since we cannot adopt
* char* chunks embedded within the larger body without significant effort.
* FIXME(nsm): Bug 1127552 - We should add telemetry to calls to formData() and
* friends to figure out if Fetch ends up copying big blobs to see if this is
* worth optimizing.
*/
class MOZ_STACK_CLASS FormDataParser
{
private:
RefPtr<nsFormData> mFormData;
nsCString mMimeType;
nsCString mData;
// Entry state, reset in START_PART.
nsCString mName;
nsCString mFilename;
nsCString mContentType;
enum
{
START_PART,
PARSE_HEADER,
PARSE_BODY,
} mState;
nsIGlobalObject* mParentObject;
// Reads over a boundary and sets start to the position after the end of the
// boundary. Returns false if no boundary is found immediately.
bool
PushOverBoundary(const nsACString& aBoundaryString,
nsACString::const_iterator& aStart,
nsACString::const_iterator& aEnd)
{
// We copy the end iterator to keep the original pointing to the real end
// of the string.
nsACString::const_iterator end(aEnd);
const char* beginning = aStart.get();
if (FindInReadable(aBoundaryString, aStart, end)) {
// We either should find the body immediately, or after 2 chars with the
// 2 chars being '-', everything else is failure.
if ((aStart.get() - beginning) == 0) {
aStart.advance(aBoundaryString.Length());
return true;
}
if ((aStart.get() - beginning) == 2) {
if (*(--aStart) == '-' && *(--aStart) == '-') {
aStart.advance(aBoundaryString.Length() + 2);
return true;
}
}
}
return false;
}
bool
ParseHeader(nsACString::const_iterator& aStart,
nsACString::const_iterator& aEnd,
bool* aWasEmptyHeader)
{
nsAutoCString headerName, headerValue;
if (!FetchUtil::ExtractHeader(aStart, aEnd,
headerName, headerValue,
aWasEmptyHeader)) {
return false;
}
if (*aWasEmptyHeader) {
return true;
}
if (headerName.LowerCaseEqualsLiteral("content-disposition")) {
nsCCharSeparatedTokenizer tokenizer(headerValue, ';');
bool seenFormData = false;
while (tokenizer.hasMoreTokens()) {
const nsDependentCSubstring& token = tokenizer.nextToken();
if (token.IsEmpty()) {
continue;
}
if (token.EqualsLiteral("form-data")) {
seenFormData = true;
continue;
}
if (seenFormData &&
StringBeginsWith(token, NS_LITERAL_CSTRING("name="))) {
mName = StringTail(token, token.Length() - 5);
mName.Trim(" \"");
continue;
}
if (seenFormData &&
StringBeginsWith(token, NS_LITERAL_CSTRING("filename="))) {
mFilename = StringTail(token, token.Length() - 9);
mFilename.Trim(" \"");
continue;
}
}
if (mName.IsVoid()) {
// Could not parse a valid entry name.
return false;
}
} else if (headerName.LowerCaseEqualsLiteral("content-type")) {
mContentType = headerValue;
}
return true;
}
// The end of a body is marked by a CRLF followed by the boundary. So the
// CRLF is part of the boundary and not the body, but any prior CRLFs are
// part of the body. This will position the iterator at the beginning of the
// boundary (after the CRLF).
bool
ParseBody(const nsACString& aBoundaryString,
nsACString::const_iterator& aStart,
nsACString::const_iterator& aEnd)
{
const char* beginning = aStart.get();
// Find the boundary marking the end of the body.
nsACString::const_iterator end(aEnd);
if (!FindInReadable(aBoundaryString, aStart, end)) {
return false;
}
// We found a boundary, strip the just prior CRLF, and consider
// everything else the body section.
if (aStart.get() - beginning < 2) {
// Only the first entry can have a boundary right at the beginning. Even
// an empty body will have a CRLF before the boundary. So this is
// a failure.
return false;
}
// Check that there is a CRLF right before the boundary.
aStart.advance(-2);
// Skip optional hyphens.
if (*aStart == '-' && *(aStart.get()+1) == '-') {
if (aStart.get() - beginning < 2) {
return false;
}
aStart.advance(-2);
}
if (*aStart != nsCRT::CR || *(aStart.get()+1) != nsCRT::LF) {
return false;
}
nsAutoCString body(beginning, aStart.get() - beginning);
// Restore iterator to after the \r\n as we promised.
// We do not need to handle the extra hyphens case since our boundary
// parser in PushOverBoundary()
aStart.advance(2);
if (!mFormData) {
mFormData = new nsFormData();
}
NS_ConvertUTF8toUTF16 name(mName);
if (mFilename.IsVoid()) {
mFormData->Append(name, NS_ConvertUTF8toUTF16(body));
} else {
// Unfortunately we've to copy the data first since all our strings are
// going to free it. We also need fallible alloc, so we can't just use
// ToNewCString().
char* copy = static_cast<char*>(moz_xmalloc(body.Length()));
if (!copy) {
NS_WARNING("Failed to copy File entry body.");
return false;
}
nsCString::const_iterator bodyIter, bodyEnd;
body.BeginReading(bodyIter);
body.EndReading(bodyEnd);
char *p = copy;
while (bodyIter != bodyEnd) {
*p++ = *bodyIter++;
}
p = nullptr;
RefPtr<Blob> file =
File::CreateMemoryFile(mParentObject,
reinterpret_cast<void *>(copy), body.Length(),
NS_ConvertUTF8toUTF16(mFilename),
NS_ConvertUTF8toUTF16(mContentType), /* aLastModifiedDate */ 0);
Optional<nsAString> dummy;
mFormData->Append(name, *file, dummy);
}
return true;
}
public:
FormDataParser(const nsACString& aMimeType, const nsACString& aData, nsIGlobalObject* aParent)
: mMimeType(aMimeType), mData(aData), mState(START_PART), mParentObject(aParent)
{
}
bool
Parse()
{
// Determine boundary from mimetype.
const char* boundaryId = nullptr;
boundaryId = strstr(mMimeType.BeginWriting(), "boundary");
if (!boundaryId) {
return false;
}
boundaryId = strchr(boundaryId, '=');
if (!boundaryId) {
return false;
}
// Skip over '='.
boundaryId++;
char *attrib = (char *) strchr(boundaryId, ';');
if (attrib) *attrib = '\0';
nsAutoCString boundaryString(boundaryId);
if (attrib) *attrib = ';';
boundaryString.Trim(" \"");
if (boundaryString.Length() == 0) {
return false;
}
nsACString::const_iterator start, end;
mData.BeginReading(start);
// This should ALWAYS point to the end of data.
// Helpers make copies.
mData.EndReading(end);
while (start != end) {
switch(mState) {
case START_PART:
mName.SetIsVoid(true);
mFilename.SetIsVoid(true);
mContentType = NS_LITERAL_CSTRING("text/plain");
// MUST start with boundary.
if (!PushOverBoundary(boundaryString, start, end)) {
return false;
}
if (start != end && *start == '-') {
// End of data.
if (!mFormData) {
mFormData = new nsFormData();
}
return true;
}
if (!PushOverLine(start)) {
return false;
}
mState = PARSE_HEADER;
break;
case PARSE_HEADER:
bool emptyHeader;
if (!ParseHeader(start, end, &emptyHeader)) {
return false;
}
if (emptyHeader && !PushOverLine(start)) {
return false;
}
mState = emptyHeader ? PARSE_BODY : PARSE_HEADER;
break;
case PARSE_BODY:
if (mName.IsVoid()) {
NS_WARNING("No content-disposition header with a valid name was "
"found. Failing at body parse.");
return false;
}
if (!ParseBody(boundaryString, start, end)) {
return false;
}
mState = START_PART;
break;
default:
MOZ_CRASH("Invalid case");
}
}
NS_NOTREACHED("Should never reach here.");
return false;
}
already_AddRefed<nsFormData> FormData()
{
return mFormData.forget();
}
};
}
// static
already_AddRefed<nsFormData>
FetchUtil::ConsumeFormData(nsIGlobalObject* aParent, const nsCString& aMimeType,
+10
View File
@@ -65,6 +65,16 @@ public:
static void
ConsumeJson(JSContext* aCx, JS::MutableHandle<JS::Value> aValue,
const nsString& aStr, ErrorResult& aRv);
/**
* Extracts an HTTP header from a substring range.
*/
static bool
ExtractHeader(nsACString::const_iterator& aStart,
nsACString::const_iterator& aEnd,
nsCString& aHeaderName,
nsCString& aHeaderValue,
bool* aWasEmptyHeader);
};
} // namespace dom
+4 -5
View File
@@ -35,10 +35,9 @@ CreateGenericEvent(EventTarget* aOwner,
{
RefPtr<Event> event = new Event(aOwner, nullptr, nullptr);
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(
event->InitEvent(aType,
aBubbles == eDoesBubble ? true : false,
aCancelable == eCancelable ? true : false)));
event->InitEvent(aType,
aBubbles == eDoesBubble ? true : false,
aCancelable == eCancelable ? true : false);
event->SetTrusted(true);
@@ -58,7 +57,7 @@ IDBVersionChangeEvent::CreateInternal(EventTarget* aOwner,
event->mNewVersion.SetValue(aNewVersion.Value());
}
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(event->InitEvent(aType, false, false)));
event->InitEvent(aType, false, false);
event->SetTrusted(true);
@@ -11,7 +11,7 @@
* http://dev.w3.org/csswg/css3-animations/#animation-events-
*/
[builtinclass, uuid(b1bea1bc-689b-4e07-8cbc-ef342725f9a6)]
[builtinclass, uuid(772c7069-3f7d-42cf-97ab-b32f1c0b83da)]
interface nsIDOMAnimationEvent : nsIDOMEvent {
readonly attribute DOMString animationName;
readonly attribute float elapsedTime;
@@ -15,7 +15,7 @@
*
*/
[builtinclass, uuid(ee7b8943-440e-4cc3-b25e-c17c8a821d8b)]
[builtinclass, uuid(96abf41b-32a8-4ff6-a0d6-4ade4ddebf89)]
interface nsIDOMBeforeUnloadEvent : nsIDOMEvent
{
/**
@@ -8,7 +8,7 @@
interface nsIDOMDataTransfer;
[builtinclass, uuid(8D92944A-F2E5-41F4-9CF3-D85043B90CAC)]
[builtinclass, uuid(4ef84980-52c2-425c-b41a-2ee75ec5d497)]
interface nsIDOMClipboardEvent : nsIDOMEvent
{
readonly attribute nsIDOMDataTransfer clipboardData;
+1 -1
View File
@@ -5,7 +5,7 @@
#include "nsIDOMEvent.idl"
[builtinclass, uuid(3fdc07cb-3b2e-4c6e-a054-008a4f302202)]
[builtinclass, uuid(7efbe68a-811a-4159-801c-226948cfd08f)]
interface nsIDOMCommandEvent : nsIDOMEvent
{
readonly attribute DOMString command;
@@ -6,7 +6,7 @@
#include "nsIDOMUIEvent.idl"
[builtinclass, uuid(ef545b90-a5f4-471c-b4f8-03b5e0f6fda2)]
[builtinclass, uuid(5adfd99b-d3c7-4c6d-92d1-527264a71b50)]
interface nsIDOMCompositionEvent : nsIDOMUIEvent
{
readonly attribute DOMString data;
+1 -1
View File
@@ -6,7 +6,7 @@
#include "nsIDOMEvent.idl"
interface nsIVariant;
[builtinclass, uuid(b56ae6ca-c822-489e-be71-2a9f3c56082e)]
[builtinclass, uuid(55fa3a13-4812-45a7-98b7-3be6cec2df43)]
interface nsIDOMCustomEvent : nsIDOMEvent
{
@@ -6,7 +6,7 @@
#include "nsIDOMEvent.idl"
#include "nsIVariant.idl"
[builtinclass, uuid(dc6b39da-87ff-4b6f-b065-b52602602e06)]
[builtinclass, uuid(31ceb43e-5f49-43bf-9a18-3b60a535c814)]
interface nsIDOMDataContainerEvent : nsIDOMEvent
{
/**
+1 -1
View File
@@ -8,7 +8,7 @@
interface nsIDOMDataTransfer;
[builtinclass, uuid(4d0fe952-7ca7-4730-a163-4454e39ed187)]
[builtinclass, uuid(12aabbe9-7c70-4bf9-b133-a8d6a120679e)]
interface nsIDOMDragEvent : nsIDOMMouseEvent
{
readonly attribute nsIDOMDataTransfer dataTransfer;
+2 -1
View File
@@ -40,7 +40,7 @@ class EventTarget;
* http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
*/
[builtinclass, uuid(63857daf-c084-4ea6-a8b9-6812e3176991)]
[builtinclass, uuid(f58daacf-4d1a-4002-8fd7-06b614dfbcf6)]
interface nsIDOMEvent : nsISupports
{
// PhaseType
@@ -161,6 +161,7 @@ interface nsIDOMEvent : nsISupports
* @param cancelableArg Specifies whether or not the event's default
* action can be prevented.
*/
[notxpcom,nostdcall]
void initEvent(in DOMString eventTypeArg,
in boolean canBubbleArg,
in boolean cancelableArg);
+1 -1
View File
@@ -5,7 +5,7 @@
#include "nsIDOMUIEvent.idl"
[builtinclass, uuid(4faecbd6-1bcd-42d8-bc66-ec6b95050063)]
[builtinclass, uuid(f2606aee-1801-4e4c-9700-af99e435c02c)]
interface nsIDOMFocusEvent : nsIDOMUIEvent
{
readonly attribute nsIDOMEventTarget relatedTarget;
+1 -1
View File
@@ -5,7 +5,7 @@
#include "nsIDOMUIEvent.idl"
[builtinclass, uuid(d2b3e35f-8627-4732-a92d-cda54c8f8054)]
[builtinclass, uuid(f4082a63-73c0-49ad-86e0-c406a54573f7)]
interface nsIDOMKeyEvent : nsIDOMUIEvent
{
const unsigned long DOM_VK_CANCEL = 0x03;
+1 -1
View File
@@ -12,7 +12,7 @@
* For more information on this interface, please see
* http://www.whatwg.org/specs/web-apps/current-work/#messageevent
*/
[builtinclass, uuid(bb869a03-5fc0-4a1b-838a-342e5025fc05)]
[builtinclass, uuid(4408a2f5-614f-40a3-8786-e16bd3f74e32)]
interface nsIDOMMessageEvent : nsIDOMEvent
{
/**
+1 -1
View File
@@ -13,7 +13,7 @@
* http://www.w3.org/TR/DOM-Level-2-Events/
*/
[builtinclass, uuid(df068636-9a5b-11e3-b71f-2c27d728e7f9)]
[builtinclass, uuid(dbebc4be-75c9-47ca-aee8-0a8b4ae14a87)]
interface nsIDOMMouseEvent : nsIDOMUIEvent
{
readonly attribute long screenX;
@@ -5,7 +5,7 @@
#include "nsIDOMMouseEvent.idl"
[builtinclass, uuid(2bce5c03-5bed-4c22-8a6a-a3ac8f5563d7)]
[builtinclass, uuid(00404ebe-4598-4c4e-a60a-d7491922f9db)]
interface nsIDOMMouseScrollEvent : nsIDOMMouseEvent
{
const long HORIZONTAL_AXIS = 1;
@@ -5,7 +5,7 @@
#include "nsIDOMEvent.idl"
[builtinclass, uuid(982d9800-1402-46e5-8ad2-56fb0f4905ef)]
[builtinclass, uuid(df7e4cd9-e41f-4c8e-a764-2e3191d2f463)]
interface nsIDOMMutationEvent : nsIDOMEvent
{
const unsigned short MODIFICATION = 1;
@@ -12,7 +12,7 @@ interface nsIDOMPaintRequestList;
* event, which fires at a window when painting has happened in
* that window.
*/
[builtinclass, uuid(ef68f0d5-5b55-4198-9e59-a5e2c57d3adc)]
[builtinclass, uuid(550f660c-65a5-4e17-b828-3dbec7c44304)]
interface nsIDOMNotifyPaintEvent : nsIDOMEvent
{
/**
@@ -5,7 +5,7 @@
#include "nsIDOMUIEvent.idl"
[builtinclass, uuid(49ab3d1d-f549-4cdb-904c-f6b6d3a0ec9e)]
[builtinclass, uuid(05aaf2cf-27c3-4d3d-9e55-4c6a4cf700ec)]
interface nsIDOMScrollAreaEvent : nsIDOMUIEvent
{
// Scroll area client rect
@@ -99,7 +99,7 @@
* consuming events.
*/
[builtinclass, uuid(d78656ab-9d68-4f03-83f9-7c7bee071aa7)]
[builtinclass, uuid(1b9afbf0-2cf0-4a7b-99bc-cd35dbd5b637)]
interface nsIDOMSimpleGestureEvent : nsIDOMMouseEvent
{
/* Swipe direction constants */
@@ -11,7 +11,7 @@
* http://dev.w3.org/csswg/css3-transitions/#transition-events-
*/
[builtinclass, uuid(a37171e0-9f43-41ea-a25c-0b78a3329683)]
[builtinclass, uuid(acb69403-0dcb-4db0-9ffc-8a22cc56c4eb)]
interface nsIDOMTransitionEvent : nsIDOMEvent {
readonly attribute DOMString propertyName;
readonly attribute float elapsedTime;
+1 -1
View File
@@ -13,7 +13,7 @@
* http://www.w3.org/TR/DOM-Level-2-Events/
*/
[builtinclass, uuid(d73852f8-7bd6-477d-8233-117dbf83860b)]
[builtinclass, uuid(db058d10-1db9-4cf9-bb4c-483c304a137f)]
interface nsIDOMUIEvent : nsIDOMEvent
{
readonly attribute nsIDOMWindow view;
+1 -1
View File
@@ -6,7 +6,7 @@
#include "nsIDOMMouseEvent.idl"
[builtinclass, uuid(86e2b577-7e61-4ed5-8ddd-c1533bf07137)]
[builtinclass, uuid(f1ca2983-8559-43d1-be0e-1af8331755fd)]
interface nsIDOMWheelEvent : nsIDOMMouseEvent
{
const unsigned long DOM_DELTA_PIXEL = 0x00;
+1 -1
View File
@@ -13,7 +13,7 @@
* http://www.w3.org/TR/SVG/animate.html#InterfaceTimeEvent
*/
[builtinclass, uuid(4a5a5fa6-2783-4171-b8bb-cae4ab06e6ff)]
[builtinclass, uuid(7a1dc95e-2c05-4171-8bde-275f094dda1d)]
interface nsIDOMTimeEvent : nsIDOMEvent
{
readonly attribute long detail;
+1 -1
View File
@@ -11,7 +11,7 @@
#include "nsIDOMUIEvent.idl"
[builtinclass, uuid(2d5b6e19-74bb-40af-9aac-59a1e53e3fcc)]
[builtinclass, uuid(8aa1b009-4a88-4c85-bfba-87ee32fd789f)]
interface nsIDOMXULCommandEvent : nsIDOMUIEvent
{
/**
@@ -185,6 +185,26 @@ BadOpaqueRedirectInterception=A ServiceWorker passed an opaqueredirect Response
# LOCALIZATION NOTE: Do not translate "ServiceWorker" or "FetchEvent.preventDefault()".
InterceptionCanceled=ServiceWorker canceled network interception by calling FetchEvent.preventDefault().
# LOCALIZATION NOTE: Do not translate 'youtube'. %S values are origins, like https://domain.com:port
# LOCALIZATION NOTE: Do not translate "ServiceWorker", "Promise", or "FetchEvent.respondWith()".
InterceptionRejectedResponse=ServiceWorker passed a rejected Promise to FetchEvent.respondWith(). This typically means that the code that resolves the Promise has failed.
# LOCALIZATION NOTE: Do not translate "ServiceWorker". %S is a URL.
InterceptionFailedWithURL=Failed to load '%S'. A ServiceWorker intercepted the request and encountered an unexpected error.
# LOCALIZATION NOTE: Do not translate "ServiceWorker", "FetchEvent.respondWith()", "opaque", or "Response". %S is a URL.
OpaqueInterceptionDisabledWithURL=Failed to load '%S'. A ServiceWorker passed an opaque Response to FetchEvent.respondWith() while opaque interception is disabled.
# LOCALIZATION NOTE: Do not translate "ServiceWorker", "FetchEvent.respondWith()", "FetchEvent", "no-cors", "opaque", "Response", or "RequestMode". %1$S is a URL. %2$S is a RequestMode value.
BadOpaqueInterceptionRequestModeWithURL=Failed to load '%1$S'. A ServiceWorker passed an opaque Response to FetchEvent.respondWith() while handling a '%2$S' FetchEvent. Opaque Response objects are only valid when the RequestMode is 'no-cors'.
# LOCALIZATION NOTE: Do not translate "ServiceWorker", "Error", "Response", "FetchEvent.respondWith()", or "fetch()". %S is a URL.
InterceptedErrorResponseWithURL=Failed to load '%S'. A ServiceWorker passed an Error Response to FetchEvent.respondWith(). This typically means the ServiceWorker performed an invalid fetch() call.
# LOCALIZATION NOTE: Do not translate "ServiceWorker", "Response", "FetchEvent.respondWith()", or "Response.clone()". %S is a URL.
InterceptedUsedResponseWithURL=Failed to load '%S'. A ServiceWorker passed a used Response to FetchEvent.respondWith(). The body of a Response may only be read once. Use Response.clone() to access the body multiple times.
# LOCALIZATION NOTE: Do not translate "ServiceWorker", "opaqueredirect", "Response", "FetchEvent.respondWith()", or "FetchEvent". %s is a URL.
BadOpaqueRedirectInterceptionWithURL=Failed to load '%S'. A ServiceWorker passed an opaqueredirect Response to FetchEvent.respondWith() while handling a non-navigation FetchEvent.
# LOCALIZATION NOTE: Do not translate "ServiceWorker" or "FetchEvent.preventDefault()". %S is a URL.
InterceptionCanceledWithURL=Failed to load '%S'. A ServiceWorker canceled the load by calling FetchEvent.preventDefault().
# LOCALIZATION NOTE: Do not translate "ServiceWorker", "promise", or "FetchEvent.respondWith()". %1$S is a URL. %2$S is an error string.
InterceptionRejectedResponseWithURL=Failed to load '%1$S'. A ServiceWorker passed a promise to FetchEvent.respondWith() that rejected with '%2$S'.
# LOCALIZATION NOTE: Do not translate "ServiceWorker", "promise", "FetchEvent.respondWith()", or "Response". %1$S is a URL. %2$S is an error string.
InterceptedNonResponseWithURL=Failed to load '%1$S'. A ServiceWorker passed a promise to FetchEvent.respondWith() that resolved with non-Response value '%2$S'.
RewriteYoutubeEmbed=Rewriting old-style Youtube Flash embed (%S) to iframe embed (%S). Please update page to use iframe instead of embed/object, if possible.
# LOCALIZATION NOTE: Do not translate 'youtube'. %S values are origins, like https://domain.com:port
RewriteYoutubeEmbedInvalidQuery=Rewriting old-style Youtube Flash embed (%S) to iframe embed (%S). Query was invalid and removed from URL. Please update page to use iframe instead of embed/object, if possible.
+1 -7
View File
@@ -1042,13 +1042,7 @@ MediaRecorder::DispatchSimpleEvent(const nsAString & aStr)
}
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
rv = event->InitEvent(aStr, false, false);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to init the error event!!!");
return;
}
event->InitEvent(aStr, false, false);
event->SetTrusted(true);
rv = DispatchDOMEvent(nullptr, event, nullptr, nullptr);
+1 -6
View File
@@ -165,12 +165,7 @@ TextTrackList::CreateAndDispatchChangeEvent()
{
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
nsresult rv = event->InitEvent(NS_LITERAL_STRING("change"), false, false);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to init the change event!");
return;
}
event->InitEvent(NS_LITERAL_STRING("change"), false, false);
event->SetTrusted(true);
nsCOMPtr<nsIRunnable> eventRunner = new TrackEventRunner(this, event);
@@ -759,9 +759,8 @@ SpeechRecognition::DispatchError(EventType aErrorType,
RefPtr<SpeechRecognitionError> srError =
new SpeechRecognitionError(nullptr, nullptr, nullptr);
ErrorResult err;
srError->InitSpeechRecognitionError(NS_LITERAL_STRING("error"), true, false,
aErrorCode, aMessage, err);
aErrorCode, aMessage);
RefPtr<SpeechEvent> event = new SpeechEvent(this, aErrorType);
event->mError = srError;
+1 -1
View File
@@ -66,7 +66,7 @@ public:
return mPorts[aIndex];
}
public:
private:
nsCOMPtr<nsISupports> mOwner;
nsTArray<RefPtr<MessagePort>> mPorts;
};
+1 -2
View File
@@ -159,8 +159,7 @@ TCPServerSocket::OnStopListening(nsIServerSocket* aServer, nsresult aStatus)
{
if (aStatus != NS_BINDING_ABORTED) {
RefPtr<Event> event = new Event(GetOwner());
nsresult rv = event->InitEvent(NS_LITERAL_STRING("error"), false, false);
NS_ENSURE_SUCCESS(rv, rv);
event->InitEvent(NS_LITERAL_STRING("error"), false, false);
event->SetTrusted(true);
bool dummy;
DispatchEvent(event, &dummy);
+1 -4
View File
@@ -175,10 +175,7 @@ DesktopNotification::DispatchNotificationEvent(const nsString& aName)
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
// it doesn't bubble, and it isn't cancelable
nsresult rv = event->InitEvent(aName, false, false);
if (NS_FAILED(rv)) {
return;
}
event->InitEvent(aName, false, false);
event->SetTrusted(true);
DispatchDOMEvent(nullptr, event, nullptr, nullptr);
}
+1 -2
View File
@@ -1109,8 +1109,7 @@ Notification::DispatchClickEvent()
{
AssertIsOnTargetThread();
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
nsresult rv = event->InitEvent(NS_LITERAL_STRING("click"), false, true);
NS_ENSURE_SUCCESS(rv, false);
event->InitEvent(NS_LITERAL_STRING("click"), false, true);
event->SetTrusted(true);
WantsPopupControlCheck popupControlCheck(event);
bool doDefaultAction = true;
+75
View File
@@ -0,0 +1,75 @@
var state = "from_scope";
var resolvePromiseCallback;
onfetch = function(event) {
if (event.request.url.indexOf("lifetime_frame.html") >= 0) {
event.respondWith(new Response("iframe_lifetime"));
return;
}
var currentState = state;
event.waitUntil(
clients.matchAll()
.then(clients => {
clients.forEach(client => {
client.postMessage({type: "fetch", state: currentState});
});
})
);
if (event.request.url.indexOf("update") >= 0) {
state = "update";
} else if (event.request.url.indexOf("wait") >= 0) {
event.respondWith(new Promise(function(res, rej) {
if (resolvePromiseCallback) {
dump("ERROR: service worker was already waiting on a promise.\n");
}
resolvePromiseCallback = function() {
res(new Response("resolve_respondWithPromise"));
};
}));
state = "wait";
} else if (event.request.url.indexOf("release") >= 0) {
state = "release";
resolvePromise();
}
}
function resolvePromise() {
if (resolvePromiseCallback === undefined || resolvePromiseCallback == null) {
dump("ERROR: wait promise was not set.\n");
return;
}
resolvePromiseCallback();
resolvePromiseCallback = null;
}
onmessage = function(event) {
// FIXME(catalinb): we cannot treat these events as extendable
// yet. Bug 1143717
event.source.postMessage({type: "message", state: state});
state = event.data;
if (event.data === "release") {
resolvePromise();
}
}
onpush = function(event) {
// FIXME(catalinb): push message carry no data. So we assume the only
// push message we get is "wait"
clients.matchAll().then(function(client) {
if (client.length == 0) {
dump("ERROR: no clients to send the response to.\n");
}
client[0].postMessage({type: "push", state: state});
state = "wait";
event.waitUntil(new Promise(function(res, rej) {
if (resolvePromiseCallback) {
dump("ERROR: service worker was already waiting on a promise.\n");
}
resolvePromiseCallback = res;
}));
});
}
+7 -1
View File
@@ -5,6 +5,7 @@ support-files =
push-server.sjs
frame.html
webpush.js
lifetime_worker.js
[test_has_permissions.html]
skip-if = os == "android" || toolkit == "gonk"
@@ -20,5 +21,10 @@ skip-if = os == "android" || toolkit == "gonk"
skip-if = os == "android" || toolkit == "gonk"
[test_multiple_register_different_scope.html]
skip-if = os == "android" || toolkit == "gonk"
[test_try_registering_offline_disabled.html]
[test_data.html]
skip-if = os == "android" || toolkit == "gonk"
# Disabled for too many intermittent failures (bug 1164432)
# [test_try_registering_offline_disabled.html]
# skip-if = os == "android" || toolkit == "gonk"
[test_serviceworker_lifetime.html]
skip-if = os == "android" || toolkit == "gonk"
+186
View File
@@ -0,0 +1,186 @@
<!DOCTYPE HTML>
<html>
<!--
Bug 1185544: Add data delivery to the WebSocket backend.
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/licenses/publicdomain/
-->
<head>
<title>Test for Bug 1185544</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/dom/push/test/webpush.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
</head>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1185544">Mozilla Bug 1185544</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script class="testbody" type="text/javascript">
var registration;
function start() {
return navigator.serviceWorker.register("worker.js" + "?" + (Math.random()), {scope: "."})
.then(swr => { registration = swr; return swr; });
}
var controlledFrame;
function createControlledIFrame(swr) {
var p = new Promise(function(res, rej) {
var iframe = document.createElement('iframe');
iframe.id = "controlledFrame";
iframe.src = "http://mochi.test:8888/tests/dom/push/test/frame.html";
iframe.onload = function() {
res(swr)
}
controlledFrame = iframe;
document.body.appendChild(iframe);
});
return p;
}
function subscribe(swr) {
return swr.pushManager.subscribe();
}
function sendRequestToWorker(request) {
return new Promise((resolve, reject) => {
var channel = new MessageChannel();
channel.port1.onmessage = e => {
(e.data.error ? reject : resolve)(e.data);
};
registration.active.postMessage(request, [channel.port2]);
});
}
function comparePublicKey(pushSubscription) {
// FIXME(kitcambridge): Enable when `ServiceWorkerMessageEvent` is
// implemented (bug 1143717).
return Promise.resolve(pushSubscription);
/*
return sendRequestToWorker({ type: "publicKey" }).then(data => {
return registration.pushManager.getSubscription().then(
pushSubscription => {
isDeeply(pushSubscription.getKey("p256dh"), data,
"Mismatched key share");
return pushSubscription;
});
});
*/
}
function waitForMessage(pushSubscription, message) {
return Promise.all([
controlledFrame.contentWindow.waitOnPushMessage(pushSubscription),
webpush(pushSubscription, message),
]).then(([message]) => message);
}
function sendPushMessageFromPage(pushSubscription) {
var typedArray = new Uint8Array([226, 130, 40, 240, 40, 140, 188]);
var json = { hello: "world" };
return waitForMessage(pushSubscription, "Text message from page")
.then(message => {
is(message.data.text, "Text message from page", "Wrong text message data");
return waitForMessage(
pushSubscription,
typedArray
);
}).then(message => {
isDeeply(new Uint8Array(message.data.arrayBuffer), typedArray,
"Wrong array buffer message data");
return waitForMessage(
pushSubscription,
JSON.stringify(json)
);
}).then(message => {
ok(message.data.json.ok, "Unexpected error parsing JSON");
isDeeply(message.data.json.value, json, "Wrong JSON message data");
return waitForMessage(
pushSubscription,
""
);
}).then(message => {
ok(message, "Should include data for empty messages");
is(message.data.text, "", "Wrong text for empty message");
is(message.data.arrayBuffer.byteLength, 0, "Wrong buffer length for empty message");
ok(!message.data.json.ok, "Expected JSON parse error for empty message");
return waitForMessage(
pushSubscription,
new Uint8Array([0x48, 0x69, 0x21, 0x20, 0xf0, 0x9f, 0x91, 0x80])
);
}).then(message => {
is(message.data.text, "Hi! \ud83d\udc40", "Wrong text for message with emoji");
return new Promise((resolve, reject) => {
var reader = new FileReader();
reader.onloadend = event => {
if (reader.error) {
reject(reader.error);
} else {
resolve(reader.result);
}
};
reader.readAsText(message.data.blob);
});
}).then(text => {
is(text, "Hi! \ud83d\udc40", "Wrong blob data for message with emoji");
is(text, "Hi! \ud83d\udc40", "Wrong blob data for message with emoji");
// Send a blank message.
return Promise.all([
controlledFrame.contentWindow.waitOnPushMessage(pushSubscription),
fetch("http://mochi.test:8888/tests/dom/push/test/push-server.sjs", {
method: "PUT",
headers: {
"X-Push-Method": "POST",
"X-Push-Server": pushSubscription.endpoint,
},
}),
]).then(([message]) => message);
}).then(message => {
ok(!message.data, "Should exclude data for blank messages");
return pushSubscription;
});
}
function unsubscribe(pushSubscription) {
controlledFrame.parentNode.removeChild(controlledFrame);
controlledFrame = null;
return pushSubscription.unsubscribe();
}
function unregister() {
return registration.unregister();
}
function runTest() {
start()
.then(createControlledIFrame)
.then(subscribe)
.then(comparePublicKey)
.then(sendPushMessageFromPage)
.then(unsubscribe)
.then(unregister)
.catch(function(e) {
ok(false, "Some test failed with error " + e);
}).then(SimpleTest.finish);
}
SpecialPowers.pushPrefEnv({"set": [
["dom.push.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true]
]}, runTest);
SpecialPowers.addPermission("desktop-notification", true, document);
SimpleTest.waitForExplicitFinish();
</script>
</body>
</html>
@@ -0,0 +1,331 @@
<!DOCTYPE HTML>
<html>
<!--
Test the lifetime management of service workers. We keep this test in
dom/push/tests to pass the external network check when connecting to
the mozilla push service.
How this test works:
- the service worker maintains a state variable and a promise used for
extending its lifetime. Note that the terminating the worker will reset
these variables to their default values.
- we send 3 types of requests to the service worker:
|update|, |wait| and |release|. All three requests will cause the sw to update
its state to the new value and reply with a message containing
its previous state. Furthermore, |wait| will set a waitUntil or a respondWith
promise that's not resolved until the next |release| message.
- Each subtest will use a combination of values for the timeouts and check
if the service worker is in the correct state as we send it different
events.
- We also wait and assert for service worker termination using an event dispatched
through nsIObserverService.
-->
<head>
<title>Test for Bug 1188545</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
</head>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1188545">Mozilla Bug 118845</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
<script class="testbody" type="text/javascript">
function start() {
return navigator.serviceWorker.register("lifetime_worker.js", {scope: "./"})
.then((swr) => ({registration: swr}));
}
function waitForActiveServiceWorker(ctx) {
return navigator.serviceWorker.ready.then(function(result) {
ok(ctx.registration.active, "Service Worker is active");
return ctx;
});
}
function unregister(ctx) {
return ctx.registration.unregister().then(function(result) {
ok(result, "Unregister should return true.");
}, function(e) {
dump("Unregistering the SW failed with " + e + "\n");
});
}
function registerPushNotification(ctx) {
var p = new Promise(function(res, rej) {
ctx.registration.pushManager.subscribe().then(
function(pushSubscription) {
ok(true, "successful registered for push notification");
ctx.subscription = pushSubscription;
res(ctx);
}, function(error) {
ok(false, "could not register for push notification");
res(ctx);
});
});
return p;
}
function sendPushToPushServer(pushEndpoint) {
// Work around CORS for now.
var xhr = new XMLHttpRequest();
xhr.open('GET', "http://mochi.test:8888/tests/dom/push/test/push-server.sjs", true);
xhr.setRequestHeader("X-Push-Method", "PUT");
xhr.setRequestHeader("X-Push-Server", pushEndpoint);
xhr.send("version=24601");
}
function unregisterPushNotification(ctx) {
return ctx.subscription.unsubscribe().then(function(result) {
ok(result, "unsubscribe should succeed.");
ctx.subscription = null;
return ctx;
});
}
function createIframe(ctx) {
var p = new Promise(function(res, rej) {
var iframe = document.createElement('iframe');
// This file doesn't exist, the service worker will give us an empty
// document.
iframe.src = "http://mochi.test:8888/tests/dom/push/test/lifetime_frame.html";
iframe.onload = function() {
ctx.iframe = iframe;
res(ctx);
}
document.body.appendChild(iframe);
});
return p;
}
function closeIframe(ctx) {
ctx.iframe.parentNode.removeChild(ctx.iframe);
return new Promise(function(res, rej) {
// XXXcatalinb: give the worker more time to "notice" it stopped
// controlling documents
ctx.iframe = null;
setTimeout(res, 0);
}).then(() => ctx);
}
function waitAndCheckMessage(contentWindow, expected) {
function checkMessage(expected, resolve, event) {
ok(event.data.type == expected.type, "Received correct message type: " + expected.type);
ok(event.data.state == expected.state, "Service worker is in the correct state: " + expected.state);
this.navigator.serviceWorker.onmessage = null;
resolve();
}
return new Promise(function(res, rej) {
contentWindow.navigator.serviceWorker.onmessage =
checkMessage.bind(contentWindow, expected, res);
});
}
function fetchEvent(ctx, expected_state, new_state) {
var expected = { type: "fetch", state: expected_state };
var p = waitAndCheckMessage(ctx.iframe.contentWindow, expected);
ctx.iframe.contentWindow.fetch(new_state);
return p;
}
function pushEvent(ctx, expected_state, new_state) {
var expected = {type: "push", state: expected_state};
var p = waitAndCheckMessage(ctx.iframe.contentWindow, expected);
sendPushToPushServer(ctx.subscription.endpoint);
return p;
}
function messageEventIframe(ctx, expected_state, new_state) {
var expected = {type: "message", state: expected_state};
var p = waitAndCheckMessage(ctx.iframe.contentWindow, expected);
ctx.iframe.contentWindow.navigator.serviceWorker.controller.postMessage(new_state);
return p;
}
function messageEvent(ctx, expected_state, new_state) {
var expected = {type: "message", state: expected_state};
var p = waitAndCheckMessage(window, expected);
ctx.registration.active.postMessage(new_state);
return p;
}
function checkStateAndUpdate(eventFunction, expected_state, new_state) {
return function(ctx) {
return eventFunction(ctx, expected_state, new_state)
.then(() => ctx);
}
}
function setShutdownObserver(expectingEvent) {
return function(ctx) {
cancelShutdownObserver(ctx);
ctx.observer_promise = new Promise(function(res, rej) {
ctx.observer = {
observe: function(subject, topic, data) {
ok((topic == "service-worker-shutdown") && expectingEvent, "Service worker was terminated.");
this.remove(ctx);
},
remove: function(ctx) {
SpecialPowers.removeObserver(this, "service-worker-shutdown");
ctx.observer = null;
res(ctx);
}
}
SpecialPowers.addObserver(ctx.observer, "service-worker-shutdown", false);
});
return ctx;
}
}
function waitOnShutdownObserver(ctx) {
return ctx.observer_promise;
}
function cancelShutdownObserver(ctx) {
if (ctx.observer) {
ctx.observer.remove(ctx);
}
return ctx.observer_promise;
}
function subTest(test) {
return function(ctx) {
return new Promise(function(res, rej) {
function run() {
test.steps(ctx).catch(function(e) {
ok(false, "Some test failed with error: " + e);
}).then((ctx) => res(ctx));
}
SpecialPowers.pushPrefEnv({"set" : test.prefs}, run);
});
}
}
var test1 = {
prefs: [
["dom.serviceWorkers.idle_timeout", 0],
["dom.serviceWorkers.idle_extended_timeout", 2999999]
],
// Test that service workers are terminated after the grace period expires
// when there are no pending waitUntil or respondWith promises.
steps: function(ctx) {
// Test with fetch events and respondWith promises
return createIframe(ctx)
.then(setShutdownObserver(true))
.then(checkStateAndUpdate(fetchEvent, "from_scope", "update"))
.then(waitOnShutdownObserver)
.then(setShutdownObserver(false))
.then(checkStateAndUpdate(fetchEvent, "from_scope", "wait"))
.then(checkStateAndUpdate(fetchEvent, "wait", "update"))
.then(checkStateAndUpdate(fetchEvent, "update", "update"))
.then(setShutdownObserver(true))
// The service worker should be terminated when the promise is resolved.
.then(checkStateAndUpdate(fetchEvent, "update", "release"))
.then(waitOnShutdownObserver)
.then(setShutdownObserver(false))
.then(closeIframe)
.then(cancelShutdownObserver)
// Test with push events and message events
.then(createIframe)
.then(setShutdownObserver(false))
.then(checkStateAndUpdate(pushEvent, "from_scope", "wait"))
.then(setShutdownObserver(true))
.then(checkStateAndUpdate(messageEventIframe, "wait", "update"))
.then(waitOnShutdownObserver)
.then(closeIframe)
}
}
var test2 = {
prefs: [
["dom.serviceWorkers.idle_timeout", 0],
["dom.serviceWorkers.idle_extended_timeout", 2999999]
],
steps: function(ctx) {
// Non push workers are terminated when they stop controlling documents.
return createIframe(ctx)
.then(setShutdownObserver(true))
.then(checkStateAndUpdate(fetchEvent, "from_scope", "wait"))
.then(closeIframe)
.then(waitOnShutdownObserver)
// Push workers are exempt from this rule.
.then(createIframe)
.then(setShutdownObserver(false))
.then(checkStateAndUpdate(pushEvent, "from_scope", "wait"))
.then(closeIframe)
.then(setShutdownObserver(true))
.then(checkStateAndUpdate(messageEvent, "wait", "release"))
.then(waitOnShutdownObserver)
}
};
var test3 = {
prefs: [
["dom.serviceWorkers.idle_timeout", 2999999],
["dom.serviceWorkers.idle_extended_timeout", 0]
],
steps: function(ctx) {
// set the grace period to 0 and dispatch a message which will reset
// the internal sw timer to the new value.
var test3_1 = {
prefs: [
["dom.serviceWorkers.idle_timeout", 0]
],
steps: function(ctx) {
return new Promise(function(res, rej) {
ctx.registration.active.postMessage("update");
res(ctx);
});
}
}
// Test that service worker is closed when the extended timeout expired
return createIframe(ctx)
.then(setShutdownObserver(false))
.then(checkStateAndUpdate(messageEvent, "from_scope", "update"))
.then(checkStateAndUpdate(messageEventIframe, "update", "update"))
.then(checkStateAndUpdate(fetchEvent, "update", "wait"))
.then(setShutdownObserver(true))
.then(subTest(test3_1)) // This should cause the internal timer to expire.
.then(waitOnShutdownObserver)
.then(closeIframe)
}
}
function runTest() {
start()
.then(waitForActiveServiceWorker)
.then(registerPushNotification)
.then(subTest(test1))
.then(subTest(test2))
.then(subTest(test3))
.then(unregisterPushNotification)
.then(unregister)
.catch(function(e) {
ok(false, "Some test failed with error " + e)
}).then(SimpleTest.finish);
}
SpecialPowers.pushPrefEnv({"set": [
["dom.push.enabled", true],
["dom.serviceWorkers.exemptFromPerDomainMax", true],
["dom.serviceWorkers.enabled", true],
["dom.serviceWorkers.testing.enabled", true],
["dom.serviceWorkers.interception.enabled", true]
]}, runTest);
SpecialPowers.addPermission('push', true, document);
SimpleTest.waitForExplicitFinish();
</script>
</body>
</html>
+21 -9
View File
@@ -10,7 +10,7 @@
NS_IMPL_ISUPPORTS(nsContentSecurityManager, nsIContentSecurityManager)
nsresult
static nsresult
ValidateSecurityFlags(nsILoadInfo* aLoadInfo)
{
nsSecurityFlags securityMode = aLoadInfo->GetSecurityMode();
@@ -43,7 +43,7 @@ static bool SchemeIs(nsIURI* aURI, const char* aScheme)
return NS_SUCCEEDED(baseURI->SchemeIs(aScheme, &isScheme)) && isScheme;
}
nsresult
static nsresult
DoCheckLoadURIChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
{
nsresult rv = NS_OK;
@@ -73,11 +73,23 @@ DoCheckLoadURIChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
return NS_OK;
}
nsresult
static bool
URIHasFlags(nsIURI* aURI, uint32_t aURIFlags)
{
bool hasFlags;
nsresult rv = NS_URIChainHasFlags(aURI, aURIFlags, &hasFlags);
NS_ENSURE_SUCCESS(rv, false);
return hasFlags;
}
static nsresult
DoSOPChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
{
if (aLoadInfo->GetAllowChrome() && SchemeIs(aURI, "chrome")) {
// Enforce same-origin policy, except to chrome.
if (aLoadInfo->GetAllowChrome() &&
(URIHasFlags(aURI, nsIProtocolHandler::URI_IS_UI_RESOURCE) ||
SchemeIs(aURI, "moz-safe-about"))) {
// UI resources are allowed.
return DoCheckLoadURIChecks(aURI, aLoadInfo);
}
@@ -96,11 +108,11 @@ DoSOPChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
sameOriginDataInherits);
}
nsresult
static nsresult
DoCORSChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo,
nsCOMPtr<nsIStreamListener>& aInAndOutListener)
{
MOZ_ASSERT(aInAndOutListener, "can not perform CORS checks without a listener");
MOZ_RELEASE_ASSERT(aInAndOutListener, "can not perform CORS checks without a listener");
// No need to set up CORS if TriggeringPrincipal is the SystemPrincipal.
// For example, allow user stylesheets to load XBL from external files
@@ -123,7 +135,7 @@ DoCORSChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo,
return NS_OK;
}
nsresult
static nsresult
DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
{
nsContentPolicyType contentPolicyType =
@@ -285,7 +297,7 @@ DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
}
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType,
nsresult rv = NS_CheckContentLoadPolicy(internalContentPolicyType,
aURI,
aLoadInfo->LoadingPrincipal(),
requestingContext,
+2 -3
View File
@@ -64,9 +64,8 @@ TimeEvent::InitTimeEvent(const nsAString& aTypeArg,
nsIDOMWindow* aViewArg,
int32_t aDetailArg)
{
nsresult rv = Event::InitEvent(aTypeArg, false /*doesn't bubble*/,
false /*can't cancel*/);
NS_ENSURE_SUCCESS(rv, rv);
Event::InitEvent(aTypeArg, false /*doesn't bubble*/,
false /*can't cancel*/);
mDetail = aDetailArg;
mView = aViewArg;
-6
View File
@@ -47,12 +47,6 @@ public:
return mView;
}
void InitTimeEvent(const nsAString& aType, nsIDOMWindow* aView,
int32_t aDetail, ErrorResult& aRv)
{
aRv = InitTimeEvent(aType, aView, aDetail);
}
private:
~TimeEvent() {}
+1 -3
View File
@@ -390,15 +390,13 @@ nsDeviceSensors::FireDOMMotionEvent(nsIDOMDocument *domdoc,
DeviceMotionEvent* me = static_cast<DeviceMotionEvent*>(event.get());
ErrorResult rv;
me->InitDeviceMotionEvent(NS_LITERAL_STRING("devicemotion"),
true,
false,
*mLastAcceleration,
*mLastAccelerationIncludingGravity,
*mLastRotationRate,
Nullable<double>(DEFAULT_SENSOR_POLL),
rv);
Nullable<double>(DEFAULT_SENSOR_POLL));
event->SetTrusted(true);
-1
View File
@@ -17,7 +17,6 @@ interface CompositionEvent : UIEvent
partial interface CompositionEvent
{
[Throws]
void initCompositionEvent(DOMString typeArg,
boolean canBubbleArg,
boolean cancelableArg,
-1
View File
@@ -47,7 +47,6 @@ dictionary DeviceMotionEventInit : EventInit {
// Mozilla extensions.
partial interface DeviceMotionEvent {
[Throws]
void initDeviceMotionEvent(DOMString type,
boolean canBubble,
boolean cancelable,
-1
View File
@@ -13,7 +13,6 @@ interface DeviceOrientationEvent : Event
readonly attribute boolean absolute;
// initDeviceOrientationEvent is a Gecko specific deprecated method.
[Throws]
void initDeviceOrientationEvent(DOMString type,
boolean canBubble,
boolean cancelable,
-1
View File
@@ -9,7 +9,6 @@ interface DragEvent : MouseEvent
{
readonly attribute DataTransfer? dataTransfer;
[Throws]
void initDragEvent(DOMString type,
boolean canBubble,
boolean cancelable,
-1
View File
@@ -45,7 +45,6 @@ interface Event {
[Pure]
readonly attribute DOMHighResTimeStamp timeStamp;
[Throws]
void initEvent(DOMString type, boolean bubbles, boolean cancelable);
attribute boolean cancelBubble;
};
+43
View File
@@ -0,0 +1,43 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* For more information on this interface, please see
* http://www.whatwg.org/specs/web-apps/current-work/#messageevent
*/
[Constructor(DOMString type, optional ExtendableMessageEventInit eventInitDict),
Exposed=(ServiceWorker)]
interface ExtendableMessageEvent : ExtendableEvent {
/**
* Custom data associated with this event.
*/
[GetterThrows]
readonly attribute any data;
/**
* The origin of the site from which this event originated.
*/
readonly attribute DOMString origin;
/**
* The last event ID string of the event source.
*/
readonly attribute DOMString lastEventId;
/**
* The client, service worker or port which originated this event.
*/
readonly attribute (Client or ServiceWorker or MessagePort)? source;
readonly attribute MessagePortList? ports;
};
dictionary ExtendableMessageEventInit : ExtendableEventInit {
any data;
DOMString origin = "";
DOMString lastEventId = "";
(Client or ServiceWorker or MessagePort)? source;
sequence<MessagePort>? ports;
};
+3 -7
View File
@@ -10,11 +10,8 @@
[Constructor(DOMString type, optional FetchEventInit eventInitDict),
Func="mozilla::dom::workers::ServiceWorkerVisible",
Exposed=(ServiceWorker)]
interface FetchEvent : Event {
readonly attribute Request request;
// https://github.com/slightlyoff/ServiceWorker/issues/631
readonly attribute Client? client; // The window issuing the request.
interface FetchEvent : ExtendableEvent {
[SameObject] readonly attribute Request? request;
readonly attribute boolean isReload;
[Throws]
@@ -23,6 +20,5 @@ interface FetchEvent : Event {
dictionary FetchEventInit : EventInit {
Request request;
Client client;
boolean isReload;
boolean isReload = false;
};
-1
View File
@@ -10,7 +10,6 @@ interface HashChangeEvent : Event
readonly attribute DOMString? oldURL;
readonly attribute DOMString? newURL;
[Throws]
void initHashChangeEvent(DOMString typeArg,
boolean canBubbleArg,
boolean cancelableArg,
-1
View File
@@ -224,7 +224,6 @@ interface KeyEvent
// for compatibility with the other web browsers on Windows.
const unsigned long DOM_VK_WIN_OEM_CLEAR = 0xFE;
[Throws]
void initKeyEvent(DOMString type,
boolean canBubble,
boolean cancelable,
+7 -5
View File
@@ -31,12 +31,9 @@ interface MessageEvent : Event {
readonly attribute DOMString lastEventId;
/**
* The window, port or client which originated this event.
* FIXME(catalinb): Update this when the spec changes are implemented.
* https://www.w3.org/Bugs/Public/show_bug.cgi?id=28199
* https://bugzilla.mozilla.org/show_bug.cgi?id=1143717
* The window or port which originated this event.
*/
readonly attribute (WindowProxy or MessagePort or Client)? source;
readonly attribute (WindowProxy or MessagePort)? source;
/**
* Initializes this event with the given data, in a manner analogous to
@@ -44,6 +41,11 @@ interface MessageEvent : Event {
* data, origin, source, and lastEventId attributes of this appropriately.
*/
readonly attribute MessagePortList? ports;
void initMessageEvent(DOMString type, boolean bubbles, boolean cancelable,
any data, DOMString origin, DOMString lastEventId,
(WindowProxy or MessagePort)? source,
sequence<MessagePort>? ports);
};
dictionary MessageEventInit : EventInit {
-2
View File
@@ -32,7 +32,6 @@ interface MouseEvent : UIEvent {
readonly attribute long movementY;
// Deprecated in DOM Level 3:
[Throws]
void initMouseEvent(DOMString typeArg,
boolean canBubbleArg,
boolean cancelableArg,
@@ -91,7 +90,6 @@ partial interface MouseEvent
readonly attribute unsigned short mozInputSource;
[Throws]
void initNSMouseEvent(DOMString typeArg,
boolean canBubbleArg,
boolean cancelableArg,
-1
View File
@@ -11,7 +11,6 @@ interface MouseScrollEvent : MouseEvent
readonly attribute long axis;
[Throws]
void initMouseScrollEvent(DOMString type,
boolean canBubble,
boolean cancelable,
-1
View File
@@ -11,7 +11,6 @@ interface ScrollAreaEvent : UIEvent
readonly attribute float width;
readonly attribute float height;
[Throws]
void initScrollAreaEvent(DOMString type,
boolean canBubble,
boolean cancelable,
-1
View File
@@ -24,7 +24,6 @@ interface SimpleGestureEvent : MouseEvent
readonly attribute unsigned long clickCount;
[Throws]
void initSimpleGestureEvent(DOMString typeArg,
boolean canBubbleArg,
boolean cancelableArg,
-1
View File
@@ -20,7 +20,6 @@ interface StorageEvent : Event
readonly attribute Storage? storageArea;
// Bug 1016053 - This is not spec compliant.
[Throws]
void initStorageEvent(DOMString type,
boolean canBubble,
boolean cancelable,

Some files were not shown because too many files have changed in this diff Show More