michael@0: //* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef LookupCache_h__ michael@0: #define LookupCache_h__ michael@0: michael@0: #include "Entries.h" michael@0: #include "nsString.h" michael@0: #include "nsTArray.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsIFile.h" michael@0: #include "nsIFileStreams.h" michael@0: #include "nsUrlClassifierPrefixSet.h" michael@0: #include "prlog.h" michael@0: michael@0: namespace mozilla { michael@0: namespace safebrowsing { michael@0: michael@0: #define MAX_HOST_COMPONENTS 5 michael@0: #define MAX_PATH_COMPONENTS 4 michael@0: michael@0: class LookupResult { michael@0: public: michael@0: LookupResult() : mComplete(false), mNoise(false), mFresh(false), mProtocolConfirmed(false) {} michael@0: michael@0: // The fragment that matched in the LookupCache michael@0: union { michael@0: Prefix prefix; michael@0: Completion complete; michael@0: } hash; michael@0: michael@0: const Prefix &PrefixHash() { return hash.prefix; } michael@0: const Completion &CompleteHash() { return hash.complete; } michael@0: michael@0: bool Confirmed() const { return (mComplete && mFresh) || mProtocolConfirmed; } michael@0: bool Complete() const { return mComplete; } michael@0: michael@0: // True if we have a complete match for this hash in the table. michael@0: bool mComplete; michael@0: michael@0: // True if this is a noise entry, i.e. an extra entry michael@0: // that is inserted to mask the true URL we are requesting michael@0: bool mNoise; michael@0: michael@0: // True if we've updated this table recently-enough. michael@0: bool mFresh; michael@0: michael@0: bool mProtocolConfirmed; michael@0: michael@0: nsCString mTableName; michael@0: }; michael@0: michael@0: typedef nsTArray LookupResultArray; michael@0: michael@0: struct CacheResult { michael@0: AddComplete entry; michael@0: nsCString table; michael@0: }; michael@0: typedef nsTArray CacheResultArray; michael@0: michael@0: class LookupCache { michael@0: public: michael@0: // Check for a canonicalized IP address. michael@0: static bool IsCanonicalizedIP(const nsACString& aHost); michael@0: michael@0: // take a lookup string (www.hostname.com/path/to/resource.html) and michael@0: // expand it into the set of fragments that should be searched for in an michael@0: // entry michael@0: static nsresult GetLookupFragments(const nsACString& aSpec, michael@0: nsTArray* aFragments); michael@0: // Similar to GetKey(), but if the domain contains three or more components, michael@0: // two keys will be returned: michael@0: // hostname.com/foo/bar -> [hostname.com] michael@0: // mail.hostname.com/foo/bar -> [hostname.com, mail.hostname.com] michael@0: // www.mail.hostname.com/foo/bar -> [hostname.com, mail.hostname.com] michael@0: static nsresult GetHostKeys(const nsACString& aSpec, michael@0: nsTArray* aHostKeys); michael@0: // Get the database key for a given URI. This is the top three michael@0: // domain components if they exist, otherwise the top two. michael@0: // hostname.com/foo/bar -> hostname.com michael@0: // mail.hostname.com/foo/bar -> mail.hostname.com michael@0: // www.mail.hostname.com/foo/bar -> mail.hostname.com michael@0: static nsresult GetKey(const nsACString& aSpec, Completion* aHash, michael@0: nsCOMPtr& aCryptoHash); michael@0: michael@0: LookupCache(const nsACString& aTableName, nsIFile* aStoreFile); michael@0: ~LookupCache(); michael@0: michael@0: const nsCString &TableName() const { return mTableName; } michael@0: michael@0: nsresult Init(); michael@0: nsresult Open(); michael@0: // The directory handle where we operate will michael@0: // be moved away when a backup is made. michael@0: nsresult UpdateDirHandle(nsIFile* aStoreDirectory); michael@0: // This will Clear() the passed arrays when done. michael@0: nsresult Build(AddPrefixArray& aAddPrefixes, michael@0: AddCompleteArray& aAddCompletes); michael@0: nsresult GetPrefixes(nsTArray* aAddPrefixes); michael@0: void ClearCompleteCache(); michael@0: michael@0: #if DEBUG && defined(PR_LOGGING) michael@0: void Dump(); michael@0: #endif michael@0: nsresult WriteFile(); michael@0: nsresult Has(const Completion& aCompletion, michael@0: bool* aHas, bool* aComplete); michael@0: bool IsPrimed(); michael@0: michael@0: private: michael@0: void ClearAll(); michael@0: nsresult Reset(); michael@0: void UpdateHeader(); michael@0: nsresult ReadHeader(nsIInputStream* aInputStream); michael@0: nsresult ReadCompletions(nsIInputStream* aInputStream); michael@0: nsresult EnsureSizeConsistent(); michael@0: nsresult LoadPrefixSet(); michael@0: // Construct a Prefix Set with known prefixes. michael@0: // This will Clear() aAddPrefixes when done. michael@0: nsresult ConstructPrefixSet(AddPrefixArray& aAddPrefixes); michael@0: michael@0: struct Header { michael@0: uint32_t magic; michael@0: uint32_t version; michael@0: uint32_t numCompletions; michael@0: }; michael@0: Header mHeader; michael@0: michael@0: bool mPrimed; michael@0: nsCString mTableName; michael@0: nsCOMPtr mStoreDirectory; michael@0: CompletionArray mCompletions; michael@0: // Set of prefixes known to be in the database michael@0: nsRefPtr mPrefixSet; michael@0: }; michael@0: michael@0: } michael@0: } michael@0: michael@0: #endif