Mozilla Cross-Reference mozilla-central
mozilla/ browser/ base/ content/ browser-eme.js
Hg Log
Hg Blame
Diff file
Raw file
view using tree:
1 # -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
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/.
5 
6 let gEMEHandler = {
7   ensureEMEEnabled: function(browser, keySystem) {
8     Services.prefs.setBoolPref("media.eme.enabled", true);
9     if (keySystem) {
10       if (keySystem.startsWith("com.adobe") &&
11           Services.prefs.getPrefType("media.gmp-eme-adobe.enabled") &&
12           !Services.prefs.getBoolPref("media.gmp-eme-adobe.enabled")) {
13         Services.prefs.setBoolPref("media.gmp-eme-adobe.enabled", true);
14       } else if (keySystem == "org.w3.clearkey" &&
15                  Services.prefs.getPrefType("media.eme.clearkey.enabled") &&
16                  !Services.prefs.getBoolPref("media.eme.clearkey.enabled")) {
17         Services.prefs.setBoolPref("media.eme.clearkey.enabled", true);
18       }
19     }
20     browser.reload();
21   },
22   getLearnMoreLink: function(msgId) {
23     let text = gNavigatorBundle.getString("emeNotifications." + msgId + ".learnMoreLabel");
24     let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
25     return "<label class='text-link' href='" + baseURL + "drm-content'>" +
26            text + "</label>";
27   },
28   onDontAskAgain: function(menuPopupItem) {
29     let button = menuPopupItem.parentNode.anchorNode;
30     let bar = button.parentNode;
31     Services.prefs.setBoolPref("browser.eme.ui." + bar.value + ".disabled", true);
32     bar.close();
33   },
34   onNotNow: function(menuPopupItem) {
35     let button = menuPopupItem.parentNode.anchorNode;
36     button.parentNode.close();
37   },
38   receiveMessage: function({target: browser, data: data}) {
39     let parsedData;
40     try {
41       parsedData = JSON.parse(data);
42     } catch (ex) {
43       Cu.reportError("Malformed EME video message with data: " + data);
44       return;
45     }
46     let {status: status, keySystem: keySystem} = parsedData;
47     // Don't need to show if disabled
48     if (!Services.prefs.getBoolPref("browser.eme.ui.enabled")) {
49       return;
50     }
51 
52     let notificationId;
53     let buttonCallback;
54     let params = [];
55     switch (status) {
56       case "available":
57       case "cdm-created":
58         this.showPopupNotificationForSuccess(browser, keySystem);
59         // ... and bail!
60         return;
61 
62       case "api-disabled":
63       case "cdm-disabled":
64         notificationId = "drmContentDisabled";
65         buttonCallback = gEMEHandler.ensureEMEEnabled.bind(gEMEHandler, browser, keySystem)
66         params = [this.getLearnMoreLink(notificationId)];
67         break;
68 
69       case "cdm-not-supported":
70         notificationId = "drmContentCDMNotSupported";
71         params = [this._brandShortName, this.getLearnMoreLink(notificationId)];
72         break;
73 
74       case "cdm-insufficient-version":
75         notificationId = "drmContentCDMInsufficientVersion";
76         params = [this._brandShortName];
77         break;
78 
79       case "cdm-not-installed":
80         notificationId = "drmContentCDMInstalling";
81         params = [this._brandShortName];
82         break;
83 
84       case "error":
85         // Fall through and do the same for unknown messages:
86       default:
87         let typeOfIssue = status == "error" ? "error" : "message ('" + status + "')";
88         Cu.reportError("Unknown " + typeOfIssue + " dealing with EME key request: " + data);
89         return;
90     }
91 
92     this.showNotificationBar(browser, notificationId, keySystem, params, buttonCallback);
93   },
94   showNotificationBar: function(browser, notificationId, keySystem, labelParams, callback) {
95     let box = gBrowser.getNotificationBox(browser);
96     if (box.getNotificationWithValue(notificationId)) {
97       return;
98     }
99 
100     // If the user turned these off, bail out:
101     try {
102       if (Services.prefs.getBoolPref("browser.eme.ui." + notificationId + ".disabled")) {
103         return;
104       }
105     } catch (ex) { /* Don't care if the pref doesn't exist */ }
106 
107     let msgPrefix = "emeNotifications." + notificationId + ".";
108     let msgId = msgPrefix + "message";
109 
110     // Specialcase Adobe's CDM on unsupported platforms to be more informative:
111     if (notificationId == "drmContentCDMNotSupported" &&
112         keySystem.startsWith("com.adobe")) {
113       let os = Services.appinfo.OS.toLowerCase();
114       if (os.startsWith("win") && Services.appinfo.XPCOMABI.startsWith("x86_64")) {
115         msgId = msgPrefix + "64bit.message";
116       } else if (os.startsWith("linux") || os.startsWith("darwin")) {
117         msgId = msgPrefix + "unsupportedOS.message";
118         labelParams.splice(1, 0, os.startsWith("linux") ? "Linux" : "Mac OS X");
119       }
120     }
121 
122     let message = labelParams.length ?
123                   gNavigatorBundle.getFormattedString(msgId, labelParams) :
124                   gNavigatorBundle.getString(msgId);
125 
126     let buttons = [];
127     if (callback) {
128       let btnLabelId = msgPrefix + "button.label";
129       let btnAccessKeyId = msgPrefix + "button.accesskey";
130       buttons.push({
131         label: gNavigatorBundle.getString(btnLabelId),
132         accessKey: gNavigatorBundle.getString(btnAccessKeyId),
133         callback: callback
134       });
135 
136       let optionsId = "emeNotifications.optionsButton";
137       buttons.push({
138         label: gNavigatorBundle.getString(optionsId + ".label"),
139         accessKey: gNavigatorBundle.getString(optionsId + ".accesskey"),
140         popup: "emeNotificationsPopup"
141       });
142     }
143 
144     let iconURL = "chrome://browser/skin/drm-icon.svg#chains-black";
145 
146     // Do a little dance to get rich content into the notification:
147     let fragment = document.createDocumentFragment();
148     let descriptionContainer = document.createElement("description");
149     descriptionContainer.innerHTML = message;
150     while (descriptionContainer.childNodes.length) {
151       fragment.appendChild(descriptionContainer.childNodes[0]);
152     }
153 
154     box.appendNotification(fragment, notificationId, iconURL, box.PRIORITY_WARNING_MEDIUM,
155                            buttons);
156   },
157   showPopupNotificationForSuccess: function(browser, keySystem) {
158     // We're playing EME content! Remove any "we can't play because..." messages.
159     var box = gBrowser.getNotificationBox(browser);
160     ["drmContentDisabled",
161      "drmContentCDMNotSupported",
162      "drmContentCDMInsufficientVersion",
163      "drmContentCDMInstalling"
164      ].forEach(function (value) {
165         var notification = box.getNotificationWithValue(value);
166         if (notification)
167           box.removeNotification(notification);
168       });
169 
170     // Don't bother creating it if it's already there:
171     if (PopupNotifications.getNotification("drmContentPlaying", browser)) {
172       return;
173     }
174 
175     let msgPrefix = "emeNotifications.drmContentPlaying.";
176     let msgId = msgPrefix + "message2";
177     let btnLabelId = msgPrefix + "button.label";
178     let btnAccessKeyId = msgPrefix + "button.accesskey";
179 
180     let message = gNavigatorBundle.getFormattedString(msgId, [this._brandShortName]);
181     let anchorId = "eme-notification-icon";
182     let firstPlayPref = "browser.eme.ui.firstContentShown";
183     if (!Services.prefs.getPrefType(firstPlayPref) ||
184         !Services.prefs.getBoolPref(firstPlayPref)) {
185       document.getElementById(anchorId).setAttribute("firstplay", "true");
186       Services.prefs.setBoolPref(firstPlayPref, true);
187     } else {
188       document.getElementById(anchorId).removeAttribute("firstplay");
189     }
190 
191 
192     let mainAction = {
193       label: gNavigatorBundle.getString(btnLabelId),
194       accessKey: gNavigatorBundle.getString(btnAccessKeyId),
195       callback: function() { openPreferences("paneContent"); },
196       dismiss: true
197     };
198     let options = {
199       dismissed: true,
200       eventCallback: aTopic => aTopic == "swapping",
201     };
202     PopupNotifications.show(browser, "drmContentPlaying", message, anchorId, mainAction, null, options);
203   },
204   QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener])
205 };
206 
207 XPCOMUtils.defineLazyGetter(gEMEHandler, "_brandShortName", function() {
208   return document.getElementById("bundle_brand").getString("brandShortName");
209 });
210 
211 window.messageManager.addMessageListener("EMEVideo:ContentMediaKeysRequest", gEMEHandler);
212 window.addEventListener("unload", function() {
213   window.messageManager.removeMessageListener("EMEVideo:ContentMediaKeysRequest", gEMEHandler);
214 }, false);
215 
view http://hg.mozilla.org/mozilla-central/rev/ /browser/base/content/browser-eme.js