forked from mirrors/gecko-dev
		
	 e930b89c34
			
		
	
	
		e930b89c34
		
	
	
	
	
		
			
			***
Bug 1514594: Part 3a - Change ChromeUtils.import to return an exports object; not pollute global. r=mccr8
This changes the behavior of ChromeUtils.import() to return an exports object,
rather than a module global, in all cases except when `null` is passed as a
second argument, and changes the default behavior not to pollute the global
scope with the module's exports. Thus, the following code written for the old
model:
  ChromeUtils.import("resource://gre/modules/Services.jsm");
is approximately the same as the following, in the new model:
  var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
Since the two behaviors are mutually incompatible, this patch will land with a
scripted rewrite to update all existing callers to use the new model rather
than the old.
***
Bug 1514594: Part 3b - Mass rewrite all JS code to use the new ChromeUtils.import API. rs=Gijs
This was done using the followng script:
https://bitbucket.org/kmaglione/m-c-rewrites/src/tip/processors/cu-import-exports.jsm
***
Bug 1514594: Part 3c - Update ESLint plugin for ChromeUtils.import API changes. r=Standard8
Differential Revision: https://phabricator.services.mozilla.com/D16747
***
Bug 1514594: Part 3d - Remove/fix hundreds of duplicate imports from sync tests. r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D16748
***
Bug 1514594: Part 3e - Remove no-op ChromeUtils.import() calls. r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D16749
***
Bug 1514594: Part 3f.1 - Cleanup various test corner cases after mass rewrite. r=Gijs
***
Bug 1514594: Part 3f.2 - Cleanup various non-test corner cases after mass rewrite. r=Gijs
Differential Revision: https://phabricator.services.mozilla.com/D16750
--HG--
extra : rebase_source : 359574ee3064c90f33bf36c2ebe3159a24cc8895
extra : histedit_source : b93c8f42808b1599f9122d7842d2c0b3e656a594%2C64a3a4e3359dc889e2ab2b49461bab9e27fc10a7
		
	
			
		
			
				
	
	
		
			214 lines
		
	
	
	
		
			7.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			214 lines
		
	
	
	
		
			7.5 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/. */
 | |
| 
 | |
| // We wastefully reload the same JS files across components.  This puts all
 | |
| // the common JS files used by safebrowsing and url-classifier into a
 | |
| // single component.
 | |
| 
 | |
| const G_GDEBUG = false;
 | |
| 
 | |
| const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 | |
| const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 | |
| 
 | |
| const PREF_DISABLE_TEST_BACKOFF = "browser.safebrowsing.provider.test.disableBackoff";
 | |
| /**
 | |
|  * Partially applies a function to a particular "this object" and zero or
 | |
|  * more arguments. The result is a new function with some arguments of the first
 | |
|  * function pre-filled and the value of |this| "pre-specified".
 | |
|  *
 | |
|  * Remaining arguments specified at call-time are appended to the pre-
 | |
|  * specified ones.
 | |
|  *
 | |
|  * Usage:
 | |
|  * var barMethBound = BindToObject(myFunction, myObj, "arg1", "arg2");
 | |
|  * barMethBound("arg3", "arg4");
 | |
|  *
 | |
|  * @param fn {string} Reference to the function to be bound
 | |
|  *
 | |
|  * @param self {object} Specifies the object which |this| should point to
 | |
|  * when the function is run. If the value is null or undefined, it will default
 | |
|  * to the global object.
 | |
|  *
 | |
|  * @returns {function} A partially-applied form of the speficied function.
 | |
|  */
 | |
| this.BindToObject = function BindToObject(fn, self, opt_args) {
 | |
|   var boundargs = fn.boundArgs_ || [];
 | |
|   boundargs = boundargs.concat(Array.slice(arguments, 2, arguments.length));
 | |
| 
 | |
|   if (fn.boundSelf_)
 | |
|     self = fn.boundSelf_;
 | |
|   if (fn.boundFn_)
 | |
|     fn = fn.boundFn_;
 | |
| 
 | |
|   var newfn = function() {
 | |
|     // Combine the static args and the new args into one big array
 | |
|     var args = boundargs.concat(Array.slice(arguments));
 | |
|     return fn.apply(self, args);
 | |
|   };
 | |
| 
 | |
|   newfn.boundArgs_ = boundargs;
 | |
|   newfn.boundSelf_ = self;
 | |
|   newfn.boundFn_ = fn;
 | |
| 
 | |
|   return newfn;
 | |
| };
 | |
