forked from mirrors/gecko-dev
		
	A LazyIdle thread should be created and removed by the same thread. This patch fixes testcases that trigger the assertion. Depends on D49874 Differential Revision: https://phabricator.services.mozilla.com/D49875 --HG-- extra : moz-landing-system : lando
		
			
				
	
	
		
			257 lines
		
	
	
	
		
			8.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			257 lines
		
	
	
	
		
			8.6 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 Classifier_h__
 | 
						|
#define Classifier_h__
 | 
						|
 | 
						|
#include "Entries.h"
 | 
						|
#include "HashStore.h"
 | 
						|
#include "ProtocolParser.h"
 | 
						|
#include "LookupCache.h"
 | 
						|
#include "nsCOMPtr.h"
 | 
						|
#include "nsString.h"
 | 
						|
#include "nsIFile.h"
 | 
						|
#include "nsDataHashtable.h"
 | 
						|
 | 
						|
class nsIThread;
 | 
						|
 | 
						|
namespace mozilla {
 | 
						|
namespace safebrowsing {
 | 
						|
 | 
						|
/**
 | 
						|
 * Maintains the stores and LookupCaches for the url classifier.
 | 
						|
 */
 | 
						|
class Classifier {
 | 
						|
 public:
 | 
						|
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Classifier);
 | 
						|
 | 
						|
  Classifier();
 | 
						|
 | 
						|
  nsresult Open(nsIFile& aCacheDirectory);
 | 
						|
  void Close();
 | 
						|
  void Reset();  // Not including any intermediary for update.
 | 
						|
 | 
						|
  /**
 | 
						|
   * Clear data for specific tables.
 | 
						|
   * If ClearType is Clear_Cache, this function will only clear cache in lookup
 | 
						|
   * cache, otherwise, it will clear data in lookup cache and data stored on
 | 
						|
   * disk.
 | 
						|
   */
 | 
						|
  enum ClearType {
 | 
						|
    Clear_Cache,
 | 
						|
    Clear_All,
 | 
						|
  };
 | 
						|
  void ResetTables(ClearType aType, const nsTArray<nsCString>& aTables);
 | 
						|
 | 
						|
  /**
 | 
						|
   * Get the list of active tables and their chunks in a format
 | 
						|
   * suitable for an update request.
 | 
						|
   */
 | 
						|
  void TableRequest(nsACString& aResult);
 | 
						|
 | 
						|
  /*
 | 
						|
   * Get all tables that we know about.
 | 
						|
   */
 | 
						|
  nsresult ActiveTables(nsTArray<nsCString>& aTables) const;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Check URL fragments against a specified table.
 | 
						|
   * The fragments should be generated by |LookupCache::GetLookupFragments|
 | 
						|
   */
 | 
						|
  nsresult CheckURIFragments(const nsTArray<nsCString>& aSpecFragments,
 | 
						|
                             const nsACString& table,
 | 
						|
                             LookupResultArray& aResults);
 | 
						|
 | 
						|
  /**
 | 
						|
   * Asynchronously apply updates to the in-use databases. When the
 | 
						|
   * update is complete, the caller can be notified by |aCallback|, which
 | 
						|
   * will occur on the caller thread.
 | 
						|
   */
 | 
						|
  using AsyncUpdateCallback = std::function<void(nsresult)>;
 | 
						|
  nsresult AsyncApplyUpdates(const TableUpdateArray& aUpdates,
 | 
						|
                             const AsyncUpdateCallback& aCallback);
 | 
						|
 | 
						|
  /**
 | 
						|
   * Wait until the ongoing async update is finished and callback
 | 
						|
   * is fired. Once this function returns, AsyncApplyUpdates is
 | 
						|
   * no longer available.
 | 
						|
   */
 | 
						|
  void FlushAndDisableAsyncUpdate();
 | 
						|
 | 
						|
  /**
 | 
						|
   * Apply full hashes retrived from gethash to cache.
 | 
						|
   */
 | 
						|
  nsresult ApplyFullHashes(ConstTableUpdateArray& aUpdates);
 | 
						|
 | 
						|
  /*
 | 
						|
   * Get a bunch of extra prefixes to query for completion
 | 
						|
   * and mask the real entry being requested
 | 
						|
   */
 | 
						|
  nsresult ReadNoiseEntries(const Prefix& aPrefix, const nsACString& aTableName,
 | 
						|
                            uint32_t aCount, PrefixArray& aNoiseEntries);
 | 
						|
 | 
						|
#ifdef MOZ_SAFEBROWSING_DUMP_FAILED_UPDATES
 | 
						|
  nsresult DumpRawTableUpdates(const nsACString& aRawUpdates);
 | 
						|
#endif
 | 
						|
 | 
						|
  static void SplitTables(const nsACString& str, nsTArray<nsCString>& tables);
 | 
						|
 | 
						|
  // Given a root store directory, return a private store directory
 | 
						|
  // based on the table name. To avoid migration issue, the private
 | 
						|
  // store directory is only different from root directory for V4 tables.
 | 
						|
  //
 | 
						|
  // For V4 tables (suffixed by '-proto'), the private directory would
 | 
						|
  // be [root directory path]/[provider]. The provider of V4 tables is
 | 
						|
  // 'google4'.
 | 
						|
  //
 | 
						|
  // Note that if the table name is not owned by any provider, just use
 | 
						|
  // the root directory.
 | 
						|
  static nsresult GetPrivateStoreDirectory(nsIFile* aRootStoreDirectory,
 | 
						|
                                           const nsACString& aTableName,
 | 
						|
                                           const nsACString& aProvider,
 | 
						|
                                           nsIFile** aPrivateStoreDirectory);
 | 
						|
 | 
						|
  // Swap in in-memory and on-disk database and remove all
 | 
						|
  // update intermediaries.
 | 
						|
  nsresult SwapInNewTablesAndCleanup();
 | 
						|
 | 
						|
  RefPtr<LookupCache> GetLookupCache(const nsACString& aTable,
 | 
						|
                                     bool aForUpdate = false);
 | 
						|
 | 
						|
  void GetCacheInfo(const nsACString& aTable,
 | 
						|
                    nsIUrlClassifierCacheInfo** aCache);
 | 
						|
 | 
						|
  bool OnUpdateThread() const;
 | 
						|
 | 
						|
 private:
 | 
						|
  ~Classifier();
 | 
						|
 | 
						|
  void DropStores();
 | 
						|
  void DeleteTables(nsIFile* aDirectory, const nsTArray<nsCString>& aTables);
 | 
						|
 | 
						|
  nsresult CreateStoreDirectory();
 | 
						|
  nsresult SetupPathNames();
 | 
						|
  nsresult RecoverBackups();
 | 
						|
  nsresult CleanToDelete();
 | 
						|
  nsresult CopyInUseDirForUpdate();
 | 
						|
  nsresult CopyDirectoryInterruptible(nsCOMPtr<nsIFile>& aDestDir,
 | 
						|
                                      nsCOMPtr<nsIFile>& aSourceDir);
 | 
						|
  nsresult RegenActiveTables();
 | 
						|
 | 
						|
  void MergeNewLookupCaches();  // Merge mNewLookupCaches into mLookupCaches.
 | 
						|
 | 
						|
  void CopyAndInvalidateFullHashCache();
 | 
						|
 | 
						|
  // Remove any intermediary for update, including in-memory
 | 
						|
  // and on-disk data.
 | 
						|
  void RemoveUpdateIntermediaries();
 | 
						|
 | 
						|
#ifdef MOZ_SAFEBROWSING_DUMP_FAILED_UPDATES
 | 
						|
  already_AddRefed<nsIFile> GetFailedUpdateDirectroy();
 | 
						|
  nsresult DumpFailedUpdate();
 | 
						|
#endif
 | 
						|
 | 
						|
  nsresult ScanStoreDir(nsIFile* aDirectory,
 | 
						|
                        const nsTArray<nsCString>& aExtensions,
 | 
						|
                        nsTArray<nsCString>& aTables);
 | 
						|
 | 
						|
  nsresult UpdateHashStore(TableUpdateArray& aUpdates,
 | 
						|
                           const nsACString& aTable);
 | 
						|
 | 
						|
  nsresult UpdateTableV4(TableUpdateArray& aUpdates, const nsACString& aTable);
 | 
						|
 | 
						|
  nsresult UpdateCache(RefPtr<const TableUpdate> aUpdates);
 | 
						|
 | 
						|
  RefPtr<LookupCache> GetLookupCacheForUpdate(const nsACString& aTable) {
 | 
						|
    return GetLookupCache(aTable, true);
 | 
						|
  }
 | 
						|
 | 
						|
  RefPtr<LookupCache> GetLookupCacheFrom(const nsACString& aTable,
 | 
						|
                                         LookupCacheArray& aLookupCaches,
 | 
						|
                                         nsIFile* aRootStoreDirectory);
 | 
						|
 | 
						|
  bool CheckValidUpdate(TableUpdateArray& aUpdates, const nsACString& aTable);
 | 
						|
 | 
						|
  nsresult LoadHashStore(nsIFile* aDirectory, nsACString& aResult,
 | 
						|
                         nsTArray<nsCString>& aFailedTableNames);
 | 
						|
 | 
						|
  nsresult LoadMetadata(nsIFile* aDirectory, nsACString& aResult,
 | 
						|
                        nsTArray<nsCString>& aFailedTableNames);
 | 
						|
 | 
						|
  static nsCString GetProvider(const nsACString& aTableName);
 | 
						|
 | 
						|
  /**
 | 
						|
   * The "background" part of ApplyUpdates. Once the background update
 | 
						|
   * is called, the foreground update has to be called along with the
 | 
						|
   * background result no matter whether the background update is
 | 
						|
   * successful or not.
 | 
						|
   */
 | 
						|
  nsresult ApplyUpdatesBackground(TableUpdateArray& aUpdates,
 | 
						|
                                  nsTArray<nsCString>& aFailedTableNames);
 | 
						|
 | 
						|
  /**
 | 
						|
   * The "foreground" part of ApplyUpdates. The in-use data (in-memory and
 | 
						|
   * on-disk) will be touched so this MUST be mutually exclusive to other
 | 
						|
   * member functions.
 | 
						|
   *
 | 
						|
   * If |aBackgroundRv| is successful, the return value is the result of
 | 
						|
   * bringing stuff to the foreground. Otherwise, the foreground table may
 | 
						|
   * be reset according to the background update failed reason and
 | 
						|
   * |aBackgroundRv| will be returned to forward the background update result.
 | 
						|
   */
 | 
						|
  nsresult ApplyUpdatesForeground(nsresult aBackgroundRv,
 | 
						|
                                  const nsTArray<nsCString>& aFailedTableNames);
 | 
						|
 | 
						|
  // Used by worker thread and update thread to abort current operation.
 | 
						|
  bool ShouldAbort() const;
 | 
						|
 | 
						|
  // Add built-in entries for testing.
 | 
						|
  nsresult AddMozEntries(nsTArray<nsCString>& aTables);
 | 
						|
 | 
						|
  // Remove test files if exist
 | 
						|
  nsresult ClearLegacyFiles();
 | 
						|
 | 
						|
  // Root dir of the Local profile.
 | 
						|
  nsCOMPtr<nsIFile> mCacheDirectory;
 | 
						|
  // Main directory where to store the databases.
 | 
						|
  nsCOMPtr<nsIFile> mRootStoreDirectory;
 | 
						|
  // Used for atomically updating the other dirs.
 | 
						|
  nsCOMPtr<nsIFile> mBackupDirectory;
 | 
						|
  nsCOMPtr<nsIFile> mUpdatingDirectory;  // For update only.
 | 
						|
  nsCOMPtr<nsIFile> mToDeleteDirectory;
 | 
						|
  LookupCacheArray mLookupCaches;  // For query only.
 | 
						|
  nsTArray<nsCString> mActiveTablesCache;
 | 
						|
  uint32_t mHashKey;
 | 
						|
 | 
						|
  // In-memory cache for the result of TableRequest. See
 | 
						|
  // nsIUrlClassifierDBService.getTables for the format.
 | 
						|
  nsCString mTableRequestResult;
 | 
						|
 | 
						|
  // Whether mTableRequestResult is outdated and needs to
 | 
						|
  // be reloaded from disk.
 | 
						|
  bool mIsTableRequestResultOutdated;
 | 
						|
 | 
						|
  // The copy of mLookupCaches for update only.
 | 
						|
  LookupCacheArray mNewLookupCaches;
 | 
						|
 | 
						|
  // True when Reset() is called.
 | 
						|
  bool mUpdateInterrupted;
 | 
						|
 | 
						|
  // True once CLose() has been called
 | 
						|
  bool mIsClosed;
 | 
						|
 | 
						|
  nsCOMPtr<nsIThread> mUpdateThread;  // For async update.
 | 
						|
 | 
						|
  // Identical to mRootStoreDirectory but for update only because
 | 
						|
  // nsIFile is not thread safe and mRootStoreDirectory needs to
 | 
						|
  // be accessed in CopyInUseDirForUpdate().
 | 
						|
  // It will be initialized right before update on the worker thread.
 | 
						|
  nsCOMPtr<nsIFile> mRootStoreDirectoryForUpdate;
 | 
						|
};
 | 
						|
 | 
						|
}  // namespace safebrowsing
 | 
						|
}  // namespace mozilla
 | 
						|
 | 
						|
#endif
 |