Bug 1382533 - Disable Presentation API when privacy.resistFingerprinting = true
MozReview-Commit-ID: IDKEqSqm9Ug
--- a/dom/presentation/Presentation.cpp
+++ b/dom/presentation/Presentation.cpp
@@ -58,38 +58,50 @@ Presentation::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
return PresentationBinding::Wrap(aCx, this, aGivenProto);
}
void
Presentation::SetDefaultRequest(PresentationRequest* aRequest)
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return;
+ }
+
nsCOMPtr<nsIDocument> doc = mWindow ? mWindow->GetExtantDoc() : nullptr;
if (NS_WARN_IF(!doc)) {
return;
}
if (doc->GetSandboxFlags() & SANDBOXED_PRESENTATION) {
return;
}
mDefaultRequest = aRequest;
}
already_AddRefed<PresentationRequest>
Presentation::GetDefaultRequest() const
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return nullptr;
+ }
+
RefPtr<PresentationRequest> request = mDefaultRequest;
return request.forget();
}
already_AddRefed<PresentationReceiver>
Presentation::GetReceiver()
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return nullptr;
+ }
+
// return the same receiver if already created
if (mReceiver) {
RefPtr<PresentationReceiver> receiver = mReceiver;
return receiver.forget();
}
if (!HasReceiverSupport() || !IsInPresentedContent()) {
return nullptr;
--- a/dom/presentation/PresentationAvailability.cpp
+++ b/dom/presentation/PresentationAvailability.cpp
@@ -4,16 +4,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "PresentationAvailability.h"
#include "mozilla/dom/PresentationAvailabilityBinding.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/Unused.h"
+#include "nsContentUtils.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIPresentationDeviceManager.h"
#include "nsIPresentationService.h"
#include "nsServiceManagerUtils.h"
#include "PresentationLog.h"
using namespace mozilla;
using namespace mozilla::dom;
@@ -152,16 +153,20 @@ void
PresentationAvailability::EnqueuePromise(RefPtr<Promise>& aPromise)
{
mPromises.AppendElement(aPromise);
}
bool
PresentationAvailability::Value() const
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return false;
+ }
+
return mIsAvailable;
}
NS_IMETHODIMP
PresentationAvailability::NotifyAvailableChange(const nsTArray<nsString>& aAvailabilityUrls,
bool aIsAvailable)
{
bool available = false;
@@ -186,22 +191,31 @@ PresentationAvailability::UpdateAvailabi
bool isChanged = (aIsAvailable != mIsAvailable);
mIsAvailable = aIsAvailable;
if (!mPromises.IsEmpty()) {
// Use the first availability change notification to resolve promise.
do {
nsTArray<RefPtr<Promise>> promises = Move(mPromises);
+
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ continue;
+ }
+
for (auto& promise : promises) {
promise->MaybeResolve(this);
}
// more promises may have been added to mPromises, at least in theory
} while (!mPromises.IsEmpty());
return;
}
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return;
+ }
+
if (isChanged) {
Unused <<
NS_WARN_IF(NS_FAILED(DispatchTrustedEvent(NS_LITERAL_STRING("change"))));
}
}
--- a/dom/presentation/PresentationConnection.cpp
+++ b/dom/presentation/PresentationConnection.cpp
@@ -152,47 +152,73 @@ PresentationConnection::WrapObject(JSCon
JS::Handle<JSObject*> aGivenProto)
{
return PresentationConnectionBinding::Wrap(aCx, this, aGivenProto);
}
void
PresentationConnection::GetId(nsAString& aId) const
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ aId = EmptyString();
+ return;
+ }
+
aId = mId;
}
void
PresentationConnection::GetUrl(nsAString& aUrl) const
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ aUrl = EmptyString();
+ return;
+ }
+
aUrl = mUrl;
}
PresentationConnectionState
PresentationConnection::State() const
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return PresentationConnectionState::Terminated;
+ }
+
return mState;
}
PresentationConnectionBinaryType
PresentationConnection::BinaryType() const
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return PresentationConnectionBinaryType::Blob;
+ }
+
return mBinaryType;
}
void
PresentationConnection::SetBinaryType(PresentationConnectionBinaryType aType)
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return;
+ }
+
mBinaryType = aType;
}
void
PresentationConnection::Send(const nsAString& aData,
ErrorResult& aRv)
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return;
+ }
+
// Sending is not allowed if the session is not connected.
if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
@@ -212,16 +238,20 @@ PresentationConnection::Send(const nsASt
NS_LITERAL_STRING("\""));
}
}
void
PresentationConnection::Send(Blob& aData,
ErrorResult& aRv)
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return;
+ }
+
if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if(NS_WARN_IF(!service)) {
@@ -236,16 +266,20 @@ PresentationConnection::Send(Blob& aData
NS_LITERAL_STRING("Unable to send binary message for Blob message."));
}
}
void
PresentationConnection::Send(const ArrayBuffer& aData,
ErrorResult& aRv)
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return;
+ }
+
if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if(NS_WARN_IF(!service)) {
@@ -268,16 +302,20 @@ PresentationConnection::Send(const Array
NS_LITERAL_STRING("Unable to send binary message for ArrayBuffer message."));
}
}
void
PresentationConnection::Send(const ArrayBufferView& aData,
ErrorResult& aRv)
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return;
+ }
+
if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if(NS_WARN_IF(!service)) {
@@ -299,16 +337,20 @@ PresentationConnection::Send(const Array
AsyncCloseConnectionWithErrorMsg(
NS_LITERAL_STRING("Unable to send binary message for ArrayBufferView message."));
}
}
void
PresentationConnection::Close(ErrorResult& aRv)
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return;
+ }
+
// It only works when the state is CONNECTED or CONNECTING.
if (NS_WARN_IF(mState != PresentationConnectionState::Connected &&
mState != PresentationConnectionState::Connecting)) {
return;
}
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
@@ -321,16 +363,20 @@ PresentationConnection::Close(ErrorResul
service->CloseSession(mId,
mRole,
nsIPresentationService::CLOSED_REASON_CLOSED)));
}
void
PresentationConnection::Terminate(ErrorResult& aRv)
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return;
+ }
+
// It only works when the state is CONNECTED.
if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
return;
}
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if(NS_WARN_IF(!service)) {
@@ -407,16 +453,20 @@ PresentationConnection::NotifyStateChang
nsresult
PresentationConnection::ProcessStateChanged(nsresult aReason)
{
switch (mState) {
case PresentationConnectionState::Connecting:
return NS_OK;
case PresentationConnectionState::Connected: {
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return NS_OK;
+ }
+
RefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(this, NS_LITERAL_STRING("connect"), false);
return asyncDispatcher->PostDOMEvent();
}
case PresentationConnectionState::Closed: {
PresentationConnectionClosedReason reason =
PresentationConnectionClosedReason::Closed;
@@ -436,20 +486,22 @@ PresentationConnection::ProcessStateChan
}
Unused <<
NS_WARN_IF(NS_FAILED(DispatchConnectionCloseEvent(reason, errorMsg)));
return RemoveFromLoadGroup();
}
case PresentationConnectionState::Terminated: {
- // Ensure onterminate event is fired.
- RefPtr<AsyncEventDispatcher> asyncDispatcher =
- new AsyncEventDispatcher(this, NS_LITERAL_STRING("terminate"), false);
- Unused << NS_WARN_IF(NS_FAILED(asyncDispatcher->PostDOMEvent()));
+ if (!nsContentUtils::ShouldResistFingerprinting()) {
+ // Ensure onterminate event is fired.
+ RefPtr<AsyncEventDispatcher> asyncDispatcher =
+ new AsyncEventDispatcher(this, NS_LITERAL_STRING("terminate"), false);
+ Unused << NS_WARN_IF(NS_FAILED(asyncDispatcher->PostDOMEvent()));
+ }
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if (NS_WARN_IF(!service)) {
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = service->UnregisterSessionListener(mId, mRole);
@@ -490,16 +542,20 @@ PresentationConnection::NotifyMessage(co
}
return NS_OK;
}
nsresult
PresentationConnection::DoReceiveMessage(const nsACString& aData, bool aIsBinary)
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return NS_OK;
+ }
+
// Transform the data.
AutoJSAPI jsapi;
if (!jsapi.Init(GetOwner())) {
return NS_ERROR_FAILURE;
}
JSContext* cx = jsapi.cx();
JS::Rooted<JS::Value> jsData(cx);
@@ -535,16 +591,20 @@ PresentationConnection::DoReceiveMessage
}
nsresult
PresentationConnection::DispatchConnectionCloseEvent(
PresentationConnectionClosedReason aReason,
const nsAString& aMessage,
bool aDispatchNow)
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return NS_OK;
+ }
+
if (mState != PresentationConnectionState::Closed) {
MOZ_ASSERT(false, "The connection state should be closed.");
return NS_ERROR_FAILURE;
}
PresentationConnectionCloseEventInit init;
init.mReason = aReason;
init.mMessage = aMessage;
--- a/dom/presentation/PresentationConnectionList.cpp
+++ b/dom/presentation/PresentationConnectionList.cpp
@@ -1,16 +1,17 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "PresentationConnectionList.h"
+#include "nsContentUtils.h"
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/dom/PresentationConnectionAvailableEvent.h"
#include "mozilla/dom/PresentationConnectionListBinding.h"
#include "mozilla/dom/Promise.h"
#include "PresentationConnection.h"
namespace mozilla {
namespace dom {
@@ -40,23 +41,32 @@ PresentationConnectionList::WrapObject(J
{
return PresentationConnectionListBinding::Wrap(aCx, this, aGivenProto);
}
void
PresentationConnectionList::GetConnections(
nsTArray<RefPtr<PresentationConnection>>& aConnections) const
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ aConnections.Clear();
+ return;
+ }
+
aConnections = mConnections;
}
nsresult
PresentationConnectionList::DispatchConnectionAvailableEvent(
PresentationConnection* aConnection)
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return NS_OK;
+ }
+
PresentationConnectionAvailableEventInit init;
init.mConnection = aConnection;
RefPtr<PresentationConnectionAvailableEvent> event =
PresentationConnectionAvailableEvent::Constructor(
this,
NS_LITERAL_STRING("connectionavailable"),
init);
@@ -99,17 +109,19 @@ PresentationConnectionList::NotifyStateC
FindConnectionById(aSessionId) != mConnections.NoIndex ? true : false;
PresentationConnectionListBinding::ClearCachedConnectionsValue(this);
switch (aConnection->State()) {
case PresentationConnectionState::Connected:
if (!connectionFound) {
mConnections.AppendElement(aConnection);
if (mGetConnectionListPromise) {
- mGetConnectionListPromise->MaybeResolve(this);
+ if (!nsContentUtils::ShouldResistFingerprinting()) {
+ mGetConnectionListPromise->MaybeResolve(this);
+ }
mGetConnectionListPromise = nullptr;
return;
}
}
DispatchConnectionAvailableEvent(aConnection);
break;
case PresentationConnectionState::Terminated:
if (connectionFound) {
--- a/dom/presentation/PresentationReceiver.cpp
+++ b/dom/presentation/PresentationReceiver.cpp
@@ -140,16 +140,19 @@ PresentationReceiver::GetConnectionList(
[self]() -> void { self->CreateConnectionList(); }));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
}
}
RefPtr<Promise> promise = mGetConnectionListPromise;
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
+ }
return promise.forget();
}
void
PresentationReceiver::CreateConnectionList()
{
MOZ_ASSERT(mGetConnectionListPromise);
--- a/dom/presentation/PresentationRequest.cpp
+++ b/dom/presentation/PresentationRequest.cpp
@@ -167,16 +167,21 @@ PresentationRequest::StartWithDevice(con
return nullptr;
}
RefPtr<Promise> promise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
+ return promise.forget();
+ }
+
if (IsProhibitMixedSecurityContexts(doc) &&
!IsAllURLAuthenticated()) {
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
return promise.forget();
}
if (doc->GetSandboxFlags() & SANDBOXED_PRESENTATION) {
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
@@ -266,16 +271,21 @@ PresentationRequest::Reconnect(const nsA
return nullptr;
}
RefPtr<Promise> promise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
+ return promise.forget();
+ }
+
if (IsProhibitMixedSecurityContexts(doc) &&
!IsAllURLAuthenticated()) {
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
return promise.forget();
}
if (doc->GetSandboxFlags() & SANDBOXED_PRESENTATION) {
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
@@ -379,16 +389,21 @@ PresentationRequest::GetAvailability(Err
return nullptr;
}
RefPtr<Promise> promise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
+ return promise.forget();
+ }
+
if (IsProhibitMixedSecurityContexts(doc) &&
!IsAllURLAuthenticated()) {
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
return promise.forget();
}
if (doc->GetSandboxFlags() & SANDBOXED_PRESENTATION) {
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
@@ -438,16 +453,20 @@ PresentationRequest::FindOrCreatePresent
aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return;
}
}
nsresult
PresentationRequest::DispatchConnectionAvailableEvent(PresentationConnection* aConnection)
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return NS_OK;
+ }
+
PresentationConnectionAvailableEventInit init;
init.mConnection = aConnection;
RefPtr<PresentationConnectionAvailableEvent> event =
PresentationConnectionAvailableEvent::Constructor(this,
NS_LITERAL_STRING("connectionavailable"),
init);
if (NS_WARN_IF(!event)) {
--- a/dom/presentation/PresentationSessionInfo.cpp
+++ b/dom/presentation/PresentationSessionInfo.cpp
@@ -640,16 +640,20 @@ PresentationControllingInfo::Shutdown(ns
Unused << NS_WARN_IF(NS_FAILED(mServerSocket->Close()));
mServerSocket = nullptr;
}
}
nsresult
PresentationControllingInfo::GetAddress()
{
+ if (nsContentUtils::ShouldResistFingerprinting()) {
+ return NS_ERROR_FAILURE;
+ }
+
#if defined(MOZ_WIDGET_ANDROID)
RefPtr<PresentationNetworkHelper> networkHelper =
new PresentationNetworkHelper(this,
&PresentationControllingInfo::OnGetAddress);
nsresult rv = networkHelper->GetWifiIPAddress();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}