| 
 | |
| // This implements logic for stopping requests if the server starts to return
 | |
| // too many errors.  If we get MAX_ERRORS errors in ERROR_PERIOD minutes, we
 | |
| // back off for TIMEOUT_INCREMENT minutes.  If we get another error
 | |
| // immediately after we restart, we double the timeout and add
 | |
| // TIMEOUT_INCREMENT minutes, etc.
 | |
| //
 | |
| // This is similar to the logic used by the search suggestion service.
 | |
| 
 | |
| // HTTP responses that count as an error.  We also include any 5xx response
 | |
| // as an error.
 | |
| this.HTTP_FOUND                 = 302;
 | |
| this.HTTP_SEE_OTHER             = 303;
 | |
| this.HTTP_TEMPORARY_REDIRECT    = 307;
 | |
| 
 | |
| /**
 | |
|  * @param maxErrors Number of times to request before backing off.
 | |
|  * @param retryIncrement Time (ms) for each retry before backing off.
 | |
|  * @param maxRequests Number the number of requests needed to trigger backoff
 | |
|  * @param requestPeriod Number time (ms) in which maxRequests have to occur to
 | |
|  *     trigger the backoff behavior (0 to disable maxRequests)
 | |
|  * @param timeoutIncrement Number time (ms) the starting timeout period
 | |
|  *     we double this time for consecutive errors
 | |
|  * @param maxTimeout Number time (ms) maximum timeout period
 | |
|  * @param tolerance Checking next request tolerance.
 | |
|  */
 | |
| this.RequestBackoff =
 | |
