Bug 1359076: Disable all Device Sensor APIs except orientation by default r?bkelly draft
authorJonathan Kingston <jkt@mozilla.com>
Mon, 24 Jul 2017 10:07:00 +0200
changeset 761491 b83c5489afdf15e6573dc9f1acdb5e9c0f57b9bf
parent 761490 940b93518f531af9a1d9a1f24139f87426634968
push id100957
push userbmo:jkt@mozilla.com
push dateThu, 01 Mar 2018 01:50:16 +0000
reviewersbkelly
bugs1359076
milestone60.0a1
Bug 1359076: Disable all Device Sensor APIs except orientation by default r?bkelly This patch disables device sensors except orientation by default. It implements per-sensor prefs to disable orientation, motion, proximity and ambient light selectively. The patch also makes the pref checks happen at runtime (versus on process start) using Preferences::AddBoolVarCache. The patch also removes the related Event constructors also. MozReview-Commit-ID: EA8ARjjtlkF
dom/base/nsDeprecatedOperationList.h
dom/base/nsGlobalWindowInner.cpp
dom/base/nsGlobalWindowInner.h
dom/events/test/mochitest.ini
dom/events/test/test_bug742376.html
dom/events/test/test_deviceSensor.html
dom/events/test/test_disabled_events.html
dom/events/test/test_eventctors.html
dom/events/test/test_eventctors_sensors.html
dom/locales/en-US/chrome/dom/dom.properties
dom/system/nsDeviceSensors.cpp
dom/system/nsDeviceSensors.h
dom/tests/mochitest/general/test_interfaces.js
dom/webidl/DeviceLightEvent.webidl
dom/webidl/DeviceMotionEvent.webidl
dom/webidl/DeviceOrientationEvent.webidl
dom/webidl/DeviceProximityEvent.webidl
dom/webidl/UserProximityEvent.webidl
modules/libpref/init/all.js
--- a/dom/base/nsDeprecatedOperationList.h
+++ b/dom/base/nsDeprecatedOperationList.h
@@ -38,8 +38,12 @@ DEPRECATED_OPERATION(PrefixedFullscreenA
 DEPRECATED_OPERATION(LenientSetter)
 DEPRECATED_OPERATION(FileLastModifiedDate)
 DEPRECATED_OPERATION(ImageBitmapRenderingContext_TransferImageBitmap)
 DEPRECATED_OPERATION(URLCreateObjectURL_MediaStream)
 DEPRECATED_OPERATION(XMLBaseAttribute)
 DEPRECATED_OPERATION(WindowContentUntrusted)
 DEPRECATED_OPERATION(RegisterProtocolHandlerInsecure)
 DEPRECATED_OPERATION(MixedDisplayObjectSubrequest)
+DEPRECATED_OPERATION(MotionEvent)
+DEPRECATED_OPERATION(OrientationEvent)
+DEPRECATED_OPERATION(ProximityEvent)
+DEPRECATED_OPERATION(AmbientLightEvent)
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -3026,16 +3026,22 @@ nsGlobalWindowInner::IsRequestIdleCallba
 
 /* static */ bool
 nsGlobalWindowInner::RegisterProtocolHandlerAllowedForContext(JSContext* aCx, JSObject* aObj)
 {
   return IsSecureContextOrObjectIsFromSecureContext(aCx, aObj) ||
          Preferences::GetBool("dom.registerProtocolHandler.insecure.enabled");
 }
 
+/* static */ bool
+nsGlobalWindowInner::DeviceSensorsEnabled(JSContext* aCx, JSObject* aObj)
+{
+  return Preferences::GetBool("device.sensors.enabled");
+}
+
 nsIDOMOfflineResourceList*
 nsGlobalWindowInner::GetApplicationCache(ErrorResult& aError)
 {
   if (!mApplicationCache) {
     nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(GetDocShell()));
     if (!webNav || !mDoc) {
       aError.Throw(NS_ERROR_FAILURE);
       return nullptr;
--- a/dom/base/nsGlobalWindowInner.h
+++ b/dom/base/nsGlobalWindowInner.h
@@ -397,16 +397,18 @@ public:
   static bool OfflineCacheAllowedForContext(JSContext* /* unused */, JSObject* aObj);
 
   static bool IsRequestIdleCallbackEnabled(JSContext* aCx, JSObject* /* unused */);
 
   static bool IsWindowPrintEnabled(JSContext* /* unused */, JSObject* /* unused */);
 
   static bool RegisterProtocolHandlerAllowedForContext(JSContext* /* unused */, JSObject* aObj);
 
+  static bool DeviceSensorsEnabled(JSContext* /* unused */, JSObject* aObj);
+
   bool DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
                  JS::Handle<jsid> aId,
                  JS::MutableHandle<JS::PropertyDescriptor> aDesc);
   // The return value is whether DoResolve might end up resolving the given id.
   // If in doubt, return true.
   static bool MayResolve(jsid aId);
 
   void GetOwnPropertyNames(JSContext* aCx, JS::AutoIdVector& aNames,
--- a/dom/events/test/mochitest.ini
+++ b/dom/events/test/mochitest.ini
@@ -112,17 +112,17 @@ skip-if = toolkit == 'android' #CRASH_DU
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_bug684208.html]
 [test_bug689564.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_bug698929.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_bug704423.html]
 [test_bug741666.html]
-[test_bug742376.html]
+[test_deviceSensor.html]
 [test_bug812744.html]
 [test_bug822898.html]
 [test_bug855741.html]
 [test_bug864040.html]
 [test_bug924087.html]
 [test_bug930374-content.html]
 [test_bug944011.html]
 [test_bug944847.html]
@@ -162,16 +162,18 @@ skip-if = toolkit == 'android' #CRASH_DU
 [test_dom_wheel_event.html]
 [test_draggableprop.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
 [test_dragstart.html]
 [test_error_events.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_eventctors.html]
 skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
+[test_eventctors_sensors.html]
+[test_disabled_events.html]
 [test_eventhandler_scoping.html]
 [test_eventTimeStamp.html]
 [test_focus_disabled.html]
 [test_focus_abspos.html]
 [test_legacy_event.html]
 [test_messageEvent.html]
 [test_messageEvent_init.html]
 [test_moz_mouse_pixel_scroll_event.html]
rename from dom/events/test/test_bug742376.html
rename to dom/events/test/test_deviceSensor.html
--- a/dom/events/test/test_bug742376.html
+++ b/dom/events/test/test_deviceSensor.html
@@ -10,65 +10,127 @@ https://bugzilla.mozilla.org/show_bug.cg
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
 
 <body>
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=742376">Mozilla Bug 742376</a>
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 742376 **/
-
-function hasListeners() {
+let Cc = SpecialPowers.Cc;
+let Ci = SpecialPowers.Ci;
+let dss = Cc["@mozilla.org/devicesensors;1"].getService(Ci.nsIDeviceSensors);
 
-  var Cc = SpecialPowers.Cc;
-  var Ci = SpecialPowers.Ci;
-  var dss = Cc["@mozilla.org/devicesensors;1"].getService(Ci.nsIDeviceSensors);
+function hasLightListeners() {
+  return dss.hasWindowListener(Ci.nsIDeviceSensorData.TYPE_LIGHT, window);
+}
 
+function hasOrientationListeners() {
   return dss.hasWindowListener(Ci.nsIDeviceSensorData.TYPE_ORIENTATION, window) ||
          dss.hasWindowListener(Ci.nsIDeviceSensorData.TYPE_ROTATION_VECTOR, window) ||
          dss.hasWindowListener(Ci.nsIDeviceSensorData.TYPE_GAME_ROTATION_VECTOR, window);
 }
 
-is(hasListeners(), false, "Must not have listeners before tests start");
+function hasProximityListeners() {
+  return dss.hasWindowListener(Ci.nsIDeviceSensorData.TYPE_PROXIMITY, window);
+}
+
+function hasMotionListeners() {
+  return dss.hasWindowListener(Ci.nsIDeviceSensorData.TYPE_ACCELERATION, window) ||
+         dss.hasWindowListener(Ci.nsIDeviceSensorData.TYPE_LINEAR_ACCELERATION, window) ||
+         dss.hasWindowListener(Ci.nsIDeviceSensorData.TYPE_GYROSCOPE, window);
+}
 
-function dumbListener(event) {}
-function dumbListener2(event) {}
-function dumbListener3(event) {}
+async function test_event_presence(prefName, eventCheck, eventName) {
+  function dumbListener(event) {}
+  function dumbListener2(event) {}
+  function dumbListener3(event) {}
+
+  await SpecialPowers.pushPrefEnv({"set": [
+    [prefName, true]
+  ]});
+
+  is(eventCheck(), false, "Must not have listeners before tests start");
 
-window.addEventListener("deviceorientation", dumbListener);
-window.addEventListener("random_event_name", function() {});
-window.addEventListener("deviceorientation", dumbListener2);
+  window.addEventListener(eventName, dumbListener);
+  window.addEventListener("random_event_name", function() {});
+  window.addEventListener(eventName, dumbListener2);
 
-is(hasListeners(), true, "Listeners should have been added");
+  is(eventCheck(), true, `Should have listeners when ${eventName} sensor is enabled`);
+
+  window.removeEventListener(eventName, dumbListener);
+  window.removeEventListener(eventName, dumbListener2);
+
+  is(eventCheck(), false, "Must not have listeners when removed");
 
-window.setTimeout(function() {
+  await SpecialPowers.pushPrefEnv({"set": [
+    [prefName, false]
+  ]});
 
-  window.removeEventListener("deviceorientation", dumbListener);
-  is(hasListeners(), true, "Only some listeners should have been removed");
-  window.setTimeout(function() {
+  window.addEventListener(eventName, dumbListener);
+  window.addEventListener("random_event_name", function() {});
+  window.addEventListener(eventName, dumbListener2);
+
+  is(eventCheck(), false, "Must not have listeners when sensor is disabled");
+}
 
-    window.removeEventListener("deviceorientation", dumbListener2);
-    window.setTimeout(function() {
-      is(hasListeners(), false, "Listeners should have been removed");
-      testEventHandler();
-    }, 0);
-  }, 0);
-}, 0);
+async function start() {
+  await SpecialPowers.pushPrefEnv({"set": [
+    ["device.sensors.enabled", true],
+    ["device.sensors.orientation.enabled", true]
+  ]});
+
+  is(hasOrientationListeners(), false, "Must not have listeners before tests start");
+
+  function dumbListener(event) {}
+  function dumbListener2(event) {}
+  function dumbListener3(event) {}
+
+  window.addEventListener("deviceorientation", dumbListener);
+  window.addEventListener("random_event_name", function() {});
+  window.addEventListener("deviceorientation", dumbListener2);
+
+  is(hasOrientationListeners(), true, "Listeners should have been added");
 
-function testEventHandler() {
-  window.ondeviceorientation = function() {}
-  window.setTimeout(function() {
-    is(hasListeners(), true, "Handler should have been added");
-    window.ondeviceorientation = null;
+  await new Promise(resolve => {
+    window.setTimeout(function() {
+      window.removeEventListener("deviceorientation", dumbListener);
+      is(hasOrientationListeners(), true, "Only some listeners should have been removed");
+      window.setTimeout(function() {
+        window.removeEventListener("deviceorientation", dumbListener2);
+        window.setTimeout(function() {
+          is(hasOrientationListeners(), false, "Listeners should have been removed");
+          resolve();
+        }, 0);
+      }, 0);
+    }, 0);
+  });
+
+  await new Promise(resolve => {
+    window.ondeviceorientation = function() {}
     window.setTimeout(function() {
-      is(hasListeners(), false, "Handler should have been removed");
-      SimpleTest.finish();
+      is(hasOrientationListeners(), true, "Handler should have been added");
+      window.ondeviceorientation = null;
+      window.setTimeout(function() {
+        is(hasOrientationListeners(), false, "Handler should have been removed");
+        resolve();
+      }, 0);
     }, 0);
-  }, 0)
+  });
+
+  await test_event_presence("device.sensors.ambientLight.enabled", hasLightListeners, "devicelight");
+  await test_event_presence("device.sensors.proximity.enabled", hasProximityListeners, "deviceproximity");
+  await test_event_presence("device.sensors.motion.enabled", hasMotionListeners, "devicemotion");
+  await test_event_presence("device.sensors.orientation.enabled", hasOrientationListeners, "deviceorientation");
+
+  SimpleTest.finish();
+
 }
 
 SimpleTest.waitForExplicitFinish();
 
+start();
+
 </script>
 </pre>
 </body>
 </html>
 
copy from dom/events/test/test_eventctors.html
copy to dom/events/test/test_disabled_events.html
--- a/dom/events/test/test_eventctors.html
+++ b/dom/events/test/test_disabled_events.html
@@ -1,946 +1,40 @@
 <!DOCTYPE HTML>
 <html>
 <!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=675884
+https://bugzilla.mozilla.org/show_bug.cgi?id=1359076
 -->
 <head>
   <title>Test for Bug 675884</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=675884">Mozilla Bug 675884</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1359076">Mozilla Bug 1359076</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
-/** Test for Bug 675884 **/
-
-var receivedEvent;
-document.addEventListener("hello", function(e) { receivedEvent = e; }, true);
-
-function isMethodResultInitializer(aPropName)
-{
-  return aPropName.startsWith("modifier");
-}
-
-function getPropValue(aEvent, aPropName)
-{
-  if (aPropName.startsWith("modifier")) {
-    return aEvent.getModifierState(aPropName.substr("modifier".length));
-  }
-  return aEvent[aPropName];
-}
-
-// Event
-var e;
-var ex = false;
-try {
-  e = new Event();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-try {
-  e = new Event("foo", 123);
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "2nd parameter should be an object!");
-ex = false;
-
-try {
-  e = new Event("foo", "asdf");
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "2nd parameter should be an object!");
-ex = false;
-
-
-try {
-  e = new Event("foo", false);
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "2nd parameter should be an object!");
-ex = false;
-
-
-e = new Event("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-e.isTrusted = true;
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-
-try {
-  e.__defineGetter__("isTrusted", function() { return true });
-} catch (exp) {
-  ex = true;
-}
-ok(ex, "Shouldn't be able to re-define the getter for isTrusted.");
-ex = false;
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-
-ok(!("isTrusted" in Object.getPrototypeOf(e)))
-
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-document.dispatchEvent(e);
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-is(receivedEvent, e, "Wrong event!");
-
-e = new Event("hello", null);
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-document.dispatchEvent(e);
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-is(receivedEvent, e, "Wrong event!");
-
-e = new Event("hello", undefined);
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-document.dispatchEvent(e);
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-is(receivedEvent, e, "Wrong event!");
-
-e = new Event("hello", {});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-document.dispatchEvent(e);
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-is(receivedEvent, e, "Wrong event!");
-
-e = new Event("hello", { bubbles: true, cancelable: true });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// CustomEvent
-
-try {
-  e = new CustomEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-e = new CustomEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new CustomEvent("hello", { bubbles: true, cancelable: true, detail: window });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.detail, window , "Wrong event.detail!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new CustomEvent("hello", { cancelable: true, detail: window });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.detail, window , "Wrong event.detail!");
-
-e = new CustomEvent("hello", { detail: 123 });
-is(e.detail, 123, "Wrong event.detail!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-
-var dict = { get detail() { return document.body } };
-e = new CustomEvent("hello", dict);
-is(e.detail, dict.detail, "Wrong event.detail!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-
-var dict = { get detail() { throw "foo"; } };
-
-try {
-  e = new CustomEvent("hello", dict);
-} catch (exp) {
-  ex = true;
-}
-ok(ex, "Should have thrown an exception!");
-ex = false;
-
-// BlobEvent
-
-try {
-  e = new BlobEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-e = new BlobEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-try {
-  e.__defineGetter__("isTrusted", function() { return true });
-} catch (exp) {
-  ex = true;
-}
-ok(ex, "Shouldn't be able to re-define the getter for isTrusted.");
-ex = false;
-ok(!e.isTrusted, "BlobEvent shouldn't be trusted!");
-
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-var blob = new Blob();
-e = new BlobEvent("hello", { bubbles: true, cancelable: true, data: blob });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.data, blob , "Wrong event.data!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-
-e = new BlobEvent("hello", {data: blob});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event should be cancelable1!");
-is(e.data, blob , "Wrong event.data!");
-
-e = new BlobEvent("hello", { data: null });
-is(e.data, null, "Wrong event.data!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-blob = null;
-// CloseEvent
-
-try {
-  e = new CloseEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-e = new CloseEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.wasClean, false, "wasClean should be false!");
-is(e.code, 0, "code should be 0!");
-is(e.reason, "", "reason should be ''!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new CloseEvent("hello",
-  { bubbles: true, cancelable: true, wasClean: true, code: 1, reason: "foo" });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.wasClean, true, "wasClean should be true!");
-is(e.code, 1, "code should be 1!");
-is(e.reason, "foo", "reason should be 'foo'!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new CloseEvent("hello",
-  { bubbles: true, cancelable: true, wasClean: true, code: 1 });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.wasClean, true, "wasClean should be true!");
-is(e.code, 1, "code should be 1!");
-is(e.reason, "", "reason should be ''!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-
-// HashChangeEvent
-
-try {
-  e = new HashChangeEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-e = new HashChangeEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.oldURL, "", "oldURL should be ''");
-is(e.newURL, "", "newURL should be ''");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new HashChangeEvent("hello",
-  { bubbles: true, cancelable: true, oldURL: "old", newURL: "new" });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.oldURL, "old", "oldURL should be 'old'");
-is(e.newURL, "new", "newURL should be 'new'");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new HashChangeEvent("hello",
-  { bubbles: true, cancelable: true, newURL: "new" });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.oldURL, "", "oldURL should be ''");
-is(e.newURL, "new", "newURL should be 'new'");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// InputEvent
-
-e = new InputEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.detail, 0, "detail should be 0");
-ok(!e.isComposing, "isComposing should be false");
-
-e = new InputEvent("hi!", { bubbles: true, detail: 5, isComposing: false });
-is(e.type, "hi!", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.detail, 5, "detail should be 5");
-ok(!e.isComposing, "isComposing should be false");
-
-e = new InputEvent("hi!", { cancelable: true, detail: 0, isComposing: true });
-is(e.type, "hi!", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.detail, 0, "detail should be 0");
-ok(e.isComposing, "isComposing should be true");
-
-// KeyboardEvent
-
-try {
-  e = new KeyboardEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "KeyboardEvent: First parameter is required!");
-ex = false;
-
-e = new KeyboardEvent("hello");
-ok(e.type, "hello", "KeyboardEvent: Wrong event type!");
-ok(!e.isTrusted, "KeyboardEvent: Event shouldn't be trusted!");
-ok(!e.bubbles, "KeyboardEvent: Event shouldn't bubble!");
-ok(!e.cancelable, "KeyboardEvent: Event shouldn't be cancelable!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "KeyboardEvent: Wrong event!");
-
-var keyboardEventProps =
-[
-  { bubbles: false },
-  { cancelable: false },
-  { view: null },
-  { detail: 0 },
-  { key: "" },
-  { code: "" },
-  { location: 0 },
-  { ctrlKey: false },
-  { shiftKey: false },
-  { altKey: false },
-  { metaKey: false },
-  { modifierAltGraph: false },
-  { modifierCapsLock: false },
-  { modifierFn: false },
-  { modifierFnLock: false },
-  { modifierNumLock: false },
-  { modifierOS: false },
-  { modifierScrollLock: false },
-  { modifierSymbol: false },
-  { modifierSymbolLock: false },
-  { repeat: false },
-  { isComposing: false },
-  { charCode: 0 },
-  { keyCode: 0 },
-  { which: 0 },
-];
-
-var testKeyboardProps =
-[
-  { bubbles: true },
-  { cancelable: true },
-  { view: window },
-  { detail: 1 },
-  { key: "CustomKey" },
-  { code: "CustomCode" },
-  { location: 1 },
-  { ctrlKey: true },
-  { shiftKey: true },
-  { altKey: true },
-  { metaKey: true },
-  { modifierAltGraph: true },
-  { modifierCapsLock: true },
-  { modifierFn: true },
-  { modifierFnLock: true },
-  { modifierNumLock: true },
-  { modifierOS: true },
-  { modifierScrollLock: true },
-  { modifierSymbol: true },
-  { modifierSymbolLock: true },
-  { repeat: true },
-  { isComposing: true },
-  { charCode: 2 },
-  { keyCode: 3 },
-  { which: 4 },
-  { charCode: 5, which: 6 },
-  { keyCode: 7, which: 8 },
-  { keyCode: 9, charCode: 10 },
-  { keyCode: 11, charCode: 12, which: 13 },
-];
-
-var defaultKeyboardEventValues = {};
-for (var i = 0; i < keyboardEventProps.length; ++i) {
-  for (prop in keyboardEventProps[i]) {
-    if (!isMethodResultInitializer(prop)) {
-      ok(prop in e, "keyboardEvent: KeyboardEvent doesn't have property " + prop + "!");
-    }
-    defaultKeyboardEventValues[prop] = keyboardEventProps[i][prop]; 
-  }
-}
-
-while (testKeyboardProps.length) {
-  var p = testKeyboardProps.shift();
-  e = new KeyboardEvent("foo", p);
-  for (var def in defaultKeyboardEventValues) {
-    if (!(def in p)) {
-      is(getPropValue(e, def), defaultKeyboardEventValues[def],
-         "KeyboardEvent: Wrong default value for " + def + "!");
-    } else {
-      is(getPropValue(e, def), p[def],
-         "KeyboardEvent: Wrong event init value for " + def + "!");
-    }
-  }
-}
-
-// PageTransitionEvent
-
-try {
-  e = new PageTransitionEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-e = new PageTransitionEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.persisted, false, "persisted should be false");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
+SimpleTest.waitForExplicitFinish();
 
-e = new PageTransitionEvent("hello",
-  { bubbles: true, cancelable: true, persisted: true});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.persisted, true, "persisted should be true");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new PageTransitionEvent("hello", { persisted: true});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.persisted, true, "persisted should be true");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// PopStateEvent
-
-try {
-  e = new PopStateEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-e = new PopStateEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.state, null, "persisted should be null");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new PopStateEvent("hello",
-  { bubbles: true, cancelable: true, state: window});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.state, window, "persisted should be window");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-
-e = new PopStateEvent("hello", { state: window});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.state, window, "persisted should be window");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// UIEvent
-
-try {
-  e = new UIEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-try {
-  e = new UIEvent("foo", { view: {} });
-  e.view.onunload;
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "{} isn't a valid value.");
-ex = false;
-
-try {
-  e = new UIEvent("foo", { view: null });
-} catch(exp) {
-  ex = true;
-}
-ok(!ex, "null is a valid value.");
-is(e.view, null);
-ex = false;
-
-e = new UIEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.detail, 0, "detail should be 0");
-is(e.view, null, "view should be null");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new UIEvent("hello",
-  { bubbles: true, cancelable: true, view: window, detail: 1});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.detail, 1, "detail should be 1");
-is(e.view, window, "view should be window");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// StorageEvent
-
-e = document.createEvent("StorageEvent");
-ok(e, "Should have created an event!");
-
-try {
-  e = new StorageEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-e = new StorageEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.key, null, "key should be null");
-is(e.oldValue, null, "oldValue should be null");
-is(e.newValue, null, "newValue should be null");
-is(e.url, "", "url should be ''");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new StorageEvent("hello",
-  { bubbles: true, cancelable: true, key: "key",
-    oldValue: "oldValue", newValue: "newValue", url: "url",
-    storageArea: localStorage });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.key, "key", "Wrong value");
-is(e.oldValue, "oldValue", "Wrong value");
-is(e.newValue, "newValue", "Wrong value");
-is(e.url, "url", "Wrong value");
-is(e.storageArea, localStorage, "Wrong value");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// DeviceProximityEvent
-e = new DeviceProximityEvent("hello", {min: 0, value: 1, max: 2});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event should not be trusted");
-is(e.value, 1, "value should be 1");
-is(e.min, 0, "min should be 0");
-is(e.max, 2, "max should be 2");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-e = new DeviceProximityEvent("hello");
-is(e.value, Infinity, "Uninitialized value should be infinity");
-is(e.min, -Infinity, "Uninitialized min should be -infinity");
-is(e.max, Infinity, "Uninitialized max should be infinity");
-
-// UserProximityEvent
-e = new UserProximityEvent("hello", {near: true});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event should not be trusted");
-is(e.near, true, "near should be true");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// DeviceLightEvent
-e = new DeviceLightEvent("hello", {value: 1} );
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event should not be trusted");
-is(e.value, 1, "value should be 1");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-e = new DeviceLightEvent("hello", {value: Infinity} );
-is(e.value, Infinity, "value should be positive infinity");
-e = new DeviceLightEvent("hello", {value: -Infinity} );
-is(e.value, -Infinity, "value should be negative infinity");
-e = new DeviceLightEvent("hello");
-is(e.value, Infinity, "Uninitialized value should be positive infinity");
-
-// DeviceOrientationEvent
-e = new DeviceOrientationEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event should not be trusted");
-is(e.alpha, null);
-is(e.beta, null);
-is(e.gamma, null);
-is(e.absolute, false);
-
-e = new DeviceOrientationEvent("hello", { alpha: 1, beta: 2, gamma: 3, absolute: true } );
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event should not be trusted");
-is(e.alpha, 1);
-is(e.beta, 2);
-is(e.gamma, 3);
-is(e.absolute, true);
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// MouseEvent
-
-try {
-  e = new MouseEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "MouseEvent: First parameter is required!");
-ex = false;
-
-e = new MouseEvent("hello",  { buttons: 1, movementX: 2, movementY: 3});
-is(e.type, "hello", "MouseEvent: Wrong event type!");
-ok(!e.isTrusted, "MouseEvent: Event shouldn't be trusted!");
-ok(!e.bubbles, "MouseEvent: Event shouldn't bubble!");
-ok(!e.cancelable, "MouseEvent: Event shouldn't be cancelable!");
-is(e.buttons, 1);
-is(e.movementX, 2);
-is(e.movementY, 3);
-document.dispatchEvent(e);
-is(receivedEvent, e, "MouseEvent: Wrong event!");
-
-var mouseEventProps =
-[ { screenX: 0 },
-  { screenY: 0 },
-  { clientX: 0 },
-  { clientY: 0 },
-  { ctrlKey: false },
-  { shiftKey: false },
-  { altKey: false },
-  { metaKey: false },
-  { modifierAltGraph: false },
-  { modifierCapsLock: false },
-  { modifierFn: false },
-  { modifierFnLock: false },
-  { modifierNumLock: false },
-  { modifierOS: false },
-  { modifierScrollLock: false },
-  { modifierSymbol: false },
-  { modifierSymbolLock: false },
-  { button: 0 },
-  { buttons: 0 },
-  { relatedTarget: null },
-];
-
-var testProps =
-[
-  { screenX: 1 },
-  { screenY: 2 },
-  { clientX: 3 },
-  { clientY: 4 },
-  { ctrlKey: true },
-  { shiftKey: true },
-  { altKey: true },
-  { metaKey: true },
-  { modifierAltGraph: true },
-  { modifierCapsLock: true },
-  { modifierFn: true },
-  { modifierFnLock: true },
-  { modifierNumLock: true },
-  { modifierOS: true },
-  { modifierScrollLock: true },
-  { modifierSymbol: true },
-  { modifierSymbolLock: true },
-  { button: 5 },
-  { buttons: 6 },
-  { relatedTarget: window }
-];
-
-var defaultMouseEventValues = {};
-for (var i = 0; i < mouseEventProps.length; ++i) {
-  for (prop in mouseEventProps[i]) {
-    if (!isMethodResultInitializer(prop)) {
-      ok(prop in e, "MouseEvent: MouseEvent doesn't have property " + prop + "!");
-    }
-    defaultMouseEventValues[prop] = mouseEventProps[i][prop]; 
-  }
-}
-
-while (testProps.length) {
-  var p = testProps.shift();
-  e = new MouseEvent("foo", p);
-  for (var def in defaultMouseEventValues) {
-    if (!(def in p)) {
-      is(getPropValue(e, def), defaultMouseEventValues[def],
-         "MouseEvent: Wrong default value for " + def + "!");
-    } else {
-      is(getPropValue(e, def), p[def], "MouseEvent: Wrong event init value for " + def + "!");
-    }
-  }
-}
-
-// PopupBlockedEvent
-
-try {
-  e = new PopupBlockedEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "PopupBlockedEvent: First parameter is required!");
-ex = false;
-
-e = new PopupBlockedEvent("hello");
-is(e.type, "hello", "PopupBlockedEvent: Wrong event type!");
-ok(!e.isTrusted, "PopupBlockedEvent: Event shouldn't be trusted!");
-ok(!e.bubbles, "PopupBlockedEvent: Event shouldn't bubble!");
-ok(!e.cancelable, "PopupBlockedEvent: Event shouldn't be cancelable!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "PopupBlockedEvent: Wrong event!");
-
-e = new PopupBlockedEvent("hello",
-                          { requestingWindow: window,
-                            popupWindowFeatures: "features",
-                            popupWindowName: "name"
-                          });
-is(e.requestingWindow, window);
-is(e.popupWindowFeatures, "features");
-is(e.popupWindowName, "name");
-
-// WheelEvent
-
-try {
-  e = new WheelEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "WheelEvent: First parameter is required!");
-ex = false;
-
-e = new WheelEvent("hello",  { buttons: 1, movementX: 2, movementY: 3});
-is(e.type, "hello", "WheelEvent: Wrong event type!");
-is(e.buttons, 1);
-is(e.movementX, 2);
-is(e.movementY, 3);
-ok(!e.isTrusted, "WheelEvent: Event shouldn't be trusted!");
-ok(!e.bubbles, "WheelEvent: Event shouldn't bubble!");
-ok(!e.cancelable, "WheelEvent: Event shouldn't be cancelable!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "WheelEvent: Wrong event!");
-
-var wheelEventProps =
-[ { screenX: 0 },
-  { screenY: 0 },
-  { clientX: 0 },
-  { clientY: 0 },
-  { ctrlKey: false },
-  { shiftKey: false },
-  { altKey: false },
-  { metaKey: false },
-  { modifierAltGraph: false },
-  { modifierCapsLock: false },
-  { modifierFn: false },
-  { modifierFnLock: false },
-  { modifierNumLock: false },
-  { modifierOS: false },
-  { modifierScrollLock: false },
-  { modifierSymbol: false },
-  { modifierSymbolLock: false },
-  { button: 0 },
-  { buttons: 0 },
-  { relatedTarget: null },
-  { deltaX: 0.0 },
-  { deltaY: 0.0 },
-  { deltaZ: 0.0 },
-  { deltaMode: 0 }
-];
-
-var testWheelProps =
-[
-  { screenX: 1 },
-  { screenY: 2 },
-  { clientX: 3 },
-  { clientY: 4 },
-  { ctrlKey: true },
-  { shiftKey: true },
-  { altKey: true },
-  { metaKey: true },
-  { modifierAltGraph: true },
-  { modifierCapsLock: true },
-  { modifierFn: true },
-  { modifierFnLock: true },
-  { modifierNumLock: true },
-  { modifierOS: true },
-  { modifierScrollLock: true },
-  { modifierSymbol: true },
-  { modifierSymbolLock: true },
-  { button: 5 },
-  { buttons: 6 },
-  { relatedTarget: window },
-  { deltaX: 7.8 },
-  { deltaY: 9.1 },
-  { deltaZ: 2.3 },
-  { deltaMode: 4 }
-];
-
-var defaultWheelEventValues = {};
-for (var i = 0; i < wheelEventProps.length; ++i) {
-  for (prop in wheelEventProps[i]) {
-    if (!isMethodResultInitializer(prop)) {
-      ok(prop in e, "WheelEvent: WheelEvent doesn't have property " + prop + "!");
-    }
-    defaultWheelEventValues[prop] = wheelEventProps[i][prop]; 
-  }
-}
-
-while (testWheelProps.length) {
-  var p = testWheelProps.shift();
-  e = new WheelEvent("foo", p);
-  for (var def in defaultWheelEventValues) {
-    if (!(def in p)) {
-      is(getPropValue(e, def), defaultWheelEventValues[def],
-         "WheelEvent: Wrong default value for " + def + "!");
-    } else {
-      is(getPropValue(e, def), p[def], "WheelEvent: Wrong event init value for " + def + "!");
-    }
-  }
-}
-
-// DragEvent
-
-try {
-  e = new DragEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "DragEvent: First parameter is required!");
-ex = false;
-
-e = new DragEvent("hello", { buttons: 1, movementX: 2, movementY: 3});
-is(e.type, "hello", "DragEvent: Wrong event type!");
-is(e.buttons, 1);
-is(e.movementX, 2);
-is(e.movementY, 3);
-document.dispatchEvent(e);
-is(receivedEvent, e, "DragEvent: Wrong event!");
-
-// TransitionEvent
-e = new TransitionEvent("hello", { propertyName: "color", elapsedTime: 3.5, pseudoElement: "", foobar: "baz" })
-is("propertyName" in e, true, "Transition events have propertyName property");
-is("foobar" in e, false, "Transition events do not copy random properties from event init");
-is(e.propertyName, "color", "Transition event copies propertyName from TransitionEventInit");
-is(e.elapsedTime, 3.5, "Transition event copies elapsedTime from TransitionEventInit");
-is(e.pseudoElement, "", "Transition event copies pseudoElement from TransitionEventInit");
-is(e.bubbles, false, "Lack of bubbles property in TransitionEventInit");
-is(e.cancelable, false, "Lack of cancelable property in TransitionEventInit");
-is(e.type, "hello", "Wrong event type!");
-is(e.isTrusted, false, "Event shouldn't be trusted!");
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-
-// AnimationEvent
-e = new AnimationEvent("hello", { animationName: "bounce3", elapsedTime: 3.5, pseudoElement: "", foobar: "baz" })
-is("animationName" in e, true, "Animation events have animationName property");
-is("foobar" in e, false, "Animation events do not copy random properties from event init");
-is(e.animationName, "bounce3", "Animation event copies animationName from AnimationEventInit");
-is(e.elapsedTime, 3.5, "Animation event copies elapsedTime from AnimationEventInit");
-is(e.pseudoElement, "", "Animation event copies pseudoElement from AnimationEventInit");
-is(e.bubbles, false, "Lack of bubbles property in AnimationEventInit");
-is(e.cancelable, false, "Lack of cancelable property in AnimationEventInit");
-is(e.type, "hello", "Wrong event type!");
-is(e.isTrusted, false, "Event shouldn't be trusted!");
-is(e.eventPhase, Event.NONE, "Wrong event phase");
+SpecialPowers.pushPrefEnv({"set": [
+  ["device.sensors.orientation.enabled", false],
+  ["device.sensors.motion.enabled", false],
+  ["device.sensors.proximity.enabled", false],
+  ["device.sensors.ambientLight.enabled", false],
+  ["dom.w3c_pointer_events.enabled", false]
+]}, () => {
+  is("DeviceProximityEvent" in window, false, "DeviceProximityEvent does not exist");
+  is("UserProximityEvent" in window, false, "UserProximityEvent does not exist");
+  is("DeviceLightEvent" in window, false, "DeviceLightEvent does not exist");
+  is("DeviceOrientationEvent" in window, false, "DeviceOrientationEvent does not exist");
+  is("DeviceMotionEvent" in window, false, "DeviceMotionEvent does not exist");
+  SimpleTest.finish();
+});
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/events/test/test_eventctors.html
+++ b/dom/events/test/test_eventctors.html
@@ -619,71 +619,16 @@ ok(e.cancelable, "Event should be cancel
 is(e.key, "key", "Wrong value");
 is(e.oldValue, "oldValue", "Wrong value");
 is(e.newValue, "newValue", "Wrong value");
 is(e.url, "url", "Wrong value");
 is(e.storageArea, localStorage, "Wrong value");
 document.dispatchEvent(e);
 is(receivedEvent, e, "Wrong event!");
 
-// DeviceProximityEvent
-e = new DeviceProximityEvent("hello", {min: 0, value: 1, max: 2});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event should not be trusted");
-is(e.value, 1, "value should be 1");
-is(e.min, 0, "min should be 0");
-is(e.max, 2, "max should be 2");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-e = new DeviceProximityEvent("hello");
-is(e.value, Infinity, "Uninitialized value should be infinity");
-is(e.min, -Infinity, "Uninitialized min should be -infinity");
-is(e.max, Infinity, "Uninitialized max should be infinity");
-
-// UserProximityEvent
-e = new UserProximityEvent("hello", {near: true});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event should not be trusted");
-is(e.near, true, "near should be true");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// DeviceLightEvent
-e = new DeviceLightEvent("hello", {value: 1} );
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event should not be trusted");
-is(e.value, 1, "value should be 1");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-e = new DeviceLightEvent("hello", {value: Infinity} );
-is(e.value, Infinity, "value should be positive infinity");
-e = new DeviceLightEvent("hello", {value: -Infinity} );
-is(e.value, -Infinity, "value should be negative infinity");
-e = new DeviceLightEvent("hello");
-is(e.value, Infinity, "Uninitialized value should be positive infinity");
-
-// DeviceOrientationEvent
-e = new DeviceOrientationEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event should not be trusted");
-is(e.alpha, null);
-is(e.beta, null);
-is(e.gamma, null);
-is(e.absolute, false);
-
-e = new DeviceOrientationEvent("hello", { alpha: 1, beta: 2, gamma: 3, absolute: true } );
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event should not be trusted");
-is(e.alpha, 1);
-is(e.beta, 2);
-is(e.gamma, 3);
-is(e.absolute, true);
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
 // MouseEvent
 
 try {
   e = new MouseEvent();
 } catch(exp) {
   ex = true;
 }
 ok(ex, "MouseEvent: First parameter is required!");
copy from dom/events/test/test_eventctors.html
copy to dom/events/test/test_eventctors_sensors.html
--- a/dom/events/test/test_eventctors.html
+++ b/dom/events/test/test_eventctors_sensors.html
@@ -12,935 +12,99 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=675884">Mozilla Bug 675884</a>
 <p id="display"></p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script type="application/javascript">
 
-/** Test for Bug 675884 **/
-
-var receivedEvent;
-document.addEventListener("hello", function(e) { receivedEvent = e; }, true);
-
-function isMethodResultInitializer(aPropName)
-{
-  return aPropName.startsWith("modifier");
-}
-
-function getPropValue(aEvent, aPropName)
-{
-  if (aPropName.startsWith("modifier")) {
-    return aEvent.getModifierState(aPropName.substr("modifier".length));
-  }
-  return aEvent[aPropName];
-}
-
-// Event
-var e;
-var ex = false;
-try {
-  e = new Event();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-try {
-  e = new Event("foo", 123);
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "2nd parameter should be an object!");
-ex = false;
-
-try {
-  e = new Event("foo", "asdf");
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "2nd parameter should be an object!");
-ex = false;
-
-
-try {
-  e = new Event("foo", false);
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "2nd parameter should be an object!");
-ex = false;
-
-
-e = new Event("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-e.isTrusted = true;
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-
-try {
-  e.__defineGetter__("isTrusted", function() { return true });
-} catch (exp) {
-  ex = true;
-}
-ok(ex, "Shouldn't be able to re-define the getter for isTrusted.");
-ex = false;
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-
-ok(!("isTrusted" in Object.getPrototypeOf(e)))
-
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-document.dispatchEvent(e);
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-is(receivedEvent, e, "Wrong event!");
-
-e = new Event("hello", null);
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-document.dispatchEvent(e);
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-is(receivedEvent, e, "Wrong event!");
-
-e = new Event("hello", undefined);
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-document.dispatchEvent(e);
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-is(receivedEvent, e, "Wrong event!");
-
-e = new Event("hello", {});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-document.dispatchEvent(e);
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-is(receivedEvent, e, "Wrong event!");
-
-e = new Event("hello", { bubbles: true, cancelable: true });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// CustomEvent
-
-try {
-  e = new CustomEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-e = new CustomEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new CustomEvent("hello", { bubbles: true, cancelable: true, detail: window });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.detail, window , "Wrong event.detail!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new CustomEvent("hello", { cancelable: true, detail: window });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.detail, window , "Wrong event.detail!");
-
-e = new CustomEvent("hello", { detail: 123 });
-is(e.detail, 123, "Wrong event.detail!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-
-var dict = { get detail() { return document.body } };
-e = new CustomEvent("hello", dict);
-is(e.detail, dict.detail, "Wrong event.detail!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-
-var dict = { get detail() { throw "foo"; } };
-
-try {
-  e = new CustomEvent("hello", dict);
-} catch (exp) {
-  ex = true;
-}
-ok(ex, "Should have thrown an exception!");
-ex = false;
-
-// BlobEvent
-
-try {
-  e = new BlobEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-e = new BlobEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-try {
-  e.__defineGetter__("isTrusted", function() { return true });
-} catch (exp) {
-  ex = true;
-}
-ok(ex, "Shouldn't be able to re-define the getter for isTrusted.");
-ex = false;
-ok(!e.isTrusted, "BlobEvent shouldn't be trusted!");
-
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-var blob = new Blob();
-e = new BlobEvent("hello", { bubbles: true, cancelable: true, data: blob });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.data, blob , "Wrong event.data!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-
-e = new BlobEvent("hello", {data: blob});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event should be cancelable1!");
-is(e.data, blob , "Wrong event.data!");
-
-e = new BlobEvent("hello", { data: null });
-is(e.data, null, "Wrong event.data!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-blob = null;
-// CloseEvent
+SimpleTest.waitForExplicitFinish();
 
-try {
-  e = new CloseEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-e = new CloseEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.wasClean, false, "wasClean should be false!");
-is(e.code, 0, "code should be 0!");
-is(e.reason, "", "reason should be ''!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new CloseEvent("hello",
-  { bubbles: true, cancelable: true, wasClean: true, code: 1, reason: "foo" });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.wasClean, true, "wasClean should be true!");
-is(e.code, 1, "code should be 1!");
-is(e.reason, "foo", "reason should be 'foo'!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new CloseEvent("hello",
-  { bubbles: true, cancelable: true, wasClean: true, code: 1 });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.wasClean, true, "wasClean should be true!");
-is(e.code, 1, "code should be 1!");
-is(e.reason, "", "reason should be ''!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-
-// HashChangeEvent
-
-try {
-  e = new HashChangeEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-e = new HashChangeEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.oldURL, "", "oldURL should be ''");
-is(e.newURL, "", "newURL should be ''");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new HashChangeEvent("hello",
-  { bubbles: true, cancelable: true, oldURL: "old", newURL: "new" });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.oldURL, "old", "oldURL should be 'old'");
-is(e.newURL, "new", "newURL should be 'new'");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new HashChangeEvent("hello",
-  { bubbles: true, cancelable: true, newURL: "new" });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.oldURL, "", "oldURL should be ''");
-is(e.newURL, "new", "newURL should be 'new'");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// InputEvent
-
-e = new InputEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.detail, 0, "detail should be 0");
-ok(!e.isComposing, "isComposing should be false");
-
-e = new InputEvent("hi!", { bubbles: true, detail: 5, isComposing: false });
-is(e.type, "hi!", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.detail, 5, "detail should be 5");
-ok(!e.isComposing, "isComposing should be false");
-
-e = new InputEvent("hi!", { cancelable: true, detail: 0, isComposing: true });
-is(e.type, "hi!", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.detail, 0, "detail should be 0");
-ok(e.isComposing, "isComposing should be true");
-
-// KeyboardEvent
+SpecialPowers.pushPrefEnv({"set": [
+  ["device.sensors.enabled", true],
+  ["device.sensors.orientation.enabled", true],
+  ["device.sensors.motion.enabled", true],
+  ["device.sensors.proximity.enabled", true],
+  ["device.sensors.ambientLight.enabled", true]
+]}, () => {
+  let receivedEvent;
+  document.addEventListener("hello", function(e) { receivedEvent = e; }, true);
+  // DeviceProximityEvent
+  let e = new DeviceProximityEvent("hello", {min: 0, value: 1, max: 2});
+  is(e.type, "hello", "Wrong event type!");
+  ok(!e.isTrusted, "Event should not be trusted");
+  is(e.value, 1, "value should be 1");
+  is(e.min, 0, "min should be 0");
+  is(e.max, 2, "max should be 2");
+  document.dispatchEvent(e);
+  is(receivedEvent, e, "Wrong event!");
+  e = new DeviceProximityEvent("hello");
+  is(e.value, Infinity, "Uninitialized value should be infinity");
+  is(e.min, -Infinity, "Uninitialized min should be -infinity");
+  is(e.max, Infinity, "Uninitialized max should be infinity");
 
-try {
-  e = new KeyboardEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "KeyboardEvent: First parameter is required!");
-ex = false;
-
-e = new KeyboardEvent("hello");
-ok(e.type, "hello", "KeyboardEvent: Wrong event type!");
-ok(!e.isTrusted, "KeyboardEvent: Event shouldn't be trusted!");
-ok(!e.bubbles, "KeyboardEvent: Event shouldn't bubble!");
-ok(!e.cancelable, "KeyboardEvent: Event shouldn't be cancelable!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "KeyboardEvent: Wrong event!");
-
-var keyboardEventProps =
-[
-  { bubbles: false },
-  { cancelable: false },
-  { view: null },
-  { detail: 0 },
-  { key: "" },
-  { code: "" },
-  { location: 0 },
-  { ctrlKey: false },
-  { shiftKey: false },
-  { altKey: false },
-  { metaKey: false },
-  { modifierAltGraph: false },
-  { modifierCapsLock: false },
-  { modifierFn: false },
-  { modifierFnLock: false },
-  { modifierNumLock: false },
-  { modifierOS: false },
-  { modifierScrollLock: false },
-  { modifierSymbol: false },
-  { modifierSymbolLock: false },
-  { repeat: false },
-  { isComposing: false },
-  { charCode: 0 },
-  { keyCode: 0 },
-  { which: 0 },
-];
-
-var testKeyboardProps =
-[
-  { bubbles: true },
-  { cancelable: true },
-  { view: window },
-  { detail: 1 },
-  { key: "CustomKey" },
-  { code: "CustomCode" },
-  { location: 1 },
-  { ctrlKey: true },
-  { shiftKey: true },
-  { altKey: true },
-  { metaKey: true },
-  { modifierAltGraph: true },
-  { modifierCapsLock: true },
-  { modifierFn: true },
-  { modifierFnLock: true },
-  { modifierNumLock: true },
-  { modifierOS: true },
-  { modifierScrollLock: true },
-  { modifierSymbol: true },
-  { modifierSymbolLock: true },
-  { repeat: true },
-  { isComposing: true },
-  { charCode: 2 },
-  { keyCode: 3 },
-  { which: 4 },
-  { charCode: 5, which: 6 },
-  { keyCode: 7, which: 8 },
-  { keyCode: 9, charCode: 10 },
-  { keyCode: 11, charCode: 12, which: 13 },
-];
-
-var defaultKeyboardEventValues = {};
-for (var i = 0; i < keyboardEventProps.length; ++i) {
-  for (prop in keyboardEventProps[i]) {
-    if (!isMethodResultInitializer(prop)) {
-      ok(prop in e, "keyboardEvent: KeyboardEvent doesn't have property " + prop + "!");
-    }
-    defaultKeyboardEventValues[prop] = keyboardEventProps[i][prop]; 
-  }
-}
-
-while (testKeyboardProps.length) {
-  var p = testKeyboardProps.shift();
-  e = new KeyboardEvent("foo", p);
-  for (var def in defaultKeyboardEventValues) {
-    if (!(def in p)) {
-      is(getPropValue(e, def), defaultKeyboardEventValues[def],
-         "KeyboardEvent: Wrong default value for " + def + "!");
-    } else {
-      is(getPropValue(e, def), p[def],
-         "KeyboardEvent: Wrong event init value for " + def + "!");
-    }
-  }
-}
-
-// PageTransitionEvent
-
-try {
-  e = new PageTransitionEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-e = new PageTransitionEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.persisted, false, "persisted should be false");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
+  // UserProximityEvent
+  e = new UserProximityEvent("hello", {near: true});
+  is(e.type, "hello", "Wrong event type!");
+  ok(!e.isTrusted, "Event should not be trusted");
+  is(e.near, true, "near should be true");
+  document.dispatchEvent(e);
+  is(receivedEvent, e, "Wrong event!");
 
-e = new PageTransitionEvent("hello",
-  { bubbles: true, cancelable: true, persisted: true});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.persisted, true, "persisted should be true");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new PageTransitionEvent("hello", { persisted: true});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.persisted, true, "persisted should be true");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// PopStateEvent
-
-try {
-  e = new PopStateEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-e = new PopStateEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.state, null, "persisted should be null");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new PopStateEvent("hello",
-  { bubbles: true, cancelable: true, state: window});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.state, window, "persisted should be window");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-
-e = new PopStateEvent("hello", { state: window});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.state, window, "persisted should be window");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// UIEvent
-
-try {
-  e = new UIEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-try {
-  e = new UIEvent("foo", { view: {} });
-  e.view.onunload;
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "{} isn't a valid value.");
-ex = false;
-
-try {
-  e = new UIEvent("foo", { view: null });
-} catch(exp) {
-  ex = true;
-}
-ok(!ex, "null is a valid value.");
-is(e.view, null);
-ex = false;
-
-e = new UIEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.detail, 0, "detail should be 0");
-is(e.view, null, "view should be null");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new UIEvent("hello",
-  { bubbles: true, cancelable: true, view: window, detail: 1});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.detail, 1, "detail should be 1");
-is(e.view, window, "view should be window");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// StorageEvent
-
-e = document.createEvent("StorageEvent");
-ok(e, "Should have created an event!");
+  // DeviceLightEvent
+  e = new DeviceLightEvent("hello", {value: 1} );
+  is(e.type, "hello", "Wrong event type!");
+  ok(!e.isTrusted, "Event should not be trusted");
+  is(e.value, 1, "value should be 1");
+  document.dispatchEvent(e);
+  is(receivedEvent, e, "Wrong event!");
+  e = new DeviceLightEvent("hello", {value: Infinity} );
+  is(e.value, Infinity, "value should be positive infinity");
+  e = new DeviceLightEvent("hello", {value: -Infinity} );
+  is(e.value, -Infinity, "value should be negative infinity");
+  e = new DeviceLightEvent("hello");
+  is(e.value, Infinity, "Uninitialized value should be positive infinity");
 
-try {
-  e = new StorageEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "First parameter is required!");
-ex = false;
-
-e = new StorageEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(!e.bubbles, "Event shouldn't bubble!");
-ok(!e.cancelable, "Event shouldn't be cancelable!");
-is(e.key, null, "key should be null");
-is(e.oldValue, null, "oldValue should be null");
-is(e.newValue, null, "newValue should be null");
-is(e.url, "", "url should be ''");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-e = new StorageEvent("hello",
-  { bubbles: true, cancelable: true, key: "key",
-    oldValue: "oldValue", newValue: "newValue", url: "url",
-    storageArea: localStorage });
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event shouldn't be trusted!");
-ok(e.bubbles, "Event should bubble!");
-ok(e.cancelable, "Event should be cancelable!");
-is(e.key, "key", "Wrong value");
-is(e.oldValue, "oldValue", "Wrong value");
-is(e.newValue, "newValue", "Wrong value");
-is(e.url, "url", "Wrong value");
-is(e.storageArea, localStorage, "Wrong value");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// DeviceProximityEvent
-e = new DeviceProximityEvent("hello", {min: 0, value: 1, max: 2});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event should not be trusted");
-is(e.value, 1, "value should be 1");
-is(e.min, 0, "min should be 0");
-is(e.max, 2, "max should be 2");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-e = new DeviceProximityEvent("hello");
-is(e.value, Infinity, "Uninitialized value should be infinity");
-is(e.min, -Infinity, "Uninitialized min should be -infinity");
-is(e.max, Infinity, "Uninitialized max should be infinity");
-
-// UserProximityEvent
-e = new UserProximityEvent("hello", {near: true});
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event should not be trusted");
-is(e.near, true, "near should be true");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// DeviceLightEvent
-e = new DeviceLightEvent("hello", {value: 1} );
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event should not be trusted");
-is(e.value, 1, "value should be 1");
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-e = new DeviceLightEvent("hello", {value: Infinity} );
-is(e.value, Infinity, "value should be positive infinity");
-e = new DeviceLightEvent("hello", {value: -Infinity} );
-is(e.value, -Infinity, "value should be negative infinity");
-e = new DeviceLightEvent("hello");
-is(e.value, Infinity, "Uninitialized value should be positive infinity");
-
-// DeviceOrientationEvent
-e = new DeviceOrientationEvent("hello");
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event should not be trusted");
-is(e.alpha, null);
-is(e.beta, null);
-is(e.gamma, null);
-is(e.absolute, false);
-
-e = new DeviceOrientationEvent("hello", { alpha: 1, beta: 2, gamma: 3, absolute: true } );
-is(e.type, "hello", "Wrong event type!");
-ok(!e.isTrusted, "Event should not be trusted");
-is(e.alpha, 1);
-is(e.beta, 2);
-is(e.gamma, 3);
-is(e.absolute, true);
-document.dispatchEvent(e);
-is(receivedEvent, e, "Wrong event!");
-
-// MouseEvent
-
-try {
-  e = new MouseEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "MouseEvent: First parameter is required!");
-ex = false;
-
-e = new MouseEvent("hello",  { buttons: 1, movementX: 2, movementY: 3});
-is(e.type, "hello", "MouseEvent: Wrong event type!");
-ok(!e.isTrusted, "MouseEvent: Event shouldn't be trusted!");
-ok(!e.bubbles, "MouseEvent: Event shouldn't bubble!");
-ok(!e.cancelable, "MouseEvent: Event shouldn't be cancelable!");
-is(e.buttons, 1);
-is(e.movementX, 2);
-is(e.movementY, 3);
-document.dispatchEvent(e);
-is(receivedEvent, e, "MouseEvent: Wrong event!");
+  // DeviceOrientationEvent
+  e = new DeviceOrientationEvent("hello");
+  is(e.type, "hello", "Wrong event type!");
+  ok(!e.isTrusted, "Event should not be trusted");
+  is(e.alpha, null);
+  is(e.beta, null);
+  is(e.gamma, null);
+  is(e.absolute, false);
 
-var mouseEventProps =
-[ { screenX: 0 },
-  { screenY: 0 },
-  { clientX: 0 },
-  { clientY: 0 },
-  { ctrlKey: false },
-  { shiftKey: false },
-  { altKey: false },
-  { metaKey: false },
-  { modifierAltGraph: false },
-  { modifierCapsLock: false },
-  { modifierFn: false },
-  { modifierFnLock: false },
-  { modifierNumLock: false },
-  { modifierOS: false },
-  { modifierScrollLock: false },
-  { modifierSymbol: false },
-  { modifierSymbolLock: false },
-  { button: 0 },
-  { buttons: 0 },
-  { relatedTarget: null },
-];
-
-var testProps =
-[
-  { screenX: 1 },
-  { screenY: 2 },
-  { clientX: 3 },
-  { clientY: 4 },
-  { ctrlKey: true },
-  { shiftKey: true },
-  { altKey: true },
-  { metaKey: true },
-  { modifierAltGraph: true },
-  { modifierCapsLock: true },
-  { modifierFn: true },
-  { modifierFnLock: true },
-  { modifierNumLock: true },
-  { modifierOS: true },
-  { modifierScrollLock: true },
-  { modifierSymbol: true },
-  { modifierSymbolLock: true },
-  { button: 5 },
-  { buttons: 6 },
-  { relatedTarget: window }
-];
-
-var defaultMouseEventValues = {};
-for (var i = 0; i < mouseEventProps.length; ++i) {
-  for (prop in mouseEventProps[i]) {
-    if (!isMethodResultInitializer(prop)) {
-      ok(prop in e, "MouseEvent: MouseEvent doesn't have property " + prop + "!");
-    }
-    defaultMouseEventValues[prop] = mouseEventProps[i][prop]; 
-  }
-}
-
-while (testProps.length) {
-  var p = testProps.shift();
-  e = new MouseEvent("foo", p);
-  for (var def in defaultMouseEventValues) {
-    if (!(def in p)) {
-      is(getPropValue(e, def), defaultMouseEventValues[def],
-         "MouseEvent: Wrong default value for " + def + "!");
-    } else {
-      is(getPropValue(e, def), p[def], "MouseEvent: Wrong event init value for " + def + "!");
-    }
-  }
-}
-
-// PopupBlockedEvent
-
-try {
-  e = new PopupBlockedEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "PopupBlockedEvent: First parameter is required!");
-ex = false;
-
-e = new PopupBlockedEvent("hello");
-is(e.type, "hello", "PopupBlockedEvent: Wrong event type!");
-ok(!e.isTrusted, "PopupBlockedEvent: Event shouldn't be trusted!");
-ok(!e.bubbles, "PopupBlockedEvent: Event shouldn't bubble!");
-ok(!e.cancelable, "PopupBlockedEvent: Event shouldn't be cancelable!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "PopupBlockedEvent: Wrong event!");
-
-e = new PopupBlockedEvent("hello",
-                          { requestingWindow: window,
-                            popupWindowFeatures: "features",
-                            popupWindowName: "name"
-                          });
-is(e.requestingWindow, window);
-is(e.popupWindowFeatures, "features");
-is(e.popupWindowName, "name");
-
-// WheelEvent
-
-try {
-  e = new WheelEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "WheelEvent: First parameter is required!");
-ex = false;
-
-e = new WheelEvent("hello",  { buttons: 1, movementX: 2, movementY: 3});
-is(e.type, "hello", "WheelEvent: Wrong event type!");
-is(e.buttons, 1);
-is(e.movementX, 2);
-is(e.movementY, 3);
-ok(!e.isTrusted, "WheelEvent: Event shouldn't be trusted!");
-ok(!e.bubbles, "WheelEvent: Event shouldn't bubble!");
-ok(!e.cancelable, "WheelEvent: Event shouldn't be cancelable!");
-document.dispatchEvent(e);
-is(receivedEvent, e, "WheelEvent: Wrong event!");
+  e = new DeviceOrientationEvent("hello", { alpha: 1, beta: 2, gamma: 3, absolute: true } );
+  is(e.type, "hello", "Wrong event type!");
+  ok(!e.isTrusted, "Event should not be trusted");
+  is(e.alpha, 1);
+  is(e.beta, 2);
+  is(e.gamma, 3);
+  is(e.absolute, true);
+  document.dispatchEvent(e);
+  is(receivedEvent, e, "Wrong event!");
 
-var wheelEventProps =
-[ { screenX: 0 },
-  { screenY: 0 },
-  { clientX: 0 },
-  { clientY: 0 },
-  { ctrlKey: false },
-  { shiftKey: false },
-  { altKey: false },
-  { metaKey: false },
-  { modifierAltGraph: false },
-  { modifierCapsLock: false },
-  { modifierFn: false },
-  { modifierFnLock: false },
-  { modifierNumLock: false },
-  { modifierOS: false },
-  { modifierScrollLock: false },
-  { modifierSymbol: false },
-  { modifierSymbolLock: false },
-  { button: 0 },
-  { buttons: 0 },
-  { relatedTarget: null },
-  { deltaX: 0.0 },
-  { deltaY: 0.0 },
-  { deltaZ: 0.0 },
-  { deltaMode: 0 }
-];
-
-var testWheelProps =
-[
-  { screenX: 1 },
-  { screenY: 2 },
-  { clientX: 3 },
-  { clientY: 4 },
-  { ctrlKey: true },
-  { shiftKey: true },
-  { altKey: true },
-  { metaKey: true },
-  { modifierAltGraph: true },
-  { modifierCapsLock: true },
-  { modifierFn: true },
-  { modifierFnLock: true },
-  { modifierNumLock: true },
-  { modifierOS: true },
-  { modifierScrollLock: true },
-  { modifierSymbol: true },
-  { modifierSymbolLock: true },
-  { button: 5 },
-  { buttons: 6 },
-  { relatedTarget: window },
-  { deltaX: 7.8 },
-  { deltaY: 9.1 },
-  { deltaZ: 2.3 },
-  { deltaMode: 4 }
-];
+  // DeviceMotionEvent
+  e = new DeviceMotionEvent("hello");
+  is(e.type, "hello", "Wrong event type!");
+  ok(!e.isTrusted, "Event should not be trusted");
+  is(typeof e.acceleration, "object");
+  is(e.acceleration.x, null);
+  is(e.acceleration.y, null);
+  is(e.acceleration.z, null);
+  is(typeof e.accelerationIncludingGravity, "object");
+  is(e.accelerationIncludingGravity.x, null);
+  is(e.accelerationIncludingGravity.y, null);
+  is(e.accelerationIncludingGravity.z, null);
+  is(typeof e.rotationRate, "object");
+  is(e.rotationRate.alpha, null);
+  is(e.rotationRate.beta, null);
+  is(e.rotationRate.gamma, null);
+  is(e.interval, null);
 
-var defaultWheelEventValues = {};
-for (var i = 0; i < wheelEventProps.length; ++i) {
-  for (prop in wheelEventProps[i]) {
-    if (!isMethodResultInitializer(prop)) {
-      ok(prop in e, "WheelEvent: WheelEvent doesn't have property " + prop + "!");
-    }
-    defaultWheelEventValues[prop] = wheelEventProps[i][prop]; 
-  }
-}
-
-while (testWheelProps.length) {
-  var p = testWheelProps.shift();
-  e = new WheelEvent("foo", p);
-  for (var def in defaultWheelEventValues) {
-    if (!(def in p)) {
-      is(getPropValue(e, def), defaultWheelEventValues[def],
-         "WheelEvent: Wrong default value for " + def + "!");
-    } else {
-      is(getPropValue(e, def), p[def], "WheelEvent: Wrong event init value for " + def + "!");
-    }
-  }
-}
-
-// DragEvent
-
-try {
-  e = new DragEvent();
-} catch(exp) {
-  ex = true;
-}
-ok(ex, "DragEvent: First parameter is required!");
-ex = false;
-
-e = new DragEvent("hello", { buttons: 1, movementX: 2, movementY: 3});
-is(e.type, "hello", "DragEvent: Wrong event type!");
-is(e.buttons, 1);
-is(e.movementX, 2);
-is(e.movementY, 3);
-document.dispatchEvent(e);
-is(receivedEvent, e, "DragEvent: Wrong event!");
-
-// TransitionEvent
-e = new TransitionEvent("hello", { propertyName: "color", elapsedTime: 3.5, pseudoElement: "", foobar: "baz" })
-is("propertyName" in e, true, "Transition events have propertyName property");
-is("foobar" in e, false, "Transition events do not copy random properties from event init");
-is(e.propertyName, "color", "Transition event copies propertyName from TransitionEventInit");
-is(e.elapsedTime, 3.5, "Transition event copies elapsedTime from TransitionEventInit");
-is(e.pseudoElement, "", "Transition event copies pseudoElement from TransitionEventInit");
-is(e.bubbles, false, "Lack of bubbles property in TransitionEventInit");
-is(e.cancelable, false, "Lack of cancelable property in TransitionEventInit");
-is(e.type, "hello", "Wrong event type!");
-is(e.isTrusted, false, "Event shouldn't be trusted!");
-is(e.eventPhase, Event.NONE, "Wrong event phase");
-
-// AnimationEvent
-e = new AnimationEvent("hello", { animationName: "bounce3", elapsedTime: 3.5, pseudoElement: "", foobar: "baz" })
-is("animationName" in e, true, "Animation events have animationName property");
-is("foobar" in e, false, "Animation events do not copy random properties from event init");
-is(e.animationName, "bounce3", "Animation event copies animationName from AnimationEventInit");
-is(e.elapsedTime, 3.5, "Animation event copies elapsedTime from AnimationEventInit");
-is(e.pseudoElement, "", "Animation event copies pseudoElement from AnimationEventInit");
-is(e.bubbles, false, "Lack of bubbles property in AnimationEventInit");
-is(e.cancelable, false, "Lack of cancelable property in AnimationEventInit");
-is(e.type, "hello", "Wrong event type!");
-is(e.isTrusted, false, "Event shouldn't be trusted!");
-is(e.eventPhase, Event.NONE, "Wrong event phase");
+  SimpleTest.finish();
+});
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -350,8 +350,12 @@ ScriptSourceNotAllowed=<script> source URI is not allowed in this document: “%S”.
 ModuleSourceNotAllowed=Module source URI is not allowed in this document: “%S”.
 # LOCALIZATION NOTE: %1$S is the invalid property value and %2$S is the property name.
 InvalidKeyframePropertyValue=Keyframe property value “%1$S” is invalid according to the syntax for “%2$S”.
 # LOCALIZATION NOTE: Do not translate "ReadableStream".
 ReadableStreamReadingFailed=Failed to read data from the ReadableStream: “%S”.
 # LOCALIZATION NOTE: Do not translate "registerProtocolHandler".
 RegisterProtocolHandlerInsecureWarning=Use of the registerProtocolHandler for insecure connections will be removed in version 62.
 MixedDisplayObjectSubrequestWarning=Loading insecure content within a plugin embedded in a secure connection is going to be removed.
+MotionEventWarning=Use of the motion sensor is deprecated.
+OrientationEventWarning=Use of the orientation sensor is deprecated.
+ProximityEventWarning=Use of the proximity sensor is deprecated.
+AmbientLightEventWarning=Use of the ambient light sensor is deprecated.
--- a/dom/system/nsDeviceSensors.cpp
+++ b/dom/system/nsDeviceSensors.cpp
@@ -32,16 +32,22 @@
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace hal;
 
 #undef near
 
 #define DEFAULT_SENSOR_POLL 100
 
+static bool gPrefSensorsEnabled = false;
+static bool gPrefMotionSensorEnabled = false;
+static bool gPrefOrientationSensorEnabled = false;
+static bool gPrefProximitySensorEnabled = false;
+static bool gPrefAmbientLightSensorEnabled = false;
+
 static const nsTArray<nsIDOMWindow*>::index_type NoIndex =
   nsTArray<nsIDOMWindow*>::NoIndex;
 
 class nsDeviceSensorData final : public nsIDeviceSensorData
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDEVICESENSORDATA
@@ -101,17 +107,31 @@ NS_IMETHODIMP nsDeviceSensorData::GetZ(d
 }
 
 NS_IMPL_ISUPPORTS(nsDeviceSensors, nsIDeviceSensors)
 
 nsDeviceSensors::nsDeviceSensors()
 {
   mIsUserProximityNear = false;
   mLastDOMMotionEventTime = TimeStamp::Now();
-  mEnabled = Preferences::GetBool("device.sensors.enabled", true);
+  Preferences::AddBoolVarCache(&gPrefSensorsEnabled,
+                              "device.sensors.enabled",
+                              true);
+  Preferences::AddBoolVarCache(&gPrefMotionSensorEnabled,
+                              "device.sensors.motion.enabled",
+                              true);
+  Preferences::AddBoolVarCache(&gPrefOrientationSensorEnabled,
+                              "device.sensors.orientation.enabled",
+                              true);
+  Preferences::AddBoolVarCache(&gPrefProximitySensorEnabled,
+                              "device.sensors.proximity.enabled",
+                              false);
+  Preferences::AddBoolVarCache(&gPrefAmbientLightSensorEnabled,
+                              "device.sensors.ambientLight.enabled",
+                              false);
 
   for (int i = 0; i < NUM_SENSOR_TYPE; i++) {
     nsTArray<nsIDOMWindow*> *windows = new nsTArray<nsIDOMWindow*>();
     mWindowListeners.AppendElement(windows);
   }
 
   mLastDOMMotionEventTime = TimeStamp::Now();
 }
@@ -125,17 +145,17 @@ nsDeviceSensors::~nsDeviceSensors()
 
   for (int i = 0; i < NUM_SENSOR_TYPE; i++) {
     delete mWindowListeners[i];
   }
 }
 
 NS_IMETHODIMP nsDeviceSensors::HasWindowListener(uint32_t aType, nsIDOMWindow *aWindow, bool *aRetVal)
 {
-  if (AreSensorEventsDisabled(aWindow))
+  if (!IsSensorAllowedByPref(aType, aWindow))
     *aRetVal = false;
   else
     *aRetVal = mWindowListeners[aType]->IndexOf(aWindow) != NoIndex;
 
   return NS_OK;
 }
 
 class DeviceSensorTestEvent : public Runnable
@@ -166,17 +186,17 @@ private:
   RefPtr<nsDeviceSensors> mTarget;
   uint32_t mType;
 };
 
 static bool sTestSensorEvents = false;
 
 NS_IMETHODIMP nsDeviceSensors::AddWindowListener(uint32_t aType, nsIDOMWindow *aWindow)
 {
-  if (AreSensorEventsDisabled(aWindow))
+  if (!IsSensorAllowedByPref(aType, aWindow))
     return NS_OK;
 
   if (mWindowListeners[aType]->IndexOf(aWindow) != NoIndex)
     return NS_OK;
 
   if (!IsSensorEnabled(aType)) {
     RegisterSensorObserver((SensorType)aType, this);
   }
@@ -582,22 +602,69 @@ nsDeviceSensors::FireDOMMotionEvent(nsID
 
   mLastRotationRate.reset();
   mLastAccelerationIncludingGravity.reset();
   mLastAcceleration.reset();
   mLastDOMMotionEventTime = TimeStamp::Now();
 }
 
 bool
-nsDeviceSensors::AreSensorEventsDisabled(nsIDOMWindow* aWindow)
+nsDeviceSensors::IsSensorAllowedByPref(uint32_t aType, nsIDOMWindow* aWindow)
 {
-  if (!mEnabled) {
-    return true;
+  // checks "device.sensors.enabled" master pref
+  if (!gPrefSensorsEnabled) {
+    return false;
   }
 
   nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aWindow);
+  nsCOMPtr<nsIDocument> doc;
+  if (window) {
+    doc = window->GetExtantDoc();
+  }
 
-  if (!window) {
+  switch (aType) {
+  case nsIDeviceSensorData::TYPE_LINEAR_ACCELERATION:
+  case nsIDeviceSensorData::TYPE_ACCELERATION:
+  case nsIDeviceSensorData::TYPE_GYROSCOPE:
+    // checks "device.sensors.motion.enabled" pref
+    if (!gPrefMotionSensorEnabled) {
+      return false;
+    } else if (doc) {
+      doc->WarnOnceAbout(nsIDocument::eMotionEvent);
+    }
+    break;
+  case nsIDeviceSensorData::TYPE_GAME_ROTATION_VECTOR:
+  case nsIDeviceSensorData::TYPE_ORIENTATION:
+  case nsIDeviceSensorData::TYPE_ROTATION_VECTOR:
+    // checks "device.sensors.orientation.enabled" pref
+    if (!gPrefOrientationSensorEnabled) {
+      return false;
+    } else if (doc) {
+      doc->WarnOnceAbout(nsIDocument::eOrientationEvent);
+    }
+    break;
+  case nsIDeviceSensorData::TYPE_PROXIMITY:
+    // checks "device.sensors.proximity.enabled" pref
+    if (!gPrefProximitySensorEnabled) {
+      return false;
+    } else if (doc) {
+      doc->WarnOnceAbout(nsIDocument::eProximityEvent, true);
+    }
+    break;
+  case nsIDeviceSensorData::TYPE_LIGHT:
+    // checks "device.sensors.ambientLight.enabled" pref
+    if (!gPrefAmbientLightSensorEnabled) {
+      return false;
+    } else if (doc) {
+      doc->WarnOnceAbout(nsIDocument::eAmbientLightEvent, true);
+    }
+    break;
+  default:
+    MOZ_ASSERT_UNREACHABLE("Device sensor type not recognised");
     return false;
   }
 
-  return nsContentUtils::ShouldResistFingerprinting(window->GetDocShell());
+  if (!window) {
+    return true;
+  }
+
+  return !nsContentUtils::ShouldResistFingerprinting(window->GetDocShell());
 }
--- a/dom/system/nsDeviceSensors.h
+++ b/dom/system/nsDeviceSensors.h
@@ -64,23 +64,21 @@ private:
   void FireDOMMotionEvent(nsIDocument* domDoc,
                           mozilla::dom::EventTarget* target,
                           uint32_t type,
                           PRTime timestamp,
                           double x,
                           double y,
                           double z);
 
-  bool mEnabled;
-
   inline bool IsSensorEnabled(uint32_t aType) {
     return mWindowListeners[aType]->Length() > 0;
   }
 
-  bool AreSensorEventsDisabled(nsIDOMWindow* aWindow);
+  bool IsSensorAllowedByPref(uint32_t aType, nsIDOMWindow* aWindow);
 
   mozilla::TimeStamp mLastDOMMotionEventTime;
   bool mIsUserProximityNear;
   mozilla::Maybe<DeviceAccelerationInit> mLastAcceleration;
   mozilla::Maybe<DeviceAccelerationInit> mLastAccelerationIncludingGravity;
   mozilla::Maybe<DeviceRotationRateInit> mLastRotationRate;
 };
 
--- a/dom/tests/mochitest/general/test_interfaces.js
+++ b/dom/tests/mochitest/general/test_interfaces.js
@@ -274,23 +274,23 @@ var interfaceNamesInGlobalScope =
     {name: "DataTransfer", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DataTransferItem", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DataTransferItemList", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DelayNode", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "DeviceLightEvent", insecureContext: true},
+    {name: "DeviceLightEvent", insecureContext: true, release: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DeviceMotionEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DeviceOrientationEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "DeviceProximityEvent", insecureContext: true},
+    {name: "DeviceProximityEvent", insecureContext: true, release: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "Directory", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "Document", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DocumentFragment", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "DocumentTimeline", insecureContext: true, release: false},
@@ -1144,17 +1144,17 @@ var interfaceNamesInGlobalScope =
     {name: "U2F", insecureContext: true, disabled: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "UIEvent", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "URL", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "URLSearchParams", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "UserProximityEvent", insecureContext: true},
+    {name: "UserProximityEvent", insecureContext: true, release: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "ValidityState", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "VideoPlaybackQuality", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "VideoStreamTrack", insecureContext: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "VRDisplay", insecureContext: true, releaseNonWindowsAndMac: false},
--- a/dom/webidl/DeviceLightEvent.webidl
+++ b/dom/webidl/DeviceLightEvent.webidl
@@ -1,15 +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(DOMString type, optional DeviceLightEventInit eventInitDict)]
+[Pref="device.sensors.ambientLight.enabled", Func="nsGlobalWindowInner::DeviceSensorsEnabled", Constructor(DOMString type, optional DeviceLightEventInit eventInitDict)]
 interface DeviceLightEvent : Event
 {
   readonly attribute unrestricted double value;
 };
 
 dictionary DeviceLightEventInit : EventInit
 {
   unrestricted double value = Infinity;
--- a/dom/webidl/DeviceMotionEvent.webidl
+++ b/dom/webidl/DeviceMotionEvent.webidl
@@ -13,17 +13,17 @@ interface DeviceAcceleration {
 
 [NoInterfaceObject]
 interface DeviceRotationRate {
   readonly attribute double? alpha;
   readonly attribute double? beta;
   readonly attribute double? gamma;
 };
 
-[Constructor(DOMString type, optional DeviceMotionEventInit eventInitDict)]
+[Pref="device.sensors.motion.enabled", Func="nsGlobalWindowInner::DeviceSensorsEnabled", Constructor(DOMString type, optional DeviceMotionEventInit eventInitDict)]
 interface DeviceMotionEvent : Event {
   readonly attribute DeviceAcceleration? acceleration;
   readonly attribute DeviceAcceleration? accelerationIncludingGravity;
   readonly attribute DeviceRotationRate? rotationRate;
   readonly attribute double? interval;
 };
 
 dictionary DeviceAccelerationInit {
--- a/dom/webidl/DeviceOrientationEvent.webidl
+++ b/dom/webidl/DeviceOrientationEvent.webidl
@@ -1,15 +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(DOMString type, optional DeviceOrientationEventInit eventInitDict), LegacyEventInit]
+[Pref="device.sensors.orientation.enabled", Func="nsGlobalWindowInner::DeviceSensorsEnabled", Constructor(DOMString type, optional DeviceOrientationEventInit eventInitDict), LegacyEventInit]
 interface DeviceOrientationEvent : Event
 {
   readonly attribute double? alpha;
   readonly attribute double? beta;
   readonly attribute double? gamma;
   readonly attribute boolean absolute;
 
   // initDeviceOrientationEvent is a Gecko specific deprecated method.
--- a/dom/webidl/DeviceProximityEvent.webidl
+++ b/dom/webidl/DeviceProximityEvent.webidl
@@ -1,15 +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(DOMString type, optional DeviceProximityEventInit eventInitDict)]
+[Pref="device.sensors.proximity.enabled", Func="nsGlobalWindowInner::DeviceSensorsEnabled", Constructor(DOMString type, optional DeviceProximityEventInit eventInitDict)]
 interface DeviceProximityEvent : Event
 {
   readonly attribute double value;
   readonly attribute double min;
   readonly attribute double max;
 };
 
 dictionary DeviceProximityEventInit : EventInit
--- a/dom/webidl/UserProximityEvent.webidl
+++ b/dom/webidl/UserProximityEvent.webidl
@@ -1,15 +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(DOMString type, optional UserProximityEventInit eventInitDict)]
+[Pref="device.sensors.proximity.enabled", Func="nsGlobalWindowInner::DeviceSensorsEnabled", Constructor(DOMString type, optional UserProximityEventInit eventInitDict)]
 interface UserProximityEvent : Event
 {
   readonly attribute boolean near;
 };
 
 dictionary UserProximityEventInit : EventInit
 {
   boolean near = false;
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5060,18 +5060,27 @@ pref("layers.shared-buffer-provider.enab
 pref("layers.force-active", false);
 
 // Enable/Disable the geolocation API for content
 pref("geo.enabled", true);
 
 // Timeout for outbound network geolocation provider XHR
 pref("geo.wifi.xhr.timeout", 60000);
 
-// Enable/Disable the orientation API for content
+// Enable/Disable the various sensor APIs for content
 pref("device.sensors.enabled", true);
+pref("device.sensors.orientation.enabled", true);
+pref("device.sensors.motion.enabled", true);
+#ifdef EARLY_BETA_OR_EARLIER
+pref("device.sensors.proximity.enabled", false);
+pref("device.sensors.ambientLight.enabled", false);
+#else
+pref("device.sensors.proximity.enabled", true);
+pref("device.sensors.ambientLight.enabled", true);
+#endif
 
 // Enable/Disable the device storage API for content
 pref("device.storage.enabled", false);
 
 // Toggle which thread the HTML5 parser uses for stream parsing
 pref("html5.offmainthread", true);
 // Time in milliseconds between the time a network buffer is seen and the
 // timer firing when the timer hasn't fired previously in this parse in the