summaryrefslogtreecommitdiffstats
path: root/browser/actors/PluginChild.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'browser/actors/PluginChild.sys.mjs')
-rw-r--r--browser/actors/PluginChild.sys.mjs92
1 files changed, 92 insertions, 0 deletions
diff --git a/browser/actors/PluginChild.sys.mjs b/browser/actors/PluginChild.sys.mjs
new file mode 100644
index 0000000000..6eea749ef9
--- /dev/null
+++ b/browser/actors/PluginChild.sys.mjs
@@ -0,0 +1,92 @@
+/* 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/. */
+
+// Handle GMP crashes
+export class PluginChild extends JSWindowActorChild {
+ handleEvent(event) {
+ // Ignore events for other frames.
+ let eventDoc = event.target.ownerDocument || event.target.document;
+ if (eventDoc && eventDoc != this.document) {
+ return;
+ }
+
+ let eventType = event.type;
+ if (eventType == "PluginCrashed") {
+ this.onPluginCrashed(event);
+ }
+ }
+
+ /**
+ * Determines whether or not the crashed plugin is contained within current
+ * full screen DOM element.
+ * @param fullScreenElement (DOM element)
+ * The DOM element that is currently full screen, or null.
+ * @param domElement
+ * The DOM element which contains the crashed plugin, or the crashed plugin
+ * itself.
+ * @returns bool
+ * True if the plugin is a descendant of the full screen DOM element, false otherwise.
+ **/
+ isWithinFullScreenElement(fullScreenElement, domElement) {
+ /**
+ * Traverses down iframes until it find a non-iframe full screen DOM element.
+ * @param fullScreenIframe
+ * Target iframe to begin searching from.
+ * @returns DOM element
+ * The full screen DOM element contained within the iframe (could be inner iframe), or the original iframe if no inner DOM element is found.
+ **/
+ let getTrueFullScreenElement = fullScreenIframe => {
+ if (
+ typeof fullScreenIframe.contentDocument !== "undefined" &&
+ fullScreenIframe.contentDocument.mozFullScreenElement
+ ) {
+ return getTrueFullScreenElement(
+ fullScreenIframe.contentDocument.mozFullScreenElement
+ );
+ }
+ return fullScreenIframe;
+ };
+
+ if (fullScreenElement.tagName === "IFRAME") {
+ fullScreenElement = getTrueFullScreenElement(fullScreenElement);
+ }
+
+ if (fullScreenElement.contains(domElement)) {
+ return true;
+ }
+ let parentIframe = domElement.ownerGlobal.frameElement;
+ if (parentIframe) {
+ return this.isWithinFullScreenElement(fullScreenElement, parentIframe);
+ }
+ return false;
+ }
+
+ /**
+ * The PluginCrashed event handler. The target of the event is the
+ * document that GMP is being used in.
+ */
+ async onPluginCrashed(aEvent) {
+ if (!this.contentWindow.PluginCrashedEvent.isInstance(aEvent)) {
+ return;
+ }
+
+ let { target, gmpPlugin, pluginID } = aEvent;
+ let fullScreenElement =
+ this.contentWindow.top.document.mozFullScreenElement;
+ if (fullScreenElement) {
+ if (this.isWithinFullScreenElement(fullScreenElement, target)) {
+ this.contentWindow.top.document.mozCancelFullScreen();
+ }
+ }
+
+ if (!gmpPlugin || !target.document) {
+ // TODO: Throw exception? How did we get here?
+ return;
+ }
+
+ this.sendAsyncMessage("PluginContent:ShowPluginCrashedNotification", {
+ pluginCrashID: { pluginID },
+ });
+ }
+}