| function RequestBackoff(maxErrors, retryIncrement,
 | |
|                         maxRequests, requestPeriod,
 | |
|                         timeoutIncrement, maxTimeout,
 | |
|                         tolerance, provider = null) {
 | |
|   this.MAX_ERRORS_ = maxErrors;
 | |
|   this.RETRY_INCREMENT_ = retryIncrement;
 | |
|   this.MAX_REQUESTS_ = maxRequests;
 | |
|   this.REQUEST_PERIOD_ = requestPeriod;
 | |
|   this.TIMEOUT_INCREMENT_ = timeoutIncrement;
 | |
|   this.MAX_TIMEOUT_ = maxTimeout;
 | |
|   this.TOLERANCE_ = tolerance;
 | |
| 
 | |
|   // Queue of ints keeping the time of all requests
 | |
|   this.requestTimes_ = [];
 | |
| 
 | |
|   this.numErrors_ = 0;
 | |
|   this.errorTimeout_ = 0;
 | |
|   this.nextRequestTime_ = 0;
 | |
| 
 | |
|   // For test provider, we will disable backoff if preference is set to false.
 | |
|   if (provider === "test") {
 | |
|     this.canMakeRequestDefault = this.canMakeRequest;
 | |
|     this.canMakeRequest = function() {
 | |
|       if (Services.prefs.getBoolPref(PREF_DISABLE_TEST_BACKOFF, true)) {
 | |
|         return true;
 | |
|       }
 | |
|       return this.canMakeRequestDefault();
 | |
|     };
 | |
|   }
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Reset the object for reuse. This deliberately doesn't clear requestTimes_.
 | |
|  */
 | |
| RequestBackoff.prototype.reset = function() {
 | |
|   this.numErrors_ = 0;
 | |
|   this.errorTimeout_ = 0;
 | |
|   this.nextRequestTime_ = 0;
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Check to see if we can make a request.
 | |
|  */
 | |
| RequestBackoff.prototype.canMakeRequest = function() {
 | |
|   var now = Date.now();
 | |
|   // Note that nsITimer delay is approximate: the timer can be fired before the
 | |
|   // requested time has elapsed. So, give it a tolerance
 | |
|   if (now + this.TOLERANCE_ < this.nextRequestTime_) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   return (this.requestTimes_.length < this.MAX_REQUESTS_ ||
 | |
|           (now - this.requestTimes_[0]) > this.REQUEST_PERIOD_);
 | |
| };
 | |
| 
 | |
| RequestBackoff.prototype.noteRequest = function() {
 | |
|   var now = Date.now();
 | |
|   this.requestTimes_.push(now);
 | |
| 
 | |
|   // We only care about keeping track of MAX_REQUESTS
 | |
|   if (this.requestTimes_.length > this.MAX_REQUESTS_)
 | |
|     this.requestTimes_.shift();
 | |
| };
 | |
| 
 | |
| RequestBackoff.prototype.nextRequestDelay = function() {
 | |
|   return Math.max(0, this.nextRequestTime_ - Date.now());
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Notify this object of the last server response.  If it's an error,
 | |
|  */
 | |
| RequestBackoff.prototype.noteServerResponse = function(status) {
 | |
|   if (this.isErrorStatus(status)) {
 | |
|     this.numErrors_++;
 | |
| 
 | |
|     if (this.numErrors_ < this.MAX_ERRORS_)
 | |
|       this.errorTimeout_ = this.RETRY_INCREMENT_;
 | |
|     else if (this.numErrors_ == this.MAX_ERRORS_)
 | |
|       this.errorTimeout_ = this.TIMEOUT_INCREMENT_;
 | |
|     else
 | |
|       this.errorTimeout_ *= 2;
 | |
| 
 | |
|     this.errorTimeout_ = Math.min(this.errorTimeout_, this.MAX_TIMEOUT_);
 | |
|     this.nextRequestTime_ = Date.now() + this.errorTimeout_;
 | |
|   } else {
 | |
|     // Reset error timeout, allow requests to go through.
 | |
|     this.reset();
 | |
|   }
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * We consider 302, 303, 307, 4xx, and 5xx http responses to be errors.
 | |
|  * @param status Number http status
 | |
|  * @return Boolean true if we consider this http status an error
 | |
|  */
 | |
| RequestBackoff.prototype.isErrorStatus = function(status) {
 | |
|   return ((400 <= status && status <= 599) ||
 | |
|           HTTP_FOUND == status ||
 | |
|           HTTP_SEE_OTHER == status ||
 | |
|           HTTP_TEMPORARY_REDIRECT == status);
 | |
| };
 | |
| 
 | |
| // Wrap a general-purpose |RequestBackoff| to a v4-specific one
 | |
| // since both listmanager and hashcompleter would use it.
 | |
| // Note that |maxRequests| and |requestPeriod| is still configurable
 | |
| // to throttle pending requests.
 | |
| function RequestBackoffV4(maxRequests, requestPeriod,
 | |
|                           provider = null) {
 | |
|   let rand = Math.random();
 | |
|   let retryInterval = Math.floor(15 * 60 * 1000 * (rand + 1)); // 15 ~ 30 min.
 | |
|   let backoffInterval = Math.floor(30 * 60 * 1000 * (rand + 1)); // 30 ~ 60 min.
 | |
| 
 | |
|   return new RequestBackoff(2 /* max errors */,
 | |
|                 retryInterval /* retry interval, 15~30 min */,
 | |
|                   maxRequests /* num requests */,
 | |
|                 requestPeriod /* request time, 60 min */,
 | |
|               backoffInterval /* backoff interval, 60 min */,
 | |
|           24 * 60 * 60 * 1000 /* max backoff, 24hr */,
 | |
|                          1000 /* tolerance of 1 sec */,
 | |
|                      provider /* provider name */);
 | |
| }
 | |
| 
 | |
| // Expose this whole component.
 | |
| var lib = this;
 | |
| 
 | |
| function UrlClassifierLib() {
 | |
|   this.wrappedJSObject = lib;
 | |
| }
 | |
| UrlClassifierLib.prototype.classID = Components.ID("{26a4a019-2827-4a89-a85c-5931a678823a}");
 | |
| UrlClassifierLib.prototype.QueryInterface = ChromeUtils.generateQI([]);
 | |
| 
 | |
| this.NSGetFactory = XPCOMUtils.generateNSGetFactory([UrlClassifierLib]);
 |