1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 * A module that enables async flushes. Updates from frame scripts are
7 * throttled to be sent only once per second. If an action wants a tab's latest
8 * state without waiting for a second then it can request an async flush and
9 * wait until the frame scripts reported back. At this point the parent has the
10 * latest data and the action can continue.
12 export var TabStateFlusher = Object.freeze({
14 * Requests an async flush for the given browser. Returns a promise that will
15 * resolve when we heard back from the content process and the parent has
16 * all the latest data.
19 return TabStateFlusherInternal.flush(browser);
23 * Requests an async flush for all browsers of a given window. Returns a Promise
24 * that will resolve when we've heard back from all browsers.
27 return TabStateFlusherInternal.flushWindow(window);
31 * Resolves all active flush requests for a given browser. This should be
32 * used when the content process crashed or the final update message was
33 * seen. In those cases we can't guarantee to ever hear back from the frame
34 * script so we just resolve all requests instead of discarding them.
36 * @param browser (<xul:browser>)
37 * The browser for which all flushes are being resolved.
38 * @param success (bool, optional)
39 * Whether or not the flushes succeeded.
40 * @param message (string, optional)
41 * An error message that will be sent to the Console in the
42 * event that the flushes failed.
44 resolveAll(browser, success = true, message = "") {
45 TabStateFlusherInternal.resolveAll(browser, success, message);
49 var TabStateFlusherInternal = {
50 // A map storing all active requests per browser. A request is a
51 // triple of a map containing all flush requests, a promise that
52 // resolve when a request for a browser is canceled, and the
53 // function to call to cancel a reqeust.
54 _requests: new WeakMap(),
57 entry.cancelPromise = new Promise(resolve => {
58 entry.cancel = resolve;
60 TabStateFlusherInternal.initEntry(entry);
68 * Requests an async flush for the given browser. Returns a promise that will
69 * resolve when we heard back from the content process and the parent has
70 * all the latest data.
73 let nativePromise = Promise.resolve();
74 if (browser && browser.frameLoader) {
76 Request native listener to flush the tabState.
77 Resolves when flush is complete.
79 nativePromise = browser.frameLoader.requestTabStateFlush();
82 // Retrieve active requests for given browser.
83 let permanentKey = browser.permanentKey;
84 let request = this._requests.get(permanentKey);
86 // If we don't have any requests for this browser, create a new
88 request = this.initEntry({});
89 this._requests.set(permanentKey, request);
92 // It's fine to resolve the request immediately after the native promise
93 // resolves, since SessionStore will have processed all updates from this
94 // browser by that point.
95 return Promise.race([nativePromise, request.cancelPromise]);
99 * Requests an async flush for all non-lazy browsers of a given window.
100 * Returns a Promise that will resolve when we've heard back from all browsers.
102 flushWindow(window) {
104 for (let browser of window.gBrowser.browsers) {
105 if (window.gBrowser.getTabForBrowser(browser).linkedPanel) {
106 promises.push(this.flush(browser));
109 return Promise.all(promises);
113 * Resolves all active flush requests for a given browser. This should be
114 * used when the content process crashed or the final update message was
115 * seen. In those cases we can't guarantee to ever hear back from the frame
116 * script so we just resolve all requests instead of discarding them.
118 * @param browser (<xul:browser>)
119 * The browser for which all flushes are being resolved.
120 * @param success (bool, optional)
121 * Whether or not the flushes succeeded.
122 * @param message (string, optional)
123 * An error message that will be sent to the Console in the
124 * event that the flushes failed.
126 resolveAll(browser, success = true, message = "") {
127 // Nothing to do if there are no pending flushes for the given browser.
128 if (!this._requests.has(browser.permanentKey)) {
132 // Retrieve the cancel function for a given browser.
133 let { cancel } = this._requests.get(browser.permanentKey);
136 console.error("Failed to flush browser: ", message);
139 // Resolve all requests.