Files
tubestation/toolkit/components/url-classifier/nsUrlClassifierStreamUpdater.h
Henry Chang 259a763c10 Bug 1338638 - Fix race condition for DBService APIs to avoid long delayed initial download. r=francois
When starting up, SafeBrowsing.jsm will try to use DBService to add testing entries. Meanwhile,
listmanager will request StreamUpdater to download lists with a random initial delay.

The requests that listmanager issue to StreamUpdater will be queued up
if DBserve is busy and will be retried when StreamUpdater is notified that
the previous update is complete. However, in some edge cases,
the queued requests may not be processed until the next update request from listmanager.
For example, SafeBrowsing.jsm calls DBService.beginUpdate at t0 and the update is
complete at t1. If listmanager sends all requests via StreamUpdate between t0 and t1,
they will all be queued up and no further request can trigger the queued ones.

So in this patch I add a timer to re-trigger FetchNextRequest() in case StreamUpdater is not
notified the previous update is complete.

MozReview-Commit-ID: 3hHsS5N7WRI
2017-04-11 17:13:01 +08:00

122 lines
3.9 KiB
C++

//* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-/
/* 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/. */
#ifndef nsUrlClassifierStreamUpdater_h_
#define nsUrlClassifierStreamUpdater_h_
#include <nsISupportsUtils.h>
#include "nsCOMPtr.h"
#include "nsIObserver.h"
#include "nsIUrlClassifierStreamUpdater.h"
#include "nsIStreamListener.h"
#include "nsIChannel.h"
#include "nsTArray.h"
#include "nsITimer.h"
#include "mozilla/Attributes.h"
// Forward declare pointers
class nsIURI;
class nsUrlClassifierStreamUpdater final : public nsIUrlClassifierStreamUpdater,
public nsIUrlClassifierUpdateObserver,
public nsIStreamListener,
public nsIObserver,
public nsIInterfaceRequestor,
public nsITimerCallback
{
public:
nsUrlClassifierStreamUpdater();
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIURLCLASSIFIERSTREAMUPDATER
NS_DECL_NSIURLCLASSIFIERUPDATEOBSERVER
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIOBSERVER
NS_DECL_NSITIMERCALLBACK
private:
// No subclassing
~nsUrlClassifierStreamUpdater() {}
// When the dbservice sends an UpdateComplete or UpdateFailure, we call this
// to reset the stream updater.
void DownloadDone();
// Disallow copy constructor
nsUrlClassifierStreamUpdater(nsUrlClassifierStreamUpdater&);
nsresult AddRequestBody(const nsACString &aRequestBody);
// Fetches an update for a single table.
nsresult FetchUpdate(nsIURI *aURI,
const nsACString &aRequest,
bool aIsPostRequest,
const nsACString &aTable);
// Dumb wrapper so we don't have to create URIs.
nsresult FetchUpdate(const nsACString &aURI,
const nsACString &aRequest,
bool aIsPostRequest,
const nsACString &aTable);
// Fetches the next table, from mPendingUpdates.
nsresult FetchNext();
// Fetches the next request, from mPendingRequests
nsresult FetchNextRequest();
bool mIsUpdating;
bool mInitialized;
bool mDownloadError;
bool mBeganStream;
nsCString mDownloadErrorStatusStr;
// Note that mStreamTable is only used by v2, it is empty for v4 update.
nsCString mStreamTable;
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsIUrlClassifierDBService> mDBService;
// In v2, a update response might contain redirection and this
// timer is for fetching the redirected update.
nsCOMPtr<nsITimer> mFetchIndirectUpdatesTimer;
// When we DownloadUpdate(), the DBService might be busy on processing
// request issused outside of StreamUpdater. We have to fire a timer to
// retry on our own.
nsCOMPtr<nsITimer> mFetchNextRequestTimer;
struct PendingRequest {
nsCString mTables;
nsCString mRequestPayload;
bool mIsPostRequest;
nsCString mUrl;
nsCOMPtr<nsIUrlClassifierCallback> mSuccessCallback;
nsCOMPtr<nsIUrlClassifierCallback> mUpdateErrorCallback;
nsCOMPtr<nsIUrlClassifierCallback> mDownloadErrorCallback;
};
nsTArray<PendingRequest> mPendingRequests;
struct PendingUpdate {
nsCString mUrl;
nsCString mTable;
};
nsTArray<PendingUpdate> mPendingUpdates;
nsCOMPtr<nsIUrlClassifierCallback> mSuccessCallback;
nsCOMPtr<nsIUrlClassifierCallback> mUpdateErrorCallback;
nsCOMPtr<nsIUrlClassifierCallback> mDownloadErrorCallback;
// The provider for current update request and should be only used by telemetry
// since it would show up as "other" for any other providers.
nsCString mTelemetryProvider;
PRIntervalTime mTelemetryClockStart;
};
#endif // nsUrlClassifierStreamUpdater_h_