Bug 1421500 - Disable back-off for SafeBrowsing testcases not testing back-off. r?francois
After this patch landed, we will have 3 cases:
1. For providers are not "test", for example, google, google4, mozilla ... etc
backoff CANNOT be disabled.
2. For "test" provider, if preference "browser.safebrowsing.provider.test.disableBackoff" is ON
backoff is disabled.
3. For "test" provider, if preference "browser.safebrowsing.provider.test.disableBackoff" is Off
backoff is NOT disabled.
So if your testcase will use listmanager or hashcompleter, you should try to use "test" provider
if possible, otherwise testcase may encounter intermittent failure due to backoff.
MozReview-Commit-ID: 3BDxs0ARyQM
--- a/toolkit/components/url-classifier/nsUrlClassifierHashCompleter.js
+++ b/toolkit/components/url-classifier/nsUrlClassifierHashCompleter.js
@@ -223,17 +223,18 @@ HashCompleter.prototype = {
// Initialize request backoffs separately, since requests are deleted
// after they are dispatched.
var jslib = Cc["@mozilla.org/url-classifier/jslib;1"]
.getService().wrappedJSObject;
// Using the V4 backoff algorithm for both V2 and V4. See bug 1273398.
this._backoffs[aGethashUrl] = new jslib.RequestBackoffV4(
10 /* keep track of max requests */,
- 0 /* don't throttle on successful requests per time period */);
+ 0 /* don't throttle on successful requests per time period */,
+ gUrlUtil.getProvider(aTableName) /* used by testcase */);
}
if (!this._nextGethashTimeMs[aGethashUrl]) {
this._nextGethashTimeMs[aGethashUrl] = 0;
}
// Start off this request. Without dispatching to a thread, every call to
// complete makes an individual HTTP request.
--- a/toolkit/components/url-classifier/nsUrlClassifierLib.js
+++ b/toolkit/components/url-classifier/nsUrlClassifierLib.js
@@ -3,20 +3,23 @@
* 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 Cc = Components.classes;
const Ci = Components.interfaces;
+const Cu = Components.utils;
const G_GDEBUG = false;
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.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.
*
@@ -78,31 +81,42 @@ this.HTTP_TEMPORARY_REDIRECT = 307;
* 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) {
+ 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;
@@ -170,28 +184,30 @@ RequestBackoff.prototype.isErrorStatus =
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) {
+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 */);
+ 1000 /* tolerance of 1 sec */,
+ provider /* provider name */);
}
// Expose this whole component.
var lib = this;
function UrlClassifierLib() {
this.wrappedJSObject = lib;
}
--- a/toolkit/components/url-classifier/nsUrlClassifierListManager.js
+++ b/toolkit/components/url-classifier/nsUrlClassifierListManager.js
@@ -96,17 +96,18 @@ PROT_ListManager.prototype.registerTable
// Keep track of all of our update URLs.
if (!this.needsUpdate_[updateUrl]) {
this.needsUpdate_[updateUrl] = {};
// Using the V4 backoff algorithm for both V2 and V4. See bug 1273398.
this.requestBackoffs_[updateUrl] = new RequestBackoffV4(
4 /* num requests */,
- 60 * 60 * 1000 /* request time, 60 min */);
+ 60 * 60 * 1000 /* request time, 60 min */,
+ providerName /* used by testcase */);
}
this.needsUpdate_[updateUrl][tableName] = false;
return true;
};
/**
* Unregister a table table from list
--- a/toolkit/components/url-classifier/tests/unit/head_urlclassifier.js
+++ b/toolkit/components/url-classifier/tests/unit/head_urlclassifier.js
@@ -21,16 +21,17 @@ Cc["@mozilla.org/psm;1"].getService(Ci.n
// Disable hashcompleter noise for tests
Services.prefs.setIntPref("urlclassifier.gethashnoise", 0);
// Enable malware/phishing checking for tests
Services.prefs.setBoolPref("browser.safebrowsing.malware.enabled", true);
Services.prefs.setBoolPref("browser.safebrowsing.blockedURIs.enabled", true);
Services.prefs.setBoolPref("browser.safebrowsing.phishing.enabled", true);
+Services.prefs.setBoolPref("browser.safebrowsing.provider.test.disableBackoff", true);
// Enable all completions for tests
Services.prefs.setCharPref("urlclassifier.disallow_completions", "");
// Hash completion timeout
Services.prefs.setIntPref("urlclassifier.gethash.timeout_ms", 5000);
function delFile(name) {
--- a/toolkit/components/url-classifier/tests/unit/test_hashcompleter.js
+++ b/toolkit/components/url-classifier/tests/unit/test_hashcompleter.js
@@ -235,16 +235,18 @@ var completer = Cc["@mozilla.org/url-cla
var gethashUrl;
// Expected highest completion set for which the server sends a response.
var expectedMaxServerCompletionSet = 0;
var maxServerCompletionSet = 0;
function run_test() {
+ // This test case exercises the backoff functionality so we can't leave it disabled.
+ Services.prefs.setBoolPref("browser.safebrowsing.provider.test.disableBackoff", false);
// Generate a random completion set that return successful responses.
completionSets.push(getRandomCompletionSet(false));
// We backoff after receiving an error, so requests shouldn't reach the
// server after that.
expectedMaxServerCompletionSet = completionSets.length;
// Generate some completion sets that return 503s.
for (let j = 0; j < 10; ++j) {
completionSets.push(getRandomCompletionSet(true));
@@ -388,13 +390,15 @@ callback.prototype = {
if (currentCompletionSet < completionSets.length &&
finishedCompletions == completionSets[currentCompletionSet].length) {
runNextCompletion();
}
},
};
function finish() {
+ Services.prefs.clearUserPref("browser.safebrowsing.provider.test.disableBackoff");
+
do_check_eq(expectedMaxServerCompletionSet, maxServerCompletionSet);
server.stop(function() {
do_test_finished();
});
}