mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 13:43:44 +00:00
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:
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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': {
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -46,8 +46,7 @@ public:
|
||||
|
||||
void InitClipboardEvent(const nsAString& aType, bool aCanBubble,
|
||||
bool aCancelable,
|
||||
DataTransfer* aClipboardData,
|
||||
ErrorResult& aError);
|
||||
DataTransfer* aClipboardData);
|
||||
|
||||
protected:
|
||||
~ClipboardEvent() {}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -49,8 +49,7 @@ public:
|
||||
bool aCanBubble,
|
||||
bool aCancelable,
|
||||
SpeechRecognitionErrorCode aError,
|
||||
const nsAString& aMessage,
|
||||
ErrorResult& aRv);
|
||||
const nsAString& aMessage);
|
||||
|
||||
protected:
|
||||
SpeechRecognitionErrorCode mError;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
return mPorts[aIndex];
|
||||
}
|
||||
|
||||
public:
|
||||
private:
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
nsTArray<RefPtr<MessagePort>> mPorts;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}));
|
||||
});
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ interface CompositionEvent : UIEvent
|
||||
|
||||
partial interface CompositionEvent
|
||||
{
|
||||
[Throws]
|
||||
void initCompositionEvent(DOMString typeArg,
|
||||
boolean canBubbleArg,
|
||||
boolean cancelableArg,
|
||||
|
||||
@@ -47,7 +47,6 @@ dictionary DeviceMotionEventInit : EventInit {
|
||||
|
||||
// Mozilla extensions.
|
||||
partial interface DeviceMotionEvent {
|
||||
[Throws]
|
||||
void initDeviceMotionEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -9,7 +9,6 @@ interface DragEvent : MouseEvent
|
||||
{
|
||||
readonly attribute DataTransfer? dataTransfer;
|
||||
|
||||
[Throws]
|
||||
void initDragEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
|
||||
@@ -45,7 +45,6 @@ interface Event {
|
||||
[Pure]
|
||||
readonly attribute DOMHighResTimeStamp timeStamp;
|
||||
|
||||
[Throws]
|
||||
void initEvent(DOMString type, boolean bubbles, boolean cancelable);
|
||||
attribute boolean cancelBubble;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -10,7 +10,6 @@ interface HashChangeEvent : Event
|
||||
readonly attribute DOMString? oldURL;
|
||||
readonly attribute DOMString? newURL;
|
||||
|
||||
[Throws]
|
||||
void initHashChangeEvent(DOMString typeArg,
|
||||
boolean canBubbleArg,
|
||||
boolean cancelableArg,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -11,7 +11,6 @@ interface MouseScrollEvent : MouseEvent
|
||||
|
||||
readonly attribute long axis;
|
||||
|
||||
[Throws]
|
||||
void initMouseScrollEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
|
||||
@@ -11,7 +11,6 @@ interface ScrollAreaEvent : UIEvent
|
||||
readonly attribute float width;
|
||||
readonly attribute float height;
|
||||
|
||||
[Throws]
|
||||
void initScrollAreaEvent(DOMString type,
|
||||
boolean canBubble,
|
||||
boolean cancelable,
|
||||
|
||||
@@ -24,7 +24,6 @@ interface SimpleGestureEvent : MouseEvent
|
||||
|
||||
readonly attribute unsigned long clickCount;
|
||||
|
||||
[Throws]
|
||||
void initSimpleGestureEvent(DOMString typeArg,
|
||||
boolean canBubbleArg,
|
||||
boolean cancelableArg,
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user