1 /* vim: set ts=2 sw=2 sts=2 et tw=80: */
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
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 ChromeUtils.defineLazyGetter(lazy, "gBrandBundle", function () {
9 return Services.strings.createBundle(
10 "chrome://branding/locale/brand.properties"
14 ChromeUtils.defineLazyGetter(lazy, "gNavigatorBundle", function () {
15 return Services.strings.createBundle(
16 "chrome://browser/locale/browser.properties"
20 ChromeUtils.defineLazyGetter(lazy, "gFluentStrings", function () {
21 return new Localization(["branding/brand.ftl", "browser/browser.ftl"], true);
24 export class EncryptedMediaParent extends JSWindowActorParent {
26 return Services.prefs.getBoolPref("browser.eme.ui.enabled");
29 ensureEMEEnabled(aBrowser, aKeySystem) {
30 Services.prefs.setBoolPref("media.eme.enabled", true);
33 aKeySystem == "com.widevine.alpha" &&
34 Services.prefs.getPrefType("media.gmp-widevinecdm.enabled") &&
35 !Services.prefs.getBoolPref("media.gmp-widevinecdm.enabled")
37 Services.prefs.setBoolPref("media.gmp-widevinecdm.enabled", true);
42 isKeySystemVisible(aKeySystem) {
47 aKeySystem == "com.widevine.alpha" &&
48 Services.prefs.getPrefType("media.gmp-widevinecdm.visible")
50 return Services.prefs.getBoolPref("media.gmp-widevinecdm.visible");
55 getMessageWithBrandName(aNotificationId) {
56 let msgId = "emeNotifications." + aNotificationId + ".message";
57 return lazy.gNavigatorBundle.formatStringFromName(msgId, [
58 lazy.gBrandBundle.GetStringFromName("brandShortName"),
62 receiveMessage(aMessage) {
63 // The top level browsing context's embedding element should be a xul browser element.
64 let browser = this.browsingContext.top.embedderElement;
67 // We don't have a browser so bail!
73 parsedData = JSON.parse(aMessage.data);
75 console.error("Malformed EME video message with data: ", aMessage.data);
78 let { status, keySystem } = parsedData;
80 // First, see if we need to do updates. We don't need to do anything for
82 if (!this.isKeySystemVisible(keySystem)) {
85 if (status == "cdm-not-installed") {
86 Services.obs.notifyObservers(browser, "EMEVideo:CDMMissing");
89 // Don't need to show UI if disabled.
90 if (!this.isUiEnabled()) {
97 // Notification message can be either a string or a DOM fragment.
98 let notificationMessage;
102 // Only show the chain icon for proprietary CDMs. Clearkey is not one.
103 if (keySystem != "org.w3.clearkey") {
104 this.showPopupNotificationForSuccess(browser, keySystem);
111 notificationId = "drmContentDisabled";
112 buttonCallback = () => {
113 this.ensureEMEEnabled(browser, keySystem);
115 notificationMessage = lazy.gNavigatorBundle.GetStringFromName(
116 "emeNotifications.drmContentDisabled.message2"
118 supportPage = "drm-content";
121 case "cdm-not-installed":
122 notificationId = "drmContentCDMInstalling";
123 notificationMessage = this.getMessageWithBrandName(notificationId);
126 case "cdm-not-supported":
127 // Not to pop up user-level notification because they cannot do anything
133 "Unknown message ('" +
135 "') dealing with EME key request: " +
142 // Now actually create the notification
144 let notificationBox = browser.getTabBrowser().getNotificationBox(browser);
145 if (notificationBox.getNotificationWithValue(notificationId)) {
151 buttons.push({ supportPage });
153 if (buttonCallback) {
154 let msgPrefix = "emeNotifications." + notificationId + ".";
155 let manageLabelId = msgPrefix + "button.label";
156 let manageAccessKeyId = msgPrefix + "button.accesskey";
158 label: lazy.gNavigatorBundle.GetStringFromName(manageLabelId),
159 accessKey: lazy.gNavigatorBundle.GetStringFromName(manageAccessKeyId),
160 callback: buttonCallback,
164 let iconURL = "chrome://browser/skin/drm-icon.svg";
165 notificationBox.appendNotification(
168 label: notificationMessage,
170 priority: notificationBox.PRIORITY_INFO_HIGH,
176 async showPopupNotificationForSuccess(aBrowser) {
177 // We're playing EME content! Remove any "we can't play because..." messages.
178 let notificationBox = aBrowser.getTabBrowser().getNotificationBox(aBrowser);
179 ["drmContentDisabled", "drmContentCDMInstalling"].forEach(function (value) {
180 let notification = notificationBox.getNotificationWithValue(value);
182 notificationBox.removeNotification(notification);
186 // Don't bother creating it if it's already there:
188 aBrowser.ownerGlobal.PopupNotifications.getNotification(
196 let msgPrefix = "eme-notifications-drm-content-playing";
197 let msgId = msgPrefix;
198 let manageLabelId = msgPrefix + "-manage";
199 let manageAccessKeyId = msgPrefix + "-manage-accesskey";
200 let dismissLabelId = msgPrefix + "-dismiss";
201 let dismissAccessKeyId = msgPrefix + "-dismiss-accesskey";
209 ] = await lazy.gFluentStrings.formatValues([
217 let anchorId = "eme-notification-icon";
218 let firstPlayPref = "browser.eme.ui.firstContentShown";
219 let document = aBrowser.ownerDocument;
221 !Services.prefs.getPrefType(firstPlayPref) ||
222 !Services.prefs.getBoolPref(firstPlayPref)
224 document.getElementById(anchorId).setAttribute("firstplay", "true");
225 Services.prefs.setBoolPref(firstPlayPref, true);
227 document.getElementById(anchorId).removeAttribute("firstplay");
232 accessKey: manageAccessKey,
234 aBrowser.ownerGlobal.openPreferences("general-drm");
239 let secondaryActions = [
242 accessKey: dismissAccessKey,
250 eventCallback: aTopic => aTopic == "swapping",
252 Services.urlFormatter.formatURLPref("app.support.baseURL") +
256 aBrowser.ownerGlobal.PopupNotifications.show(