Bumping manifests a=b2g-bump
[gecko.git] / browser / modules / CastingApps.jsm
blob1c8a706ea02f19b270f6c922cee808a9b7d64cf7
1 // -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4  * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 "use strict";
6 this.EXPORTED_SYMBOLS = ["CastingApps"];
8 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
10 Cu.import("resource://gre/modules/Services.jsm");
11 Cu.import("resource://gre/modules/SimpleServiceDiscovery.jsm");
14 var CastingApps = {
15   _sendEventToVideo: function (element, data) {
16     let event = element.ownerDocument.createEvent("CustomEvent");
17     event.initCustomEvent("media-videoCasting", false, true, JSON.stringify(data));
18     element.dispatchEvent(event);
19   },
21   makeURI: function (url, charset, baseURI) {
22     return Services.io.newURI(url, charset, baseURI);
23   },
25   getVideo: function (element) {
26     if (!element) {
27       return null;
28     }
30     let extensions = SimpleServiceDiscovery.getSupportedExtensions();
31     let types = SimpleServiceDiscovery.getSupportedMimeTypes();
33     // Grab the poster attribute from the <video>
34     let posterURL = element.poster;
36     // First, look to see if the <video> has a src attribute
37     let sourceURL = element.src;
39     // If empty, try the currentSrc
40     if (!sourceURL) {
41       sourceURL = element.currentSrc;
42     }
44     if (sourceURL) {
45       // Use the file extension to guess the mime type
46       let sourceURI = this.makeURI(sourceURL, null, this.makeURI(element.baseURI));
47       if (this.allowableExtension(sourceURI, extensions)) {
48         return { element: element, source: sourceURI.spec, poster: posterURL, sourceURI: sourceURI};
49       }
50     }
52     // Next, look to see if there is a <source> child element that meets
53     // our needs
54     let sourceNodes = element.getElementsByTagName("source");
55     for (let sourceNode of sourceNodes) {
56       let sourceURI = this.makeURI(sourceNode.src, null, this.makeURI(sourceNode.baseURI));
58       // Using the type attribute is our ideal way to guess the mime type. Otherwise,
59       // fallback to using the file extension to guess the mime type
60       if (this.allowableMimeType(sourceNode.type, types) || this.allowableExtension(sourceURI, extensions)) {
61         return { element: element, source: sourceURI.spec, poster: posterURL, sourceURI: sourceURI, type: sourceNode.type };
62       }
63     }
65     return null;
66   },
68   sendVideoToService: function (videoElement, service) {
69     if (!service)
70       return;
72     let video = this.getVideo(videoElement);
73     if (!video) {
74       return;
75     }
77     // Make sure we have a player app for the given service
78     let app = SimpleServiceDiscovery.findAppForService(service);
79     if (!app)
80       return;
82     video.title = videoElement.ownerDocument.defaultView.top.document.title;
83     if (video.element) {
84       // If the video is currently playing on the device, pause it
85       if (!video.element.paused) {
86         video.element.pause();
87       }
88     }
90     app.stop(() => {
91       app.start(started => {
92         if (!started) {
93           Cu.reportError("CastingApps: Unable to start app");
94           return;
95         }
97         app.remoteMedia(remoteMedia => {
98           if (!remoteMedia) {
99             Cu.reportError("CastingApps: Failed to create remotemedia");
100             return;
101           }
103           this.session = {
104             service: service,
105             app: app,
106             remoteMedia: remoteMedia,
107             data: {
108               title: video.title,
109               source: video.source,
110               poster: video.poster
111             },
112             videoRef: Cu.getWeakReference(video.element)
113           };
114         }, this);
115       });
116     });
117   },
119   getServicesForVideo: function (videoElement) {
120     let video = this.getVideo(videoElement);
121     if (!video) {
122       return {};
123     }
125     let filteredServices = SimpleServiceDiscovery.services.filter(service => {
126       return this.allowableExtension(video.sourceURI, service.extensions) ||
127              this.allowableMimeType(video.type, service.types);
128     });
130     return filteredServices;
131   },
133   getServicesForMirroring: function () {
134     return SimpleServiceDiscovery.services.filter(service => service.mirror);
135   },
137   // RemoteMedia callback API methods
138   onRemoteMediaStart: function (remoteMedia) {
139     if (!this.session) {
140       return;
141     }
143     remoteMedia.load(this.session.data);
145     let video = this.session.videoRef.get();
146     if (video) {
147       this._sendEventToVideo(video, { active: true });
148     }
149   },
151   onRemoteMediaStop: function (remoteMedia) {
152   },
154   onRemoteMediaStatus: function (remoteMedia) {
155   },
157   allowableExtension: function (uri, extensions) {
158     return (uri instanceof Ci.nsIURL) && extensions.indexOf(uri.fileExtension) != -1;
159   },
161   allowableMimeType: function (type, types) {
162     return types.indexOf(type) != -1;
163   }