Bug 1359076: Disable all Device Sensor APIs except orientation and ambient light by default r?bkelly
This patch disables device sensors except orientation and ambient light by default.
It implements per-sensor prefs to disable orientation, proximity and ambient light
selectively. The patch also makes the pref checks happen at runtime (versus on process
start) using Preferences::AddBoolVarCache.
MozReview-Commit-ID: EA8ARjjtlkF
--- a/dom/events/test/test_bug742376.html
+++ b/dom/events/test/test_bug742376.html
@@ -11,64 +11,69 @@ https://bugzilla.mozilla.org/show_bug.cg
</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() {
-
- var Cc = SpecialPowers.Cc;
- var Ci = SpecialPowers.Ci;
- var dss = Cc["@mozilla.org/devicesensors;1"].getService(Ci.nsIDeviceSensors);
+SpecialPowers.pushPrefEnv({"set": [["device.sensors.enabled", true],
+ ["device.sensors.orientation.enabled", true]] })
+.then(function() {
- 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);
-}
+ function hasListeners() {
-is(hasListeners(), false, "Must not have listeners before tests start");
+ var Cc = SpecialPowers.Cc;
+ var Ci = SpecialPowers.Ci;
+ var dss = Cc["@mozilla.org/devicesensors;1"].getService(Ci.nsIDeviceSensors);
-function dumbListener(event) {}
-function dumbListener2(event) {}
-function dumbListener3(event) {}
+ 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");
-window.addEventListener("deviceorientation", dumbListener);
-window.addEventListener("random_event_name", function() {});
-window.addEventListener("deviceorientation", dumbListener2);
+ function dumbListener(event) {}
+ function dumbListener2(event) {}
+ function dumbListener3(event) {}
-is(hasListeners(), true, "Listeners should have been added");
+ window.addEventListener("deviceorientation", dumbListener);
+ window.addEventListener("random_event_name", function() {});
+ window.addEventListener("deviceorientation", dumbListener2);
-window.setTimeout(function() {
+ is(hasListeners(), true, "Listeners should have been added");
- window.removeEventListener("deviceorientation", dumbListener);
- is(hasListeners(), true, "Only some listeners should have been removed");
window.setTimeout(function() {
- window.removeEventListener("deviceorientation", dumbListener2);
+ window.removeEventListener("deviceorientation", dumbListener);
+ is(hasListeners(), true, "Only some listeners should have been removed");
window.setTimeout(function() {
- is(hasListeners(), false, "Listeners should have been removed");
- testEventHandler();
+
+ window.removeEventListener("deviceorientation", dumbListener2);
+ window.setTimeout(function() {
+ is(hasListeners(), false, "Listeners should have been removed");
+ testEventHandler();
+ }, 0);
}, 0);
}, 0);
-}, 0);
-function testEventHandler() {
- window.ondeviceorientation = function() {}
- window.setTimeout(function() {
- is(hasListeners(), true, "Handler should have been added");
- window.ondeviceorientation = null;
+ function testEventHandler() {
+ window.ondeviceorientation = function() {}
window.setTimeout(function() {
- is(hasListeners(), false, "Handler should have been removed");
- SimpleTest.finish();
- }, 0);
- }, 0)
-}
+ is(hasListeners(), true, "Handler should have been added");
+ window.ondeviceorientation = null;
+ window.setTimeout(function() {
+ is(hasListeners(), false, "Handler should have been removed");
+ SimpleTest.finish();
+ }, 0);
+ }, 0)
+ }
+});
SimpleTest.waitForExplicitFinish();
</script>
</pre>
</body>
</html>
--- a/dom/system/nsDeviceSensors.cpp
+++ b/dom/system/nsDeviceSensors.cpp
@@ -31,16 +31,21 @@
using namespace mozilla;
using namespace mozilla::dom;
using namespace hal;
#undef near
#define DEFAULT_SENSOR_POLL 100
+static bool gPrefSensorsEnabled= 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
@@ -100,17 +105,28 @@ 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(&gPrefOrientationSensorEnabled,
+ "device.sensors.orientation.enabled",
+ true);
+ Preferences::AddBoolVarCache(&gPrefProximitySensorEnabled,
+ "device.sensors.proximity.enabled",
+ false);
+ Preferences::AddBoolVarCache(&gPrefAmbientLightSensorEnabled,
+ "device.sensors.ambient_lightenabled",
+ false);
for (int i = 0; i < NUM_SENSOR_TYPE; i++) {
nsTArray<nsIDOMWindow*> *windows = new nsTArray<nsIDOMWindow*>();
mWindowListeners.AppendElement(windows);
}
mLastDOMMotionEventTime = TimeStamp::Now();
}
@@ -124,17 +140,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
@@ -165,17 +181,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);
}
@@ -565,22 +581,43 @@ 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;
+ }
+ switch (aType) {
+ case nsIDeviceSensorData::TYPE_LINEAR_ACCELERATION:
+ case nsIDeviceSensorData::TYPE_ACCELERATION:
+ case nsIDeviceSensorData::TYPE_GYROSCOPE:
+ 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; }
+ break;
+
+ case nsIDeviceSensorData::TYPE_PROXIMITY:
+ // checks "device.sensors.proximity.enabled" pref
+ if (!gPrefProximitySensorEnabled) { return false; }
+ break;
+ case nsIDeviceSensorData::TYPE_LIGHT:
+ // checks "device.sensors.ambient_light.enabled" pref
+ if (!gPrefAmbientLightSensorEnabled) { return false; }
+ break;
}
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aWindow);
if (!window) {
- return false;
+ return true;
}
- return nsContentUtils::ShouldResistFingerprinting(window->GetDocShell());
+ return !nsContentUtils::ShouldResistFingerprinting(window->GetDocShell());
}
--- a/dom/system/nsDeviceSensors.h
+++ b/dom/system/nsDeviceSensors.h
@@ -63,23 +63,21 @@ private:
void FireDOMMotionEvent(class nsIDOMDocument *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/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4908,18 +4908,22 @@ pref("webrender.highlight-painted-layers
pref("gfx.webrender.layers-free", 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);
+// orientation is for DOMOrientationEvent and DOMMotionEvent
+pref("device.sensors.orientation.enabled", true);
+pref("device.sensors.proximity.enabled", false);
+pref("device.sensors.ambient_light.enabled", false);
// 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