--- a/dom/presentation/Presentation.cpp
+++ b/dom/presentation/Presentation.cpp
@@ -39,64 +39,16 @@ NS_INTERFACE_MAP_END
/* static */ already_AddRefed<Presentation>
Presentation::Create(nsPIDOMWindowInner* aWindow)
{
RefPtr<Presentation> presentation = new Presentation(aWindow);
return presentation.forget();
}
-/* static */ bool
-Presentation::HasReceiverSupport(JSContext* aCx, JSObject* aGlobal)
-{
- JS::Rooted<JSObject*> global(aCx, aGlobal);
-
- nsCOMPtr<nsPIDOMWindowInner> inner =
- do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(global));
- if (NS_WARN_IF(!inner)) {
- return false;
- }
-
- // Grant access to browser receiving pages and their same-origin iframes. (App
- // pages should be controlled by "presentation" permission in app manifests.)
- nsCOMPtr<nsIDocShell> docshell = inner->GetDocShell();
- if (!docshell) {
- return false;
- }
-
- if (!Preferences::GetBool("dom.presentation.testing.simulate-receiver") &&
- !docshell->GetIsInMozBrowserOrApp()) {
- return false;
- }
-
- nsAutoString presentationURL;
- nsContentUtils::GetPresentationURL(docshell, presentationURL);
-
- if (presentationURL.IsEmpty()) {
- return false;
- }
-
- nsCOMPtr<nsIScriptSecurityManager> securityManager =
- nsContentUtils::GetSecurityManager();
- if (!securityManager) {
- return false;
- }
-
- nsCOMPtr<nsIURI> presentationURI;
- nsresult rv = NS_NewURI(getter_AddRefs(presentationURI), presentationURL);
- if (NS_FAILED(rv)) {
- return false;
- }
-
- nsCOMPtr<nsIURI> docURI = inner->GetDocumentURI();
- return NS_SUCCEEDED(securityManager->CheckSameOriginURI(presentationURI,
- docURI,
- false));
-}
-
Presentation::Presentation(nsPIDOMWindowInner* aWindow)
: mWindow(aWindow)
{
}
Presentation::~Presentation()
{
}
@@ -106,53 +58,45 @@ Presentation::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
return PresentationBinding::Wrap(aCx, this, aGivenProto);
}
void
Presentation::SetDefaultRequest(PresentationRequest* aRequest)
{
- if (IsInPresentedContent()) {
- 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 (IsInPresentedContent()) {
- return nullptr;
- }
-
RefPtr<PresentationRequest> request = mDefaultRequest;
return request.forget();
}
already_AddRefed<PresentationReceiver>
Presentation::GetReceiver()
{
// return the same receiver if already created
if (mReceiver) {
RefPtr<PresentationReceiver> receiver = mReceiver;
return receiver.forget();
}
- if (!IsInPresentedContent()) {
+ if (!HasReceiverSupport() || !IsInPresentedContent()) {
return nullptr;
}
mReceiver = PresentationReceiver::Create(mWindow);
if (NS_WARN_IF(!mReceiver)) {
MOZ_ASSERT(mReceiver);
return nullptr;
}
@@ -169,16 +113,60 @@ Presentation::SetStartSessionUnsettled(b
bool
Presentation::IsStartSessionUnsettled() const
{
return mStartSessionUnsettled;
}
bool
+Presentation::HasReceiverSupport() const
+{
+ if (!mWindow) {
+ return false;
+ }
+
+ // Grant access to browser receiving pages and their same-origin iframes. (App
+ // pages should be controlled by "presentation" permission in app manifests.)
+ nsCOMPtr<nsIDocShell> docShell = mWindow->GetDocShell();
+ if (!docShell) {
+ return false;
+ }
+
+ if (!Preferences::GetBool("dom.presentation.testing.simulate-receiver") &&
+ !docShell->GetIsInMozBrowserOrApp()) {
+ return false;
+ }
+
+ nsAutoString presentationURL;
+ nsContentUtils::GetPresentationURL(docShell, presentationURL);
+
+ if (presentationURL.IsEmpty()) {
+ return false;
+ }
+
+ nsCOMPtr<nsIScriptSecurityManager> securityManager =
+ nsContentUtils::GetSecurityManager();
+ if (!securityManager) {
+ return false;
+ }
+
+ nsCOMPtr<nsIURI> presentationURI;
+ nsresult rv = NS_NewURI(getter_AddRefs(presentationURI), presentationURL);
+ if (NS_FAILED(rv)) {
+ return false;
+ }
+
+ nsCOMPtr<nsIURI> docURI = mWindow->GetDocumentURI();
+ return NS_SUCCEEDED(securityManager->CheckSameOriginURI(presentationURI,
+ docURI,
+ false));
+}
+
+bool
Presentation::IsInPresentedContent() const
{
if (!mWindow) {
return false;
}
nsCOMPtr<nsIDocShell> docShell = mWindow->GetDocShell();
MOZ_ASSERT(docShell);
--- a/dom/presentation/Presentation.h
+++ b/dom/presentation/Presentation.h
@@ -25,18 +25,16 @@ class Presentation final : public nsISup
, public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Presentation)
static already_AddRefed<Presentation> Create(nsPIDOMWindowInner* aWindow);
- static bool HasReceiverSupport(JSContext* aCx, JSObject* aGlobal);
-
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
nsPIDOMWindowInner* GetParentObject() const
{
return mWindow;
}
@@ -51,16 +49,18 @@ public:
void SetStartSessionUnsettled(bool aIsUnsettled);
bool IsStartSessionUnsettled() const;
private:
explicit Presentation(nsPIDOMWindowInner* aWindow);
virtual ~Presentation();
+ bool HasReceiverSupport() const;
+
bool IsInPresentedContent() const;
RefPtr<PresentationRequest> mDefaultRequest;
RefPtr<PresentationReceiver> mReceiver;
nsCOMPtr<nsPIDOMWindowInner> mWindow;
bool mStartSessionUnsettled = false;
};
--- a/dom/presentation/tests/mochitest/file_presentation_1ua_receiver.html
+++ b/dom/presentation/tests/mochitest/file_presentation_1ua_receiver.html
@@ -58,16 +58,17 @@ function is_same_buffer(recv_data, expec
return true;
}
function testConnectionAvailable() {
return new Promise(function(aResolve, aReject) {
info('Receiver: --- testConnectionAvailable ---');
ok(navigator.presentation, "Receiver: navigator.presentation should be available.");
ok(navigator.presentation.receiver, "Receiver: navigator.presentation.receiver should be available.");
+ is(navigator.presentation.defaultRequest, null, "Receiver: navigator.presentation.defaultRequest should be null.");
navigator.presentation.receiver.connectionList
.then((aList) => {
is(aList.connections.length, 1, "Should get one conncetion.");
connection = aList.connections[0];
ok(connection.id, "Connection ID should be set: " + connection.id);
is(connection.state, "connected", "Connection state at receiver side should be connected.");
aResolve();
--- a/dom/presentation/tests/mochitest/file_presentation_non_receiver.html
+++ b/dom/presentation/tests/mochitest/file_presentation_non_receiver.html
@@ -23,17 +23,17 @@ function info(msg) {
}
function finish() {
alert('DONE');
}
function testConnectionAvailable() {
return new Promise(function(aResolve, aReject) {
- ok(!navigator.presentation.receiver, "navigator.presentation.receiver shouldn't be available in non-receiving pages.");
+ is(navigator.presentation.receiver, null, "navigator.presentation.receiver shouldn't be available in non-receiving pages.");
aResolve();
});
}
testConnectionAvailable().
then(finish);
</script>
--- a/dom/presentation/tests/mochitest/file_presentation_non_receiver_inner_iframe.html
+++ b/dom/presentation/tests/mochitest/file_presentation_non_receiver_inner_iframe.html
@@ -11,16 +11,16 @@
"use strict";
function ok(a, msg) {
alert((a ? 'OK ' : 'KO ') + msg);
}
function testConnectionAvailable() {
return new Promise(function(aResolve, aReject) {
- ok(!navigator.presentation.receiver, "navigator.presentation.receiver shouldn't be available in inner iframes with different origins from receiving pages.");
+ is(navigator.presentation.receiver, null, "navigator.presentation.receiver shouldn't be available in inner iframes with different origins from receiving pages.");
aResolve();
});
}
</script>
</body>
</html>
--- a/dom/presentation/tests/mochitest/file_presentation_receiver.html
+++ b/dom/presentation/tests/mochitest/file_presentation_receiver.html
@@ -50,27 +50,20 @@ function testConnectionAvailable() {
finish();
aReject();
}
);
command({ name: 'trigger-incoming-offer' });
});
}
-function testDefauleRequestIsNull() {
+function testDefaultRequestIsUndefined() {
return new Promise(function(aResolve, aReject) {
- navigator.presentation.defaultRequest = new PresentationRequest("http://example.com");
- if (navigator.presentation.defaultRequest === null) {
- ok(true, "defaultRequest should be null.");
- aResolve();
- }
- else {
- ok(false, "defaultRequest should be null.");
- aReject();
- }
+ is(navigator.presentation.defaultRequest, undefined, "navigator.presentation.defaultRequest should not be available in receiving UA");
+ aResolve();
});
}
function testConnectionAvailableSameOriginInnerIframe() {
return new Promise(function(aResolve, aReject) {
var iframe = document.createElement('iframe');
iframe.setAttribute('src', './file_presentation_receiver_inner_iframe.html');
document.body.appendChild(iframe);
@@ -129,17 +122,17 @@ function testCloseConnection() {
aResolve();
};
connection.close();
});
}
testConnectionAvailable().
-then(testDefauleRequestIsNull).
+then(testDefaultRequestIsUndefined).
then(testConnectionAvailableSameOriginInnerIframe).
then(testConnectionUnavailableDiffOriginInnerIframe).
then(testConnectionListSameObject).
then(testIncomingMessage).
then(testCloseConnection).
then(finish);
</script>
--- a/dom/presentation/tests/mochitest/test_presentation_dc_receiver.html
+++ b/dom/presentation/tests/mochitest/test_presentation_dc_receiver.html
@@ -94,17 +94,17 @@ function setup() {
function testIncomingSessionRequest() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('receiver-launching', function launchReceiverHandler(aSessionId) {
gScript.removeMessageListener('receiver-launching', launchReceiverHandler);
info("Trying to launch receiver page.");
ok(navigator.presentation, "navigator.presentation should be available in in-process pages.");
- ok(!navigator.presentation.receiver, "Non-receiving in-process pages shouldn't get a presentation receiver instance.");
+ is(navigator.presentation.receiver, null, "Non-receiving in-process pages shouldn't get a presentation receiver instance.");
aResolve();
});
gScript.sendAsyncMessage('trigger-incoming-session-request', receiverUrl);
});
}
function teardown() {
@@ -123,17 +123,17 @@ function runTests() {
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPermissions([
{type: 'presentation-device-manage', allow: false, context: document},
{type: "browser", allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
- ["dom.presentation.controller.enabled", true],
+ ["dom.presentation.controller.enabled", false],
["dom.presentation.receiver.enabled", true],
["dom.presentation.session_transport.data_channel.enable", true],
["dom.mozBrowserFramesEnabled", true]]},
runTests);
});
</script>
</body>
--- a/dom/presentation/tests/mochitest/test_presentation_dc_receiver_oop.html
+++ b/dom/presentation/tests/mochitest/test_presentation_dc_receiver_oop.html
@@ -193,17 +193,17 @@ function runTests() {
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPermissions([
{type: 'presentation-device-manage', allow: false, context: document},
{type: 'browser', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
- ["dom.presentation.controller.enabled", true],
+ ["dom.presentation.controller.enabled", false],
["dom.presentation.receiver.enabled", true],
["dom.presentation.session_transport.data_channel.enable", true],
["dom.mozBrowserFramesEnabled", true],
["dom.ipc.browser_frames.oop_by_default", true],
["presentation.receiver.loading.timeout", 5000000]]},
runTests);
});
--- a/dom/presentation/tests/mochitest/test_presentation_tcp_receiver.html
+++ b/dom/presentation/tests/mochitest/test_presentation_tcp_receiver.html
@@ -90,17 +90,17 @@ function setup() {
function testIncomingSessionRequest() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('receiver-launching', function launchReceiverHandler(aSessionId) {
gScript.removeMessageListener('receiver-launching', launchReceiverHandler);
info("Trying to launch receiver page.");
ok(navigator.presentation, "navigator.presentation should be available in in-process pages.");
- ok(!navigator.presentation.receiver, "Non-receiving in-process pages shouldn't get a presentation receiver instance.");
+ is(navigator.presentation.receiver, null, "Non-receiving in-process pages shouldn't get a presentation receiver instance.");
aResolve();
});
gScript.sendAsyncMessage('trigger-incoming-session-request', receiverUrl);
});
}
function teardown() {
@@ -119,17 +119,17 @@ function runTests() {
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPermissions([
{type: 'presentation-device-manage', allow: false, context: document},
{type: 'browser', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
- ["dom.presentation.controller.enabled", true],
+ ["dom.presentation.controller.enabled", false],
["dom.presentation.receiver.enabled", true],
["dom.mozBrowserFramesEnabled", true],
["dom.presentation.session_transport.data_channel.enable", false]]},
runTests);
});
</script>
</body>
--- a/dom/presentation/tests/mochitest/test_presentation_tcp_receiver_oop.html
+++ b/dom/presentation/tests/mochitest/test_presentation_tcp_receiver_oop.html
@@ -159,17 +159,17 @@ function runTests() {
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPermissions([
{type: 'presentation-device-manage', allow: false, context: document},
{type: 'browser', allow: true, context: document},
], function() {
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
- ["dom.presentation.controller.enabled", true],
+ ["dom.presentation.controller.enabled", false],
["dom.presentation.receiver.enabled", true],
["dom.presentation.session_transport.data_channel.enable", false],
["dom.mozBrowserFramesEnabled", true],
["dom.ipc.browser_frames.oop_by_default", true]]},
runTests);
});
</script>
--- a/dom/presentation/tests/mochitest/test_presentation_tcp_sender_default_request.html
+++ b/dom/presentation/tests/mochitest/test_presentation_tcp_sender_default_request.html
@@ -77,17 +77,17 @@ function testStartConnection() {
});
gScript.addMessageListener('data-transport-initialized', function dataTransportInitializedHandler() {
gScript.removeMessageListener('data-transport-initialized', dataTransportInitializedHandler);
info("Data transport channel is initialized.");
gScript.sendAsyncMessage('trigger-incoming-answer');
});
- ok(!navigator.presentation.receiver, "Sender shouldn't get a presentation receiver instance.");
+ is(navigator.presentation.receiver, undefined, "Sender shouldn't get a presentation receiver instance.");
navigator.presentation.defaultRequest.onconnectionavailable = function(aEvent) {
navigator.presentation.defaultRequest.onconnectionavailable = null;
connection = aEvent.connection;
ok(connection, "|connectionavailable| event is fired with a connection.");
ok(connection.id, "Connection ID should be set.");
is(connection.state, "connecting", "The initial state should be connecting.");
connection.onconnect = function() {
@@ -137,14 +137,15 @@ function runTests() {
then(testStartConnection).
then(testCloseConnection).
then(teardown);
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({ 'set': [["dom.presentation.enabled", true],
["dom.presentation.controller.enabled", true],
+ ["dom.presentation.receiver.enabled", false],
["dom.presentation.session_transport.data_channel.enable", false]]},
runTests);
</script>
</body>
</html>
--- a/dom/webidl/Presentation.webidl
+++ b/dom/webidl/Presentation.webidl
@@ -1,31 +1,30 @@
/* -*- 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/.
+ *
+ * The origin of this IDL file is
+ * https://w3c.github.io/presentation-api/#interface-presentation
*/
[Pref="dom.presentation.enabled"]
interface Presentation {
/*
* This should be used by the UA as the default presentation request for the
* controller. When the UA wishes to initiate a PresentationConnection on the
* controller's behalf, it MUST start a presentation connection using the default
* presentation request (as if the controller had called |defaultRequest.start()|).
*
* Only used by controlling browsing context (senders).
- *
- * The origin of this IDL file is
- * https://w3c.github.io/presentation-api/#interface-presentation
*/
[Pref="dom.presentation.controller.enabled"]
attribute PresentationRequest? defaultRequest;
/*
* This should be available on the receiving browsing context in order to
* access the controlling browsing context and communicate with them.
*/
[SameObject,
- Pref="dom.presentation.receiver.enabled",
- Func="Presentation::HasReceiverSupport"]
+ Pref="dom.presentation.receiver.enabled"]
readonly attribute PresentationReceiver? receiver;
};