toolkit/components/places/tests/cpp/places_test_harness.h

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 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "TestHarness.h"
     8 #include "nsMemory.h"
     9 #include "nsThreadUtils.h"
    10 #include "nsNetUtil.h"
    11 #include "nsDocShellCID.h"
    13 #include "nsToolkitCompsCID.h"
    14 #include "nsINavHistoryService.h"
    15 #include "nsIObserverService.h"
    16 #include "mozilla/IHistory.h"
    17 #include "mozIStorageConnection.h"
    18 #include "mozIStorageStatement.h"
    19 #include "mozIStorageAsyncStatement.h"
    20 #include "mozIStorageStatementCallback.h"
    21 #include "mozIStoragePendingStatement.h"
    22 #include "nsPIPlacesDatabase.h"
    23 #include "nsIObserver.h"
    24 #include "prinrval.h"
    25 #include "mozilla/Attributes.h"
    27 #define WAITFORTOPIC_TIMEOUT_SECONDS 5
    30 static size_t gTotalTests = 0;
    31 static size_t gPassedTests = 0;
    33 #define do_check_true(aCondition) \
    34   PR_BEGIN_MACRO \
    35     gTotalTests++; \
    36     if (aCondition) { \
    37       gPassedTests++; \
    38     } else { \
    39       fail("%s | Expected true, got false at line %d", __FILE__, __LINE__); \
    40     } \
    41   PR_END_MACRO
    43 #define do_check_false(aCondition) \
    44   PR_BEGIN_MACRO \
    45     gTotalTests++; \
    46     if (!aCondition) { \
    47       gPassedTests++; \
    48     } else { \
    49       fail("%s | Expected false, got true at line %d", __FILE__, __LINE__); \
    50     } \
    51   PR_END_MACRO
    53 #define do_check_success(aResult) \
    54   do_check_true(NS_SUCCEEDED(aResult))
    56 #ifdef LINUX
    57 // XXX Linux opt builds on tinderbox are orange due to linking with stdlib.
    58 // This is sad and annoying, but it's a workaround that works.
    59 #define do_check_eq(aExpected, aActual) \
    60   do_check_true(aExpected == aActual)
    61 #else
    62 #include <sstream>
    64 #define do_check_eq(aActual, aExpected) \
    65   PR_BEGIN_MACRO \
    66     gTotalTests++; \
    67     if (aExpected == aActual) { \
    68       gPassedTests++; \
    69     } else { \
    70       std::ostringstream temp; \
    71       temp << __FILE__ << " | Expected '" << aExpected << "', got '"; \
    72       temp << aActual <<"' at line " << __LINE__; \
    73       fail(temp.str().c_str()); \
    74     } \
    75   PR_END_MACRO
    76 #endif
    78 struct Test
    79 {
    80   void (*func)(void);
    81   const char* const name;
    82 };
    83 #define TEST(aName) \
    84   {aName, #aName}
    86 /**
    87  * Runs the next text.
    88  */
    89 void run_next_test();
    91 /**
    92  * To be used around asynchronous work.
    93  */
    94 void do_test_pending();
    95 void do_test_finished();
    97 /**
    98  * Spins current thread until a topic is received.
    99  */
   100 class WaitForTopicSpinner MOZ_FINAL : public nsIObserver
   101 {
   102 public:
   103   NS_DECL_ISUPPORTS
   105   WaitForTopicSpinner(const char* const aTopic)
   106   : mTopicReceived(false)
   107   , mStartTime(PR_IntervalNow())
   108   {
   109     nsCOMPtr<nsIObserverService> observerService =
   110       do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
   111     do_check_true(observerService);
   112     (void)observerService->AddObserver(this, aTopic, false);
   113   }
   115   void Spin() {
   116     while (!mTopicReceived) {
   117       if ((PR_IntervalNow() - mStartTime) > (WAITFORTOPIC_TIMEOUT_SECONDS * PR_USEC_PER_SEC)) {
   118         // Timed out waiting for the topic.
   119         do_check_true(false);
   120         break;
   121       }
   122       (void)NS_ProcessNextEvent();
   123     }
   124   }
   126   NS_IMETHOD Observe(nsISupports* aSubject,
   127                      const char* aTopic,
   128                      const char16_t* aData)
   129   {
   130     mTopicReceived = true;
   131     nsCOMPtr<nsIObserverService> observerService =
   132       do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
   133     do_check_true(observerService);
   134     (void)observerService->RemoveObserver(this, aTopic);
   135     return NS_OK;
   136   }
   138 private:
   139   bool mTopicReceived;
   140   PRIntervalTime mStartTime;
   141 };
   142 NS_IMPL_ISUPPORTS(
   143   WaitForTopicSpinner,
   144   nsIObserver
   145 )
   147 /**
   148  * Spins current thread until an async statement is executed.
   149  */
   150 class AsyncStatementSpinner MOZ_FINAL : public mozIStorageStatementCallback
   151 {
   152 public:
   153   NS_DECL_ISUPPORTS
   154   NS_DECL_MOZISTORAGESTATEMENTCALLBACK
   156   AsyncStatementSpinner();
   157   void SpinUntilCompleted();
   158   uint16_t completionReason;
   160 protected:
   161   volatile bool mCompleted;
   162 };
   164 NS_IMPL_ISUPPORTS(AsyncStatementSpinner,
   165                   mozIStorageStatementCallback)
   167 AsyncStatementSpinner::AsyncStatementSpinner()
   168 : completionReason(0)
   169 , mCompleted(false)
   170 {
   171 }
   173 NS_IMETHODIMP
   174 AsyncStatementSpinner::HandleResult(mozIStorageResultSet *aResultSet)
   175 {
   176   return NS_OK;
   177 }
   179 NS_IMETHODIMP
   180 AsyncStatementSpinner::HandleError(mozIStorageError *aError)
   181 {
   182   return NS_OK;
   183 }
   185 NS_IMETHODIMP
   186 AsyncStatementSpinner::HandleCompletion(uint16_t aReason)
   187 {
   188   completionReason = aReason;
   189   mCompleted = true;
   190   return NS_OK;
   191 }
   193 void AsyncStatementSpinner::SpinUntilCompleted()
   194 {
   195   nsCOMPtr<nsIThread> thread(::do_GetCurrentThread());
   196   nsresult rv = NS_OK;
   197   bool processed = true;
   198   while (!mCompleted && NS_SUCCEEDED(rv)) {
   199     rv = thread->ProcessNextEvent(true, &processed);
   200   }
   201 }
   203 struct PlaceRecord
   204 {
   205   int64_t id;
   206   int32_t hidden;
   207   int32_t typed;
   208   int32_t visitCount;
   209   nsCString guid;
   210 };
   212 struct VisitRecord
   213 {
   214   int64_t id;
   215   int64_t lastVisitId;
   216   int32_t transitionType;
   217 };
   219 already_AddRefed<mozilla::IHistory>
   220 do_get_IHistory()
   221 {
   222   nsCOMPtr<mozilla::IHistory> history = do_GetService(NS_IHISTORY_CONTRACTID);
   223   do_check_true(history);
   224   return history.forget();
   225 }
   227 already_AddRefed<nsINavHistoryService>
   228 do_get_NavHistory()
   229 {
   230   nsCOMPtr<nsINavHistoryService> serv =
   231     do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID);
   232   do_check_true(serv);
   233   return serv.forget();
   234 }
   236 already_AddRefed<mozIStorageConnection>
   237 do_get_db()
   238 {
   239   nsCOMPtr<nsINavHistoryService> history = do_get_NavHistory();
   240   nsCOMPtr<nsPIPlacesDatabase> database = do_QueryInterface(history);
   241   do_check_true(database);
   243   nsCOMPtr<mozIStorageConnection> dbConn;
   244   nsresult rv = database->GetDBConnection(getter_AddRefs(dbConn));
   245   do_check_success(rv);
   246   return dbConn.forget();
   247 }
   249 /**
   250  * Get the place record from the database.
   251  *
   252  * @param aURI The unique URI of the place we are looking up
   253  * @param result Out parameter where the result is stored
   254  */
   255 void
   256 do_get_place(nsIURI* aURI, PlaceRecord& result)
   257 {
   258   nsCOMPtr<mozIStorageConnection> dbConn = do_get_db();
   259   nsCOMPtr<mozIStorageStatement> stmt;
   261   nsCString spec;
   262   nsresult rv = aURI->GetSpec(spec);
   263   do_check_success(rv);
   265   rv = dbConn->CreateStatement(NS_LITERAL_CSTRING(
   266     "SELECT id, hidden, typed, visit_count, guid FROM moz_places "
   267     "WHERE url=?1 "
   268   ), getter_AddRefs(stmt));
   269   do_check_success(rv);
   271   rv = stmt->BindUTF8StringByIndex(0, spec);
   272   do_check_success(rv);
   274   bool hasResults;
   275   rv = stmt->ExecuteStep(&hasResults);
   276   do_check_success(rv);
   277   if (!hasResults) {
   278     result.id = 0;
   279     return;
   280   }
   282   rv = stmt->GetInt64(0, &result.id);
   283   do_check_success(rv);
   284   rv = stmt->GetInt32(1, &result.hidden);
   285   do_check_success(rv);
   286   rv = stmt->GetInt32(2, &result.typed);
   287   do_check_success(rv);
   288   rv = stmt->GetInt32(3, &result.visitCount);
   289   do_check_success(rv);
   290   rv = stmt->GetUTF8String(4, result.guid);
   291   do_check_success(rv);
   292 }
   294 /**
   295  * Gets the most recent visit to a place.
   296  *
   297  * @param placeID ID from the moz_places table
   298  * @param result Out parameter where visit is stored
   299  */
   300 void
   301 do_get_lastVisit(int64_t placeId, VisitRecord& result)
   302 {
   303   nsCOMPtr<mozIStorageConnection> dbConn = do_get_db();
   304   nsCOMPtr<mozIStorageStatement> stmt;
   306   nsresult rv = dbConn->CreateStatement(NS_LITERAL_CSTRING(
   307     "SELECT id, from_visit, visit_type FROM moz_historyvisits "
   308     "WHERE place_id=?1 "
   309     "LIMIT 1"
   310   ), getter_AddRefs(stmt));
   311   do_check_success(rv);
   313   rv = stmt->BindInt64ByIndex(0, placeId);
   314   do_check_success(rv);
   316   bool hasResults;
   317   rv = stmt->ExecuteStep(&hasResults);
   318   do_check_success(rv);
   320   if (!hasResults) {
   321     result.id = 0;
   322     return;
   323   }
   325   rv = stmt->GetInt64(0, &result.id);
   326   do_check_success(rv);
   327   rv = stmt->GetInt64(1, &result.lastVisitId);
   328   do_check_success(rv);
   329   rv = stmt->GetInt32(2, &result.transitionType);
   330   do_check_success(rv);
   331 }
   333 void
   334 do_wait_async_updates() {
   335   nsCOMPtr<mozIStorageConnection> db = do_get_db();
   336   nsCOMPtr<mozIStorageAsyncStatement> stmt;
   338   db->CreateAsyncStatement(NS_LITERAL_CSTRING("BEGIN EXCLUSIVE"),
   339                            getter_AddRefs(stmt));
   340   nsCOMPtr<mozIStoragePendingStatement> pending;
   341   (void)stmt->ExecuteAsync(nullptr, getter_AddRefs(pending));
   343   db->CreateAsyncStatement(NS_LITERAL_CSTRING("COMMIT"),
   344                            getter_AddRefs(stmt));
   345   nsRefPtr<AsyncStatementSpinner> spinner = new AsyncStatementSpinner();
   346   (void)stmt->ExecuteAsync(spinner, getter_AddRefs(pending));
   348   spinner->SpinUntilCompleted();
   349 }
   351 /**
   352  * Adds a URI to the database.
   353  *
   354  * @param aURI
   355  *        The URI to add to the database.
   356  */
   357 void
   358 addURI(nsIURI* aURI)
   359 {
   360   nsCOMPtr<mozilla::IHistory> history = do_GetService(NS_IHISTORY_CONTRACTID);
   361   do_check_true(history);
   362   nsresult rv = history->VisitURI(aURI, nullptr, mozilla::IHistory::TOP_LEVEL);
   363   do_check_success(rv);
   365   do_wait_async_updates();
   366 }
   368 static const char TOPIC_PROFILE_CHANGE[] = "profile-before-change";
   369 static const char TOPIC_PLACES_CONNECTION_CLOSED[] = "places-connection-closed";
   371 class WaitForConnectionClosed MOZ_FINAL : public nsIObserver
   372 {
   373   nsRefPtr<WaitForTopicSpinner> mSpinner;
   374 public:
   375   NS_DECL_ISUPPORTS
   377   WaitForConnectionClosed()
   378   {
   379     nsCOMPtr<nsIObserverService> os =
   380       do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
   381     MOZ_ASSERT(os);
   382     if (os) {
   383       MOZ_ALWAYS_TRUE(NS_SUCCEEDED(os->AddObserver(this, TOPIC_PROFILE_CHANGE, false)));
   384     }
   385     mSpinner = new WaitForTopicSpinner(TOPIC_PLACES_CONNECTION_CLOSED);
   386   }
   388   NS_IMETHOD Observe(nsISupports* aSubject,
   389                      const char* aTopic,
   390                      const char16_t* aData)
   391   {
   392     nsCOMPtr<nsIObserverService> os =
   393       do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
   394     MOZ_ASSERT(os);
   395     if (os) {
   396       MOZ_ALWAYS_TRUE(NS_SUCCEEDED(os->RemoveObserver(this, aTopic)));
   397     }
   399     mSpinner->Spin();
   401     return NS_OK;
   402   }
   403 };
   405 NS_IMPL_ISUPPORTS(WaitForConnectionClosed, nsIObserver)

mercurial