Get rid of the Presentation Web API.
This commit is contained in:
parent
f2cdd889d5
commit
0d8f4cab66
|
@ -214,7 +214,6 @@ pref("browser.slowStartup.timeThreshold", 40000);
|
||||||
pref("browser.slowStartup.maxSamples", 5);
|
pref("browser.slowStartup.maxSamples", 5);
|
||||||
|
|
||||||
pref("browser.enable_automatic_image_resizing", true);
|
pref("browser.enable_automatic_image_resizing", true);
|
||||||
pref("browser.casting.enabled", false);
|
|
||||||
pref("browser.chrome.site_icons", true);
|
pref("browser.chrome.site_icons", true);
|
||||||
pref("browser.chrome.favicons", true);
|
pref("browser.chrome.favicons", true);
|
||||||
// browser.warnOnQuit == false will override all other possible prompts when quitting or restarting
|
// browser.warnOnQuit == false will override all other possible prompts when quitting or restarting
|
||||||
|
|
|
@ -214,7 +214,6 @@ pref("browser.slowStartup.timeThreshold", 40000);
|
||||||
pref("browser.slowStartup.maxSamples", 5);
|
pref("browser.slowStartup.maxSamples", 5);
|
||||||
|
|
||||||
pref("browser.enable_automatic_image_resizing", true);
|
pref("browser.enable_automatic_image_resizing", true);
|
||||||
pref("browser.casting.enabled", false);
|
|
||||||
pref("browser.chrome.site_icons", true);
|
pref("browser.chrome.site_icons", true);
|
||||||
pref("browser.chrome.favicons", true);
|
pref("browser.chrome.favicons", true);
|
||||||
// browser.warnOnQuit == false will override all other possible prompts when quitting or restarting
|
// browser.warnOnQuit == false will override all other possible prompts when quitting or restarting
|
||||||
|
|
|
@ -226,11 +226,6 @@
|
||||||
label="&emailVideoCmd.label;"
|
label="&emailVideoCmd.label;"
|
||||||
accesskey="&emailVideoCmd.accesskey;"
|
accesskey="&emailVideoCmd.accesskey;"
|
||||||
oncommand="gContextMenu.sendMedia();"/>
|
oncommand="gContextMenu.sendMedia();"/>
|
||||||
<menu id="context-castvideo"
|
|
||||||
label="&castVideoCmd.label;"
|
|
||||||
accesskey="&castVideoCmd.accesskey;">
|
|
||||||
<menupopup id="context-castvideo-popup" onpopupshowing="gContextMenu.populateCastVideoMenu(this)"/>
|
|
||||||
</menu>
|
|
||||||
<menuitem id="context-sendaudio"
|
<menuitem id="context-sendaudio"
|
||||||
label="&emailAudioCmd.label;"
|
label="&emailAudioCmd.label;"
|
||||||
accesskey="&emailAudioCmd.accesskey;"
|
accesskey="&emailAudioCmd.accesskey;"
|
||||||
|
|
|
@ -436,8 +436,7 @@
|
||||||
|
|
||||||
<menu id="tools-menu"
|
<menu id="tools-menu"
|
||||||
label="&toolsMenu.label;"
|
label="&toolsMenu.label;"
|
||||||
accesskey="&toolsMenu.accesskey;"
|
accesskey="&toolsMenu.accesskey;">
|
||||||
onpopupshowing="mirrorShow(this)">
|
|
||||||
<menupopup id="menu_ToolsPopup"
|
<menupopup id="menu_ToolsPopup"
|
||||||
#ifdef MOZ_SERVICES_SYNC
|
#ifdef MOZ_SERVICES_SYNC
|
||||||
onpopupshowing="gSyncUI.updateUI();"
|
onpopupshowing="gSyncUI.updateUI();"
|
||||||
|
@ -486,13 +485,6 @@
|
||||||
key="key_viewInfo"
|
key="key_viewInfo"
|
||||||
#endif
|
#endif
|
||||||
command="View:PageInfo"/>
|
command="View:PageInfo"/>
|
||||||
<menu id="menu_mirrorTabCmd"
|
|
||||||
hidden="true"
|
|
||||||
accesskey="&mirrorTabCmd.accesskey;"
|
|
||||||
label="&mirrorTabCmd.label;">
|
|
||||||
<menupopup id="menu_mirrorTab-popup"
|
|
||||||
onpopupshowing="populateMirrorTabMenu(this)"/>
|
|
||||||
</menu>
|
|
||||||
<menuseparator id="prefSep"/>
|
<menuseparator id="prefSep"/>
|
||||||
<menuitem id="menu_preferences"
|
<menuitem id="menu_preferences"
|
||||||
label="&preferencesCmd2.label;"
|
label="&preferencesCmd2.label;"
|
||||||
|
|
|
@ -17,7 +17,6 @@ Cu.import("resource://gre/modules/NotificationDB.jsm");
|
||||||
["AppConstants", "resource://gre/modules/AppConstants.jsm"],
|
["AppConstants", "resource://gre/modules/AppConstants.jsm"],
|
||||||
["BrowserUsageTelemetry", "resource:///modules/BrowserUsageTelemetry.jsm"],
|
["BrowserUsageTelemetry", "resource:///modules/BrowserUsageTelemetry.jsm"],
|
||||||
["BrowserUtils", "resource://gre/modules/BrowserUtils.jsm"],
|
["BrowserUtils", "resource://gre/modules/BrowserUtils.jsm"],
|
||||||
["CastingApps", "resource:///modules/CastingApps.jsm"],
|
|
||||||
["CharsetMenu", "resource://gre/modules/CharsetMenu.jsm"],
|
["CharsetMenu", "resource://gre/modules/CharsetMenu.jsm"],
|
||||||
["Color", "resource://gre/modules/Color.jsm"],
|
["Color", "resource://gre/modules/Color.jsm"],
|
||||||
["ContentSearch", "resource:///modules/ContentSearch.jsm"],
|
["ContentSearch", "resource:///modules/ContentSearch.jsm"],
|
||||||
|
@ -40,7 +39,6 @@ Cu.import("resource://gre/modules/NotificationDB.jsm");
|
||||||
["RecentWindow", "resource:///modules/RecentWindow.jsm"],
|
["RecentWindow", "resource:///modules/RecentWindow.jsm"],
|
||||||
["SessionStore", "resource:///modules/sessionstore/SessionStore.jsm"],
|
["SessionStore", "resource:///modules/sessionstore/SessionStore.jsm"],
|
||||||
["ShortcutUtils", "resource://gre/modules/ShortcutUtils.jsm"],
|
["ShortcutUtils", "resource://gre/modules/ShortcutUtils.jsm"],
|
||||||
["SimpleServiceDiscovery", "resource://gre/modules/SimpleServiceDiscovery.jsm"],
|
|
||||||
["SitePermissions", "resource:///modules/SitePermissions.jsm"],
|
["SitePermissions", "resource:///modules/SitePermissions.jsm"],
|
||||||
["TabCrashHandler", "resource:///modules/ContentCrashHandlers.jsm"],
|
["TabCrashHandler", "resource:///modules/ContentCrashHandlers.jsm"],
|
||||||
["Task", "resource://gre/modules/Task.jsm"],
|
["Task", "resource://gre/modules/Task.jsm"],
|
||||||
|
@ -2959,35 +2957,6 @@ function BrowserFullScreen()
|
||||||
window.fullScreen = !window.fullScreen;
|
window.fullScreen = !window.fullScreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mirrorShow(popup) {
|
|
||||||
let services = [];
|
|
||||||
if (Services.prefs.getBoolPref("browser.casting.enabled")) {
|
|
||||||
services = CastingApps.getServicesForMirroring();
|
|
||||||
}
|
|
||||||
popup.ownerDocument.getElementById("menu_mirrorTabCmd").hidden = !services.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
function mirrorMenuItemClicked(event) {
|
|
||||||
gBrowser.selectedBrowser.messageManager.sendAsyncMessage("SecondScreen:tab-mirror",
|
|
||||||
{service: event.originalTarget._service});
|
|
||||||
}
|
|
||||||
|
|
||||||
function populateMirrorTabMenu(popup) {
|
|
||||||
popup.innerHTML = null;
|
|
||||||
if (!Services.prefs.getBoolPref("browser.casting.enabled")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let doc = popup.ownerDocument;
|
|
||||||
let services = CastingApps.getServicesForMirroring();
|
|
||||||
services.forEach(service => {
|
|
||||||
let item = doc.createElement("menuitem");
|
|
||||||
item.setAttribute("label", service.friendlyName);
|
|
||||||
item._service = service;
|
|
||||||
item.addEventListener("command", mirrorMenuItemClicked);
|
|
||||||
popup.appendChild(item);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getWebNavigation()
|
function getWebNavigation()
|
||||||
{
|
{
|
||||||
return gBrowser.webNavigation;
|
return gBrowser.webNavigation;
|
||||||
|
|
|
@ -199,21 +199,10 @@ nsContextMenu.prototype = {
|
||||||
// Send media URL (but not for canvas, since it's a big data: URL)
|
// Send media URL (but not for canvas, since it's a big data: URL)
|
||||||
this.showItem("context-sendimage", this.onImage);
|
this.showItem("context-sendimage", this.onImage);
|
||||||
this.showItem("context-sendvideo", this.onVideo);
|
this.showItem("context-sendvideo", this.onVideo);
|
||||||
this.showItem("context-castvideo", this.onVideo);
|
|
||||||
this.showItem("context-sendaudio", this.onAudio);
|
this.showItem("context-sendaudio", this.onAudio);
|
||||||
let mediaIsBlob = this.mediaURL.startsWith("blob:");
|
let mediaIsBlob = this.mediaURL.startsWith("blob:");
|
||||||
this.setItemAttr("context-sendvideo", "disabled", !this.mediaURL || mediaIsBlob);
|
this.setItemAttr("context-sendvideo", "disabled", !this.mediaURL || mediaIsBlob);
|
||||||
this.setItemAttr("context-sendaudio", "disabled", !this.mediaURL || mediaIsBlob);
|
this.setItemAttr("context-sendaudio", "disabled", !this.mediaURL || mediaIsBlob);
|
||||||
let shouldShowCast = Services.prefs.getBoolPref("browser.casting.enabled");
|
|
||||||
// getServicesForVideo alone would be sufficient here (it depends on
|
|
||||||
// SimpleServiceDiscovery.services), but SimpleServiceDiscovery is guaranteed
|
|
||||||
// to be already loaded, since we load it on startup in nsBrowserGlue,
|
|
||||||
// and CastingApps isn't, so check SimpleServiceDiscovery.services first
|
|
||||||
// to avoid needing to load CastingApps.jsm if we don't need to.
|
|
||||||
shouldShowCast = shouldShowCast && this.mediaURL &&
|
|
||||||
SimpleServiceDiscovery.services.length > 0 &&
|
|
||||||
CastingApps.getServicesForVideo(this.target).length > 0;
|
|
||||||
this.setItemAttr("context-castvideo", "disabled", !shouldShowCast);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
initViewItems: function CM_initViewItems() {
|
initViewItems: function CM_initViewItems() {
|
||||||
|
@ -1408,25 +1397,6 @@ nsContextMenu.prototype = {
|
||||||
MailIntegration.sendMessage(this.mediaURL, "");
|
MailIntegration.sendMessage(this.mediaURL, "");
|
||||||
},
|
},
|
||||||
|
|
||||||
castVideo: function() {
|
|
||||||
CastingApps.openExternal(this.target, window);
|
|
||||||
},
|
|
||||||
|
|
||||||
populateCastVideoMenu: function(popup) {
|
|
||||||
let videoEl = this.target;
|
|
||||||
popup.innerHTML = null;
|
|
||||||
let doc = popup.ownerDocument;
|
|
||||||
let services = CastingApps.getServicesForVideo(videoEl);
|
|
||||||
services.forEach(service => {
|
|
||||||
let item = doc.createElement("menuitem");
|
|
||||||
item.setAttribute("label", service.friendlyName);
|
|
||||||
item.addEventListener("command", event => {
|
|
||||||
CastingApps.sendVideoToService(videoEl, service);
|
|
||||||
});
|
|
||||||
popup.appendChild(item);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
playPlugin: function() {
|
playPlugin: function() {
|
||||||
gPluginHandler.contextMenuCommand(this.browser, this.target, "play");
|
gPluginHandler.contextMenuCommand(this.browser, this.target, "play");
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,21 +25,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "ReaderMode",
|
||||||
"resource://gre/modules/ReaderMode.jsm");
|
"resource://gre/modules/ReaderMode.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "Readerable",
|
XPCOMUtils.defineLazyModuleGetter(this, "Readerable",
|
||||||
"resource://gre/modules/Readerable.jsm");
|
"resource://gre/modules/Readerable.jsm");
|
||||||
XPCOMUtils.defineLazyGetter(this, "SimpleServiceDiscovery", function() {
|
|
||||||
let ssdp = Cu.import("resource://gre/modules/SimpleServiceDiscovery.jsm", {}).SimpleServiceDiscovery;
|
|
||||||
// Register targets
|
|
||||||
ssdp.registerDevice({
|
|
||||||
id: "roku:ecp",
|
|
||||||
target: "roku:ecp",
|
|
||||||
factory: function(aService) {
|
|
||||||
Cu.import("resource://gre/modules/RokuApp.jsm");
|
|
||||||
return new RokuApp(aService);
|
|
||||||
},
|
|
||||||
types: ["video/mp4"],
|
|
||||||
extensions: ["mp4"]
|
|
||||||
});
|
|
||||||
return ssdp;
|
|
||||||
});
|
|
||||||
|
|
||||||
// TabChildGlobal
|
// TabChildGlobal
|
||||||
var global = this;
|
var global = this;
|
||||||
|
@ -94,19 +79,6 @@ addMessageListener("MixedContent:ReenableProtection", function() {
|
||||||
docShell.mixedContentChannel = null;
|
docShell.mixedContentChannel = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
addMessageListener("SecondScreen:tab-mirror", function(message) {
|
|
||||||
if (!Services.prefs.getBoolPref("browser.casting.enabled")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let app = SimpleServiceDiscovery.findAppForService(message.data.service);
|
|
||||||
if (app) {
|
|
||||||
let width = content.innerWidth;
|
|
||||||
let height = content.innerHeight;
|
|
||||||
let viewport = {cssWidth: width, cssHeight: height, width: width, height: height};
|
|
||||||
app.mirror(function() {}, content, viewport, function() {}, content);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var AboutHomeListener = {
|
var AboutHomeListener = {
|
||||||
init: function(chromeGlobal) {
|
init: function(chromeGlobal) {
|
||||||
chromeGlobal.addEventListener('AboutHomeLoad', this, false, true);
|
chromeGlobal.addEventListener('AboutHomeLoad', this, false, true);
|
||||||
|
|
|
@ -56,7 +56,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "winShellService",
|
||||||
["RemotePrompt", "resource:///modules/RemotePrompt.jsm"],
|
["RemotePrompt", "resource:///modules/RemotePrompt.jsm"],
|
||||||
["SessionStore", "resource:///modules/sessionstore/SessionStore.jsm"],
|
["SessionStore", "resource:///modules/sessionstore/SessionStore.jsm"],
|
||||||
["ShellService", "resource:///modules/ShellService.jsm"],
|
["ShellService", "resource:///modules/ShellService.jsm"],
|
||||||
["SimpleServiceDiscovery", "resource://gre/modules/SimpleServiceDiscovery.jsm"],
|
|
||||||
["TabCrashHandler", "resource:///modules/ContentCrashHandlers.jsm"],
|
["TabCrashHandler", "resource:///modules/ContentCrashHandlers.jsm"],
|
||||||
["Task", "resource://gre/modules/Task.jsm"],
|
["Task", "resource://gre/modules/Task.jsm"],
|
||||||
["URLBarZoom", "resource:///modules/URLBarZoom.jsm"],
|
["URLBarZoom", "resource:///modules/URLBarZoom.jsm"],
|
||||||
|
@ -1014,32 +1013,8 @@ BrowserGlue.prototype = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_initServiceDiscovery: function () {
|
|
||||||
if (!Services.prefs.getBoolPref("browser.casting.enabled")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var rokuDevice = {
|
|
||||||
id: "roku:ecp",
|
|
||||||
target: "roku:ecp",
|
|
||||||
factory: function(aService) {
|
|
||||||
Cu.import("resource://gre/modules/RokuApp.jsm");
|
|
||||||
return new RokuApp(aService);
|
|
||||||
},
|
|
||||||
types: ["video/mp4"],
|
|
||||||
extensions: ["mp4"]
|
|
||||||
};
|
|
||||||
|
|
||||||
// Register targets
|
|
||||||
SimpleServiceDiscovery.registerDevice(rokuDevice);
|
|
||||||
|
|
||||||
// Search for devices continuously every 120 seconds
|
|
||||||
SimpleServiceDiscovery.search(120 * 1000);
|
|
||||||
},
|
|
||||||
|
|
||||||
// All initial windows have opened.
|
// All initial windows have opened.
|
||||||
_onWindowsRestored: function BG__onWindowsRestored() {
|
_onWindowsRestored: function BG__onWindowsRestored() {
|
||||||
this._initServiceDiscovery();
|
|
||||||
|
|
||||||
// Show update notification, if needed.
|
// Show update notification, if needed.
|
||||||
if (Services.prefs.prefHasUserValue("app.update.postupdate"))
|
if (Services.prefs.prefHasUserValue("app.update.postupdate"))
|
||||||
this._showUpdateNotification();
|
this._showUpdateNotification();
|
||||||
|
|
|
@ -217,7 +217,6 @@
|
||||||
@RESPATH@/components/dom_xhr.xpt
|
@RESPATH@/components/dom_xhr.xpt
|
||||||
@RESPATH@/components/dom_xpath.xpt
|
@RESPATH@/components/dom_xpath.xpt
|
||||||
@RESPATH@/components/dom_xul.xpt
|
@RESPATH@/components/dom_xul.xpt
|
||||||
@RESPATH@/components/dom_presentation.xpt
|
|
||||||
@RESPATH@/components/downloads.xpt
|
@RESPATH@/components/downloads.xpt
|
||||||
@RESPATH@/components/editor.xpt
|
@RESPATH@/components/editor.xpt
|
||||||
@RESPATH@/components/embed_base.xpt
|
@RESPATH@/components/embed_base.xpt
|
||||||
|
@ -532,13 +531,6 @@
|
||||||
@RESPATH@/components/nsAsyncShutdown.manifest
|
@RESPATH@/components/nsAsyncShutdown.manifest
|
||||||
@RESPATH@/components/nsAsyncShutdown.js
|
@RESPATH@/components/nsAsyncShutdown.js
|
||||||
|
|
||||||
@RESPATH@/components/PresentationDeviceInfoManager.manifest
|
|
||||||
@RESPATH@/components/PresentationDeviceInfoManager.js
|
|
||||||
@RESPATH@/components/BuiltinProviders.manifest
|
|
||||||
@RESPATH@/components/PresentationControlService.js
|
|
||||||
@RESPATH@/components/PresentationDataChannelSessionTransport.js
|
|
||||||
@RESPATH@/components/PresentationDataChannelSessionTransport.manifest
|
|
||||||
|
|
||||||
; InputMethod API
|
; InputMethod API
|
||||||
@RESPATH@/components/MozKeyboard.js
|
@RESPATH@/components/MozKeyboard.js
|
||||||
@RESPATH@/components/InputMethod.manifest
|
@RESPATH@/components/InputMethod.manifest
|
||||||
|
|
|
@ -96,8 +96,6 @@ when there are no windows but Firefox is still running. -->
|
||||||
<!ENTITY pageInfoCmd.label "Page Info">
|
<!ENTITY pageInfoCmd.label "Page Info">
|
||||||
<!ENTITY pageInfoCmd.accesskey "I">
|
<!ENTITY pageInfoCmd.accesskey "I">
|
||||||
<!ENTITY pageInfoCmd.commandkey "i">
|
<!ENTITY pageInfoCmd.commandkey "i">
|
||||||
<!ENTITY mirrorTabCmd.label "Mirror Tab">
|
|
||||||
<!ENTITY mirrorTabCmd.accesskey "m">
|
|
||||||
<!-- LOCALIZATION NOTE (enterFullScreenCmd.label, exitFullScreenCmd.label):
|
<!-- LOCALIZATION NOTE (enterFullScreenCmd.label, exitFullScreenCmd.label):
|
||||||
These should match what Safari and other Apple applications use on OS X Lion. -->
|
These should match what Safari and other Apple applications use on OS X Lion. -->
|
||||||
<!ENTITY enterFullScreenCmd.label "Enter Full Screen">
|
<!ENTITY enterFullScreenCmd.label "Enter Full Screen">
|
||||||
|
@ -494,8 +492,6 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
||||||
<!ENTITY emailImageCmd.accesskey "g">
|
<!ENTITY emailImageCmd.accesskey "g">
|
||||||
<!ENTITY emailVideoCmd.label "Email Video…">
|
<!ENTITY emailVideoCmd.label "Email Video…">
|
||||||
<!ENTITY emailVideoCmd.accesskey "a">
|
<!ENTITY emailVideoCmd.accesskey "a">
|
||||||
<!ENTITY castVideoCmd.label "Send Video To Device">
|
|
||||||
<!ENTITY castVideoCmd.accesskey "e">
|
|
||||||
<!ENTITY emailAudioCmd.label "Email Audio…">
|
<!ENTITY emailAudioCmd.label "Email Audio…">
|
||||||
<!ENTITY emailAudioCmd.accesskey "a">
|
<!ENTITY emailAudioCmd.accesskey "a">
|
||||||
<!ENTITY playPluginCmd.label "Activate this plugin">
|
<!ENTITY playPluginCmd.label "Activate this plugin">
|
||||||
|
|
|
@ -1,164 +0,0 @@
|
||||||
// -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
|
|
||||||
/* 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/. */
|
|
||||||
"use strict";
|
|
||||||
this.EXPORTED_SYMBOLS = ["CastingApps"];
|
|
||||||
|
|
||||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
|
||||||
Cu.import("resource://gre/modules/SimpleServiceDiscovery.jsm");
|
|
||||||
|
|
||||||
|
|
||||||
var CastingApps = {
|
|
||||||
_sendEventToVideo: function (element, data) {
|
|
||||||
let event = element.ownerDocument.createEvent("CustomEvent");
|
|
||||||
event.initCustomEvent("media-videoCasting", false, true, JSON.stringify(data));
|
|
||||||
element.dispatchEvent(event);
|
|
||||||
},
|
|
||||||
|
|
||||||
makeURI: function (url, charset, baseURI) {
|
|
||||||
return Services.io.newURI(url, charset, baseURI);
|
|
||||||
},
|
|
||||||
|
|
||||||
getVideo: function (element) {
|
|
||||||
if (!element) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let extensions = SimpleServiceDiscovery.getSupportedExtensions();
|
|
||||||
let types = SimpleServiceDiscovery.getSupportedMimeTypes();
|
|
||||||
|
|
||||||
// Grab the poster attribute from the <video>
|
|
||||||
let posterURL = element.poster;
|
|
||||||
|
|
||||||
// First, look to see if the <video> has a src attribute
|
|
||||||
let sourceURL = element.src;
|
|
||||||
|
|
||||||
// If empty, try the currentSrc
|
|
||||||
if (!sourceURL) {
|
|
||||||
sourceURL = element.currentSrc;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sourceURL) {
|
|
||||||
// Use the file extension to guess the mime type
|
|
||||||
let sourceURI = this.makeURI(sourceURL, null, this.makeURI(element.baseURI));
|
|
||||||
if (this.allowableExtension(sourceURI, extensions)) {
|
|
||||||
return { element: element, source: sourceURI.spec, poster: posterURL, sourceURI: sourceURI};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next, look to see if there is a <source> child element that meets
|
|
||||||
// our needs
|
|
||||||
let sourceNodes = element.getElementsByTagName("source");
|
|
||||||
for (let sourceNode of sourceNodes) {
|
|
||||||
let sourceURI = this.makeURI(sourceNode.src, null, this.makeURI(sourceNode.baseURI));
|
|
||||||
|
|
||||||
// Using the type attribute is our ideal way to guess the mime type. Otherwise,
|
|
||||||
// fallback to using the file extension to guess the mime type
|
|
||||||
if (this.allowableMimeType(sourceNode.type, types) || this.allowableExtension(sourceURI, extensions)) {
|
|
||||||
return { element: element, source: sourceURI.spec, poster: posterURL, sourceURI: sourceURI, type: sourceNode.type };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
sendVideoToService: function (videoElement, service) {
|
|
||||||
if (!service)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let video = this.getVideo(videoElement);
|
|
||||||
if (!video) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we have a player app for the given service
|
|
||||||
let app = SimpleServiceDiscovery.findAppForService(service);
|
|
||||||
if (!app)
|
|
||||||
return;
|
|
||||||
|
|
||||||
video.title = videoElement.ownerGlobal.top.document.title;
|
|
||||||
if (video.element) {
|
|
||||||
// If the video is currently playing on the device, pause it
|
|
||||||
if (!video.element.paused) {
|
|
||||||
video.element.pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
app.stop(() => {
|
|
||||||
app.start(started => {
|
|
||||||
if (!started) {
|
|
||||||
Cu.reportError("CastingApps: Unable to start app");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
app.remoteMedia(remoteMedia => {
|
|
||||||
if (!remoteMedia) {
|
|
||||||
Cu.reportError("CastingApps: Failed to create remotemedia");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.session = {
|
|
||||||
service: service,
|
|
||||||
app: app,
|
|
||||||
remoteMedia: remoteMedia,
|
|
||||||
data: {
|
|
||||||
title: video.title,
|
|
||||||
source: video.source,
|
|
||||||
poster: video.poster
|
|
||||||
},
|
|
||||||
videoRef: Cu.getWeakReference(video.element)
|
|
||||||
};
|
|
||||||
}, this);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
getServicesForVideo: function (videoElement) {
|
|
||||||
let video = this.getVideo(videoElement);
|
|
||||||
if (!video) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
let filteredServices = SimpleServiceDiscovery.services.filter(service => {
|
|
||||||
return this.allowableExtension(video.sourceURI, service.extensions) ||
|
|
||||||
this.allowableMimeType(video.type, service.types);
|
|
||||||
});
|
|
||||||
|
|
||||||
return filteredServices;
|
|
||||||
},
|
|
||||||
|
|
||||||
getServicesForMirroring: function () {
|
|
||||||
return SimpleServiceDiscovery.services.filter(service => service.mirror);
|
|
||||||
},
|
|
||||||
|
|
||||||
// RemoteMedia callback API methods
|
|
||||||
onRemoteMediaStart: function (remoteMedia) {
|
|
||||||
if (!this.session) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
remoteMedia.load(this.session.data);
|
|
||||||
|
|
||||||
let video = this.session.videoRef.get();
|
|
||||||
if (video) {
|
|
||||||
this._sendEventToVideo(video, { active: true });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onRemoteMediaStop: function (remoteMedia) {
|
|
||||||
},
|
|
||||||
|
|
||||||
onRemoteMediaStatus: function (remoteMedia) {
|
|
||||||
},
|
|
||||||
|
|
||||||
allowableExtension: function (uri, extensions) {
|
|
||||||
return (uri instanceof Ci.nsIURL) && extensions.indexOf(uri.fileExtension) != -1;
|
|
||||||
},
|
|
||||||
|
|
||||||
allowableMimeType: function (type, types) {
|
|
||||||
return types.indexOf(type) != -1;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -9,7 +9,6 @@ EXTRA_JS_MODULES += [
|
||||||
'AboutNewTab.jsm',
|
'AboutNewTab.jsm',
|
||||||
'AttributionCode.jsm',
|
'AttributionCode.jsm',
|
||||||
'BrowserUsageTelemetry.jsm',
|
'BrowserUsageTelemetry.jsm',
|
||||||
'CastingApps.jsm',
|
|
||||||
'ContentClick.jsm',
|
'ContentClick.jsm',
|
||||||
'ContentLinkHandler.jsm',
|
'ContentLinkHandler.jsm',
|
||||||
'ContentObservers.jsm',
|
'ContentObservers.jsm',
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
#include "mozilla/dom/FlyWebPublishedServer.h"
|
#include "mozilla/dom/FlyWebPublishedServer.h"
|
||||||
#include "mozilla/dom/FlyWebService.h"
|
#include "mozilla/dom/FlyWebService.h"
|
||||||
#include "mozilla/dom/Permissions.h"
|
#include "mozilla/dom/Permissions.h"
|
||||||
#include "mozilla/dom/Presentation.h"
|
|
||||||
#include "mozilla/dom/ServiceWorkerContainer.h"
|
#include "mozilla/dom/ServiceWorkerContainer.h"
|
||||||
#include "mozilla/dom/StorageManager.h"
|
#include "mozilla/dom/StorageManager.h"
|
||||||
#include "mozilla/dom/TCPSocket.h"
|
#include "mozilla/dom/TCPSocket.h"
|
||||||
|
@ -67,8 +66,6 @@
|
||||||
#include "nsIAppsService.h"
|
#include "nsIAppsService.h"
|
||||||
#include "mozIApplication.h"
|
#include "mozIApplication.h"
|
||||||
#include "WidgetUtils.h"
|
#include "WidgetUtils.h"
|
||||||
#include "nsIPresentationService.h"
|
|
||||||
|
|
||||||
#include "mozilla/dom/MediaDevices.h"
|
#include "mozilla/dom/MediaDevices.h"
|
||||||
#include "MediaManager.h"
|
#include "MediaManager.h"
|
||||||
|
|
||||||
|
@ -218,7 +215,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
|
||||||
#ifdef MOZ_EME
|
#ifdef MOZ_EME
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager)
|
||||||
#endif
|
#endif
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresentation)
|
|
||||||
#ifdef MOZ_GAMEPAD
|
#ifdef MOZ_GAMEPAD
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepadServiceTest)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepadServiceTest)
|
||||||
#endif
|
#endif
|
||||||
|
@ -284,10 +280,6 @@ Navigator::Invalidate()
|
||||||
mTimeManager = nullptr;
|
mTimeManager = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPresentation) {
|
|
||||||
mPresentation = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
mServiceWorkerContainer = nullptr;
|
mServiceWorkerContainer = nullptr;
|
||||||
|
|
||||||
#ifdef MOZ_EME
|
#ifdef MOZ_EME
|
||||||
|
@ -1931,19 +1923,5 @@ Navigator::RequestMediaKeySystemAccess(const nsAString& aKeySystem,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Presentation*
|
|
||||||
Navigator::GetPresentation(ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
if (!mPresentation) {
|
|
||||||
if (!mWindow) {
|
|
||||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
mPresentation = Presentation::Create(mWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mPresentation;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -74,7 +74,6 @@ class Connection;
|
||||||
} // namespace network
|
} // namespace network
|
||||||
|
|
||||||
class PowerManager;
|
class PowerManager;
|
||||||
class Presentation;
|
|
||||||
class LegacyMozTCPSocket;
|
class LegacyMozTCPSocket;
|
||||||
class StorageManager;
|
class StorageManager;
|
||||||
|
|
||||||
|
@ -210,8 +209,6 @@ public:
|
||||||
system::AudioChannelManager* GetMozAudioChannelManager(ErrorResult& aRv);
|
system::AudioChannelManager* GetMozAudioChannelManager(ErrorResult& aRv);
|
||||||
#endif // MOZ_AUDIO_CHANNEL_MANAGER
|
#endif // MOZ_AUDIO_CHANNEL_MANAGER
|
||||||
|
|
||||||
Presentation* GetPresentation(ErrorResult& aRv);
|
|
||||||
|
|
||||||
bool SendBeacon(const nsAString& aUrl,
|
bool SendBeacon(const nsAString& aUrl,
|
||||||
const Nullable<ArrayBufferViewOrBlobOrStringOrFormData>& aData,
|
const Nullable<ArrayBufferViewOrBlobOrStringOrFormData>& aData,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
|
@ -288,7 +285,6 @@ private:
|
||||||
RefPtr<time::TimeManager> mTimeManager;
|
RefPtr<time::TimeManager> mTimeManager;
|
||||||
RefPtr<ServiceWorkerContainer> mServiceWorkerContainer;
|
RefPtr<ServiceWorkerContainer> mServiceWorkerContainer;
|
||||||
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
||||||
RefPtr<Presentation> mPresentation;
|
|
||||||
#ifdef MOZ_GAMEPAD
|
#ifdef MOZ_GAMEPAD
|
||||||
RefPtr<GamepadServiceTest> mGamepadServiceTest;
|
RefPtr<GamepadServiceTest> mGamepadServiceTest;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -151,8 +151,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "mozilla/dom/File.h"
|
#include "mozilla/dom/File.h"
|
||||||
#include "mozilla/dom/PPresentationChild.h"
|
|
||||||
#include "mozilla/dom/PresentationIPCService.h"
|
|
||||||
#include "mozilla/ipc/InputStreamUtils.h"
|
#include "mozilla/ipc/InputStreamUtils.h"
|
||||||
|
|
||||||
#ifdef MOZ_WEBSPEECH
|
#ifdef MOZ_WEBSPEECH
|
||||||
|
@ -1418,20 +1416,6 @@ ContentChild::SendPBlobConstructor(PBlobChild* aActor,
|
||||||
return PContentChild::SendPBlobConstructor(aActor, aParams);
|
return PContentChild::SendPBlobConstructor(aActor, aParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
PPresentationChild*
|
|
||||||
ContentChild::AllocPPresentationChild()
|
|
||||||
{
|
|
||||||
MOZ_CRASH("We should never be manually allocating PPresentationChild actors");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
ContentChild::DeallocPPresentationChild(PPresentationChild* aActor)
|
|
||||||
{
|
|
||||||
delete aActor;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
PFlyWebPublishedServerChild*
|
PFlyWebPublishedServerChild*
|
||||||
ContentChild::AllocPFlyWebPublishedServerChild(const nsString& name,
|
ContentChild::AllocPFlyWebPublishedServerChild(const nsString& name,
|
||||||
const FlyWebPublishOptions& params)
|
const FlyWebPublishOptions& params)
|
||||||
|
@ -1448,35 +1432,6 @@ ContentChild::DeallocPFlyWebPublishedServerChild(PFlyWebPublishedServerChild* aA
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
ContentChild::RecvNotifyPresentationReceiverLaunched(PBrowserChild* aIframe,
|
|
||||||
const nsString& aSessionId)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDocShell> docShell =
|
|
||||||
do_GetInterface(static_cast<TabChild*>(aIframe)->WebNavigation());
|
|
||||||
NS_WARNING_ASSERTION(docShell, "WebNavigation failed");
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
NS_WARNING_ASSERTION(service, "presentation service is missing");
|
|
||||||
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(static_cast<PresentationIPCService*>(service.get())->MonitorResponderLoading(aSessionId, docShell)));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
ContentChild::RecvNotifyPresentationReceiverCleanUp(const nsString& aSessionId)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
NS_WARNING_ASSERTION(service, "presentation service is missing");
|
|
||||||
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(service->UntrackSessionInfo(aSessionId, nsIPresentationService::ROLE_RECEIVER)));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ContentChild::RecvNotifyEmptyHTTPCache()
|
ContentChild::RecvNotifyEmptyHTTPCache()
|
||||||
{
|
{
|
||||||
|
|
|
@ -298,23 +298,12 @@ public:
|
||||||
|
|
||||||
virtual bool DeallocPStorageChild(PStorageChild* aActor) override;
|
virtual bool DeallocPStorageChild(PStorageChild* aActor) override;
|
||||||
|
|
||||||
virtual PPresentationChild* AllocPPresentationChild() override;
|
|
||||||
|
|
||||||
virtual bool DeallocPPresentationChild(PPresentationChild* aActor) override;
|
|
||||||
|
|
||||||
virtual PFlyWebPublishedServerChild*
|
virtual PFlyWebPublishedServerChild*
|
||||||
AllocPFlyWebPublishedServerChild(const nsString& name,
|
AllocPFlyWebPublishedServerChild(const nsString& name,
|
||||||
const FlyWebPublishOptions& params) override;
|
const FlyWebPublishOptions& params) override;
|
||||||
|
|
||||||
virtual bool DeallocPFlyWebPublishedServerChild(PFlyWebPublishedServerChild* aActor) override;
|
virtual bool DeallocPFlyWebPublishedServerChild(PFlyWebPublishedServerChild* aActor) override;
|
||||||
|
|
||||||
virtual bool
|
|
||||||
RecvNotifyPresentationReceiverLaunched(PBrowserChild* aIframe,
|
|
||||||
const nsString& aSessionId) override;
|
|
||||||
|
|
||||||
virtual bool
|
|
||||||
RecvNotifyPresentationReceiverCleanUp(const nsString& aSessionId) override;
|
|
||||||
|
|
||||||
virtual bool RecvNotifyEmptyHTTPCache() override;
|
virtual bool RecvNotifyEmptyHTTPCache() override;
|
||||||
|
|
||||||
virtual PSpeechSynthesisChild* AllocPSpeechSynthesisChild() override;
|
virtual PSpeechSynthesisChild* AllocPSpeechSynthesisChild() override;
|
||||||
|
|
|
@ -53,8 +53,6 @@
|
||||||
#include "mozilla/dom/ServiceWorkerRegistrar.h"
|
#include "mozilla/dom/ServiceWorkerRegistrar.h"
|
||||||
#include "mozilla/dom/power/PowerManagerService.h"
|
#include "mozilla/dom/power/PowerManagerService.h"
|
||||||
#include "mozilla/dom/Permissions.h"
|
#include "mozilla/dom/Permissions.h"
|
||||||
#include "mozilla/dom/PresentationParent.h"
|
|
||||||
#include "mozilla/dom/PPresentationParent.h"
|
|
||||||
#include "mozilla/dom/PushNotifier.h"
|
#include "mozilla/dom/PushNotifier.h"
|
||||||
#include "mozilla/dom/FlyWebPublishedServerIPC.h"
|
#include "mozilla/dom/FlyWebPublishedServerIPC.h"
|
||||||
#include "mozilla/dom/quota/QuotaManagerService.h"
|
#include "mozilla/dom/quota/QuotaManagerService.h"
|
||||||
|
@ -3094,27 +3092,6 @@ ContentParent::DeallocPStorageParent(PStorageParent* aActor)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PPresentationParent*
|
|
||||||
ContentParent::AllocPPresentationParent()
|
|
||||||
{
|
|
||||||
RefPtr<PresentationParent> actor = new PresentationParent();
|
|
||||||
return actor.forget().take();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
ContentParent::DeallocPPresentationParent(PPresentationParent* aActor)
|
|
||||||
{
|
|
||||||
RefPtr<PresentationParent> actor =
|
|
||||||
dont_AddRef(static_cast<PresentationParent*>(aActor));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
ContentParent::RecvPPresentationConstructor(PPresentationParent* aActor)
|
|
||||||
{
|
|
||||||
return static_cast<PresentationParent*>(aActor)->Init(mChildID);
|
|
||||||
}
|
|
||||||
|
|
||||||
PFlyWebPublishedServerParent*
|
PFlyWebPublishedServerParent*
|
||||||
ContentParent::AllocPFlyWebPublishedServerParent(const nsString& name,
|
ContentParent::AllocPFlyWebPublishedServerParent(const nsString& name,
|
||||||
const FlyWebPublishOptions& params)
|
const FlyWebPublishOptions& params)
|
||||||
|
|
|
@ -801,12 +801,6 @@ private:
|
||||||
|
|
||||||
virtual bool DeallocPStorageParent(PStorageParent* aActor) override;
|
virtual bool DeallocPStorageParent(PStorageParent* aActor) override;
|
||||||
|
|
||||||
virtual PPresentationParent* AllocPPresentationParent() override;
|
|
||||||
|
|
||||||
virtual bool DeallocPPresentationParent(PPresentationParent* aActor) override;
|
|
||||||
|
|
||||||
virtual bool RecvPPresentationConstructor(PPresentationParent* aActor) override;
|
|
||||||
|
|
||||||
virtual PFlyWebPublishedServerParent*
|
virtual PFlyWebPublishedServerParent*
|
||||||
AllocPFlyWebPublishedServerParent(const nsString& name,
|
AllocPFlyWebPublishedServerParent(const nsString& name,
|
||||||
const FlyWebPublishOptions& params) override;
|
const FlyWebPublishOptions& params) override;
|
||||||
|
|
|
@ -43,7 +43,6 @@ include protocol PJavaScript;
|
||||||
include protocol PRemoteSpellcheckEngine;
|
include protocol PRemoteSpellcheckEngine;
|
||||||
include protocol PWebBrowserPersistDocument;
|
include protocol PWebBrowserPersistDocument;
|
||||||
include protocol PWebrtcGlobal;
|
include protocol PWebrtcGlobal;
|
||||||
include protocol PPresentation;
|
|
||||||
include protocol PVideoDecoderManager;
|
include protocol PVideoDecoderManager;
|
||||||
include protocol PFlyWebPublishedServer;
|
include protocol PFlyWebPublishedServer;
|
||||||
include DOMTypes;
|
include DOMTypes;
|
||||||
|
@ -260,7 +259,6 @@ nested(upto inside_cpow) sync protocol PContent
|
||||||
manages PRemoteSpellcheckEngine;
|
manages PRemoteSpellcheckEngine;
|
||||||
manages PWebBrowserPersistDocument;
|
manages PWebBrowserPersistDocument;
|
||||||
manages PWebrtcGlobal;
|
manages PWebrtcGlobal;
|
||||||
manages PPresentation;
|
|
||||||
manages PFlyWebPublishedServer;
|
manages PFlyWebPublishedServer;
|
||||||
|
|
||||||
both:
|
both:
|
||||||
|
@ -479,18 +477,6 @@ child:
|
||||||
*/
|
*/
|
||||||
async UpdateWindow(uintptr_t aChildId);
|
async UpdateWindow(uintptr_t aChildId);
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify the child that presentation receiver has been launched with the
|
|
||||||
* correspondent iframe.
|
|
||||||
*/
|
|
||||||
async NotifyPresentationReceiverLaunched(PBrowser aIframe, nsString aSessionId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify the child that the info about a presentation receiver needs to be
|
|
||||||
* cleaned up.
|
|
||||||
*/
|
|
||||||
async NotifyPresentationReceiverCleanUp(nsString aSessionId);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify the child that cache is emptied.
|
* Notify the child that cache is emptied.
|
||||||
*/
|
*/
|
||||||
|
@ -681,8 +667,6 @@ parent:
|
||||||
|
|
||||||
async PWebrtcGlobal();
|
async PWebrtcGlobal();
|
||||||
|
|
||||||
async PPresentation();
|
|
||||||
|
|
||||||
async PFlyWebPublishedServer(nsString name, FlyWebPublishOptions params);
|
async PFlyWebPublishedServer(nsString name, FlyWebPublishOptions params);
|
||||||
|
|
||||||
// Services remoting
|
// Services remoting
|
||||||
|
|
|
@ -40,7 +40,6 @@ include protocol PJavaScript;
|
||||||
include protocol PRemoteSpellcheckEngine;
|
include protocol PRemoteSpellcheckEngine;
|
||||||
include protocol PWebBrowserPersistDocument;
|
include protocol PWebBrowserPersistDocument;
|
||||||
include protocol PWebrtcGlobal;
|
include protocol PWebrtcGlobal;
|
||||||
include protocol PPresentation;
|
|
||||||
include protocol PVideoDecoderManager;
|
include protocol PVideoDecoderManager;
|
||||||
include protocol PFlyWebPublishedServer;
|
include protocol PFlyWebPublishedServer;
|
||||||
include DOMTypes;
|
include DOMTypes;
|
||||||
|
@ -243,7 +242,6 @@ nested(upto inside_cpow) sync protocol PContent
|
||||||
manages PRemoteSpellcheckEngine;
|
manages PRemoteSpellcheckEngine;
|
||||||
manages PWebBrowserPersistDocument;
|
manages PWebBrowserPersistDocument;
|
||||||
manages PWebrtcGlobal;
|
manages PWebrtcGlobal;
|
||||||
manages PPresentation;
|
|
||||||
manages PFlyWebPublishedServer;
|
manages PFlyWebPublishedServer;
|
||||||
|
|
||||||
both:
|
both:
|
||||||
|
@ -462,18 +460,6 @@ child:
|
||||||
*/
|
*/
|
||||||
async UpdateWindow(uintptr_t aChildId);
|
async UpdateWindow(uintptr_t aChildId);
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify the child that presentation receiver has been launched with the
|
|
||||||
* correspondent iframe.
|
|
||||||
*/
|
|
||||||
async NotifyPresentationReceiverLaunched(PBrowser aIframe, nsString aSessionId);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify the child that the info about a presentation receiver needs to be
|
|
||||||
* cleaned up.
|
|
||||||
*/
|
|
||||||
async NotifyPresentationReceiverCleanUp(nsString aSessionId);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify the child that cache is emptied.
|
* Notify the child that cache is emptied.
|
||||||
*/
|
*/
|
||||||
|
@ -659,8 +645,6 @@ parent:
|
||||||
|
|
||||||
async PWebrtcGlobal();
|
async PWebrtcGlobal();
|
||||||
|
|
||||||
async PPresentation();
|
|
||||||
|
|
||||||
async PFlyWebPublishedServer(nsString name, FlyWebPublishOptions params);
|
async PFlyWebPublishedServer(nsString name, FlyWebPublishOptions params);
|
||||||
|
|
||||||
// Services remoting
|
// Services remoting
|
||||||
|
|
|
@ -107,8 +107,6 @@ if CONFIG['OS_ARCH'] == 'WINNT':
|
||||||
if CONFIG['MOZ_SECUREELEMENT']:
|
if CONFIG['MOZ_SECUREELEMENT']:
|
||||||
DIRS += ['secureelement']
|
DIRS += ['secureelement']
|
||||||
|
|
||||||
DIRS += ['presentation']
|
|
||||||
|
|
||||||
TEST_DIRS += [
|
TEST_DIRS += [
|
||||||
'tests',
|
'tests',
|
||||||
'imptests',
|
'imptests',
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
/* -*- 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 "AvailabilityCollection.h"
|
|
||||||
|
|
||||||
#include "mozilla/ClearOnShutdown.h"
|
|
||||||
#include "PresentationAvailability.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
/* static */
|
|
||||||
StaticAutoPtr<AvailabilityCollection>
|
|
||||||
AvailabilityCollection::sSingleton;
|
|
||||||
static bool gOnceAliveNowDead = false;
|
|
||||||
|
|
||||||
/* static */ AvailabilityCollection*
|
|
||||||
AvailabilityCollection::GetSingleton()
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (!sSingleton && !gOnceAliveNowDead) {
|
|
||||||
sSingleton = new AvailabilityCollection();
|
|
||||||
ClearOnShutdown(&sSingleton);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sSingleton;
|
|
||||||
}
|
|
||||||
|
|
||||||
AvailabilityCollection::AvailabilityCollection()
|
|
||||||
{
|
|
||||||
MOZ_COUNT_CTOR(AvailabilityCollection);
|
|
||||||
}
|
|
||||||
|
|
||||||
AvailabilityCollection::~AvailabilityCollection()
|
|
||||||
{
|
|
||||||
MOZ_COUNT_DTOR(AvailabilityCollection);
|
|
||||||
gOnceAliveNowDead = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
AvailabilityCollection::Add(PresentationAvailability* aAvailability)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (!aAvailability) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WeakPtr<PresentationAvailability> availability = aAvailability;
|
|
||||||
if (mAvailabilities.Contains(aAvailability)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mAvailabilities.AppendElement(aAvailability);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
AvailabilityCollection::Remove(PresentationAvailability* aAvailability)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (!aAvailability) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WeakPtr<PresentationAvailability> availability = aAvailability;
|
|
||||||
mAvailabilities.RemoveElement(availability);
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<PresentationAvailability>
|
|
||||||
AvailabilityCollection::Find(const uint64_t aWindowId, const nsTArray<nsString>& aUrls)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
// Loop backwards to allow removing elements in the loop.
|
|
||||||
for (int i = mAvailabilities.Length() - 1; i >= 0; --i) {
|
|
||||||
WeakPtr<PresentationAvailability> availability = mAvailabilities[i];
|
|
||||||
if (!availability) {
|
|
||||||
// The availability object was destroyed. Remove it from the list.
|
|
||||||
mAvailabilities.RemoveElementAt(i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (availability->Equals(aWindowId, aUrls)) {
|
|
||||||
RefPtr<PresentationAvailability> matchedAvailability = availability.get();
|
|
||||||
return matchedAvailability.forget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,45 +0,0 @@
|
||||||
/* -*- 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_AvailabilityCollection_h
|
|
||||||
#define mozilla_dom_AvailabilityCollection_h
|
|
||||||
|
|
||||||
#include "mozilla/StaticPtr.h"
|
|
||||||
#include "mozilla/WeakPtr.h"
|
|
||||||
#include "nsString.h"
|
|
||||||
#include "nsTArray.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class PresentationAvailability;
|
|
||||||
|
|
||||||
class AvailabilityCollection final
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static AvailabilityCollection* GetSingleton();
|
|
||||||
|
|
||||||
void Add(PresentationAvailability* aAvailability);
|
|
||||||
|
|
||||||
void Remove(PresentationAvailability* aAvailability);
|
|
||||||
|
|
||||||
already_AddRefed<PresentationAvailability>
|
|
||||||
Find(const uint64_t aWindowId, const nsTArray<nsString>& aUrls);
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class StaticAutoPtr<AvailabilityCollection>;
|
|
||||||
|
|
||||||
AvailabilityCollection();
|
|
||||||
virtual ~AvailabilityCollection();
|
|
||||||
|
|
||||||
static StaticAutoPtr<AvailabilityCollection> sSingleton;
|
|
||||||
nsTArray<WeakPtr<PresentationAvailability>> mAvailabilities;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_AvailabilityCollection_h
|
|
|
@ -1,116 +0,0 @@
|
||||||
/* -*- 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 "ControllerConnectionCollection.h"
|
|
||||||
|
|
||||||
#include "mozilla/ClearOnShutdown.h"
|
|
||||||
#include "nsIPresentationService.h"
|
|
||||||
#include "PresentationConnection.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
/* static */
|
|
||||||
StaticAutoPtr<ControllerConnectionCollection>
|
|
||||||
ControllerConnectionCollection::sSingleton;
|
|
||||||
|
|
||||||
/* static */ ControllerConnectionCollection*
|
|
||||||
ControllerConnectionCollection::GetSingleton()
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (!sSingleton) {
|
|
||||||
sSingleton = new ControllerConnectionCollection();
|
|
||||||
ClearOnShutdown(&sSingleton);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sSingleton;
|
|
||||||
}
|
|
||||||
|
|
||||||
ControllerConnectionCollection::ControllerConnectionCollection()
|
|
||||||
{
|
|
||||||
MOZ_COUNT_CTOR(ControllerConnectionCollection);
|
|
||||||
}
|
|
||||||
|
|
||||||
ControllerConnectionCollection::~ControllerConnectionCollection()
|
|
||||||
{
|
|
||||||
MOZ_COUNT_DTOR(ControllerConnectionCollection);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ControllerConnectionCollection::AddConnection(
|
|
||||||
PresentationConnection* aConnection,
|
|
||||||
const uint8_t aRole)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
if (aRole != nsIPresentationService::ROLE_CONTROLLER) {
|
|
||||||
MOZ_ASSERT(false, "This is allowed only to be called at controller side.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!aConnection) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WeakPtr<PresentationConnection> connection = aConnection;
|
|
||||||
if (mConnections.Contains(connection)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mConnections.AppendElement(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ControllerConnectionCollection::RemoveConnection(
|
|
||||||
PresentationConnection* aConnection,
|
|
||||||
const uint8_t aRole)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
if (aRole != nsIPresentationService::ROLE_CONTROLLER) {
|
|
||||||
MOZ_ASSERT(false, "This is allowed only to be called at controller side.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!aConnection) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WeakPtr<PresentationConnection> connection = aConnection;
|
|
||||||
mConnections.RemoveElement(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<PresentationConnection>
|
|
||||||
ControllerConnectionCollection::FindConnection(
|
|
||||||
uint64_t aWindowId,
|
|
||||||
const nsAString& aId,
|
|
||||||
const uint8_t aRole)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
if (aRole != nsIPresentationService::ROLE_CONTROLLER) {
|
|
||||||
MOZ_ASSERT(false, "This is allowed only to be called at controller side.");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop backwards to allow removing elements in the loop.
|
|
||||||
for (int i = mConnections.Length() - 1; i >= 0; --i) {
|
|
||||||
WeakPtr<PresentationConnection> connection = mConnections[i];
|
|
||||||
if (!connection) {
|
|
||||||
// The connection was destroyed. Remove it from the list.
|
|
||||||
mConnections.RemoveElementAt(i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connection->Equals(aWindowId, aId)) {
|
|
||||||
RefPtr<PresentationConnection> matchedConnection = connection.get();
|
|
||||||
return matchedConnection.forget();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,49 +0,0 @@
|
||||||
/* -*- 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_ControllerConnectionCollection_h
|
|
||||||
#define mozilla_dom_ControllerConnectionCollection_h
|
|
||||||
|
|
||||||
#include "mozilla/StaticPtr.h"
|
|
||||||
#include "mozilla/WeakPtr.h"
|
|
||||||
#include "nsString.h"
|
|
||||||
#include "nsTArray.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class PresentationConnection;
|
|
||||||
|
|
||||||
class ControllerConnectionCollection final
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static ControllerConnectionCollection* GetSingleton();
|
|
||||||
|
|
||||||
void AddConnection(PresentationConnection* aConnection,
|
|
||||||
const uint8_t aRole);
|
|
||||||
|
|
||||||
void RemoveConnection(PresentationConnection* aConnection,
|
|
||||||
const uint8_t aRole);
|
|
||||||
|
|
||||||
already_AddRefed<PresentationConnection>
|
|
||||||
FindConnection(uint64_t aWindowId,
|
|
||||||
const nsAString& aId,
|
|
||||||
const uint8_t aRole);
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class StaticAutoPtr<ControllerConnectionCollection>;
|
|
||||||
|
|
||||||
ControllerConnectionCollection();
|
|
||||||
virtual ~ControllerConnectionCollection();
|
|
||||||
|
|
||||||
static StaticAutoPtr<ControllerConnectionCollection> sSingleton;
|
|
||||||
nsTArray<WeakPtr<PresentationConnection>> mConnections;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_ControllerConnectionCollection_h
|
|
|
@ -1,46 +0,0 @@
|
||||||
/* -*- 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 "DCPresentationChannelDescription.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(DCPresentationChannelDescription,
|
|
||||||
nsIPresentationChannelDescription)
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
DCPresentationChannelDescription::GetType(uint8_t* aRetVal)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!aRetVal)) {
|
|
||||||
return NS_ERROR_INVALID_POINTER;
|
|
||||||
}
|
|
||||||
|
|
||||||
*aRetVal = nsIPresentationChannelDescription::TYPE_DATACHANNEL;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
DCPresentationChannelDescription::GetTcpAddress(nsIArray** aRetVal)
|
|
||||||
{
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
DCPresentationChannelDescription::GetTcpPort(uint16_t* aRetVal)
|
|
||||||
{
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
DCPresentationChannelDescription::GetDataChannelSDP(nsAString& aDataChannelSDP)
|
|
||||||
{
|
|
||||||
aDataChannelSDP = mSDP;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,37 +0,0 @@
|
||||||
/* -*- 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_DCPresentationChannelDescription_h
|
|
||||||
#define mozilla_dom_DCPresentationChannelDescription_h
|
|
||||||
|
|
||||||
#include "nsIPresentationControlChannel.h"
|
|
||||||
#include "nsString.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
// PresentationChannelDescription for Data Channel
|
|
||||||
class DCPresentationChannelDescription final : public nsIPresentationChannelDescription
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIPRESENTATIONCHANNELDESCRIPTION
|
|
||||||
|
|
||||||
explicit DCPresentationChannelDescription(const nsAString& aSDP)
|
|
||||||
: mSDP(aSDP)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~DCPresentationChannelDescription() = default;
|
|
||||||
|
|
||||||
nsString mSDP;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_DCPresentationChannelDescription_h
|
|
|
@ -1,182 +0,0 @@
|
||||||
/* -*- 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 "Presentation.h"
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "mozilla/dom/PresentationBinding.h"
|
|
||||||
#include "mozilla/dom/Promise.h"
|
|
||||||
#include "nsContentUtils.h"
|
|
||||||
#include "nsCycleCollectionParticipant.h"
|
|
||||||
#include "nsIDocShell.h"
|
|
||||||
#include "nsIPresentationService.h"
|
|
||||||
#include "nsIScriptSecurityManager.h"
|
|
||||||
#include "nsJSUtils.h"
|
|
||||||
#include "nsNetUtil.h"
|
|
||||||
#include "nsPIDOMWindow.h"
|
|
||||||
#include "nsSandboxFlags.h"
|
|
||||||
#include "nsServiceManagerUtils.h"
|
|
||||||
#include "PresentationReceiver.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Presentation,
|
|
||||||
mWindow,
|
|
||||||
mDefaultRequest, mReceiver)
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(Presentation)
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(Presentation)
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Presentation)
|
|
||||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
||||||
NS_INTERFACE_MAP_END
|
|
||||||
|
|
||||||
/* static */ already_AddRefed<Presentation>
|
|
||||||
Presentation::Create(nsPIDOMWindowInner* aWindow)
|
|
||||||
{
|
|
||||||
RefPtr<Presentation> presentation = new Presentation(aWindow);
|
|
||||||
return presentation.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
Presentation::Presentation(nsPIDOMWindowInner* aWindow)
|
|
||||||
: mWindow(aWindow)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Presentation::~Presentation()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual */ JSObject*
|
|
||||||
Presentation::WrapObject(JSContext* aCx,
|
|
||||||
JS::Handle<JSObject*> aGivenProto)
|
|
||||||
{
|
|
||||||
return PresentationBinding::Wrap(aCx, this, aGivenProto);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Presentation::SetDefaultRequest(PresentationRequest* aRequest)
|
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
|
||||||
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 (!HasReceiverSupport() || !IsInPresentedContent()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
mReceiver = PresentationReceiver::Create(mWindow);
|
|
||||||
if (NS_WARN_IF(!mReceiver)) {
|
|
||||||
MOZ_ASSERT(mReceiver);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<PresentationReceiver> receiver = mReceiver;
|
|
||||||
return receiver.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Presentation::SetStartSessionUnsettled(bool aIsUnsettled)
|
|
||||||
{
|
|
||||||
mStartSessionUnsettled = aIsUnsettled;
|
|
||||||
}
|
|
||||||
|
|
||||||
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() &&
|
|
||||||
!docShell->GetIsTopLevelContentDocShell()) {
|
|
||||||
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);
|
|
||||||
|
|
||||||
nsAutoString presentationURL;
|
|
||||||
nsContentUtils::GetPresentationURL(docShell, presentationURL);
|
|
||||||
|
|
||||||
return !presentationURL.IsEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,70 +0,0 @@
|
||||||
/* -*- 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_Presentation_h
|
|
||||||
#define mozilla_dom_Presentation_h
|
|
||||||
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsCycleCollectionParticipant.h"
|
|
||||||
#include "nsISupportsImpl.h"
|
|
||||||
#include "nsWrapperCache.h"
|
|
||||||
|
|
||||||
class nsPIDOMWindowInner;
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class Promise;
|
|
||||||
class PresentationReceiver;
|
|
||||||
class PresentationRequest;
|
|
||||||
|
|
||||||
class Presentation final : public nsISupports
|
|
||||||
, public nsWrapperCache
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Presentation)
|
|
||||||
|
|
||||||
static already_AddRefed<Presentation> Create(nsPIDOMWindowInner* aWindow);
|
|
||||||
|
|
||||||
virtual JSObject* WrapObject(JSContext* aCx,
|
|
||||||
JS::Handle<JSObject*> aGivenProto) override;
|
|
||||||
|
|
||||||
nsPIDOMWindowInner* GetParentObject() const
|
|
||||||
{
|
|
||||||
return mWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
// WebIDL (public APIs)
|
|
||||||
void SetDefaultRequest(PresentationRequest* aRequest);
|
|
||||||
|
|
||||||
already_AddRefed<PresentationRequest> GetDefaultRequest() const;
|
|
||||||
|
|
||||||
already_AddRefed<PresentationReceiver> GetReceiver();
|
|
||||||
|
|
||||||
// For bookkeeping unsettled start session request
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_Presentation_h
|
|
|
@ -1,206 +0,0 @@
|
||||||
/* -*- 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 "mozilla/Unused.h"
|
|
||||||
#include "nsCycleCollectionParticipant.h"
|
|
||||||
#include "nsIPresentationDeviceManager.h"
|
|
||||||
#include "nsIPresentationService.h"
|
|
||||||
#include "nsServiceManagerUtils.h"
|
|
||||||
#include "PresentationLog.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(mPromises)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PresentationAvailability, DOMEventTargetHelper)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromises);
|
|
||||||
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,
|
|
||||||
const nsTArray<nsString>& aUrls,
|
|
||||||
RefPtr<Promise>& aPromise)
|
|
||||||
{
|
|
||||||
RefPtr<PresentationAvailability> availability =
|
|
||||||
new PresentationAvailability(aWindow, aUrls);
|
|
||||||
return NS_WARN_IF(!availability->Init(aPromise)) ? nullptr
|
|
||||||
: availability.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationAvailability::PresentationAvailability(nsPIDOMWindowInner* aWindow,
|
|
||||||
const nsTArray<nsString>& aUrls)
|
|
||||||
: DOMEventTargetHelper(aWindow)
|
|
||||||
, mIsAvailable(false)
|
|
||||||
, mUrls(aUrls)
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < mUrls.Length(); ++i) {
|
|
||||||
mAvailabilityOfUrl.AppendElement(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationAvailability::~PresentationAvailability()
|
|
||||||
{
|
|
||||||
Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationAvailability::Init(RefPtr<Promise>& aPromise)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!service)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv = service->RegisterAvailabilityListener(mUrls, this);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
// If the user agent is unable to monitor available device,
|
|
||||||
// Resolve promise with |value| set to false.
|
|
||||||
mIsAvailable = false;
|
|
||||||
aPromise->MaybeResolve(this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
EnqueuePromise(aPromise);
|
|
||||||
|
|
||||||
AvailabilityCollection* collection = AvailabilityCollection::GetSingleton();
|
|
||||||
if (collection) {
|
|
||||||
collection->Add(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PresentationAvailability::Shutdown()
|
|
||||||
{
|
|
||||||
AvailabilityCollection* collection = AvailabilityCollection::GetSingleton();
|
|
||||||
if (collection ) {
|
|
||||||
collection->Remove(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!service)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Unused <<
|
|
||||||
NS_WARN_IF(NS_FAILED(service->UnregisterAvailabilityListener(mUrls,
|
|
||||||
this)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual */ void
|
|
||||||
PresentationAvailability::DisconnectFromOwner()
|
|
||||||
{
|
|
||||||
Shutdown();
|
|
||||||
DOMEventTargetHelper::DisconnectFromOwner();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual */ JSObject*
|
|
||||||
PresentationAvailability::WrapObject(JSContext* aCx,
|
|
||||||
JS::Handle<JSObject*> aGivenProto)
|
|
||||||
{
|
|
||||||
return PresentationAvailabilityBinding::Wrap(aCx, this, aGivenProto);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationAvailability::Equals(const uint64_t aWindowID,
|
|
||||||
const nsTArray<nsString>& aUrls) const
|
|
||||||
{
|
|
||||||
if (GetOwner() && GetOwner()->WindowID() == aWindowID &&
|
|
||||||
mUrls.Length() == aUrls.Length()) {
|
|
||||||
for (const auto& url : aUrls) {
|
|
||||||
if (!mUrls.Contains(url)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationAvailability::IsCachedValueReady()
|
|
||||||
{
|
|
||||||
// All pending promises will be solved when cached value is ready and
|
|
||||||
// no promise should be enqueued afterward.
|
|
||||||
return mPromises.IsEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationAvailability::EnqueuePromise(RefPtr<Promise>& aPromise)
|
|
||||||
{
|
|
||||||
mPromises.AppendElement(aPromise);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationAvailability::Value() const
|
|
||||||
{
|
|
||||||
return mIsAvailable;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationAvailability::NotifyAvailableChange(const nsTArray<nsString>& aAvailabilityUrls,
|
|
||||||
bool aIsAvailable)
|
|
||||||
{
|
|
||||||
bool available = false;
|
|
||||||
for (uint32_t i = 0; i < mUrls.Length(); ++i) {
|
|
||||||
if (aAvailabilityUrls.Contains(mUrls[i])) {
|
|
||||||
mAvailabilityOfUrl[i] = aIsAvailable;
|
|
||||||
}
|
|
||||||
available |= mAvailabilityOfUrl[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_DispatchToCurrentThread(NewRunnableMethod
|
|
||||||
<bool>(this,
|
|
||||||
&PresentationAvailability::UpdateAvailabilityAndDispatchEvent,
|
|
||||||
available));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationAvailability::UpdateAvailabilityAndDispatchEvent(bool aIsAvailable)
|
|
||||||
{
|
|
||||||
PRES_DEBUG("%s\n", __func__);
|
|
||||||
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);
|
|
||||||
for (auto& promise : promises) {
|
|
||||||
promise->MaybeResolve(this);
|
|
||||||
}
|
|
||||||
// more promises may have been added to mPromises, at least in theory
|
|
||||||
} while (!mPromises.IsEmpty());
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isChanged) {
|
|
||||||
Unused <<
|
|
||||||
NS_WARN_IF(NS_FAILED(DispatchTrustedEvent(NS_LITERAL_STRING("change"))));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
/* -*- 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/. */
|
|
||||||
|
|
||||||
#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 SupportsWeakPtr<PresentationAvailability>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PresentationAvailability,
|
|
||||||
DOMEventTargetHelper)
|
|
||||||
NS_DECL_NSIPRESENTATIONAVAILABILITYLISTENER
|
|
||||||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(PresentationAvailability)
|
|
||||||
|
|
||||||
static already_AddRefed<PresentationAvailability>
|
|
||||||
Create(nsPIDOMWindowInner* aWindow,
|
|
||||||
const nsTArray<nsString>& aUrls,
|
|
||||||
RefPtr<Promise>& aPromise);
|
|
||||||
|
|
||||||
virtual void DisconnectFromOwner() override;
|
|
||||||
|
|
||||||
virtual JSObject* WrapObject(JSContext* aCx,
|
|
||||||
JS::Handle<JSObject*> aGivenProto) override;
|
|
||||||
|
|
||||||
bool Equals(const uint64_t aWindowID, const nsTArray<nsString>& aUrls) const;
|
|
||||||
|
|
||||||
bool IsCachedValueReady();
|
|
||||||
|
|
||||||
void EnqueuePromise(RefPtr<Promise>& aPromise);
|
|
||||||
|
|
||||||
// WebIDL (public APIs)
|
|
||||||
bool Value() const;
|
|
||||||
|
|
||||||
IMPL_EVENT_HANDLER(change);
|
|
||||||
|
|
||||||
private:
|
|
||||||
explicit PresentationAvailability(nsPIDOMWindowInner* aWindow,
|
|
||||||
const nsTArray<nsString>& aUrls);
|
|
||||||
|
|
||||||
virtual ~PresentationAvailability();
|
|
||||||
|
|
||||||
bool Init(RefPtr<Promise>& aPromise);
|
|
||||||
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
void UpdateAvailabilityAndDispatchEvent(bool aIsAvailable);
|
|
||||||
|
|
||||||
bool mIsAvailable;
|
|
||||||
|
|
||||||
nsTArray<RefPtr<Promise>> mPromises;
|
|
||||||
|
|
||||||
nsTArray<nsString> mUrls;
|
|
||||||
nsTArray<bool> mAvailabilityOfUrl;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationAvailability_h
|
|
|
@ -1,282 +0,0 @@
|
||||||
/* -*- 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 "mozilla/dom/Promise.h"
|
|
||||||
#include "nsIDocShell.h"
|
|
||||||
#include "nsIInterfaceRequestorUtils.h"
|
|
||||||
#include "nsIPresentationService.h"
|
|
||||||
#include "nsIWebProgress.h"
|
|
||||||
#include "nsServiceManagerUtils.h"
|
|
||||||
#include "nsThreadUtils.h"
|
|
||||||
#include "PresentationCallbacks.h"
|
|
||||||
#include "PresentationRequest.h"
|
|
||||||
#include "PresentationConnection.h"
|
|
||||||
#include "PresentationTransportBuilderConstructor.h"
|
|
||||||
|
|
||||||
using namespace mozilla;
|
|
||||||
using namespace mozilla::dom;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Implementation of PresentationRequesterCallback
|
|
||||||
*/
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(PresentationRequesterCallback, nsIPresentationServiceCallback)
|
|
||||||
|
|
||||||
PresentationRequesterCallback::PresentationRequesterCallback(PresentationRequest* aRequest,
|
|
||||||
const nsAString& aSessionId,
|
|
||||||
Promise* aPromise)
|
|
||||||
: mRequest(aRequest)
|
|
||||||
, mSessionId(aSessionId)
|
|
||||||
, mPromise(aPromise)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mRequest);
|
|
||||||
MOZ_ASSERT(mPromise);
|
|
||||||
MOZ_ASSERT(!mSessionId.IsEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationRequesterCallback::~PresentationRequesterCallback()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsIPresentationServiceCallback
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationRequesterCallback::NotifySuccess(const nsAString& aUrl)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (aUrl.IsEmpty()) {
|
|
||||||
return NotifyError(NS_ERROR_DOM_OPERATION_ERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<PresentationConnection> connection =
|
|
||||||
PresentationConnection::Create(mRequest->GetOwner(), mSessionId, aUrl,
|
|
||||||
nsIPresentationService::ROLE_CONTROLLER);
|
|
||||||
if (NS_WARN_IF(!connection)) {
|
|
||||||
return NotifyError(NS_ERROR_DOM_OPERATION_ERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
mRequest->NotifyPromiseSettled();
|
|
||||||
mPromise->MaybeResolve(connection);
|
|
||||||
|
|
||||||
return mRequest->DispatchConnectionAvailableEvent(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationRequesterCallback::NotifyError(nsresult aError)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
mRequest->NotifyPromiseSettled();
|
|
||||||
mPromise->MaybeReject(aError);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Implementation of PresentationRequesterCallback
|
|
||||||
*/
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_INHERITED0(PresentationReconnectCallback,
|
|
||||||
PresentationRequesterCallback)
|
|
||||||
|
|
||||||
PresentationReconnectCallback::PresentationReconnectCallback(
|
|
||||||
PresentationRequest* aRequest,
|
|
||||||
const nsAString& aSessionId,
|
|
||||||
Promise* aPromise,
|
|
||||||
PresentationConnection* aConnection)
|
|
||||||
: PresentationRequesterCallback(aRequest, aSessionId, aPromise)
|
|
||||||
, mConnection(aConnection)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationReconnectCallback::~PresentationReconnectCallback()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationReconnectCallback::NotifySuccess(const nsAString& aUrl)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!service)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
|
||||||
// We found a matched connection with the same window ID, URL, and
|
|
||||||
// the session ID. Resolve the promise with this connection and dispatch
|
|
||||||
// the event.
|
|
||||||
if (mConnection) {
|
|
||||||
mConnection->NotifyStateChange(
|
|
||||||
mSessionId,
|
|
||||||
nsIPresentationSessionListener::STATE_CONNECTING,
|
|
||||||
NS_OK);
|
|
||||||
mPromise->MaybeResolve(mConnection);
|
|
||||||
rv = mRequest->DispatchConnectionAvailableEvent(mConnection);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Use |PresentationRequesterCallback::NotifySuccess| to create a new
|
|
||||||
// connection since we don't find one that can be reused.
|
|
||||||
rv = PresentationRequesterCallback::NotifySuccess(aUrl);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = service->UpdateWindowIdBySessionId(mSessionId,
|
|
||||||
nsIPresentationService::ROLE_CONTROLLER,
|
|
||||||
mRequest->GetOwner()->WindowID());
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsString sessionId = nsString(mSessionId);
|
|
||||||
return NS_DispatchToMainThread(
|
|
||||||
NS_NewRunnableFunction([sessionId, service]() -> void {
|
|
||||||
service->BuildTransport(sessionId,
|
|
||||||
nsIPresentationService::ROLE_CONTROLLER);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationReconnectCallback::NotifyError(nsresult aError)
|
|
||||||
{
|
|
||||||
if (mConnection) {
|
|
||||||
mConnection->NotifyStateChange(
|
|
||||||
mSessionId,
|
|
||||||
nsIPresentationSessionListener::STATE_CLOSED,
|
|
||||||
aError);
|
|
||||||
}
|
|
||||||
return PresentationRequesterCallback::NotifyError(aError);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(PresentationResponderLoadingCallback,
|
|
||||||
nsIWebProgressListener,
|
|
||||||
nsISupportsWeakReference)
|
|
||||||
|
|
||||||
PresentationResponderLoadingCallback::PresentationResponderLoadingCallback(const nsAString& aSessionId)
|
|
||||||
: mSessionId(aSessionId)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationResponderLoadingCallback::~PresentationResponderLoadingCallback()
|
|
||||||
{
|
|
||||||
if (mProgress) {
|
|
||||||
mProgress->RemoveProgressListener(this);
|
|
||||||
mProgress = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationResponderLoadingCallback::Init(nsIDocShell* aDocShell)
|
|
||||||
{
|
|
||||||
mProgress = do_GetInterface(aDocShell);
|
|
||||||
if (NS_WARN_IF(!mProgress)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t busyFlags = nsIDocShell::BUSY_FLAGS_NONE;
|
|
||||||
nsresult rv = aDocShell->GetBusyFlags(&busyFlags);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((busyFlags == nsIDocShell::BUSY_FLAGS_NONE) ||
|
|
||||||
(busyFlags & nsIDocShell::BUSY_FLAGS_PAGE_LOADING)) {
|
|
||||||
// The docshell has finished loading or is receiving data (|STATE_TRANSFERRING|
|
|
||||||
// has already been fired), so the page is ready for presentation use.
|
|
||||||
return NotifyReceiverReady(/* isLoading = */ true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start to listen to document state change event |STATE_TRANSFERRING|.
|
|
||||||
return mProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_DOCUMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationResponderLoadingCallback::NotifyReceiverReady(bool aIsLoading)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(mProgress);
|
|
||||||
if (NS_WARN_IF(!window || !window->GetCurrentInnerWindow())) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
uint64_t windowId = window->GetCurrentInnerWindow()->WindowID();
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!service)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationTransportBuilderConstructor> constructor =
|
|
||||||
PresentationTransportBuilderConstructor::Create();
|
|
||||||
return service->NotifyReceiverReady(mSessionId,
|
|
||||||
windowId,aIsLoading,
|
|
||||||
constructor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsIWebProgressListener
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationResponderLoadingCallback::OnStateChange(nsIWebProgress* aWebProgress,
|
|
||||||
nsIRequest* aRequest,
|
|
||||||
uint32_t aStateFlags,
|
|
||||||
nsresult aStatus)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (aStateFlags & (nsIWebProgressListener::STATE_TRANSFERRING |
|
|
||||||
nsIWebProgressListener::STATE_STOP)) {
|
|
||||||
mProgress->RemoveProgressListener(this);
|
|
||||||
|
|
||||||
bool isLoading = aStateFlags & nsIWebProgressListener::STATE_TRANSFERRING;
|
|
||||||
return NotifyReceiverReady(isLoading);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationResponderLoadingCallback::OnProgressChange(nsIWebProgress* aWebProgress,
|
|
||||||
nsIRequest* aRequest,
|
|
||||||
int32_t aCurSelfProgress,
|
|
||||||
int32_t aMaxSelfProgress,
|
|
||||||
int32_t aCurTotalProgress,
|
|
||||||
int32_t aMaxTotalProgress)
|
|
||||||
{
|
|
||||||
// Do nothing.
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationResponderLoadingCallback::OnLocationChange(nsIWebProgress* aWebProgress,
|
|
||||||
nsIRequest* aRequest,
|
|
||||||
nsIURI* aURI,
|
|
||||||
uint32_t aFlags)
|
|
||||||
{
|
|
||||||
// Do nothing.
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationResponderLoadingCallback::OnStatusChange(nsIWebProgress* aWebProgress,
|
|
||||||
nsIRequest* aRequest,
|
|
||||||
nsresult aStatus,
|
|
||||||
const char16_t* aMessage)
|
|
||||||
{
|
|
||||||
// Do nothing.
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationResponderLoadingCallback::OnSecurityChange(nsIWebProgress* aWebProgress,
|
|
||||||
nsIRequest* aRequest,
|
|
||||||
uint32_t state)
|
|
||||||
{
|
|
||||||
// Do nothing.
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
|
@ -1,85 +0,0 @@
|
||||||
/* -*- 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationCallbacks_h
|
|
||||||
#define mozilla_dom_PresentationCallbacks_h
|
|
||||||
|
|
||||||
#include "mozilla/RefPtr.h"
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsIPresentationService.h"
|
|
||||||
#include "nsIWebProgressListener.h"
|
|
||||||
#include "nsString.h"
|
|
||||||
#include "nsWeakReference.h"
|
|
||||||
|
|
||||||
class nsIDocShell;
|
|
||||||
class nsIWebProgress;
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class PresentationConnection;
|
|
||||||
class PresentationRequest;
|
|
||||||
class Promise;
|
|
||||||
|
|
||||||
class PresentationRequesterCallback : public nsIPresentationServiceCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIPRESENTATIONSERVICECALLBACK
|
|
||||||
|
|
||||||
PresentationRequesterCallback(PresentationRequest* aRequest,
|
|
||||||
const nsAString& aSessionId,
|
|
||||||
Promise* aPromise);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual ~PresentationRequesterCallback();
|
|
||||||
|
|
||||||
RefPtr<PresentationRequest> mRequest;
|
|
||||||
nsString mSessionId;
|
|
||||||
RefPtr<Promise> mPromise;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PresentationReconnectCallback final : public PresentationRequesterCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
NS_DECL_NSIPRESENTATIONSERVICECALLBACK
|
|
||||||
|
|
||||||
PresentationReconnectCallback(PresentationRequest* aRequest,
|
|
||||||
const nsAString& aSessionId,
|
|
||||||
Promise* aPromise,
|
|
||||||
PresentationConnection* aConnection);
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~PresentationReconnectCallback();
|
|
||||||
|
|
||||||
RefPtr<PresentationConnection> mConnection;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PresentationResponderLoadingCallback final : public nsIWebProgressListener
|
|
||||||
, public nsSupportsWeakReference
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIWEBPROGRESSLISTENER
|
|
||||||
|
|
||||||
explicit PresentationResponderLoadingCallback(const nsAString& aSessionId);
|
|
||||||
|
|
||||||
nsresult Init(nsIDocShell* aDocShell);
|
|
||||||
|
|
||||||
private:
|
|
||||||
~PresentationResponderLoadingCallback();
|
|
||||||
|
|
||||||
nsresult NotifyReceiverReady(bool aIsLoading);
|
|
||||||
|
|
||||||
nsString mSessionId;
|
|
||||||
nsCOMPtr<nsIWebProgress> mProgress;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationCallbacks_h
|
|
|
@ -1,763 +0,0 @@
|
||||||
/* -*- 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 "PresentationConnection.h"
|
|
||||||
|
|
||||||
#include "ControllerConnectionCollection.h"
|
|
||||||
#include "mozilla/AsyncEventDispatcher.h"
|
|
||||||
#include "mozilla/dom/DOMException.h"
|
|
||||||
#include "mozilla/dom/File.h"
|
|
||||||
#include "mozilla/dom/MessageEvent.h"
|
|
||||||
#include "mozilla/dom/MessageEventBinding.h"
|
|
||||||
#include "mozilla/dom/PresentationConnectionCloseEvent.h"
|
|
||||||
#include "mozilla/ErrorNames.h"
|
|
||||||
#include "mozilla/DebugOnly.h"
|
|
||||||
#include "nsContentUtils.h"
|
|
||||||
#include "nsCycleCollectionParticipant.h"
|
|
||||||
#include "nsIPresentationService.h"
|
|
||||||
#include "nsServiceManagerUtils.h"
|
|
||||||
#include "nsStringStream.h"
|
|
||||||
#include "PresentationConnectionList.h"
|
|
||||||
#include "PresentationLog.h"
|
|
||||||
|
|
||||||
using namespace mozilla;
|
|
||||||
using namespace mozilla::dom;
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(PresentationConnection)
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PresentationConnection, DOMEventTargetHelper)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwningConnectionList)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PresentationConnection, DOMEventTargetHelper)
|
|
||||||
tmp->Shutdown();
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwningConnectionList)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
||||||
|
|
||||||
NS_IMPL_ADDREF_INHERITED(PresentationConnection, DOMEventTargetHelper)
|
|
||||||
NS_IMPL_RELEASE_INHERITED(PresentationConnection, DOMEventTargetHelper)
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PresentationConnection)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIPresentationSessionListener)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIRequest)
|
|
||||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
|
||||||
|
|
||||||
PresentationConnection::PresentationConnection(nsPIDOMWindowInner* aWindow,
|
|
||||||
const nsAString& aId,
|
|
||||||
const nsAString& aUrl,
|
|
||||||
const uint8_t aRole,
|
|
||||||
PresentationConnectionList* aList)
|
|
||||||
: DOMEventTargetHelper(aWindow)
|
|
||||||
, mId(aId)
|
|
||||||
, mUrl(aUrl)
|
|
||||||
, mState(PresentationConnectionState::Connecting)
|
|
||||||
, mOwningConnectionList(aList)
|
|
||||||
, mBinaryType(PresentationConnectionBinaryType::Arraybuffer)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
|
|
||||||
aRole == nsIPresentationService::ROLE_RECEIVER);
|
|
||||||
mRole = aRole;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual */ PresentationConnection::~PresentationConnection()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */ already_AddRefed<PresentationConnection>
|
|
||||||
PresentationConnection::Create(nsPIDOMWindowInner* aWindow,
|
|
||||||
const nsAString& aId,
|
|
||||||
const nsAString& aUrl,
|
|
||||||
const uint8_t aRole,
|
|
||||||
PresentationConnectionList* aList)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
|
|
||||||
aRole == nsIPresentationService::ROLE_RECEIVER);
|
|
||||||
RefPtr<PresentationConnection> connection =
|
|
||||||
new PresentationConnection(aWindow, aId, aUrl, aRole, aList);
|
|
||||||
if (NS_WARN_IF(!connection->Init())) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aRole == nsIPresentationService::ROLE_CONTROLLER) {
|
|
||||||
ControllerConnectionCollection::GetSingleton()->AddConnection(connection,
|
|
||||||
aRole);
|
|
||||||
}
|
|
||||||
|
|
||||||
return connection.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationConnection::Init()
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(mId.IsEmpty())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
if(NS_WARN_IF(!service)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv = service->RegisterSessionListener(mId, mRole, this);
|
|
||||||
if(NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = AddIntoLoadGroup();
|
|
||||||
if(NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationConnection::Shutdown()
|
|
||||||
{
|
|
||||||
PRES_DEBUG("connection shutdown:id[%s], role[%d]\n",
|
|
||||||
NS_ConvertUTF16toUTF8(mId).get(), mRole);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!service)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DebugOnly<nsresult> rv = service->UnregisterSessionListener(mId, mRole);
|
|
||||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "UnregisterSessionListener failed");
|
|
||||||
|
|
||||||
DebugOnly<nsresult> rv2 = RemoveFromLoadGroup();
|
|
||||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv2), "RemoveFromLoadGroup failed");
|
|
||||||
|
|
||||||
if (mRole == nsIPresentationService::ROLE_CONTROLLER) {
|
|
||||||
ControllerConnectionCollection::GetSingleton()->RemoveConnection(this,
|
|
||||||
mRole);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual */ void
|
|
||||||
PresentationConnection::DisconnectFromOwner()
|
|
||||||
{
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(ProcessConnectionWentAway()));
|
|
||||||
DOMEventTargetHelper::DisconnectFromOwner();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual */ JSObject*
|
|
||||||
PresentationConnection::WrapObject(JSContext* aCx,
|
|
||||||
JS::Handle<JSObject*> aGivenProto)
|
|
||||||
{
|
|
||||||
return PresentationConnectionBinding::Wrap(aCx, this, aGivenProto);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationConnection::GetId(nsAString& aId) const
|
|
||||||
{
|
|
||||||
aId = mId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationConnection::GetUrl(nsAString& aUrl) const
|
|
||||||
{
|
|
||||||
aUrl = mUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationConnectionState
|
|
||||||
PresentationConnection::State() const
|
|
||||||
{
|
|
||||||
return mState;
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationConnectionBinaryType
|
|
||||||
PresentationConnection::BinaryType() const
|
|
||||||
{
|
|
||||||
return mBinaryType;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationConnection::SetBinaryType(PresentationConnectionBinaryType aType)
|
|
||||||
{
|
|
||||||
mBinaryType = aType;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationConnection::Send(const nsAString& aData,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
if(NS_WARN_IF(!service)) {
|
|
||||||
AsyncCloseConnectionWithErrorMsg(
|
|
||||||
NS_LITERAL_STRING("Unable to send message due to an internal error."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv = service->SendSessionMessage(mId, mRole, aData);
|
|
||||||
if(NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
const uint32_t kMaxMessageLength = 256;
|
|
||||||
nsAutoString data(Substring(aData, 0, kMaxMessageLength));
|
|
||||||
|
|
||||||
AsyncCloseConnectionWithErrorMsg(
|
|
||||||
NS_LITERAL_STRING("Unable to send message: \"") + data +
|
|
||||||
NS_LITERAL_STRING("\""));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationConnection::Send(Blob& aData,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
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)) {
|
|
||||||
AsyncCloseConnectionWithErrorMsg(
|
|
||||||
NS_LITERAL_STRING("Unable to send message due to an internal error."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv = service->SendSessionBlob(mId, mRole, &aData);
|
|
||||||
if(NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
AsyncCloseConnectionWithErrorMsg(
|
|
||||||
NS_LITERAL_STRING("Unable to send binary message for Blob message."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationConnection::Send(const ArrayBuffer& aData,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
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)) {
|
|
||||||
AsyncCloseConnectionWithErrorMsg(
|
|
||||||
NS_LITERAL_STRING("Unable to send message due to an internal error."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
aData.ComputeLengthAndData();
|
|
||||||
|
|
||||||
static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
|
|
||||||
|
|
||||||
uint32_t length = aData.Length();
|
|
||||||
char* data = reinterpret_cast<char*>(aData.Data());
|
|
||||||
nsDependentCSubstring msgString(data, length);
|
|
||||||
|
|
||||||
nsresult rv = service->SendSessionBinaryMsg(mId, mRole, msgString);
|
|
||||||
if(NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
AsyncCloseConnectionWithErrorMsg(
|
|
||||||
NS_LITERAL_STRING("Unable to send binary message for ArrayBuffer message."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationConnection::Send(const ArrayBufferView& aData,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
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)) {
|
|
||||||
AsyncCloseConnectionWithErrorMsg(
|
|
||||||
NS_LITERAL_STRING("Unable to send message due to an internal error."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
aData.ComputeLengthAndData();
|
|
||||||
|
|
||||||
static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
|
|
||||||
|
|
||||||
uint32_t length = aData.Length();
|
|
||||||
char* data = reinterpret_cast<char*>(aData.Data());
|
|
||||||
nsDependentCSubstring msgString(data, length);
|
|
||||||
|
|
||||||
nsresult rv = service->SendSessionBinaryMsg(mId, mRole, msgString);
|
|
||||||
if(NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
AsyncCloseConnectionWithErrorMsg(
|
|
||||||
NS_LITERAL_STRING("Unable to send binary message for ArrayBufferView message."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationConnection::Close(ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
if(NS_WARN_IF(!service)) {
|
|
||||||
aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(
|
|
||||||
service->CloseSession(mId,
|
|
||||||
mRole,
|
|
||||||
nsIPresentationService::CLOSED_REASON_CLOSED)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationConnection::Terminate(ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
// 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)) {
|
|
||||||
aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(service->TerminateSession(mId, mRole)));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationConnection::Equals(uint64_t aWindowId,
|
|
||||||
const nsAString& aId)
|
|
||||||
{
|
|
||||||
return GetOwner() &&
|
|
||||||
aWindowId == GetOwner()->WindowID() &&
|
|
||||||
mId.Equals(aId);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationConnection::NotifyStateChange(const nsAString& aSessionId,
|
|
||||||
uint16_t aState,
|
|
||||||
nsresult aReason)
|
|
||||||
{
|
|
||||||
PRES_DEBUG("connection state change:id[%s], state[%x], reason[%x], role[%d]\n",
|
|
||||||
NS_ConvertUTF16toUTF8(aSessionId).get(), aState,
|
|
||||||
aReason, mRole);
|
|
||||||
|
|
||||||
if (!aSessionId.Equals(mId)) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A terminated connection should always remain in terminated.
|
|
||||||
if (mState == PresentationConnectionState::Terminated) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationConnectionState state;
|
|
||||||
switch (aState) {
|
|
||||||
case nsIPresentationSessionListener::STATE_CONNECTING:
|
|
||||||
state = PresentationConnectionState::Connecting;
|
|
||||||
break;
|
|
||||||
case nsIPresentationSessionListener::STATE_CONNECTED:
|
|
||||||
state = PresentationConnectionState::Connected;
|
|
||||||
break;
|
|
||||||
case nsIPresentationSessionListener::STATE_CLOSED:
|
|
||||||
state = PresentationConnectionState::Closed;
|
|
||||||
break;
|
|
||||||
case nsIPresentationSessionListener::STATE_TERMINATED:
|
|
||||||
state = PresentationConnectionState::Terminated;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
NS_WARNING("Unknown presentation session state.");
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mState == state) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
mState = state;
|
|
||||||
|
|
||||||
nsresult rv = ProcessStateChanged(aReason);
|
|
||||||
if(NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mOwningConnectionList) {
|
|
||||||
mOwningConnectionList->NotifyStateChange(aSessionId, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationConnection::ProcessStateChanged(nsresult aReason)
|
|
||||||
{
|
|
||||||
switch (mState) {
|
|
||||||
case PresentationConnectionState::Connecting:
|
|
||||||
return NS_OK;
|
|
||||||
case PresentationConnectionState::Connected: {
|
|
||||||
RefPtr<AsyncEventDispatcher> asyncDispatcher =
|
|
||||||
new AsyncEventDispatcher(this, NS_LITERAL_STRING("connect"), false);
|
|
||||||
return asyncDispatcher->PostDOMEvent();
|
|
||||||
}
|
|
||||||
case PresentationConnectionState::Closed: {
|
|
||||||
PresentationConnectionClosedReason reason =
|
|
||||||
PresentationConnectionClosedReason::Closed;
|
|
||||||
|
|
||||||
nsString errorMsg;
|
|
||||||
if (NS_FAILED(aReason)) {
|
|
||||||
reason = PresentationConnectionClosedReason::Error;
|
|
||||||
nsCString name, message;
|
|
||||||
|
|
||||||
// If aReason is not a DOM error, use error name as message.
|
|
||||||
if (NS_FAILED(NS_GetNameAndMessageForDOMNSResult(aReason,
|
|
||||||
name,
|
|
||||||
message))) {
|
|
||||||
mozilla::GetErrorName(aReason, message);
|
|
||||||
message.InsertLiteral("Internal error: ", 0);
|
|
||||||
}
|
|
||||||
CopyUTF8toUTF16(message, errorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
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()));
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!service)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv = service->UnregisterSessionListener(mId, mRole);
|
|
||||||
if(NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
return RemoveFromLoadGroup();
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
MOZ_CRASH("Unknown presentation session state.");
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationConnection::NotifyMessage(const nsAString& aSessionId,
|
|
||||||
const nsACString& aData,
|
|
||||||
bool aIsBinary)
|
|
||||||
{
|
|
||||||
PRES_DEBUG("connection %s:id[%s], data[%s], role[%d]\n", __func__,
|
|
||||||
NS_ConvertUTF16toUTF8(aSessionId).get(),
|
|
||||||
nsPromiseFlatCString(aData).get(), mRole);
|
|
||||||
|
|
||||||
if (!aSessionId.Equals(mId)) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No message should be expected when the session is not connected.
|
|
||||||
if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
|
|
||||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_WARN_IF(NS_FAILED(DoReceiveMessage(aData, aIsBinary)))) {
|
|
||||||
AsyncCloseConnectionWithErrorMsg(
|
|
||||||
NS_LITERAL_STRING("Unable to receive a message."));
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationConnection::DoReceiveMessage(const nsACString& aData, bool aIsBinary)
|
|
||||||
{
|
|
||||||
// Transform the data.
|
|
||||||
AutoJSAPI jsapi;
|
|
||||||
if (!jsapi.Init(GetOwner())) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
JSContext* cx = jsapi.cx();
|
|
||||||
JS::Rooted<JS::Value> jsData(cx);
|
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
if (aIsBinary) {
|
|
||||||
if (mBinaryType == PresentationConnectionBinaryType::Blob) {
|
|
||||||
RefPtr<Blob> blob =
|
|
||||||
Blob::CreateStringBlob(GetOwner(), aData, EmptyString());
|
|
||||||
MOZ_ASSERT(blob);
|
|
||||||
|
|
||||||
if (!ToJSValue(cx, blob, &jsData)) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
} else if (mBinaryType == PresentationConnectionBinaryType::Arraybuffer) {
|
|
||||||
JS::Rooted<JSObject*> arrayBuf(cx);
|
|
||||||
rv = nsContentUtils::CreateArrayBuffer(cx, aData, arrayBuf.address());
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
jsData.setObject(*arrayBuf);
|
|
||||||
} else {
|
|
||||||
NS_RUNTIMEABORT("Unknown binary type!");
|
|
||||||
return NS_ERROR_UNEXPECTED;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
NS_ConvertUTF8toUTF16 utf16Data(aData);
|
|
||||||
if(NS_WARN_IF(!ToJSValue(cx, utf16Data, &jsData))) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return DispatchMessageEvent(jsData);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationConnection::DispatchConnectionCloseEvent(
|
|
||||||
PresentationConnectionClosedReason aReason,
|
|
||||||
const nsAString& aMessage,
|
|
||||||
bool aDispatchNow)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
RefPtr<PresentationConnectionCloseEvent> closedEvent =
|
|
||||||
PresentationConnectionCloseEvent::Constructor(this,
|
|
||||||
NS_LITERAL_STRING("close"),
|
|
||||||
init);
|
|
||||||
closedEvent->SetTrusted(true);
|
|
||||||
|
|
||||||
if (aDispatchNow) {
|
|
||||||
bool ignore;
|
|
||||||
return DOMEventTargetHelper::DispatchEvent(closedEvent, &ignore);
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<AsyncEventDispatcher> asyncDispatcher =
|
|
||||||
new AsyncEventDispatcher(this, static_cast<Event*>(closedEvent));
|
|
||||||
return asyncDispatcher->PostDOMEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationConnection::DispatchMessageEvent(JS::Handle<JS::Value> aData)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
|
|
||||||
if (NS_WARN_IF(!global)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the origin.
|
|
||||||
nsAutoString origin;
|
|
||||||
nsresult rv = nsContentUtils::GetUTFOrigin(global->PrincipalOrNull(), origin);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<MessageEvent> messageEvent = new MessageEvent(this, nullptr, nullptr);
|
|
||||||
|
|
||||||
messageEvent->InitMessageEvent(nullptr,
|
|
||||||
NS_LITERAL_STRING("message"),
|
|
||||||
false, false, aData, origin,
|
|
||||||
EmptyString(), nullptr,
|
|
||||||
Sequence<OwningNonNull<MessagePort>>());
|
|
||||||
messageEvent->SetTrusted(true);
|
|
||||||
|
|
||||||
RefPtr<AsyncEventDispatcher> asyncDispatcher =
|
|
||||||
new AsyncEventDispatcher(this, static_cast<Event*>(messageEvent));
|
|
||||||
return asyncDispatcher->PostDOMEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationConnection::ProcessConnectionWentAway()
|
|
||||||
{
|
|
||||||
if (mState != PresentationConnectionState::Connected &&
|
|
||||||
mState != PresentationConnectionState::Connecting) {
|
|
||||||
// If the state is not connected or connecting, do not need to
|
|
||||||
// close the session.
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
mState = PresentationConnectionState::Terminated;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!service)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return service->CloseSession(
|
|
||||||
mId, mRole, nsIPresentationService::CLOSED_REASON_WENTAWAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationConnection::GetName(nsACString &aResult)
|
|
||||||
{
|
|
||||||
aResult.AssignLiteral("about:presentation-connection");
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationConnection::IsPending(bool* aRetval)
|
|
||||||
{
|
|
||||||
*aRetval = true;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationConnection::GetStatus(nsresult* aStatus)
|
|
||||||
{
|
|
||||||
*aStatus = NS_OK;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationConnection::Cancel(nsresult aStatus)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIRunnable> event =
|
|
||||||
NewRunnableMethod(this, &PresentationConnection::ProcessConnectionWentAway);
|
|
||||||
return NS_DispatchToCurrentThread(event);
|
|
||||||
}
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationConnection::Suspend(void)
|
|
||||||
{
|
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationConnection::Resume(void)
|
|
||||||
{
|
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationConnection::GetLoadGroup(nsILoadGroup** aLoadGroup)
|
|
||||||
{
|
|
||||||
*aLoadGroup = nullptr;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDocument> doc = GetOwner() ? GetOwner()->GetExtantDoc() : nullptr;
|
|
||||||
if (!doc) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*aLoadGroup = doc->GetDocumentLoadGroup().take();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationConnection::SetLoadGroup(nsILoadGroup * aLoadGroup)
|
|
||||||
{
|
|
||||||
return NS_ERROR_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationConnection::GetLoadFlags(nsLoadFlags* aLoadFlags)
|
|
||||||
{
|
|
||||||
*aLoadFlags = nsIRequest::LOAD_BACKGROUND;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationConnection::SetLoadFlags(nsLoadFlags aLoadFlags)
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationConnection::AddIntoLoadGroup()
|
|
||||||
{
|
|
||||||
// Avoid adding to loadgroup multiple times
|
|
||||||
if (mWeakLoadGroup) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
|
||||||
nsresult rv = GetLoadGroup(getter_AddRefs(loadGroup));
|
|
||||||
if(NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = loadGroup->AddRequest(this, nullptr);
|
|
||||||
if(NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
mWeakLoadGroup = do_GetWeakReference(loadGroup);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationConnection::RemoveFromLoadGroup()
|
|
||||||
{
|
|
||||||
if (!mWeakLoadGroup) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsILoadGroup> loadGroup = do_QueryReferent(mWeakLoadGroup);
|
|
||||||
if (loadGroup) {
|
|
||||||
mWeakLoadGroup = nullptr;
|
|
||||||
return loadGroup->RemoveRequest(this, nullptr, NS_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationConnection::AsyncCloseConnectionWithErrorMsg(const nsAString& aMessage)
|
|
||||||
{
|
|
||||||
if (mState == PresentationConnectionState::Terminated) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsString message = nsString(aMessage);
|
|
||||||
RefPtr<PresentationConnection> self = this;
|
|
||||||
nsCOMPtr<nsIRunnable> r =
|
|
||||||
NS_NewRunnableFunction([self, message]() -> void {
|
|
||||||
// Set |mState| to |PresentationConnectionState::Closed| here to avoid
|
|
||||||
// calling |ProcessStateChanged|.
|
|
||||||
self->mState = PresentationConnectionState::Closed;
|
|
||||||
|
|
||||||
// Make sure dispatching the event and closing the connection are invoked
|
|
||||||
// at the same time by setting |aDispatchNow| to true.
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(
|
|
||||||
self->DispatchConnectionCloseEvent(PresentationConnectionClosedReason::Error,
|
|
||||||
message,
|
|
||||||
true)));
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
if(NS_WARN_IF(!service)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(
|
|
||||||
service->CloseSession(self->mId,
|
|
||||||
self->mRole,
|
|
||||||
nsIPresentationService::CLOSED_REASON_ERROR)));
|
|
||||||
});
|
|
||||||
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(r)));
|
|
||||||
}
|
|
|
@ -1,128 +0,0 @@
|
||||||
/* -*- 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationConnection_h
|
|
||||||
#define mozilla_dom_PresentationConnection_h
|
|
||||||
|
|
||||||
#include "mozilla/DOMEventTargetHelper.h"
|
|
||||||
#include "mozilla/dom/TypedArray.h"
|
|
||||||
#include "mozilla/WeakPtr.h"
|
|
||||||
#include "mozilla/dom/PresentationConnectionBinding.h"
|
|
||||||
#include "mozilla/dom/PresentationConnectionCloseEventBinding.h"
|
|
||||||
#include "nsIPresentationListener.h"
|
|
||||||
#include "nsIRequest.h"
|
|
||||||
#include "nsWeakReference.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class Blob;
|
|
||||||
class PresentationConnectionList;
|
|
||||||
|
|
||||||
class PresentationConnection final : public DOMEventTargetHelper
|
|
||||||
, public nsIPresentationSessionListener
|
|
||||||
, public nsIRequest
|
|
||||||
, public SupportsWeakPtr<PresentationConnection>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PresentationConnection,
|
|
||||||
DOMEventTargetHelper)
|
|
||||||
NS_DECL_NSIPRESENTATIONSESSIONLISTENER
|
|
||||||
NS_DECL_NSIREQUEST
|
|
||||||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(PresentationConnection)
|
|
||||||
|
|
||||||
static already_AddRefed<PresentationConnection>
|
|
||||||
Create(nsPIDOMWindowInner* aWindow,
|
|
||||||
const nsAString& aId,
|
|
||||||
const nsAString& aUrl,
|
|
||||||
const uint8_t aRole,
|
|
||||||
PresentationConnectionList* aList = nullptr);
|
|
||||||
|
|
||||||
virtual void DisconnectFromOwner() override;
|
|
||||||
|
|
||||||
virtual JSObject* WrapObject(JSContext* aCx,
|
|
||||||
JS::Handle<JSObject*> aGivenProto) override;
|
|
||||||
|
|
||||||
// WebIDL (public APIs)
|
|
||||||
void GetId(nsAString& aId) const;
|
|
||||||
|
|
||||||
void GetUrl(nsAString& aUrl) const;
|
|
||||||
|
|
||||||
PresentationConnectionState State() const;
|
|
||||||
|
|
||||||
PresentationConnectionBinaryType BinaryType() const;
|
|
||||||
|
|
||||||
void SetBinaryType(PresentationConnectionBinaryType aType);
|
|
||||||
|
|
||||||
void Send(const nsAString& aData,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
|
|
||||||
void Send(Blob& aData,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
|
|
||||||
void Send(const ArrayBuffer& aData,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
|
|
||||||
void Send(const ArrayBufferView& aData,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
|
|
||||||
void Close(ErrorResult& aRv);
|
|
||||||
|
|
||||||
void Terminate(ErrorResult& aRv);
|
|
||||||
|
|
||||||
bool
|
|
||||||
Equals(uint64_t aWindowId, const nsAString& aId);
|
|
||||||
|
|
||||||
IMPL_EVENT_HANDLER(connect);
|
|
||||||
IMPL_EVENT_HANDLER(close);
|
|
||||||
IMPL_EVENT_HANDLER(terminate);
|
|
||||||
IMPL_EVENT_HANDLER(message);
|
|
||||||
|
|
||||||
private:
|
|
||||||
PresentationConnection(nsPIDOMWindowInner* aWindow,
|
|
||||||
const nsAString& aId,
|
|
||||||
const nsAString& aUrl,
|
|
||||||
const uint8_t aRole,
|
|
||||||
PresentationConnectionList* aList);
|
|
||||||
|
|
||||||
~PresentationConnection();
|
|
||||||
|
|
||||||
bool Init();
|
|
||||||
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
nsresult ProcessStateChanged(nsresult aReason);
|
|
||||||
|
|
||||||
nsresult DispatchConnectionCloseEvent(PresentationConnectionClosedReason aReason,
|
|
||||||
const nsAString& aMessage,
|
|
||||||
bool aDispatchNow = false);
|
|
||||||
|
|
||||||
nsresult DispatchMessageEvent(JS::Handle<JS::Value> aData);
|
|
||||||
|
|
||||||
nsresult ProcessConnectionWentAway();
|
|
||||||
|
|
||||||
nsresult AddIntoLoadGroup();
|
|
||||||
|
|
||||||
nsresult RemoveFromLoadGroup();
|
|
||||||
|
|
||||||
void AsyncCloseConnectionWithErrorMsg(const nsAString& aMessage);
|
|
||||||
|
|
||||||
nsresult DoReceiveMessage(const nsACString& aData, bool aIsBinary);
|
|
||||||
|
|
||||||
nsString mId;
|
|
||||||
nsString mUrl;
|
|
||||||
uint8_t mRole;
|
|
||||||
PresentationConnectionState mState;
|
|
||||||
RefPtr<PresentationConnectionList> mOwningConnectionList;
|
|
||||||
nsWeakPtr mWeakLoadGroup;
|
|
||||||
PresentationConnectionBinaryType mBinaryType;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationConnection_h
|
|
|
@ -1,125 +0,0 @@
|
||||||
/* -*- 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 "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 {
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(PresentationConnectionList, DOMEventTargetHelper,
|
|
||||||
mGetConnectionListPromise,
|
|
||||||
mConnections)
|
|
||||||
|
|
||||||
NS_IMPL_ADDREF_INHERITED(PresentationConnectionList, DOMEventTargetHelper)
|
|
||||||
NS_IMPL_RELEASE_INHERITED(PresentationConnectionList, DOMEventTargetHelper)
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PresentationConnectionList)
|
|
||||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
|
||||||
|
|
||||||
PresentationConnectionList::PresentationConnectionList(nsPIDOMWindowInner* aWindow,
|
|
||||||
Promise* aPromise)
|
|
||||||
: DOMEventTargetHelper(aWindow)
|
|
||||||
, mGetConnectionListPromise(aPromise)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aWindow);
|
|
||||||
MOZ_ASSERT(aPromise);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual */ JSObject*
|
|
||||||
PresentationConnectionList::WrapObject(JSContext* aCx,
|
|
||||||
JS::Handle<JSObject*> aGivenProto)
|
|
||||||
{
|
|
||||||
return PresentationConnectionListBinding::Wrap(aCx, this, aGivenProto);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationConnectionList::GetConnections(
|
|
||||||
nsTArray<RefPtr<PresentationConnection>>& aConnections) const
|
|
||||||
{
|
|
||||||
aConnections = mConnections;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationConnectionList::DispatchConnectionAvailableEvent(
|
|
||||||
PresentationConnection* aConnection)
|
|
||||||
{
|
|
||||||
PresentationConnectionAvailableEventInit init;
|
|
||||||
init.mConnection = aConnection;
|
|
||||||
|
|
||||||
RefPtr<PresentationConnectionAvailableEvent> event =
|
|
||||||
PresentationConnectionAvailableEvent::Constructor(
|
|
||||||
this,
|
|
||||||
NS_LITERAL_STRING("connectionavailable"),
|
|
||||||
init);
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!event)) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
event->SetTrusted(true);
|
|
||||||
|
|
||||||
RefPtr<AsyncEventDispatcher> asyncDispatcher =
|
|
||||||
new AsyncEventDispatcher(this, event);
|
|
||||||
return asyncDispatcher->PostDOMEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationConnectionList::ConnectionArrayIndex
|
|
||||||
PresentationConnectionList::FindConnectionById(
|
|
||||||
const nsAString& aId)
|
|
||||||
{
|
|
||||||
for (ConnectionArrayIndex i = 0; i < mConnections.Length(); i++) {
|
|
||||||
nsAutoString id;
|
|
||||||
mConnections[i]->GetId(id);
|
|
||||||
if (id == nsAutoString(aId)) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mConnections.NoIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationConnectionList::NotifyStateChange(const nsAString& aSessionId,
|
|
||||||
PresentationConnection* aConnection)
|
|
||||||
{
|
|
||||||
if (!aConnection) {
|
|
||||||
MOZ_ASSERT(false, "PresentationConnection can not be null.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool connectionFound =
|
|
||||||
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);
|
|
||||||
mGetConnectionListPromise = nullptr;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DispatchConnectionAvailableEvent(aConnection);
|
|
||||||
break;
|
|
||||||
case PresentationConnectionState::Terminated:
|
|
||||||
if (connectionFound) {
|
|
||||||
mConnections.RemoveElement(aConnection);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,57 +0,0 @@
|
||||||
/* -*- 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationConnectionList_h
|
|
||||||
#define mozilla_dom_PresentationConnectionList_h
|
|
||||||
|
|
||||||
#include "mozilla/DOMEventTargetHelper.h"
|
|
||||||
#include "nsTArray.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class PresentationConnection;
|
|
||||||
class Promise;
|
|
||||||
|
|
||||||
class PresentationConnectionList final : public DOMEventTargetHelper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PresentationConnectionList,
|
|
||||||
DOMEventTargetHelper)
|
|
||||||
|
|
||||||
PresentationConnectionList(nsPIDOMWindowInner* aWindow,
|
|
||||||
Promise* aPromise);
|
|
||||||
|
|
||||||
virtual JSObject* WrapObject(JSContext* aCx,
|
|
||||||
JS::Handle<JSObject*> aGivenProto) override;
|
|
||||||
|
|
||||||
void GetConnections(nsTArray<RefPtr<PresentationConnection>>& aConnections) const;
|
|
||||||
|
|
||||||
void NotifyStateChange(const nsAString& aSessionId, PresentationConnection* aConnection);
|
|
||||||
|
|
||||||
IMPL_EVENT_HANDLER(connectionavailable);
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~PresentationConnectionList() = default;
|
|
||||||
|
|
||||||
nsresult DispatchConnectionAvailableEvent(PresentationConnection* aConnection);
|
|
||||||
|
|
||||||
typedef nsTArray<RefPtr<PresentationConnection>> ConnectionArray;
|
|
||||||
typedef ConnectionArray::index_type ConnectionArrayIndex;
|
|
||||||
|
|
||||||
ConnectionArrayIndex FindConnectionById(const nsAString& aId);
|
|
||||||
|
|
||||||
RefPtr<Promise> mGetConnectionListPromise;
|
|
||||||
|
|
||||||
// This array stores only non-terminsted connections.
|
|
||||||
ConnectionArray mConnections;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationConnectionList_h
|
|
|
@ -1,378 +0,0 @@
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
|
||||||
|
|
||||||
// Bug 1228209 - plan to remove this eventually
|
|
||||||
function log(aMsg) {
|
|
||||||
//dump("-*- PresentationDataChannelSessionTransport.js : " + aMsg + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
const PRESENTATIONTRANSPORT_CID = Components.ID("{dd2bbf2f-3399-4389-8f5f-d382afb8b2d6}");
|
|
||||||
const PRESENTATIONTRANSPORT_CONTRACTID = "mozilla.org/presentation/datachanneltransport;1";
|
|
||||||
|
|
||||||
const PRESENTATIONTRANSPORTBUILDER_CID = Components.ID("{215b2f62-46e2-4004-a3d1-6858e56c20f3}");
|
|
||||||
const PRESENTATIONTRANSPORTBUILDER_CONTRACTID = "mozilla.org/presentation/datachanneltransportbuilder;1";
|
|
||||||
|
|
||||||
function PresentationDataChannelDescription(aDataChannelSDP) {
|
|
||||||
this._dataChannelSDP = JSON.stringify(aDataChannelSDP);
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationDataChannelDescription.prototype = {
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationChannelDescription]),
|
|
||||||
get type() {
|
|
||||||
return Ci.nsIPresentationChannelDescription.TYPE_DATACHANNEL;
|
|
||||||
},
|
|
||||||
get tcpAddress() {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
get tcpPort() {
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
get dataChannelSDP() {
|
|
||||||
return this._dataChannelSDP;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function PresentationTransportBuilder() {
|
|
||||||
log("PresentationTransportBuilder construct");
|
|
||||||
this._isControlChannelNeeded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationTransportBuilder.prototype = {
|
|
||||||
classID: PRESENTATIONTRANSPORTBUILDER_CID,
|
|
||||||
contractID: PRESENTATIONTRANSPORTBUILDER_CONTRACTID,
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationSessionTransportBuilder,
|
|
||||||
Ci.nsIPresentationDataChannelSessionTransportBuilder,
|
|
||||||
Ci.nsITimerCallback]),
|
|
||||||
|
|
||||||
buildDataChannelTransport: function(aRole, aWindow, aListener) {
|
|
||||||
if (!aRole || !aWindow || !aListener) {
|
|
||||||
log("buildDataChannelTransport with illegal parameters");
|
|
||||||
throw Cr.NS_ERROR_ILLEGAL_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._window) {
|
|
||||||
log("buildDataChannelTransport has started.");
|
|
||||||
throw Cr.NS_ERROR_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
log("buildDataChannelTransport with role " + aRole);
|
|
||||||
this._role = aRole;
|
|
||||||
this._window = aWindow;
|
|
||||||
this._listener = aListener.QueryInterface(Ci.nsIPresentationSessionTransportBuilderListener);
|
|
||||||
|
|
||||||
// TODO bug 1227053 set iceServers from |nsIPresentationDevice|
|
|
||||||
this._peerConnection = new this._window.RTCPeerConnection();
|
|
||||||
|
|
||||||
// |this._listener == null| will throw since the control channel is
|
|
||||||
// abnormally closed.
|
|
||||||
this._peerConnection.onicecandidate = aEvent => aEvent.candidate &&
|
|
||||||
this._listener.sendIceCandidate(JSON.stringify(aEvent.candidate));
|
|
||||||
|
|
||||||
this._peerConnection.onnegotiationneeded = () => {
|
|
||||||
log("onnegotiationneeded with role " + this._role);
|
|
||||||
if (!this._peerConnection) {
|
|
||||||
log("ignoring negotiationneeded without PeerConnection");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._peerConnection.createOffer()
|
|
||||||
.then(aOffer => this._peerConnection.setLocalDescription(aOffer))
|
|
||||||
.then(() => this._listener
|
|
||||||
.sendOffer(new PresentationDataChannelDescription(this._peerConnection.localDescription)))
|
|
||||||
.catch(e => this._reportError(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (this._role) {
|
|
||||||
case Ci.nsIPresentationService.ROLE_CONTROLLER:
|
|
||||||
this._dataChannel = this._peerConnection.createDataChannel("presentationAPI");
|
|
||||||
this._setDataChannel();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Ci.nsIPresentationService.ROLE_RECEIVER:
|
|
||||||
this._peerConnection.ondatachannel = aEvent => {
|
|
||||||
this._dataChannel = aEvent.channel;
|
|
||||||
// Ensure the binaryType of dataChannel is blob.
|
|
||||||
this._dataChannel.binaryType = "blob";
|
|
||||||
this._setDataChannel();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw Cr.NS_ERROR_ILLEGAL_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO bug 1228235 we should have a way to let device providers customize
|
|
||||||
// the time-out duration.
|
|
||||||
let timeout = Services.prefs.getIntPref("presentation.receiver.loading.timeout", 10000);
|
|
||||||
|
|
||||||
// The timer is to check if the negotiation finishes on time.
|
|
||||||
this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
|
||||||
this._timer.initWithCallback(this, timeout, this._timer.TYPE_ONE_SHOT);
|
|
||||||
},
|
|
||||||
|
|
||||||
notify: function() {
|
|
||||||
if (!this._sessionTransport) {
|
|
||||||
this._cleanup(Cr.NS_ERROR_NET_TIMEOUT);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_reportError: function(aError) {
|
|
||||||
log("report Error " + aError.name + ":" + aError.message);
|
|
||||||
this._cleanup(Cr.NS_ERROR_FAILURE);
|
|
||||||
},
|
|
||||||
|
|
||||||
_setDataChannel: function() {
|
|
||||||
this._dataChannel.onopen = () => {
|
|
||||||
log("data channel is open, notify the listener, role " + this._role);
|
|
||||||
|
|
||||||
// Handoff the ownership of _peerConnection and _dataChannel to
|
|
||||||
// _sessionTransport
|
|
||||||
this._sessionTransport = new PresentationTransport();
|
|
||||||
this._sessionTransport.init(this._peerConnection, this._dataChannel, this._window);
|
|
||||||
this._peerConnection.onicecandidate = null;
|
|
||||||
this._peerConnection.onnegotiationneeded = null;
|
|
||||||
this._peerConnection = this._dataChannel = null;
|
|
||||||
|
|
||||||
this._listener.onSessionTransport(this._sessionTransport);
|
|
||||||
this._sessionTransport.callback.notifyTransportReady();
|
|
||||||
|
|
||||||
this._cleanup(Cr.NS_OK);
|
|
||||||
};
|
|
||||||
|
|
||||||
this._dataChannel.onerror = aError => {
|
|
||||||
log("data channel onerror " + aError.name + ":" + aError.message);
|
|
||||||
this._cleanup(Cr.NS_ERROR_FAILURE);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_cleanup: function(aReason) {
|
|
||||||
if (aReason != Cr.NS_OK) {
|
|
||||||
this._listener.onError(aReason);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._dataChannel) {
|
|
||||||
this._dataChannel.close();
|
|
||||||
this._dataChannel = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._peerConnection) {
|
|
||||||
this._peerConnection.close();
|
|
||||||
this._peerConnection = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._role = null;
|
|
||||||
this._window = null;
|
|
||||||
|
|
||||||
this._listener = null;
|
|
||||||
this._sessionTransport = null;
|
|
||||||
|
|
||||||
if (this._timer) {
|
|
||||||
this._timer.cancel();
|
|
||||||
this._timer = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// nsIPresentationControlChannelListener
|
|
||||||
onOffer: function(aOffer) {
|
|
||||||
if (this._role !== Ci.nsIPresentationService.ROLE_RECEIVER ||
|
|
||||||
this._sessionTransport) {
|
|
||||||
log("onOffer status error");
|
|
||||||
this._cleanup(Cr.NS_ERROR_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
log("onOffer: " + aOffer.dataChannelSDP + " with role " + this._role);
|
|
||||||
|
|
||||||
let offer = new this._window
|
|
||||||
.RTCSessionDescription(JSON.parse(aOffer.dataChannelSDP));
|
|
||||||
|
|
||||||
this._peerConnection.setRemoteDescription(offer)
|
|
||||||
.then(() => this._peerConnection.signalingState == "stable" ||
|
|
||||||
this._peerConnection.createAnswer())
|
|
||||||
.then(aAnswer => this._peerConnection.setLocalDescription(aAnswer))
|
|
||||||
.then(() => {
|
|
||||||
this._isControlChannelNeeded = false;
|
|
||||||
this._listener
|
|
||||||
.sendAnswer(new PresentationDataChannelDescription(this._peerConnection.localDescription))
|
|
||||||
}).catch(e => this._reportError(e));
|
|
||||||
},
|
|
||||||
|
|
||||||
onAnswer: function(aAnswer) {
|
|
||||||
if (this._role !== Ci.nsIPresentationService.ROLE_CONTROLLER ||
|
|
||||||
this._sessionTransport) {
|
|
||||||
log("onAnswer status error");
|
|
||||||
this._cleanup(Cr.NS_ERROR_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
log("onAnswer: " + aAnswer.dataChannelSDP + " with role " + this._role);
|
|
||||||
|
|
||||||
let answer = new this._window
|
|
||||||
.RTCSessionDescription(JSON.parse(aAnswer.dataChannelSDP));
|
|
||||||
|
|
||||||
this._peerConnection.setRemoteDescription(answer).catch(e => this._reportError(e));
|
|
||||||
this._isControlChannelNeeded = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
onIceCandidate: function(aCandidate) {
|
|
||||||
log("onIceCandidate: " + aCandidate + " with role " + this._role);
|
|
||||||
if (!this._window || !this._peerConnection) {
|
|
||||||
log("ignoring ICE candidate after connection");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let candidate = new this._window.RTCIceCandidate(JSON.parse(aCandidate));
|
|
||||||
this._peerConnection.addIceCandidate(candidate).catch(e => this._reportError(e));
|
|
||||||
},
|
|
||||||
|
|
||||||
notifyDisconnected: function(aReason) {
|
|
||||||
log("notifyDisconnected reason: " + aReason);
|
|
||||||
|
|
||||||
if (aReason != Cr.NS_OK) {
|
|
||||||
this._cleanup(aReason);
|
|
||||||
} else if (this._isControlChannelNeeded) {
|
|
||||||
this._cleanup(Cr.NS_ERROR_FAILURE);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
function PresentationTransport() {
|
|
||||||
this._messageQueue = [];
|
|
||||||
this._closeReason = Cr.NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationTransport.prototype = {
|
|
||||||
classID: PRESENTATIONTRANSPORT_CID,
|
|
||||||
contractID: PRESENTATIONTRANSPORT_CONTRACTID,
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationSessionTransport]),
|
|
||||||
|
|
||||||
init: function(aPeerConnection, aDataChannel, aWindow) {
|
|
||||||
log("initWithDataChannel");
|
|
||||||
this._enableDataNotification = false;
|
|
||||||
this._dataChannel = aDataChannel;
|
|
||||||
this._peerConnection = aPeerConnection;
|
|
||||||
this._window = aWindow;
|
|
||||||
|
|
||||||
this._dataChannel.onopen = () => {
|
|
||||||
log("data channel reopen. Should never touch here");
|
|
||||||
};
|
|
||||||
|
|
||||||
this._dataChannel.onclose = () => {
|
|
||||||
log("data channel onclose");
|
|
||||||
if (this._callback) {
|
|
||||||
this._callback.notifyTransportClosed(this._closeReason);
|
|
||||||
}
|
|
||||||
this._cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._dataChannel.onmessage = aEvent => {
|
|
||||||
log("data channel onmessage " + aEvent.data);
|
|
||||||
|
|
||||||
if (!this._enableDataNotification || !this._callback) {
|
|
||||||
log("queue message");
|
|
||||||
this._messageQueue.push(aEvent.data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._doNotifyData(aEvent.data);
|
|
||||||
};
|
|
||||||
|
|
||||||
this._dataChannel.onerror = aError => {
|
|
||||||
log("data channel onerror " + aError.name + ":" + aError.message);
|
|
||||||
if (this._callback) {
|
|
||||||
this._callback.notifyTransportClosed(Cr.NS_ERROR_FAILURE);
|
|
||||||
}
|
|
||||||
this._cleanup();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// nsIPresentationTransport
|
|
||||||
get selfAddress() {
|
|
||||||
throw NS_ERROR_NOT_AVAILABLE;
|
|
||||||
},
|
|
||||||
|
|
||||||
get callback() {
|
|
||||||
return this._callback;
|
|
||||||
},
|
|
||||||
|
|
||||||
set callback(aCallback) {
|
|
||||||
this._callback = aCallback;
|
|
||||||
},
|
|
||||||
|
|
||||||
send: function(aData) {
|
|
||||||
log("send " + aData);
|
|
||||||
this._dataChannel.send(aData);
|
|
||||||
},
|
|
||||||
|
|
||||||
sendBinaryMsg: function(aData) {
|
|
||||||
log("sendBinaryMsg");
|
|
||||||
|
|
||||||
let array = new Uint8Array(aData.length);
|
|
||||||
for (let i = 0; i < aData.length; i++) {
|
|
||||||
array[i] = aData.charCodeAt(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._dataChannel.send(array);
|
|
||||||
},
|
|
||||||
|
|
||||||
sendBlob: function(aBlob) {
|
|
||||||
log("sendBlob");
|
|
||||||
|
|
||||||
this._dataChannel.send(aBlob);
|
|
||||||
},
|
|
||||||
|
|
||||||
enableDataNotification: function() {
|
|
||||||
log("enableDataNotification");
|
|
||||||
if (this._enableDataNotification) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._callback) {
|
|
||||||
throw NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._enableDataNotification = true;
|
|
||||||
|
|
||||||
this._messageQueue.forEach(aData => this._doNotifyData(aData));
|
|
||||||
this._messageQueue = [];
|
|
||||||
},
|
|
||||||
|
|
||||||
close: function(aReason) {
|
|
||||||
this._closeReason = aReason;
|
|
||||||
|
|
||||||
this._dataChannel.close();
|
|
||||||
},
|
|
||||||
|
|
||||||
_cleanup: function() {
|
|
||||||
this._dataChannel = null;
|
|
||||||
|
|
||||||
if (this._peerConnection) {
|
|
||||||
this._peerConnection.close();
|
|
||||||
this._peerConnection = null;
|
|
||||||
}
|
|
||||||
this._callback = null;
|
|
||||||
this._messageQueue = [];
|
|
||||||
this._window = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
_doNotifyData: function(aData) {
|
|
||||||
if (!this._callback) {
|
|
||||||
throw NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aData instanceof this._window.Blob) {
|
|
||||||
let reader = new this._window.FileReader();
|
|
||||||
reader.addEventListener("load", (aEvent) => {
|
|
||||||
this._callback.notifyData(aEvent.target.result, true);
|
|
||||||
});
|
|
||||||
reader.readAsBinaryString(aData);
|
|
||||||
} else {
|
|
||||||
this._callback.notifyData(aData, false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PresentationTransportBuilder,
|
|
||||||
PresentationTransport]);
|
|
|
@ -1,6 +0,0 @@
|
||||||
# PresentationDataChannelSessionTransport.js
|
|
||||||
component {dd2bbf2f-3399-4389-8f5f-d382afb8b2d6} PresentationDataChannelSessionTransport.js
|
|
||||||
contract @mozilla.org/presentation/datachanneltransport;1 {dd2bbf2f-3399-4389-8f5f-d382afb8b2d6}
|
|
||||||
|
|
||||||
component {215b2f62-46e2-4004-a3d1-6858e56c20f3} PresentationDataChannelSessionTransport.js
|
|
||||||
contract @mozilla.org/presentation/datachanneltransportbuilder;1 {215b2f62-46e2-4004-a3d1-6858e56c20f3}
|
|
|
@ -1,119 +0,0 @@
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
|
||||||
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
|
|
||||||
|
|
||||||
function log(aMsg) {
|
|
||||||
//dump("-*- PresentationDeviceInfoManager.js : " + aMsg + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
const PRESENTATIONDEVICEINFOMANAGER_CID = Components.ID("{1bd66bef-f643-4be3-b690-0c656353eafd}");
|
|
||||||
const PRESENTATIONDEVICEINFOMANAGER_CONTRACTID = "@mozilla.org/presentation-device/deviceInfo;1";
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
|
||||||
"@mozilla.org/childprocessmessagemanager;1",
|
|
||||||
"nsIMessageSender");
|
|
||||||
|
|
||||||
function PresentationDeviceInfoManager() {}
|
|
||||||
|
|
||||||
PresentationDeviceInfoManager.prototype = {
|
|
||||||
__proto__: DOMRequestIpcHelper.prototype,
|
|
||||||
|
|
||||||
classID: PRESENTATIONDEVICEINFOMANAGER_CID,
|
|
||||||
contractID: PRESENTATIONDEVICEINFOMANAGER_CONTRACTID,
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference,
|
|
||||||
Ci.nsIObserver,
|
|
||||||
Ci.nsIDOMGlobalPropertyInitializer]),
|
|
||||||
|
|
||||||
receiveMessage: function(aMsg) {
|
|
||||||
if (!aMsg || !aMsg.data) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = aMsg.data;
|
|
||||||
|
|
||||||
log("receive aMsg: " + aMsg.name);
|
|
||||||
switch (aMsg.name) {
|
|
||||||
case "PresentationDeviceInfoManager:OnDeviceChange": {
|
|
||||||
let detail = {
|
|
||||||
detail: {
|
|
||||||
type: data.type,
|
|
||||||
deviceInfo: data.deviceInfo,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let event = new this._window.CustomEvent("devicechange", Cu.cloneInto(detail, this._window));
|
|
||||||
this.__DOM_IMPL__.dispatchEvent(event);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "PresentationDeviceInfoManager:GetAll:Result:Ok": {
|
|
||||||
let resolver = this.takePromiseResolver(data.requestId);
|
|
||||||
|
|
||||||
if (!resolver) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
resolver.resolve(Cu.cloneInto(data.devices, this._window));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "PresentationDeviceInfoManager:GetAll:Result:Error": {
|
|
||||||
let resolver = this.takePromiseResolver(data.requestId);
|
|
||||||
|
|
||||||
if (!resolver) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
resolver.reject(data.error);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
init: function(aWin) {
|
|
||||||
log("init");
|
|
||||||
this.initDOMRequestHelper(aWin, [
|
|
||||||
{name: "PresentationDeviceInfoManager:OnDeviceChange", weakRef: true},
|
|
||||||
{name: "PresentationDeviceInfoManager:GetAll:Result:Ok", weakRef: true},
|
|
||||||
{name: "PresentationDeviceInfoManager:GetAll:Result:Error", weakRef: true},
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
|
|
||||||
uninit: function() {
|
|
||||||
log("uninit");
|
|
||||||
let self = this;
|
|
||||||
|
|
||||||
this.forEachPromiseResolver(function(aKey) {
|
|
||||||
self.takePromiseResolver(aKey).reject("PresentationDeviceInfoManager got destroyed");
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
get ondevicechange() {
|
|
||||||
return this.__DOM_IMPL__.getEventHandler("ondevicechange");
|
|
||||||
},
|
|
||||||
|
|
||||||
set ondevicechange(aHandler) {
|
|
||||||
this.__DOM_IMPL__.setEventHandler("ondevicechange", aHandler);
|
|
||||||
},
|
|
||||||
|
|
||||||
getAll: function() {
|
|
||||||
log("getAll");
|
|
||||||
let self = this;
|
|
||||||
return this.createPromiseWithId(function(aResolverId) {
|
|
||||||
cpmm.sendAsyncMessage("PresentationDeviceInfoManager:GetAll", {
|
|
||||||
requestId: aResolverId,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
forceDiscovery: function() {
|
|
||||||
cpmm.sendAsyncMessage("PresentationDeviceInfoManager:ForceDiscovery");
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PresentationDeviceInfoManager]);
|
|
|
@ -1,104 +0,0 @@
|
||||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- /
|
|
||||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
|
||||||
|
|
||||||
this.EXPORTED_SYMBOLS = ["PresentationDeviceInfoService"];
|
|
||||||
|
|
||||||
function log(aMsg) {
|
|
||||||
//dump("PresentationDeviceInfoManager.jsm: " + aMsg + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyServiceGetter(this, "presentationDeviceManager",
|
|
||||||
"@mozilla.org/presentation-device/manager;1",
|
|
||||||
"nsIPresentationDeviceManager");
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
|
|
||||||
"@mozilla.org/parentprocessmessagemanager;1",
|
|
||||||
"nsIMessageBroadcaster");
|
|
||||||
|
|
||||||
this.PresentationDeviceInfoService = {
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener,
|
|
||||||
Ci.nsIObserver]),
|
|
||||||
|
|
||||||
init: function() {
|
|
||||||
log("init");
|
|
||||||
ppmm.addMessageListener("PresentationDeviceInfoManager:GetAll", this);
|
|
||||||
ppmm.addMessageListener("PresentationDeviceInfoManager:ForceDiscovery", this);
|
|
||||||
Services.obs.addObserver(this, "presentation-device-change", false);
|
|
||||||
},
|
|
||||||
|
|
||||||
getAll: function(aData, aMm) {
|
|
||||||
log("getAll");
|
|
||||||
let deviceArray = presentationDeviceManager.getAvailableDevices().QueryInterface(Ci.nsIArray);
|
|
||||||
if (!deviceArray) {
|
|
||||||
aData.error = "DataError";
|
|
||||||
aMm.sendAsyncMessage("PresentationDeviceInfoManager:GetAll:Result:Error", aData);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
aData.devices = [];
|
|
||||||
for (let i = 0; i < deviceArray.length; i++) {
|
|
||||||
let device = deviceArray.queryElementAt(i, Ci.nsIPresentationDevice);
|
|
||||||
aData.devices.push({
|
|
||||||
id: device.id,
|
|
||||||
name: device.name,
|
|
||||||
type: device.type,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
aMm.sendAsyncMessage("PresentationDeviceInfoManager:GetAll:Result:Ok", aData);
|
|
||||||
},
|
|
||||||
|
|
||||||
forceDiscovery: function() {
|
|
||||||
log("forceDiscovery");
|
|
||||||
presentationDeviceManager.forceDiscovery();
|
|
||||||
},
|
|
||||||
|
|
||||||
observe: function(aSubject, aTopic, aData) {
|
|
||||||
log("observe: " + aTopic);
|
|
||||||
|
|
||||||
let device = aSubject.QueryInterface(Ci.nsIPresentationDevice);
|
|
||||||
let data = {
|
|
||||||
type: aData,
|
|
||||||
deviceInfo: {
|
|
||||||
id: device.id,
|
|
||||||
name: device.name,
|
|
||||||
type: device.type,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
ppmm.broadcastAsyncMessage("PresentationDeviceInfoManager:OnDeviceChange", data);
|
|
||||||
},
|
|
||||||
|
|
||||||
receiveMessage: function(aMessage) {
|
|
||||||
if (!aMessage.target.assertPermission("presentation-device-manage")) {
|
|
||||||
debug("receive message " + aMessage.name +
|
|
||||||
" from a content process with no 'presentation-device-manage' privileges.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let msg = aMessage.data || {};
|
|
||||||
let mm = aMessage.target;
|
|
||||||
|
|
||||||
log("receiveMessage: " + aMessage.name);
|
|
||||||
switch (aMessage.name) {
|
|
||||||
case "PresentationDeviceInfoManager:GetAll": {
|
|
||||||
this.getAll(msg, mm);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "PresentationDeviceInfoManager:ForceDiscovery": {
|
|
||||||
this.forceDiscovery();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
this.PresentationDeviceInfoService.init();
|
|
|
@ -1,3 +0,0 @@
|
||||||
# PresentationDeviceInfoManager.js
|
|
||||||
component {1bd66bef-f643-4be3-b690-0c656353eafd} PresentationDeviceInfoManager.js
|
|
||||||
contract @mozilla.org/presentation-device/deviceInfo;1 {1bd66bef-f643-4be3-b690-0c656353eafd}
|
|
|
@ -1,336 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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 "PresentationDeviceManager.h"
|
|
||||||
|
|
||||||
#include "mozilla/Services.h"
|
|
||||||
#include "MainThreadUtils.h"
|
|
||||||
#include "nsArrayUtils.h"
|
|
||||||
#include "nsCategoryCache.h"
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsIMutableArray.h"
|
|
||||||
#include "nsIObserverService.h"
|
|
||||||
#include "nsXULAppAPI.h"
|
|
||||||
#include "PresentationSessionRequest.h"
|
|
||||||
#include "PresentationTerminateRequest.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(PresentationDeviceManager,
|
|
||||||
nsIPresentationDeviceManager,
|
|
||||||
nsIPresentationDeviceListener,
|
|
||||||
nsIObserver,
|
|
||||||
nsISupportsWeakReference)
|
|
||||||
|
|
||||||
PresentationDeviceManager::PresentationDeviceManager()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationDeviceManager::~PresentationDeviceManager()
|
|
||||||
{
|
|
||||||
UnloadDeviceProviders();
|
|
||||||
mDevices.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationDeviceManager::Init()
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
|
||||||
if (obs) {
|
|
||||||
obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadDeviceProviders();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationDeviceManager::Shutdown()
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
|
||||||
if (obs) {
|
|
||||||
obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
UnloadDeviceProviders();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationDeviceManager::LoadDeviceProviders()
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mProviders.IsEmpty());
|
|
||||||
|
|
||||||
nsCategoryCache<nsIPresentationDeviceProvider> providerCache(PRESENTATION_DEVICE_PROVIDER_CATEGORY);
|
|
||||||
providerCache.GetEntries(mProviders);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < mProviders.Length(); ++i) {
|
|
||||||
mProviders[i]->SetListener(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationDeviceManager::UnloadDeviceProviders()
|
|
||||||
{
|
|
||||||
for (uint32_t i = 0; i < mProviders.Length(); ++i) {
|
|
||||||
mProviders[i]->SetListener(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
mProviders.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationDeviceManager::NotifyDeviceChange(nsIPresentationDevice* aDevice,
|
|
||||||
const char16_t* aType)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
||||||
if (obs) {
|
|
||||||
obs->NotifyObservers(aDevice,
|
|
||||||
PRESENTATION_DEVICE_CHANGE_TOPIC,
|
|
||||||
aType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsIPresentationDeviceManager
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationDeviceManager::ForceDiscovery()
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < mProviders.Length(); ++i) {
|
|
||||||
mProviders[i]->ForceDiscovery();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationDeviceManager::AddDeviceProvider(nsIPresentationDeviceProvider* aProvider)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG(aProvider);
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (NS_WARN_IF(mProviders.Contains(aProvider))) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
mProviders.AppendElement(aProvider);
|
|
||||||
aProvider->SetListener(this);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationDeviceManager::RemoveDeviceProvider(nsIPresentationDeviceProvider* aProvider)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG(aProvider);
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!mProviders.RemoveElement(aProvider))) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
aProvider->SetListener(nullptr);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationDeviceManager::GetDeviceAvailable(bool* aRetVal)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG_POINTER(aRetVal);
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
*aRetVal = !mDevices.IsEmpty();
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationDeviceManager::GetAvailableDevices(nsIArray* aPresentationUrls, nsIArray** aRetVal)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG_POINTER(aRetVal);
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
// Bug 1194049: some providers may discontinue discovery after timeout.
|
|
||||||
// Call |ForceDiscovery()| here to make sure device lists are updated.
|
|
||||||
NS_DispatchToMainThread(
|
|
||||||
NewRunnableMethod(this, &PresentationDeviceManager::ForceDiscovery));
|
|
||||||
|
|
||||||
nsTArray<nsString> presentationUrls;
|
|
||||||
if (aPresentationUrls) {
|
|
||||||
uint32_t length;
|
|
||||||
nsresult rv = aPresentationUrls->GetLength(&length);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
|
||||||
for (uint32_t i = 0; i < length; ++i) {
|
|
||||||
nsCOMPtr<nsISupportsString> isupportStr =
|
|
||||||
do_QueryElementAt(aPresentationUrls, i);
|
|
||||||
|
|
||||||
nsAutoString presentationUrl;
|
|
||||||
rv = isupportStr->GetData(presentationUrl);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
presentationUrls.AppendElement(presentationUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIMutableArray> devices = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
|
||||||
for (uint32_t i = 0; i < mDevices.Length(); ++i) {
|
|
||||||
if (presentationUrls.IsEmpty()) {
|
|
||||||
devices->AppendElement(mDevices[i], false);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t j = 0; j < presentationUrls.Length(); ++j) {
|
|
||||||
bool isSupported;
|
|
||||||
if (NS_SUCCEEDED(mDevices[i]->IsRequestedUrlSupported(presentationUrls[j],
|
|
||||||
&isSupported)) &&
|
|
||||||
isSupported) {
|
|
||||||
devices->AppendElement(mDevices[i], false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
devices.forget(aRetVal);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsIPresentationDeviceListener
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationDeviceManager::AddDevice(nsIPresentationDevice* aDevice)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG(aDevice);
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (NS_WARN_IF(mDevices.Contains(aDevice))) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
mDevices.AppendElement(aDevice);
|
|
||||||
|
|
||||||
NotifyDeviceChange(aDevice, u"add");
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationDeviceManager::RemoveDevice(nsIPresentationDevice* aDevice)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG(aDevice);
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
int32_t index = mDevices.IndexOf(aDevice);
|
|
||||||
if (NS_WARN_IF(index < 0)) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
mDevices.RemoveElementAt(index);
|
|
||||||
|
|
||||||
NotifyDeviceChange(aDevice, u"remove");
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationDeviceManager::UpdateDevice(nsIPresentationDevice* aDevice)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG(aDevice);
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!mDevices.Contains(aDevice))) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
NotifyDeviceChange(aDevice, u"update");
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationDeviceManager::OnSessionRequest(nsIPresentationDevice* aDevice,
|
|
||||||
const nsAString& aUrl,
|
|
||||||
const nsAString& aPresentationId,
|
|
||||||
nsIPresentationControlChannel* aControlChannel)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG(aDevice);
|
|
||||||
NS_ENSURE_ARG(aControlChannel);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
||||||
NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
RefPtr<PresentationSessionRequest> request =
|
|
||||||
new PresentationSessionRequest(aDevice, aUrl, aPresentationId, aControlChannel);
|
|
||||||
obs->NotifyObservers(request,
|
|
||||||
PRESENTATION_SESSION_REQUEST_TOPIC,
|
|
||||||
nullptr);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationDeviceManager::OnTerminateRequest(nsIPresentationDevice* aDevice,
|
|
||||||
const nsAString& aPresentationId,
|
|
||||||
nsIPresentationControlChannel* aControlChannel,
|
|
||||||
bool aIsFromReceiver)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG(aDevice);
|
|
||||||
NS_ENSURE_ARG(aControlChannel);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
||||||
NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
RefPtr<PresentationTerminateRequest> request =
|
|
||||||
new PresentationTerminateRequest(aDevice, aPresentationId,
|
|
||||||
aControlChannel, aIsFromReceiver);
|
|
||||||
obs->NotifyObservers(request,
|
|
||||||
PRESENTATION_TERMINATE_REQUEST_TOPIC,
|
|
||||||
nullptr);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationDeviceManager::OnReconnectRequest(nsIPresentationDevice* aDevice,
|
|
||||||
const nsAString& aUrl,
|
|
||||||
const nsAString& aPresentationId,
|
|
||||||
nsIPresentationControlChannel* aControlChannel)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG(aDevice);
|
|
||||||
NS_ENSURE_ARG(aControlChannel);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
||||||
NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE);
|
|
||||||
|
|
||||||
RefPtr<PresentationSessionRequest> request =
|
|
||||||
new PresentationSessionRequest(aDevice, aUrl, aPresentationId, aControlChannel);
|
|
||||||
obs->NotifyObservers(request,
|
|
||||||
PRESENTATION_RECONNECT_REQUEST_TOPIC,
|
|
||||||
nullptr);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsIObserver
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationDeviceManager::Observe(nsISupports *aSubject,
|
|
||||||
const char *aTopic,
|
|
||||||
const char16_t *aData)
|
|
||||||
{
|
|
||||||
if (!strcmp(aTopic, "profile-after-change")) {
|
|
||||||
Init();
|
|
||||||
} else if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
|
||||||
Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,54 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationDeviceManager_h__
|
|
||||||
#define mozilla_dom_PresentationDeviceManager_h__
|
|
||||||
|
|
||||||
#include "nsIObserver.h"
|
|
||||||
#include "nsIPresentationDevice.h"
|
|
||||||
#include "nsIPresentationDeviceManager.h"
|
|
||||||
#include "nsIPresentationDeviceProvider.h"
|
|
||||||
#include "nsCOMArray.h"
|
|
||||||
#include "nsWeakReference.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class PresentationDeviceManager final : public nsIPresentationDeviceManager
|
|
||||||
, public nsIPresentationDeviceListener
|
|
||||||
, public nsIObserver
|
|
||||||
, public nsSupportsWeakReference
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIPRESENTATIONDEVICEMANAGER
|
|
||||||
NS_DECL_NSIPRESENTATIONDEVICELISTENER
|
|
||||||
NS_DECL_NSIOBSERVER
|
|
||||||
|
|
||||||
PresentationDeviceManager();
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~PresentationDeviceManager();
|
|
||||||
|
|
||||||
void Init();
|
|
||||||
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
void LoadDeviceProviders();
|
|
||||||
|
|
||||||
void UnloadDeviceProviders();
|
|
||||||
|
|
||||||
void NotifyDeviceChange(nsIPresentationDevice* aDevice,
|
|
||||||
const char16_t* aType);
|
|
||||||
|
|
||||||
nsCOMArray<nsIPresentationDeviceProvider> mProviders;
|
|
||||||
nsCOMArray<nsIPresentationDevice> mDevices;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif /* mozilla_dom_PresentationDeviceManager_h__ */
|
|
|
@ -1,26 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationLog_h
|
|
||||||
#define mozilla_dom_PresentationLog_h
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MOZ_LOG=Presentation:5
|
|
||||||
* For detail, see PresentationService.cpp
|
|
||||||
*/
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
extern mozilla::LazyLogModule gPresentationLog;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef PRES_ERROR
|
|
||||||
#define PRES_ERROR(...) MOZ_LOG(mozilla::dom::gPresentationLog, mozilla::LogLevel::Error, (__VA_ARGS__))
|
|
||||||
|
|
||||||
#undef PRES_DEBUG
|
|
||||||
#define PRES_DEBUG(...) MOZ_LOG(mozilla::dom::gPresentationLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationLog_h
|
|
|
@ -1,28 +0,0 @@
|
||||||
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
||||||
|
|
||||||
const NETWORKHELPER_CID = Components.ID("{5fb96caa-6d49-4f6b-9a4b-65dd0d51f92d}");
|
|
||||||
|
|
||||||
function PresentationNetworkHelper() {}
|
|
||||||
|
|
||||||
PresentationNetworkHelper.prototype = {
|
|
||||||
classID: NETWORKHELPER_CID,
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationNetworkHelper]),
|
|
||||||
|
|
||||||
getWifiIPAddress: function(aListener) {
|
|
||||||
Messaging.sendRequestForResult({type: "Wifi:GetIPAddress"})
|
|
||||||
.then(result => aListener.onGetWifiIPAddress(result),
|
|
||||||
err => aListener.onError(err));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PresentationNetworkHelper]);
|
|
|
@ -1,3 +0,0 @@
|
||||||
# PresentationNetworkHelper.js
|
|
||||||
component {5fb96caa-6d49-4f6b-9a4b-65dd0d51f92d} PresentationNetworkHelper.js
|
|
||||||
contract @mozilla.org/presentation-device/networkHelper;1 {5fb96caa-6d49-4f6b-9a4b-65dd0d51f92d}
|
|
|
@ -1,179 +0,0 @@
|
||||||
/* -*- 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 "PresentationReceiver.h"
|
|
||||||
|
|
||||||
#include "mozilla/dom/PresentationReceiverBinding.h"
|
|
||||||
#include "mozilla/dom/Promise.h"
|
|
||||||
#include "nsContentUtils.h"
|
|
||||||
#include "nsIPresentationService.h"
|
|
||||||
#include "nsPIDOMWindow.h"
|
|
||||||
#include "nsServiceManagerUtils.h"
|
|
||||||
#include "nsThreadUtils.h"
|
|
||||||
#include "PresentationConnection.h"
|
|
||||||
#include "PresentationConnectionList.h"
|
|
||||||
#include "PresentationLog.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PresentationReceiver,
|
|
||||||
mOwner,
|
|
||||||
mGetConnectionListPromise,
|
|
||||||
mConnectionList)
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(PresentationReceiver)
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(PresentationReceiver)
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PresentationReceiver)
|
|
||||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIPresentationRespondingListener)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
||||||
NS_INTERFACE_MAP_END
|
|
||||||
|
|
||||||
/* static */ already_AddRefed<PresentationReceiver>
|
|
||||||
PresentationReceiver::Create(nsPIDOMWindowInner* aWindow)
|
|
||||||
{
|
|
||||||
RefPtr<PresentationReceiver> receiver = new PresentationReceiver(aWindow);
|
|
||||||
return NS_WARN_IF(!receiver->Init()) ? nullptr : receiver.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationReceiver::PresentationReceiver(nsPIDOMWindowInner* aWindow)
|
|
||||||
: mOwner(aWindow)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationReceiver::~PresentationReceiver()
|
|
||||||
{
|
|
||||||
Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationReceiver::Init()
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!mOwner)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
mWindowId = mOwner->WindowID();
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDocShell> docShell = mOwner->GetDocShell();
|
|
||||||
MOZ_ASSERT(docShell);
|
|
||||||
|
|
||||||
nsContentUtils::GetPresentationURL(docShell, mUrl);
|
|
||||||
return !mUrl.IsEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PresentationReceiver::Shutdown()
|
|
||||||
{
|
|
||||||
PRES_DEBUG("receiver shutdown:windowId[%d]\n", mWindowId);
|
|
||||||
|
|
||||||
// Unregister listener for incoming sessions.
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!service)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Unused <<
|
|
||||||
NS_WARN_IF(NS_FAILED(service->UnregisterRespondingListener(mWindowId)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual */ JSObject*
|
|
||||||
PresentationReceiver::WrapObject(JSContext* aCx,
|
|
||||||
JS::Handle<JSObject*> aGivenProto)
|
|
||||||
{
|
|
||||||
return PresentationReceiverBinding::Wrap(aCx, this, aGivenProto);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationReceiver::NotifySessionConnect(uint64_t aWindowId,
|
|
||||||
const nsAString& aSessionId)
|
|
||||||
{
|
|
||||||
PRES_DEBUG("receiver session connect:id[%s], windowId[%x]\n",
|
|
||||||
NS_ConvertUTF16toUTF8(aSessionId).get(), aWindowId);
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!mOwner)) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_WARN_IF(aWindowId != mWindowId)) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!mConnectionList)) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<PresentationConnection> connection =
|
|
||||||
PresentationConnection::Create(mOwner, aSessionId, mUrl,
|
|
||||||
nsIPresentationService::ROLE_RECEIVER,
|
|
||||||
mConnectionList);
|
|
||||||
if (NS_WARN_IF(!connection)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<Promise>
|
|
||||||
PresentationReceiver::GetConnectionList(ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mOwner);
|
|
||||||
if (NS_WARN_IF(!global)) {
|
|
||||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mGetConnectionListPromise) {
|
|
||||||
mGetConnectionListPromise = Promise::Create(global, aRv);
|
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<PresentationReceiver> self = this;
|
|
||||||
nsresult rv =
|
|
||||||
NS_DispatchToMainThread(NS_NewRunnableFunction([self] () -> void {
|
|
||||||
self->CreateConnectionList();
|
|
||||||
}));
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
aRv.Throw(rv);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<Promise> promise = mGetConnectionListPromise;
|
|
||||||
return promise.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationReceiver::CreateConnectionList()
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mGetConnectionListPromise);
|
|
||||||
|
|
||||||
if (mConnectionList) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mConnectionList = new PresentationConnectionList(mOwner,
|
|
||||||
mGetConnectionListPromise);
|
|
||||||
|
|
||||||
// Register listener for incoming sessions.
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!service)) {
|
|
||||||
mGetConnectionListPromise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv = service->RegisterRespondingListener(mWindowId, this);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
mGetConnectionListPromise->MaybeReject(rv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,71 +0,0 @@
|
||||||
/* -*- 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationReceiver_h
|
|
||||||
#define mozilla_dom_PresentationReceiver_h
|
|
||||||
|
|
||||||
#include "mozilla/ErrorResult.h"
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsCycleCollectionParticipant.h"
|
|
||||||
#include "nsIPresentationListener.h"
|
|
||||||
#include "nsWrapperCache.h"
|
|
||||||
#include "nsString.h"
|
|
||||||
|
|
||||||
class nsPIDOMWindowInner;
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class PresentationConnection;
|
|
||||||
class PresentationConnectionList;
|
|
||||||
class Promise;
|
|
||||||
|
|
||||||
class PresentationReceiver final : public nsIPresentationRespondingListener
|
|
||||||
, public nsWrapperCache
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PresentationReceiver)
|
|
||||||
NS_DECL_NSIPRESENTATIONRESPONDINGLISTENER
|
|
||||||
|
|
||||||
static already_AddRefed<PresentationReceiver> Create(nsPIDOMWindowInner* aWindow);
|
|
||||||
|
|
||||||
virtual JSObject* WrapObject(JSContext* aCx,
|
|
||||||
JS::Handle<JSObject*> aGivenProto) override;
|
|
||||||
|
|
||||||
nsPIDOMWindowInner* GetParentObject() const
|
|
||||||
{
|
|
||||||
return mOwner;
|
|
||||||
}
|
|
||||||
|
|
||||||
// WebIDL (public APIs)
|
|
||||||
already_AddRefed<Promise> GetConnectionList(ErrorResult& aRv);
|
|
||||||
|
|
||||||
private:
|
|
||||||
explicit PresentationReceiver(nsPIDOMWindowInner* aWindow);
|
|
||||||
|
|
||||||
virtual ~PresentationReceiver();
|
|
||||||
|
|
||||||
MOZ_IS_CLASS_INIT bool Init();
|
|
||||||
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
void CreateConnectionList();
|
|
||||||
|
|
||||||
// Store the inner window ID for |UnregisterRespondingListener| call in
|
|
||||||
// |Shutdown| since the inner window may not exist at that moment.
|
|
||||||
uint64_t mWindowId;
|
|
||||||
|
|
||||||
nsCOMPtr<nsPIDOMWindowInner> mOwner;
|
|
||||||
nsString mUrl;
|
|
||||||
RefPtr<Promise> mGetConnectionListPromise;
|
|
||||||
RefPtr<PresentationConnectionList> mConnectionList;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationReceiver_h
|
|
|
@ -1,563 +0,0 @@
|
||||||
/* -*- 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 "PresentationRequest.h"
|
|
||||||
|
|
||||||
#include "AvailabilityCollection.h"
|
|
||||||
#include "ControllerConnectionCollection.h"
|
|
||||||
#include "mozilla/BasePrincipal.h"
|
|
||||||
#include "mozilla/dom/Navigator.h"
|
|
||||||
#include "mozilla/dom/PresentationRequestBinding.h"
|
|
||||||
#include "mozilla/dom/PresentationConnectionAvailableEvent.h"
|
|
||||||
#include "mozilla/dom/Promise.h"
|
|
||||||
#include "mozilla/Move.h"
|
|
||||||
#include "mozIThirdPartyUtil.h"
|
|
||||||
#include "nsContentSecurityManager.h"
|
|
||||||
#include "nsCycleCollectionParticipant.h"
|
|
||||||
#include "nsGlobalWindow.h"
|
|
||||||
#include "nsIDocument.h"
|
|
||||||
#include "nsIPresentationService.h"
|
|
||||||
#include "nsIURI.h"
|
|
||||||
#include "nsIUUIDGenerator.h"
|
|
||||||
#include "nsNetUtil.h"
|
|
||||||
#include "nsSandboxFlags.h"
|
|
||||||
#include "nsServiceManagerUtils.h"
|
|
||||||
#include "Presentation.h"
|
|
||||||
#include "PresentationAvailability.h"
|
|
||||||
#include "PresentationCallbacks.h"
|
|
||||||
#include "PresentationLog.h"
|
|
||||||
#include "PresentationTransportBuilderConstructor.h"
|
|
||||||
|
|
||||||
using namespace mozilla;
|
|
||||||
using namespace mozilla::dom;
|
|
||||||
|
|
||||||
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,
|
|
||||||
nsIURI* aBaseUri,
|
|
||||||
nsIDocument* aDocument,
|
|
||||||
nsAString& aAbsoluteUrl)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIURI> uri;
|
|
||||||
nsresult rv = NS_NewURI(getter_AddRefs(uri),
|
|
||||||
aUrl,
|
|
||||||
aDocument ? aDocument->GetDocumentCharacterSet().get()
|
|
||||||
: nullptr,
|
|
||||||
aBaseUri);
|
|
||||||
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsAutoCString spec;
|
|
||||||
uri->GetSpec(spec);
|
|
||||||
|
|
||||||
aAbsoluteUrl = NS_ConvertUTF8toUTF16(spec);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */ already_AddRefed<PresentationRequest>
|
|
||||||
PresentationRequest::Constructor(const GlobalObject& aGlobal,
|
|
||||||
const nsAString& aUrl,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
Sequence<nsString> urls;
|
|
||||||
urls.AppendElement(aUrl, fallible);
|
|
||||||
return Constructor(aGlobal, urls, aRv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */ already_AddRefed<PresentationRequest>
|
|
||||||
PresentationRequest::Constructor(const GlobalObject& aGlobal,
|
|
||||||
const Sequence<nsString>& aUrls,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
|
|
||||||
if (!window) {
|
|
||||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aUrls.IsEmpty()) {
|
|
||||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve relative URL to absolute URL
|
|
||||||
nsCOMPtr<nsIURI> baseUri = window->GetDocBaseURI();
|
|
||||||
nsTArray<nsString> urls;
|
|
||||||
for (const auto& url : aUrls) {
|
|
||||||
nsAutoString absoluteUrl;
|
|
||||||
nsresult rv =
|
|
||||||
GetAbsoluteURL(url, baseUri, window->GetExtantDoc(), absoluteUrl);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
urls.AppendElement(absoluteUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<PresentationRequest> request =
|
|
||||||
new PresentationRequest(window, Move(urls));
|
|
||||||
return NS_WARN_IF(!request->Init()) ? nullptr : request.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationRequest::PresentationRequest(nsPIDOMWindowInner* aWindow,
|
|
||||||
nsTArray<nsString>&& aUrls)
|
|
||||||
: DOMEventTargetHelper(aWindow)
|
|
||||||
, mUrls(Move(aUrls))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationRequest::~PresentationRequest()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationRequest::Init()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual */ JSObject*
|
|
||||||
PresentationRequest::WrapObject(JSContext* aCx,
|
|
||||||
JS::Handle<JSObject*> aGivenProto)
|
|
||||||
{
|
|
||||||
return PresentationRequestBinding::Wrap(aCx, this, aGivenProto);
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<Promise>
|
|
||||||
PresentationRequest::Start(ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
return StartWithDevice(NullString(), aRv);
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<Promise>
|
|
||||||
PresentationRequest::StartWithDevice(const nsAString& aDeviceId,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
|
|
||||||
if (NS_WARN_IF(!global)) {
|
|
||||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the origin.
|
|
||||||
nsAutoString origin;
|
|
||||||
nsresult rv = nsContentUtils::GetUTFOrigin(global->PrincipalOrNull(), origin);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
aRv.Throw(rv);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDocument> doc = GetOwner()->GetExtantDoc();
|
|
||||||
if (NS_WARN_IF(!doc)) {
|
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
return promise.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<Navigator> navigator =
|
|
||||||
nsGlobalWindow::Cast(GetOwner())->GetNavigator(aRv);
|
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<Presentation> presentation = navigator->GetPresentation(aRv);
|
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (presentation->IsStartSessionUnsettled()) {
|
|
||||||
promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
|
|
||||||
return promise.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a session ID.
|
|
||||||
nsCOMPtr<nsIUUIDGenerator> uuidgen =
|
|
||||||
do_GetService("@mozilla.org/uuid-generator;1");
|
|
||||||
if(NS_WARN_IF(!uuidgen)) {
|
|
||||||
promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
|
|
||||||
return promise.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
nsID uuid;
|
|
||||||
uuidgen->GenerateUUIDInPlace(&uuid);
|
|
||||||
char buffer[NSID_LENGTH];
|
|
||||||
uuid.ToProvidedString(buffer);
|
|
||||||
nsAutoString id;
|
|
||||||
CopyASCIItoUTF16(buffer, id);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
if(NS_WARN_IF(!service)) {
|
|
||||||
promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
|
|
||||||
return promise.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
presentation->SetStartSessionUnsettled(true);
|
|
||||||
|
|
||||||
// Get xul:browser element in parent process or nsWindowRoot object in child
|
|
||||||
// process. If it's in child process, the corresponding xul:browser element
|
|
||||||
// will be obtained at PresentationRequestParent::DoRequest in its parent
|
|
||||||
// process.
|
|
||||||
nsCOMPtr<nsIDOMEventTarget> handler =
|
|
||||||
do_QueryInterface(GetOwner()->GetChromeEventHandler());
|
|
||||||
nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
|
|
||||||
nsCOMPtr<nsIPresentationServiceCallback> callback =
|
|
||||||
new PresentationRequesterCallback(this, id, promise);
|
|
||||||
nsCOMPtr<nsIPresentationTransportBuilderConstructor> constructor =
|
|
||||||
PresentationTransportBuilderConstructor::Create();
|
|
||||||
rv = service->StartSession(mUrls,
|
|
||||||
id,
|
|
||||||
origin,
|
|
||||||
aDeviceId,
|
|
||||||
GetOwner()->WindowID(),
|
|
||||||
handler,
|
|
||||||
principal,
|
|
||||||
callback,
|
|
||||||
constructor);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
|
|
||||||
NotifyPromiseSettled();
|
|
||||||
}
|
|
||||||
|
|
||||||
return promise.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<Promise>
|
|
||||||
PresentationRequest::Reconnect(const nsAString& aPresentationId,
|
|
||||||
ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
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)) {
|
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
return promise.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
nsString presentationId = nsString(aPresentationId);
|
|
||||||
nsCOMPtr<nsIRunnable> r =
|
|
||||||
NewRunnableMethod<nsString, RefPtr<Promise>>(
|
|
||||||
this,
|
|
||||||
&PresentationRequest::FindOrCreatePresentationConnection,
|
|
||||||
presentationId,
|
|
||||||
promise);
|
|
||||||
|
|
||||||
if (NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(r)))) {
|
|
||||||
promise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
return promise.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationRequest::FindOrCreatePresentationConnection(
|
|
||||||
const nsAString& aPresentationId,
|
|
||||||
Promise* aPromise)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aPromise);
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!GetOwner())) {
|
|
||||||
aPromise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<PresentationConnection> connection =
|
|
||||||
ControllerConnectionCollection::GetSingleton()->FindConnection(
|
|
||||||
GetOwner()->WindowID(),
|
|
||||||
aPresentationId,
|
|
||||||
nsIPresentationService::ROLE_CONTROLLER);
|
|
||||||
|
|
||||||
if (connection) {
|
|
||||||
nsAutoString url;
|
|
||||||
connection->GetUrl(url);
|
|
||||||
if (mUrls.Contains(url)) {
|
|
||||||
switch (connection->State()) {
|
|
||||||
case PresentationConnectionState::Closed:
|
|
||||||
// We found the matched connection.
|
|
||||||
break;
|
|
||||||
case PresentationConnectionState::Connecting:
|
|
||||||
case PresentationConnectionState::Connected:
|
|
||||||
aPromise->MaybeResolve(connection);
|
|
||||||
return;
|
|
||||||
case PresentationConnectionState::Terminated:
|
|
||||||
// A terminated connection cannot be reused.
|
|
||||||
connection = nullptr;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
MOZ_CRASH("Unknown presentation session state.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
connection = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
if(NS_WARN_IF(!service)) {
|
|
||||||
aPromise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationServiceCallback> callback =
|
|
||||||
new PresentationReconnectCallback(this,
|
|
||||||
aPresentationId,
|
|
||||||
aPromise,
|
|
||||||
connection);
|
|
||||||
|
|
||||||
nsresult rv =
|
|
||||||
service->ReconnectSession(mUrls,
|
|
||||||
aPresentationId,
|
|
||||||
nsIPresentationService::ROLE_CONTROLLER,
|
|
||||||
callback);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
aPromise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<Promise>
|
|
||||||
PresentationRequest::GetAvailability(ErrorResult& aRv)
|
|
||||||
{
|
|
||||||
PRES_DEBUG("%s\n", __func__);
|
|
||||||
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)) {
|
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
|
||||||
if (NS_WARN_IF(aRv.Failed())) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
return promise.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
FindOrCreatePresentationAvailability(promise);
|
|
||||||
|
|
||||||
return promise.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationRequest::FindOrCreatePresentationAvailability(RefPtr<Promise>& aPromise)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aPromise);
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!GetOwner())) {
|
|
||||||
aPromise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AvailabilityCollection* collection = AvailabilityCollection::GetSingleton();
|
|
||||||
if (NS_WARN_IF(!collection)) {
|
|
||||||
aPromise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<PresentationAvailability> availability =
|
|
||||||
collection->Find(GetOwner()->WindowID(), mUrls);
|
|
||||||
|
|
||||||
if (!availability) {
|
|
||||||
availability = PresentationAvailability::Create(GetOwner(), mUrls, aPromise);
|
|
||||||
} else {
|
|
||||||
PRES_DEBUG(">resolve with same object\n");
|
|
||||||
|
|
||||||
// Fetching cached available devices is asynchronous in our implementation,
|
|
||||||
// we need to ensure the promise is resolved in order.
|
|
||||||
if (availability->IsCachedValueReady()) {
|
|
||||||
aPromise->MaybeResolve(availability);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
availability->EnqueuePromise(aPromise);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!availability) {
|
|
||||||
aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationRequest::DispatchConnectionAvailableEvent(PresentationConnection* aConnection)
|
|
||||||
{
|
|
||||||
PresentationConnectionAvailableEventInit init;
|
|
||||||
init.mConnection = aConnection;
|
|
||||||
|
|
||||||
RefPtr<PresentationConnectionAvailableEvent> event =
|
|
||||||
PresentationConnectionAvailableEvent::Constructor(this,
|
|
||||||
NS_LITERAL_STRING("connectionavailable"),
|
|
||||||
init);
|
|
||||||
if (NS_WARN_IF(!event)) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
event->SetTrusted(true);
|
|
||||||
|
|
||||||
RefPtr<AsyncEventDispatcher> asyncDispatcher =
|
|
||||||
new AsyncEventDispatcher(this, event);
|
|
||||||
return asyncDispatcher->PostDOMEvent();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationRequest::NotifyPromiseSettled()
|
|
||||||
{
|
|
||||||
PRES_DEBUG("%s\n", __func__);
|
|
||||||
|
|
||||||
if (!GetOwner()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorResult rv;
|
|
||||||
RefPtr<Navigator> navigator =
|
|
||||||
nsGlobalWindow::Cast(GetOwner())->GetNavigator(rv);
|
|
||||||
if (!navigator) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<Presentation> presentation = navigator->GetPresentation(rv);
|
|
||||||
|
|
||||||
if (presentation) {
|
|
||||||
presentation->SetStartSessionUnsettled(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationRequest::IsProhibitMixedSecurityContexts(nsIDocument* aDocument)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aDocument);
|
|
||||||
|
|
||||||
if (nsContentUtils::IsChromeDoc(aDocument)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDocument> doc = aDocument;
|
|
||||||
while (doc && !nsContentUtils::IsChromeDoc(doc)) {
|
|
||||||
if (nsContentUtils::HttpsStateIsModern(doc)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
doc = doc->GetParentDocument();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationRequest::IsPrioriAuthenticatedURL(const nsAString& aUrl)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIURI> uri;
|
|
||||||
if (NS_FAILED(NS_NewURI(getter_AddRefs(uri), aUrl))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsAutoCString scheme;
|
|
||||||
nsresult rv = uri->GetScheme(scheme);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scheme.EqualsLiteral("data")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsAutoCString uriSpec;
|
|
||||||
rv = uri->GetSpec(uriSpec);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uriSpec.EqualsLiteral("about:blank") ||
|
|
||||||
uriSpec.EqualsLiteral("about:srcdoc")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
PrincipalOriginAttributes attrs;
|
|
||||||
nsCOMPtr<nsIPrincipal> principal =
|
|
||||||
BasePrincipal::CreateCodebasePrincipal(uri, attrs);
|
|
||||||
if (NS_WARN_IF(!principal)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIContentSecurityManager> csm =
|
|
||||||
do_GetService(NS_CONTENTSECURITYMANAGER_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!csm)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isTrustworthyOrigin = false;
|
|
||||||
csm->IsOriginPotentiallyTrustworthy(principal, &isTrustworthyOrigin);
|
|
||||||
return isTrustworthyOrigin;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationRequest::IsAllURLAuthenticated()
|
|
||||||
{
|
|
||||||
for (const auto& url : mUrls) {
|
|
||||||
if (!IsPrioriAuthenticatedURL(url)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
/* -*- 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationRequest_h
|
|
||||||
#define mozilla_dom_PresentationRequest_h
|
|
||||||
|
|
||||||
#include "mozilla/dom/BindingDeclarations.h"
|
|
||||||
#include "mozilla/DOMEventTargetHelper.h"
|
|
||||||
|
|
||||||
class nsIDocument;
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class Promise;
|
|
||||||
class PresentationAvailability;
|
|
||||||
class PresentationConnection;
|
|
||||||
|
|
||||||
class PresentationRequest final : public DOMEventTargetHelper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
|
|
||||||
static already_AddRefed<PresentationRequest> Constructor(
|
|
||||||
const GlobalObject& aGlobal,
|
|
||||||
const nsAString& aUrl,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
|
|
||||||
static already_AddRefed<PresentationRequest> Constructor(
|
|
||||||
const GlobalObject& aGlobal,
|
|
||||||
const Sequence<nsString>& aUrls,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
|
|
||||||
virtual JSObject* WrapObject(JSContext* aCx,
|
|
||||||
JS::Handle<JSObject*> aGivenProto) override;
|
|
||||||
|
|
||||||
// WebIDL (public APIs)
|
|
||||||
already_AddRefed<Promise> Start(ErrorResult& aRv);
|
|
||||||
|
|
||||||
already_AddRefed<Promise> StartWithDevice(const nsAString& aDeviceId,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
|
|
||||||
already_AddRefed<Promise> Reconnect(const nsAString& aPresentationId,
|
|
||||||
ErrorResult& aRv);
|
|
||||||
|
|
||||||
already_AddRefed<Promise> GetAvailability(ErrorResult& aRv);
|
|
||||||
|
|
||||||
IMPL_EVENT_HANDLER(connectionavailable);
|
|
||||||
|
|
||||||
nsresult DispatchConnectionAvailableEvent(PresentationConnection* aConnection);
|
|
||||||
|
|
||||||
void NotifyPromiseSettled();
|
|
||||||
|
|
||||||
private:
|
|
||||||
PresentationRequest(nsPIDOMWindowInner* aWindow,
|
|
||||||
nsTArray<nsString>&& aUrls);
|
|
||||||
|
|
||||||
~PresentationRequest();
|
|
||||||
|
|
||||||
bool Init();
|
|
||||||
|
|
||||||
void FindOrCreatePresentationConnection(const nsAString& aPresentationId,
|
|
||||||
Promise* aPromise);
|
|
||||||
|
|
||||||
void FindOrCreatePresentationAvailability(RefPtr<Promise>& aPromise);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
bool IsAllURLAuthenticated();
|
|
||||||
|
|
||||||
nsTArray<nsString> mUrls;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationRequest_h
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,68 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationService_h
|
|
||||||
#define mozilla_dom_PresentationService_h
|
|
||||||
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsIObserver.h"
|
|
||||||
#include "PresentationServiceBase.h"
|
|
||||||
#include "PresentationSessionInfo.h"
|
|
||||||
|
|
||||||
class nsIPresentationSessionRequest;
|
|
||||||
class nsIPresentationTerminateRequest;
|
|
||||||
class nsIURI;
|
|
||||||
class nsIPresentationSessionTransportBuilder;
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class PresentationDeviceRequest;
|
|
||||||
class PresentationRespondingInfo;
|
|
||||||
|
|
||||||
class PresentationService final
|
|
||||||
: public nsIPresentationService
|
|
||||||
, public nsIObserver
|
|
||||||
, public PresentationServiceBase<PresentationSessionInfo>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIOBSERVER
|
|
||||||
NS_DECL_NSIPRESENTATIONSERVICE
|
|
||||||
|
|
||||||
PresentationService();
|
|
||||||
bool Init();
|
|
||||||
|
|
||||||
bool IsSessionAccessible(const nsAString& aSessionId,
|
|
||||||
const uint8_t aRole,
|
|
||||||
base::ProcessId aProcessId);
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class PresentationDeviceRequest;
|
|
||||||
|
|
||||||
virtual ~PresentationService();
|
|
||||||
void HandleShutdown();
|
|
||||||
nsresult HandleDeviceAdded(nsIPresentationDevice* aDevice);
|
|
||||||
nsresult HandleDeviceRemoved();
|
|
||||||
nsresult HandleSessionRequest(nsIPresentationSessionRequest* aRequest);
|
|
||||||
nsresult HandleTerminateRequest(nsIPresentationTerminateRequest* aRequest);
|
|
||||||
nsresult HandleReconnectRequest(nsIPresentationSessionRequest* aRequest);
|
|
||||||
|
|
||||||
// This is meant to be called by PresentationDeviceRequest.
|
|
||||||
already_AddRefed<PresentationSessionInfo>
|
|
||||||
CreateControllingSessionInfo(const nsAString& aUrl,
|
|
||||||
const nsAString& aSessionId,
|
|
||||||
uint64_t aWindowId);
|
|
||||||
|
|
||||||
// Emumerate all devices to get the availability of each input Urls.
|
|
||||||
nsresult UpdateAvailabilityUrlChange(
|
|
||||||
const nsTArray<nsString>& aAvailabilityUrls);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationService_h
|
|
|
@ -1,401 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationServiceBase_h
|
|
||||||
#define mozilla_dom_PresentationServiceBase_h
|
|
||||||
|
|
||||||
#include "mozilla/Unused.h"
|
|
||||||
#include "nsClassHashtable.h"
|
|
||||||
#include "nsCOMArray.h"
|
|
||||||
#include "nsIPresentationListener.h"
|
|
||||||
#include "nsIPresentationService.h"
|
|
||||||
#include "nsRefPtrHashtable.h"
|
|
||||||
#include "nsString.h"
|
|
||||||
#include "nsTArray.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class PresentationServiceBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PresentationServiceBase() = default;
|
|
||||||
|
|
||||||
already_AddRefed<T>
|
|
||||||
GetSessionInfo(const nsAString& aSessionId, const uint8_t aRole)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
|
|
||||||
aRole == nsIPresentationService::ROLE_RECEIVER);
|
|
||||||
|
|
||||||
RefPtr<T> info;
|
|
||||||
if (aRole == nsIPresentationService::ROLE_CONTROLLER) {
|
|
||||||
return mSessionInfoAtController.Get(aSessionId, getter_AddRefs(info)) ?
|
|
||||||
info.forget() : nullptr;
|
|
||||||
} else {
|
|
||||||
return mSessionInfoAtReceiver.Get(aSessionId, getter_AddRefs(info)) ?
|
|
||||||
info.forget() : nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class SessionIdManager final
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit SessionIdManager()
|
|
||||||
{
|
|
||||||
MOZ_COUNT_CTOR(SessionIdManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
~SessionIdManager()
|
|
||||||
{
|
|
||||||
MOZ_COUNT_DTOR(SessionIdManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult GetWindowId(const nsAString& aSessionId, uint64_t* aWindowId)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (mRespondingWindowIds.Get(aSessionId, aWindowId)) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult GetSessionIds(uint64_t aWindowId, nsTArray<nsString>& aSessionIds)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
nsTArray<nsString>* sessionIdArray;
|
|
||||||
if (!mRespondingSessionIds.Get(aWindowId, &sessionIdArray)) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
aSessionIds.Assign(*sessionIdArray);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddSessionId(uint64_t aWindowId, const nsAString& aSessionId)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (NS_WARN_IF(aWindowId == 0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsTArray<nsString>* sessionIdArray;
|
|
||||||
if (!mRespondingSessionIds.Get(aWindowId, &sessionIdArray)) {
|
|
||||||
sessionIdArray = new nsTArray<nsString>();
|
|
||||||
mRespondingSessionIds.Put(aWindowId, sessionIdArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
sessionIdArray->AppendElement(nsString(aSessionId));
|
|
||||||
mRespondingWindowIds.Put(aSessionId, aWindowId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveSessionId(const nsAString& aSessionId)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
uint64_t windowId = 0;
|
|
||||||
if (mRespondingWindowIds.Get(aSessionId, &windowId)) {
|
|
||||||
mRespondingWindowIds.Remove(aSessionId);
|
|
||||||
nsTArray<nsString>* sessionIdArray;
|
|
||||||
if (mRespondingSessionIds.Get(windowId, &sessionIdArray)) {
|
|
||||||
sessionIdArray->RemoveElement(nsString(aSessionId));
|
|
||||||
if (sessionIdArray->IsEmpty()) {
|
|
||||||
mRespondingSessionIds.Remove(windowId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult UpdateWindowId(const nsAString& aSessionId, const uint64_t aWindowId)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
RemoveSessionId(aSessionId);
|
|
||||||
AddSessionId(aWindowId, aSessionId);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
mRespondingSessionIds.Clear();
|
|
||||||
mRespondingWindowIds.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
nsClassHashtable<nsUint64HashKey, nsTArray<nsString>> mRespondingSessionIds;
|
|
||||||
nsDataHashtable<nsStringHashKey, uint64_t> mRespondingWindowIds;
|
|
||||||
};
|
|
||||||
|
|
||||||
class AvailabilityManager final
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit AvailabilityManager()
|
|
||||||
{
|
|
||||||
MOZ_COUNT_CTOR(AvailabilityManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
~AvailabilityManager()
|
|
||||||
{
|
|
||||||
MOZ_COUNT_DTOR(AvailabilityManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddAvailabilityListener(
|
|
||||||
const nsTArray<nsString>& aAvailabilityUrls,
|
|
||||||
nsIPresentationAvailabilityListener* aListener)
|
|
||||||
{
|
|
||||||
nsTArray<nsString> dummy;
|
|
||||||
AddAvailabilityListener(aAvailabilityUrls, aListener, dummy);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddAvailabilityListener(
|
|
||||||
const nsTArray<nsString>& aAvailabilityUrls,
|
|
||||||
nsIPresentationAvailabilityListener* aListener,
|
|
||||||
nsTArray<nsString>& aAddedUrls)
|
|
||||||
{
|
|
||||||
if (!aListener) {
|
|
||||||
MOZ_ASSERT(false, "aListener should not be null.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aAvailabilityUrls.IsEmpty()) {
|
|
||||||
MOZ_ASSERT(false, "aAvailabilityUrls should not be empty.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
aAddedUrls.Clear();
|
|
||||||
nsTArray<nsString> knownAvailableUrls;
|
|
||||||
for (const auto& url : aAvailabilityUrls) {
|
|
||||||
AvailabilityEntry* entry;
|
|
||||||
if (!mAvailabilityUrlTable.Get(url, &entry)) {
|
|
||||||
entry = new AvailabilityEntry();
|
|
||||||
mAvailabilityUrlTable.Put(url, entry);
|
|
||||||
aAddedUrls.AppendElement(url);
|
|
||||||
}
|
|
||||||
if (!entry->mListeners.Contains(aListener)) {
|
|
||||||
entry->mListeners.AppendElement(aListener);
|
|
||||||
}
|
|
||||||
if (entry->mAvailable) {
|
|
||||||
knownAvailableUrls.AppendElement(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!knownAvailableUrls.IsEmpty()) {
|
|
||||||
Unused <<
|
|
||||||
NS_WARN_IF(
|
|
||||||
NS_FAILED(aListener->NotifyAvailableChange(knownAvailableUrls,
|
|
||||||
true)));
|
|
||||||
} else {
|
|
||||||
// If we can't find any known available url and there is no newly
|
|
||||||
// added url, we still need to notify the listener of the result.
|
|
||||||
// So, the promise returned by |getAvailability| can be resolved.
|
|
||||||
if (aAddedUrls.IsEmpty()) {
|
|
||||||
Unused <<
|
|
||||||
NS_WARN_IF(
|
|
||||||
NS_FAILED(aListener->NotifyAvailableChange(aAvailabilityUrls,
|
|
||||||
false)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveAvailabilityListener(
|
|
||||||
const nsTArray<nsString>& aAvailabilityUrls,
|
|
||||||
nsIPresentationAvailabilityListener* aListener)
|
|
||||||
{
|
|
||||||
nsTArray<nsString> dummy;
|
|
||||||
RemoveAvailabilityListener(aAvailabilityUrls, aListener, dummy);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveAvailabilityListener(
|
|
||||||
const nsTArray<nsString>& aAvailabilityUrls,
|
|
||||||
nsIPresentationAvailabilityListener* aListener,
|
|
||||||
nsTArray<nsString>& aRemovedUrls)
|
|
||||||
{
|
|
||||||
if (!aListener) {
|
|
||||||
MOZ_ASSERT(false, "aListener should not be null.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aAvailabilityUrls.IsEmpty()) {
|
|
||||||
MOZ_ASSERT(false, "aAvailabilityUrls should not be empty.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
aRemovedUrls.Clear();
|
|
||||||
for (const auto& url : aAvailabilityUrls) {
|
|
||||||
AvailabilityEntry* entry;
|
|
||||||
if (mAvailabilityUrlTable.Get(url, &entry)) {
|
|
||||||
entry->mListeners.RemoveElement(aListener);
|
|
||||||
if (entry->mListeners.IsEmpty()) {
|
|
||||||
mAvailabilityUrlTable.Remove(url);
|
|
||||||
aRemovedUrls.AppendElement(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult DoNotifyAvailableChange(const nsTArray<nsString>& aAvailabilityUrls,
|
|
||||||
bool aAvailable)
|
|
||||||
{
|
|
||||||
typedef nsClassHashtable<nsISupportsHashKey,
|
|
||||||
nsTArray<nsString>> ListenerToUrlsMap;
|
|
||||||
ListenerToUrlsMap availabilityListenerTable;
|
|
||||||
// Create a mapping from nsIPresentationAvailabilityListener to
|
|
||||||
// availabilityUrls.
|
|
||||||
for (auto it = mAvailabilityUrlTable.ConstIter(); !it.Done(); it.Next()) {
|
|
||||||
if (aAvailabilityUrls.Contains(it.Key())) {
|
|
||||||
AvailabilityEntry* entry = it.UserData();
|
|
||||||
entry->mAvailable = aAvailable;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < entry->mListeners.Length(); ++i) {
|
|
||||||
nsIPresentationAvailabilityListener* listener =
|
|
||||||
entry->mListeners.ObjectAt(i);
|
|
||||||
nsTArray<nsString>* urlArray;
|
|
||||||
if (!availabilityListenerTable.Get(listener, &urlArray)) {
|
|
||||||
urlArray = new nsTArray<nsString>();
|
|
||||||
availabilityListenerTable.Put(listener, urlArray);
|
|
||||||
}
|
|
||||||
urlArray->AppendElement(it.Key());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto it = availabilityListenerTable.Iter(); !it.Done(); it.Next()) {
|
|
||||||
auto listener =
|
|
||||||
static_cast<nsIPresentationAvailabilityListener*>(it.Key());
|
|
||||||
|
|
||||||
Unused <<
|
|
||||||
NS_WARN_IF(NS_FAILED(listener->NotifyAvailableChange(*it.UserData(),
|
|
||||||
aAvailable)));
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetAvailbilityUrlByAvailability(nsTArray<nsString>& aOutArray,
|
|
||||||
bool aAvailable)
|
|
||||||
{
|
|
||||||
aOutArray.Clear();
|
|
||||||
|
|
||||||
for (auto it = mAvailabilityUrlTable.ConstIter(); !it.Done(); it.Next()) {
|
|
||||||
if (it.UserData()->mAvailable == aAvailable) {
|
|
||||||
aOutArray.AppendElement(it.Key());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
mAvailabilityUrlTable.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct AvailabilityEntry
|
|
||||||
{
|
|
||||||
explicit AvailabilityEntry()
|
|
||||||
: mAvailable(false)
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool mAvailable;
|
|
||||||
nsCOMArray<nsIPresentationAvailabilityListener> mListeners;
|
|
||||||
};
|
|
||||||
|
|
||||||
nsClassHashtable<nsStringHashKey, AvailabilityEntry> mAvailabilityUrlTable;
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual ~PresentationServiceBase() = default;
|
|
||||||
|
|
||||||
void Shutdown()
|
|
||||||
{
|
|
||||||
mRespondingListeners.Clear();
|
|
||||||
mControllerSessionIdManager.Clear();
|
|
||||||
mReceiverSessionIdManager.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult GetWindowIdBySessionIdInternal(const nsAString& aSessionId,
|
|
||||||
uint8_t aRole,
|
|
||||||
uint64_t* aWindowId)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
|
|
||||||
aRole == nsIPresentationService::ROLE_RECEIVER);
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!aWindowId)) {
|
|
||||||
return NS_ERROR_INVALID_POINTER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aRole == nsIPresentationService::ROLE_CONTROLLER) {
|
|
||||||
return mControllerSessionIdManager.GetWindowId(aSessionId, aWindowId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mReceiverSessionIdManager.GetWindowId(aSessionId, aWindowId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddRespondingSessionId(uint64_t aWindowId,
|
|
||||||
const nsAString& aSessionId,
|
|
||||||
uint8_t aRole)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
|
|
||||||
aRole == nsIPresentationService::ROLE_RECEIVER);
|
|
||||||
|
|
||||||
if (aRole == nsIPresentationService::ROLE_CONTROLLER) {
|
|
||||||
mControllerSessionIdManager.AddSessionId(aWindowId, aSessionId);
|
|
||||||
} else {
|
|
||||||
mReceiverSessionIdManager.AddSessionId(aWindowId, aSessionId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveRespondingSessionId(const nsAString& aSessionId,
|
|
||||||
uint8_t aRole)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
|
|
||||||
aRole == nsIPresentationService::ROLE_RECEIVER);
|
|
||||||
|
|
||||||
if (aRole == nsIPresentationService::ROLE_CONTROLLER) {
|
|
||||||
mControllerSessionIdManager.RemoveSessionId(aSessionId);
|
|
||||||
} else {
|
|
||||||
mReceiverSessionIdManager.RemoveSessionId(aSessionId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult UpdateWindowIdBySessionIdInternal(const nsAString& aSessionId,
|
|
||||||
uint8_t aRole,
|
|
||||||
const uint64_t aWindowId)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
|
|
||||||
aRole == nsIPresentationService::ROLE_RECEIVER);
|
|
||||||
|
|
||||||
if (aRole == nsIPresentationService::ROLE_CONTROLLER) {
|
|
||||||
return mControllerSessionIdManager.UpdateWindowId(aSessionId, aWindowId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mReceiverSessionIdManager.UpdateWindowId(aSessionId, aWindowId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the responding listener based on the window ID of the (in-process or
|
|
||||||
// OOP) receiver page.
|
|
||||||
nsRefPtrHashtable<nsUint64HashKey, nsIPresentationRespondingListener>
|
|
||||||
mRespondingListeners;
|
|
||||||
|
|
||||||
// Store the mapping between the window ID of the in-process and OOP page and the ID
|
|
||||||
// of the responding session. It's used for both controller and receiver page
|
|
||||||
// to retrieve the correspondent session ID. Besides, also keep the mapping
|
|
||||||
// between the responding session ID and the window ID to help look up the
|
|
||||||
// window ID.
|
|
||||||
SessionIdManager mControllerSessionIdManager;
|
|
||||||
SessionIdManager mReceiverSessionIdManager;
|
|
||||||
|
|
||||||
nsRefPtrHashtable<nsStringHashKey, T> mSessionInfoAtController;
|
|
||||||
nsRefPtrHashtable<nsStringHashKey, T> mSessionInfoAtReceiver;
|
|
||||||
|
|
||||||
AvailabilityManager mAvailabilityManager;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationServiceBase_h
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,304 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationSessionInfo_h
|
|
||||||
#define mozilla_dom_PresentationSessionInfo_h
|
|
||||||
|
|
||||||
#include "base/process.h"
|
|
||||||
#include "mozilla/dom/nsIContentParent.h"
|
|
||||||
#include "mozilla/dom/Promise.h"
|
|
||||||
#include "mozilla/dom/PromiseNativeHandler.h"
|
|
||||||
#include "mozilla/DebugOnly.h"
|
|
||||||
#include "mozilla/RefPtr.h"
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsINetworkInfoService.h"
|
|
||||||
#include "nsIPresentationControlChannel.h"
|
|
||||||
#include "nsIPresentationDevice.h"
|
|
||||||
#include "nsIPresentationListener.h"
|
|
||||||
#include "nsIPresentationService.h"
|
|
||||||
#include "nsIPresentationSessionTransport.h"
|
|
||||||
#include "nsIPresentationSessionTransportBuilder.h"
|
|
||||||
#include "nsIServerSocket.h"
|
|
||||||
#include "nsITimer.h"
|
|
||||||
#include "nsString.h"
|
|
||||||
#include "PresentationCallbacks.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class PresentationSessionInfo : public nsIPresentationSessionTransportCallback
|
|
||||||
, public nsIPresentationControlChannelListener
|
|
||||||
, public nsIPresentationSessionTransportBuilderListener
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIPRESENTATIONSESSIONTRANSPORTCALLBACK
|
|
||||||
NS_DECL_NSIPRESENTATIONSESSIONTRANSPORTBUILDERLISTENER
|
|
||||||
|
|
||||||
PresentationSessionInfo(const nsAString& aUrl,
|
|
||||||
const nsAString& aSessionId,
|
|
||||||
const uint8_t aRole)
|
|
||||||
: mUrl(aUrl)
|
|
||||||
, mSessionId(aSessionId)
|
|
||||||
, mIsResponderReady(false)
|
|
||||||
, mIsTransportReady(false)
|
|
||||||
, mState(nsIPresentationSessionListener::STATE_CONNECTING)
|
|
||||||
, mReason(NS_OK)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(!mUrl.IsEmpty());
|
|
||||||
MOZ_ASSERT(!mSessionId.IsEmpty());
|
|
||||||
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
|
|
||||||
aRole == nsIPresentationService::ROLE_RECEIVER);
|
|
||||||
mRole = aRole;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual nsresult Init(nsIPresentationControlChannel* aControlChannel);
|
|
||||||
|
|
||||||
const nsAString& GetUrl() const
|
|
||||||
{
|
|
||||||
return mUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nsAString& GetSessionId() const
|
|
||||||
{
|
|
||||||
return mSessionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t GetRole() const
|
|
||||||
{
|
|
||||||
return mRole;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult SetListener(nsIPresentationSessionListener* aListener);
|
|
||||||
|
|
||||||
void SetDevice(nsIPresentationDevice* aDevice)
|
|
||||||
{
|
|
||||||
mDevice = aDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<nsIPresentationDevice> GetDevice() const
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIPresentationDevice> device = mDevice;
|
|
||||||
return device.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetControlChannel(nsIPresentationControlChannel* aControlChannel)
|
|
||||||
{
|
|
||||||
if (mControlChannel) {
|
|
||||||
mControlChannel->SetListener(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
mControlChannel = aControlChannel;
|
|
||||||
if (mControlChannel) {
|
|
||||||
mControlChannel->SetListener(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult Send(const nsAString& aData);
|
|
||||||
|
|
||||||
nsresult SendBinaryMsg(const nsACString& aData);
|
|
||||||
|
|
||||||
nsresult SendBlob(nsIDOMBlob* aBlob);
|
|
||||||
|
|
||||||
nsresult Close(nsresult aReason,
|
|
||||||
uint32_t aState);
|
|
||||||
|
|
||||||
nsresult OnTerminate(nsIPresentationControlChannel* aControlChannel);
|
|
||||||
|
|
||||||
nsresult ReplyError(nsresult aReason);
|
|
||||||
|
|
||||||
virtual bool IsAccessible(base::ProcessId aProcessId);
|
|
||||||
|
|
||||||
void SetTransportBuilderConstructor(
|
|
||||||
nsIPresentationTransportBuilderConstructor* aBuilderConstructor)
|
|
||||||
{
|
|
||||||
mBuilderConstructor = aBuilderConstructor;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual ~PresentationSessionInfo()
|
|
||||||
{
|
|
||||||
Shutdown(NS_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Shutdown(nsresult aReason);
|
|
||||||
|
|
||||||
nsresult ReplySuccess();
|
|
||||||
|
|
||||||
bool IsSessionReady()
|
|
||||||
{
|
|
||||||
return mIsResponderReady && mIsTransportReady;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual nsresult UntrackFromService();
|
|
||||||
|
|
||||||
void SetStateWithReason(uint32_t aState, nsresult aReason)
|
|
||||||
{
|
|
||||||
if (mState == aState) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mState = aState;
|
|
||||||
mReason = aReason;
|
|
||||||
|
|
||||||
// Notify session state change.
|
|
||||||
if (mListener) {
|
|
||||||
DebugOnly<nsresult> rv =
|
|
||||||
mListener->NotifyStateChange(mSessionId, mState, aReason);
|
|
||||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "NotifyStateChanged");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ContinueTermination();
|
|
||||||
|
|
||||||
void ResetBuilder()
|
|
||||||
{
|
|
||||||
mBuilder = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should be nsIPresentationChannelDescription::TYPE_TCP/TYPE_DATACHANNEL
|
|
||||||
uint8_t mTransportType = 0;
|
|
||||||
|
|
||||||
nsPIDOMWindowInner* GetWindow();
|
|
||||||
|
|
||||||
nsString mUrl;
|
|
||||||
nsString mSessionId;
|
|
||||||
// mRole should be nsIPresentationService::ROLE_CONTROLLER
|
|
||||||
// or nsIPresentationService::ROLE_RECEIVER.
|
|
||||||
uint8_t mRole;
|
|
||||||
bool mIsResponderReady;
|
|
||||||
bool mIsTransportReady;
|
|
||||||
bool mIsOnTerminating = false;
|
|
||||||
uint32_t mState; // CONNECTED, CLOSED, TERMINATED
|
|
||||||
nsresult mReason;
|
|
||||||
nsCOMPtr<nsIPresentationSessionListener> mListener;
|
|
||||||
nsCOMPtr<nsIPresentationDevice> mDevice;
|
|
||||||
nsCOMPtr<nsIPresentationSessionTransport> mTransport;
|
|
||||||
nsCOMPtr<nsIPresentationControlChannel> mControlChannel;
|
|
||||||
nsCOMPtr<nsIPresentationSessionTransportBuilder> mBuilder;
|
|
||||||
nsCOMPtr<nsIPresentationTransportBuilderConstructor> mBuilderConstructor;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Session info with controlling browsing context (sender side) behaviors.
|
|
||||||
class PresentationControllingInfo final : public PresentationSessionInfo
|
|
||||||
, public nsIServerSocketListener
|
|
||||||
, public nsIListNetworkAddressesListener
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
NS_DECL_NSIPRESENTATIONCONTROLCHANNELLISTENER
|
|
||||||
NS_DECL_NSISERVERSOCKETLISTENER
|
|
||||||
NS_DECL_NSILISTNETWORKADDRESSESLISTENER
|
|
||||||
NS_DECL_NSIPRESENTATIONSESSIONTRANSPORTCALLBACK
|
|
||||||
|
|
||||||
PresentationControllingInfo(const nsAString& aUrl,
|
|
||||||
const nsAString& aSessionId)
|
|
||||||
: PresentationSessionInfo(aUrl,
|
|
||||||
aSessionId,
|
|
||||||
nsIPresentationService::ROLE_CONTROLLER)
|
|
||||||
{}
|
|
||||||
|
|
||||||
nsresult Init(nsIPresentationControlChannel* aControlChannel) override;
|
|
||||||
|
|
||||||
nsresult Reconnect(nsIPresentationServiceCallback* aCallback);
|
|
||||||
|
|
||||||
nsresult BuildTransport();
|
|
||||||
|
|
||||||
private:
|
|
||||||
~PresentationControllingInfo()
|
|
||||||
{
|
|
||||||
Shutdown(NS_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Shutdown(nsresult aReason) override;
|
|
||||||
|
|
||||||
nsresult GetAddress();
|
|
||||||
|
|
||||||
nsresult OnGetAddress(const nsACString& aAddress);
|
|
||||||
|
|
||||||
nsresult ContinueReconnect();
|
|
||||||
|
|
||||||
nsresult NotifyReconnectResult(nsresult aStatus);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIServerSocket> mServerSocket;
|
|
||||||
nsCOMPtr<nsIPresentationServiceCallback> mReconnectCallback;
|
|
||||||
bool mIsReconnecting = false;
|
|
||||||
bool mDoReconnectAfterClose = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Session info with presenting browsing context (receiver side) behaviors.
|
|
||||||
class PresentationPresentingInfo final : public PresentationSessionInfo
|
|
||||||
, public PromiseNativeHandler
|
|
||||||
, public nsITimerCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
NS_DECL_NSIPRESENTATIONCONTROLCHANNELLISTENER
|
|
||||||
NS_DECL_NSITIMERCALLBACK
|
|
||||||
|
|
||||||
PresentationPresentingInfo(const nsAString& aUrl,
|
|
||||||
const nsAString& aSessionId,
|
|
||||||
nsIPresentationDevice* aDevice)
|
|
||||||
: PresentationSessionInfo(aUrl,
|
|
||||||
aSessionId,
|
|
||||||
nsIPresentationService::ROLE_RECEIVER)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aDevice);
|
|
||||||
SetDevice(aDevice);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult Init(nsIPresentationControlChannel* aControlChannel) override;
|
|
||||||
|
|
||||||
nsresult NotifyResponderReady();
|
|
||||||
nsresult NotifyResponderFailure();
|
|
||||||
|
|
||||||
NS_IMETHODIMP OnSessionTransport(nsIPresentationSessionTransport* transport) override;
|
|
||||||
|
|
||||||
void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
|
||||||
|
|
||||||
void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
|
||||||
|
|
||||||
void SetPromise(Promise* aPromise)
|
|
||||||
{
|
|
||||||
mPromise = aPromise;
|
|
||||||
mPromise->AppendNativeHandler(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsAccessible(base::ProcessId aProcessId) override;
|
|
||||||
|
|
||||||
nsresult DoReconnect();
|
|
||||||
|
|
||||||
private:
|
|
||||||
~PresentationPresentingInfo()
|
|
||||||
{
|
|
||||||
Shutdown(NS_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Shutdown(nsresult aReason) override;
|
|
||||||
|
|
||||||
nsresult InitTransportAndSendAnswer();
|
|
||||||
|
|
||||||
nsresult UntrackFromService() override;
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
FlushPendingEvents(nsIPresentationDataChannelSessionTransportBuilder* builder);
|
|
||||||
|
|
||||||
bool mHasFlushPendingEvents = false;
|
|
||||||
RefPtr<PresentationResponderLoadingCallback> mLoadingCallback;
|
|
||||||
nsCOMPtr<nsITimer> mTimer;
|
|
||||||
nsCOMPtr<nsIPresentationChannelDescription> mRequesterDescription;
|
|
||||||
nsTArray<nsString> mPendingCandidates;
|
|
||||||
RefPtr<Promise> mPromise;
|
|
||||||
|
|
||||||
// The content parent communicating with the content process which the OOP
|
|
||||||
// receiver page belongs to.
|
|
||||||
nsCOMPtr<nsIContentParent> mContentParent;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationSessionInfo_h
|
|
|
@ -1,72 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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 "PresentationSessionRequest.h"
|
|
||||||
#include "nsIPresentationControlChannel.h"
|
|
||||||
#include "nsIPresentationDevice.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(PresentationSessionRequest, nsIPresentationSessionRequest)
|
|
||||||
|
|
||||||
PresentationSessionRequest::PresentationSessionRequest(nsIPresentationDevice* aDevice,
|
|
||||||
const nsAString& aUrl,
|
|
||||||
const nsAString& aPresentationId,
|
|
||||||
nsIPresentationControlChannel* aControlChannel)
|
|
||||||
: mUrl(aUrl)
|
|
||||||
, mPresentationId(aPresentationId)
|
|
||||||
, mDevice(aDevice)
|
|
||||||
, mControlChannel(aControlChannel)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationSessionRequest::~PresentationSessionRequest()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsIPresentationSessionRequest
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationSessionRequest::GetDevice(nsIPresentationDevice** aRetVal)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG_POINTER(aRetVal);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationDevice> device = mDevice;
|
|
||||||
device.forget(aRetVal);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationSessionRequest::GetUrl(nsAString& aRetVal)
|
|
||||||
{
|
|
||||||
aRetVal = mUrl;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationSessionRequest::GetPresentationId(nsAString& aRetVal)
|
|
||||||
{
|
|
||||||
aRetVal = mPresentationId;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationSessionRequest::GetControlChannel(nsIPresentationControlChannel** aRetVal)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG_POINTER(aRetVal);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationControlChannel> controlChannel = mControlChannel;
|
|
||||||
controlChannel.forget(aRetVal);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,41 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationSessionRequest_h__
|
|
||||||
#define mozilla_dom_PresentationSessionRequest_h__
|
|
||||||
|
|
||||||
#include "nsIPresentationSessionRequest.h"
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsString.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class PresentationSessionRequest final : public nsIPresentationSessionRequest
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIPRESENTATIONSESSIONREQUEST
|
|
||||||
|
|
||||||
PresentationSessionRequest(nsIPresentationDevice* aDevice,
|
|
||||||
const nsAString& aUrl,
|
|
||||||
const nsAString& aPresentationId,
|
|
||||||
nsIPresentationControlChannel* aControlChannel);
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~PresentationSessionRequest();
|
|
||||||
|
|
||||||
nsString mUrl;
|
|
||||||
nsString mPresentationId;
|
|
||||||
nsCOMPtr<nsIPresentationDevice> mDevice;
|
|
||||||
nsCOMPtr<nsIPresentationControlChannel> mControlChannel;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif /* mozilla_dom_PresentationSessionRequest_h__ */
|
|
||||||
|
|
|
@ -1,589 +0,0 @@
|
||||||
/* -*- 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 "nsArrayUtils.h"
|
|
||||||
#include "nsIAsyncStreamCopier.h"
|
|
||||||
#include "nsIInputStreamPump.h"
|
|
||||||
#include "nsIMultiplexInputStream.h"
|
|
||||||
#include "nsIMutableArray.h"
|
|
||||||
#include "nsIOutputStream.h"
|
|
||||||
#include "nsIPresentationControlChannel.h"
|
|
||||||
#include "nsIScriptableInputStream.h"
|
|
||||||
#include "nsISocketTransport.h"
|
|
||||||
#include "nsISocketTransportService.h"
|
|
||||||
#include "nsISupportsPrimitives.h"
|
|
||||||
#include "nsNetUtil.h"
|
|
||||||
#include "nsQueryObject.h"
|
|
||||||
#include "nsServiceManagerUtils.h"
|
|
||||||
#include "nsStreamUtils.h"
|
|
||||||
#include "nsThreadUtils.h"
|
|
||||||
#include "PresentationLog.h"
|
|
||||||
#include "PresentationTCPSessionTransport.h"
|
|
||||||
|
|
||||||
#define BUFFER_SIZE 65536
|
|
||||||
|
|
||||||
using namespace mozilla;
|
|
||||||
using namespace mozilla::dom;
|
|
||||||
|
|
||||||
class CopierCallbacks final : public nsIRequestObserver
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit CopierCallbacks(PresentationTCPSessionTransport* aTransport)
|
|
||||||
: mOwner(aTransport)
|
|
||||||
{}
|
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIREQUESTOBSERVER
|
|
||||||
private:
|
|
||||||
~CopierCallbacks() {}
|
|
||||||
|
|
||||||
RefPtr<PresentationTCPSessionTransport> mOwner;
|
|
||||||
};
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(CopierCallbacks, nsIRequestObserver)
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
CopierCallbacks::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
CopierCallbacks::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext, nsresult aStatus)
|
|
||||||
{
|
|
||||||
mOwner->NotifyCopyComplete(aStatus);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION(PresentationTCPSessionTransport, mTransport,
|
|
||||||
mSocketInputStream, mSocketOutputStream,
|
|
||||||
mInputStreamPump, mInputStreamScriptable,
|
|
||||||
mMultiplexStream, mMultiplexStreamCopier, mCallback)
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(PresentationTCPSessionTransport)
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(PresentationTCPSessionTransport)
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PresentationTCPSessionTransport)
|
|
||||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPresentationSessionTransport)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIPresentationSessionTransport)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIPresentationSessionTransportBuilder)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIPresentationTCPSessionTransportBuilder)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)
|
|
||||||
NS_INTERFACE_MAP_END
|
|
||||||
|
|
||||||
PresentationTCPSessionTransport::PresentationTCPSessionTransport()
|
|
||||||
: mReadyState(ReadyState::CLOSED)
|
|
||||||
, mAsyncCopierActive(false)
|
|
||||||
, mCloseStatus(NS_OK)
|
|
||||||
, mDataNotificationEnabled(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationTCPSessionTransport::~PresentationTCPSessionTransport()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTCPSessionTransport::BuildTCPSenderTransport(nsISocketTransport* aTransport,
|
|
||||||
nsIPresentationSessionTransportBuilderListener* aListener)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!aTransport)) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
mTransport = aTransport;
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!aListener)) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
mListener = aListener;
|
|
||||||
|
|
||||||
nsresult rv = CreateStream();
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
mRole = nsIPresentationService::ROLE_CONTROLLER;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationSessionTransport> sessionTransport = do_QueryObject(this);
|
|
||||||
nsCOMPtr<nsIRunnable> onSessionTransportRunnable =
|
|
||||||
NewRunnableMethod
|
|
||||||
<nsIPresentationSessionTransport*>(mListener,
|
|
||||||
&nsIPresentationSessionTransportBuilderListener::OnSessionTransport,
|
|
||||||
sessionTransport);
|
|
||||||
|
|
||||||
NS_DispatchToCurrentThread(onSessionTransportRunnable.forget());
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> setReadyStateRunnable =
|
|
||||||
NewRunnableMethod<ReadyState>(this,
|
|
||||||
&PresentationTCPSessionTransport::SetReadyState,
|
|
||||||
ReadyState::OPEN);
|
|
||||||
return NS_DispatchToCurrentThread(setReadyStateRunnable.forget());
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTCPSessionTransport::BuildTCPReceiverTransport(nsIPresentationChannelDescription* aDescription,
|
|
||||||
nsIPresentationSessionTransportBuilderListener* aListener)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!aDescription)) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!aListener)) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
mListener = aListener;
|
|
||||||
|
|
||||||
uint16_t serverPort;
|
|
||||||
nsresult rv = aDescription->GetTcpPort(&serverPort);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIArray> serverHosts;
|
|
||||||
rv = aDescription->GetTcpAddress(getter_AddRefs(serverHosts));
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO bug 1228504 Take all IP addresses in PresentationChannelDescription
|
|
||||||
// into account. And at the first stage Presentation API is only exposed on
|
|
||||||
// Firefox OS where the first IP appears enough for most scenarios.
|
|
||||||
nsCOMPtr<nsISupportsCString> supportStr = do_QueryElementAt(serverHosts, 0);
|
|
||||||
if (NS_WARN_IF(!supportStr)) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsAutoCString serverHost;
|
|
||||||
supportStr->GetData(serverHost);
|
|
||||||
if (serverHost.IsEmpty()) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
PRES_DEBUG("%s:ServerHost[%s],ServerPort[%d]\n", __func__, serverHost.get(), serverPort);
|
|
||||||
|
|
||||||
SetReadyState(ReadyState::CONNECTING);
|
|
||||||
|
|
||||||
nsCOMPtr<nsISocketTransportService> sts =
|
|
||||||
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!sts)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
rv = sts->CreateTransport(nullptr, 0, serverHost, serverPort, nullptr,
|
|
||||||
getter_AddRefs(mTransport));
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIThread> mainThread;
|
|
||||||
NS_GetMainThread(getter_AddRefs(mainThread));
|
|
||||||
|
|
||||||
mTransport->SetEventSink(this, mainThread);
|
|
||||||
|
|
||||||
rv = CreateStream();
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
mRole = nsIPresentationService::ROLE_RECEIVER;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationSessionTransport> sessionTransport = do_QueryObject(this);
|
|
||||||
nsCOMPtr<nsIRunnable> runnable =
|
|
||||||
NewRunnableMethod
|
|
||||||
<nsIPresentationSessionTransport*>(mListener,
|
|
||||||
&nsIPresentationSessionTransportBuilderListener::OnSessionTransport,
|
|
||||||
sessionTransport);
|
|
||||||
return NS_DispatchToCurrentThread(runnable.forget());
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationTCPSessionTransport::CreateStream()
|
|
||||||
{
|
|
||||||
nsresult rv = mTransport->OpenInputStream(0, 0, 0, getter_AddRefs(mSocketInputStream));
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
rv = mTransport->OpenOutputStream(nsITransport::OPEN_UNBUFFERED, 0, 0, getter_AddRefs(mSocketOutputStream));
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the other side is not listening, we will get an |onInputStreamReady|
|
|
||||||
// callback where |available| raises to indicate the connection was refused.
|
|
||||||
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(mSocketInputStream);
|
|
||||||
if (NS_WARN_IF(!asyncStream)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIThread> mainThread;
|
|
||||||
NS_GetMainThread(getter_AddRefs(mainThread));
|
|
||||||
|
|
||||||
rv = asyncStream->AsyncWait(this, nsIAsyncInputStream::WAIT_CLOSURE_ONLY, 0, mainThread);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
mInputStreamScriptable = do_CreateInstance("@mozilla.org/scriptableinputstream;1", &rv);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
rv = mInputStreamScriptable->Init(mSocketInputStream);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
mMultiplexStream = do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1", &rv);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
mMultiplexStreamCopier = do_CreateInstance("@mozilla.org/network/async-stream-copier;1", &rv);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsISocketTransportService> sts =
|
|
||||||
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!sts)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIEventTarget> target = do_QueryInterface(sts);
|
|
||||||
rv = mMultiplexStreamCopier->Init(mMultiplexStream,
|
|
||||||
mSocketOutputStream,
|
|
||||||
target,
|
|
||||||
true, /* source buffered */
|
|
||||||
false, /* sink buffered */
|
|
||||||
BUFFER_SIZE,
|
|
||||||
false, /* close source */
|
|
||||||
false); /* close sink */
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationTCPSessionTransport::CreateInputStreamPump()
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(mInputStreamPump)) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
mInputStreamPump = do_CreateInstance(NS_INPUTSTREAMPUMP_CONTRACTID, &rv);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = mInputStreamPump->Init(mSocketInputStream, -1, -1, 0, 0, false);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = mInputStreamPump->AsyncRead(this, nullptr);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTCPSessionTransport::EnableDataNotification()
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!mCallback)) {
|
|
||||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mDataNotificationEnabled) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
mDataNotificationEnabled = true;
|
|
||||||
|
|
||||||
if (IsReadyToNotifyData()) {
|
|
||||||
return CreateInputStreamPump();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsIPresentationSessionTransportBuilderListener
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTCPSessionTransport::GetCallback(nsIPresentationSessionTransportCallback** aCallback)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIPresentationSessionTransportCallback> callback = mCallback;
|
|
||||||
callback.forget(aCallback);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTCPSessionTransport::SetCallback(nsIPresentationSessionTransportCallback* aCallback)
|
|
||||||
{
|
|
||||||
mCallback = aCallback;
|
|
||||||
|
|
||||||
if (!!mCallback && ReadyState::OPEN == mReadyState) {
|
|
||||||
// Notify the transport channel is ready.
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mCallback->NotifyTransportReady()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTCPSessionTransport::GetSelfAddress(nsINetAddr** aSelfAddress)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!mTransport)) {
|
|
||||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mTransport->GetScriptableSelfAddr(aSelfAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationTCPSessionTransport::EnsureCopying()
|
|
||||||
{
|
|
||||||
if (mAsyncCopierActive) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mAsyncCopierActive = true;
|
|
||||||
RefPtr<CopierCallbacks> callbacks = new CopierCallbacks(this);
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mMultiplexStreamCopier->AsyncCopy(callbacks, nullptr)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationTCPSessionTransport::NotifyCopyComplete(nsresult aStatus)
|
|
||||||
{
|
|
||||||
mAsyncCopierActive = false;
|
|
||||||
mMultiplexStream->RemoveStream(0);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(aStatus))) {
|
|
||||||
if (mReadyState != ReadyState::CLOSED) {
|
|
||||||
mCloseStatus = aStatus;
|
|
||||||
SetReadyState(ReadyState::CLOSED);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t count;
|
|
||||||
nsresult rv = mMultiplexStream->GetCount(&count);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count) {
|
|
||||||
EnsureCopying();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mReadyState == ReadyState::CLOSING) {
|
|
||||||
mSocketOutputStream->Close();
|
|
||||||
mCloseStatus = NS_OK;
|
|
||||||
SetReadyState(ReadyState::CLOSED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTCPSessionTransport::Send(const nsAString& aData)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(mReadyState != ReadyState::OPEN)) {
|
|
||||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
nsCOMPtr<nsIStringInputStream> stream =
|
|
||||||
do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID, &rv);
|
|
||||||
if(NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_ConvertUTF16toUTF8 msgString(aData);
|
|
||||||
rv = stream->SetData(msgString.BeginReading(), msgString.Length());
|
|
||||||
if(NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
mMultiplexStream->AppendStream(stream);
|
|
||||||
|
|
||||||
EnsureCopying();
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTCPSessionTransport::SendBinaryMsg(const nsACString& aData)
|
|
||||||
{
|
|
||||||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTCPSessionTransport::SendBlob(nsIDOMBlob* aBlob)
|
|
||||||
{
|
|
||||||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTCPSessionTransport::Close(nsresult aReason)
|
|
||||||
{
|
|
||||||
PRES_DEBUG("%s:reason[%x]\n", __func__, aReason);
|
|
||||||
|
|
||||||
if (mReadyState == ReadyState::CLOSED || mReadyState == ReadyState::CLOSING) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
mCloseStatus = aReason;
|
|
||||||
SetReadyState(ReadyState::CLOSING);
|
|
||||||
|
|
||||||
uint32_t count = 0;
|
|
||||||
mMultiplexStream->GetCount(&count);
|
|
||||||
if (!count) {
|
|
||||||
mSocketOutputStream->Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
mSocketInputStream->Close();
|
|
||||||
mDataNotificationEnabled = false;
|
|
||||||
|
|
||||||
mListener = nullptr;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationTCPSessionTransport::SetReadyState(ReadyState aReadyState)
|
|
||||||
{
|
|
||||||
mReadyState = aReadyState;
|
|
||||||
|
|
||||||
if (mReadyState == ReadyState::OPEN) {
|
|
||||||
if (IsReadyToNotifyData()) {
|
|
||||||
CreateInputStreamPump();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!mCallback)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify the transport channel is ready.
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mCallback->NotifyTransportReady()));
|
|
||||||
} else if (mReadyState == ReadyState::CLOSED && mCallback) {
|
|
||||||
if (NS_WARN_IF(!mCallback)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify the transport channel has been shut down.
|
|
||||||
Unused <<
|
|
||||||
NS_WARN_IF(NS_FAILED(mCallback->NotifyTransportClosed(mCloseStatus)));
|
|
||||||
mCallback = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsITransportEventSink
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTCPSessionTransport::OnTransportStatus(nsITransport* aTransport,
|
|
||||||
nsresult aStatus,
|
|
||||||
int64_t aProgress,
|
|
||||||
int64_t aProgressMax)
|
|
||||||
{
|
|
||||||
PRES_DEBUG("%s:aStatus[%x]\n", __func__, aStatus);
|
|
||||||
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (aStatus != NS_NET_STATUS_CONNECTED_TO) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetReadyState(ReadyState::OPEN);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsIInputStreamCallback
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTCPSessionTransport::OnInputStreamReady(nsIAsyncInputStream* aStream)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
// Only used for detecting if the connection was refused.
|
|
||||||
uint64_t dummy;
|
|
||||||
nsresult rv = aStream->Available(&dummy);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
if (mReadyState != ReadyState::CLOSED) {
|
|
||||||
mCloseStatus = NS_ERROR_CONNECTION_REFUSED;
|
|
||||||
SetReadyState(ReadyState::CLOSED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsIRequestObserver
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTCPSessionTransport::OnStartRequest(nsIRequest* aRequest,
|
|
||||||
nsISupports* aContext)
|
|
||||||
{
|
|
||||||
// Do nothing.
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTCPSessionTransport::OnStopRequest(nsIRequest* aRequest,
|
|
||||||
nsISupports* aContext,
|
|
||||||
nsresult aStatusCode)
|
|
||||||
{
|
|
||||||
PRES_DEBUG("%s:aStatusCode[%x]\n", __func__, aStatusCode);
|
|
||||||
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
uint32_t count;
|
|
||||||
nsresult rv = mMultiplexStream->GetCount(&count);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
mInputStreamPump = nullptr;
|
|
||||||
|
|
||||||
if (count != 0 && NS_SUCCEEDED(aStatusCode)) {
|
|
||||||
// If we have some buffered output still, and status is not an error, the
|
|
||||||
// other side has done a half-close, but we don't want to be in the close
|
|
||||||
// state until we are done sending everything that was buffered. We also
|
|
||||||
// don't want to call |NotifyTransportClosed| yet.
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We call this even if there is no error.
|
|
||||||
if (mReadyState != ReadyState::CLOSED) {
|
|
||||||
mCloseStatus = aStatusCode;
|
|
||||||
SetReadyState(ReadyState::CLOSED);
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsIStreamListener
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTCPSessionTransport::OnDataAvailable(nsIRequest* aRequest,
|
|
||||||
nsISupports* aContext,
|
|
||||||
nsIInputStream* aStream,
|
|
||||||
uint64_t aOffset,
|
|
||||||
uint32_t aCount)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!mCallback)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCString data;
|
|
||||||
nsresult rv = mInputStreamScriptable->ReadBytes(aCount, data);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass the incoming data to the listener.
|
|
||||||
return mCallback->NotifyData(data, false);
|
|
||||||
}
|
|
|
@ -1,110 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationSessionTransport_h
|
|
||||||
#define mozilla_dom_PresentationSessionTransport_h
|
|
||||||
|
|
||||||
#include "mozilla/RefPtr.h"
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsIAsyncInputStream.h"
|
|
||||||
#include "nsIPresentationSessionTransport.h"
|
|
||||||
#include "nsIPresentationSessionTransportBuilder.h"
|
|
||||||
#include "nsIStreamListener.h"
|
|
||||||
#include "nsISupportsImpl.h"
|
|
||||||
#include "nsITransport.h"
|
|
||||||
|
|
||||||
class nsISocketTransport;
|
|
||||||
class nsIInputStreamPump;
|
|
||||||
class nsIScriptableInputStream;
|
|
||||||
class nsIMultiplexInputStream;
|
|
||||||
class nsIAsyncStreamCopier;
|
|
||||||
class nsIInputStream;
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* App-to-App transport channel for the presentation session. It's usually
|
|
||||||
* initialized with an |InitWithSocketTransport| call if at the presenting sender
|
|
||||||
* side; whereas it's initialized with an |InitWithChannelDescription| if at the
|
|
||||||
* presenting receiver side. The lifetime is managed in either
|
|
||||||
* |PresentationControllingInfo| (sender side) or |PresentationPresentingInfo|
|
|
||||||
* (receiver side) in PresentationSessionInfo.cpp.
|
|
||||||
*/
|
|
||||||
class PresentationTCPSessionTransport final : public nsIPresentationSessionTransport
|
|
||||||
, public nsIPresentationTCPSessionTransportBuilder
|
|
||||||
, public nsITransportEventSink
|
|
||||||
, public nsIInputStreamCallback
|
|
||||||
, public nsIStreamListener
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(PresentationTCPSessionTransport,
|
|
||||||
nsIPresentationSessionTransport)
|
|
||||||
|
|
||||||
NS_DECL_NSIPRESENTATIONSESSIONTRANSPORT
|
|
||||||
NS_DECL_NSIPRESENTATIONSESSIONTRANSPORTBUILDER
|
|
||||||
NS_DECL_NSIPRESENTATIONTCPSESSIONTRANSPORTBUILDER
|
|
||||||
NS_DECL_NSITRANSPORTEVENTSINK
|
|
||||||
NS_DECL_NSIINPUTSTREAMCALLBACK
|
|
||||||
NS_DECL_NSIREQUESTOBSERVER
|
|
||||||
NS_DECL_NSISTREAMLISTENER
|
|
||||||
|
|
||||||
PresentationTCPSessionTransport();
|
|
||||||
|
|
||||||
void NotifyCopyComplete(nsresult aStatus);
|
|
||||||
|
|
||||||
private:
|
|
||||||
~PresentationTCPSessionTransport();
|
|
||||||
|
|
||||||
nsresult CreateStream();
|
|
||||||
|
|
||||||
nsresult CreateInputStreamPump();
|
|
||||||
|
|
||||||
void EnsureCopying();
|
|
||||||
|
|
||||||
enum class ReadyState {
|
|
||||||
CONNECTING,
|
|
||||||
OPEN,
|
|
||||||
CLOSING,
|
|
||||||
CLOSED
|
|
||||||
};
|
|
||||||
|
|
||||||
void SetReadyState(ReadyState aReadyState);
|
|
||||||
|
|
||||||
bool IsReadyToNotifyData()
|
|
||||||
{
|
|
||||||
return mDataNotificationEnabled && mReadyState == ReadyState::OPEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReadyState mReadyState;
|
|
||||||
bool mAsyncCopierActive;
|
|
||||||
nsresult mCloseStatus;
|
|
||||||
bool mDataNotificationEnabled;
|
|
||||||
|
|
||||||
uint8_t mRole = 0;
|
|
||||||
|
|
||||||
// Raw socket streams
|
|
||||||
nsCOMPtr<nsISocketTransport> mTransport;
|
|
||||||
nsCOMPtr<nsIInputStream> mSocketInputStream;
|
|
||||||
nsCOMPtr<nsIOutputStream> mSocketOutputStream;
|
|
||||||
|
|
||||||
// Input stream machinery
|
|
||||||
nsCOMPtr<nsIInputStreamPump> mInputStreamPump;
|
|
||||||
nsCOMPtr<nsIScriptableInputStream> mInputStreamScriptable;
|
|
||||||
|
|
||||||
// Output stream machinery
|
|
||||||
nsCOMPtr<nsIMultiplexInputStream> mMultiplexStream;
|
|
||||||
nsCOMPtr<nsIAsyncStreamCopier> mMultiplexStreamCopier;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationSessionTransportCallback> mCallback;
|
|
||||||
nsCOMPtr<nsIPresentationSessionTransportBuilderListener> mListener;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationSessionTransport_h
|
|
|
@ -1,73 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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 "PresentationTerminateRequest.h"
|
|
||||||
#include "nsIPresentationControlChannel.h"
|
|
||||||
#include "nsIPresentationDevice.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(PresentationTerminateRequest, nsIPresentationTerminateRequest)
|
|
||||||
|
|
||||||
PresentationTerminateRequest::PresentationTerminateRequest(
|
|
||||||
nsIPresentationDevice* aDevice,
|
|
||||||
const nsAString& aPresentationId,
|
|
||||||
nsIPresentationControlChannel* aControlChannel,
|
|
||||||
bool aIsFromReceiver)
|
|
||||||
: mPresentationId(aPresentationId)
|
|
||||||
, mDevice(aDevice)
|
|
||||||
, mControlChannel(aControlChannel)
|
|
||||||
, mIsFromReceiver(aIsFromReceiver)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationTerminateRequest::~PresentationTerminateRequest()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsIPresentationTerminateRequest
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTerminateRequest::GetDevice(nsIPresentationDevice** aRetVal)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG_POINTER(aRetVal);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationDevice> device = mDevice;
|
|
||||||
device.forget(aRetVal);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTerminateRequest::GetPresentationId(nsAString& aRetVal)
|
|
||||||
{
|
|
||||||
aRetVal = mPresentationId;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTerminateRequest::GetControlChannel(
|
|
||||||
nsIPresentationControlChannel** aRetVal)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG_POINTER(aRetVal);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationControlChannel> controlChannel = mControlChannel;
|
|
||||||
controlChannel.forget(aRetVal);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTerminateRequest::GetIsFromReceiver(bool* aRetVal)
|
|
||||||
{
|
|
||||||
*aRetVal = mIsFromReceiver;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,41 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationTerminateRequest_h__
|
|
||||||
#define mozilla_dom_PresentationTerminateRequest_h__
|
|
||||||
|
|
||||||
#include "nsIPresentationTerminateRequest.h"
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsString.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class PresentationTerminateRequest final : public nsIPresentationTerminateRequest
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIPRESENTATIONTERMINATEREQUEST
|
|
||||||
|
|
||||||
PresentationTerminateRequest(nsIPresentationDevice* aDevice,
|
|
||||||
const nsAString& aPresentationId,
|
|
||||||
nsIPresentationControlChannel* aControlChannel,
|
|
||||||
bool aIsFromReceiver);
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~PresentationTerminateRequest();
|
|
||||||
|
|
||||||
nsString mPresentationId;
|
|
||||||
nsCOMPtr<nsIPresentationDevice> mDevice;
|
|
||||||
nsCOMPtr<nsIPresentationControlChannel> mControlChannel;
|
|
||||||
bool mIsFromReceiver;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif /* mozilla_dom_PresentationTerminateRequest_h__ */
|
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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 "PresentationTransportBuilderConstructor.h"
|
|
||||||
|
|
||||||
#include "nsComponentManagerUtils.h"
|
|
||||||
#include "nsIPresentationControlChannel.h"
|
|
||||||
#include "nsIPresentationSessionTransport.h"
|
|
||||||
#include "nsXULAppAPI.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(DummyPresentationTransportBuilderConstructor,
|
|
||||||
nsIPresentationTransportBuilderConstructor)
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
DummyPresentationTransportBuilderConstructor::CreateTransportBuilder(
|
|
||||||
uint8_t aType,
|
|
||||||
nsIPresentationSessionTransportBuilder** aRetval)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(false, "Unexpected to be invoked.");
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_INHERITED0(PresentationTransportBuilderConstructor,
|
|
||||||
DummyPresentationTransportBuilderConstructor)
|
|
||||||
|
|
||||||
/* static */ already_AddRefed<nsIPresentationTransportBuilderConstructor>
|
|
||||||
PresentationTransportBuilderConstructor::Create()
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIPresentationTransportBuilderConstructor> constructor;
|
|
||||||
if (XRE_IsContentProcess()) {
|
|
||||||
constructor = new DummyPresentationTransportBuilderConstructor();
|
|
||||||
} else {
|
|
||||||
constructor = new PresentationTransportBuilderConstructor();
|
|
||||||
}
|
|
||||||
|
|
||||||
return constructor.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTransportBuilderConstructor::CreateTransportBuilder(
|
|
||||||
uint8_t aType,
|
|
||||||
nsIPresentationSessionTransportBuilder** aRetval)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!aRetval)) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
*aRetval = nullptr;
|
|
||||||
|
|
||||||
if (NS_WARN_IF(aType != nsIPresentationChannelDescription::TYPE_TCP &&
|
|
||||||
aType != nsIPresentationChannelDescription::TYPE_DATACHANNEL)) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (XRE_IsContentProcess()) {
|
|
||||||
MOZ_ASSERT(false,
|
|
||||||
"CreateTransportBuilder can only be invoked in parent process.");
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationSessionTransportBuilder> builder;
|
|
||||||
if (aType == nsIPresentationChannelDescription::TYPE_TCP) {
|
|
||||||
builder =
|
|
||||||
do_CreateInstance(PRESENTATION_TCP_SESSION_TRANSPORT_CONTRACTID);
|
|
||||||
} else {
|
|
||||||
builder =
|
|
||||||
do_CreateInstance("@mozilla.org/presentation/datachanneltransportbuilder;1");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!builder)) {
|
|
||||||
return NS_ERROR_DOM_OPERATION_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.forget(aRetval);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,48 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationTransportBuilderConstructor_h
|
|
||||||
#define mozilla_dom_PresentationTransportBuilderConstructor_h
|
|
||||||
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsIPresentationSessionTransportBuilder.h"
|
|
||||||
#include "nsISupportsImpl.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class DummyPresentationTransportBuilderConstructor :
|
|
||||||
public nsIPresentationTransportBuilderConstructor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIPRESENTATIONTRANSPORTBUILDERCONSTRUCTOR
|
|
||||||
|
|
||||||
DummyPresentationTransportBuilderConstructor() = default;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual ~DummyPresentationTransportBuilderConstructor() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PresentationTransportBuilderConstructor final :
|
|
||||||
public DummyPresentationTransportBuilderConstructor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS_INHERITED
|
|
||||||
NS_DECL_NSIPRESENTATIONTRANSPORTBUILDERCONSTRUCTOR
|
|
||||||
|
|
||||||
static already_AddRefed<nsIPresentationTransportBuilderConstructor>
|
|
||||||
Create();
|
|
||||||
|
|
||||||
private:
|
|
||||||
PresentationTransportBuilderConstructor() = default;
|
|
||||||
virtual ~PresentationTransportBuilderConstructor() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationTransportBuilderConstructor_h
|
|
|
@ -1,30 +0,0 @@
|
||||||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
|
||||||
# vim: set filetype=python:
|
|
||||||
# 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/.
|
|
||||||
|
|
||||||
XPIDL_SOURCES += [
|
|
||||||
'nsIPresentationControlChannel.idl',
|
|
||||||
'nsIPresentationControlService.idl',
|
|
||||||
'nsIPresentationDevice.idl',
|
|
||||||
'nsIPresentationDeviceManager.idl',
|
|
||||||
'nsIPresentationDevicePrompt.idl',
|
|
||||||
'nsIPresentationDeviceProvider.idl',
|
|
||||||
'nsIPresentationListener.idl',
|
|
||||||
'nsIPresentationLocalDevice.idl',
|
|
||||||
'nsIPresentationRequestUIGlue.idl',
|
|
||||||
'nsIPresentationService.idl',
|
|
||||||
'nsIPresentationSessionRequest.idl',
|
|
||||||
'nsIPresentationSessionTransport.idl',
|
|
||||||
'nsIPresentationSessionTransportBuilder.idl',
|
|
||||||
'nsIPresentationTerminateRequest.idl',
|
|
||||||
]
|
|
||||||
|
|
||||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
|
|
||||||
XPIDL_SOURCES += [
|
|
||||||
'nsIPresentationNetworkHelper.idl',
|
|
||||||
]
|
|
||||||
|
|
||||||
XPIDL_MODULE = 'dom_presentation'
|
|
||||||
|
|
|
@ -1,139 +0,0 @@
|
||||||
/* 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 "nsISupports.idl"
|
|
||||||
|
|
||||||
interface nsIArray;
|
|
||||||
interface nsIInputStream;
|
|
||||||
|
|
||||||
[scriptable, uuid(ae318e05-2a4e-4f85-95c0-e8b191ad812c)]
|
|
||||||
interface nsIPresentationChannelDescription: nsISupports
|
|
||||||
{
|
|
||||||
const unsigned short TYPE_TCP = 1;
|
|
||||||
const unsigned short TYPE_DATACHANNEL = 2;
|
|
||||||
|
|
||||||
// Type of transport channel.
|
|
||||||
readonly attribute uint8_t type;
|
|
||||||
|
|
||||||
// Addresses for TCP channel (as a list of nsISupportsCString).
|
|
||||||
// Should only be used while type == TYPE_TCP.
|
|
||||||
readonly attribute nsIArray tcpAddress;
|
|
||||||
|
|
||||||
// Port number for TCP channel.
|
|
||||||
// Should only be used while type == TYPE_TCP.
|
|
||||||
readonly attribute uint16_t tcpPort;
|
|
||||||
|
|
||||||
// SDP for Data Channel.
|
|
||||||
// Should only be used while type == TYPE_DATACHANNEL.
|
|
||||||
readonly attribute DOMString dataChannelSDP;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The callbacks for events on control channel.
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(96dd548f-7d0f-43c1-b1ad-28e666cf1e82)]
|
|
||||||
interface nsIPresentationControlChannelListener: nsISupports
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Callback for receiving offer from remote endpoint.
|
|
||||||
* @param offer The received offer.
|
|
||||||
*/
|
|
||||||
void onOffer(in nsIPresentationChannelDescription offer);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Callback for receiving answer from remote endpoint.
|
|
||||||
* @param answer The received answer.
|
|
||||||
*/
|
|
||||||
void onAnswer(in nsIPresentationChannelDescription answer);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Callback for receiving ICE candidate from remote endpoint.
|
|
||||||
* @param answer The received answer.
|
|
||||||
*/
|
|
||||||
void onIceCandidate(in DOMString candidate);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The callback for notifying channel connected. This should be async called
|
|
||||||
* after nsIPresentationDevice::establishControlChannel.
|
|
||||||
*/
|
|
||||||
void notifyConnected();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The callback for notifying channel disconnected.
|
|
||||||
* @param reason The reason of channel close, NS_OK represents normal close.
|
|
||||||
*/
|
|
||||||
void notifyDisconnected(in nsresult reason);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The callback for notifying the reconnect command is acknowledged.
|
|
||||||
*/
|
|
||||||
void notifyReconnected();
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The control channel for establishing RTCPeerConnection for a presentation
|
|
||||||
* session. SDP Offer/Answer will be exchanged through this interface. The
|
|
||||||
* control channel should be in-order.
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(e60e208c-a9f5-4bc6-9a3e-47f3e4ae9c57)]
|
|
||||||
interface nsIPresentationControlChannel: nsISupports
|
|
||||||
{
|
|
||||||
// The listener for handling events of this control channel.
|
|
||||||
// All the events should be pending until listener is assigned.
|
|
||||||
attribute nsIPresentationControlChannelListener listener;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send offer to remote endpoint. |onOffer| should be invoked on remote
|
|
||||||
* endpoint.
|
|
||||||
* @param offer The offer to send.
|
|
||||||
* @throws NS_ERROR_FAILURE on failure
|
|
||||||
*/
|
|
||||||
void sendOffer(in nsIPresentationChannelDescription offer);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send answer to remote endpoint. |onAnswer| should be invoked on remote
|
|
||||||
* endpoint.
|
|
||||||
* @param answer The answer to send.
|
|
||||||
* @throws NS_ERROR_FAILURE on failure
|
|
||||||
*/
|
|
||||||
void sendAnswer(in nsIPresentationChannelDescription answer);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send ICE candidate to remote endpoint. |onIceCandidate| should be invoked
|
|
||||||
* on remote endpoint.
|
|
||||||
* @param candidate The candidate to send
|
|
||||||
* @throws NS_ERROR_FAILURE on failure
|
|
||||||
*/
|
|
||||||
void sendIceCandidate(in DOMString candidate);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Launch a presentation on remote endpoint.
|
|
||||||
* @param presentationId The Id for representing this session.
|
|
||||||
* @param url The URL requested to open by remote device.
|
|
||||||
* @throws NS_ERROR_FAILURE on failure
|
|
||||||
*/
|
|
||||||
void launch(in DOMString presentationId, in DOMString url);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Terminate a presentation on remote endpoint.
|
|
||||||
* @param presentationId The Id for representing this session.
|
|
||||||
* @throws NS_ERROR_FAILURE on failure
|
|
||||||
*/
|
|
||||||
void terminate(in DOMString presentationId);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Disconnect the control channel.
|
|
||||||
* @param reason The reason of disconnecting channel; NS_OK represents normal.
|
|
||||||
*/
|
|
||||||
void disconnect(in nsresult reason);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reconnect a presentation on remote endpoint.
|
|
||||||
* Note that only controller is allowed to reconnect a session.
|
|
||||||
* @param presentationId The Id for representing this session.
|
|
||||||
* @param url The URL requested to open by remote device.
|
|
||||||
* @throws NS_ERROR_FAILURE on failure
|
|
||||||
*/
|
|
||||||
void reconnect(in DOMString presentationId, in DOMString url);
|
|
||||||
};
|
|
|
@ -1,156 +0,0 @@
|
||||||
/* 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 "nsISupports.idl"
|
|
||||||
|
|
||||||
interface nsIPresentationControlChannel;
|
|
||||||
|
|
||||||
%{C++
|
|
||||||
#define PRESENTATION_CONTROL_SERVICE_CONTACT_ID \
|
|
||||||
"@mozilla.org/presentation/control-service;1"
|
|
||||||
%}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The device information required for establishing control channel.
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(296fd171-e4d0-4de0-99ff-ad8ed52ddef3)]
|
|
||||||
interface nsITCPDeviceInfo: nsISupports
|
|
||||||
{
|
|
||||||
readonly attribute AUTF8String id;
|
|
||||||
readonly attribute AUTF8String address;
|
|
||||||
readonly attribute uint16_t port;
|
|
||||||
// SHA-256 fingerprint of server certificate. Empty string represents
|
|
||||||
// server doesn't support TLS or not available.
|
|
||||||
readonly attribute AUTF8String certFingerprint;
|
|
||||||
};
|
|
||||||
|
|
||||||
[scriptable, uuid(09bddfaf-fcc2-4dc9-b33e-a509a1c2fb6d)]
|
|
||||||
interface nsIPresentationControlServerListener: nsISupports
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Callback while the server is ready or restarted.
|
|
||||||
* @param aPort
|
|
||||||
* The port of the server socket.
|
|
||||||
* @param aCertFingerprint
|
|
||||||
* The SHA-256 fingerprint of TLS server certificate.
|
|
||||||
* Empty string represents server started without encryption.
|
|
||||||
*/
|
|
||||||
void onServerReady(in uint16_t aPort, in AUTF8String aCertFingerprint);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback while the server is stopped or fails to start.
|
|
||||||
* @param aResult
|
|
||||||
* The error cause of server stopped or the reason of
|
|
||||||
* start failure.
|
|
||||||
* NS_OK means the server is stopped by close.
|
|
||||||
*/
|
|
||||||
void onServerStopped(in nsresult aResult);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback while the remote host is requesting to start a presentation session.
|
|
||||||
* @param aDeviceInfo The device information related to the remote host.
|
|
||||||
* @param aUrl The URL requested to open by remote device.
|
|
||||||
* @param aPresentationId The Id for representing this session.
|
|
||||||
* @param aControlChannel The control channel for this session.
|
|
||||||
*/
|
|
||||||
void onSessionRequest(in nsITCPDeviceInfo aDeviceInfo,
|
|
||||||
in DOMString aUrl,
|
|
||||||
in DOMString aPresentationId,
|
|
||||||
in nsIPresentationControlChannel aControlChannel);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback while the remote host is requesting to terminate a presentation session.
|
|
||||||
* @param aDeviceInfo The device information related to the remote host.
|
|
||||||
* @param aPresentationId The Id for representing this session.
|
|
||||||
* @param aControlChannel The control channel for this session.
|
|
||||||
* @param aIsFromReceiver true if termination is initiated by receiver.
|
|
||||||
*/
|
|
||||||
void onTerminateRequest(in nsITCPDeviceInfo aDeviceInfo,
|
|
||||||
in DOMString aPresentationId,
|
|
||||||
in nsIPresentationControlChannel aControlChannel,
|
|
||||||
in boolean aIsFromReceiver);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback while the remote host is requesting to reconnect a presentation session.
|
|
||||||
* @param aDeviceInfo The device information related to the remote host.
|
|
||||||
* @param aUrl The URL requested to open by remote device.
|
|
||||||
* @param aPresentationId The Id for representing this session.
|
|
||||||
* @param aControlChannel The control channel for this session.
|
|
||||||
*/
|
|
||||||
void onReconnectRequest(in nsITCPDeviceInfo aDeviceInfo,
|
|
||||||
in DOMString url,
|
|
||||||
in DOMString aPresentationId,
|
|
||||||
in nsIPresentationControlChannel aControlChannel);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Presentation control service which can be used for both presentation
|
|
||||||
* control client and server.
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(55d6b605-2389-4aae-a8fe-60d4440540ea)]
|
|
||||||
interface nsIPresentationControlService: nsISupports
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* This method initializes server socket. Caller should set listener and
|
|
||||||
* monitor onServerReady event to get the correct server info.
|
|
||||||
* @param aEncrypted
|
|
||||||
* True for using TLS control channel.
|
|
||||||
* @param aPort
|
|
||||||
* The port of the server socket. Pass 0 or opt-out to indicate no
|
|
||||||
* preference, and a port will be selected automatically.
|
|
||||||
* @throws NS_ERROR_FAILURE if the server socket has been inited or the
|
|
||||||
* server socket can not be inited.
|
|
||||||
*/
|
|
||||||
void startServer(in boolean aEncrypted, [optional] in uint16_t aPort);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request connection to designated remote presentation control receiver.
|
|
||||||
* @param aDeviceInfo
|
|
||||||
* The remtoe device info for establish connection.
|
|
||||||
* @returns The control channel for this session.
|
|
||||||
* @throws NS_ERROR_FAILURE if the Id hasn't been inited.
|
|
||||||
*/
|
|
||||||
nsIPresentationControlChannel connect(in nsITCPDeviceInfo aDeviceInfo);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check the compatibility to remote presentation control server.
|
|
||||||
* @param aVersion
|
|
||||||
* The version of remote server.
|
|
||||||
*/
|
|
||||||
boolean isCompatibleServer(in uint32_t aVersion);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close server socket and call |listener.onClose(NS_OK)|
|
|
||||||
*/
|
|
||||||
void close();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the listen port of the TCP socket, valid after the server is ready.
|
|
||||||
* 0 indicates the server socket is not ready or is closed.
|
|
||||||
*/
|
|
||||||
readonly attribute uint16_t port;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The protocol version implemented by this server.
|
|
||||||
*/
|
|
||||||
readonly attribute uint32_t version;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The id of the TCP presentation server. |requestSession| won't
|
|
||||||
* work until the |id| is set.
|
|
||||||
*/
|
|
||||||
attribute AUTF8String id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The fingerprint of the TLS server certificate.
|
|
||||||
* Empty string indicates the server is not ready or not encrypted.
|
|
||||||
*/
|
|
||||||
attribute AUTF8String certFingerprint;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The listener for handling events of this presentation control server.
|
|
||||||
* Listener must be provided before invoke |startServer| and |close|.
|
|
||||||
*/
|
|
||||||
attribute nsIPresentationControlServerListener listener;
|
|
||||||
};
|
|
|
@ -1,43 +0,0 @@
|
||||||
/* 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 "nsISupports.idl"
|
|
||||||
|
|
||||||
interface nsIPresentationControlChannel;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remote device.
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(b1e0a7af-5936-4066-8f2e-f789fb9a7e8f)]
|
|
||||||
interface nsIPresentationDevice : nsISupports
|
|
||||||
{
|
|
||||||
// The unique Id for the device. UUID is recommanded.
|
|
||||||
readonly attribute AUTF8String id;
|
|
||||||
|
|
||||||
// The human-readable name of this device.
|
|
||||||
readonly attribute AUTF8String name;
|
|
||||||
|
|
||||||
// TODO expose more info in order to fulfill UX spec
|
|
||||||
// The category of this device, could be "wifi", "bluetooth", "hdmi", etc.
|
|
||||||
readonly attribute AUTF8String type;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Establish a control channel to this device.
|
|
||||||
* @returns The control channel for this session.
|
|
||||||
* @throws NS_ERROR_FAILURE if the establishment fails
|
|
||||||
*/
|
|
||||||
nsIPresentationControlChannel establishControlChannel();
|
|
||||||
|
|
||||||
// Do something when presentation session is disconnected.
|
|
||||||
void disconnect();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Query if requested presentation URL is supported.
|
|
||||||
* @params requestedUrl the designated URL for a presentation request.
|
|
||||||
* @returns true if designated URL is supported.
|
|
||||||
*/
|
|
||||||
boolean isRequestedUrlSupported(in DOMString requestedUrl);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
/* 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 "nsISupports.idl"
|
|
||||||
|
|
||||||
interface nsIArray;
|
|
||||||
interface nsIPresentationDeviceProvider;
|
|
||||||
|
|
||||||
%{C++
|
|
||||||
#define PRESENTATION_DEVICE_MANAGER_CONTRACTID "@mozilla.org/presentation-device/manager;1"
|
|
||||||
#define PRESENTATION_DEVICE_CHANGE_TOPIC "presentation-device-change"
|
|
||||||
%}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Manager for the device availability. User can observe "presentation-device-change"
|
|
||||||
* for any update of the available devices.
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(beb61db5-3d5f-454f-a15a-dbfa0337c569)]
|
|
||||||
interface nsIPresentationDeviceManager : nsISupports
|
|
||||||
{
|
|
||||||
// true if there is any device available.
|
|
||||||
readonly attribute boolean deviceAvailable;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Register a device provider manually.
|
|
||||||
* @param provider The device provider to add.
|
|
||||||
*/
|
|
||||||
void addDeviceProvider(in nsIPresentationDeviceProvider provider);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Unregister a device provider manually.
|
|
||||||
* @param provider The device provider to remove.
|
|
||||||
*/
|
|
||||||
void removeDeviceProvider(in nsIPresentationDeviceProvider provider);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Force all registered device providers to update device information.
|
|
||||||
*/
|
|
||||||
void forceDiscovery();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Retrieve all available devices or all available devices that supports
|
|
||||||
* designated presentation URLs, return a list of nsIPresentationDevice.
|
|
||||||
* The returned list is a cached device list and could be out-of-date.
|
|
||||||
* Observe device change events to get following updates.
|
|
||||||
* @param presentationUrls the target presentation URLs for device filtering
|
|
||||||
*/
|
|
||||||
nsIArray getAvailableDevices([optional] in nsIArray presentationUrls);
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
/* 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 "nsISupports.idl"
|
|
||||||
|
|
||||||
interface nsIArray;
|
|
||||||
interface nsIDOMEventTarget;
|
|
||||||
interface nsIPresentationDevice;
|
|
||||||
interface nsIPrincipal;
|
|
||||||
|
|
||||||
%{C++
|
|
||||||
#define PRESENTATION_DEVICE_PROMPT_CONTRACTID "@mozilla.org/presentation-device/prompt;1"
|
|
||||||
%}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The information and callbacks for device selection
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(b2aa7f6a-9448-446a-bba4-9c29638b0ed4)]
|
|
||||||
interface nsIPresentationDeviceRequest : nsISupports
|
|
||||||
{
|
|
||||||
// The origin which initiate the request.
|
|
||||||
readonly attribute DOMString origin;
|
|
||||||
|
|
||||||
// The array of candidate URLs.
|
|
||||||
readonly attribute nsIArray requestURLs;
|
|
||||||
|
|
||||||
// The XUL browser element that the request was originated in.
|
|
||||||
readonly attribute nsIDOMEventTarget chromeEventHandler;
|
|
||||||
|
|
||||||
// The principal of the request.
|
|
||||||
readonly attribute nsIPrincipal principal;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Callback after selecting a device
|
|
||||||
* @param device The selected device.
|
|
||||||
*/
|
|
||||||
void select(in nsIPresentationDevice device);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Callback after selection failed or canceled by user.
|
|
||||||
* @param reason The error cause for canceling this request.
|
|
||||||
*/
|
|
||||||
void cancel(in nsresult reason);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* UI prompt for device selection.
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(ac1a7e44-de86-454f-a9f1-276de2539831)]
|
|
||||||
interface nsIPresentationDevicePrompt : nsISupports
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Request a device selection.
|
|
||||||
* @param request The information and callbacks of this selection request.
|
|
||||||
*/
|
|
||||||
void promptDeviceSelection(in nsIPresentationDeviceRequest request);
|
|
||||||
};
|
|
|
@ -1,75 +0,0 @@
|
||||||
/* 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 "nsISupports.idl"
|
|
||||||
|
|
||||||
interface nsIPresentationDevice;
|
|
||||||
interface nsIPresentationControlChannel;
|
|
||||||
|
|
||||||
%{C++
|
|
||||||
#define PRESENTATION_DEVICE_PROVIDER_CATEGORY "presentation-device-provider"
|
|
||||||
%}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The callbacks for any device updates and session request.
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(46fd372b-2e40-4179-9b36-0478d141e440)]
|
|
||||||
interface nsIPresentationDeviceListener: nsISupports
|
|
||||||
{
|
|
||||||
void addDevice(in nsIPresentationDevice device);
|
|
||||||
void removeDevice(in nsIPresentationDevice device);
|
|
||||||
void updateDevice(in nsIPresentationDevice device);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Callback while the remote device is requesting to start a presentation session.
|
|
||||||
* @param device The remote device that sent session request.
|
|
||||||
* @param url The URL requested to open by remote device.
|
|
||||||
* @param presentationId The Id for representing this session.
|
|
||||||
* @param controlChannel The control channel for this session.
|
|
||||||
*/
|
|
||||||
void onSessionRequest(in nsIPresentationDevice device,
|
|
||||||
in DOMString url,
|
|
||||||
in DOMString presentationId,
|
|
||||||
in nsIPresentationControlChannel controlChannel);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Callback while the remote device is requesting to terminate a presentation session.
|
|
||||||
* @param device The remote device that sent session request.
|
|
||||||
* @param presentationId The Id for representing this session.
|
|
||||||
* @param controlChannel The control channel for this session.
|
|
||||||
* @param aIsFromReceiver true if termination is initiated by receiver.
|
|
||||||
*/
|
|
||||||
void onTerminateRequest(in nsIPresentationDevice device,
|
|
||||||
in DOMString presentationId,
|
|
||||||
in nsIPresentationControlChannel controlChannel,
|
|
||||||
in boolean aIsFromReceiver);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Callback while the remote device is requesting to reconnect a presentation session.
|
|
||||||
* @param device The remote device that sent session request.
|
|
||||||
* @param aUrl The URL requested to open by remote device.
|
|
||||||
* @param presentationId The Id for representing this session.
|
|
||||||
* @param controlChannel The control channel for this session.
|
|
||||||
*/
|
|
||||||
void onReconnectRequest(in nsIPresentationDevice device,
|
|
||||||
in DOMString url,
|
|
||||||
in DOMString presentationId,
|
|
||||||
in nsIPresentationControlChannel controlChannel);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Device provider for any device protocol, can be registered as default
|
|
||||||
* providers by adding its contractID to category "presentation-device-provider".
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(3db2578a-0f50-44ad-b01b-28427b71b7bf)]
|
|
||||||
interface nsIPresentationDeviceProvider: nsISupports
|
|
||||||
{
|
|
||||||
// The listener for handling any device update.
|
|
||||||
attribute nsIPresentationDeviceListener listener;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Force to update device information.
|
|
||||||
*/
|
|
||||||
void forceDiscovery();
|
|
||||||
};
|
|
|
@ -1,50 +0,0 @@
|
||||||
/* 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 "nsISupports.idl"
|
|
||||||
|
|
||||||
[ref] native URLArrayRef(const nsTArray<nsString>);
|
|
||||||
|
|
||||||
[uuid(0105f837-4279-4715-9d5b-2dc3f8b65353)]
|
|
||||||
interface nsIPresentationAvailabilityListener : nsISupports
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Called when device availability changes.
|
|
||||||
*/
|
|
||||||
[noscript] void notifyAvailableChange(in URLArrayRef urls,
|
|
||||||
in bool available);
|
|
||||||
};
|
|
||||||
|
|
||||||
[scriptable, uuid(7dd48df8-8f8c-48c7-ac37-7b9fd1acf2f8)]
|
|
||||||
interface nsIPresentationSessionListener : nsISupports
|
|
||||||
{
|
|
||||||
const unsigned short STATE_CONNECTING = 0;
|
|
||||||
const unsigned short STATE_CONNECTED = 1;
|
|
||||||
const unsigned short STATE_CLOSED = 2;
|
|
||||||
const unsigned short STATE_TERMINATED = 3;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Called when session state changes.
|
|
||||||
*/
|
|
||||||
void notifyStateChange(in DOMString sessionId,
|
|
||||||
in unsigned short state,
|
|
||||||
in nsresult reason);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Called when receive messages.
|
|
||||||
*/
|
|
||||||
void notifyMessage(in DOMString sessionId,
|
|
||||||
in ACString data,
|
|
||||||
in boolean isBinary);
|
|
||||||
};
|
|
||||||
|
|
||||||
[scriptable, uuid(27f101d7-9ed1-429e-b4f8-43b00e8e111c)]
|
|
||||||
interface nsIPresentationRespondingListener : nsISupports
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Called when an incoming session connects.
|
|
||||||
*/
|
|
||||||
void notifySessionConnect(in unsigned long long windowId,
|
|
||||||
in DOMString sessionId);
|
|
||||||
};
|
|
|
@ -1,17 +0,0 @@
|
||||||
/* 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 "nsIPresentationDevice.idl"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Local device.
|
|
||||||
* This device is used for 1-UA use case. The result for display is rendered by
|
|
||||||
* this host device.
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(dd239720-cab6-4fb5-9025-cba23f1bbc2d)]
|
|
||||||
interface nsIPresentationLocalDevice : nsIPresentationDevice
|
|
||||||
{
|
|
||||||
// (1-UA only) The property is used to get the window ID of 1-UA device.
|
|
||||||
readonly attribute AUTF8String windowId;
|
|
||||||
};
|
|
|
@ -1,36 +0,0 @@
|
||||||
/* 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 "nsISupports.idl"
|
|
||||||
|
|
||||||
%{C++
|
|
||||||
#define PRESENTATION_NETWORK_HELPER_CONTRACTID \
|
|
||||||
"@mozilla.org/presentation-device/networkHelper;1"
|
|
||||||
%}
|
|
||||||
|
|
||||||
[scriptable, uuid(0a7e134f-ff80-4e73-91e6-12b3134fe568)]
|
|
||||||
interface nsIPresentationNetworkHelperListener : nsISupports
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Called when error occurs.
|
|
||||||
* @param aReason error message.
|
|
||||||
*/
|
|
||||||
void onError(in AUTF8String aReason);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when get Wi-Fi IP address.
|
|
||||||
* @param aIPAddress the IP address of Wi-Fi interface.
|
|
||||||
*/
|
|
||||||
void onGetWifiIPAddress(in AUTF8String aIPAddress);
|
|
||||||
};
|
|
||||||
|
|
||||||
[scriptable, uuid(650dc16b-3d9c-49a6-9037-1d6f2d18c90c)]
|
|
||||||
interface nsIPresentationNetworkHelper : nsISupports
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get IP address of Wi-Fi interface.
|
|
||||||
* @param aListener the callback interface.
|
|
||||||
*/
|
|
||||||
void getWifiIPAddress(in nsIPresentationNetworkHelperListener aListener);
|
|
||||||
};
|
|
|
@ -1,29 +0,0 @@
|
||||||
/* 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 "nsISupports.idl"
|
|
||||||
|
|
||||||
interface nsIPresentationDevice;
|
|
||||||
|
|
||||||
%{C++
|
|
||||||
#define PRESENTATION_REQUEST_UI_GLUE_CONTRACTID \
|
|
||||||
"@mozilla.org/presentation/requestuiglue;1"
|
|
||||||
%}
|
|
||||||
|
|
||||||
[scriptable, uuid(faa45119-6fb5-496c-aa4c-f740177a38b5)]
|
|
||||||
interface nsIPresentationRequestUIGlue : nsISupports
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* This method is called to open the responding app/page when
|
|
||||||
* a presentation request comes in at receiver side.
|
|
||||||
*
|
|
||||||
* @param url The url of the request.
|
|
||||||
* @param sessionId The session ID of the request.
|
|
||||||
*
|
|
||||||
* @return A promise that resolves to the opening frame.
|
|
||||||
*/
|
|
||||||
nsISupports sendRequest(in DOMString url,
|
|
||||||
in DOMString sessionId,
|
|
||||||
in nsIPresentationDevice device);
|
|
||||||
};
|
|
|
@ -1,275 +0,0 @@
|
||||||
/* 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 "nsISupports.idl"
|
|
||||||
|
|
||||||
interface nsIDOMBlob;
|
|
||||||
interface nsIDOMEventTarget;
|
|
||||||
interface nsIInputStream;
|
|
||||||
interface nsIPresentationAvailabilityListener;
|
|
||||||
interface nsIPresentationRespondingListener;
|
|
||||||
interface nsIPresentationSessionListener;
|
|
||||||
interface nsIPresentationTransportBuilderConstructor;
|
|
||||||
interface nsIPrincipal;
|
|
||||||
|
|
||||||
%{C++
|
|
||||||
#define PRESENTATION_SERVICE_CID \
|
|
||||||
{ 0x1d9bb10c, 0xc0ab, 0x4fe8, \
|
|
||||||
{ 0x9e, 0x4f, 0x40, 0x58, 0xb8, 0x51, 0x98, 0x32 } }
|
|
||||||
#define PRESENTATION_SERVICE_CONTRACTID \
|
|
||||||
"@mozilla.org/presentation/presentationservice;1"
|
|
||||||
|
|
||||||
#include "nsTArray.h"
|
|
||||||
|
|
||||||
class nsString;
|
|
||||||
%}
|
|
||||||
|
|
||||||
[ref] native URLArrayRef(const nsTArray<nsString>);
|
|
||||||
|
|
||||||
[scriptable, uuid(12073206-0065-4b10-9488-a6eb9b23e65b)]
|
|
||||||
interface nsIPresentationServiceCallback : nsISupports
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Called when the operation succeeds.
|
|
||||||
*
|
|
||||||
* @param url: the selected request url used to start or reconnect a session.
|
|
||||||
*/
|
|
||||||
void notifySuccess(in DOMString url);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Called when the operation fails.
|
|
||||||
*
|
|
||||||
* @param error: error message.
|
|
||||||
*/
|
|
||||||
void notifyError(in nsresult error);
|
|
||||||
};
|
|
||||||
|
|
||||||
[scriptable, uuid(de42b741-5619-4650-b961-c2cebb572c95)]
|
|
||||||
interface nsIPresentationService : nsISupports
|
|
||||||
{
|
|
||||||
const unsigned short ROLE_CONTROLLER = 0x1;
|
|
||||||
const unsigned short ROLE_RECEIVER = 0x2;
|
|
||||||
|
|
||||||
const unsigned short CLOSED_REASON_ERROR = 0x1;
|
|
||||||
const unsigned short CLOSED_REASON_CLOSED = 0x2;
|
|
||||||
const unsigned short CLOSED_REASON_WENTAWAY = 0x3;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Start a new presentation session and display a prompt box which asks users
|
|
||||||
* to select a device.
|
|
||||||
*
|
|
||||||
* @param urls: The candidate Urls of presenting page. Only one url would be used.
|
|
||||||
* @param sessionId: An ID to identify presentation session.
|
|
||||||
* @param origin: The url of requesting page.
|
|
||||||
* @param deviceId: The specified device of handling this request, null string
|
|
||||||
* for prompt device selection dialog.
|
|
||||||
* @param windowId: The inner window ID associated with the presentation
|
|
||||||
* session. (0 implies no window ID since no actual window
|
|
||||||
* uses 0 as its ID. Generally it's the case the window is
|
|
||||||
* located in different process from this service)
|
|
||||||
* @param eventTarget: The chrome event handler, in particular XUL browser
|
|
||||||
* element in parent process, that the request was
|
|
||||||
* originated in.
|
|
||||||
* @param principal: The principal that initiated the session.
|
|
||||||
* @param callback: Invoke the callback when the operation is completed.
|
|
||||||
* NotifySuccess() is called with |id| if a session is
|
|
||||||
* established successfully with the selected device.
|
|
||||||
* Otherwise, NotifyError() is called with a error message.
|
|
||||||
* @param constructor: The constructor for creating a transport builder.
|
|
||||||
*/
|
|
||||||
[noscript] void startSession(in URLArrayRef urls,
|
|
||||||
in DOMString sessionId,
|
|
||||||
in DOMString origin,
|
|
||||||
in DOMString deviceId,
|
|
||||||
in unsigned long long windowId,
|
|
||||||
in nsIDOMEventTarget eventTarget,
|
|
||||||
in nsIPrincipal principal,
|
|
||||||
in nsIPresentationServiceCallback callback,
|
|
||||||
in nsIPresentationTransportBuilderConstructor constructor);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send the message to the session.
|
|
||||||
*
|
|
||||||
* @param sessionId: An ID to identify presentation session.
|
|
||||||
* @param role: Identify the function called by controller or receiver.
|
|
||||||
* @param data: the message being sent out.
|
|
||||||
*/
|
|
||||||
void sendSessionMessage(in DOMString sessionId,
|
|
||||||
in uint8_t role,
|
|
||||||
in DOMString data);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send the binary message to the session.
|
|
||||||
*
|
|
||||||
* @param sessionId: An ID to identify presentation session.
|
|
||||||
* @param role: Identify the function called by controller or receiver.
|
|
||||||
* @param data: the message being sent out.
|
|
||||||
*/
|
|
||||||
void sendSessionBinaryMsg(in DOMString sessionId,
|
|
||||||
in uint8_t role,
|
|
||||||
in ACString data);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send the blob to the session.
|
|
||||||
*
|
|
||||||
* @param sessionId: An ID to identify presentation session.
|
|
||||||
* @param role: Identify the function called by controller or receiver.
|
|
||||||
* @param blob: The input blob to be sent.
|
|
||||||
*/
|
|
||||||
void sendSessionBlob(in DOMString sessionId,
|
|
||||||
in uint8_t role,
|
|
||||||
in nsIDOMBlob blob);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Close the session.
|
|
||||||
*
|
|
||||||
* @param sessionId: An ID to identify presentation session.
|
|
||||||
* @param role: Identify the function called by controller or receiver.
|
|
||||||
*/
|
|
||||||
void closeSession(in DOMString sessionId,
|
|
||||||
in uint8_t role,
|
|
||||||
in uint8_t closedReason);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Terminate the session.
|
|
||||||
*
|
|
||||||
* @param sessionId: An ID to identify presentation session.
|
|
||||||
* @param role: Identify the function called by controller or receiver.
|
|
||||||
*/
|
|
||||||
void terminateSession(in DOMString sessionId,
|
|
||||||
in uint8_t role);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reconnect the session.
|
|
||||||
*
|
|
||||||
* @param url: The request Urls.
|
|
||||||
* @param sessionId: An ID to identify presentation session.
|
|
||||||
* @param role: Identify the function called by controller or receiver.
|
|
||||||
* @param callback: NotifySuccess() is called when a control channel
|
|
||||||
* is opened successfully.
|
|
||||||
* Otherwise, NotifyError() is called with a error message.
|
|
||||||
*/
|
|
||||||
[noscript] void reconnectSession(in URLArrayRef urls,
|
|
||||||
in DOMString sessionId,
|
|
||||||
in uint8_t role,
|
|
||||||
in nsIPresentationServiceCallback callback);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Register an availability listener. Must be called from the main thread.
|
|
||||||
*
|
|
||||||
* @param availabilityUrls: The Urls that this listener is interested in.
|
|
||||||
* @param listener: The listener to register.
|
|
||||||
*/
|
|
||||||
[noscript] void registerAvailabilityListener(
|
|
||||||
in URLArrayRef availabilityUrls,
|
|
||||||
in nsIPresentationAvailabilityListener listener);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Unregister an availability listener. Must be called from the main thread.
|
|
||||||
*
|
|
||||||
* @param availabilityUrls: The Urls that are registered before.
|
|
||||||
* @param listener: The listener to unregister.
|
|
||||||
*/
|
|
||||||
[noscript] void unregisterAvailabilityListener(
|
|
||||||
in URLArrayRef availabilityUrls,
|
|
||||||
in nsIPresentationAvailabilityListener listener);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Register a session listener. Must be called from the main thread.
|
|
||||||
*
|
|
||||||
* @param sessionId: An ID to identify presentation session.
|
|
||||||
* @param role: Identify the function called by controller or receiver.
|
|
||||||
* @param listener: The listener to register.
|
|
||||||
*/
|
|
||||||
void registerSessionListener(in DOMString sessionId,
|
|
||||||
in uint8_t role,
|
|
||||||
in nsIPresentationSessionListener listener);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Unregister a session listener. Must be called from the main thread.
|
|
||||||
*
|
|
||||||
* @param sessionId: An ID to identify presentation session.
|
|
||||||
* @param role: Identify the function called by controller or receiver.
|
|
||||||
*/
|
|
||||||
void unregisterSessionListener(in DOMString sessionId,
|
|
||||||
in uint8_t role);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Register a responding listener. Must be called from the main thread.
|
|
||||||
*
|
|
||||||
* @param windowId: The window ID associated with the listener.
|
|
||||||
* @param listener: The listener to register.
|
|
||||||
*/
|
|
||||||
void registerRespondingListener(in unsigned long long windowId,
|
|
||||||
in nsIPresentationRespondingListener listener);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Unregister a responding listener. Must be called from the main thread.
|
|
||||||
* @param windowId: The window ID associated with the listener.
|
|
||||||
*/
|
|
||||||
void unregisterRespondingListener(in unsigned long long windowId);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Notify the receiver page is ready for presentation use.
|
|
||||||
*
|
|
||||||
* @param sessionId An ID to identify presentation session.
|
|
||||||
* @param windowId The inner window ID associated with the presentation
|
|
||||||
* session.
|
|
||||||
* @param isLoading true if receiver page is loading successfully.
|
|
||||||
* @param constructor: The constructor for creating a transport builder.
|
|
||||||
*/
|
|
||||||
void notifyReceiverReady(in DOMString sessionId,
|
|
||||||
in unsigned long long windowId,
|
|
||||||
in boolean isLoading,
|
|
||||||
in nsIPresentationTransportBuilderConstructor constructor);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Notify the transport is closed
|
|
||||||
*
|
|
||||||
* @param sessionId: An ID to identify presentation session.
|
|
||||||
* @param role: Identify the function called by controller or receiver.
|
|
||||||
* @param reason: the error message. NS_OK indicates it is closed normally.
|
|
||||||
*/
|
|
||||||
void NotifyTransportClosed(in DOMString sessionId,
|
|
||||||
in uint8_t role,
|
|
||||||
in nsresult reason);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Untrack the relevant info about the presentation session if there's any.
|
|
||||||
*
|
|
||||||
* @param sessionId: An ID to identify presentation session.
|
|
||||||
* @param role: Identify the function called by controller or receiver.
|
|
||||||
*/
|
|
||||||
void untrackSessionInfo(in DOMString sessionId, in uint8_t role);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The windowId for building RTCDataChannel session transport
|
|
||||||
*
|
|
||||||
* @param sessionId: An ID to identify presentation session.
|
|
||||||
* @param role: Identify the function called by controller or receiver.
|
|
||||||
*/
|
|
||||||
unsigned long long getWindowIdBySessionId(in DOMString sessionId,
|
|
||||||
in uint8_t role);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Update the mapping of the session ID and window ID.
|
|
||||||
*
|
|
||||||
* @param sessionId: An ID to identify presentation session.
|
|
||||||
* @param role: Identify the function called by controller or receiver.
|
|
||||||
* @param windowId: The inner window ID associated with the presentation
|
|
||||||
* session.
|
|
||||||
*/
|
|
||||||
void updateWindowIdBySessionId(in DOMString sessionId,
|
|
||||||
in uint8_t role,
|
|
||||||
in unsigned long long windowId);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* To build the session transport.
|
|
||||||
* NOTE: This function should be only called at controller side.
|
|
||||||
*
|
|
||||||
* @param sessionId: An ID to identify presentation session.
|
|
||||||
* @param role: Identify the function called by controller or receiver.
|
|
||||||
*/
|
|
||||||
void buildTransport(in DOMString sessionId, in uint8_t role);
|
|
||||||
};
|
|
|
@ -1,35 +0,0 @@
|
||||||
/* 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 "nsISupports.idl"
|
|
||||||
|
|
||||||
interface nsIPresentationDevice;
|
|
||||||
interface nsIPresentationControlChannel;
|
|
||||||
|
|
||||||
%{C++
|
|
||||||
#define PRESENTATION_SESSION_REQUEST_TOPIC "presentation-session-request"
|
|
||||||
#define PRESENTATION_RECONNECT_REQUEST_TOPIC "presentation-reconnect-request"
|
|
||||||
%}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The event of a device requesting for starting or reconnecting
|
|
||||||
* a presentation session. User can monitor the session request
|
|
||||||
* on every device by observing "presentation-sesion-request" for a
|
|
||||||
* new session and "presentation-reconnect-request" for reconnecting.
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(d808a084-d0f8-455a-a8df-5879e05a755b)]
|
|
||||||
interface nsIPresentationSessionRequest: nsISupports
|
|
||||||
{
|
|
||||||
// The device which requesting the presentation session.
|
|
||||||
readonly attribute nsIPresentationDevice device;
|
|
||||||
|
|
||||||
// The URL requested to open by remote device.
|
|
||||||
readonly attribute DOMString url;
|
|
||||||
|
|
||||||
// The Id for representing this session.
|
|
||||||
readonly attribute DOMString presentationId;
|
|
||||||
|
|
||||||
// The control channel for this session.
|
|
||||||
readonly attribute nsIPresentationControlChannel controlChannel;
|
|
||||||
};
|
|
|
@ -1,69 +0,0 @@
|
||||||
/* 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 "nsISupports.idl"
|
|
||||||
|
|
||||||
interface nsIDOMBlob;
|
|
||||||
interface nsIInputStream;
|
|
||||||
interface nsINetAddr;
|
|
||||||
|
|
||||||
%{C++
|
|
||||||
#define PRESENTATION_TCP_SESSION_TRANSPORT_CONTRACTID \
|
|
||||||
"@mozilla.org/presentation/presentationtcpsessiontransport;1"
|
|
||||||
%}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The callback for session transport events.
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(9f158786-41a6-4a10-b29b-9497f25d4b67)]
|
|
||||||
interface nsIPresentationSessionTransportCallback : nsISupports
|
|
||||||
{
|
|
||||||
void notifyTransportReady();
|
|
||||||
void notifyTransportClosed(in nsresult reason);
|
|
||||||
void notifyData(in ACString data, in boolean isBinary);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* App-to-App transport channel for the presentation session.
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(670b7e1b-65be-42b6-a596-be571907fa18)]
|
|
||||||
interface nsIPresentationSessionTransport : nsISupports
|
|
||||||
{
|
|
||||||
// Should be set once the underlying session transport is built
|
|
||||||
attribute nsIPresentationSessionTransportCallback callback;
|
|
||||||
|
|
||||||
// valid for TCP session transport
|
|
||||||
readonly attribute nsINetAddr selfAddress;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enable the notification for incoming data. |notifyData| of
|
|
||||||
* |nsIPresentationSessionTransportCallback| can start getting invoked.
|
|
||||||
* Should set callback before |enableDataNotification| is called.
|
|
||||||
*/
|
|
||||||
void enableDataNotification();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send message to the remote endpoint.
|
|
||||||
* @param data The message to send.
|
|
||||||
*/
|
|
||||||
void send(in DOMString data);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send the binary message to the remote endpoint.
|
|
||||||
* @param data: the message being sent out.
|
|
||||||
*/
|
|
||||||
void sendBinaryMsg(in ACString data);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Send the blob to the remote endpoint.
|
|
||||||
* @param blob: The input blob to be sent.
|
|
||||||
*/
|
|
||||||
void sendBlob(in nsIDOMBlob blob);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Close this session transport.
|
|
||||||
* @param reason The reason for closing this session transport.
|
|
||||||
*/
|
|
||||||
void close(in nsresult reason);
|
|
||||||
};
|
|
|
@ -1,80 +0,0 @@
|
||||||
/* 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 "nsISupports.idl"
|
|
||||||
|
|
||||||
interface nsIPresentationChannelDescription;
|
|
||||||
interface nsISocketTransport;
|
|
||||||
interface mozIDOMWindow;
|
|
||||||
interface nsIPresentationControlChannel;
|
|
||||||
interface nsIPresentationSessionTransport;
|
|
||||||
|
|
||||||
[scriptable, uuid(673f6de1-e253-41b8-9be8-b7ff161fa8dc)]
|
|
||||||
interface nsIPresentationSessionTransportBuilderListener : nsISupports
|
|
||||||
{
|
|
||||||
// Should set |transport.callback| in |onSessionTransport|.
|
|
||||||
void onSessionTransport(in nsIPresentationSessionTransport transport);
|
|
||||||
void onError(in nsresult reason);
|
|
||||||
|
|
||||||
void sendOffer(in nsIPresentationChannelDescription offer);
|
|
||||||
void sendAnswer(in nsIPresentationChannelDescription answer);
|
|
||||||
void sendIceCandidate(in DOMString candidate);
|
|
||||||
void close(in nsresult reason);
|
|
||||||
};
|
|
||||||
|
|
||||||
[scriptable, uuid(2fdbe67d-80f9-48dc-8237-5bef8fa19801)]
|
|
||||||
interface nsIPresentationSessionTransportBuilder : nsISupports
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The constructor for creating a transport builder.
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(706482b2-1b51-4bed-a21d-785a9cfcfac7)]
|
|
||||||
interface nsIPresentationTransportBuilderConstructor : nsISupports
|
|
||||||
{
|
|
||||||
nsIPresentationSessionTransportBuilder createTransportBuilder(in uint8_t type);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builder for TCP session transport
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(cde36d6e-f471-4262-a70d-f932a26b21d9)]
|
|
||||||
interface nsIPresentationTCPSessionTransportBuilder : nsIPresentationSessionTransportBuilder
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The following creation functions will trigger |listener.onSessionTransport|
|
|
||||||
* if the session transport is successfully built, |listener.onError| if some
|
|
||||||
* error occurs during building session transport.
|
|
||||||
*/
|
|
||||||
void buildTCPSenderTransport(in nsISocketTransport aTransport,
|
|
||||||
in nsIPresentationSessionTransportBuilderListener aListener);
|
|
||||||
|
|
||||||
void buildTCPReceiverTransport(in nsIPresentationChannelDescription aDescription,
|
|
||||||
in nsIPresentationSessionTransportBuilderListener aListener);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builder for WebRTC data channel session transport
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(8131c4e0-3a8c-4bc1-a92a-8431473d2fe8)]
|
|
||||||
interface nsIPresentationDataChannelSessionTransportBuilder : nsIPresentationSessionTransportBuilder
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The following creation function will trigger |listener.onSessionTransport|
|
|
||||||
* if the session transport is successfully built, |listener.onError| if some
|
|
||||||
* error occurs during creating session transport. The |notifyConnected| of
|
|
||||||
* |aControlChannel| should be called before calling
|
|
||||||
* |buildDataChannelTransport|.
|
|
||||||
*/
|
|
||||||
void buildDataChannelTransport(in uint8_t aRole,
|
|
||||||
in mozIDOMWindow aWindow,
|
|
||||||
in nsIPresentationSessionTransportBuilderListener aListener);
|
|
||||||
|
|
||||||
// Bug 1275150 - Merge TCP builder with the following APIs
|
|
||||||
void onOffer(in nsIPresentationChannelDescription offer);
|
|
||||||
void onAnswer(in nsIPresentationChannelDescription answer);
|
|
||||||
void onIceCandidate(in DOMString candidate);
|
|
||||||
void notifyDisconnected(in nsresult reason);
|
|
||||||
};
|
|
|
@ -1,33 +0,0 @@
|
||||||
/* 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 "nsISupports.idl"
|
|
||||||
|
|
||||||
interface nsIPresentationDevice;
|
|
||||||
interface nsIPresentationControlChannel;
|
|
||||||
|
|
||||||
%{C++
|
|
||||||
#define PRESENTATION_TERMINATE_REQUEST_TOPIC "presentation-terminate-request"
|
|
||||||
%}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The event of a device requesting for terminating a presentation session. User can
|
|
||||||
* monitor the terminate request on every device by observing "presentation-terminate-request".
|
|
||||||
*/
|
|
||||||
[scriptable, uuid(3ddbf3a4-53ee-4b70-9bbc-58ac90dce6b5)]
|
|
||||||
interface nsIPresentationTerminateRequest: nsISupports
|
|
||||||
{
|
|
||||||
// The device which requesting to terminate presentation session.
|
|
||||||
readonly attribute nsIPresentationDevice device;
|
|
||||||
|
|
||||||
// The Id for representing this session.
|
|
||||||
readonly attribute DOMString presentationId;
|
|
||||||
|
|
||||||
// The control channel for this session.
|
|
||||||
// Should only use this channel to complete session termination.
|
|
||||||
readonly attribute nsIPresentationControlChannel controlChannel;
|
|
||||||
|
|
||||||
// True if termination is initiated by receiver.
|
|
||||||
readonly attribute boolean isFromReceiver;
|
|
||||||
};
|
|
|
@ -1,112 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
|
||||||
/* 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 protocol PContent;
|
|
||||||
include protocol PPresentationRequest;
|
|
||||||
include protocol PPresentationBuilder;
|
|
||||||
|
|
||||||
include InputStreamParams;
|
|
||||||
|
|
||||||
using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
|
|
||||||
using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
struct StartSessionRequest
|
|
||||||
{
|
|
||||||
nsString[] urls;
|
|
||||||
nsString sessionId;
|
|
||||||
nsString origin;
|
|
||||||
nsString deviceId;
|
|
||||||
uint64_t windowId;
|
|
||||||
TabId tabId;
|
|
||||||
Principal principal;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SendSessionMessageRequest
|
|
||||||
{
|
|
||||||
nsString sessionId;
|
|
||||||
uint8_t role;
|
|
||||||
nsString data;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CloseSessionRequest
|
|
||||||
{
|
|
||||||
nsString sessionId;
|
|
||||||
uint8_t role;
|
|
||||||
uint8_t closedReason;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TerminateSessionRequest
|
|
||||||
{
|
|
||||||
nsString sessionId;
|
|
||||||
uint8_t role;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ReconnectSessionRequest
|
|
||||||
{
|
|
||||||
nsString[] urls;
|
|
||||||
nsString sessionId;
|
|
||||||
uint8_t role;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BuildTransportRequest
|
|
||||||
{
|
|
||||||
nsString sessionId;
|
|
||||||
uint8_t role;
|
|
||||||
};
|
|
||||||
|
|
||||||
union PresentationIPCRequest
|
|
||||||
{
|
|
||||||
StartSessionRequest;
|
|
||||||
SendSessionMessageRequest;
|
|
||||||
CloseSessionRequest;
|
|
||||||
TerminateSessionRequest;
|
|
||||||
ReconnectSessionRequest;
|
|
||||||
BuildTransportRequest;
|
|
||||||
};
|
|
||||||
|
|
||||||
sync protocol PPresentation
|
|
||||||
{
|
|
||||||
manager PContent;
|
|
||||||
manages PPresentationBuilder;
|
|
||||||
manages PPresentationRequest;
|
|
||||||
|
|
||||||
child:
|
|
||||||
async NotifyAvailableChange(nsString[] aAvailabilityUrls,
|
|
||||||
bool aAvailable);
|
|
||||||
async NotifySessionStateChange(nsString aSessionId,
|
|
||||||
uint16_t aState,
|
|
||||||
nsresult aReason);
|
|
||||||
async NotifyMessage(nsString aSessionId, nsCString aData, bool aIsBinary);
|
|
||||||
async NotifySessionConnect(uint64_t aWindowId, nsString aSessionId);
|
|
||||||
async NotifyCloseSessionTransport(nsString aSessionId,
|
|
||||||
uint8_t aRole,
|
|
||||||
nsresult aReason);
|
|
||||||
|
|
||||||
async PPresentationBuilder(nsString aSessionId, uint8_t aRole);
|
|
||||||
|
|
||||||
parent:
|
|
||||||
async __delete__();
|
|
||||||
|
|
||||||
async RegisterAvailabilityHandler(nsString[] aAvailabilityUrls);
|
|
||||||
async UnregisterAvailabilityHandler(nsString[] aAvailabilityUrls);
|
|
||||||
|
|
||||||
async RegisterSessionHandler(nsString aSessionId, uint8_t aRole);
|
|
||||||
async UnregisterSessionHandler(nsString aSessionId, uint8_t aRole);
|
|
||||||
|
|
||||||
async RegisterRespondingHandler(uint64_t aWindowId);
|
|
||||||
async UnregisterRespondingHandler(uint64_t aWindowId);
|
|
||||||
|
|
||||||
async PPresentationRequest(PresentationIPCRequest aRequest);
|
|
||||||
|
|
||||||
async NotifyReceiverReady(nsString aSessionId, uint64_t aWindowId, bool aIsLoading);
|
|
||||||
async NotifyTransportClosed(nsString aSessionId, uint8_t aRole, nsresult aReason);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,34 +0,0 @@
|
||||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
|
||||||
/* vim: set ts=2 et sw=2 tw=80: */
|
|
||||||
/* 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 protocol PPresentation;
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
async protocol PPresentationBuilder
|
|
||||||
{
|
|
||||||
manager PPresentation;
|
|
||||||
|
|
||||||
parent:
|
|
||||||
async SendOffer(nsString aSDP);
|
|
||||||
async SendAnswer(nsString aSDP);
|
|
||||||
async SendIceCandidate(nsString aCandidate);
|
|
||||||
async Close(nsresult aReason);
|
|
||||||
|
|
||||||
async OnSessionTransport();
|
|
||||||
async OnSessionTransportError(nsresult aReason);
|
|
||||||
|
|
||||||
child:
|
|
||||||
async OnOffer(nsString aSDP);
|
|
||||||
async OnAnswer(nsString aSDP);
|
|
||||||
async OnIceCandidate(nsString aCandidate);
|
|
||||||
|
|
||||||
async __delete__();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,22 +0,0 @@
|
||||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
|
||||||
/* vim: set ts=2 et sw=2 tw=80: */
|
|
||||||
/* 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 protocol PPresentation;
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
sync protocol PPresentationRequest
|
|
||||||
{
|
|
||||||
manager PPresentation;
|
|
||||||
|
|
||||||
child:
|
|
||||||
async __delete__(nsresult result);
|
|
||||||
async NotifyRequestUrlSelected(nsString aUrl);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,184 +0,0 @@
|
||||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
|
||||||
/* vim: set ts=2 et sw=2 tw=80: */
|
|
||||||
/* 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 "DCPresentationChannelDescription.h"
|
|
||||||
#include "nsComponentManagerUtils.h"
|
|
||||||
#include "nsGlobalWindow.h"
|
|
||||||
#include "PresentationBuilderChild.h"
|
|
||||||
#include "PresentationIPCService.h"
|
|
||||||
#include "nsServiceManagerUtils.h"
|
|
||||||
#include "mozilla/Unused.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(PresentationBuilderChild,
|
|
||||||
nsIPresentationSessionTransportBuilderListener)
|
|
||||||
|
|
||||||
PresentationBuilderChild::PresentationBuilderChild(const nsString& aSessionId,
|
|
||||||
uint8_t aRole)
|
|
||||||
: mSessionId(aSessionId)
|
|
||||||
, mRole(aRole)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult PresentationBuilderChild::Init()
|
|
||||||
{
|
|
||||||
mBuilder = do_CreateInstance("@mozilla.org/presentation/datachanneltransportbuilder;1");
|
|
||||||
if (NS_WARN_IF(!mBuilder)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t windowId = 0;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!service)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_WARN_IF(NS_FAILED(service->GetWindowIdBySessionId(
|
|
||||||
mSessionId,
|
|
||||||
mRole,
|
|
||||||
&windowId)))) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsPIDOMWindowInner* window = nsGlobalWindow::GetInnerWindowWithId(windowId)->AsInner();
|
|
||||||
if (NS_WARN_IF(!window)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mBuilder->BuildDataChannelTransport(mRole, window, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationBuilderChild::ActorDestroy(ActorDestroyReason aWhy)
|
|
||||||
{
|
|
||||||
mBuilder = nullptr;
|
|
||||||
mActorDestroyed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationBuilderChild::RecvOnOffer(const nsString& aSDP)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!mBuilder)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
RefPtr<DCPresentationChannelDescription> description =
|
|
||||||
new DCPresentationChannelDescription(aSDP);
|
|
||||||
|
|
||||||
if (NS_WARN_IF(NS_FAILED(mBuilder->OnOffer(description)))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationBuilderChild::RecvOnAnswer(const nsString& aSDP)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!mBuilder)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
RefPtr<DCPresentationChannelDescription> description =
|
|
||||||
new DCPresentationChannelDescription(aSDP);
|
|
||||||
|
|
||||||
if (NS_WARN_IF(NS_FAILED(mBuilder->OnAnswer(description)))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationBuilderChild::RecvOnIceCandidate(const nsString& aCandidate)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(mBuilder && NS_FAILED(mBuilder->OnIceCandidate(aCandidate)))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsPresentationSessionTransportBuilderListener
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationBuilderChild::OnSessionTransport(nsIPresentationSessionTransport* aTransport)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(mActorDestroyed || !SendOnSessionTransport())){
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
NS_WARNING_ASSERTION(service, "no presentation service");
|
|
||||||
if (service) {
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(static_cast<PresentationIPCService*>(service.get())->
|
|
||||||
NotifySessionTransport(mSessionId, mRole, aTransport)));
|
|
||||||
}
|
|
||||||
mBuilder = nullptr;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationBuilderChild::OnError(nsresult reason)
|
|
||||||
{
|
|
||||||
mBuilder = nullptr;
|
|
||||||
|
|
||||||
if (NS_WARN_IF(mActorDestroyed || !SendOnSessionTransportError(reason))){
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationBuilderChild::SendOffer(nsIPresentationChannelDescription* aOffer)
|
|
||||||
{
|
|
||||||
nsAutoString SDP;
|
|
||||||
nsresult rv = aOffer->GetDataChannelSDP(SDP);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_WARN_IF(mActorDestroyed || !SendSendOffer(SDP))){
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationBuilderChild::SendAnswer(nsIPresentationChannelDescription* aAnswer)
|
|
||||||
{
|
|
||||||
nsAutoString SDP;
|
|
||||||
nsresult rv = aAnswer->GetDataChannelSDP(SDP);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_WARN_IF(mActorDestroyed || !SendSendAnswer(SDP))){
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationBuilderChild::SendIceCandidate(const nsAString& candidate)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(mActorDestroyed || !SendSendIceCandidate(nsString(candidate)))) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationBuilderChild::Close(nsresult reason)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(mActorDestroyed || !SendClose(reason))) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
|
||||||
/* vim: set ts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationBuilderChild_h
|
|
||||||
#define mozilla_dom_PresentationBuilderChild_h
|
|
||||||
|
|
||||||
#include "mozilla/dom/PPresentationBuilderChild.h"
|
|
||||||
#include "nsIPresentationSessionTransportBuilder.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class PresentationBuilderChild final: public PPresentationBuilderChild
|
|
||||||
, public nsIPresentationSessionTransportBuilderListener
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIPRESENTATIONSESSIONTRANSPORTBUILDERLISTENER
|
|
||||||
|
|
||||||
explicit PresentationBuilderChild(const nsString& aSessionId,
|
|
||||||
uint8_t aRole);
|
|
||||||
|
|
||||||
nsresult Init();
|
|
||||||
|
|
||||||
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
|
||||||
|
|
||||||
virtual bool RecvOnOffer(const nsString& aSDP) override;
|
|
||||||
|
|
||||||
virtual bool RecvOnAnswer(const nsString& aSDP) override;
|
|
||||||
|
|
||||||
virtual bool RecvOnIceCandidate(const nsString& aCandidate) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~PresentationBuilderChild() = default;
|
|
||||||
|
|
||||||
nsString mSessionId;
|
|
||||||
uint8_t mRole;
|
|
||||||
bool mActorDestroyed = false;
|
|
||||||
nsCOMPtr<nsIPresentationDataChannelSessionTransportBuilder> mBuilder;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationBuilderChild_h
|
|
|
@ -1,267 +0,0 @@
|
||||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
|
||||||
/* vim: set ts=2 et sw=2 tw=80: */
|
|
||||||
/* 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 "DCPresentationChannelDescription.h"
|
|
||||||
#include "PresentationBuilderParent.h"
|
|
||||||
#include "PresentationSessionInfo.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class PresentationSessionTransportIPC final :
|
|
||||||
public nsIPresentationSessionTransport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIPRESENTATIONSESSIONTRANSPORT
|
|
||||||
|
|
||||||
PresentationSessionTransportIPC(PresentationParent* aParent,
|
|
||||||
const nsAString& aSessionId,
|
|
||||||
uint8_t aRole)
|
|
||||||
: mParent(aParent)
|
|
||||||
, mSessionId(aSessionId)
|
|
||||||
, mRole(aRole)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mParent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~PresentationSessionTransportIPC() = default;
|
|
||||||
|
|
||||||
RefPtr<PresentationParent> mParent;
|
|
||||||
nsString mSessionId;
|
|
||||||
uint8_t mRole;
|
|
||||||
};
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(PresentationSessionTransportIPC,
|
|
||||||
nsIPresentationSessionTransport)
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationSessionTransportIPC::GetCallback(
|
|
||||||
nsIPresentationSessionTransportCallback** aCallback)
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationSessionTransportIPC::SetCallback(
|
|
||||||
nsIPresentationSessionTransportCallback* aCallback)
|
|
||||||
{
|
|
||||||
if (aCallback) {
|
|
||||||
aCallback->NotifyTransportReady();
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationSessionTransportIPC::GetSelfAddress(nsINetAddr** aSelfAddress)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(false, "Not expected.");
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationSessionTransportIPC::EnableDataNotification()
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationSessionTransportIPC::Send(const nsAString& aData)
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationSessionTransportIPC::SendBinaryMsg(const nsACString& aData)
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationSessionTransportIPC::SendBlob(nsIDOMBlob* aBlob)
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationSessionTransportIPC::Close(nsresult aReason)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!mParent->SendNotifyCloseSessionTransport(mSessionId,
|
|
||||||
mRole,
|
|
||||||
aReason))) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(PresentationBuilderParent,
|
|
||||||
nsIPresentationSessionTransportBuilder,
|
|
||||||
nsIPresentationDataChannelSessionTransportBuilder)
|
|
||||||
|
|
||||||
PresentationBuilderParent::PresentationBuilderParent(PresentationParent* aParent)
|
|
||||||
: mParent(aParent)
|
|
||||||
{
|
|
||||||
MOZ_COUNT_CTOR(PresentationBuilderParent);
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationBuilderParent::~PresentationBuilderParent()
|
|
||||||
{
|
|
||||||
MOZ_COUNT_DTOR(PresentationBuilderParent);
|
|
||||||
|
|
||||||
if (mNeedDestroyActor) {
|
|
||||||
Unused << NS_WARN_IF(!Send__delete__(this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationBuilderParent::BuildDataChannelTransport(
|
|
||||||
uint8_t aRole,
|
|
||||||
mozIDOMWindow* aWindow, /* unused */
|
|
||||||
nsIPresentationSessionTransportBuilderListener* aListener)
|
|
||||||
{
|
|
||||||
mBuilderListener = aListener;
|
|
||||||
|
|
||||||
RefPtr<PresentationSessionInfo> info = static_cast<PresentationSessionInfo*>(aListener);
|
|
||||||
nsAutoString sessionId(info->GetSessionId());
|
|
||||||
if (NS_WARN_IF(!mParent->SendPPresentationBuilderConstructor(this,
|
|
||||||
sessionId,
|
|
||||||
aRole))) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
mIPCSessionTransport = new PresentationSessionTransportIPC(mParent,
|
|
||||||
sessionId,
|
|
||||||
aRole);
|
|
||||||
mNeedDestroyActor = true;
|
|
||||||
mParent = nullptr;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationBuilderParent::OnIceCandidate(const nsAString& aCandidate)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!SendOnIceCandidate(nsString(aCandidate)))){
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationBuilderParent::OnOffer(nsIPresentationChannelDescription* aDescription)
|
|
||||||
{
|
|
||||||
nsAutoString SDP;
|
|
||||||
nsresult rv = aDescription->GetDataChannelSDP(SDP);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!SendOnOffer(SDP))){
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationBuilderParent::OnAnswer(nsIPresentationChannelDescription* aDescription)
|
|
||||||
{
|
|
||||||
nsAutoString SDP;
|
|
||||||
nsresult rv = aDescription->GetDataChannelSDP(SDP);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!SendOnAnswer(SDP))){
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationBuilderParent::NotifyDisconnected(nsresult aReason)
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationBuilderParent::ActorDestroy(ActorDestroyReason aWhy)
|
|
||||||
{
|
|
||||||
mNeedDestroyActor = false;
|
|
||||||
mParent = nullptr;
|
|
||||||
mBuilderListener = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationBuilderParent::RecvSendOffer(const nsString& aSDP)
|
|
||||||
{
|
|
||||||
RefPtr<DCPresentationChannelDescription> description =
|
|
||||||
new DCPresentationChannelDescription(aSDP);
|
|
||||||
if (NS_WARN_IF(!mBuilderListener ||
|
|
||||||
NS_FAILED(mBuilderListener->SendOffer(description)))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationBuilderParent::RecvSendAnswer(const nsString& aSDP)
|
|
||||||
{
|
|
||||||
RefPtr<DCPresentationChannelDescription> description =
|
|
||||||
new DCPresentationChannelDescription(aSDP);
|
|
||||||
if (NS_WARN_IF(!mBuilderListener ||
|
|
||||||
NS_FAILED(mBuilderListener->SendAnswer(description)))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationBuilderParent::RecvSendIceCandidate(const nsString& aCandidate)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!mBuilderListener ||
|
|
||||||
NS_FAILED(mBuilderListener->SendIceCandidate(aCandidate)))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationBuilderParent::RecvClose(const nsresult& aReason)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!mBuilderListener ||
|
|
||||||
NS_FAILED(mBuilderListener->Close(aReason)))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delegate to nsIPresentationSessionTransportBuilderListener
|
|
||||||
bool
|
|
||||||
PresentationBuilderParent::RecvOnSessionTransport()
|
|
||||||
{
|
|
||||||
RefPtr<PresentationBuilderParent> kungFuDeathGrip = this;
|
|
||||||
Unused <<
|
|
||||||
NS_WARN_IF(!mBuilderListener ||
|
|
||||||
NS_FAILED(mBuilderListener->OnSessionTransport(mIPCSessionTransport)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationBuilderParent::RecvOnSessionTransportError(const nsresult& aReason)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!mBuilderListener ||
|
|
||||||
NS_FAILED(mBuilderListener->OnError(aReason)))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,52 +0,0 @@
|
||||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
|
||||||
/* vim: set ts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationBuilderParent_h__
|
|
||||||
#define mozilla_dom_PresentationBuilderParent_h__
|
|
||||||
|
|
||||||
#include "mozilla/dom/PPresentationBuilderParent.h"
|
|
||||||
#include "PresentationParent.h"
|
|
||||||
#include "nsIPresentationSessionTransportBuilder.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class PresentationBuilderParent final: public PPresentationBuilderParent
|
|
||||||
, public nsIPresentationDataChannelSessionTransportBuilder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIPRESENTATIONSESSIONTRANSPORTBUILDER
|
|
||||||
NS_DECL_NSIPRESENTATIONDATACHANNELSESSIONTRANSPORTBUILDER
|
|
||||||
|
|
||||||
explicit PresentationBuilderParent(PresentationParent* aParent);
|
|
||||||
|
|
||||||
virtual bool RecvSendOffer(const nsString& aSDP) override;
|
|
||||||
|
|
||||||
virtual bool RecvSendAnswer(const nsString& aSDP) override;
|
|
||||||
|
|
||||||
virtual bool RecvSendIceCandidate(const nsString& aCandidate) override;
|
|
||||||
|
|
||||||
virtual bool RecvClose(const nsresult& aReason) override;
|
|
||||||
|
|
||||||
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
|
||||||
|
|
||||||
virtual bool RecvOnSessionTransport() override;
|
|
||||||
|
|
||||||
virtual bool RecvOnSessionTransportError(const nsresult& aReason) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~PresentationBuilderParent();
|
|
||||||
bool mNeedDestroyActor = false;
|
|
||||||
RefPtr<PresentationParent> mParent;
|
|
||||||
nsCOMPtr<nsIPresentationSessionTransportBuilderListener> mBuilderListener;
|
|
||||||
nsCOMPtr<nsIPresentationSessionTransport> mIPCSessionTransport;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationBuilderParent_h__
|
|
|
@ -1,198 +0,0 @@
|
||||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
|
||||||
/* vim: set ts=2 et sw=2 tw=80: */
|
|
||||||
/* 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 "DCPresentationChannelDescription.h"
|
|
||||||
#include "mozilla/StaticPtr.h"
|
|
||||||
#include "PresentationBuilderChild.h"
|
|
||||||
#include "PresentationChild.h"
|
|
||||||
#include "PresentationIPCService.h"
|
|
||||||
#include "nsThreadUtils.h"
|
|
||||||
|
|
||||||
using namespace mozilla;
|
|
||||||
using namespace mozilla::dom;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Implementation of PresentationChild
|
|
||||||
*/
|
|
||||||
|
|
||||||
PresentationChild::PresentationChild(PresentationIPCService* aService)
|
|
||||||
: mActorDestroyed(false)
|
|
||||||
, mService(aService)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mService);
|
|
||||||
|
|
||||||
MOZ_COUNT_CTOR(PresentationChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationChild::~PresentationChild()
|
|
||||||
{
|
|
||||||
MOZ_COUNT_DTOR(PresentationChild);
|
|
||||||
|
|
||||||
if (!mActorDestroyed) {
|
|
||||||
Send__delete__(this);
|
|
||||||
}
|
|
||||||
mService = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationChild::ActorDestroy(ActorDestroyReason aWhy)
|
|
||||||
{
|
|
||||||
mActorDestroyed = true;
|
|
||||||
mService->NotifyPresentationChildDestroyed();
|
|
||||||
mService = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
PPresentationRequestChild*
|
|
||||||
PresentationChild::AllocPPresentationRequestChild(const PresentationIPCRequest& aRequest)
|
|
||||||
{
|
|
||||||
NS_NOTREACHED("We should never be manually allocating PPresentationRequestChild actors");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationChild::DeallocPPresentationRequestChild(PPresentationRequestChild* aActor)
|
|
||||||
{
|
|
||||||
delete aActor;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PresentationChild::RecvPPresentationBuilderConstructor(
|
|
||||||
PPresentationBuilderChild* aActor,
|
|
||||||
const nsString& aSessionId,
|
|
||||||
const uint8_t& aRole)
|
|
||||||
{
|
|
||||||
// Child will build the session transport
|
|
||||||
PresentationBuilderChild* actor = static_cast<PresentationBuilderChild*>(aActor);
|
|
||||||
return NS_WARN_IF(NS_FAILED(actor->Init())) ? false : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
PPresentationBuilderChild*
|
|
||||||
PresentationChild::AllocPPresentationBuilderChild(const nsString& aSessionId,
|
|
||||||
const uint8_t& aRole)
|
|
||||||
{
|
|
||||||
RefPtr<PresentationBuilderChild> actor
|
|
||||||
= new PresentationBuilderChild(aSessionId, aRole);
|
|
||||||
|
|
||||||
return actor.forget().take();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationChild::DeallocPPresentationBuilderChild(PPresentationBuilderChild* aActor)
|
|
||||||
{
|
|
||||||
RefPtr<PresentationBuilderChild> actor =
|
|
||||||
dont_AddRef(static_cast<PresentationBuilderChild*>(aActor));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationChild::RecvNotifyAvailableChange(
|
|
||||||
nsTArray<nsString>&& aAvailabilityUrls,
|
|
||||||
const bool& aAvailable)
|
|
||||||
{
|
|
||||||
if (mService) {
|
|
||||||
Unused <<
|
|
||||||
NS_WARN_IF(NS_FAILED(mService->NotifyAvailableChange(aAvailabilityUrls,
|
|
||||||
aAvailable)));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationChild::RecvNotifySessionStateChange(const nsString& aSessionId,
|
|
||||||
const uint16_t& aState,
|
|
||||||
const nsresult& aReason)
|
|
||||||
{
|
|
||||||
if (mService) {
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mService->NotifySessionStateChange(aSessionId,
|
|
||||||
aState,
|
|
||||||
aReason)));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationChild::RecvNotifyMessage(const nsString& aSessionId,
|
|
||||||
const nsCString& aData,
|
|
||||||
const bool& aIsBinary)
|
|
||||||
{
|
|
||||||
if (mService) {
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mService->NotifyMessage(aSessionId,
|
|
||||||
aData,
|
|
||||||
aIsBinary)));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationChild::RecvNotifySessionConnect(const uint64_t& aWindowId,
|
|
||||||
const nsString& aSessionId)
|
|
||||||
{
|
|
||||||
if (mService) {
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mService->NotifySessionConnect(aWindowId, aSessionId)));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationChild::RecvNotifyCloseSessionTransport(const nsString& aSessionId,
|
|
||||||
const uint8_t& aRole,
|
|
||||||
const nsresult& aReason)
|
|
||||||
{
|
|
||||||
if (mService) {
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(
|
|
||||||
mService->CloseContentSessionTransport(aSessionId, aRole, aReason)));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Implementation of PresentationRequestChild
|
|
||||||
*/
|
|
||||||
|
|
||||||
PresentationRequestChild::PresentationRequestChild(nsIPresentationServiceCallback* aCallback)
|
|
||||||
: mActorDestroyed(false)
|
|
||||||
, mCallback(aCallback)
|
|
||||||
{
|
|
||||||
MOZ_COUNT_CTOR(PresentationRequestChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationRequestChild::~PresentationRequestChild()
|
|
||||||
{
|
|
||||||
MOZ_COUNT_DTOR(PresentationRequestChild);
|
|
||||||
|
|
||||||
mCallback = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationRequestChild::ActorDestroy(ActorDestroyReason aWhy)
|
|
||||||
{
|
|
||||||
mActorDestroyed = true;
|
|
||||||
mCallback = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationRequestChild::Recv__delete__(const nsresult& aResult)
|
|
||||||
{
|
|
||||||
if (mActorDestroyed) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCallback) {
|
|
||||||
if (NS_FAILED(aResult)) {
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mCallback->NotifyError(aResult)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationRequestChild::RecvNotifyRequestUrlSelected(const nsString& aUrl)
|
|
||||||
{
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mCallback->NotifySuccess(aUrl)));
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -1,101 +0,0 @@
|
||||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
|
||||||
/* vim: set ts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationChild_h
|
|
||||||
#define mozilla_dom_PresentationChild_h
|
|
||||||
|
|
||||||
#include "mozilla/dom/PPresentationBuilderChild.h"
|
|
||||||
#include "mozilla/dom/PPresentationChild.h"
|
|
||||||
#include "mozilla/dom/PPresentationRequestChild.h"
|
|
||||||
|
|
||||||
class nsIPresentationServiceCallback;
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class PresentationIPCService;
|
|
||||||
|
|
||||||
class PresentationChild final : public PPresentationChild
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit PresentationChild(PresentationIPCService* aService);
|
|
||||||
|
|
||||||
virtual void
|
|
||||||
ActorDestroy(ActorDestroyReason aWhy) override;
|
|
||||||
|
|
||||||
virtual PPresentationRequestChild*
|
|
||||||
AllocPPresentationRequestChild(const PresentationIPCRequest& aRequest) override;
|
|
||||||
|
|
||||||
virtual bool
|
|
||||||
DeallocPPresentationRequestChild(PPresentationRequestChild* aActor) override;
|
|
||||||
|
|
||||||
bool RecvPPresentationBuilderConstructor(PPresentationBuilderChild* aActor,
|
|
||||||
const nsString& aSessionId,
|
|
||||||
const uint8_t& aRole) override;
|
|
||||||
|
|
||||||
virtual PPresentationBuilderChild*
|
|
||||||
AllocPPresentationBuilderChild(const nsString& aSessionId, const uint8_t& aRole) override;
|
|
||||||
|
|
||||||
virtual bool
|
|
||||||
DeallocPPresentationBuilderChild(PPresentationBuilderChild* aActor) override;
|
|
||||||
|
|
||||||
virtual bool
|
|
||||||
RecvNotifyAvailableChange(nsTArray<nsString>&& aAvailabilityUrls,
|
|
||||||
const bool& aAvailable) override;
|
|
||||||
|
|
||||||
virtual bool
|
|
||||||
RecvNotifySessionStateChange(const nsString& aSessionId,
|
|
||||||
const uint16_t& aState,
|
|
||||||
const nsresult& aReason) override;
|
|
||||||
|
|
||||||
virtual bool
|
|
||||||
RecvNotifyMessage(const nsString& aSessionId,
|
|
||||||
const nsCString& aData,
|
|
||||||
const bool& aIsBinary) override;
|
|
||||||
|
|
||||||
virtual bool
|
|
||||||
RecvNotifySessionConnect(const uint64_t& aWindowId,
|
|
||||||
const nsString& aSessionId) override;
|
|
||||||
|
|
||||||
virtual bool
|
|
||||||
RecvNotifyCloseSessionTransport(const nsString& aSessionId,
|
|
||||||
const uint8_t& aRole,
|
|
||||||
const nsresult& aReason) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~PresentationChild();
|
|
||||||
|
|
||||||
bool mActorDestroyed = false;
|
|
||||||
RefPtr<PresentationIPCService> mService;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PresentationRequestChild final : public PPresentationRequestChild
|
|
||||||
{
|
|
||||||
friend class PresentationChild;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit PresentationRequestChild(nsIPresentationServiceCallback* aCallback);
|
|
||||||
|
|
||||||
virtual void
|
|
||||||
ActorDestroy(ActorDestroyReason aWhy) override;
|
|
||||||
|
|
||||||
virtual bool
|
|
||||||
Recv__delete__(const nsresult& aResult) override;
|
|
||||||
|
|
||||||
virtual bool
|
|
||||||
RecvNotifyRequestUrlSelected(const nsString& aUrl) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~PresentationRequestChild();
|
|
||||||
|
|
||||||
bool mActorDestroyed = false;
|
|
||||||
nsCOMPtr<nsIPresentationServiceCallback> mCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationChild_h
|
|
|
@ -1,109 +0,0 @@
|
||||||
/* -*- 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 "nsServiceManagerUtils.h"
|
|
||||||
#include "PresentationContentSessionInfo.h"
|
|
||||||
#include "PresentationIPCService.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(PresentationContentSessionInfo,
|
|
||||||
nsIPresentationSessionTransportCallback);
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationContentSessionInfo::Init() {
|
|
||||||
if (NS_WARN_IF(NS_FAILED(mTransport->SetCallback(this)))) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
if (NS_WARN_IF(NS_FAILED(mTransport->EnableDataNotification()))) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationContentSessionInfo::Send(const nsAString& aData)
|
|
||||||
{
|
|
||||||
if (!mTransport) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mTransport->Send(aData);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationContentSessionInfo::SendBinaryMsg(const nsACString& aData)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!mTransport)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mTransport->SendBinaryMsg(aData);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationContentSessionInfo::SendBlob(nsIDOMBlob* aBlob)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!mTransport)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mTransport->SendBlob(aBlob);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationContentSessionInfo::Close(nsresult aReason)
|
|
||||||
{
|
|
||||||
if (!mTransport) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mTransport->Close(aReason);
|
|
||||||
}
|
|
||||||
|
|
||||||
// nsIPresentationSessionTransportCallback
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationContentSessionInfo::NotifyTransportReady()
|
|
||||||
{
|
|
||||||
// do nothing since |onSessionTransport| implies this
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationContentSessionInfo::NotifyTransportClosed(nsresult aReason)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
// Nullify |mTransport| here so it won't try to re-close |mTransport| in
|
|
||||||
// potential subsequent |Shutdown| calls.
|
|
||||||
mTransport = nullptr;
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!service)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
return static_cast<PresentationIPCService*>(service.get())->
|
|
||||||
NotifyTransportClosed(mSessionId, mRole, aReason);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationContentSessionInfo::NotifyData(const nsACString& aData,
|
|
||||||
bool aIsBinary)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationService> service =
|
|
||||||
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
if (NS_WARN_IF(!service)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
return static_cast<PresentationIPCService*>(service.get())->
|
|
||||||
NotifyMessage(mSessionId, aData, aIsBinary);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,62 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationContentSessionInfo_h
|
|
||||||
#define mozilla_dom_PresentationContentSessionInfo_h
|
|
||||||
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsIPresentationSessionTransport.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* PresentationContentSessionInfo manages nsIPresentationSessionTransport and
|
|
||||||
* delegates the callbacks to PresentationIPCService. Only lives in content
|
|
||||||
* process.
|
|
||||||
*/
|
|
||||||
class PresentationContentSessionInfo final : public nsIPresentationSessionTransportCallback
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIPRESENTATIONSESSIONTRANSPORTCALLBACK
|
|
||||||
|
|
||||||
PresentationContentSessionInfo(const nsAString& aSessionId,
|
|
||||||
uint8_t aRole,
|
|
||||||
nsIPresentationSessionTransport* aTransport)
|
|
||||||
: mSessionId(aSessionId)
|
|
||||||
, mRole(aRole)
|
|
||||||
, mTransport(aTransport)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(XRE_IsContentProcess());
|
|
||||||
MOZ_ASSERT(!aSessionId.IsEmpty());
|
|
||||||
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
|
|
||||||
aRole == nsIPresentationService::ROLE_RECEIVER);
|
|
||||||
MOZ_ASSERT(aTransport);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult Init();
|
|
||||||
|
|
||||||
nsresult Send(const nsAString& aData);
|
|
||||||
|
|
||||||
nsresult SendBinaryMsg(const nsACString& aData);
|
|
||||||
|
|
||||||
nsresult SendBlob(nsIDOMBlob* aBlob);
|
|
||||||
|
|
||||||
nsresult Close(nsresult aReason);
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~PresentationContentSessionInfo() {}
|
|
||||||
|
|
||||||
nsString mSessionId;
|
|
||||||
uint8_t mRole;
|
|
||||||
nsCOMPtr<nsIPresentationSessionTransport> mTransport;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationContentSessionInfo_h
|
|
|
@ -1,538 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
|
||||||
/* 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 "mozilla/dom/ContentChild.h"
|
|
||||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
|
||||||
#include "mozilla/dom/PPresentation.h"
|
|
||||||
#include "mozilla/dom/TabParent.h"
|
|
||||||
#include "mozilla/ipc/InputStreamUtils.h"
|
|
||||||
#include "mozilla/ipc/URIUtils.h"
|
|
||||||
#include "nsGlobalWindow.h"
|
|
||||||
#include "nsIPresentationListener.h"
|
|
||||||
#include "PresentationCallbacks.h"
|
|
||||||
#include "PresentationChild.h"
|
|
||||||
#include "PresentationContentSessionInfo.h"
|
|
||||||
#include "PresentationIPCService.h"
|
|
||||||
#include "PresentationLog.h"
|
|
||||||
|
|
||||||
using namespace mozilla;
|
|
||||||
using namespace mozilla::dom;
|
|
||||||
using namespace mozilla::ipc;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
PresentationChild* sPresentationChild;
|
|
||||||
|
|
||||||
} // anonymous
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(PresentationIPCService,
|
|
||||||
nsIPresentationService,
|
|
||||||
nsIPresentationAvailabilityListener)
|
|
||||||
|
|
||||||
PresentationIPCService::PresentationIPCService()
|
|
||||||
{
|
|
||||||
ContentChild* contentChild = ContentChild::GetSingleton();
|
|
||||||
if (NS_WARN_IF(!contentChild)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sPresentationChild = new PresentationChild(this);
|
|
||||||
Unused <<
|
|
||||||
NS_WARN_IF(!contentChild->SendPPresentationConstructor(sPresentationChild));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual */
|
|
||||||
PresentationIPCService::~PresentationIPCService()
|
|
||||||
{
|
|
||||||
Shutdown();
|
|
||||||
|
|
||||||
mSessionListeners.Clear();
|
|
||||||
mSessionInfoAtController.Clear();
|
|
||||||
mSessionInfoAtReceiver.Clear();
|
|
||||||
sPresentationChild = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::StartSession(
|
|
||||||
const nsTArray<nsString>& aUrls,
|
|
||||||
const nsAString& aSessionId,
|
|
||||||
const nsAString& aOrigin,
|
|
||||||
const nsAString& aDeviceId,
|
|
||||||
uint64_t aWindowId,
|
|
||||||
nsIDOMEventTarget* aEventTarget,
|
|
||||||
nsIPrincipal* aPrincipal,
|
|
||||||
nsIPresentationServiceCallback* aCallback,
|
|
||||||
nsIPresentationTransportBuilderConstructor* aBuilderConstructor)
|
|
||||||
{
|
|
||||||
if (aWindowId != 0) {
|
|
||||||
AddRespondingSessionId(aWindowId,
|
|
||||||
aSessionId,
|
|
||||||
nsIPresentationService::ROLE_CONTROLLER);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsPIDOMWindowInner* window =
|
|
||||||
nsGlobalWindow::GetInnerWindowWithId(aWindowId)->AsInner();
|
|
||||||
TabId tabId = TabParent::GetTabIdFrom(window->GetDocShell());
|
|
||||||
|
|
||||||
return SendRequest(aCallback, StartSessionRequest(aUrls,
|
|
||||||
nsString(aSessionId),
|
|
||||||
nsString(aOrigin),
|
|
||||||
nsString(aDeviceId),
|
|
||||||
aWindowId,
|
|
||||||
tabId,
|
|
||||||
IPC::Principal(aPrincipal)));
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::SendSessionMessage(const nsAString& aSessionId,
|
|
||||||
uint8_t aRole,
|
|
||||||
const nsAString& aData)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(!aSessionId.IsEmpty());
|
|
||||||
MOZ_ASSERT(!aData.IsEmpty());
|
|
||||||
|
|
||||||
RefPtr<PresentationContentSessionInfo> info =
|
|
||||||
GetSessionInfo(aSessionId, aRole);
|
|
||||||
// data channel session transport is maintained by content process
|
|
||||||
if (info) {
|
|
||||||
return info->Send(aData);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SendRequest(nullptr, SendSessionMessageRequest(nsString(aSessionId),
|
|
||||||
aRole,
|
|
||||||
nsString(aData)));
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::SendSessionBinaryMsg(const nsAString& aSessionId,
|
|
||||||
uint8_t aRole,
|
|
||||||
const nsACString &aData)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
MOZ_ASSERT(!aData.IsEmpty());
|
|
||||||
MOZ_ASSERT(!aSessionId.IsEmpty());
|
|
||||||
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
|
|
||||||
aRole == nsIPresentationService::ROLE_RECEIVER);
|
|
||||||
|
|
||||||
RefPtr<PresentationContentSessionInfo> info =
|
|
||||||
GetSessionInfo(aSessionId, aRole);
|
|
||||||
// data channel session transport is maintained by content process
|
|
||||||
if (info) {
|
|
||||||
return info->SendBinaryMsg(aData);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::SendSessionBlob(const nsAString& aSessionId,
|
|
||||||
uint8_t aRole,
|
|
||||||
nsIDOMBlob* aBlob)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
MOZ_ASSERT(!aSessionId.IsEmpty());
|
|
||||||
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
|
|
||||||
aRole == nsIPresentationService::ROLE_RECEIVER);
|
|
||||||
MOZ_ASSERT(aBlob);
|
|
||||||
|
|
||||||
RefPtr<PresentationContentSessionInfo> info =
|
|
||||||
GetSessionInfo(aSessionId, aRole);
|
|
||||||
// data channel session transport is maintained by content process
|
|
||||||
if (info) {
|
|
||||||
return info->SendBlob(aBlob);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::CloseSession(const nsAString& aSessionId,
|
|
||||||
uint8_t aRole,
|
|
||||||
uint8_t aClosedReason)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(!aSessionId.IsEmpty());
|
|
||||||
|
|
||||||
nsresult rv = SendRequest(nullptr, CloseSessionRequest(nsString(aSessionId),
|
|
||||||
aRole,
|
|
||||||
aClosedReason));
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<PresentationContentSessionInfo> info =
|
|
||||||
GetSessionInfo(aSessionId, aRole);
|
|
||||||
if (info) {
|
|
||||||
return info->Close(NS_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::TerminateSession(const nsAString& aSessionId,
|
|
||||||
uint8_t aRole)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(!aSessionId.IsEmpty());
|
|
||||||
|
|
||||||
nsresult rv = SendRequest(nullptr, TerminateSessionRequest(nsString(aSessionId), aRole));
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<PresentationContentSessionInfo> info =
|
|
||||||
GetSessionInfo(aSessionId, aRole);
|
|
||||||
if (info) {
|
|
||||||
return info->Close(NS_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::ReconnectSession(const nsTArray<nsString>& aUrls,
|
|
||||||
const nsAString& aSessionId,
|
|
||||||
uint8_t aRole,
|
|
||||||
nsIPresentationServiceCallback* aCallback)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(!aSessionId.IsEmpty());
|
|
||||||
|
|
||||||
if (aRole != nsIPresentationService::ROLE_CONTROLLER) {
|
|
||||||
MOZ_ASSERT(false, "Only controller can call ReconnectSession.");
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SendRequest(aCallback, ReconnectSessionRequest(aUrls,
|
|
||||||
nsString(aSessionId),
|
|
||||||
aRole));
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::BuildTransport(const nsAString& aSessionId,
|
|
||||||
uint8_t aRole)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(!aSessionId.IsEmpty());
|
|
||||||
|
|
||||||
if (aRole != nsIPresentationService::ROLE_CONTROLLER) {
|
|
||||||
MOZ_ASSERT(false, "Only controller can call ReconnectSession.");
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SendRequest(nullptr, BuildTransportRequest(nsString(aSessionId),
|
|
||||||
aRole));
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationIPCService::SendRequest(nsIPresentationServiceCallback* aCallback,
|
|
||||||
const PresentationIPCRequest& aRequest)
|
|
||||||
{
|
|
||||||
if (sPresentationChild) {
|
|
||||||
PresentationRequestChild* actor = new PresentationRequestChild(aCallback);
|
|
||||||
Unused << NS_WARN_IF(!sPresentationChild->SendPPresentationRequestConstructor(actor, aRequest));
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::RegisterAvailabilityListener(
|
|
||||||
const nsTArray<nsString>& aAvailabilityUrls,
|
|
||||||
nsIPresentationAvailabilityListener* aListener)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
MOZ_ASSERT(!aAvailabilityUrls.IsEmpty());
|
|
||||||
MOZ_ASSERT(aListener);
|
|
||||||
|
|
||||||
nsTArray<nsString> addedUrls;
|
|
||||||
mAvailabilityManager.AddAvailabilityListener(aAvailabilityUrls,
|
|
||||||
aListener,
|
|
||||||
addedUrls);
|
|
||||||
|
|
||||||
if (sPresentationChild && !addedUrls.IsEmpty()) {
|
|
||||||
Unused <<
|
|
||||||
NS_WARN_IF(
|
|
||||||
!sPresentationChild->SendRegisterAvailabilityHandler(addedUrls));
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::UnregisterAvailabilityListener(
|
|
||||||
const nsTArray<nsString>& aAvailabilityUrls,
|
|
||||||
nsIPresentationAvailabilityListener* aListener)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
nsTArray<nsString> removedUrls;
|
|
||||||
mAvailabilityManager.RemoveAvailabilityListener(aAvailabilityUrls,
|
|
||||||
aListener,
|
|
||||||
removedUrls);
|
|
||||||
|
|
||||||
if (sPresentationChild && !removedUrls.IsEmpty()) {
|
|
||||||
Unused <<
|
|
||||||
NS_WARN_IF(
|
|
||||||
!sPresentationChild->SendUnregisterAvailabilityHandler(removedUrls));
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::RegisterSessionListener(const nsAString& aSessionId,
|
|
||||||
uint8_t aRole,
|
|
||||||
nsIPresentationSessionListener* aListener)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
MOZ_ASSERT(aListener);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationSessionListener> listener;
|
|
||||||
if (mSessionListeners.Get(aSessionId, getter_AddRefs(listener))) {
|
|
||||||
mSessionListeners.Put(aSessionId, aListener);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
mSessionListeners.Put(aSessionId, aListener);
|
|
||||||
if (sPresentationChild) {
|
|
||||||
Unused <<
|
|
||||||
NS_WARN_IF(!sPresentationChild->SendRegisterSessionHandler(
|
|
||||||
nsString(aSessionId), aRole));
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::UnregisterSessionListener(const nsAString& aSessionId,
|
|
||||||
uint8_t aRole)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
UntrackSessionInfo(aSessionId, aRole);
|
|
||||||
|
|
||||||
mSessionListeners.Remove(aSessionId);
|
|
||||||
if (sPresentationChild) {
|
|
||||||
Unused <<
|
|
||||||
NS_WARN_IF(!sPresentationChild->SendUnregisterSessionHandler(
|
|
||||||
nsString(aSessionId), aRole));
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::RegisterRespondingListener(uint64_t aWindowId,
|
|
||||||
nsIPresentationRespondingListener* aListener)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
mRespondingListeners.Put(aWindowId, aListener);
|
|
||||||
if (sPresentationChild) {
|
|
||||||
Unused <<
|
|
||||||
NS_WARN_IF(!sPresentationChild->SendRegisterRespondingHandler(aWindowId));
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::UnregisterRespondingListener(uint64_t aWindowId)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
mRespondingListeners.Remove(aWindowId);
|
|
||||||
if (sPresentationChild) {
|
|
||||||
Unused <<
|
|
||||||
NS_WARN_IF(!sPresentationChild->SendUnregisterRespondingHandler(
|
|
||||||
aWindowId));
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationIPCService::NotifySessionTransport(const nsString& aSessionId,
|
|
||||||
const uint8_t& aRole,
|
|
||||||
nsIPresentationSessionTransport* aTransport)
|
|
||||||
{
|
|
||||||
RefPtr<PresentationContentSessionInfo> info =
|
|
||||||
new PresentationContentSessionInfo(aSessionId, aRole, aTransport);
|
|
||||||
|
|
||||||
if (NS_WARN_IF(NS_FAILED(info->Init()))) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aRole == nsIPresentationService::ROLE_CONTROLLER) {
|
|
||||||
mSessionInfoAtController.Put(aSessionId, info);
|
|
||||||
} else {
|
|
||||||
mSessionInfoAtReceiver.Put(aSessionId, info);
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::GetWindowIdBySessionId(const nsAString& aSessionId,
|
|
||||||
uint8_t aRole,
|
|
||||||
uint64_t* aWindowId)
|
|
||||||
{
|
|
||||||
return GetWindowIdBySessionIdInternal(aSessionId, aRole, aWindowId);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::UpdateWindowIdBySessionId(const nsAString& aSessionId,
|
|
||||||
uint8_t aRole,
|
|
||||||
const uint64_t aWindowId)
|
|
||||||
{
|
|
||||||
return UpdateWindowIdBySessionIdInternal(aSessionId, aRole, aWindowId);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationIPCService::NotifySessionStateChange(const nsAString& aSessionId,
|
|
||||||
uint16_t aState,
|
|
||||||
nsresult aReason)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIPresentationSessionListener> listener;
|
|
||||||
if (NS_WARN_IF(!mSessionListeners.Get(aSessionId, getter_AddRefs(listener)))) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return listener->NotifyStateChange(aSessionId, aState, aReason);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only used for OOP RTCDataChannel session transport case.
|
|
||||||
nsresult
|
|
||||||
PresentationIPCService::NotifyMessage(const nsAString& aSessionId,
|
|
||||||
const nsACString& aData,
|
|
||||||
const bool& aIsBinary)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIPresentationSessionListener> listener;
|
|
||||||
if (NS_WARN_IF(!mSessionListeners.Get(aSessionId, getter_AddRefs(listener)))) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return listener->NotifyMessage(aSessionId, aData, aIsBinary);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only used for OOP RTCDataChannel session transport case.
|
|
||||||
nsresult
|
|
||||||
PresentationIPCService::NotifyTransportClosed(const nsAString& aSessionId,
|
|
||||||
uint8_t aRole,
|
|
||||||
nsresult aReason)
|
|
||||||
{
|
|
||||||
RefPtr<PresentationContentSessionInfo> info =
|
|
||||||
GetSessionInfo(aSessionId, aRole);
|
|
||||||
if (NS_WARN_IF(!info)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
Unused << NS_WARN_IF(!sPresentationChild->SendNotifyTransportClosed(nsString(aSessionId), aRole, aReason));
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationIPCService::NotifySessionConnect(uint64_t aWindowId,
|
|
||||||
const nsAString& aSessionId)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIPresentationRespondingListener> listener;
|
|
||||||
if (NS_WARN_IF(!mRespondingListeners.Get(aWindowId, getter_AddRefs(listener)))) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return listener->NotifySessionConnect(aWindowId, aSessionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::NotifyAvailableChange(
|
|
||||||
const nsTArray<nsString>& aAvailabilityUrls,
|
|
||||||
bool aAvailable)
|
|
||||||
{
|
|
||||||
return mAvailabilityManager.DoNotifyAvailableChange(aAvailabilityUrls,
|
|
||||||
aAvailable);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::NotifyReceiverReady(
|
|
||||||
const nsAString& aSessionId,
|
|
||||||
uint64_t aWindowId,
|
|
||||||
bool aIsLoading,
|
|
||||||
nsIPresentationTransportBuilderConstructor* aBuilderConstructor)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
// No actual window uses 0 as its ID.
|
|
||||||
if (NS_WARN_IF(aWindowId == 0)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Track the responding info for an OOP receiver page.
|
|
||||||
AddRespondingSessionId(aWindowId,
|
|
||||||
aSessionId,
|
|
||||||
nsIPresentationService::ROLE_RECEIVER);
|
|
||||||
|
|
||||||
Unused << NS_WARN_IF(!sPresentationChild->SendNotifyReceiverReady(nsString(aSessionId),
|
|
||||||
aWindowId,
|
|
||||||
aIsLoading));
|
|
||||||
|
|
||||||
// Release mCallback after using aSessionId
|
|
||||||
// because aSessionId is held by mCallback.
|
|
||||||
mCallback = nullptr;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationIPCService::UntrackSessionInfo(const nsAString& aSessionId,
|
|
||||||
uint8_t aRole)
|
|
||||||
{
|
|
||||||
PRES_DEBUG("content %s:id[%s], role[%d]\n", __func__,
|
|
||||||
NS_ConvertUTF16toUTF8(aSessionId).get(), aRole);
|
|
||||||
|
|
||||||
if (nsIPresentationService::ROLE_RECEIVER == aRole) {
|
|
||||||
// Terminate receiver page.
|
|
||||||
uint64_t windowId;
|
|
||||||
if (NS_SUCCEEDED(GetWindowIdBySessionIdInternal(aSessionId,
|
|
||||||
aRole,
|
|
||||||
&windowId))) {
|
|
||||||
NS_DispatchToMainThread(NS_NewRunnableFunction([windowId]() -> void {
|
|
||||||
PRES_DEBUG("Attempt to close window[%d]\n", windowId);
|
|
||||||
|
|
||||||
if (auto* window = nsGlobalWindow::GetInnerWindowWithId(windowId)) {
|
|
||||||
window->Close();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the OOP responding info (if it has never been used).
|
|
||||||
RemoveRespondingSessionId(aSessionId, aRole);
|
|
||||||
|
|
||||||
if (nsIPresentationService::ROLE_CONTROLLER == aRole) {
|
|
||||||
mSessionInfoAtController.Remove(aSessionId);
|
|
||||||
} else {
|
|
||||||
mSessionInfoAtReceiver.Remove(aSessionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationIPCService::NotifyPresentationChildDestroyed()
|
|
||||||
{
|
|
||||||
sPresentationChild = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationIPCService::MonitorResponderLoading(const nsAString& aSessionId,
|
|
||||||
nsIDocShell* aDocShell)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
mCallback = new PresentationResponderLoadingCallback(aSessionId);
|
|
||||||
return mCallback->Init(aDocShell);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationIPCService::CloseContentSessionTransport(const nsString& aSessionId,
|
|
||||||
uint8_t aRole,
|
|
||||||
nsresult aReason)
|
|
||||||
{
|
|
||||||
RefPtr<PresentationContentSessionInfo> info =
|
|
||||||
GetSessionInfo(aSessionId, aRole);
|
|
||||||
if (NS_WARN_IF(!info)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return info->Close(aReason);
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set sw=2 ts=8 et ft=cpp : */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationIPCService_h
|
|
||||||
#define mozilla_dom_PresentationIPCService_h
|
|
||||||
|
|
||||||
#include "mozilla/dom/PresentationServiceBase.h"
|
|
||||||
#include "nsIPresentationListener.h"
|
|
||||||
#include "nsIPresentationSessionTransport.h"
|
|
||||||
#include "nsIPresentationService.h"
|
|
||||||
|
|
||||||
class nsIDocShell;
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class PresentationIPCRequest;
|
|
||||||
class PresentationContentSessionInfo;
|
|
||||||
class PresentationResponderLoadingCallback;
|
|
||||||
|
|
||||||
class PresentationIPCService final
|
|
||||||
: public nsIPresentationAvailabilityListener
|
|
||||||
, public nsIPresentationService
|
|
||||||
, public PresentationServiceBase<PresentationContentSessionInfo>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIPRESENTATIONAVAILABILITYLISTENER
|
|
||||||
NS_DECL_NSIPRESENTATIONSERVICE
|
|
||||||
|
|
||||||
PresentationIPCService();
|
|
||||||
|
|
||||||
nsresult NotifySessionStateChange(const nsAString& aSessionId,
|
|
||||||
uint16_t aState,
|
|
||||||
nsresult aReason);
|
|
||||||
|
|
||||||
nsresult NotifyMessage(const nsAString& aSessionId,
|
|
||||||
const nsACString& aData,
|
|
||||||
const bool& aIsBinary);
|
|
||||||
|
|
||||||
nsresult NotifySessionConnect(uint64_t aWindowId,
|
|
||||||
const nsAString& aSessionId);
|
|
||||||
|
|
||||||
void NotifyPresentationChildDestroyed();
|
|
||||||
|
|
||||||
nsresult MonitorResponderLoading(const nsAString& aSessionId,
|
|
||||||
nsIDocShell* aDocShell);
|
|
||||||
|
|
||||||
nsresult NotifySessionTransport(const nsString& aSessionId,
|
|
||||||
const uint8_t& aRole,
|
|
||||||
nsIPresentationSessionTransport* transport);
|
|
||||||
|
|
||||||
nsresult CloseContentSessionTransport(const nsString& aSessionId,
|
|
||||||
uint8_t aRole,
|
|
||||||
nsresult aReason);
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~PresentationIPCService();
|
|
||||||
nsresult SendRequest(nsIPresentationServiceCallback* aCallback,
|
|
||||||
const PresentationIPCRequest& aRequest);
|
|
||||||
|
|
||||||
nsRefPtrHashtable<nsStringHashKey,
|
|
||||||
nsIPresentationSessionListener> mSessionListeners;
|
|
||||||
nsRefPtrHashtable<nsUint64HashKey,
|
|
||||||
nsIPresentationRespondingListener> mRespondingListeners;
|
|
||||||
RefPtr<PresentationResponderLoadingCallback> mCallback;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationIPCService_h
|
|
|
@ -1,553 +0,0 @@
|
||||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
|
||||||
/* vim: set ts=2 et sw=2 tw=80: */
|
|
||||||
/* 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 "DCPresentationChannelDescription.h"
|
|
||||||
#include "mozilla/dom/ContentProcessManager.h"
|
|
||||||
#include "mozilla/ipc/InputStreamUtils.h"
|
|
||||||
#include "mozilla/Unused.h"
|
|
||||||
#include "nsIPresentationDeviceManager.h"
|
|
||||||
#include "nsIPresentationSessionTransport.h"
|
|
||||||
#include "nsIPresentationSessionTransportBuilder.h"
|
|
||||||
#include "nsServiceManagerUtils.h"
|
|
||||||
#include "PresentationBuilderParent.h"
|
|
||||||
#include "PresentationParent.h"
|
|
||||||
#include "PresentationService.h"
|
|
||||||
#include "PresentationSessionInfo.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class PresentationTransportBuilderConstructorIPC final :
|
|
||||||
public nsIPresentationTransportBuilderConstructor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIPRESENTATIONTRANSPORTBUILDERCONSTRUCTOR
|
|
||||||
|
|
||||||
explicit PresentationTransportBuilderConstructorIPC(PresentationParent* aParent)
|
|
||||||
: mParent(aParent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~PresentationTransportBuilderConstructorIPC() = default;
|
|
||||||
|
|
||||||
RefPtr<PresentationParent> mParent;
|
|
||||||
};
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(PresentationTransportBuilderConstructorIPC,
|
|
||||||
nsIPresentationTransportBuilderConstructor)
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationTransportBuilderConstructorIPC::CreateTransportBuilder(
|
|
||||||
uint8_t aType,
|
|
||||||
nsIPresentationSessionTransportBuilder** aRetval)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(!aRetval)) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
*aRetval = nullptr;
|
|
||||||
|
|
||||||
if (NS_WARN_IF(aType != nsIPresentationChannelDescription::TYPE_TCP &&
|
|
||||||
aType != nsIPresentationChannelDescription::TYPE_DATACHANNEL)) {
|
|
||||||
return NS_ERROR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (XRE_IsContentProcess()) {
|
|
||||||
MOZ_ASSERT(false,
|
|
||||||
"CreateTransportBuilder can only be invoked in parent process.");
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationSessionTransportBuilder> builder;
|
|
||||||
if (aType == nsIPresentationChannelDescription::TYPE_TCP) {
|
|
||||||
builder = do_CreateInstance(PRESENTATION_TCP_SESSION_TRANSPORT_CONTRACTID);
|
|
||||||
} else {
|
|
||||||
builder = new PresentationBuilderParent(mParent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!builder)) {
|
|
||||||
return NS_ERROR_DOM_OPERATION_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.forget(aRetval);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Implementation of PresentationParent
|
|
||||||
*/
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(PresentationParent,
|
|
||||||
nsIPresentationAvailabilityListener,
|
|
||||||
nsIPresentationSessionListener,
|
|
||||||
nsIPresentationRespondingListener)
|
|
||||||
|
|
||||||
PresentationParent::PresentationParent()
|
|
||||||
{
|
|
||||||
MOZ_COUNT_CTOR(PresentationParent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual */ PresentationParent::~PresentationParent()
|
|
||||||
{
|
|
||||||
MOZ_COUNT_DTOR(PresentationParent);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationParent::Init(ContentParentId aContentParentId)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(!mService);
|
|
||||||
mService = do_GetService(PRESENTATION_SERVICE_CONTRACTID);
|
|
||||||
mChildId = aContentParentId;
|
|
||||||
return NS_WARN_IF(!mService) ? false : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationParent::ActorDestroy(ActorDestroyReason aWhy)
|
|
||||||
{
|
|
||||||
mActorDestroyed = true;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < mSessionIdsAtController.Length(); i++) {
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mService->
|
|
||||||
UnregisterSessionListener(mSessionIdsAtController[i],
|
|
||||||
nsIPresentationService::ROLE_CONTROLLER)));
|
|
||||||
}
|
|
||||||
mSessionIdsAtController.Clear();
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < mSessionIdsAtReceiver.Length(); i++) {
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mService->
|
|
||||||
UnregisterSessionListener(mSessionIdsAtReceiver[i], nsIPresentationService::ROLE_RECEIVER)));
|
|
||||||
}
|
|
||||||
mSessionIdsAtReceiver.Clear();
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < mWindowIds.Length(); i++) {
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mService->
|
|
||||||
UnregisterRespondingListener(mWindowIds[i])));
|
|
||||||
}
|
|
||||||
mWindowIds.Clear();
|
|
||||||
|
|
||||||
if (!mContentAvailabilityUrls.IsEmpty()) {
|
|
||||||
mService->UnregisterAvailabilityListener(mContentAvailabilityUrls, this);
|
|
||||||
}
|
|
||||||
mService = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationParent::RecvPPresentationRequestConstructor(
|
|
||||||
PPresentationRequestParent* aActor,
|
|
||||||
const PresentationIPCRequest& aRequest)
|
|
||||||
{
|
|
||||||
PresentationRequestParent* actor = static_cast<PresentationRequestParent*>(aActor);
|
|
||||||
|
|
||||||
nsresult rv = NS_ERROR_FAILURE;
|
|
||||||
switch (aRequest.type()) {
|
|
||||||
case PresentationIPCRequest::TStartSessionRequest:
|
|
||||||
rv = actor->DoRequest(aRequest.get_StartSessionRequest());
|
|
||||||
break;
|
|
||||||
case PresentationIPCRequest::TSendSessionMessageRequest:
|
|
||||||
rv = actor->DoRequest(aRequest.get_SendSessionMessageRequest());
|
|
||||||
break;
|
|
||||||
case PresentationIPCRequest::TCloseSessionRequest:
|
|
||||||
rv = actor->DoRequest(aRequest.get_CloseSessionRequest());
|
|
||||||
break;
|
|
||||||
case PresentationIPCRequest::TTerminateSessionRequest:
|
|
||||||
rv = actor->DoRequest(aRequest.get_TerminateSessionRequest());
|
|
||||||
break;
|
|
||||||
case PresentationIPCRequest::TReconnectSessionRequest:
|
|
||||||
rv = actor->DoRequest(aRequest.get_ReconnectSessionRequest());
|
|
||||||
break;
|
|
||||||
case PresentationIPCRequest::TBuildTransportRequest:
|
|
||||||
rv = actor->DoRequest(aRequest.get_BuildTransportRequest());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
MOZ_CRASH("Unknown PresentationIPCRequest type");
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_WARN_IF(NS_FAILED(rv)) ? false : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
PPresentationRequestParent*
|
|
||||||
PresentationParent::AllocPPresentationRequestParent(
|
|
||||||
const PresentationIPCRequest& aRequest)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mService);
|
|
||||||
RefPtr<PresentationRequestParent> actor = new PresentationRequestParent(mService, mChildId);
|
|
||||||
return actor.forget().take();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationParent::DeallocPPresentationRequestParent(
|
|
||||||
PPresentationRequestParent* aActor)
|
|
||||||
{
|
|
||||||
RefPtr<PresentationRequestParent> actor =
|
|
||||||
dont_AddRef(static_cast<PresentationRequestParent*>(aActor));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
PPresentationBuilderParent*
|
|
||||||
PresentationParent::AllocPPresentationBuilderParent(const nsString& aSessionId,
|
|
||||||
const uint8_t& aRole)
|
|
||||||
{
|
|
||||||
NS_NOTREACHED("We should never be manually allocating AllocPPresentationBuilderParent actors");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationParent::DeallocPPresentationBuilderParent(
|
|
||||||
PPresentationBuilderParent* aActor)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationParent::Recv__delete__()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationParent::RecvRegisterAvailabilityHandler(
|
|
||||||
nsTArray<nsString>&& aAvailabilityUrls)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mService);
|
|
||||||
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mService->RegisterAvailabilityListener(
|
|
||||||
aAvailabilityUrls,
|
|
||||||
this)));
|
|
||||||
mContentAvailabilityUrls.AppendElements(aAvailabilityUrls);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationParent::RecvUnregisterAvailabilityHandler(
|
|
||||||
nsTArray<nsString>&& aAvailabilityUrls)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mService);
|
|
||||||
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mService->UnregisterAvailabilityListener(
|
|
||||||
aAvailabilityUrls,
|
|
||||||
this)));
|
|
||||||
for (const auto& url : aAvailabilityUrls) {
|
|
||||||
mContentAvailabilityUrls.RemoveElement(url);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual */ bool
|
|
||||||
PresentationParent::RecvRegisterSessionHandler(const nsString& aSessionId,
|
|
||||||
const uint8_t& aRole)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mService);
|
|
||||||
|
|
||||||
// Validate the accessibility (primarily for receiver side) so that a
|
|
||||||
// compromised child process can't fake the ID.
|
|
||||||
if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())->
|
|
||||||
IsSessionAccessible(aSessionId, aRole, OtherPid()))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nsIPresentationService::ROLE_CONTROLLER == aRole) {
|
|
||||||
mSessionIdsAtController.AppendElement(aSessionId);
|
|
||||||
} else {
|
|
||||||
mSessionIdsAtReceiver.AppendElement(aSessionId);
|
|
||||||
}
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mService->RegisterSessionListener(aSessionId, aRole, this)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual */ bool
|
|
||||||
PresentationParent::RecvUnregisterSessionHandler(const nsString& aSessionId,
|
|
||||||
const uint8_t& aRole)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mService);
|
|
||||||
if (nsIPresentationService::ROLE_CONTROLLER == aRole) {
|
|
||||||
mSessionIdsAtController.RemoveElement(aSessionId);
|
|
||||||
} else {
|
|
||||||
mSessionIdsAtReceiver.RemoveElement(aSessionId);
|
|
||||||
}
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mService->UnregisterSessionListener(aSessionId, aRole)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual */ bool
|
|
||||||
PresentationParent::RecvRegisterRespondingHandler(const uint64_t& aWindowId)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mService);
|
|
||||||
|
|
||||||
mWindowIds.AppendElement(aWindowId);
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mService->RegisterRespondingListener(aWindowId, this)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* virtual */ bool
|
|
||||||
PresentationParent::RecvUnregisterRespondingHandler(const uint64_t& aWindowId)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mService);
|
|
||||||
mWindowIds.RemoveElement(aWindowId);
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mService->UnregisterRespondingListener(aWindowId)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationParent::NotifyAvailableChange(const nsTArray<nsString>& aAvailabilityUrls,
|
|
||||||
bool aAvailable)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(mActorDestroyed ||
|
|
||||||
!SendNotifyAvailableChange(aAvailabilityUrls,
|
|
||||||
aAvailable))) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationParent::NotifyStateChange(const nsAString& aSessionId,
|
|
||||||
uint16_t aState,
|
|
||||||
nsresult aReason)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(mActorDestroyed ||
|
|
||||||
!SendNotifySessionStateChange(nsString(aSessionId),
|
|
||||||
aState,
|
|
||||||
aReason))) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationParent::NotifyMessage(const nsAString& aSessionId,
|
|
||||||
const nsACString& aData,
|
|
||||||
bool aIsBinary)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(mActorDestroyed ||
|
|
||||||
!SendNotifyMessage(nsString(aSessionId),
|
|
||||||
nsCString(aData),
|
|
||||||
aIsBinary))) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationParent::NotifySessionConnect(uint64_t aWindowId,
|
|
||||||
const nsAString& aSessionId)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(mActorDestroyed ||
|
|
||||||
!SendNotifySessionConnect(aWindowId, nsString(aSessionId)))) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationParent::RecvNotifyReceiverReady(const nsString& aSessionId,
|
|
||||||
const uint64_t& aWindowId,
|
|
||||||
const bool& aIsLoading)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mService);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresentationTransportBuilderConstructor> constructor =
|
|
||||||
new PresentationTransportBuilderConstructorIPC(this);
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mService->NotifyReceiverReady(aSessionId,
|
|
||||||
aWindowId,
|
|
||||||
aIsLoading,
|
|
||||||
constructor)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
PresentationParent::RecvNotifyTransportClosed(const nsString& aSessionId,
|
|
||||||
const uint8_t& aRole,
|
|
||||||
const nsresult& aReason)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mService);
|
|
||||||
|
|
||||||
Unused << NS_WARN_IF(NS_FAILED(mService->NotifyTransportClosed(aSessionId, aRole, aReason)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Implementation of PresentationRequestParent
|
|
||||||
*/
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(PresentationRequestParent, nsIPresentationServiceCallback)
|
|
||||||
|
|
||||||
PresentationRequestParent::PresentationRequestParent(nsIPresentationService* aService,
|
|
||||||
ContentParentId aContentParentId)
|
|
||||||
: mService(aService)
|
|
||||||
, mChildId(aContentParentId)
|
|
||||||
{
|
|
||||||
MOZ_COUNT_CTOR(PresentationRequestParent);
|
|
||||||
}
|
|
||||||
|
|
||||||
PresentationRequestParent::~PresentationRequestParent()
|
|
||||||
{
|
|
||||||
MOZ_COUNT_DTOR(PresentationRequestParent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PresentationRequestParent::ActorDestroy(ActorDestroyReason aWhy)
|
|
||||||
{
|
|
||||||
mActorDestroyed = true;
|
|
||||||
mService = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationRequestParent::DoRequest(const StartSessionRequest& aRequest)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mService);
|
|
||||||
|
|
||||||
mSessionId = aRequest.sessionId();
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDOMEventTarget> eventTarget;
|
|
||||||
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
|
|
||||||
RefPtr<TabParent> tp =
|
|
||||||
cpm->GetTopLevelTabParentByProcessAndTabId(mChildId, aRequest.tabId());
|
|
||||||
if (tp) {
|
|
||||||
eventTarget = do_QueryInterface(tp->GetOwnerElement());
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<PresentationParent> parent = static_cast<PresentationParent*>(Manager());
|
|
||||||
nsCOMPtr<nsIPresentationTransportBuilderConstructor> constructor =
|
|
||||||
new PresentationTransportBuilderConstructorIPC(parent);
|
|
||||||
return mService->StartSession(aRequest.urls(), aRequest.sessionId(),
|
|
||||||
aRequest.origin(), aRequest.deviceId(),
|
|
||||||
aRequest.windowId(), eventTarget,
|
|
||||||
aRequest.principal(), this, constructor);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationRequestParent::DoRequest(const SendSessionMessageRequest& aRequest)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mService);
|
|
||||||
|
|
||||||
// Validate the accessibility (primarily for receiver side) so that a
|
|
||||||
// compromised child process can't fake the ID.
|
|
||||||
if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())->
|
|
||||||
IsSessionAccessible(aRequest.sessionId(), aRequest.role(), OtherPid()))) {
|
|
||||||
return SendResponse(NS_ERROR_DOM_SECURITY_ERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv = mService->SendSessionMessage(aRequest.sessionId(),
|
|
||||||
aRequest.role(),
|
|
||||||
aRequest.data());
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return SendResponse(rv);
|
|
||||||
}
|
|
||||||
return SendResponse(NS_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationRequestParent::DoRequest(const CloseSessionRequest& aRequest)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mService);
|
|
||||||
|
|
||||||
// Validate the accessibility (primarily for receiver side) so that a
|
|
||||||
// compromised child process can't fake the ID.
|
|
||||||
if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())->
|
|
||||||
IsSessionAccessible(aRequest.sessionId(), aRequest.role(), OtherPid()))) {
|
|
||||||
return SendResponse(NS_ERROR_DOM_SECURITY_ERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv = mService->CloseSession(aRequest.sessionId(),
|
|
||||||
aRequest.role(),
|
|
||||||
aRequest.closedReason());
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return SendResponse(rv);
|
|
||||||
}
|
|
||||||
return SendResponse(NS_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationRequestParent::DoRequest(const TerminateSessionRequest& aRequest)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mService);
|
|
||||||
|
|
||||||
// Validate the accessibility (primarily for receiver side) so that a
|
|
||||||
// compromised child process can't fake the ID.
|
|
||||||
if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())->
|
|
||||||
IsSessionAccessible(aRequest.sessionId(), aRequest.role(), OtherPid()))) {
|
|
||||||
return SendResponse(NS_ERROR_DOM_SECURITY_ERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv = mService->TerminateSession(aRequest.sessionId(), aRequest.role());
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return SendResponse(rv);
|
|
||||||
}
|
|
||||||
return SendResponse(NS_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationRequestParent::DoRequest(const ReconnectSessionRequest& aRequest)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mService);
|
|
||||||
|
|
||||||
// Validate the accessibility (primarily for receiver side) so that a
|
|
||||||
// compromised child process can't fake the ID.
|
|
||||||
if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())->
|
|
||||||
IsSessionAccessible(aRequest.sessionId(), aRequest.role(), OtherPid()))) {
|
|
||||||
|
|
||||||
// NOTE: Return NS_ERROR_DOM_NOT_FOUND_ERR here to match the spec.
|
|
||||||
// https://w3c.github.io/presentation-api/#reconnecting-to-a-presentation
|
|
||||||
return SendResponse(NS_ERROR_DOM_NOT_FOUND_ERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
mSessionId = aRequest.sessionId();
|
|
||||||
return mService->ReconnectSession(aRequest.urls(),
|
|
||||||
aRequest.sessionId(),
|
|
||||||
aRequest.role(),
|
|
||||||
this);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationRequestParent::DoRequest(const BuildTransportRequest& aRequest)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mService);
|
|
||||||
|
|
||||||
// Validate the accessibility (primarily for receiver side) so that a
|
|
||||||
// compromised child process can't fake the ID.
|
|
||||||
if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())->
|
|
||||||
IsSessionAccessible(aRequest.sessionId(), aRequest.role(), OtherPid()))) {
|
|
||||||
return SendResponse(NS_ERROR_DOM_SECURITY_ERR);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv = mService->BuildTransport(aRequest.sessionId(), aRequest.role());
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return SendResponse(rv);
|
|
||||||
}
|
|
||||||
return SendResponse(NS_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationRequestParent::NotifySuccess(const nsAString& aUrl)
|
|
||||||
{
|
|
||||||
Unused << SendNotifyRequestUrlSelected(nsString(aUrl));
|
|
||||||
return SendResponse(NS_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
PresentationRequestParent::NotifyError(nsresult aError)
|
|
||||||
{
|
|
||||||
return SendResponse(aError);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
PresentationRequestParent::SendResponse(nsresult aResult)
|
|
||||||
{
|
|
||||||
if (NS_WARN_IF(mActorDestroyed || !Send__delete__(this, aResult))) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
|
@ -1,137 +0,0 @@
|
||||||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
|
||||||
/* vim: set ts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_PresentationParent_h__
|
|
||||||
#define mozilla_dom_PresentationParent_h__
|
|
||||||
|
|
||||||
#include "mozilla/dom/ipc/IdType.h"
|
|
||||||
#include "mozilla/dom/PPresentationBuilderParent.h"
|
|
||||||
#include "mozilla/dom/PPresentationParent.h"
|
|
||||||
#include "mozilla/dom/PPresentationRequestParent.h"
|
|
||||||
#include "nsIPresentationListener.h"
|
|
||||||
#include "nsIPresentationService.h"
|
|
||||||
#include "nsIPresentationSessionTransportBuilder.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
|
||||||
namespace dom {
|
|
||||||
|
|
||||||
class PresentationParent final : public PPresentationParent
|
|
||||||
, public nsIPresentationAvailabilityListener
|
|
||||||
, public nsIPresentationSessionListener
|
|
||||||
, public nsIPresentationRespondingListener
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIPRESENTATIONAVAILABILITYLISTENER
|
|
||||||
NS_DECL_NSIPRESENTATIONSESSIONLISTENER
|
|
||||||
NS_DECL_NSIPRESENTATIONRESPONDINGLISTENER
|
|
||||||
|
|
||||||
PresentationParent();
|
|
||||||
|
|
||||||
bool Init(ContentParentId aContentParentId);
|
|
||||||
|
|
||||||
bool RegisterTransportBuilder(const nsString& aSessionId, const uint8_t& aRole);
|
|
||||||
|
|
||||||
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
|
||||||
|
|
||||||
virtual bool
|
|
||||||
RecvPPresentationRequestConstructor(PPresentationRequestParent* aActor,
|
|
||||||
const PresentationIPCRequest& aRequest) override;
|
|
||||||
|
|
||||||
virtual PPresentationRequestParent*
|
|
||||||
AllocPPresentationRequestParent(const PresentationIPCRequest& aRequest) override;
|
|
||||||
|
|
||||||
virtual bool
|
|
||||||
DeallocPPresentationRequestParent(PPresentationRequestParent* aActor) override;
|
|
||||||
|
|
||||||
virtual PPresentationBuilderParent*
|
|
||||||
AllocPPresentationBuilderParent(const nsString& aSessionId,
|
|
||||||
const uint8_t& aRole) override;
|
|
||||||
|
|
||||||
virtual bool
|
|
||||||
DeallocPPresentationBuilderParent(
|
|
||||||
PPresentationBuilderParent* aActor) override;
|
|
||||||
|
|
||||||
virtual bool Recv__delete__() override;
|
|
||||||
|
|
||||||
virtual bool RecvRegisterAvailabilityHandler(
|
|
||||||
nsTArray<nsString>&& aAvailabilityUrls) override;
|
|
||||||
|
|
||||||
virtual bool RecvUnregisterAvailabilityHandler(
|
|
||||||
nsTArray<nsString>&& aAvailabilityUrls) override;
|
|
||||||
|
|
||||||
virtual bool RecvRegisterSessionHandler(const nsString& aSessionId,
|
|
||||||
const uint8_t& aRole) override;
|
|
||||||
|
|
||||||
virtual bool RecvUnregisterSessionHandler(const nsString& aSessionId,
|
|
||||||
const uint8_t& aRole) override;
|
|
||||||
|
|
||||||
virtual bool RecvRegisterRespondingHandler(const uint64_t& aWindowId) override;
|
|
||||||
|
|
||||||
virtual bool RecvUnregisterRespondingHandler(const uint64_t& aWindowId) override;
|
|
||||||
|
|
||||||
virtual bool RecvNotifyReceiverReady(const nsString& aSessionId,
|
|
||||||
const uint64_t& aWindowId,
|
|
||||||
const bool& aIsLoading) override;
|
|
||||||
|
|
||||||
virtual bool RecvNotifyTransportClosed(const nsString& aSessionId,
|
|
||||||
const uint8_t& aRole,
|
|
||||||
const nsresult& aReason) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~PresentationParent();
|
|
||||||
|
|
||||||
bool mActorDestroyed = false;
|
|
||||||
nsCOMPtr<nsIPresentationService> mService;
|
|
||||||
nsTArray<nsString> mSessionIdsAtController;
|
|
||||||
nsTArray<nsString> mSessionIdsAtReceiver;
|
|
||||||
nsTArray<uint64_t> mWindowIds;
|
|
||||||
ContentParentId mChildId;
|
|
||||||
nsTArray<nsString> mContentAvailabilityUrls;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PresentationRequestParent final : public PPresentationRequestParent
|
|
||||||
, public nsIPresentationServiceCallback
|
|
||||||
{
|
|
||||||
friend class PresentationParent;
|
|
||||||
|
|
||||||
public:
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIPRESENTATIONSERVICECALLBACK
|
|
||||||
|
|
||||||
explicit PresentationRequestParent(nsIPresentationService* aService,
|
|
||||||
ContentParentId aContentParentId);
|
|
||||||
|
|
||||||
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual ~PresentationRequestParent();
|
|
||||||
|
|
||||||
nsresult SendResponse(nsresult aResult);
|
|
||||||
|
|
||||||
nsresult DoRequest(const StartSessionRequest& aRequest);
|
|
||||||
|
|
||||||
nsresult DoRequest(const SendSessionMessageRequest& aRequest);
|
|
||||||
|
|
||||||
nsresult DoRequest(const CloseSessionRequest& aRequest);
|
|
||||||
|
|
||||||
nsresult DoRequest(const TerminateSessionRequest& aRequest);
|
|
||||||
|
|
||||||
nsresult DoRequest(const ReconnectSessionRequest& aRequest);
|
|
||||||
|
|
||||||
nsresult DoRequest(const BuildTransportRequest& aRequest);
|
|
||||||
|
|
||||||
bool mActorDestroyed = false;
|
|
||||||
bool mNeedRegisterBuilder = false;
|
|
||||||
nsString mSessionId;
|
|
||||||
nsCOMPtr<nsIPresentationService> mService;
|
|
||||||
ContentParentId mChildId;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace dom
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
#endif // mozilla_dom_PresentationParent_h__
|
|
|
@ -1,89 +0,0 @@
|
||||||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
|
||||||
# vim: set filetype=python:
|
|
||||||
# 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/.
|
|
||||||
|
|
||||||
DIRS += ['interfaces', 'provider']
|
|
||||||
|
|
||||||
XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
|
|
||||||
MOCHITEST_MANIFESTS += ['tests/mochitest/mochitest.ini']
|
|
||||||
MOCHITEST_CHROME_MANIFESTS += ['tests/mochitest/chrome.ini']
|
|
||||||
|
|
||||||
EXPORTS.mozilla.dom += [
|
|
||||||
'DCPresentationChannelDescription.h',
|
|
||||||
'ipc/PresentationBuilderChild.h',
|
|
||||||
'ipc/PresentationBuilderParent.h',
|
|
||||||
'ipc/PresentationChild.h',
|
|
||||||
'ipc/PresentationIPCService.h',
|
|
||||||
'ipc/PresentationParent.h',
|
|
||||||
'Presentation.h',
|
|
||||||
'PresentationAvailability.h',
|
|
||||||
'PresentationCallbacks.h',
|
|
||||||
'PresentationConnection.h',
|
|
||||||
'PresentationConnectionList.h',
|
|
||||||
'PresentationDeviceManager.h',
|
|
||||||
'PresentationReceiver.h',
|
|
||||||
'PresentationRequest.h',
|
|
||||||
'PresentationService.h',
|
|
||||||
'PresentationServiceBase.h',
|
|
||||||
'PresentationSessionInfo.h',
|
|
||||||
'PresentationTCPSessionTransport.h',
|
|
||||||
]
|
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
|
||||||
'AvailabilityCollection.cpp',
|
|
||||||
'ControllerConnectionCollection.cpp',
|
|
||||||
'DCPresentationChannelDescription.cpp',
|
|
||||||
'ipc/PresentationBuilderChild.cpp',
|
|
||||||
'ipc/PresentationBuilderParent.cpp',
|
|
||||||
'ipc/PresentationChild.cpp',
|
|
||||||
'ipc/PresentationContentSessionInfo.cpp',
|
|
||||||
'ipc/PresentationIPCService.cpp',
|
|
||||||
'ipc/PresentationParent.cpp',
|
|
||||||
'Presentation.cpp',
|
|
||||||
'PresentationAvailability.cpp',
|
|
||||||
'PresentationCallbacks.cpp',
|
|
||||||
'PresentationConnection.cpp',
|
|
||||||
'PresentationConnectionList.cpp',
|
|
||||||
'PresentationDeviceManager.cpp',
|
|
||||||
'PresentationReceiver.cpp',
|
|
||||||
'PresentationRequest.cpp',
|
|
||||||
'PresentationService.cpp',
|
|
||||||
'PresentationSessionInfo.cpp',
|
|
||||||
'PresentationSessionRequest.cpp',
|
|
||||||
'PresentationTCPSessionTransport.cpp',
|
|
||||||
'PresentationTerminateRequest.cpp',
|
|
||||||
'PresentationTransportBuilderConstructor.cpp'
|
|
||||||
]
|
|
||||||
|
|
||||||
EXTRA_COMPONENTS += [
|
|
||||||
'PresentationDataChannelSessionTransport.js',
|
|
||||||
'PresentationDataChannelSessionTransport.manifest',
|
|
||||||
'PresentationDeviceInfoManager.js',
|
|
||||||
'PresentationDeviceInfoManager.manifest',
|
|
||||||
]
|
|
||||||
|
|
||||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
|
|
||||||
EXTRA_COMPONENTS += [
|
|
||||||
'PresentationNetworkHelper.js',
|
|
||||||
'PresentationNetworkHelper.manifest',
|
|
||||||
]
|
|
||||||
|
|
||||||
EXTRA_JS_MODULES += [
|
|
||||||
'PresentationDeviceInfoManager.jsm',
|
|
||||||
]
|
|
||||||
|
|
||||||
IPDL_SOURCES += [
|
|
||||||
'ipc/PPresentation.ipdl',
|
|
||||||
'ipc/PPresentationBuilder.ipdl',
|
|
||||||
'ipc/PPresentationRequest.ipdl'
|
|
||||||
]
|
|
||||||
|
|
||||||
LOCAL_INCLUDES += [
|
|
||||||
'../base'
|
|
||||||
]
|
|
||||||
|
|
||||||
include('/ipc/chromium/chromium-config.mozbuild')
|
|
||||||
|
|
||||||
FINAL_LIBRARY = 'xul'
|
|
|
@ -1,461 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
/* jshint esnext:true, globalstrict:true, moz:true, undef:true, unused:true */
|
|
||||||
/* globals Components, dump */
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
|
||||||
|
|
||||||
// globals XPCOMUtils
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
||||||
// globals Services
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
|
||||||
// globals Messaging
|
|
||||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
|
||||||
|
|
||||||
function log(str) {
|
|
||||||
// dump("-*- AndroidCastDeviceProvider -*-: " + str + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function: transfer nsIPresentationChannelDescription to json
|
|
||||||
function descriptionToString(aDescription) {
|
|
||||||
let json = {};
|
|
||||||
json.type = aDescription.type;
|
|
||||||
switch(aDescription.type) {
|
|
||||||
case Ci.nsIPresentationChannelDescription.TYPE_TCP:
|
|
||||||
let addresses = aDescription.tcpAddress.QueryInterface(Ci.nsIArray);
|
|
||||||
json.tcpAddress = [];
|
|
||||||
for (let idx = 0; idx < addresses.length; idx++) {
|
|
||||||
let address = addresses.queryElementAt(idx, Ci.nsISupportsCString);
|
|
||||||
json.tcpAddress.push(address.data);
|
|
||||||
}
|
|
||||||
json.tcpPort = aDescription.tcpPort;
|
|
||||||
break;
|
|
||||||
case Ci.nsIPresentationChannelDescription.TYPE_DATACHANNEL:
|
|
||||||
json.dataChannelSDP = aDescription.dataChannelSDP;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return JSON.stringify(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
const TOPIC_ANDROID_CAST_DEVICE_SYNCDEVICE = "AndroidCastDevice:SyncDevice";
|
|
||||||
const TOPIC_ANDROID_CAST_DEVICE_ADDED = "AndroidCastDevice:Added";
|
|
||||||
const TOPIC_ANDROID_CAST_DEVICE_REMOVED = "AndroidCastDevice:Removed";
|
|
||||||
const TOPIC_ANDROID_CAST_DEVICE_START = "AndroidCastDevice:Start";
|
|
||||||
const TOPIC_ANDROID_CAST_DEVICE_STOP = "AndroidCastDevice:Stop";
|
|
||||||
const TOPIC_PRESENTATION_VIEW_READY = "presentation-view-ready";
|
|
||||||
|
|
||||||
function LocalControlChannel(aProvider, aDeviceId, aRole) {
|
|
||||||
log("LocalControlChannel - create new LocalControlChannel for : "
|
|
||||||
+ aRole);
|
|
||||||
this._provider = aProvider;
|
|
||||||
this._deviceId = aDeviceId;
|
|
||||||
this._role = aRole;
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalControlChannel.prototype = {
|
|
||||||
_listener: null,
|
|
||||||
_provider: null,
|
|
||||||
_deviceId: null,
|
|
||||||
_role: null,
|
|
||||||
_isOnTerminating: false,
|
|
||||||
_isOnDisconnecting: false,
|
|
||||||
_pendingConnected: false,
|
|
||||||
_pendingDisconnect: null,
|
|
||||||
_pendingOffer: null,
|
|
||||||
_pendingCandidate: null,
|
|
||||||
/* For the controller, it would be the control channel of the receiver.
|
|
||||||
* For the receiver, it would be the control channel of the controller. */
|
|
||||||
_correspondingControlChannel: null,
|
|
||||||
|
|
||||||
set correspondingControlChannel(aCorrespondingControlChannel) {
|
|
||||||
this._correspondingControlChannel = aCorrespondingControlChannel;
|
|
||||||
},
|
|
||||||
|
|
||||||
get correspondingControlChannel() {
|
|
||||||
return this._correspondingControlChannel;
|
|
||||||
},
|
|
||||||
|
|
||||||
notifyConnected: function LCC_notifyConnected() {
|
|
||||||
this._pendingDisconnect = null;
|
|
||||||
|
|
||||||
if (!this._listener) {
|
|
||||||
this._pendingConnected = true;
|
|
||||||
} else {
|
|
||||||
this._listener.notifyConnected();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onOffer: function LCC_onOffer(aOffer) {
|
|
||||||
if (this._role == Ci.nsIPresentationService.ROLE_CONTROLLER) {
|
|
||||||
log("LocalControlChannel - onOffer of controller should not be called.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this._listener) {
|
|
||||||
this._pendingOffer = aOffer;
|
|
||||||
} else {
|
|
||||||
this._listener.onOffer(aOffer);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onAnswer: function LCC_onAnswer(aAnswer) {
|
|
||||||
if (this._role == Ci.nsIPresentationService.ROLE_RECEIVER) {
|
|
||||||
log("LocalControlChannel - onAnswer of receiver should not be called.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._listener.onAnswer(aAnswer);
|
|
||||||
},
|
|
||||||
|
|
||||||
notifyIceCandidate: function LCC_notifyIceCandidate(aCandidate) {
|
|
||||||
if (!this._listener) {
|
|
||||||
this._pendingCandidate = aCandidate;
|
|
||||||
} else {
|
|
||||||
this._listener.onIceCandidate(aCandidate);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// nsIPresentationControlChannel
|
|
||||||
get listener() {
|
|
||||||
return this._listener;
|
|
||||||
},
|
|
||||||
|
|
||||||
set listener(aListener) {
|
|
||||||
this._listener = aListener;
|
|
||||||
|
|
||||||
if (!this._listener) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._pendingConnected) {
|
|
||||||
this.notifyConnected();
|
|
||||||
this._pendingConnected = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._pendingOffer) {
|
|
||||||
this.onOffer(this._pendingOffer);
|
|
||||||
this._pendingOffer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._pendingCandidate) {
|
|
||||||
this.notifyIceCandidate(this._pendingCandidate);
|
|
||||||
this._pendingCandidate = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._pendingDisconnect != null) {
|
|
||||||
this.disconnect(this._pendingDisconnect);
|
|
||||||
this._pendingDisconnect = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
sendOffer: function LCC_sendOffer(aOffer) {
|
|
||||||
if (this._role == Ci.nsIPresentationService.ROLE_RECEIVER) {
|
|
||||||
log("LocalControlChannel - sendOffer of receiver should not be called.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
log("LocalControlChannel - sendOffer aOffer=" + descriptionToString(aOffer));
|
|
||||||
this._correspondingControlChannel.onOffer(aOffer);
|
|
||||||
},
|
|
||||||
|
|
||||||
sendAnswer: function LCC_sendAnswer(aAnswer) {
|
|
||||||
if (this._role == Ci.nsIPresentationService.ROLE_CONTROLLER) {
|
|
||||||
log("LocalControlChannel - sendAnswer of controller should not be called.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
log("LocalControlChannel - sendAnswer aAnswer=" + descriptionToString(aAnswer));
|
|
||||||
this._correspondingControlChannel.onAnswer(aAnswer);
|
|
||||||
},
|
|
||||||
|
|
||||||
sendIceCandidate: function LCC_sendIceCandidate(aCandidate) {
|
|
||||||
log("LocalControlChannel - sendAnswer aCandidate=" + aCandidate);
|
|
||||||
this._correspondingControlChannel.notifyIceCandidate(aCandidate);
|
|
||||||
},
|
|
||||||
|
|
||||||
launch: function LCC_launch(aPresentationId, aUrl) {
|
|
||||||
log("LocalControlChannel - launch aPresentationId="
|
|
||||||
+ aPresentationId + " aUrl=" + aUrl);
|
|
||||||
// Create control channel for receiver directly.
|
|
||||||
let controlChannel = new LocalControlChannel(this._provider,
|
|
||||||
this._deviceId,
|
|
||||||
Ci.nsIPresentationService.ROLE_RECEIVER);
|
|
||||||
|
|
||||||
// Set up the corresponding control channels for both controller and receiver.
|
|
||||||
this._correspondingControlChannel = controlChannel;
|
|
||||||
controlChannel._correspondingControlChannel = this;
|
|
||||||
|
|
||||||
this._provider.onSessionRequest(this._deviceId,
|
|
||||||
aUrl,
|
|
||||||
aPresentationId,
|
|
||||||
controlChannel);
|
|
||||||
controlChannel.notifyConnected();
|
|
||||||
},
|
|
||||||
|
|
||||||
terminate: function LCC_terminate(aPresentationId) {
|
|
||||||
log("LocalControlChannel - terminate aPresentationId="
|
|
||||||
+ aPresentationId);
|
|
||||||
|
|
||||||
if (this._isOnTerminating) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create control channel for corresponding role directly.
|
|
||||||
let correspondingRole = this._role == Ci.nsIPresentationService.ROLE_CONTROLLER
|
|
||||||
? Ci.nsIPresentationService.ROLE_RECEIVER
|
|
||||||
: Ci.nsIPresentationService.ROLE_CONTROLLER;
|
|
||||||
let controlChannel = new LocalControlChannel(this._provider,
|
|
||||||
this._deviceId,
|
|
||||||
correspondingRole);
|
|
||||||
// Prevent the termination recursion.
|
|
||||||
controlChannel._isOnTerminating = true;
|
|
||||||
|
|
||||||
// Set up the corresponding control channels for both controller and receiver.
|
|
||||||
this._correspondingControlChannel = controlChannel;
|
|
||||||
controlChannel._correspondingControlChannel = this;
|
|
||||||
|
|
||||||
this._provider.onTerminateRequest(this._deviceId,
|
|
||||||
aPresentationId,
|
|
||||||
controlChannel,
|
|
||||||
this._role == Ci.nsIPresentationService.ROLE_RECEIVER);
|
|
||||||
controlChannel.notifyConnected();
|
|
||||||
},
|
|
||||||
|
|
||||||
disconnect: function LCC_disconnect(aReason) {
|
|
||||||
log("LocalControlChannel - disconnect aReason=" + aReason);
|
|
||||||
|
|
||||||
if (this._isOnDisconnecting) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._pendingOffer = null;
|
|
||||||
this._pendingCandidate = null;
|
|
||||||
this._pendingConnected = false;
|
|
||||||
|
|
||||||
// this._pendingDisconnect is a nsresult.
|
|
||||||
// If it is null, it means no pending disconnect.
|
|
||||||
// If it is NS_OK, it means this control channel is disconnected normally.
|
|
||||||
// If it is other nsresult value, it means this control channel is
|
|
||||||
// disconnected abnormally.
|
|
||||||
|
|
||||||
// Remote endpoint closes the control channel with abnormal reason.
|
|
||||||
if (aReason == Cr.NS_OK &&
|
|
||||||
this._pendingDisconnect != null &&
|
|
||||||
this._pendingDisconnect != Cr.NS_OK) {
|
|
||||||
aReason = this._pendingDisconnect;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this._listener) {
|
|
||||||
this._pendingDisconnect = aReason;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._isOnDisconnecting = true;
|
|
||||||
this._correspondingControlChannel.disconnect(aReason);
|
|
||||||
this._listener.notifyDisconnected(aReason);
|
|
||||||
},
|
|
||||||
|
|
||||||
reconnect: function LCC_reconnect(aPresentationId, aUrl) {
|
|
||||||
log("1-UA on Android doesn't support reconnect.");
|
|
||||||
throw Cr.NS_ERROR_FAILURE;
|
|
||||||
},
|
|
||||||
|
|
||||||
classID: Components.ID("{c9be9450-e5c7-4294-a287-376971b017fd}"),
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel]),
|
|
||||||
};
|
|
||||||
|
|
||||||
function ChromecastRemoteDisplayDevice(aProvider, aId, aName, aRole) {
|
|
||||||
this._provider = aProvider;
|
|
||||||
this._id = aId;
|
|
||||||
this._name = aName;
|
|
||||||
this._role = aRole;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChromecastRemoteDisplayDevice.prototype = {
|
|
||||||
_id: null,
|
|
||||||
_name: null,
|
|
||||||
_role: null,
|
|
||||||
_provider: null,
|
|
||||||
_ctrlChannel: null,
|
|
||||||
|
|
||||||
update: function CRDD_update(aName) {
|
|
||||||
this._name = aName || this._name;
|
|
||||||
},
|
|
||||||
|
|
||||||
// nsIPresentationDevice
|
|
||||||
get id() { return this._id; },
|
|
||||||
|
|
||||||
get name() { return this._name; },
|
|
||||||
|
|
||||||
get type() { return "chromecast"; },
|
|
||||||
|
|
||||||
establishControlChannel: function CRDD_establishControlChannel() {
|
|
||||||
this._ctrlChannel = new LocalControlChannel(this._provider,
|
|
||||||
this._id,
|
|
||||||
this._role);
|
|
||||||
|
|
||||||
if (this._role == Ci.nsIPresentationService.ROLE_CONTROLLER) {
|
|
||||||
// Only connect to Chromecast for controller.
|
|
||||||
// Monitor the receiver being ready.
|
|
||||||
Services.obs.addObserver(this, TOPIC_PRESENTATION_VIEW_READY, true);
|
|
||||||
|
|
||||||
// Launch Chromecast service in Android.
|
|
||||||
Messaging.sendRequestForResult({
|
|
||||||
type: TOPIC_ANDROID_CAST_DEVICE_START,
|
|
||||||
id: this.id
|
|
||||||
}).then(result => {
|
|
||||||
log("Chromecast is connected.");
|
|
||||||
}).catch(error => {
|
|
||||||
log("Can not connect to Chromecast.");
|
|
||||||
// If Chromecast can not be launched, remove the observer.
|
|
||||||
Services.obs.removeObserver(this, TOPIC_PRESENTATION_VIEW_READY);
|
|
||||||
this._ctrlChannel.disconnect(Cr.NS_ERROR_FAILURE);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// If establishControlChannel called from the receiver, we don't need to
|
|
||||||
// wait the 'presentation-view-ready' event.
|
|
||||||
this._ctrlChannel.notifyConnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._ctrlChannel;
|
|
||||||
},
|
|
||||||
|
|
||||||
disconnect: function CRDD_disconnect() {
|
|
||||||
// Disconnect from Chromecast.
|
|
||||||
Messaging.sendRequestForResult({
|
|
||||||
type: TOPIC_ANDROID_CAST_DEVICE_STOP,
|
|
||||||
id: this.id
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
isRequestedUrlSupported: function CRDD_isRequestedUrlSupported(aUrl) {
|
|
||||||
let url = Cc["@mozilla.org/network/io-service;1"]
|
|
||||||
.getService(Ci.nsIIOService)
|
|
||||||
.newURI(aUrl, null, null);
|
|
||||||
return url.scheme == "http" || url.scheme == "https";
|
|
||||||
},
|
|
||||||
|
|
||||||
// nsIPresentationLocalDevice
|
|
||||||
get windowId() { return this._id; },
|
|
||||||
|
|
||||||
// nsIObserver
|
|
||||||
observe: function CRDD_observe(aSubject, aTopic, aData) {
|
|
||||||
if (aTopic == TOPIC_PRESENTATION_VIEW_READY) {
|
|
||||||
log("ChromecastRemoteDisplayDevice - observe: aTopic="
|
|
||||||
+ aTopic + " data=" + aData);
|
|
||||||
if (this.windowId === aData) {
|
|
||||||
Services.obs.removeObserver(this, TOPIC_PRESENTATION_VIEW_READY);
|
|
||||||
this._ctrlChannel.notifyConnected();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDevice,
|
|
||||||
Ci.nsIPresentationLocalDevice,
|
|
||||||
Ci.nsISupportsWeakReference,
|
|
||||||
Ci.nsIObserver]),
|
|
||||||
};
|
|
||||||
|
|
||||||
function AndroidCastDeviceProvider() {
|
|
||||||
}
|
|
||||||
|
|
||||||
AndroidCastDeviceProvider.prototype = {
|
|
||||||
_listener: null,
|
|
||||||
_deviceList: new Map(),
|
|
||||||
|
|
||||||
onSessionRequest: function APDP_onSessionRequest(aDeviceId,
|
|
||||||
aUrl,
|
|
||||||
aPresentationId,
|
|
||||||
aControlChannel) {
|
|
||||||
log("AndroidCastDeviceProvider - onSessionRequest"
|
|
||||||
+ " aDeviceId=" + aDeviceId);
|
|
||||||
let device = this._deviceList.get(aDeviceId);
|
|
||||||
let receiverDevice = new ChromecastRemoteDisplayDevice(this,
|
|
||||||
device.id,
|
|
||||||
device.name,
|
|
||||||
Ci.nsIPresentationService.ROLE_RECEIVER);
|
|
||||||
this._listener.onSessionRequest(receiverDevice,
|
|
||||||
aUrl,
|
|
||||||
aPresentationId,
|
|
||||||
aControlChannel);
|
|
||||||
},
|
|
||||||
|
|
||||||
onTerminateRequest: function APDP_onTerminateRequest(aDeviceId,
|
|
||||||
aPresentationId,
|
|
||||||
aControlChannel,
|
|
||||||
aIsFromReceiver) {
|
|
||||||
log("AndroidCastDeviceProvider - onTerminateRequest"
|
|
||||||
+ " aDeviceId=" + aDeviceId
|
|
||||||
+ " aPresentationId=" + aPresentationId
|
|
||||||
+ " aIsFromReceiver=" + aIsFromReceiver);
|
|
||||||
let device = this._deviceList.get(aDeviceId);
|
|
||||||
this._listener.onTerminateRequest(device,
|
|
||||||
aPresentationId,
|
|
||||||
aControlChannel,
|
|
||||||
aIsFromReceiver);
|
|
||||||
},
|
|
||||||
|
|
||||||
// nsIPresentationDeviceProvider
|
|
||||||
set listener(aListener) {
|
|
||||||
this._listener = aListener;
|
|
||||||
|
|
||||||
// When unload this provider.
|
|
||||||
if (!this._listener) {
|
|
||||||
// remove observer
|
|
||||||
Services.obs.removeObserver(this, TOPIC_ANDROID_CAST_DEVICE_ADDED);
|
|
||||||
Services.obs.removeObserver(this, TOPIC_ANDROID_CAST_DEVICE_REMOVED);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync all device already found by Android.
|
|
||||||
Services.obs.notifyObservers(null, TOPIC_ANDROID_CAST_DEVICE_SYNCDEVICE, "");
|
|
||||||
// Observer registration
|
|
||||||
Services.obs.addObserver(this, TOPIC_ANDROID_CAST_DEVICE_ADDED, false);
|
|
||||||
Services.obs.addObserver(this, TOPIC_ANDROID_CAST_DEVICE_REMOVED, false);
|
|
||||||
},
|
|
||||||
|
|
||||||
get listener() {
|
|
||||||
return this._listener;
|
|
||||||
},
|
|
||||||
|
|
||||||
forceDiscovery: function APDP_forceDiscovery() {
|
|
||||||
// There is no API to do force discovery in Android SDK.
|
|
||||||
},
|
|
||||||
|
|
||||||
// nsIObserver
|
|
||||||
observe: function APDP_observe(aSubject, aTopic, aData) {
|
|
||||||
switch (aTopic) {
|
|
||||||
case TOPIC_ANDROID_CAST_DEVICE_ADDED: {
|
|
||||||
let deviceInfo = JSON.parse(aData);
|
|
||||||
let deviceId = deviceInfo.uuid;
|
|
||||||
|
|
||||||
if (!this._deviceList.has(deviceId)) {
|
|
||||||
let device = new ChromecastRemoteDisplayDevice(this,
|
|
||||||
deviceInfo.uuid,
|
|
||||||
deviceInfo.friendlyName,
|
|
||||||
Ci.nsIPresentationService.ROLE_CONTROLLER);
|
|
||||||
this._deviceList.set(device.id, device);
|
|
||||||
this._listener.addDevice(device);
|
|
||||||
} else {
|
|
||||||
let device = this._deviceList.get(deviceId);
|
|
||||||
device.update(deviceInfo.friendlyName);
|
|
||||||
this._listener.updateDevice(device);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TOPIC_ANDROID_CAST_DEVICE_REMOVED: {
|
|
||||||
let deviceId = aData;
|
|
||||||
let device = this._deviceList.get(deviceId);
|
|
||||||
this._listener.removeDevice(device);
|
|
||||||
this._deviceList.delete(deviceId);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
classID: Components.ID("{7394f24c-dbc3-48c8-8a47-cd10169b7c6b}"),
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
|
||||||
Ci.nsIPresentationDeviceProvider]),
|
|
||||||
};
|
|
||||||
|
|
||||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AndroidCastDeviceProvider]);
|
|
|
@ -1,4 +0,0 @@
|
||||||
# AndroidCastDeviceProvider.js
|
|
||||||
component {7394f24c-dbc3-48c8-8a47-cd10169b7c6b} AndroidCastDeviceProvider.js
|
|
||||||
contract @mozilla.org/presentation-device/android-cast-device-provider;1 {7394f24c-dbc3-48c8-8a47-cd10169b7c6b}
|
|
||||||
category presentation-device-provider AndroidCastDeviceProvider @mozilla.org/presentation-device/android-cast-device-provider;1
|
|
|
@ -1,2 +0,0 @@
|
||||||
component {f4079b8b-ede5-4b90-a112-5b415a931deb} PresentationControlService.js
|
|
||||||
contract @mozilla.org/presentation/control-service;1 {f4079b8b-ede5-4b90-a112-5b415a931deb}
|
|
|
@ -1,240 +0,0 @@
|
||||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* 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/. */
|
|
||||||
/* jshint esnext:true, globalstrict:true, moz:true, undef:true, unused:true */
|
|
||||||
/* globals Components, dump */
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
this.EXPORTED_SYMBOLS = ["ControllerStateMachine"]; // jshint ignore:line
|
|
||||||
|
|
||||||
const { utils: Cu } = Components;
|
|
||||||
|
|
||||||
/* globals State, CommandType */
|
|
||||||
Cu.import("resource://gre/modules/presentation/StateMachineHelper.jsm");
|
|
||||||
|
|
||||||
const DEBUG = false;
|
|
||||||
function debug(str) {
|
|
||||||
dump("-*- ControllerStateMachine: " + str + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
var handlers = [
|
|
||||||
function _initHandler(stateMachine, command) {
|
|
||||||
// shouldn't receive any command at init state.
|
|
||||||
DEBUG && debug("unexpected command: " + JSON.stringify(command)); // jshint ignore:line
|
|
||||||
},
|
|
||||||
function _connectingHandler(stateMachine, command) {
|
|
||||||
switch (command.type) {
|
|
||||||
case CommandType.CONNECT_ACK:
|
|
||||||
stateMachine.state = State.CONNECTED;
|
|
||||||
stateMachine._notifyDeviceConnected();
|
|
||||||
break;
|
|
||||||
case CommandType.DISCONNECT:
|
|
||||||
stateMachine.state = State.CLOSED;
|
|
||||||
stateMachine._notifyDisconnected(command.reason);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
debug("unexpected command: " + JSON.stringify(command));
|
|
||||||
// ignore unexpected command.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
function _connectedHandler(stateMachine, command) {
|
|
||||||
switch (command.type) {
|
|
||||||
case CommandType.DISCONNECT:
|
|
||||||
stateMachine.state = State.CLOSED;
|
|
||||||
stateMachine._notifyDisconnected(command.reason);
|
|
||||||
break;
|
|
||||||
case CommandType.LAUNCH_ACK:
|
|
||||||
stateMachine._notifyLaunch(command.presentationId);
|
|
||||||
break;
|
|
||||||
case CommandType.TERMINATE:
|
|
||||||
stateMachine._notifyTerminate(command.presentationId);
|
|
||||||
break;
|
|
||||||
case CommandType.TERMINATE_ACK:
|
|
||||||
stateMachine._notifyTerminate(command.presentationId);
|
|
||||||
break;
|
|
||||||
case CommandType.ANSWER:
|
|
||||||
case CommandType.ICE_CANDIDATE:
|
|
||||||
stateMachine._notifyChannelDescriptor(command);
|
|
||||||
break;
|
|
||||||
case CommandType.RECONNECT_ACK:
|
|
||||||
stateMachine._notifyReconnect(command.presentationId);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
debug("unexpected command: " + JSON.stringify(command));
|
|
||||||
// ignore unexpected command.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
function _closingHandler(stateMachine, command) {
|
|
||||||
switch (command.type) {
|
|
||||||
case CommandType.DISCONNECT:
|
|
||||||
stateMachine.state = State.CLOSED;
|
|
||||||
stateMachine._notifyDisconnected(command.reason);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
debug("unexpected command: " + JSON.stringify(command));
|
|
||||||
// ignore unexpected command.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
function _closedHandler(stateMachine, command) {
|
|
||||||
// ignore every command in closed state.
|
|
||||||
DEBUG && debug("unexpected command: " + JSON.stringify(command)); // jshint ignore:line
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
function ControllerStateMachine(channel, deviceId) {
|
|
||||||
this.state = State.INIT;
|
|
||||||
this._channel = channel;
|
|
||||||
this._deviceId = deviceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
ControllerStateMachine.prototype = {
|
|
||||||
launch: function _launch(presentationId, url) {
|
|
||||||
if (this.state === State.CONNECTED) {
|
|
||||||
this._sendCommand({
|
|
||||||
type: CommandType.LAUNCH,
|
|
||||||
presentationId: presentationId,
|
|
||||||
url: url,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
terminate: function _terminate(presentationId) {
|
|
||||||
if (this.state === State.CONNECTED) {
|
|
||||||
this._sendCommand({
|
|
||||||
type: CommandType.TERMINATE,
|
|
||||||
presentationId: presentationId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
terminateAck: function _terminateAck(presentationId) {
|
|
||||||
if (this.state === State.CONNECTED) {
|
|
||||||
this._sendCommand({
|
|
||||||
type: CommandType.TERMINATE_ACK,
|
|
||||||
presentationId: presentationId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
reconnect: function _reconnect(presentationId, url) {
|
|
||||||
if (this.state === State.CONNECTED) {
|
|
||||||
this._sendCommand({
|
|
||||||
type: CommandType.RECONNECT,
|
|
||||||
presentationId: presentationId,
|
|
||||||
url: url,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
sendOffer: function _sendOffer(offer) {
|
|
||||||
if (this.state === State.CONNECTED) {
|
|
||||||
this._sendCommand({
|
|
||||||
type: CommandType.OFFER,
|
|
||||||
offer: offer,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
sendAnswer: function _sendAnswer() {
|
|
||||||
// answer can only be sent by presenting UA.
|
|
||||||
debug("controller shouldn't generate answer");
|
|
||||||
},
|
|
||||||
|
|
||||||
updateIceCandidate: function _updateIceCandidate(candidate) {
|
|
||||||
if (this.state === State.CONNECTED) {
|
|
||||||
this._sendCommand({
|
|
||||||
type: CommandType.ICE_CANDIDATE,
|
|
||||||
candidate: candidate,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onCommand: function _onCommand(command) {
|
|
||||||
handlers[this.state](this, command);
|
|
||||||
},
|
|
||||||
|
|
||||||
onChannelReady: function _onChannelReady() {
|
|
||||||
if (this.state === State.INIT) {
|
|
||||||
this._sendCommand({
|
|
||||||
type: CommandType.CONNECT,
|
|
||||||
deviceId: this._deviceId
|
|
||||||
});
|
|
||||||
this.state = State.CONNECTING;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onChannelClosed: function _onChannelClose(reason, isByRemote) {
|
|
||||||
switch (this.state) {
|
|
||||||
case State.CONNECTED:
|
|
||||||
if (isByRemote) {
|
|
||||||
this.state = State.CLOSED;
|
|
||||||
this._notifyDisconnected(reason);
|
|
||||||
} else {
|
|
||||||
this._sendCommand({
|
|
||||||
type: CommandType.DISCONNECT,
|
|
||||||
reason: reason
|
|
||||||
});
|
|
||||||
this.state = State.CLOSING;
|
|
||||||
this._closeReason = reason;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case State.CLOSING:
|
|
||||||
if (isByRemote) {
|
|
||||||
this.state = State.CLOSED;
|
|
||||||
if (this._closeReason) {
|
|
||||||
reason = this._closeReason;
|
|
||||||
delete this._closeReason;
|
|
||||||
}
|
|
||||||
this._notifyDisconnected(reason);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
DEBUG && debug("unexpected channel close: " + reason + ", " + isByRemote); // jshint ignore:line
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_sendCommand: function _sendCommand(command) {
|
|
||||||
this._channel.sendCommand(command);
|
|
||||||
},
|
|
||||||
|
|
||||||
_notifyDeviceConnected: function _notifyDeviceConnected() {
|
|
||||||
//XXX trigger following command
|
|
||||||
this._channel.notifyDeviceConnected();
|
|
||||||
},
|
|
||||||
|
|
||||||
_notifyDisconnected: function _notifyDisconnected(reason) {
|
|
||||||
this._channel.notifyDisconnected(reason);
|
|
||||||
},
|
|
||||||
|
|
||||||
_notifyLaunch: function _notifyLaunch(presentationId) {
|
|
||||||
this._channel.notifyLaunch(presentationId);
|
|
||||||
},
|
|
||||||
|
|
||||||
_notifyTerminate: function _notifyTerminate(presentationId) {
|
|
||||||
this._channel.notifyTerminate(presentationId);
|
|
||||||
},
|
|
||||||
|
|
||||||
_notifyReconnect: function _notifyReconnect(presentationId) {
|
|
||||||
this._channel.notifyReconnect(presentationId);
|
|
||||||
},
|
|
||||||
|
|
||||||
_notifyChannelDescriptor: function _notifyChannelDescriptor(command) {
|
|
||||||
switch (command.type) {
|
|
||||||
case CommandType.ANSWER:
|
|
||||||
this._channel.notifyAnswer(command.answer);
|
|
||||||
break;
|
|
||||||
case CommandType.ICE_CANDIDATE:
|
|
||||||
this._channel.notifyIceCandidate(command.candidate);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
this.ControllerStateMachine = ControllerStateMachine; // jshint ignore:line
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue