summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dom/fetch/FetchController.cpp110
-rw-r--r--dom/fetch/FetchController.h66
-rw-r--r--dom/fetch/FetchSignal.cpp72
-rw-r--r--dom/fetch/FetchSignal.h47
-rw-r--r--dom/fetch/Request.h1
-rw-r--r--dom/fetch/moz.build4
-rw-r--r--dom/tests/mochitest/fetch/file_fetch_controller.html40
-rw-r--r--dom/tests/mochitest/fetch/mochitest.ini2
-rw-r--r--dom/tests/mochitest/fetch/test_fetch_controller.html40
-rw-r--r--dom/webidl/FetchController.webidl15
-rw-r--r--dom/webidl/FetchSignal.webidl13
-rw-r--r--dom/webidl/Request.webidl3
-rw-r--r--dom/webidl/moz.build2
-rw-r--r--dom/workers/WorkerPrefs.h1
14 files changed, 416 insertions, 0 deletions
diff --git a/dom/fetch/FetchController.cpp b/dom/fetch/FetchController.cpp
new file mode 100644
index 000000000..b3d8a4d9c
--- /dev/null
+++ b/dom/fetch/FetchController.cpp
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#include "FetchController.h"
+#include "FetchSignal.h"
+#include "mozilla/dom/FetchControllerBinding.h"
+#include "WorkerPrivate.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(FetchController, mGlobal, mSignal)
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(FetchController)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(FetchController)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FetchController)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+ NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+/* static */ bool
+FetchController::IsEnabled(JSContext* aCx, JSObject* aGlobal)
+{
+ if (NS_IsMainThread()) {
+ return Preferences::GetBool("dom.fetchController.enabled", false);
+ }
+
+ using namespace workers;
+
+ // Otherwise, check the pref via the WorkerPrivate
+ WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
+ if (!workerPrivate) {
+ return false;
+ }
+
+ return workerPrivate->FetchControllerEnabled();
+}
+
+/* static */ already_AddRefed<FetchController>
+FetchController::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
+{
+ nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
+ if (!global) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return nullptr;
+ }
+
+ RefPtr<FetchController> fetchController = new FetchController(global);
+ return fetchController.forget();
+}
+
+FetchController::FetchController(nsIGlobalObject* aGlobal)
+ : mGlobal(aGlobal)
+ , mAborted(false)
+{}
+
+JSObject*
+FetchController::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+ return FetchControllerBinding::Wrap(aCx, this, aGivenProto);
+}
+
+nsIGlobalObject*
+FetchController::GetParentObject() const
+{
+ return mGlobal;
+}
+
+FetchSignal*
+FetchController::Signal()
+{
+ if (!mSignal) {
+ mSignal = new FetchSignal(this, mAborted);
+ }
+
+ return mSignal;
+}
+
+void
+FetchController::Abort()
+{
+ if (mAborted) {
+ return;
+ }
+
+ mAborted = true;
+
+ if (mSignal) {
+ mSignal->Abort();
+ }
+}
+
+void
+FetchController::Follow(FetchSignal& aSignal)
+{
+ // TODO
+}
+
+void
+FetchController::Unfollow(FetchSignal& aSignal)
+{
+ // TODO
+}
+
+} // dom namespace
+} // mozilla namespace
diff --git a/dom/fetch/FetchController.h b/dom/fetch/FetchController.h
new file mode 100644
index 000000000..854c6f974
--- /dev/null
+++ b/dom/fetch/FetchController.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_dom_FetchController_h
+#define mozilla_dom_FetchController_h
+
+#include "mozilla/dom/BindingDeclarations.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsWrapperCache.h"
+#include "mozilla/ErrorResult.h"
+#include "nsIGlobalObject.h"
+
+namespace mozilla {
+namespace dom {
+
+class FetchSignal;
+
+class FetchController final : public nsISupports
+ , public nsWrapperCache
+{
+public:
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(FetchController)
+
+ static bool
+ IsEnabled(JSContext* aCx, JSObject* aGlobal);
+
+ static already_AddRefed<FetchController>
+ Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
+
+ explicit FetchController(nsIGlobalObject* aGlobal);
+
+ JSObject*
+ WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
+
+ nsIGlobalObject*
+ GetParentObject() const;
+
+ FetchSignal*
+ Signal();
+
+ void
+ Abort();
+
+ void
+ Follow(FetchSignal& aSignal);
+
+ void
+ Unfollow(FetchSignal& aSignal);
+
+private:
+ ~FetchController() = default;
+
+ nsCOMPtr<nsIGlobalObject> mGlobal;
+ RefPtr<FetchSignal> mSignal;
+
+ bool mAborted;
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_FetchController_h
diff --git a/dom/fetch/FetchSignal.cpp b/dom/fetch/FetchSignal.cpp
new file mode 100644
index 000000000..4395dbcf2
--- /dev/null
+++ b/dom/fetch/FetchSignal.cpp
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#include "FetchSignal.h"
+#include "FetchController.h"
+#include "mozilla/dom/Event.h"
+#include "mozilla/dom/FetchSignalBinding.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(FetchSignal)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(FetchSignal,
+ DOMEventTargetHelper)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mController)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(FetchSignal,
+ DOMEventTargetHelper)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mController)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FetchSignal)
+NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
+
+NS_IMPL_ADDREF_INHERITED(FetchSignal, DOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(FetchSignal, DOMEventTargetHelper)
+
+FetchSignal::FetchSignal(FetchController* aController,
+ bool aAborted)
+ : DOMEventTargetHelper(aController->GetParentObject())
+ , mController(aController)
+ , mAborted(aAborted)
+{}
+
+JSObject*
+FetchSignal::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+ return FetchSignalBinding::Wrap(aCx, this, aGivenProto);
+}
+
+bool
+FetchSignal::Aborted() const
+{
+ return mAborted;
+}
+
+void
+FetchSignal::Abort()
+{
+ MOZ_ASSERT(!mAborted);
+ mAborted = true;
+
+ EventInit init;
+ init.mBubbles = false;
+ init.mCancelable = false;
+
+ // TODO which kind of event should we dispatch here?
+
+ RefPtr<Event> event =
+ Event::Constructor(this, NS_LITERAL_STRING("abort"), init);
+ event->SetTrusted(true);
+
+ DispatchDOMEvent(nullptr, event, nullptr, nullptr);
+}
+
+} // dom namespace
+} // mozilla namespace
diff --git a/dom/fetch/FetchSignal.h b/dom/fetch/FetchSignal.h
new file mode 100644
index 000000000..5bb16b834
--- /dev/null
+++ b/dom/fetch/FetchSignal.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_dom_FetchSignal_h
+#define mozilla_dom_FetchSignal_h
+
+#include "mozilla/DOMEventTargetHelper.h"
+
+namespace mozilla {
+namespace dom {
+
+class FetchController;
+
+class FetchSignal final : public DOMEventTargetHelper
+{
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(FetchSignal, DOMEventTargetHelper)
+
+ FetchSignal(FetchController* aController, bool aAborted);
+
+ JSObject*
+ WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
+
+ bool
+ Aborted() const;
+
+ void
+ Abort();
+
+ IMPL_EVENT_HANDLER(abort);
+
+private:
+ ~FetchSignal() = default;
+
+ RefPtr<FetchController> mController;
+
+ bool mAborted;
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_FetchSignal_h
diff --git a/dom/fetch/Request.h b/dom/fetch/Request.h
index d33c74812..56a75e5af 100644
--- a/dom/fetch/Request.h
+++ b/dom/fetch/Request.h
@@ -12,6 +12,7 @@
#include "nsWrapperCache.h"
#include "mozilla/dom/Fetch.h"
+#include "mozilla/dom/FetchSignal.h"
#include "mozilla/dom/InternalRequest.h"
// Required here due to certain WebIDL enums/classes being declared in both
// files.
diff --git a/dom/fetch/moz.build b/dom/fetch/moz.build
index be820ab57..757f857f2 100644
--- a/dom/fetch/moz.build
+++ b/dom/fetch/moz.build
@@ -7,8 +7,10 @@
EXPORTS.mozilla.dom += [
'ChannelInfo.h',
'Fetch.h',
+ 'FetchController.h',
'FetchDriver.h',
'FetchIPCTypes.h',
+ 'FetchSignal.h',
'FetchUtil.h',
'Headers.h',
'InternalHeaders.h',
@@ -27,7 +29,9 @@ UNIFIED_SOURCES += [
SOURCES += [
'ChannelInfo.cpp',
+ 'FetchController.cpp',
'FetchDriver.cpp',
+ 'FetchSignal.cpp',
'FetchUtil.cpp',
'Headers.cpp',
'InternalHeaders.cpp',
diff --git a/dom/tests/mochitest/fetch/file_fetch_controller.html b/dom/tests/mochitest/fetch/file_fetch_controller.html
new file mode 100644
index 000000000..6efa2fe0a
--- /dev/null
+++ b/dom/tests/mochitest/fetch/file_fetch_controller.html
@@ -0,0 +1,40 @@
+<script>
+function ok(a, msg) {
+ parent.postMessage({ type: "check", status: !!a, message: msg }, "*");
+}
+
+function is(a, b, msg) {
+ ok(a === b, msg);
+}
+
+function testWebIDL() {
+ ok("FetchController" in self, "We have a FetchController prototype");
+ ok("FetchSignal" in self, "We have a FetchSignal prototype");
+
+ var fc = new FetchController();
+ ok(!!fc, "FetchController can be created");
+ ok(fc instanceof FetchController, "FetchController is a FetchController");
+
+ ok(!!fc.signal, "FetchController has a signal");
+ ok(fc.signal instanceof FetchSignal, "fetchSignal is a FetchSignal");
+ is(fc.signal.aborted, false, "By default FetchSignal.aborted is false");
+ next();
+}
+
+var steps = [
+ testWebIDL,
+];
+
+function next() {
+ if (!steps.length) {
+ parent.postMessage({ type: "finish" }, "*");
+ return;
+ }
+
+ var step = steps.shift();
+ step();
+}
+
+next();
+
+</script>
diff --git a/dom/tests/mochitest/fetch/mochitest.ini b/dom/tests/mochitest/fetch/mochitest.ini
index cf4477463..6dba08f98 100644
--- a/dom/tests/mochitest/fetch/mochitest.ini
+++ b/dom/tests/mochitest/fetch/mochitest.ini
@@ -1,6 +1,7 @@
[DEFAULT]
support-files =
fetch_test_framework.js
+ file_fetch_controller.html
test_fetch_basic.js
test_fetch_basic_http.js
test_fetch_cors.js
@@ -41,6 +42,7 @@ support-files =
[test_fetch_basic_http.html]
[test_fetch_basic_http_sw_reroute.html]
[test_fetch_basic_http_sw_empty_reroute.html]
+[test_fetch_controller.html]
[test_fetch_cors.html]
skip-if = toolkit == 'android' # Bug 1210282
[test_fetch_cors_sw_reroute.html]
diff --git a/dom/tests/mochitest/fetch/test_fetch_controller.html b/dom/tests/mochitest/fetch/test_fetch_controller.html
new file mode 100644
index 000000000..812fb9161
--- /dev/null
+++ b/dom/tests/mochitest/fetch/test_fetch_controller.html
@@ -0,0 +1,40 @@
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test FetchController</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+
+SpecialPowers.pushPrefEnv({"set": [["dom.fetchController.enabled", true ]]}, () => {
+ let ifr = document.createElement('iframe');
+ ifr.src = "file_fetch_controller.html";
+ document.body.appendChild(ifr);
+
+ onmessage = function(e) {
+ if (e.data.type == "finish") {
+ SimpleTest.finish();
+ return;
+ }
+
+ if (e.data.type == "check") {
+ ok(e.data.status, e.data.message);
+ return;
+ }
+
+ ok(false, "Something when wrong.");
+ }
+});
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</body>
+</html>
+
diff --git a/dom/webidl/FetchController.webidl b/dom/webidl/FetchController.webidl
new file mode 100644
index 000000000..c5b1cc6da
--- /dev/null
+++ b/dom/webidl/FetchController.webidl
@@ -0,0 +1,15 @@
+/* -*- 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/.
+ */
+
+[Constructor(), Exposed=(Window,Worker),
+ Func="FetchController::IsEnabled"]
+interface FetchController {
+ readonly attribute FetchSignal signal;
+
+ void abort();
+ void follow(FetchSignal signal);
+ void unfollow(FetchSignal signal);
+};
diff --git a/dom/webidl/FetchSignal.webidl b/dom/webidl/FetchSignal.webidl
new file mode 100644
index 000000000..965355c20
--- /dev/null
+++ b/dom/webidl/FetchSignal.webidl
@@ -0,0 +1,13 @@
+/* -*- 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/.
+ */
+
+[Exposed=(Window,Worker),
+ Func="FetchController::IsEnabled"]
+interface FetchSignal : EventTarget {
+ readonly attribute boolean aborted;
+
+ attribute EventHandler onabort;
+};
diff --git a/dom/webidl/Request.webidl b/dom/webidl/Request.webidl
index e29c084d0..00497456a 100644
--- a/dom/webidl/Request.webidl
+++ b/dom/webidl/Request.webidl
@@ -47,6 +47,9 @@ dictionary RequestInit {
RequestCache cache;
RequestRedirect redirect;
DOMString integrity;
+
+ [Func="FetchController::IsEnabled"]
+ FetchSignal signal;
};
// Gecko currently does not ship RequestContext, so please don't use it in IDL
diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build
index 5e913585e..0843bac59 100644
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -141,7 +141,9 @@ WEBIDL_FILES = [
'ExtendableMessageEvent.webidl',
'FakePluginTagInit.webidl',
'Fetch.webidl',
+ 'FetchController.webidl',
'FetchEvent.webidl',
+ 'FetchSignal.webidl',
'File.webidl',
'FileList.webidl',
'FileMode.webidl',
diff --git a/dom/workers/WorkerPrefs.h b/dom/workers/WorkerPrefs.h
index 9a1be4801..d3e018b62 100644
--- a/dom/workers/WorkerPrefs.h
+++ b/dom/workers/WorkerPrefs.h
@@ -39,6 +39,7 @@ WORKER_SIMPLE_PREF("dom.push.enabled", PushEnabled, PUSH_ENABLED)
WORKER_SIMPLE_PREF("dom.requestcontext.enabled", RequestContextEnabled, REQUESTCONTEXT_ENABLED)
WORKER_SIMPLE_PREF("gfx.offscreencanvas.enabled", OffscreenCanvasEnabled, OFFSCREENCANVAS_ENABLED)
WORKER_SIMPLE_PREF("dom.webkitBlink.dirPicker.enabled", WebkitBlinkDirectoryPickerEnabled, DOM_WEBKITBLINK_DIRPICKER_WEBKITBLINK)
+WORKER_SIMPLE_PREF("dom.fetchController.enabled", FetchControllerEnabled, FETCHCONTROLLER_ENABLED)
WORKER_PREF("dom.workers.latestJSVersion", JSVersionChanged)
WORKER_PREF("intl.accept_languages", PrefLanguagesChanged)
WORKER_PREF("general.appname.override", AppNameOverrideChanged)