LCOV - code coverage report
Current view: top level - toolkit/components/url-classifier - LookupCacheV4.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 279 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 41 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "LookupCacheV4.h"
       7             : #include "HashStore.h"
       8             : #include "mozilla/Unused.h"
       9             : #include <string>
      10             : 
      11             : // MOZ_LOG=UrlClassifierDbService:5
      12             : extern mozilla::LazyLogModule gUrlClassifierDbServiceLog;
      13             : #define LOG(args) MOZ_LOG(gUrlClassifierDbServiceLog, mozilla::LogLevel::Debug, args)
      14             : #define LOG_ENABLED() MOZ_LOG_TEST(gUrlClassifierDbServiceLog, mozilla::LogLevel::Debug)
      15             : 
      16             : #define METADATA_SUFFIX NS_LITERAL_CSTRING(".metadata")
      17             : 
      18             : namespace mozilla {
      19             : namespace safebrowsing {
      20             : 
      21             : const int LookupCacheV4::VER = 4;
      22             : 
      23             : // Prefixes coming from updates and VLPrefixSet are both stored in the HashTable
      24             : // where the (key, value) pair is a prefix size and a lexicographic-sorted string.
      25             : // The difference is prefixes from updates use std:string(to avoid additional copies)
      26             : // and prefixes from VLPrefixSet use nsCString.
      27             : // This class provides a common interface for the partial update algorithm to make it
      28             : // easier to operate on two different kind prefix string map..
      29           0 : class VLPrefixSet
      30             : {
      31             : public:
      32             :   explicit VLPrefixSet(const PrefixStringMap& aMap);
      33             :   explicit VLPrefixSet(const TableUpdateV4::PrefixStdStringMap& aMap);
      34             : 
      35             :   // This function will merge the prefix map in VLPrefixSet to aPrefixMap.
      36             :   void Merge(PrefixStringMap& aPrefixMap);
      37             : 
      38             :   // Find the smallest string from the map in VLPrefixSet.
      39             :   bool GetSmallestPrefix(nsDependentCSubstring& aOutString);
      40             : 
      41             :   // Return the number of prefixes in the map
      42           0 :   uint32_t Count() const { return mCount; }
      43             : 
      44             : private:
      45             :   // PrefixString structure contains a lexicographic-sorted string with
      46             :   // a |pos| variable to indicate which substring we are pointing to right now.
      47             :   // |pos| increases each time GetSmallestPrefix finds the smallest string.
      48           0 :   struct PrefixString {
      49           0 :     PrefixString(const nsACString& aStr, uint32_t aSize)
      50           0 :      : pos(0)
      51           0 :      , size(aSize)
      52             :     {
      53           0 :       data.Rebind(aStr.BeginReading(), aStr.Length());
      54           0 :     }
      55             : 
      56           0 :     const char* get() {
      57           0 :       return pos < data.Length() ? data.BeginReading() + pos : nullptr;
      58             :     }
      59           0 :     void next() { pos += size; }
      60           0 :     uint32_t remaining() { return data.Length() - pos; }
      61             : 
      62             :     nsDependentCSubstring data;
      63             :     uint32_t pos;
      64             :     uint32_t size;
      65             :   };
      66             : 
      67             :   nsClassHashtable<nsUint32HashKey, PrefixString> mMap;
      68             :   uint32_t mCount;
      69             : };
      70             : 
      71             : nsresult
      72           0 : LookupCacheV4::Init()
      73             : {
      74           0 :   mVLPrefixSet = new VariableLengthPrefixSet();
      75           0 :   nsresult rv = mVLPrefixSet->Init(mTableName);
      76           0 :   NS_ENSURE_SUCCESS(rv, rv);
      77             : 
      78           0 :   return NS_OK;
      79             : }
      80             : 
      81             : nsresult
      82           0 : LookupCacheV4::Has(const Completion& aCompletion,
      83             :                    bool* aHas,
      84             :                    uint32_t* aMatchLength,
      85             :                    bool* aConfirmed)
      86             : {
      87           0 :   *aHas = *aConfirmed = false;
      88           0 :   *aMatchLength = 0;
      89             : 
      90           0 :   uint32_t length = 0;
      91           0 :   nsDependentCSubstring fullhash;
      92           0 :   fullhash.Rebind((const char *)aCompletion.buf, COMPLETE_SIZE);
      93             : 
      94           0 :   nsresult rv = mVLPrefixSet->Matches(fullhash, &length);
      95           0 :   NS_ENSURE_SUCCESS(rv, rv);
      96             : 
      97           0 :   MOZ_ASSERT(length == 0 || (length >= PREFIX_SIZE && length <= COMPLETE_SIZE));
      98             : 
      99           0 :   *aHas = length >= PREFIX_SIZE;
     100           0 :   *aMatchLength = length;
     101             : 
     102           0 :   if (LOG_ENABLED()) {
     103           0 :     uint32_t prefix = aCompletion.ToUint32();
     104           0 :     LOG(("Probe in V4 %s: %X, found %d, complete %d", mTableName.get(),
     105             :           prefix, *aHas, length == COMPLETE_SIZE));
     106             :   }
     107             : 
     108             :   // Check if fullhash match any prefix in the local database
     109           0 :   if (!(*aHas)) {
     110           0 :     return NS_OK;
     111             :   }
     112             : 
     113             :   // Even though V4 supports variable-length prefix, we always send 4-bytes for
     114             :   // completion (Bug 1323953). This means cached prefix length is also 4-bytes.
     115           0 :   return CheckCache(aCompletion, aHas, aConfirmed);
     116             : }
     117             : 
     118             : bool
     119           0 : LookupCacheV4::IsEmpty()
     120             : {
     121             :   bool isEmpty;
     122           0 :   mVLPrefixSet->IsEmpty(&isEmpty);
     123           0 :   return isEmpty;
     124             : }
     125             : 
     126             : nsresult
     127           0 : LookupCacheV4::Build(PrefixStringMap& aPrefixMap)
     128             : {
     129           0 :   Telemetry::AutoTimer<Telemetry::URLCLASSIFIER_VLPS_CONSTRUCT_TIME> timer;
     130             : 
     131           0 :   return mVLPrefixSet->SetPrefixes(aPrefixMap);
     132             : }
     133             : 
     134             : nsresult
     135           0 : LookupCacheV4::GetPrefixes(PrefixStringMap& aPrefixMap)
     136             : {
     137           0 :   return mVLPrefixSet->GetPrefixes(aPrefixMap);
     138             : }
     139             : 
     140             : nsresult
     141           0 : LookupCacheV4::GetFixedLengthPrefixes(FallibleTArray<uint32_t>& aPrefixes)
     142             : {
     143           0 :   return mVLPrefixSet->GetFixedLengthPrefixes(aPrefixes);
     144             : }
     145             : 
     146             : nsresult
     147           0 : LookupCacheV4::ClearPrefixes()
     148             : {
     149             :   // Clear by seting a empty map
     150           0 :   PrefixStringMap map;
     151           0 :   return mVLPrefixSet->SetPrefixes(map);
     152             : }
     153             : 
     154             : nsresult
     155           0 : LookupCacheV4::StoreToFile(nsIFile* aFile)
     156             : {
     157           0 :   return mVLPrefixSet->StoreToFile(aFile);
     158             : }
     159             : 
     160             : nsresult
     161           0 : LookupCacheV4::LoadFromFile(nsIFile* aFile)
     162             : {
     163           0 :   nsresult rv = mVLPrefixSet->LoadFromFile(aFile);
     164           0 :   if (NS_FAILED(rv)) {
     165           0 :     return rv;
     166             :   }
     167             : 
     168           0 :   nsCString state, checksum;
     169           0 :   rv = LoadMetadata(state, checksum);
     170           0 :   if (NS_FAILED(rv)) {
     171           0 :     return rv;
     172             :   }
     173             : 
     174           0 :   rv = VerifyChecksum(checksum);
     175           0 :   Telemetry::Accumulate(Telemetry::URLCLASSIFIER_VLPS_LOAD_CORRUPT,
     176           0 :                         rv == NS_ERROR_FILE_CORRUPTED);
     177             : 
     178           0 :   return rv;
     179             : }
     180             : 
     181             : size_t
     182           0 : LookupCacheV4::SizeOfPrefixSet()
     183             : {
     184           0 :   return mVLPrefixSet->SizeOfIncludingThis(moz_malloc_size_of);
     185             : }
     186             : 
     187             : static void
     188           0 : AppendPrefixToMap(PrefixStringMap& prefixes, nsDependentCSubstring& prefix)
     189             : {
     190           0 :   if (!prefix.Length()) {
     191           0 :     return;
     192             :   }
     193             : 
     194           0 :   nsCString* prefixString = prefixes.LookupOrAdd(prefix.Length());
     195           0 :   prefixString->Append(prefix.BeginReading(), prefix.Length());
     196             : }
     197             : 
     198             : // Read prefix into a buffer and also update the hash which
     199             : // keeps track of the checksum
     200             : static void
     201           0 : UpdateChecksum(nsICryptoHash* aCrypto, const nsACString& aPrefix)
     202             : {
     203           0 :   MOZ_ASSERT(aCrypto);
     204           0 :   aCrypto->Update(reinterpret_cast<uint8_t*>(const_cast<char*>(
     205           0 :                   aPrefix.BeginReading())),
     206           0 :                   aPrefix.Length());
     207           0 : }
     208             : 
     209             : // Please see https://bug1287058.bmoattachments.org/attachment.cgi?id=8795366
     210             : // for detail about partial update algorithm.
     211             : nsresult
     212           0 : LookupCacheV4::ApplyUpdate(TableUpdateV4* aTableUpdate,
     213             :                            PrefixStringMap& aInputMap,
     214             :                            PrefixStringMap& aOutputMap)
     215             : {
     216           0 :   MOZ_ASSERT(aOutputMap.IsEmpty());
     217             : 
     218           0 :   nsCOMPtr<nsICryptoHash> crypto;
     219           0 :   nsresult rv = InitCrypto(crypto);
     220           0 :   if (NS_FAILED(rv)) {
     221           0 :     return rv;
     222             :   }
     223             : 
     224             :   // oldPSet contains prefixes we already have or we just merged last round.
     225             :   // addPSet contains prefixes stored in tableUpdate which should be merged with oldPSet.
     226           0 :   VLPrefixSet oldPSet(aInputMap);
     227           0 :   VLPrefixSet addPSet(aTableUpdate->Prefixes());
     228             : 
     229             :   // RemovalIndiceArray is a sorted integer array indicating the index of prefix we should
     230             :   // remove from the old prefix set(according to lexigraphic order).
     231             :   // |removalIndex| is the current index of RemovalIndiceArray.
     232             :   // |numOldPrefixPicked| is used to record how many prefixes we picked from the old map.
     233           0 :   TableUpdateV4::RemovalIndiceArray& removalArray = aTableUpdate->RemovalIndices();
     234           0 :   uint32_t removalIndex = 0;
     235           0 :   int32_t numOldPrefixPicked = -1;
     236             : 
     237           0 :   nsDependentCSubstring smallestOldPrefix;
     238           0 :   nsDependentCSubstring smallestAddPrefix;
     239             : 
     240           0 :   bool isOldMapEmpty = false, isAddMapEmpty = false;
     241             : 
     242             :   // This is used to avoid infinite loop for partial update algorithm.
     243             :   // The maximum loops will be the number of old prefixes plus the number of add prefixes.
     244           0 :   int32_t index = oldPSet.Count() + addPSet.Count() + 1;
     245           0 :   for(;index > 0; index--) {
     246             :     // Get smallest prefix from the old prefix set if we don't have one
     247           0 :     if (smallestOldPrefix.IsEmpty() && !isOldMapEmpty) {
     248           0 :       isOldMapEmpty = !oldPSet.GetSmallestPrefix(smallestOldPrefix);
     249             :     }
     250             : 
     251             :     // Get smallest prefix from add prefix set if we don't have one
     252           0 :     if (smallestAddPrefix.IsEmpty() && !isAddMapEmpty) {
     253           0 :       isAddMapEmpty = !addPSet.GetSmallestPrefix(smallestAddPrefix);
     254             :     }
     255             : 
     256             :     bool pickOld;
     257             : 
     258             :     // If both prefix sets are not empty, then compare to find the smaller one.
     259           0 :     if (!isOldMapEmpty && !isAddMapEmpty) {
     260           0 :       if (smallestOldPrefix == smallestAddPrefix) {
     261           0 :         LOG(("Add prefix should not exist in the original prefix set."));
     262           0 :         return NS_ERROR_UC_UPDATE_DUPLICATE_PREFIX;
     263             :       }
     264             : 
     265             :       // Compare the smallest string in old prefix set and add prefix set,
     266             :       // merge the smaller one into new map to ensure merged string still
     267             :       // follows lexigraphic order.
     268           0 :       pickOld = smallestOldPrefix < smallestAddPrefix;
     269           0 :     } else if (!isOldMapEmpty && isAddMapEmpty) {
     270           0 :       pickOld = true;
     271           0 :     } else if (isOldMapEmpty && !isAddMapEmpty) {
     272           0 :       pickOld = false;
     273             :     // If both maps are empty, then partial update is complete.
     274             :     } else {
     275             :       break;
     276             :     }
     277             : 
     278           0 :     if (pickOld) {
     279           0 :       numOldPrefixPicked++;
     280             : 
     281             :       // If the number of picks from old map matches the removalIndex, then this prefix
     282             :       // will be removed by not merging it to new map.
     283           0 :       if (removalIndex < removalArray.Length() &&
     284           0 :           numOldPrefixPicked == removalArray[removalIndex]) {
     285           0 :         removalIndex++;
     286             :       } else {
     287           0 :         AppendPrefixToMap(aOutputMap, smallestOldPrefix);
     288           0 :         UpdateChecksum(crypto, smallestOldPrefix);
     289             :       }
     290           0 :       smallestOldPrefix.SetLength(0);
     291             :     } else {
     292           0 :       AppendPrefixToMap(aOutputMap, smallestAddPrefix);
     293           0 :       UpdateChecksum(crypto, smallestAddPrefix);
     294             : 
     295           0 :       smallestAddPrefix.SetLength(0);
     296             :     }
     297             :   }
     298             : 
     299             :   // We expect index will be greater to 0 because max number of runs will be
     300             :   // the number of original prefix plus add prefix.
     301           0 :   if (index <= 0) {
     302           0 :     LOG(("There are still prefixes remaining after reaching maximum runs."));
     303           0 :     return NS_ERROR_UC_UPDATE_INFINITE_LOOP;
     304             :   }
     305             : 
     306           0 :   if (removalIndex < removalArray.Length()) {
     307           0 :     LOG(("There are still prefixes to remove after exhausting the old PrefixSet."));
     308           0 :     return NS_ERROR_UC_UPDATE_WRONG_REMOVAL_INDICES;
     309             :   }
     310             : 
     311           0 :   nsAutoCString checksum;
     312           0 :   crypto->Finish(false, checksum);
     313           0 :   if (aTableUpdate->Checksum().IsEmpty()) {
     314           0 :     LOG(("Update checksum missing."));
     315           0 :     Telemetry::Accumulate(Telemetry::URLCLASSIFIER_UPDATE_ERROR, mProvider,
     316           0 :         NS_ERROR_GET_CODE(NS_ERROR_UC_UPDATE_MISSING_CHECKSUM));
     317             : 
     318             :     // Generate our own checksum to tableUpdate to ensure there is always
     319             :     // checksum in .metadata
     320           0 :     std::string stdChecksum(checksum.BeginReading(), checksum.Length());
     321           0 :     aTableUpdate->NewChecksum(stdChecksum);
     322           0 :   } else if (aTableUpdate->Checksum() != checksum){
     323           0 :     LOG(("Checksum mismatch after applying partial update"));
     324           0 :     return NS_ERROR_UC_UPDATE_CHECKSUM_MISMATCH;
     325             :   }
     326             : 
     327           0 :   return NS_OK;
     328             : }
     329             : 
     330             : nsresult
     331           0 : LookupCacheV4::AddFullHashResponseToCache(const FullHashResponseMap& aResponseMap)
     332             : {
     333           0 :   CopyClassHashTable<FullHashResponseMap>(aResponseMap, mFullHashCache);
     334             : 
     335           0 :   return NS_OK;
     336             : }
     337             : 
     338             : nsresult
     339           0 : LookupCacheV4::InitCrypto(nsCOMPtr<nsICryptoHash>& aCrypto)
     340             : {
     341             :   nsresult rv;
     342           0 :   aCrypto = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
     343           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     344           0 :     return rv;
     345             :   }
     346             : 
     347           0 :   rv = aCrypto->Init(nsICryptoHash::SHA256);
     348           0 :   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "InitCrypto failed");
     349             : 
     350           0 :   return rv;
     351             : }
     352             : 
     353             : nsresult
     354           0 : LookupCacheV4::VerifyChecksum(const nsACString& aChecksum)
     355             : {
     356           0 :   nsCOMPtr<nsICryptoHash> crypto;
     357           0 :   nsresult rv = InitCrypto(crypto);
     358           0 :   if (NS_FAILED(rv)) {
     359           0 :     return rv;
     360             :   }
     361             : 
     362           0 :   PrefixStringMap map;
     363           0 :   mVLPrefixSet->GetPrefixes(map);
     364             : 
     365           0 :   VLPrefixSet loadPSet(map);
     366           0 :   uint32_t index = loadPSet.Count() + 1;
     367           0 :   for(;index > 0; index--) {
     368           0 :     nsDependentCSubstring prefix;
     369           0 :     if (!loadPSet.GetSmallestPrefix(prefix)) {
     370           0 :       break;
     371             :     }
     372           0 :     UpdateChecksum(crypto, prefix);
     373             :   }
     374             : 
     375           0 :   nsAutoCString checksum;
     376           0 :   crypto->Finish(false, checksum);
     377             : 
     378           0 :   if (checksum != aChecksum) {
     379           0 :     LOG(("Checksum mismatch when loading prefixes from file."));
     380           0 :     return NS_ERROR_FILE_CORRUPTED;
     381             :   }
     382             : 
     383           0 :   return NS_OK;
     384             : }
     385             : 
     386             : //////////////////////////////////////////////////////////////////////////
     387             : // A set of lightweight functions for reading/writing value from/to file.
     388             : 
     389             : namespace {
     390             : 
     391             : template<typename T>
     392             : struct ValueTraits
     393             : {
     394           0 :   static uint32_t Length(const T& aValue) { return sizeof(T); }
     395           0 :   static char* WritePtr(T& aValue, uint32_t aLength) { return (char*)&aValue; }
     396           0 :   static const char* ReadPtr(const T& aValue) { return (char*)&aValue; }
     397           0 :   static bool IsFixedLength() { return true; }
     398             : };
     399             : 
     400             : template<>
     401             : struct ValueTraits<nsACString>
     402             : {
     403           0 :   static bool IsFixedLength() { return false; }
     404             : 
     405           0 :   static uint32_t Length(const nsACString& aValue)
     406             :   {
     407           0 :     return aValue.Length();
     408             :   }
     409             : 
     410           0 :   static char* WritePtr(nsACString& aValue, uint32_t aLength)
     411             :   {
     412           0 :     aValue.SetLength(aLength);
     413           0 :     return aValue.BeginWriting();
     414             :   }
     415             : 
     416           0 :   static const char* ReadPtr(const nsACString& aValue)
     417             :   {
     418           0 :     return aValue.BeginReading();
     419             :   }
     420             : };
     421             : 
     422             : template<typename T> static nsresult
     423           0 : WriteValue(nsIOutputStream *aOutputStream, const T& aValue)
     424             : {
     425           0 :   uint32_t writeLength = ValueTraits<T>::Length(aValue);
     426           0 :   if (!ValueTraits<T>::IsFixedLength()) {
     427             :     // We need to write out the variable value length.
     428           0 :     nsresult rv = WriteValue(aOutputStream, writeLength);
     429           0 :     NS_ENSURE_SUCCESS(rv, rv);
     430             :   }
     431             : 
     432             :   // Write out the value.
     433           0 :   auto valueReadPtr = ValueTraits<T>::ReadPtr(aValue);
     434             :   uint32_t written;
     435           0 :   nsresult rv = aOutputStream->Write(valueReadPtr, writeLength, &written);
     436           0 :   if (NS_FAILED(rv) || written != writeLength) {
     437           0 :     LOG(("Failed to write the value."));
     438           0 :     return NS_FAILED(rv) ? rv : NS_ERROR_FAILURE;
     439             :   }
     440             : 
     441           0 :   return rv;
     442             : }
     443             : 
     444             : template<typename T> static nsresult
     445           0 : ReadValue(nsIInputStream* aInputStream, T& aValue)
     446             : {
     447             :   nsresult rv;
     448             : 
     449             :   uint32_t readLength;
     450           0 :   if (ValueTraits<T>::IsFixedLength()) {
     451           0 :     readLength = ValueTraits<T>::Length(aValue);
     452             :   } else {
     453             :     // Read the variable value length from file.
     454           0 :     nsresult rv = ReadValue(aInputStream, readLength);
     455           0 :     NS_ENSURE_SUCCESS(rv, rv);
     456             :   }
     457             : 
     458             :   // Read the value.
     459             :   uint32_t read;
     460           0 :   auto valueWritePtr = ValueTraits<T>::WritePtr(aValue, readLength);
     461           0 :   rv = aInputStream->Read(valueWritePtr, readLength, &read);
     462           0 :   if (NS_FAILED(rv) || read != readLength) {
     463           0 :     LOG(("Failed to read the value."));
     464           0 :     return NS_FAILED(rv) ? rv : NS_ERROR_FAILURE;
     465             :   }
     466             : 
     467           0 :   return rv;
     468             : }
     469             : 
     470             : } // end of unnamed namespace.
     471             : ////////////////////////////////////////////////////////////////////////
     472             : 
     473             : nsresult
     474           0 : LookupCacheV4::WriteMetadata(TableUpdateV4* aTableUpdate)
     475             : {
     476           0 :   NS_ENSURE_ARG_POINTER(aTableUpdate);
     477           0 :   if (nsUrlClassifierDBService::ShutdownHasStarted()) {
     478           0 :     return NS_ERROR_ABORT;
     479             :   }
     480             : 
     481           0 :   nsCOMPtr<nsIFile> metaFile;
     482           0 :   nsresult rv = mStoreDirectory->Clone(getter_AddRefs(metaFile));
     483           0 :   NS_ENSURE_SUCCESS(rv, rv);
     484             : 
     485           0 :   rv = metaFile->AppendNative(mTableName + METADATA_SUFFIX);
     486           0 :   NS_ENSURE_SUCCESS(rv, rv);
     487             : 
     488           0 :   nsCOMPtr<nsIOutputStream> outputStream;
     489           0 :   rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), metaFile,
     490           0 :                                    PR_WRONLY | PR_TRUNCATE | PR_CREATE_FILE);
     491           0 :   if (!NS_SUCCEEDED(rv)) {
     492           0 :     LOG(("Unable to create file to store metadata."));
     493           0 :     return rv;
     494             :   }
     495             : 
     496             :   // Write the state.
     497           0 :   rv = WriteValue(outputStream, aTableUpdate->ClientState());
     498           0 :   if (NS_FAILED(rv)) {
     499           0 :     LOG(("Failed to write the list state."));
     500           0 :     return rv;
     501             :   }
     502             : 
     503             :   // Write the checksum.
     504           0 :   rv = WriteValue(outputStream, aTableUpdate->Checksum());
     505           0 :   if (NS_FAILED(rv)) {
     506           0 :     LOG(("Failed to write the list checksum."));
     507           0 :     return rv;
     508             :   }
     509             : 
     510           0 :   return rv;
     511             : }
     512             : 
     513             : nsresult
     514           0 : LookupCacheV4::LoadMetadata(nsACString& aState, nsACString& aChecksum)
     515             : {
     516           0 :   nsCOMPtr<nsIFile> metaFile;
     517           0 :   nsresult rv = mStoreDirectory->Clone(getter_AddRefs(metaFile));
     518           0 :   NS_ENSURE_SUCCESS(rv, rv);
     519             : 
     520           0 :   rv = metaFile->AppendNative(mTableName + METADATA_SUFFIX);
     521           0 :   NS_ENSURE_SUCCESS(rv, rv);
     522             : 
     523           0 :   nsCOMPtr<nsIInputStream> localInFile;
     524           0 :   rv = NS_NewLocalFileInputStream(getter_AddRefs(localInFile), metaFile,
     525           0 :                                   PR_RDONLY | nsIFile::OS_READAHEAD);
     526           0 :   if (NS_FAILED(rv)) {
     527           0 :     LOG(("Unable to open metadata file."));
     528           0 :     return rv;
     529             :   }
     530             : 
     531             :   // Read the list state.
     532           0 :   rv = ReadValue(localInFile, aState);
     533           0 :   if (NS_FAILED(rv)) {
     534           0 :     LOG(("Failed to read state."));
     535           0 :     return rv;
     536             :   }
     537             : 
     538             :   // Read the checksum.
     539           0 :   rv = ReadValue(localInFile, aChecksum);
     540           0 :   if (NS_FAILED(rv)) {
     541           0 :     LOG(("Failed to read checksum."));
     542           0 :     return rv;
     543             :   }
     544             : 
     545           0 :   return rv;
     546             : }
     547             : 
     548           0 : VLPrefixSet::VLPrefixSet(const PrefixStringMap& aMap)
     549           0 :   : mCount(0)
     550             : {
     551           0 :   for (auto iter = aMap.ConstIter(); !iter.Done(); iter.Next()) {
     552           0 :     uint32_t size = iter.Key();
     553           0 :     mMap.Put(size, new PrefixString(*iter.Data(), size));
     554           0 :     mCount += iter.Data()->Length() / size;
     555             :   }
     556           0 : }
     557             : 
     558           0 : VLPrefixSet::VLPrefixSet(const TableUpdateV4::PrefixStdStringMap& aMap)
     559           0 :   : mCount(0)
     560             : {
     561           0 :   for (auto iter = aMap.ConstIter(); !iter.Done(); iter.Next()) {
     562           0 :     uint32_t size = iter.Key();
     563           0 :     mMap.Put(size, new PrefixString(iter.Data()->GetPrefixString(), size));
     564           0 :     mCount += iter.Data()->GetPrefixString().Length() / size;
     565             :   }
     566           0 : }
     567             : 
     568             : void
     569           0 : VLPrefixSet::Merge(PrefixStringMap& aPrefixMap) {
     570           0 :   for (auto iter = mMap.ConstIter(); !iter.Done(); iter.Next()) {
     571           0 :     nsCString* prefixString = aPrefixMap.LookupOrAdd(iter.Key());
     572           0 :     PrefixString* str = iter.Data();
     573             : 
     574           0 :     if (str->get()) {
     575           0 :       prefixString->Append(str->get(), str->remaining());
     576             :     }
     577             :   }
     578           0 : }
     579             : 
     580             : bool
     581           0 : VLPrefixSet::GetSmallestPrefix(nsDependentCSubstring& aOutString) {
     582           0 :   PrefixString* pick = nullptr;
     583           0 :   for (auto iter = mMap.ConstIter(); !iter.Done(); iter.Next()) {
     584           0 :     PrefixString* str = iter.Data();
     585             : 
     586           0 :     if (!str->get()) {
     587           0 :       continue;
     588             :     }
     589             : 
     590           0 :     if (aOutString.IsEmpty()) {
     591           0 :       aOutString.Rebind(str->get(), iter.Key());
     592           0 :       pick = str;
     593           0 :       continue;
     594             :     }
     595             : 
     596           0 :     nsDependentCSubstring cur(str->get(), iter.Key());
     597           0 :     if (cur < aOutString) {
     598           0 :       aOutString.Rebind(str->get(), iter.Key());
     599           0 :       pick = str;
     600             :     }
     601             :   }
     602             : 
     603           0 :   if (pick) {
     604           0 :     pick->next();
     605             :   }
     606             : 
     607           0 :   return pick != nullptr;
     608             : }
     609             : 
     610             : } // namespace safebrowsing
     611             : } // namespace mozilla

Generated by: LCOV version 1.13