Bug 1215426 - [Presentation WebAPI] Grant access to browser receiving pages. r=smaug

This commit is contained in:
Sean Lin 2015-10-21 14:01:08 +08:00
parent bb65c432eb
commit 4dce1c7f21
12 changed files with 82 additions and 17 deletions

View File

@ -77,6 +77,7 @@
#include "nsIAppsService.h"
#include "mozIApplication.h"
#include "WidgetUtils.h"
#include "nsIPresentationService.h"
#ifdef MOZ_MEDIA_NAVIGATOR
#include "mozilla/dom/MediaDevices.h"
@ -2620,6 +2621,64 @@ Navigator::HasTVSupport(JSContext* aCx, JSObject* aGlobal)
return status == nsIPrincipal::APP_STATUS_CERTIFIED;
}
/* static */
bool
Navigator::HasPresentationSupport(JSContext* aCx, JSObject* aGlobal)
{
JS::Rooted<JSObject*> global(aCx, aGlobal);
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(global);
if (NS_WARN_IF(!win)) {
return false;
}
// Grant access if it has the permission.
if (CheckPermission(win, "presentation")) {
return true;
}
// Grant access to browser receiving pages and their same-origin iframes. (App
// pages should be controlled by "presentation" permission in app manifests.)
mozilla::dom::ContentChild* cc =
mozilla::dom::ContentChild::GetSingleton();
if (!cc || !cc->IsForBrowser()) {
return false;
}
nsCOMPtr<nsIDOMWindow> top;
nsresult rv = win->GetTop(getter_AddRefs(top));
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(win);
nsCOMPtr<nsIScriptObjectPrincipal> topSop = do_QueryInterface(top);
if (!sop || !topSop) {
return false;
}
nsIPrincipal* principal = sop->GetPrincipal();
nsIPrincipal* topPrincipal = topSop->GetPrincipal();
if (!principal || !topPrincipal || !principal->Subsumes(topPrincipal)) {
return false;
}
nsCOMPtr<nsPIDOMWindow> piTop = do_QueryInterface(top);
if (!piTop || !(piTop = piTop->GetCurrentInnerWindow())) {
return false;
}
nsCOMPtr<nsIPresentationService> presentationService =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if (NS_WARN_IF(!presentationService)) {
return false;
}
nsAutoString sessionId;
presentationService->GetExistentSessionIdAtLaunch(piTop->WindowID(), sessionId);
return !sessionId.IsEmpty();
}
/* static */
bool
Navigator::IsE10sEnabled(JSContext* aCx, JSObject* aGlobal)

View File

@ -335,6 +335,8 @@ public:
static bool HasTVSupport(JSContext* aCx, JSObject* aGlobal);
static bool HasPresentationSupport(JSContext* aCx, JSObject* aGlobal);
static bool IsE10sEnabled(JSContext* aCx, JSObject* aGlobal);
nsPIDOMWindow* GetParentObject() const

View File

