--- a/toolkit/components/downloads/ApplicationReputation.cpp
+++ b/toolkit/components/downloads/ApplicationReputation.cpp
@@ -87,23 +87,25 @@ mozilla::LazyLogModule ApplicationReputa
class PendingDBLookup;
// A single use class private to ApplicationReputationService encapsulating an
// nsIApplicationReputationQuery and an nsIApplicationReputationCallback. Once
// created by ApplicationReputationService, it is guaranteed to call mCallback.
// This class is private to ApplicationReputationService.
class PendingLookup final : public nsIStreamListener,
- public nsITimerCallback
+ public nsITimerCallback,
+ public nsIObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSITIMERCALLBACK
+ NS_DECL_NSIOBSERVER
// Constructor and destructor.
PendingLookup(nsIApplicationReputationQuery* aQuery,
nsIApplicationReputationCallback* aCallback);
// Start the lookup. The lookup may have 2 parts: local and remote. In the
// local lookup, PendingDBLookups are created to query the local allow and
// blocklists for various URIs associated with this downloaded file. In the
@@ -365,17 +367,18 @@ PendingDBLookup::HandleEvent(const nsACS
this));
Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_LOCAL, NO_LIST);
}
return mPendingLookup->LookupNext();
}
NS_IMPL_ISUPPORTS(PendingLookup,
nsIStreamListener,
- nsIRequestObserver)
+ nsIRequestObserver,
+ nsIObserver)
PendingLookup::PendingLookup(nsIApplicationReputationQuery* aQuery,
nsIApplicationReputationCallback* aCallback) :
mBlocklistCount(0),
mAllowlistCount(0),
mQuery(aQuery),
mCallback(aCallback)
{
@@ -1317,16 +1320,34 @@ PendingLookup::Notify(nsITimer* aTimer)
MOZ_ASSERT(aTimer == mTimeoutTimer);
Accumulate(mozilla::Telemetry::APPLICATION_REPUTATION_REMOTE_LOOKUP_TIMEOUT,
true);
mChannel->Cancel(NS_ERROR_NET_TIMEOUT);
mTimeoutTimer->Cancel();
return NS_OK;
}
+///////////////////////////////////////////////////////////////////////////////
+// nsIObserver implementation
+NS_IMETHODIMP
+PendingLookup::Observe(nsISupports *aSubject, const char *aTopic,
+ const char16_t *aData)
+{
+ if (!strcmp(aTopic, "quit-application")) {
+ if (mTimeoutTimer) {
+ mTimeoutTimer->Cancel();
+ mTimeoutTimer = nullptr;
+ }
+ if (mChannel) {
+ mChannel->Cancel(NS_ERROR_ABORT);
+ }
+ }
+ return NS_OK;
+}
+
////////////////////////////////////////////////////////////////////////////////
//// nsIStreamListener
static nsresult
AppendSegmentToString(nsIInputStream* inputStream,
void *closure,
const char *rawSegment,
uint32_t toOffset,
uint32_t count,
@@ -1514,10 +1535,18 @@ nsresult ApplicationReputationService::Q
NS_ENSURE_SUCCESS(rv, rv);
// Bail if the URI hasn't been set.
NS_ENSURE_STATE(uri);
// Create a new pending lookup and start the call chain.
RefPtr<PendingLookup> lookup(new PendingLookup(aQuery, aCallback));
NS_ENSURE_STATE(lookup);
+ // Add an observer for shutdown
+ nsCOMPtr<nsIObserverService> observerService =
+ mozilla::services::GetObserverService();
+ if (!observerService) {
+ return NS_ERROR_FAILURE;
+ }
+
+ observerService->AddObserver(lookup, "quit-application", false);
return lookup->StartLookup();
}
--- a/toolkit/components/url-classifier/Classifier.cpp
+++ b/toolkit/components/url-classifier/Classifier.cpp
@@ -331,16 +331,21 @@ Classifier::DeleteTables(nsIFile* aDirec
}
}
NS_ENSURE_SUCCESS_VOID(rv);
}
void
Classifier::AbortUpdateAndReset(const nsCString& aTable)
{
+ // We don't need to reset while shutting down. It will only slow us down.
+ if (nsUrlClassifierDBService::ShutdownHasStarted()) {
+ return;
+ }
+
LOG(("Abort updating table %s.", aTable.get()));
// ResetTables will clear both in-memory & on-disk data.
ResetTables(Clear_All, nsTArray<nsCString> { aTable });
// Remove the backup and delete directory since we are aborting
// from an update.
Unused << RemoveBackupTables();
@@ -929,16 +934,20 @@ Classifier::GetProvider(const nsACString
/*
* This will consume+delete updates from the passed nsTArray.
*/
nsresult
Classifier::UpdateHashStore(nsTArray<TableUpdate*>* aUpdates,
const nsACString& aTable)
{
+ if (nsUrlClassifierDBService::ShutdownHasStarted()) {
+ return NS_ERROR_ABORT;
+ }
+
LOG(("Classifier::UpdateHashStore(%s)", PromiseFlatCString(aTable).get()));
HashStore store(aTable, GetProvider(aTable), mRootStoreDirectory);
if (!CheckValidUpdate(aUpdates, store.TableName())) {
return NS_OK;
}
@@ -1027,16 +1036,19 @@ Classifier::UpdateHashStore(nsTArray<Tab
}
nsresult
Classifier::UpdateTableV4(nsTArray<TableUpdate*>* aUpdates,
const nsACString& aTable)
{
MOZ_ASSERT(!NS_IsMainThread(),
"UpdateTableV4 must be called on the classifier worker thread.");
+ if (nsUrlClassifierDBService::ShutdownHasStarted()) {
+ return NS_ERROR_ABORT;
+ }
LOG(("Classifier::UpdateTableV4(%s)", PromiseFlatCString(aTable).get()));
if (!CheckValidUpdate(aUpdates, aTable)) {
return NS_OK;
}
LookupCacheV4* lookupCache =
--- a/toolkit/components/url-classifier/HashStore.cpp
+++ b/toolkit/components/url-classifier/HashStore.cpp
@@ -34,16 +34,17 @@
#include "nsISeekableStream.h"
#include "nsIStreamConverterService.h"
#include "nsNetUtil.h"
#include "nsCheckSummedOutputStream.h"
#include "prio.h"
#include "mozilla/Logging.h"
#include "zlib.h"
#include "Classifier.h"
+#include "nsUrlClassifierDBService.h"
// Main store for SafeBrowsing protocol data. We store
// known add/sub chunks, prefixes and completions in memory
// during an update, and serialize to disk.
// We do not store the add prefixes, those are retrieved by
// decompressing the PrefixSet cache whenever we need to apply
// an update.
//
@@ -946,16 +947,19 @@ HashStore::WriteSubPrefixes(nsIOutputStr
return NS_OK;
}
nsresult
HashStore::WriteFile()
{
NS_ASSERTION(mInUpdate, "Must be in update to write database.");
+ if (nsUrlClassifierDBService::ShutdownHasStarted()) {
+ return NS_ERROR_ABORT;
+ }
nsCOMPtr<nsIFile> storeFile;
nsresult rv = mStoreDirectory->Clone(getter_AddRefs(storeFile));
NS_ENSURE_SUCCESS(rv, rv);
rv = storeFile->AppendNative(mTableName + NS_LITERAL_CSTRING(".sbstore"));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIOutputStream> out;
--- a/toolkit/components/url-classifier/LookupCache.cpp
+++ b/toolkit/components/url-classifier/LookupCache.cpp
@@ -139,16 +139,20 @@ LookupCache::DumpCache()
LOG(("Caches: %s", str.get()));
}
}
#endif
nsresult
LookupCache::WriteFile()
{
+ if (nsUrlClassifierDBService::ShutdownHasStarted()) {
+ return NS_ERROR_ABORT;
+ }
+
nsCOMPtr<nsIFile> psFile;
nsresult rv = mStoreDirectory->Clone(getter_AddRefs(psFile));
NS_ENSURE_SUCCESS(rv, rv);
rv = psFile->AppendNative(mTableName + NS_LITERAL_CSTRING(PREFIXSET_SUFFIX));
NS_ENSURE_SUCCESS(rv, rv);
rv = StoreToFile(psFile);
--- a/toolkit/components/url-classifier/LookupCacheV4.cpp
+++ b/toolkit/components/url-classifier/LookupCacheV4.cpp
@@ -442,16 +442,19 @@ ReadValue(nsIInputStream* aInputStream,
} // end of unnamed namespace.
////////////////////////////////////////////////////////////////////////
nsresult
LookupCacheV4::WriteMetadata(TableUpdateV4* aTableUpdate)
{
NS_ENSURE_ARG_POINTER(aTableUpdate);
+ if (nsUrlClassifierDBService::ShutdownHasStarted()) {
+ return NS_ERROR_ABORT;
+ }
nsCOMPtr<nsIFile> metaFile;
nsresult rv = mStoreDirectory->Clone(getter_AddRefs(metaFile));
NS_ENSURE_SUCCESS(rv, rv);
rv = metaFile->AppendNative(mTableName + METADATA_SUFFIX);
NS_ENSURE_SUCCESS(rv, rv);
--- a/toolkit/components/url-classifier/ProtocolParser.cpp
+++ b/toolkit/components/url-classifier/ProtocolParser.cpp
@@ -5,16 +5,17 @@
#include "ProtocolParser.h"
#include "LookupCache.h"
#include "nsNetCID.h"
#include "mozilla/Logging.h"
#include "prnetdb.h"
#include "prprf.h"
+#include "nsUrlClassifierDBService.h"
#include "nsUrlClassifierUtils.h"
#include "nsPrintfCString.h"
#include "mozilla/Base64.h"
#include "RiceDeltaDecoder.h"
#include "mozilla/EndianUtils.h"
// MOZ_LOG=UrlClassifierProtocolParser:5
mozilla::LazyLogModule gUrlClassifierProtocolParserLog("UrlClassifierProtocolParser");
@@ -139,16 +140,20 @@ ProtocolParserV2::AppendStream(const nsA
if (NS_FAILED(mUpdateStatus))
return mUpdateStatus;
nsresult rv;
mPending.Append(aData);
bool done = false;
while (!done) {
+ if (nsUrlClassifierDBService::ShutdownHasStarted()) {
+ return NS_ERROR_ABORT;
+ }
+
if (mState == PROTOCOL_STATE_CONTROL) {
rv = ProcessControl(&done);
} else if (mState == PROTOCOL_STATE_CHUNK) {
rv = ProcessChunk(&done);
} else {
NS_ERROR("Unexpected protocol state");
rv = NS_ERROR_FAILURE;
}
--- a/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
@@ -188,16 +188,20 @@ nsUrlClassifierDBServiceWorker::QueueLoo
return NS_OK;
}
nsresult
nsUrlClassifierDBServiceWorker::DoLocalLookup(const nsACString& spec,
const nsACString& tables,
LookupResultArray* results)
{
+ if (gShuttingDownThread) {
+ return NS_ERROR_ABORT;
+ }
+
MOZ_ASSERT(!NS_IsMainThread(), "DoLocalLookup must be on background thread");
if (!results) {
return NS_ERROR_FAILURE;
}
// Bail if we haven't been initialized on the background thread.
if (!mClassifier) {
return NS_ERROR_NOT_AVAILABLE;
}
@@ -303,16 +307,20 @@ nsUrlClassifierDBServiceWorker::DoLookup
c->LookupComplete(completes.forget());
return NS_OK;
}
nsresult
nsUrlClassifierDBServiceWorker::HandlePendingLookups()
{
+ if (gShuttingDownThread) {
+ return NS_ERROR_ABORT;
+ }
+
MutexAutoLock lock(mPendingLookupLock);
while (mPendingLookups.Length() > 0) {
PendingLookup lookup = mPendingLookups[0];
mPendingLookups.RemoveElementAt(0);
{
MutexAutoUnlock unlock(mPendingLookupLock);
DoLookup(lookup.mKey, lookup.mTables, lookup.mCallback);
}
@@ -325,16 +333,20 @@ nsUrlClassifierDBServiceWorker::HandlePe
}
nsresult
nsUrlClassifierDBServiceWorker::AddNoise(const Prefix aPrefix,
const nsCString tableName,
uint32_t aCount,
LookupResultArray& results)
{
+ if (gShuttingDownThread) {
+ return NS_ERROR_ABORT;
+ }
+
if (aCount < 1) {
return NS_OK;
}
PrefixArray noiseEntries;
nsresult rv = mClassifier->ReadNoiseEntries(aPrefix, tableName,
aCount, &noiseEntries);
NS_ENSURE_SUCCESS(rv, rv);
@@ -354,24 +366,29 @@ nsUrlClassifierDBServiceWorker::AddNoise
}
// Lookup a key in the db.
NS_IMETHODIMP
nsUrlClassifierDBServiceWorker::Lookup(nsIPrincipal* aPrincipal,
const nsACString& aTables,
nsIUrlClassifierCallback* c)
{
+ if (gShuttingDownThread) {
+ return NS_ERROR_ABORT;
+ }
+
return HandlePendingLookups();
}
NS_IMETHODIMP
nsUrlClassifierDBServiceWorker::GetTables(nsIUrlClassifierCallback* c)
{
- if (gShuttingDownThread)
+ if (gShuttingDownThread) {
return NS_ERROR_NOT_INITIALIZED;
+ }
nsresult rv = OpenDb();
if (NS_FAILED(rv)) {
NS_ERROR("Unable to open SafeBrowsing database");
return NS_ERROR_FAILURE;
}
NS_ENSURE_SUCCESS(rv, rv);
@@ -435,18 +452,19 @@ nsUrlClassifierDBServiceWorker::BeginUpd
// Called from the stream updater.
NS_IMETHODIMP
nsUrlClassifierDBServiceWorker::BeginStream(const nsACString &table)
{
LOG(("nsUrlClassifierDBServiceWorker::BeginStream"));
MOZ_ASSERT(!NS_IsMainThread(), "Streaming must be on the background thread");
- if (gShuttingDownThread)
+ if (gShuttingDownThread) {
return NS_ERROR_NOT_INITIALIZED;
+ }
NS_ENSURE_STATE(mUpdateObserver);
NS_ENSURE_STATE(!mInStream);
mInStream = true;
NS_ASSERTION(!mProtocolParser, "Should not have a protocol parser.");
@@ -515,18 +533,19 @@ nsUrlClassifierDBServiceWorker::BeginStr
*
* Update() can be fed partial data; It will accumulate data until there is
* enough to act on. Finish() should be called when there will be no more
* data.
*/
NS_IMETHODIMP
nsUrlClassifierDBServiceWorker::UpdateStream(const nsACString& chunk)
{
- if (gShuttingDownThread)
+ if (gShuttingDownThread) {
return NS_ERROR_NOT_INITIALIZED;
+ }
NS_ENSURE_STATE(mInStream);
HandlePendingLookups();
// Feed the chunk to the parser.
return mProtocolParser->AppendStream(chunk);
}
@@ -582,18 +601,20 @@ nsUrlClassifierDBServiceWorker::FinishSt
mProtocolParser = nullptr;
return NS_OK;
}
NS_IMETHODIMP
nsUrlClassifierDBServiceWorker::FinishUpdate()
{
- if (gShuttingDownThread)
+ if (gShuttingDownThread) {
return NS_ERROR_NOT_INITIALIZED;
+ }
+
NS_ENSURE_STATE(mUpdateObserver);
if (NS_SUCCEEDED(mUpdateStatus)) {
mUpdateStatus = ApplyUpdate();
} else {
LOG(("nsUrlClassifierDBServiceWorker::FinishUpdate() Not running "
"ApplyUpdate() since the update has already failed."));
}
@@ -734,16 +755,20 @@ nsUrlClassifierDBServiceWorker::CloseDb(
LOG(("urlclassifier db closed\n"));
return NS_OK;
}
nsresult
nsUrlClassifierDBServiceWorker::CacheCompletions(CacheResultArray *results)
{
+ if (gShuttingDownThread) {
+ return NS_ERROR_ABORT;
+ }
+
LOG(("nsUrlClassifierDBServiceWorker::CacheCompletions [%p]", this));
if (!mClassifier)
return NS_OK;
// Ownership is transferred in to us
nsAutoPtr<CacheResultArray> resultsPtr(results);
if (mLastResults == *resultsPtr) {
@@ -813,16 +838,20 @@ nsUrlClassifierDBServiceWorker::CacheMis
mMissCache.AppendElement(resultsPtr->ElementAt(i));
}
return NS_OK;
}
nsresult
nsUrlClassifierDBServiceWorker::OpenDb()
{
+ if (gShuttingDownThread) {
+ return NS_ERROR_ABORT;
+ }
+
MOZ_ASSERT(!NS_IsMainThread(), "Must initialize DB on background thread");
// Connection already open, don't do anything.
if (mClassifier) {
return NS_OK;
}
nsresult rv;
mCryptoHash = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
@@ -1342,18 +1371,19 @@ nsUrlClassifierDBService::Init()
}
// Add an observer for shutdown
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (!observerService)
return NS_ERROR_FAILURE;
+ // The application is about to quit
+ observerService->AddObserver(this, "quit-application", false);
observerService->AddObserver(this, "profile-before-change", false);
- observerService->AddObserver(this, "xpcom-shutdown-threads", false);
// XXX: Do we *really* need to be able to change all of these at runtime?
// Note: These observers should only be added when everything else above has
// succeeded. Failing to do so can cause long shutdown times in certain
// situations. See Bug 1247798 and Bug 1244803.
Preferences::AddStrongObserver(this, CHECK_MALWARE_PREF);
Preferences::AddStrongObserver(this, CHECK_PHISHING_PREF);
Preferences::AddStrongObserver(this, CHECK_TRACKING_PREF);
@@ -1463,16 +1493,19 @@ nsUrlClassifierDBService::Classify(nsIPr
}
NS_IMETHODIMP
nsUrlClassifierDBService::ClassifyLocalWithTables(nsIURI *aURI,
const nsACString & aTables,
nsACString & aTableResults)
{
MOZ_ASSERT(NS_IsMainThread(), "ClassifyLocalWithTables must be on main thread");
+ if (gShuttingDownThread) {
+ return NS_ERROR_ABORT;
+ }
if (XRE_IsContentProcess()) {
using namespace mozilla::dom;
using namespace mozilla::ipc;
URIParams uri;
SerializeURI(aURI, uri);
nsAutoCString tables(aTables);
nsAutoCString results;
@@ -1793,36 +1826,47 @@ nsUrlClassifierDBService::Observe(nsISup
NS_LITERAL_STRING(DOWNLOAD_ALLOW_TABLE_PREF).Equals(aData) ||
NS_LITERAL_STRING(DISALLOW_COMPLETION_TABLE_PREF).Equals(aData)) {
// Just read everything again.
ReadTablesFromPrefs();
} else if (NS_LITERAL_STRING(CONFIRM_AGE_PREF).Equals(aData)) {
gFreshnessGuarantee = Preferences::GetInt(CONFIRM_AGE_PREF,
CONFIRM_AGE_DEFAULT_SEC);
}
- } else if (!strcmp(aTopic, "profile-before-change") ||
- !strcmp(aTopic, "xpcom-shutdown-threads")) {
+ } else if (!strcmp(aTopic, "quit-application")) {
+ Shutdown();
+ } else if (!strcmp(aTopic, "profile-before-change")) {
+ // Unit test does not receive "quit-application",
+ // need call shutdown in this case
Shutdown();
+ LOG(("joining background thread"));
+ mWorkerProxy = nullptr;
+ nsIThread *backgroundThread = gDbBackgroundThread;
+ gDbBackgroundThread = nullptr;
+ backgroundThread->Shutdown();
+ NS_RELEASE(backgroundThread);
} else {
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
// Join the background thread if it exists.
nsresult
nsUrlClassifierDBService::Shutdown()
{
LOG(("shutting down db service\n"));
MOZ_ASSERT(XRE_IsParentProcess());
- if (!gDbBackgroundThread)
+ if (!gDbBackgroundThread || gShuttingDownThread)
return NS_OK;
+ gShuttingDownThread = true;
+
Telemetry::AutoTimer<Telemetry::URLCLASSIFIER_SHUTDOWN_TIME> timer;
mCompleters.Clear();
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefs) {
prefs->RemoveObserver(CHECK_MALWARE_PREF, this);
prefs->RemoveObserver(CHECK_PHISHING_PREF, this);
@@ -1844,29 +1888,23 @@ nsUrlClassifierDBService::Shutdown()
// First close the db connection.
if (mWorker) {
rv = mWorkerProxy->CancelUpdate();
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to post cancel update event");
rv = mWorkerProxy->CloseDb();
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to post close db event");
}
-
- mWorkerProxy = nullptr;
-
- LOG(("joining background thread"));
-
- gShuttingDownThread = true;
-
- nsIThread *backgroundThread = gDbBackgroundThread;
- gDbBackgroundThread = nullptr;
- backgroundThread->Shutdown();
- NS_RELEASE(backgroundThread);
-
return NS_OK;
}
nsIThread*
nsUrlClassifierDBService::BackgroundThread()
{
return gDbBackgroundThread;
}
+// static
+bool
+nsUrlClassifierDBService::ShutdownHasStarted()
+{
+ return gShuttingDownThread;
+}
--- a/toolkit/components/url-classifier/nsUrlClassifierDBService.h
+++ b/toolkit/components/url-classifier/nsUrlClassifierDBService.h
@@ -75,16 +75,18 @@ public:
bool GetCompleter(const nsACString& tableName,
nsIUrlClassifierHashCompleter** completer);
nsresult CacheCompletions(mozilla::safebrowsing::CacheResultArray *results);
nsresult CacheMisses(mozilla::safebrowsing::PrefixArray *results);
static nsIThread* BackgroundThread();
+ static bool ShutdownHasStarted();
+
private:
// No subclassing
~nsUrlClassifierDBService();
// Disallow copy constructor
nsUrlClassifierDBService(nsUrlClassifierDBService&);
nsresult LookupURI(nsIPrincipal* aPrincipal,
--- a/toolkit/components/url-classifier/nsUrlClassifierHashCompleter.js
+++ b/toolkit/components/url-classifier/nsUrlClassifierHashCompleter.js
@@ -150,20 +150,21 @@ function HashCompleter() {
// avoid creating multiple requests to the same gethash URL.
this._currentRequest = null;
// A map of gethashUrls to HashCompleterRequests that haven't yet begun.
this._pendingRequests = {};
// A map of gethash URLs to RequestBackoff objects.
this._backoffs = {};
- // Whether we have been informed of a shutdown by the xpcom-shutdown event.
+ // Whether we have been informed of a shutdown by the shutdown event.
this._shuttingDown = false;
- Services.obs.addObserver(this, "xpcom-shutdown", true);
+ Services.obs.addObserver(this, "quit-application", false);
+
}
HashCompleter.prototype = {
classID: Components.ID("{9111de73-9322-4bfc-8b65-2b727f3e6ec8}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIUrlClassifierHashCompleter,
Ci.nsIRunnable,
Ci.nsIObserver,
Ci.nsISupportsWeakReference,
@@ -254,32 +255,33 @@ HashCompleter.prototype = {
// Notifies the RequestBackoff of a new request so we can throttle based on
// max requests/time period. This must be called before a channel is opened,
// and finishRequest must be called once the response is received.
noteRequest: function(aGethashUrl) {
return this._backoffs[aGethashUrl].noteRequest();
},
observe: function HC_observe(aSubject, aTopic, aData) {
- if (aTopic == "xpcom-shutdown") {
+ if (aTopic == "quit-application") {
this._shuttingDown = true;
+ Services.obs.removeObserver(this, "quit-application");
}
},
};
function HashCompleterRequest(aCompleter, aGethashUrl) {
// HashCompleter object that created this HashCompleterRequest.
this._completer = aCompleter;
// The internal set of hashes and callbacks that this request corresponds to.
this._requests = [];
// nsIChannel that the hash completion query is transmitted over.
this._channel = null;
// Response body of hash completion. Created in onDataAvailable.
this._response = "";
- // Whether we have been informed of a shutdown by the xpcom-shutdown event.
+ // Whether we have been informed of a shutdown by the quit-application event.
this._shuttingDown = false;
this.gethashUrl = aGethashUrl;
}
HashCompleterRequest.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRequestObserver,
Ci.nsIStreamListener,
Ci.nsIObserver,
Ci.nsISupports]),
@@ -299,17 +301,17 @@ HashCompleterRequest.prototype = {
// begin.
begin: function HCR_begin() {
if (!this._completer.canMakeRequest(this.gethashUrl)) {
log("Can't make request to " + this.gethashUrl + "\n");
this.notifyFailure(Cr.NS_ERROR_ABORT);
return;
}
- Services.obs.addObserver(this, "xpcom-shutdown", false);
+ Services.obs.addObserver(this, "quit-application", false);
try {
this.openChannel();
// Notify the RequestBackoff if opening the channel succeeded. At this
// point, finishRequest must be called.
this._completer.noteRequest(this.gethashUrl);
}
catch (err) {
@@ -507,17 +509,17 @@ HashCompleterRequest.prototype = {
},
onStartRequest: function HCR_onStartRequest(aRequest, aContext) {
// At this point no data is available for us and we have no reason to
// terminate the connection, so we do nothing until |onStopRequest|.
},
onStopRequest: function HCR_onStopRequest(aRequest, aContext, aStatusCode) {
- Services.obs.removeObserver(this, "xpcom-shutdown");
+ Services.obs.removeObserver(this, "quit-application");
if (this._shuttingDown) {
throw Cr.NS_ERROR_ABORT;
}
// Default HTTP status to service unavailable, in case we can't retrieve
// the true status from the channel.
let httpStatus = 503;
@@ -554,23 +556,23 @@ HashCompleterRequest.prototype = {
if (success) {
this.notifySuccess();
} else {
this.notifyFailure(aStatusCode);
}
},
observe: function HCR_observe(aSubject, aTopic, aData) {
- if (aTopic != "xpcom-shutdown") {
- return;
- }
+ if (aTopic == "quit-application") {
+ this._shuttingDown = true;
+ if (this._channel) {
+ this._channel.cancel(Cr.NS_ERROR_ABORT);
+ }
- this._shuttingDown = true;
- if (this._channel) {
- this._channel.cancel(Cr.NS_ERROR_ABORT);
+ Services.obs.removeObserver(this, "quit-application");
}
},
};
// Converts a URL safe base64 string to a normal base64 string. Will not change
// normal base64 strings. This is modelled after the same function in
// nsUrlClassifierUtils.h.
function unUrlsafeBase64(aStr) {