Bug 1336904 - Add timeouts for Safe Browsing updates r=francois
These timeouts will ensure that we don't block the Safe Browsing update thread for too long when we encounter slow or bad network conditions. MozReview-Commit-ID: AJfR193cTf8
This commit is contained in:
@@ -25,9 +25,20 @@
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIURLFormatter.h"
|
||||
#include "Classifier.h"
|
||||
#include "SBTelemetryUtils.h"
|
||||
|
||||
using namespace mozilla::safebrowsing;
|
||||
|
||||
#define DEFAULT_RESPONSE_TIMEOUT 5 * 1000
|
||||
#define DEFAULT_TIMEOUT_MS 60 * 1000
|
||||
static_assert(DEFAULT_TIMEOUT_MS > DEFAULT_RESPONSE_TIMEOUT,
|
||||
"General timeout must be greater than reponse timeout");
|
||||
|
||||
static const char* gQuitApplicationMessage = "quit-application";
|
||||
|
||||
static uint32_t sResponseTimeoutMs = DEFAULT_RESPONSE_TIMEOUT;
|
||||
static uint32_t sTimeoutMs = DEFAULT_TIMEOUT_MS;
|
||||
|
||||
// Limit the list file size to 32mb
|
||||
const uint32_t MAX_FILE_SIZE = (32 * 1024 * 1024);
|
||||
|
||||
@@ -188,9 +199,44 @@ nsUrlClassifierStreamUpdater::FetchUpdate(nsIURI *aUpdateUrl,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mTelemetryClockStart = PR_IntervalNow();
|
||||
|
||||
mStreamTable = aStreamTable;
|
||||
|
||||
static bool preferencesInitialized = false;
|
||||
|
||||
if (!preferencesInitialized) {
|
||||
mozilla::Preferences::AddUintVarCache(&sTimeoutMs,
|
||||
"urlclassifier.update.timeout_ms",
|
||||
DEFAULT_TIMEOUT_MS);
|
||||
mozilla::Preferences::AddUintVarCache(&sResponseTimeoutMs,
|
||||
"urlclassifier.update.response_timeout_ms",
|
||||
DEFAULT_RESPONSE_TIMEOUT);
|
||||
preferencesInitialized = true;
|
||||
}
|
||||
|
||||
if (sResponseTimeoutMs > sTimeoutMs) {
|
||||
NS_WARNING("Safe Browsing response timeout is greater than the general "
|
||||
"timeout. Disabling these update timeouts.");
|
||||
return NS_OK;
|
||||
}
|
||||
mResponseTimeoutTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = mResponseTimeoutTimer->InitWithCallback(this,
|
||||
sResponseTimeoutMs,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
mTimeoutTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (sTimeoutMs < DEFAULT_TIMEOUT_MS) {
|
||||
LOG(("Download update timeout %d ms (< %d ms) would be too small",
|
||||
sTimeoutMs, DEFAULT_TIMEOUT_MS));
|
||||
}
|
||||
rv = mTimeoutTimer->InitWithCallback(this,
|
||||
sTimeoutMs,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -698,6 +744,11 @@ nsUrlClassifierStreamUpdater::OnStartRequest(nsIRequest *request,
|
||||
|
||||
}
|
||||
|
||||
if (mResponseTimeoutTimer) {
|
||||
mResponseTimeoutTimer->Cancel();
|
||||
mResponseTimeoutTimer = nullptr;
|
||||
}
|
||||
|
||||
uint8_t netErrCode = NS_FAILED(status) ? NetworkErrorToBucket(status) : 0;
|
||||
mozilla::Telemetry::Accumulate(
|
||||
mozilla::Telemetry::URLCLASSIFIER_UPDATE_REMOTE_NETWORK_ERROR,
|
||||
@@ -803,6 +854,21 @@ nsUrlClassifierStreamUpdater::OnStopRequest(nsIRequest *request, nsISupports* co
|
||||
rv = mDBService->FinishUpdate();
|
||||
}
|
||||
|
||||
if (mResponseTimeoutTimer) {
|
||||
mResponseTimeoutTimer->Cancel();
|
||||
mResponseTimeoutTimer = nullptr;
|
||||
}
|
||||
|
||||
// mResponseTimeoutTimer may be cleared in OnStartRequest, so we check mTimeoutTimer
|
||||
// to see whether the update was has timed out
|
||||
if (mTimeoutTimer) {
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::URLCLASSIFIER_UPDATE_TIMEOUT,
|
||||
mTelemetryProvider,
|
||||
static_cast<uint8_t>(eNoTimeout));
|
||||
mTimeoutTimer->Cancel();
|
||||
mTimeoutTimer = nullptr;
|
||||
}
|
||||
|
||||
mTelemetryProvider.Truncate();
|
||||
mTelemetryClockStart = 0;
|
||||
mChannel = nullptr;
|
||||
@@ -840,6 +906,15 @@ nsUrlClassifierStreamUpdater::Observe(nsISupports *aSubject, const char *aTopic,
|
||||
mFetchNextRequestTimer->Cancel();
|
||||
mFetchNextRequestTimer = nullptr;
|
||||
}
|
||||
if (mResponseTimeoutTimer) {
|
||||
mResponseTimeoutTimer->Cancel();
|
||||
mResponseTimeoutTimer = nullptr;
|
||||
}
|
||||
if (mTimeoutTimer) {
|
||||
mTimeoutTimer->Cancel();
|
||||
mTimeoutTimer = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -874,6 +949,47 @@ nsUrlClassifierStreamUpdater::Notify(nsITimer *timer)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool updateFailed = false;
|
||||
if (timer == mResponseTimeoutTimer) {
|
||||
mResponseTimeoutTimer = nullptr;
|
||||
if (mTimeoutTimer) {
|
||||
mTimeoutTimer->Cancel();
|
||||
mTimeoutTimer = nullptr;
|
||||
}
|
||||
mDownloadError = true; // Trigger backoff
|
||||
updateFailed = true;
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::URLCLASSIFIER_UPDATE_TIMEOUT,
|
||||
mTelemetryProvider,
|
||||
static_cast<uint8_t>(eResponseTimeout));
|
||||
}
|
||||
|
||||
if (timer == mTimeoutTimer) {
|
||||
mTimeoutTimer = nullptr;
|
||||
// No backoff since the connection may just be temporarily slow.
|
||||
updateFailed = true;
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::URLCLASSIFIER_UPDATE_TIMEOUT,
|
||||
mTelemetryProvider,
|
||||
static_cast<uint8_t>(eDownloadTimeout));
|
||||
}
|
||||
|
||||
if (updateFailed) {
|
||||
// Cancelling the channel will trigger OnStopRequest.
|
||||
mozilla::Unused << mChannel->Cancel(NS_ERROR_ABORT);
|
||||
mChannel = nullptr;
|
||||
mTelemetryClockStart = 0;
|
||||
|
||||
if (mFetchIndirectUpdatesTimer) {
|
||||
mFetchIndirectUpdatesTimer->Cancel();
|
||||
mFetchIndirectUpdatesTimer = nullptr;
|
||||
}
|
||||
if (mFetchNextRequestTimer) {
|
||||
mFetchNextRequestTimer->Cancel();
|
||||
mFetchNextRequestTimer = nullptr;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT_UNREACHABLE("A timer is fired from nowhere.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user