--- a/dom/presentation/PresentationAvailability.cpp
+++ b/dom/presentation/PresentationAvailability.cpp
@@ -1,78 +1,84 @@
/* -*- 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 "PresentationAvailability.h"
+
#include "mozilla/dom/PresentationAvailabilityBinding.h"
+#include "mozilla/dom/Promise.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIPresentationDeviceManager.h"
#include "nsIPresentationService.h"
#include "nsServiceManagerUtils.h"
-#include "PresentationAvailability.h"
using namespace mozilla;
using namespace mozilla::dom;
NS_IMPL_CYCLE_COLLECTION_CLASS(PresentationAvailability)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PresentationAvailability, DOMEventTargetHelper)
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PresentationAvailability, DOMEventTargetHelper)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise);
tmp->Shutdown();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_ADDREF_INHERITED(PresentationAvailability, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(PresentationAvailability, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PresentationAvailability)
NS_INTERFACE_MAP_ENTRY(nsIPresentationAvailabilityListener)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
/* static */ already_AddRefed<PresentationAvailability>
-PresentationAvailability::Create(nsPIDOMWindowInner* aWindow)
+PresentationAvailability::Create(nsPIDOMWindowInner* aWindow,
+ RefPtr<Promise>& aPromise)
{
- RefPtr<PresentationAvailability> availability = new PresentationAvailability(aWindow);
- return NS_WARN_IF(!availability->Init()) ? nullptr : availability.forget();
+ RefPtr<PresentationAvailability> availability =
+ new PresentationAvailability(aWindow);
+ return NS_WARN_IF(!availability->Init(aPromise)) ? nullptr
+ : availability.forget();
}
PresentationAvailability::PresentationAvailability(nsPIDOMWindowInner* aWindow)
: DOMEventTargetHelper(aWindow)
, mIsAvailable(false)
{
}
PresentationAvailability::~PresentationAvailability()
{
Shutdown();
}
bool
-PresentationAvailability::Init()
+PresentationAvailability::Init(RefPtr<Promise>& aPromise)
{
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if (NS_WARN_IF(!service)) {
return false;
}
nsresult rv = service->RegisterAvailabilityListener(this);
if (NS_WARN_IF(NS_FAILED(rv))) {
- return false;
+ // If the user agent is unable to monitor available device,
+ // Resolve promise with |value| set to false.
+ mIsAvailable = false;
+ aPromise->MaybeResolve(this);
+ return true;
}
- nsCOMPtr<nsIPresentationDeviceManager> deviceManager =
- do_GetService(PRESENTATION_DEVICE_MANAGER_CONTRACTID);
- if (NS_WARN_IF(!deviceManager)) {
- return false;
- }
- deviceManager->GetDeviceAvailable(&mIsAvailable);
+ mPromise = aPromise;
return true;
}
void PresentationAvailability::Shutdown()
{
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
@@ -109,13 +115,24 @@ PresentationAvailability::NotifyAvailabl
{
return NS_DispatchToCurrentThread(NewRunnableMethod
<bool>(this,
&PresentationAvailability::UpdateAvailabilityAndDispatchEvent,
aIsAvailable));
}
void
-PresentationAvailability::UpdateAvailabilityAndDispatchEvent(bool aIsAvailable) {
+PresentationAvailability::UpdateAvailabilityAndDispatchEvent(bool aIsAvailable)
+{
+ bool isChanged = (aIsAvailable != mIsAvailable);
+
mIsAvailable = aIsAvailable;
- NS_WARN_IF(NS_FAILED(DispatchTrustedEvent(NS_LITERAL_STRING("change"))));
+ if (mPromise) {
+ mPromise->MaybeResolve(this);
+ mPromise = nullptr;
+ return;
+ }
+
+ if (isChanged) {
+ NS_WARN_IF(NS_FAILED(DispatchTrustedEvent(NS_LITERAL_STRING("change"))));
+ }
}
--- a/dom/presentation/PresentationAvailability.h
+++ b/dom/presentation/PresentationAvailability.h
@@ -4,52 +4,58 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_PresentationAvailability_h
#define mozilla_dom_PresentationAvailability_h
#include "mozilla/DOMEventTargetHelper.h"
#include "nsIPresentationListener.h"
+#include "nsTArray.h"
namespace mozilla {
namespace dom {
+class Promise;
+
class PresentationAvailability final : public DOMEventTargetHelper
, public nsIPresentationAvailabilityListener
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PresentationAvailability,
DOMEventTargetHelper)
NS_DECL_NSIPRESENTATIONAVAILABILITYLISTENER
static already_AddRefed<PresentationAvailability>
- Create(nsPIDOMWindowInner* aWindow);
+ Create(nsPIDOMWindowInner* aWindow,
+ RefPtr<Promise>& aPromise);
virtual void DisconnectFromOwner() override;
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
// WebIDL (public APIs)
bool Value() const;
IMPL_EVENT_HANDLER(change);
private:
explicit PresentationAvailability(nsPIDOMWindowInner* aWindow);
- ~PresentationAvailability();
+ virtual ~PresentationAvailability();
- bool Init();
+ bool Init(RefPtr<Promise>& aPromise);
void Shutdown();
void UpdateAvailabilityAndDispatchEvent(bool aIsAvailable);
bool mIsAvailable;
+
+ RefPtr<Promise> mPromise;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_PresentationAvailability_h
--- a/dom/presentation/PresentationRequest.cpp
+++ b/dom/presentation/PresentationRequest.cpp
@@ -18,23 +18,21 @@
#include "nsIPresentationService.h"
#include "nsIURI.h"
#include "nsIUUIDGenerator.h"
#include "nsNetUtil.h"
#include "nsSandboxFlags.h"
#include "nsServiceManagerUtils.h"
#include "PresentationAvailability.h"
#include "PresentationCallbacks.h"
+#include "PresentationLog.h"
using namespace mozilla;
using namespace mozilla::dom;
-NS_IMPL_CYCLE_COLLECTION_INHERITED(PresentationRequest, DOMEventTargetHelper,
- mAvailability)
-
NS_IMPL_ADDREF_INHERITED(PresentationRequest, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(PresentationRequest, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PresentationRequest)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
static nsresult
GetAbsoluteURL(const nsAString& aUrl,
@@ -102,21 +100,16 @@ PresentationRequest::PresentationRequest
PresentationRequest::~PresentationRequest()
{
}
bool
PresentationRequest::Init()
{
- mAvailability = PresentationAvailability::Create(GetOwner());
- if (NS_WARN_IF(!mAvailability)) {
- return false;
- }
-
return true;
}
/* virtual */ JSObject*
PresentationRequest::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
return PresentationRequestBinding::Wrap(aCx, this, aGivenProto);
@@ -312,16 +305,18 @@ PresentationRequest::FindOrCreatePresent
if (NS_WARN_IF(NS_FAILED(rv))) {
aPromise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
}
}
already_AddRefed<Promise>
PresentationRequest::GetAvailability(ErrorResult& aRv)
{
+ PRES_DEBUG("%s:id[%s]\n", __func__,
+ NS_ConvertUTF16toUTF8(mUrl).get());
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
if (NS_WARN_IF(!global)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsCOMPtr<nsIDocument> doc = GetOwner()->GetExtantDoc();
if (NS_WARN_IF(!doc)) {
@@ -340,17 +335,28 @@ PresentationRequest::GetAvailability(Err
return promise.forget();
}
if (doc->GetSandboxFlags() & SANDBOXED_PRESENTATION) {
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
return promise.forget();
}
- promise->MaybeResolve(mAvailability);
+ // TODO
+ // Search the set of availability object and resolve
+ // promise with the one had same presentation URLs.
+
+ RefPtr<PresentationAvailability> availability =
+ PresentationAvailability::Create(GetOwner(), promise);
+
+ if (!availability) {
+ promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+ return promise.forget();
+ }
+
return promise.forget();
}
nsresult
PresentationRequest::DispatchConnectionAvailableEvent(PresentationConnection* aConnection)
{
PresentationConnectionAvailableEventInit init;
init.mConnection = aConnection;
--- a/dom/presentation/PresentationRequest.h
+++ b/dom/presentation/PresentationRequest.h
@@ -17,18 +17,16 @@ namespace dom {
class Promise;
class PresentationAvailability;
class PresentationConnection;
class PresentationRequest final : public DOMEventTargetHelper
{
public:
NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PresentationRequest,
- DOMEventTargetHelper)
static already_AddRefed<PresentationRequest> Constructor(const GlobalObject& aGlobal,
const nsAString& aUrl,
ErrorResult& aRv);
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
@@ -60,15 +58,14 @@ private:
// Implement https://w3c.github.io/webappsec-mixed-content/#categorize-settings-object
bool IsProhibitMixedSecurityContexts(nsIDocument* aDocument);
// Implement https://w3c.github.io/webappsec-mixed-content/#a-priori-authenticated-url
bool IsPrioriAuthenticatedURL(const nsAString& aUrl);
nsString mUrl;
- RefPtr<PresentationAvailability> mAvailability;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_PresentationRequest_h
--- a/dom/presentation/PresentationService.cpp
+++ b/dom/presentation/PresentationService.cpp
@@ -612,18 +612,18 @@ PresentationService::StartSession(const
// Find the designated device from available device list.
nsCOMPtr<nsIPresentationDeviceManager> deviceManager =
do_GetService(PRESENTATION_DEVICE_MANAGER_CONTRACTID);
if (NS_WARN_IF(!deviceManager)) {
return aCallback->NotifyError(NS_ERROR_DOM_OPERATION_ERR);
}
- nsCOMPtr<nsIMutableArray> presentationUrls
- = do_CreateInstance(NS_ARRAY_CONTRACTID);
+ nsCOMPtr<nsIMutableArray> presentationUrls =
+ do_CreateInstance(NS_ARRAY_CONTRACTID);
if (!presentationUrls) {
return aCallback->NotifyError(NS_ERROR_DOM_OPERATION_ERR);
}
nsCOMPtr<nsISupportsString> supportsStr =
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
supportsStr->SetData(aUrl);
presentationUrls->AppendElement(supportsStr, false);
@@ -801,21 +801,24 @@ PresentationService::BuildTransport(cons
return static_cast<PresentationControllingInfo*>(info.get())->BuildTransport();
}
NS_IMETHODIMP
PresentationService::RegisterAvailabilityListener(nsIPresentationAvailabilityListener* aListener)
{
MOZ_ASSERT(NS_IsMainThread());
- if (NS_WARN_IF(mAvailabilityListeners.Contains(aListener))) {
- return NS_OK;
+ if (!mAvailabilityListeners.Contains(aListener)) {
+ mAvailabilityListeners.AppendElement(aListener);
}
- mAvailabilityListeners.AppendElement(aListener);
+ // Leverage availablility change notification to assign
+ // the initial value of availability object.
+ NS_WARN_IF(NS_FAILED(aListener->NotifyAvailableChange(mIsAvailable)));
+
return NS_OK;
}
NS_IMETHODIMP
PresentationService::UnregisterAvailabilityListener(nsIPresentationAvailabilityListener* aListener)
{
MOZ_ASSERT(NS_IsMainThread());
--- a/dom/presentation/ipc/PresentationIPCService.cpp
+++ b/dom/presentation/ipc/PresentationIPCService.cpp
@@ -193,17 +193,17 @@ PresentationIPCService::RegisterAvailabi
NS_IMETHODIMP
PresentationIPCService::UnregisterAvailabilityListener(nsIPresentationAvailabilityListener* aListener)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aListener);
mAvailabilityListeners.RemoveElement(aListener);
- if (sPresentationChild) {
+ if (mAvailabilityListeners.IsEmpty() && sPresentationChild) {
NS_WARN_IF(!sPresentationChild->SendUnregisterAvailabilityHandler());
}
return NS_OK;
}
NS_IMETHODIMP
PresentationIPCService::RegisterSessionListener(const nsAString& aSessionId,
uint8_t aRole,
--- a/dom/presentation/tests/mochitest/mochitest.ini
+++ b/dom/presentation/tests/mochitest/mochitest.ini
@@ -68,8 +68,9 @@ skip-if = (e10s || toolkit == 'gonk' ||
skip-if = (e10s || toolkit == 'gonk' || toolkit == 'android')
[test_presentation_terminate_establish_connection_error_oop.html]
skip-if = (e10s || toolkit == 'gonk' || toolkit == 'android')
[test_presentation_sender_on_terminate_request.html]
skip-if = toolkit == 'android'
[test_presentation_sandboxed_presentation.html]
[test_presentation_reconnect.html]
[test_presentation_mixed_security_contexts.html]
+[test_presentation_availability.html]
--- a/dom/presentation/tests/mochitest/test_presentation_1ua_connection_wentaway.js
+++ b/dom/presentation/tests/mochitest/test_presentation_1ua_connection_wentaway.js
@@ -81,28 +81,29 @@ function setup() {
return Promise.resolve();
}
function testCreateRequest() {
return new Promise(function(aResolve, aReject) {
info('Sender: --- testCreateRequest ---');
request = new PresentationRequest(receiverUrl);
request.getAvailability().then((aAvailability) => {
+ is(aAvailability.value, false, "Sender: should have no available device after setup");
aAvailability.onchange = function() {
aAvailability.onchange = null;
ok(aAvailability.value, "Sender: Device should be available.");
aResolve();
}
+
+ gScript.sendAsyncMessage('trigger-device-add');
}).catch((aError) => {
ok(false, "Sender: Error occurred when getting availability: " + aError);
teardown();
aReject();
});
-
- gScript.sendAsyncMessage('trigger-device-add');
});
}
function testStartConnection() {
return new Promise(function(aResolve, aReject) {
request.start().then((aConnection) => {
connection = aConnection;
ok(connection, "Sender: Connection should be available.");
--- a/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.js
+++ b/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.js
@@ -84,28 +84,29 @@ function setup() {
return Promise.resolve();
}
function testCreateRequest() {
return new Promise(function(aResolve, aReject) {
info('Sender: --- testCreateRequest ---');
request = new PresentationRequest("file_presentation_1ua_receiver.html");
request.getAvailability().then((aAvailability) => {
+ is(aAvailability.value, false, "Sender: should have no available device after setup");
aAvailability.onchange = function() {
aAvailability.onchange = null;
ok(aAvailability.value, "Sender: Device should be available.");
aResolve();
}
+
+ gScript.sendAsyncMessage('trigger-device-add');
}).catch((aError) => {
ok(false, "Sender: Error occurred when getting availability: " + aError);
teardown();
aReject();
});
-
- gScript.sendAsyncMessage('trigger-device-add');
});
}
function testStartConnection() {
return new Promise(function(aResolve, aReject) {
request.start().then((aConnection) => {
connection = aConnection;
ok(connection, "Sender: Connection should be available.");
new file mode 100644
--- /dev/null
+++ b/dom/presentation/tests/mochitest/test_presentation_availability.html
@@ -0,0 +1,120 @@
+<!DOCTYPE HTML>
+<html>
+<!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<head>
+ <meta charset="utf-8">
+ <title>Test for PresentationAvailability</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1228508">Test PresentationAvailability</a>
+<script type="application/javascript;version=1.8">
+
+"use strict";
+
+var testDevice = {
+ id: 'id',
+ name: 'name',
+ type: 'type',
+};
+
+var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('PresentationDeviceInfoChromeScript.js'));
+var request;
+var availability;
+
+function testSetup() {
+ return new Promise(function(aResolve, aReject) {
+ gScript.addMessageListener('setup-complete', function() {
+ aResolve();
+ });
+ gScript.sendAsyncMessage('setup');
+ });
+}
+
+function testInitialUnavailable() {
+ request = new PresentationRequest("https://example.com");
+
+ return request.getAvailability().then(function(aAvailability) {
+ is(aAvailability.value, false, "Should have no available device after setup");
+ aAvailability.onchange = function() {
+ aAvailability.onchange = null;
+ ok(aAvailability.value, "Device should be available.");
+ }
+ availability = aAvailability;
+ gScript.sendAsyncMessage('trigger-device-add', testDevice);
+ }).catch(function(aError) {
+ ok(false, "Error occurred when getting availability: " + aError);
+ teardown();
+ });
+}
+
+function testInitialAvailable() {
+ let anotherRequest = new PresentationRequest("https://example.net");
+ return anotherRequest.getAvailability().then(function(aAvailability) {
+ is(aAvailability.value, true, "Should have available device initially");
+ isnot(aAvailability, availability, "Should get different availability object for different request URL");
+ }).catch(function(aError) {
+ ok(false, "Error occurred when getting availability: " + aError);
+ teardown();
+ });
+}
+
+function testOnChangeEvent() {
+ return new Promise(function(aResolve, aReject) {
+ availability.onchange = function() {
+ availability.onchange = null;
+ is(availability.value, false, "Should have no available device after device removed");
+ aResolve();
+ }
+ gScript.sendAsyncMessage('trigger-device-remove');
+ });
+}
+
+function testConsecutiveGetAvailability() {
+ let request = new PresentationRequest("https://example.org");
+ let firstAvailabilityResolved = false;
+ return Promise.all([
+ request.getAvailability().then(function() {
+ firstAvailabilityResolved = true;
+ }),
+ request.getAvailability().then(function() {
+ ok(firstAvailabilityResolved, "getAvailability() should be resolved in sequence");
+ })
+ ]).catch(function(aError) {
+ ok(false, "Error occurred when getting availability: " + aError);
+ teardown();
+ });
+}
+
+function teardown() {
+ request = null;
+ availability = null;
+ gScript.sendAsyncMessage('teardown');
+ gScript.destroy();
+ SimpleTest.finish();
+}
+
+function runTests() {
+ ok(navigator.presentation, "navigator.presentation should be available.");
+ testSetup().then(testInitialUnavailable)
+ .then(testInitialAvailable)
+ .then(testOnChangeEvent)
+ .then(testConsecutiveGetAvailability)
+ .then(teardown);
+}
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPermissions([
+ {type: "presentation-device-manage", allow: false, context: document},
+], function() {
+ SpecialPowers.pushPrefEnv({ "set": [["dom.presentation.enabled", true],
+ ["dom.presentation.controller.enabled", true],
+ ["dom.presentation.session_transport.data_channel.enable", false]]},
+ runTests);
+});
+
+</script>
+</body>
+</html>
--- a/dom/presentation/tests/mochitest/test_presentation_dc_sender.html
+++ b/dom/presentation/tests/mochitest/test_presentation_dc_sender.html
@@ -21,30 +21,31 @@ var request;
var connection;
function testSetup() {
return new Promise(function(aResolve, aReject) {
request = new PresentationRequest("http://example.com/");
request.getAvailability().then(
function(aAvailability) {
+ is(aAvailability.value, false, "Sender: should have no available device after setup");
aAvailability.onchange = function() {
aAvailability.onchange = null;
ok(aAvailability.value, "Device should be available.");
aResolve();
}
+
+ gScript.sendAsyncMessage('trigger-device-add');
},
function(aError) {
ok(false, "Error occurred when getting availability: " + aError);
teardown();
aReject();
}
);
-
- gScript.sendAsyncMessage('trigger-device-add');
});
}
function testStartConnection() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('device-prompt', function devicePromptHandler() {
gScript.removeMessageListener('device-prompt', devicePromptHandler);
info("Device prompt is triggered.");
--- a/dom/presentation/tests/mochitest/test_presentation_reconnect.html
+++ b/dom/presentation/tests/mochitest/test_presentation_reconnect.html
@@ -43,30 +43,31 @@ function testSetup() {
SimpleTest.finish();
}
}, false);
request = new PresentationRequest("http://example.com/");
request.getAvailability().then(
function(aAvailability) {
+ is(aAvailability.value, false, "Sender: should have no available device after setup");
aAvailability.onchange = function() {
aAvailability.onchange = null;
ok(aAvailability.value, "Device should be available.");
aResolve();
}
+
+ gScript.sendAsyncMessage('trigger-device-add');
},
function(aError) {
ok(false, "Error occurred when getting availability: " + aError);
teardown();
aReject();
}
);
-
- gScript.sendAsyncMessage('trigger-device-add');
});
}
function testStartConnection() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('device-prompt', function devicePromptHandler() {
info("Device prompt is triggered.");
gScript.sendAsyncMessage('trigger-device-prompt-select');
--- a/dom/presentation/tests/mochitest/test_presentation_sender_on_terminate_request.html
+++ b/dom/presentation/tests/mochitest/test_presentation_sender_on_terminate_request.html
@@ -19,30 +19,31 @@ var request;
var connection;
function testSetup() {
return new Promise(function(aResolve, aReject) {
request = new PresentationRequest("http://example.com");
request.getAvailability().then(
function(aAvailability) {
+ is(aAvailability.value, false, "Sender: should have no available device after setup");
aAvailability.onchange = function() {
aAvailability.onchange = null;
ok(aAvailability.value, "Device should be available.");
aResolve();
}
+
+ gScript.sendAsyncMessage('trigger-device-add');
},
function(aError) {
ok(false, "Error occurred when getting availability: " + aError);
teardown();
aReject();
}
);
-
- gScript.sendAsyncMessage('trigger-device-add');
});
}
function testStartConnection() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('device-prompt', function devicePromptHandler() {
gScript.removeMessageListener('device-prompt', devicePromptHandler);
info("Device prompt is triggered.");
--- a/dom/presentation/tests/mochitest/test_presentation_sender_startWithDevice.html
+++ b/dom/presentation/tests/mochitest/test_presentation_sender_startWithDevice.html
@@ -19,30 +19,31 @@ var request;
var connection;
function testSetup() {
return new Promise(function(aResolve, aReject) {
request = new PresentationRequest("https://example.com");
request.getAvailability().then(
function(aAvailability) {
+ is(aAvailability.value, false, "Sender: should have no available device after setup");
aAvailability.onchange = function() {
aAvailability.onchange = null;
ok(aAvailability.value, "Device should be available.");
aResolve();
}
+
+ gScript.sendAsyncMessage('trigger-device-add');
},
function(aError) {
ok(false, "Error occurred when getting availability: " + aError);
teardown();
aReject();
}
);
-
- gScript.sendAsyncMessage('trigger-device-add');
});
}
function testStartConnectionWithDevice() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('device-prompt', function devicePromptHandler() {
gScript.removeMessageListener('device-prompt', devicePromptHandler);
ok(false, "Device prompt should not be triggered.");
--- a/dom/presentation/tests/mochitest/test_presentation_tcp_sender.html
+++ b/dom/presentation/tests/mochitest/test_presentation_tcp_sender.html
@@ -19,30 +19,31 @@ var request;
var connection;
function testSetup() {
return new Promise(function(aResolve, aReject) {
request = new PresentationRequest("https://example.com");
request.getAvailability().then(
function(aAvailability) {
+ is(aAvailability.value, false, "Sender: should have no available device after setup");
aAvailability.onchange = function() {
aAvailability.onchange = null;
ok(aAvailability.value, "Device should be available.");
aResolve();
}
+ gScript.sendAsyncMessage('trigger-device-add');
},
function(aError) {
ok(false, "Error occurred when getting availability: " + aError);
teardown();
aReject();
}
);
- gScript.sendAsyncMessage('trigger-device-add');
});
}
function testStartConnection() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('device-prompt', function devicePromptHandler() {
gScript.removeMessageListener('device-prompt', devicePromptHandler);
info("Device prompt is triggered.");
--- a/dom/presentation/tests/mochitest/test_presentation_tcp_sender_default_request.html
+++ b/dom/presentation/tests/mochitest/test_presentation_tcp_sender_default_request.html
@@ -18,30 +18,31 @@ var gScript = SpecialPowers.loadChromeSc
var connection;
function testSetup() {
return new Promise(function(aResolve, aReject) {
navigator.presentation.defaultRequest = new PresentationRequest("https://example.com");
navigator.presentation.defaultRequest.getAvailability().then(
function(aAvailability) {
+ is(aAvailability.value, false, "Sender: should have no available device after setup");
aAvailability.onchange = function() {
aAvailability.onchange = null;
ok(aAvailability.value, "Device should be available.");
aResolve();
}
+
+ gScript.sendAsyncMessage('trigger-device-add');
},
function(aError) {
ok(false, "Error occurred when getting availability: " + aError);
teardown();
aReject();
}
);
-
- gScript.sendAsyncMessage('trigger-device-add');
});
}
function testStartConnection() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('device-prompt', function devicePromptHandler() {
gScript.removeMessageListener('device-prompt', devicePromptHandler);
info("Device prompt is triggered.");
--- a/dom/presentation/tests/mochitest/test_presentation_tcp_sender_disconnect.html
+++ b/dom/presentation/tests/mochitest/test_presentation_tcp_sender_disconnect.html
@@ -19,30 +19,31 @@ var request;
var connection;
function testSetup() {
return new Promise(function(aResolve, aReject) {
request = new PresentationRequest("http://example.com");
request.getAvailability().then(
function(aAvailability) {
+ is(aAvailability.value, false, "Sender: should have no available device after setup");
aAvailability.onchange = function() {
aAvailability.onchange = null;
ok(aAvailability.value, "Device should be available.");
aResolve();
}
+
+ gScript.sendAsyncMessage('trigger-device-add');
},
function(aError) {
ok(false, "Error occurred when getting availability: " + aError);
teardown();
aReject();
}
);
-
- gScript.sendAsyncMessage('trigger-device-add');
});
}
function testStartConnection() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('device-prompt', function devicePromptHandler() {
gScript.removeMessageListener('device-prompt', devicePromptHandler);
info("Device prompt is triggered.");
--- a/dom/presentation/tests/mochitest/test_presentation_tcp_sender_establish_connection_error.html
+++ b/dom/presentation/tests/mochitest/test_presentation_tcp_sender_establish_connection_error.html
@@ -18,30 +18,31 @@ var gScript = SpecialPowers.loadChromeSc
var request;
function setup() {
return new Promise(function(aResolve, aReject) {
request = new PresentationRequest("http://example.com");
request.getAvailability().then(
function(aAvailability) {
+ is(aAvailability.value, false, "Sender: should have no available device after setup");
aAvailability.onchange = function() {
aAvailability.onchange = null;
ok(aAvailability.value, "Device should be available.");
aResolve();
}
+
+ gScript.sendAsyncMessage('trigger-device-add');
},
function(aError) {
ok(false, "Error occurred when getting availability: " + aError);
teardown();
aReject();
}
);
-
- gScript.sendAsyncMessage('trigger-device-add');
});
}
function testCreateRequestWithEmptyURL() {
return new Promise(function(aResolve, aReject) {
try {
request = new PresentationRequest("");
} catch (aError) {
--- a/dom/presentation/tests/mochitest/test_presentation_terminate.js
+++ b/dom/presentation/tests/mochitest/test_presentation_terminate.js
@@ -81,28 +81,29 @@ function setup() {
return Promise.resolve();
}
function testCreateRequest() {
return new Promise(function(aResolve, aReject) {
info('Sender: --- testCreateRequest ---');
request = new PresentationRequest(receiverUrl);
request.getAvailability().then((aAvailability) => {
+ is(aAvailability.value, false, "Sender: should have no available device after setup");
aAvailability.onchange = function() {
aAvailability.onchange = null;
ok(aAvailability.value, 'Sender: Device should be available.');
aResolve();
}
+
+ gScript.sendAsyncMessage('trigger-device-add');
}).catch((aError) => {
ok(false, 'Sender: Error occurred when getting availability: ' + aError);
teardown();
aReject();
});
-
- gScript.sendAsyncMessage('trigger-device-add');
});
}
function testStartConnection() {
return new Promise(function(aResolve, aReject) {
request.start().then((aConnection) => {
connection = aConnection;
ok(connection, 'Sender: Connection should be available.');
--- a/dom/presentation/tests/mochitest/test_presentation_terminate_establish_connection_error.js
+++ b/dom/presentation/tests/mochitest/test_presentation_terminate_establish_connection_error.js
@@ -86,28 +86,29 @@ function setup() {
return Promise.resolve();
}
function testCreateRequest() {
return new Promise(function(aResolve, aReject) {
info('Sender: --- testCreateRequest ---');
request = new PresentationRequest(receiverUrl);
request.getAvailability().then((aAvailability) => {
+ is(aAvailability.value, false, "Sender: should have no available device after setup");
aAvailability.onchange = function() {
aAvailability.onchange = null;
ok(aAvailability.value, 'Sender: Device should be available.');
aResolve();
}
+
+ gScript.sendAsyncMessage('trigger-device-add');
}).catch((aError) => {
ok(false, 'Sender: Error occurred when getting availability: ' + aError);
teardown();
aReject();
});
-
- gScript.sendAsyncMessage('trigger-device-add');
});
}
function testStartConnection() {
return new Promise(function(aResolve, aReject) {
request.start().then((aConnection) => {
connection = aConnection;
ok(connection, 'Sender: Connection should be available.');
--- a/dom/webidl/PresentationRequest.webidl
+++ b/dom/webidl/PresentationRequest.webidl
@@ -44,16 +44,17 @@ interface PresentationRequest : EventTar
Promise<PresentationConnection> reconnect(DOMString presentationId);
/*
* UA triggers device discovery mechanism periodically and monitor device
* availability.
*
* The promise may be rejected duo to one of the following reasons:
* - "NotSupportedError": Unable to continuously monitor the availability.
+ * - "SecurityError": This operation is insecure.
*/
[Throws]
Promise<PresentationAvailability> getAvailability();
/*
* It is called when a connection associated with a PresentationRequest is created.
* The event is fired for all connections that are created for the controller.
*/
--- a/testing/profiles/prefs_general.js
+++ b/testing/profiles/prefs_general.js
@@ -227,17 +227,17 @@ user_pref("browser.snippets.firstrunHome
user_pref("general.useragent.updates.enabled", false);
// Disable webapp updates. Yes, it is supposed to be an integer.
user_pref("browser.webapps.checkForUpdates", 0);
// Enable debug logging in the tcp presentation server.
user_pref("dom.presentation.tcp_server.debug", true);
// Enable debug logging in the presentation core service.
-pref("logging.Presentation", "debug");
+user_pref("logging.Presentation", "debug");
// Don't connect to Yahoo! for RSS feed tests.
// en-US only uses .types.0.uri, but set all of them just to be sure.
user_pref('browser.contentHandlers.types.0.uri', 'http://test1.example.org/rss?url=%%s')
user_pref('browser.contentHandlers.types.1.uri', 'http://test1.example.org/rss?url=%%s')
user_pref('browser.contentHandlers.types.2.uri', 'http://test1.example.org/rss?url=%%s')
user_pref('browser.contentHandlers.types.3.uri', 'http://test1.example.org/rss?url=%%s')
user_pref('browser.contentHandlers.types.4.uri', 'http://test1.example.org/rss?url=%%s')