toolkit/components/places/Helpers.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
     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/. */
     6 #include "Helpers.h"
     7 #include "mozIStorageError.h"
     8 #include "plbase64.h"
     9 #include "prio.h"
    10 #include "nsString.h"
    11 #include "nsNavHistory.h"
    12 #include "mozilla/Services.h"
    14 // The length of guids that are used by history and bookmarks.
    15 #define GUID_LENGTH 12
    17 namespace mozilla {
    18 namespace places {
    20 ////////////////////////////////////////////////////////////////////////////////
    21 //// AsyncStatementCallback
    23 NS_IMPL_ISUPPORTS(
    24   AsyncStatementCallback
    25 , mozIStorageStatementCallback
    26 )
    28 NS_IMETHODIMP
    29 AsyncStatementCallback::HandleResult(mozIStorageResultSet *aResultSet)
    30 {
    31   NS_ABORT_IF_FALSE(false, "Was not expecting a resultset, but got it.");
    32   return NS_OK;
    33 }
    35 NS_IMETHODIMP
    36 AsyncStatementCallback::HandleCompletion(uint16_t aReason)
    37 {
    38   return NS_OK;
    39 }
    41 NS_IMETHODIMP
    42 AsyncStatementCallback::HandleError(mozIStorageError *aError)
    43 {
    44 #ifdef DEBUG
    45   int32_t result;
    46   nsresult rv = aError->GetResult(&result);
    47   NS_ENSURE_SUCCESS(rv, rv);
    48   nsAutoCString message;
    49   rv = aError->GetMessage(message);
    50   NS_ENSURE_SUCCESS(rv, rv);
    52   nsAutoCString warnMsg;
    53   warnMsg.Append("An error occurred while executing an async statement: ");
    54   warnMsg.AppendInt(result);
    55   warnMsg.Append(" ");
    56   warnMsg.Append(message);
    57   NS_WARNING(warnMsg.get());
    58 #endif
    60   return NS_OK;
    61 }
    63 #define URI_TO_URLCSTRING(uri, spec) \
    64   nsAutoCString spec; \
    65   if (NS_FAILED(aURI->GetSpec(spec))) { \
    66     return NS_ERROR_UNEXPECTED; \
    67   }
    69 // Bind URI to statement by index.
    70 nsresult // static
    71 URIBinder::Bind(mozIStorageStatement* aStatement,
    72                 int32_t aIndex,
    73                 nsIURI* aURI)
    74 {
    75   NS_ASSERTION(aStatement, "Must have non-null statement");
    76   NS_ASSERTION(aURI, "Must have non-null uri");
    78   URI_TO_URLCSTRING(aURI, spec);
    79   return URIBinder::Bind(aStatement, aIndex, spec);
    80 }
    82 // Statement URLCString to statement by index.
    83 nsresult // static
    84 URIBinder::Bind(mozIStorageStatement* aStatement,
    85                 int32_t index,
    86                 const nsACString& aURLString)
    87 {
    88   NS_ASSERTION(aStatement, "Must have non-null statement");
    89   return aStatement->BindUTF8StringByIndex(
    90     index, StringHead(aURLString, URI_LENGTH_MAX)
    91   );
    92 }
    94 // Bind URI to statement by name.
    95 nsresult // static
    96 URIBinder::Bind(mozIStorageStatement* aStatement,
    97                 const nsACString& aName,
    98                 nsIURI* aURI)
    99 {
   100   NS_ASSERTION(aStatement, "Must have non-null statement");
   101   NS_ASSERTION(aURI, "Must have non-null uri");
   103   URI_TO_URLCSTRING(aURI, spec);
   104   return URIBinder::Bind(aStatement, aName, spec);
   105 }
   107 // Bind URLCString to statement by name.
   108 nsresult // static
   109 URIBinder::Bind(mozIStorageStatement* aStatement,
   110                 const nsACString& aName,
   111                 const nsACString& aURLString)
   112 {
   113   NS_ASSERTION(aStatement, "Must have non-null statement");
   114   return aStatement->BindUTF8StringByName(
   115     aName, StringHead(aURLString, URI_LENGTH_MAX)
   116   );
   117 }
   119 // Bind URI to params by index.
   120 nsresult // static
   121 URIBinder::Bind(mozIStorageBindingParams* aParams,
   122                 int32_t aIndex,
   123                 nsIURI* aURI)
   124 {
   125   NS_ASSERTION(aParams, "Must have non-null statement");
   126   NS_ASSERTION(aURI, "Must have non-null uri");
   128   URI_TO_URLCSTRING(aURI, spec);
   129   return URIBinder::Bind(aParams, aIndex, spec);
   130 }
   132 // Bind URLCString to params by index.
   133 nsresult // static
   134 URIBinder::Bind(mozIStorageBindingParams* aParams,
   135                 int32_t index,
   136                 const nsACString& aURLString)
   137 {
   138   NS_ASSERTION(aParams, "Must have non-null statement");
   139   return aParams->BindUTF8StringByIndex(
   140     index, StringHead(aURLString, URI_LENGTH_MAX)
   141   );
   142 }
   144 // Bind URI to params by name.
   145 nsresult // static
   146 URIBinder::Bind(mozIStorageBindingParams* aParams,
   147                 const nsACString& aName,
   148                 nsIURI* aURI)
   149 {
   150   NS_ASSERTION(aParams, "Must have non-null params array");
   151   NS_ASSERTION(aURI, "Must have non-null uri");
   153   URI_TO_URLCSTRING(aURI, spec);
   154   return URIBinder::Bind(aParams, aName, spec);
   155 }
   157 // Bind URLCString to params by name.
   158 nsresult // static
   159 URIBinder::Bind(mozIStorageBindingParams* aParams,
   160                 const nsACString& aName,
   161                 const nsACString& aURLString)
   162 {
   163   NS_ASSERTION(aParams, "Must have non-null params array");
   165   nsresult rv = aParams->BindUTF8StringByName(
   166     aName, StringHead(aURLString, URI_LENGTH_MAX)
   167   );
   168   NS_ENSURE_SUCCESS(rv, rv);
   169   return NS_OK;
   170 }
   172 #undef URI_TO_URLCSTRING
   174 nsresult
   175 GetReversedHostname(nsIURI* aURI, nsString& aRevHost)
   176 {
   177   nsAutoCString forward8;
   178   nsresult rv = aURI->GetHost(forward8);
   179   // Not all URIs have a host.
   180   if (NS_FAILED(rv))
   181     return rv;
   183   // can't do reversing in UTF8, better use 16-bit chars
   184   GetReversedHostname(NS_ConvertUTF8toUTF16(forward8), aRevHost);
   185   return NS_OK;
   186 }
   188 void
   189 GetReversedHostname(const nsString& aForward, nsString& aRevHost)
   190 {
   191   ReverseString(aForward, aRevHost);
   192   aRevHost.Append(char16_t('.'));
   193 }
   195 void
   196 ReverseString(const nsString& aInput, nsString& aReversed)
   197 {
   198   aReversed.Truncate(0);
   199   for (int32_t i = aInput.Length() - 1; i >= 0; i--) {
   200     aReversed.Append(aInput[i]);
   201   }
   202 }
   204 static
   205 nsresult
   206 Base64urlEncode(const uint8_t* aBytes,
   207                 uint32_t aNumBytes,
   208                 nsCString& _result)
   209 {
   210   // SetLength does not set aside space for null termination.  PL_Base64Encode
   211   // will not null terminate, however, nsCStrings must be null terminated.  As a
   212   // result, we set the capacity to be one greater than what we need, and the
   213   // length to our desired length.
   214   uint32_t length = (aNumBytes + 2) / 3 * 4; // +2 due to integer math.
   215   NS_ENSURE_TRUE(_result.SetCapacity(length + 1, fallible_t()),
   216                  NS_ERROR_OUT_OF_MEMORY);
   217   _result.SetLength(length);
   218   (void)PL_Base64Encode(reinterpret_cast<const char*>(aBytes), aNumBytes,
   219                         _result.BeginWriting());
   221   // base64url encoding is defined in RFC 4648.  It replaces the last two
   222   // alphabet characters of base64 encoding with '-' and '_' respectively.
   223   _result.ReplaceChar('+', '-');
   224   _result.ReplaceChar('/', '_');
   225   return NS_OK;
   226 }
   228 #ifdef XP_WIN
   229 } // namespace places
   230 } // namespace mozilla
   232 // Included here because windows.h conflicts with the use of mozIStorageError
   233 // above, but make sure that these are not included inside mozilla::places.
   234 #include <windows.h>
   235 #include <wincrypt.h>
   237 namespace mozilla {
   238 namespace places {
   239 #endif
   241 static
   242 nsresult
   243 GenerateRandomBytes(uint32_t aSize,
   244                     uint8_t* _buffer)
   245 {
   246   // On Windows, we'll use its built-in cryptographic API.
   247 #if defined(XP_WIN)
   248   HCRYPTPROV cryptoProvider;
   249   BOOL rc = CryptAcquireContext(&cryptoProvider, 0, 0, PROV_RSA_FULL,
   250                                 CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
   251   if (rc) {
   252     rc = CryptGenRandom(cryptoProvider, aSize, _buffer);
   253     (void)CryptReleaseContext(cryptoProvider, 0);
   254   }
   255   return rc ? NS_OK : NS_ERROR_FAILURE;
   257   // On Unix, we'll just read in from /dev/urandom.
   258 #elif defined(XP_UNIX)
   259   NS_ENSURE_ARG_MAX(aSize, INT32_MAX);
   260   PRFileDesc* urandom = PR_Open("/dev/urandom", PR_RDONLY, 0);
   261   nsresult rv = NS_ERROR_FAILURE;
   262   if (urandom) {
   263     int32_t bytesRead = PR_Read(urandom, _buffer, aSize);
   264     if (bytesRead == static_cast<int32_t>(aSize)) {
   265       rv = NS_OK;
   266     }
   267     (void)PR_Close(urandom);
   268   }
   269   return rv;
   270 #endif
   271 }
   273 nsresult
   274 GenerateGUID(nsCString& _guid)
   275 {
   276   _guid.Truncate();
   278   // Request raw random bytes and base64url encode them.  For each set of three
   279   // bytes, we get one character.
   280   const uint32_t kRequiredBytesLength =
   281     static_cast<uint32_t>(GUID_LENGTH / 4 * 3);
   283   uint8_t buffer[kRequiredBytesLength];
   284   nsresult rv = GenerateRandomBytes(kRequiredBytesLength, buffer);
   285   NS_ENSURE_SUCCESS(rv, rv);
   287   rv = Base64urlEncode(buffer, kRequiredBytesLength, _guid);
   288   NS_ENSURE_SUCCESS(rv, rv);
   290   NS_ASSERTION(_guid.Length() == GUID_LENGTH, "GUID is not the right size!");
   291   return NS_OK;
   292 }
   294 bool
   295 IsValidGUID(const nsACString& aGUID)
   296 {
   297   nsCString::size_type len = aGUID.Length();
   298   if (len != GUID_LENGTH) {
   299     return false;
   300   }
   302   for (nsCString::size_type i = 0; i < len; i++ ) {
   303     char c = aGUID[i];
   304     if ((c >= 'a' && c <= 'z') || // a-z
   305         (c >= 'A' && c <= 'Z') || // A-Z
   306         (c >= '0' && c <= '9') || // 0-9
   307         c == '-' || c == '_') { // - or _
   308       continue;
   309     }
   310     return false;
   311   }
   312   return true;
   313 }
   315 void
   316 TruncateTitle(const nsACString& aTitle, nsACString& aTrimmed)
   317 {
   318   aTrimmed = aTitle;
   319   if (aTitle.Length() > TITLE_LENGTH_MAX) {
   320     aTrimmed = StringHead(aTitle, TITLE_LENGTH_MAX);
   321   }
   322 }
   324 void
   325 ForceWALCheckpoint()
   326 {
   327   nsRefPtr<Database> DB = Database::GetDatabase();
   328   if (DB) {
   329     nsCOMPtr<mozIStorageAsyncStatement> stmt = DB->GetAsyncStatement(
   330       "pragma wal_checkpoint "
   331     );
   332     if (stmt) {
   333       nsCOMPtr<mozIStoragePendingStatement> handle;
   334       (void)stmt->ExecuteAsync(nullptr, getter_AddRefs(handle));
   335     }
   336   }
   337 }
   339 bool
   340 GetHiddenState(bool aIsRedirect,
   341                uint32_t aTransitionType)
   342 {
   343   return aTransitionType == nsINavHistoryService::TRANSITION_FRAMED_LINK ||
   344          aTransitionType == nsINavHistoryService::TRANSITION_EMBED ||
   345          aIsRedirect;
   346 }
   348 ////////////////////////////////////////////////////////////////////////////////
   349 //// PlacesEvent
   351 PlacesEvent::PlacesEvent(const char* aTopic)
   352 : mTopic(aTopic)
   353 {
   354 }
   356 NS_IMETHODIMP
   357 PlacesEvent::Run()
   358 {
   359   Notify();
   360   return NS_OK;
   361 }
   363 void
   364 PlacesEvent::Notify()
   365 {
   366   NS_ASSERTION(NS_IsMainThread(), "Must only be used on the main thread!");
   367   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   368   if (obs) {
   369     (void)obs->NotifyObservers(nullptr, mTopic, nullptr);
   370   }
   371 }
   373 NS_IMPL_ISUPPORTS(
   374   PlacesEvent
   375 , nsIRunnable
   376 )
   378 ////////////////////////////////////////////////////////////////////////////////
   379 //// AsyncStatementCallbackNotifier
   381 NS_IMETHODIMP
   382 AsyncStatementCallbackNotifier::HandleCompletion(uint16_t aReason)
   383 {
   384   if (aReason != mozIStorageStatementCallback::REASON_FINISHED)
   385     return NS_ERROR_UNEXPECTED;
   387   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   388   if (obs) {
   389     (void)obs->NotifyObservers(nullptr, mTopic, nullptr);
   390   }
   392   return NS_OK;
   393 }
   395 ////////////////////////////////////////////////////////////////////////////////
   396 //// AsyncStatementCallbackNotifier
   398 NS_IMETHODIMP
   399 AsyncStatementTelemetryTimer::HandleCompletion(uint16_t aReason)
   400 {
   401   if (aReason == mozIStorageStatementCallback::REASON_FINISHED) {
   402     Telemetry::AccumulateTimeDelta(mHistogramId, mStart);
   403   }
   404   return NS_OK;
   405 }
   407 } // namespace places
   408 } // namespace mozilla

mercurial