@ -28,8 +28,7 @@ function finish() {
function testConnectionAvailable() {
return new Promise(function(aResolve, aReject) {
ok(navigator.presentation, "navigator.presentation should be available in OOP pages.");
ok(!navigator.presentation.receiver, "Non-receiving OOP pages shouldn't get a presentation receiver instance.");
ok(!navigator.presentation, "navigator.presentation shouldn't be available in non-receiving OOP pages.");
aResolve();
});
}

View File

@ -34,8 +34,8 @@ var connection;
function testConnectionAvailable() {
return new Promise(function(aResolve, aReject) {
ok(navigator.presentation, "navigator.presentation should be available.");
ok(navigator.presentation.receiver, "navigator.presentation.receiver should be available.");
ok(navigator.presentation, "navigator.presentation should be available in OOP receiving pages.");
ok(navigator.presentation.receiver, "navigator.presentation.receiver should be available in OOP receiving pages.");
navigator.presentation.receiver.getConnection().then(
function(aConnection) {
@ -54,6 +54,16 @@ function testConnectionAvailable() {
});
}
function testConnectionAvailableInnerIframe() {
return new Promise(function(aResolve, aReject) {
var iframe = document.createElement('iframe');
iframe.setAttribute('src', './file_presentation_receiver_inner_iframe_oop.html');
document.body.appendChild(iframe);
aResolve();
});
}
function testConnectionReady() {
return new Promise(function(aResolve, aReject) {
connection.onstatechange = function() {
@ -94,6 +104,7 @@ function testTerminateConnection() {
}
testConnectionAvailable().
then(testConnectionAvailableInnerIframe).
then(testConnectionReady).
then(testIncomingMessage).
then(testTerminateConnection).

View File

@ -32,9 +32,6 @@ function setup() {
gScript.sendAsyncMessage('trigger-device-add');
// Create a receiver OOP iframe.
SpecialPowers.addPermission('presentation', true, { url: receiverUrl,
appId: SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID,
isInBrowserElement: true });
var receiverIframe = document.createElement('iframe');
receiverIframe.setAttribute('remote', 'true');
receiverIframe.setAttribute('mozbrowser', 'true');
@ -72,9 +69,6 @@ function setup() {
obs.notifyObservers(promise, 'setup-request-promise', null);
// Create a non-receiver OOP iframe.
SpecialPowers.addPermission('presentation', true, { url: nonReceiverUrl,
appId: SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID,
isInBrowserElement: true });
var nonReceiverIframe = document.createElement('iframe');
nonReceiverIframe.setAttribute('remote', 'true');
nonReceiverIframe.setAttribute('mozbrowser', 'true');

View File

@ -433,7 +433,7 @@ partial interface Navigator {
};
partial interface Navigator {
[Throws, Pref="dom.presentation.enabled", CheckAnyPermissions="presentation", SameObject]
[Throws, Pref="dom.presentation.enabled", Func="Navigator::HasPresentationSupport", SameObject]
readonly attribute Presentation? presentation;
};

View File

@ -5,7 +5,7 @@
*/
[Pref="dom.presentation.enabled",
CheckAnyPermissions="presentation"]
Func="Navigator::HasPresentationSupport"]
interface Presentation : EventTarget {
/*
* This should be used by the UA as the default presentation request for the

View File

@ -5,7 +5,7 @@
*/
[Pref="dom.presentation.enabled",
CheckAnyPermissions="presentation"]
Func="Navigator::HasPresentationSupport"]
interface PresentationAvailability : EventTarget {
/*
* If there is at least one device discovered by UA, the value is |true|.

View File

@ -18,7 +18,7 @@ enum PresentationConnectionState
};
[Pref="dom.presentation.enabled",
CheckAnyPermissions="presentation"]
Func="Navigator::HasPresentationSupport"]
interface PresentationConnection : EventTarget {
/*
* Unique id for all existing connections.

View File

@ -7,7 +7,7 @@
[Constructor(DOMString type,
optional PresentationConnectionAvailableEventInit eventInitDict),
Pref="dom.presentation.enabled",
CheckAnyPermissions="presentation"]
Func="Navigator::HasPresentationSupport"]
interface PresentationConnectionAvailableEvent : Event
{
[SameObject]

View File

@ -5,7 +5,7 @@
*/
[Pref="dom.presentation.enabled",
CheckAnyPermissions="presentation"]
Func="Navigator::HasPresentationSupport"]
interface PresentationReceiver : EventTarget {
/*
* Get the first connected presentation connection in a receiving browsing

View File

@ -6,7 +6,7 @@
[Constructor(DOMString url),
Pref="dom.presentation.enabled",
CheckAnyPermissions="presentation"]
Func="Navigator::HasPresentationSupport"]
interface PresentationRequest : EventTarget {
/*
* A requesting page use start() to start a new connection, and it will be