forked from mirrors/gecko-dev
		
	 c9f1c242db
			
		
	
	
		c9f1c242db
		
	
	
	
	
		
			
			They'll always resolve, but might receive a negative success state and a message. We're doing this so that we can maintain a Set of in-flight flushes that we can call Promise.all on (which will fast-fail if any Promise rejects, or will just never resolve if one or more of the Promises never resolve). --HG-- extra : commitid : AkIM83IZCxK extra : rebase_source : 4fb8eb059589299c87fcbd3c4e519a81a8b93def
		
			
				
	
	
		
			184 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			184 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* 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/. */
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| this.EXPORTED_SYMBOLS = ["TabStateFlusher"];
 | |
| 
 | |
| const Cu = Components.utils;
 | |
| 
 | |
| Cu.import("resource://gre/modules/Promise.jsm", this);
 | |
| 
 | |
| /**
 | |
|  * A module that enables async flushes. Updates from frame scripts are
 | |
|  * throttled to be sent only once per second. If an action wants a tab's latest
 | |
|  * state without waiting for a second then it can request an async flush and
 | |
|  * wait until the frame scripts reported back. At this point the parent has the
 | |
|  * latest data and the action can continue.
 | |
|  */
 | |
| this.TabStateFlusher = Object.freeze({
 | |
|   /**
 | |
|    * Requests an async flush for the given browser. Returns a promise that will
 | |
|    * resolve when we heard back from the content process and the parent has
 | |
|    * all the latest data.
 | |
|    */
 | |
|   flush(browser) {
 | |
|     return TabStateFlusherInternal.flush(browser);
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Requests an async flush for all browsers of a given window. Returns a Promise
 | |
|    * that will resolve when we've heard back from all browsers.
 | |
|    */
 | |
|   flushWindow(window) {
 | |
|     return TabStateFlusherInternal.flushWindow(window);
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Resolves the flush request with the given flush ID.
 | |
|    *
 | |
|    * @param browser (<xul:browser>)
 | |
|    *        The browser for which the flush is being resolved.
 | |
|    * @param flushID (int)
 | |
|    *        The ID of the flush that was sent to the browser.
 | |
|    * @param success (bool, optional)
 | |
|    *        Whether or not the flush succeeded.
 | |
|    * @param message (string, optional)
 | |
|    *        An error message that will be sent to the Console in the
 | |
|    *        event that a flush failed.
 | |
|    */
 | |
|   resolve(browser, flushID, success=true, message="") {
 | |
|     TabStateFlusherInternal.resolve(browser, flushID, success, message);
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Resolves all active flush requests for a given browser. This should be
 | |
|    * used when the content process crashed or the final update message was
 | |
|    * seen. In those cases we can't guarantee to ever hear back from the frame
 | |
|    * script so we just resolve all requests instead of discarding them.
 | |
|    *
 | |
|    * @param browser (<xul:browser>)
 | |
|    *        The browser for which all flushes are being resolved.
 | |
|    * @param success (bool, optional)
 | |
|    *        Whether or not the flushes succeeded.
 | |
|    * @param message (string, optional)
 | |
|    *        An error message that will be sent to the Console in the
 | |
|    *        event that the flushes failed.
 | |
|    */
 | |
|   resolveAll(browser, success=true, message="") {
 | |
|     TabStateFlusherInternal.resolveAll(browser, success, message);
 | |
|   }
 | |
| });
 | |
| 
 | |
| var TabStateFlusherInternal = {
 | |
|   // Stores the last request ID.
 | |
|   _lastRequestID: 0,
 | |
| 
 | |
|   // A map storing all active requests per browser.
 | |
|   _requests: new WeakMap(),
 | |
| 
 | |
|   /**
 | |
|    * Requests an async flush for the given browser. Returns a promise that will
 | |
|    * resolve when we heard back from the content process and the parent has
 | |
|    * all the latest data.
 | |
|    */
 | |
|   flush(browser) {
 | |
|     let id = ++this._lastRequestID;
 | |
|     let mm = browser.messageManager;
 | |
|     mm.sendAsyncMessage("SessionStore:flush", {id});
 | |
| 
 | |
|     // Retrieve active requests for given browser.
 | |
|     let permanentKey = browser.permanentKey;
 | |
|     let perBrowserRequests = this._requests.get(permanentKey) || new Map();
 | |
| 
 | |
|     return new Promise(resolve => {
 | |
|       // Store resolve() so that we can resolve the promise later.
 | |
|       perBrowserRequests.set(id, resolve);
 | |
| 
 | |
|       // Update the flush requests stored per browser.
 | |
|       this._requests.set(permanentKey, perBrowserRequests);
 | |
|     });
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Requests an async flush for all browsers of a given window. Returns a Promise
 | |
|    * that will resolve when we've heard back from all browsers.
 | |
|    */
 | |
|   flushWindow(window) {
 | |
|     let browsers = window.gBrowser.browsers;
 | |
|     let promises = browsers.map((browser) => this.flush(browser));
 | |
|     return Promise.all(promises);
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Resolves the flush request with the given flush ID.
 | |
|    *
 | |
|    * @param browser (<xul:browser>)
 | |
|    *        The browser for which the flush is being resolved.
 | |
|    * @param flushID (int)
 | |
|    *        The ID of the flush that was sent to the browser.
 | |
|    * @param success (bool, optional)
 | |
|    *        Whether or not the flush succeeded.
 | |
|    * @param message (string, optional)
 | |
|    *        An error message that will be sent to the Console in the
 | |
|    *        event that a flush failed.
 | |
|    */
 | |
|   resolve(browser, flushID, success=true, message="") {
 | |
|     // Nothing to do if there are no pending flushes for the given browser.
 | |
|     if (!this._requests.has(browser.permanentKey)) {
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     // Retrieve active requests for given browser.
 | |
|     let perBrowserRequests = this._requests.get(browser.permanentKey);
 | |
|     if (!perBrowserRequests.has(flushID)) {
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     if (!success) {
 | |
|       Cu.reportError("Failed to flush browser: " + message);
 | |
|     }
 | |
| 
 | |
|     // Resolve the request with the given id.
 | |
|     let resolve = perBrowserRequests.get(flushID);
 | |
|     perBrowserRequests.delete(flushID);
 | |
|     resolve(success);
 | |
|   },
 | |
| 
 | |
|   /**
 | |
|    * Resolves all active flush requests for a given browser. This should be
 | |
|    * used when the content process crashed or the final update message was
 | |
|    * seen. In those cases we can't guarantee to ever hear back from the frame
 | |
|    * script so we just resolve all requests instead of discarding them.
 | |
|    *
 | |
|    * @param browser (<xul:browser>)
 | |
|    *        The browser for which all flushes are being resolved.
 | |
|    * @param success (bool, optional)
 | |
|    *        Whether or not the flushes succeeded.
 | |
|    * @param message (string, optional)
 | |
|    *        An error message that will be sent to the Console in the
 | |
|    *        event that the flushes failed.
 | |
|    */
 | |
|   resolveAll(browser, success=true, message="") {
 | |
|     // Nothing to do if there are no pending flushes for the given browser.
 | |
|     if (!this._requests.has(browser.permanentKey)) {
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     // Retrieve active requests for given browser.
 | |
|     let perBrowserRequests = this._requests.get(browser.permanentKey);
 | |
| 
 | |
|     if (!success) {
 | |
|       Cu.reportError("Failed to flush browser: " + message);
 | |
|     }
 | |
| 
 | |
|     // Resolve all requests.
 | |
|     for (let resolve of perBrowserRequests.values()) {
 | |
|       resolve(success);
 | |
|     }
 | |
| 
 | |
|     // Clear active requests.
 | |
|     perBrowserRequests.clear();
 | |
|   }
 | |
| };
 |