Bug 1603673 - Signal that we support web manifest processing in Fenix r=snorp,agi...
[gecko.git] / toolkit / actors / PopupBlockingChild.jsm
blobbd17700a4562e07f1113bd31a25ef4d87c1b5616
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 /* eslint no-unused-vars: ["error", {args: "none"}] */
8 var EXPORTED_SYMBOLS = ["PopupBlockingChild"];
10 // The maximum number of popup information we'll send to the parent.
11 const MAX_SENT_POPUPS = 15;
13 const { XPCOMUtils } = ChromeUtils.import(
14   "resource://gre/modules/XPCOMUtils.jsm"
17 class PopupBlockingChild extends JSWindowActorChild {
18   constructor() {
19     super();
20     this.weakDocStates = new WeakMap();
21   }
23   actorCreated() {
24     this.contentWindow.addEventListener("pageshow", this);
25   }
27   willDestroy() {
28     this.contentWindow.removeEventListener("pageshow", this);
29   }
31   /**
32    * Returns the state for the current document referred to via
33    * this.document. If no such state exists, creates it, stores it
34    * and returns it.
35    */
36   get docState() {
37     let state = this.weakDocStates.get(this.document);
38     if (!state) {
39       state = {
40         popupData: [],
41       };
42       this.weakDocStates.set(this.document, state);
43     }
45     return state;
46   }
48   receiveMessage(msg) {
49     switch (msg.name) {
50       case "UnblockPopup": {
51         let i = msg.data.index;
52         let state = this.docState;
53         let popupData = state.popupData[i];
54         if (popupData) {
55           let dwi = popupData.requestingWindow;
57           // If we have a requesting window and the requesting document is
58           // still the current document, open the popup.
59           if (dwi && dwi.document == popupData.requestingDocument) {
60             dwi.open(
61               popupData.popupWindowURISpec,
62               popupData.popupWindowName,
63               popupData.popupWindowFeatures
64             );
65           }
66         }
67         break;
68       }
70       case "GetBlockedPopupList": {
71         let state = this.docState;
72         let length = Math.min(state.popupData.length, MAX_SENT_POPUPS);
74         let result = [];
76         for (let i = 0; i < length; ++i) {
77           let popup = state.popupData[i];
79           let popupWindowURISpec = popup.popupWindowURISpec;
81           if (this.contentWindow.location.href == popupWindowURISpec) {
82             popupWindowURISpec = "<self>";
83           } else {
84             // Limit 500 chars to be sent because the URI will be cropped
85             // by the UI anyway, and data: URIs can be significantly larger.
86             popupWindowURISpec = popupWindowURISpec.substring(0, 500);
87           }
89           result.push({
90             popupWindowURISpec,
91           });
92         }
94         return result;
95       }
96     }
98     return null;
99   }
101   handleEvent(event) {
102     switch (event.type) {
103       case "DOMPopupBlocked":
104         this.onPopupBlocked(event);
105         break;
106       case "pageshow": {
107         this.onPageShow(event);
108         break;
109       }
110     }
111   }
113   onPopupBlocked(event) {
114     if (event.target != this.document) {
115       return;
116     }
118     let state = this.docState;
120     // Avoid spamming the parent process with too many blocked popups.
121     if (state.popupData.length >= PopupBlockingChild.maxReportedPopups) {
122       return;
123     }
125     let popup = {
126       popupWindowURISpec: event.popupWindowURI
127         ? event.popupWindowURI.spec
128         : "about:blank",
129       popupWindowFeatures: event.popupWindowFeatures,
130       popupWindowName: event.popupWindowName,
131       requestingWindow: event.requestingWindow,
132       requestingDocument: event.requestingWindow.document,
133     };
135     state.popupData.push(popup);
136     this.updateBlockedPopups(true);
137   }
139   onPageShow(event) {
140     if (event.target != this.document) {
141       return;
142     }
144     this.updateBlockedPopups(false);
145   }
147   updateBlockedPopups(shouldNotify) {
148     this.sendAsyncMessage("UpdateBlockedPopups", {
149       shouldNotify,
150       count: this.docState.popupData.length,
151     });
152   }
155 XPCOMUtils.defineLazyPreferenceGetter(
156   PopupBlockingChild,
157   "maxReportedPopups",
158   "privacy.popups.maxReported"