Bug 1845017 - Disable the TestPHCExhaustion test r=glandium
[gecko.git] / browser / actors / PluginParent.sys.mjs
blobba4b82fa345519bb846d1065cfb717f33d9881ea
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/. */
6 import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
8 const lazy = {};
10 ChromeUtils.defineESModuleGetters(lazy, {
11   CrashSubmit: "resource://gre/modules/CrashSubmit.sys.mjs",
12 });
14 ChromeUtils.defineLazyGetter(lazy, "gNavigatorBundle", function () {
15   const url = "chrome://browser/locale/browser.properties";
16   return Services.strings.createBundle(url);
17 });
19 export const PluginManager = {
20   gmpCrashes: new Map(),
22   observe(subject, topic, data) {
23     switch (topic) {
24       case "gmp-plugin-crash":
25         this._registerGMPCrash(subject);
26         break;
27     }
28   },
30   _registerGMPCrash(subject) {
31     let propertyBag = subject;
32     if (
33       !(propertyBag instanceof Ci.nsIWritablePropertyBag2) ||
34       !propertyBag.hasKey("pluginID") ||
35       !propertyBag.hasKey("pluginDumpID") ||
36       !propertyBag.hasKey("pluginName")
37     ) {
38       console.error("PluginManager can not read plugin information.");
39       return;
40     }
42     let pluginID = propertyBag.getPropertyAsUint32("pluginID");
43     let pluginDumpID = propertyBag.getPropertyAsAString("pluginDumpID");
44     let pluginName = propertyBag.getPropertyAsACString("pluginName");
45     if (pluginDumpID) {
46       this.gmpCrashes.set(pluginID, { pluginDumpID, pluginID, pluginName });
47     }
49     // Only the parent process gets the gmp-plugin-crash observer
50     // notification, so we need to inform any content processes that
51     // the GMP has crashed. This then fires PluginCrashed events in
52     // all the relevant windows, which will trigger child actors being
53     // created, which will contact us again, when we'll use the
54     // gmpCrashes collection to respond.
55     if (Services.ppmm) {
56       Services.ppmm.broadcastAsyncMessage("gmp-plugin-crash", {
57         pluginName,
58         pluginID,
59       });
60     }
61   },
63   /**
64    * Submit a crash report for a crashed plugin.
65    *
66    * @param pluginCrashID
67    *        An object with a pluginID.
68    * @param keyVals
69    *        An object whose key-value pairs will be merged
70    *        with the ".extra" file submitted with the report.
71    *        The properties of htis object will override properties
72    *        of the same name in the .extra file.
73    */
74   submitCrashReport(pluginCrashID, keyVals = {}) {
75     let report = this.getCrashReport(pluginCrashID);
76     if (!report) {
77       console.error(
78         `Could not find plugin dump IDs for ${JSON.stringify(pluginCrashID)}.` +
79           `It is possible that a report was already submitted.`
80       );
81       return;
82     }
84     let { pluginDumpID } = report;
85     lazy.CrashSubmit.submit(
86       pluginDumpID,
87       lazy.CrashSubmit.SUBMITTED_FROM_CRASH_TAB,
88       {
89         recordSubmission: true,
90         extraExtraKeyVals: keyVals,
91       }
92     );
94     this.gmpCrashes.delete(pluginCrashID.pluginID);
95   },
97   getCrashReport(pluginCrashID) {
98     return this.gmpCrashes.get(pluginCrashID.pluginID);
99   },
102 export class PluginParent extends JSWindowActorParent {
103   receiveMessage(msg) {
104     let browser = this.manager.rootFrameLoader.ownerElement;
105     switch (msg.name) {
106       case "PluginContent:ShowPluginCrashedNotification":
107         this.showPluginCrashedNotification(browser, msg.data.pluginCrashID);
108         break;
110       default:
111         console.error(
112           "PluginParent did not expect to handle message ",
113           msg.name
114         );
115         break;
116     }
118     return null;
119   }
121   /**
122    * Shows a plugin-crashed notification bar for a browser that has had a
123    * GMP plugin crash.
124    *
125    * @param browser
126    *        The browser to show the notification for.
127    * @param pluginCrashID
128    *        The unique-per-process identifier for GMP.
129    */
130   showPluginCrashedNotification(browser, pluginCrashID) {
131     // If there's already an existing notification bar, don't do anything.
132     let notificationBox = browser.getTabBrowser().getNotificationBox(browser);
133     let notification =
134       notificationBox.getNotificationWithValue("plugin-crashed");
136     let report = PluginManager.getCrashReport(pluginCrashID);
137     if (notification || !report) {
138       return;
139     }
141     // Configure the notification bar
142     let priority = notificationBox.PRIORITY_WARNING_MEDIUM;
143     let iconURL = "chrome://global/skin/icons/plugin.svg";
144     let reloadLabel = lazy.gNavigatorBundle.GetStringFromName(
145       "crashedpluginsMessage.reloadButton.label"
146     );
147     let reloadKey = lazy.gNavigatorBundle.GetStringFromName(
148       "crashedpluginsMessage.reloadButton.accesskey"
149     );
151     let buttons = [
152       {
153         label: reloadLabel,
154         accessKey: reloadKey,
155         popup: null,
156         callback() {
157           browser.reload();
158         },
159       },
160     ];
162     if (AppConstants.MOZ_CRASHREPORTER) {
163       let submitLabel = lazy.gNavigatorBundle.GetStringFromName(
164         "crashedpluginsMessage.submitButton.label"
165       );
166       let submitKey = lazy.gNavigatorBundle.GetStringFromName(
167         "crashedpluginsMessage.submitButton.accesskey"
168       );
169       let submitButton = {
170         label: submitLabel,
171         accessKey: submitKey,
172         popup: null,
173         callback: () => {
174           PluginManager.submitCrashReport(pluginCrashID);
175         },
176       };
178       buttons.push(submitButton);
179     }
181     let messageString = lazy.gNavigatorBundle.formatStringFromName(
182       "crashedpluginsMessage.title",
183       [report.pluginName]
184     );
185     notification = notificationBox.appendNotification(
186       "plugin-crashed",
187       {
188         label: messageString,
189         image: iconURL,
190         priority,
191       },
192       buttons
193     );
195     // Add the "learn more" link.
196     let link = notification.ownerDocument.createXULElement("label", {
197       is: "text-link",
198     });
199     link.setAttribute(
200       "value",
201       lazy.gNavigatorBundle.GetStringFromName("crashedpluginsMessage.learnMore")
202     );
203     let crashurl = Services.urlFormatter.formatURLPref("app.support.baseURL");
204     crashurl += "plugin-crashed-notificationbar";
205     link.href = crashurl;
206     // Append a blank text node to make sure we don't put
207     // the link right next to the end of the message text.
208     notification.messageText.appendChild(new Text(" "));
209     notification.messageText.appendChild(link);
210   }