Bug 1523562 [wpt PR 14799] - [Animation Worklet] Upstream animation worklet inside...
[gecko.git] / toolkit / actors / UAWidgetsChild.jsm
blob5ce5f1a9405da69782412b6b859d3c5a5896275a
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/. */
5 "use strict";
7 var EXPORTED_SYMBOLS = ["UAWidgetsChild"];
9 const {ActorChild} = ChromeUtils.import("resource://gre/modules/ActorChild.jsm");
10 const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
12 class UAWidgetsChild extends ActorChild {
13   constructor(dispatcher) {
14     super(dispatcher);
16     this.widgets = new WeakMap();
17   }
19   handleEvent(aEvent) {
20     switch (aEvent.type) {
21       case "UAWidgetSetupOrChange":
22         this.setupOrNotifyWidget(aEvent.target);
23         break;
24       case "UAWidgetTeardown":
25         this.teardownWidget(aEvent.target);
26         break;
27     }
29     // In case we are a nested frame, prevent the message manager of the
30     // parent frame from receving the event.
31     aEvent.stopPropagation();
32   }
34   setupOrNotifyWidget(aElement) {
35     let widget = this.widgets.get(aElement);
36     if (!widget) {
37       this.setupWidget(aElement);
38       return;
39     }
40     if (typeof widget.wrappedJSObject.onchange == "function") {
41       try {
42         widget.wrappedJSObject.onchange();
43       } catch (ex) {
44         Cu.reportError(ex);
45       }
46     }
47   }
49   setupWidget(aElement) {
50     let uri;
51     let widgetName;
52     switch (aElement.localName) {
53       case "video":
54       case "audio":
55         uri = "chrome://global/content/elements/videocontrols.js";
56         widgetName = "VideoControlsWidget";
57         break;
58       case "input":
59         uri = "chrome://global/content/elements/datetimebox.js";
60         widgetName = "DateTimeBoxWidget";
61         break;
62       case "embed":
63       case "object":
64         uri = "chrome://global/content/elements/pluginProblem.js";
65         widgetName = "PluginProblemWidget";
66         break;
67       case "marquee":
68         uri = "chrome://global/content/elements/marquee.js";
69         widgetName = "MarqueeWidget";
70         break;
71     }
73     if (!uri || !widgetName) {
74       Cu.reportError("Getting a UAWidgetSetupOrChange event on undefined element.");
75       return;
76     }
78     let shadowRoot = aElement.openOrClosedShadowRoot;
79     if (!shadowRoot) {
80       Cu.reportError("Getting a UAWidgetSetupOrChange event without the Shadow Root.");
81       return;
82     }
84     let isSystemPrincipal = aElement.nodePrincipal.isSystemPrincipal;
85     let sandbox = isSystemPrincipal ?
86       Object.create(null) : Cu.getUAWidgetScope(aElement.nodePrincipal);
88     if (!sandbox[widgetName]) {
89       Services.scriptloader.loadSubScript(uri, sandbox);
90     }
92     let widget = new sandbox[widgetName](shadowRoot);
93     this.widgets.set(aElement, widget);
94     try {
95       if (!isSystemPrincipal) {
96         widget.wrappedJSObject.onsetup();
97       } else {
98         widget.onsetup();
99       }
100     } catch (ex) {
101       Cu.reportError(ex);
102     }
103   }
105   teardownWidget(aElement) {
106     let widget = this.widgets.get(aElement);
107     if (!widget) {
108       return;
109     }
110     if (typeof widget.wrappedJSObject.destructor == "function") {
111       try {
112         widget.wrappedJSObject.destructor();
113       } catch (ex) {
114         Cu.reportError(ex);
115       }
116     }
117     this.widgets.delete(aElement);
118   }