tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestReadWrite.cpp (44852B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      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 file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "gtest/gtest.h"
      8 #include "mozilla/BasePrincipal.h"
      9 #include "mozilla/UniquePtr.h"
     10 #include "mozilla/dom/ServiceWorkerRegistrar.h"
     11 #include "mozilla/dom/ServiceWorkerRegistrarTypes.h"
     12 #include "mozilla/ipc/PBackgroundSharedTypes.h"
     13 #include "nsAppDirectoryServiceDefs.h"
     14 #include "nsIFile.h"
     15 #include "nsIOutputStream.h"
     16 #include "nsIServiceWorkerManager.h"
     17 #include "nsNetUtil.h"
     18 #include "nsPrintfCString.h"
     19 #include "prtime.h"
     20 
     21 using namespace mozilla::dom;
     22 using namespace mozilla::ipc;
     23 
     24 namespace {
     25 
     26 struct HandlerStats {
     27  uint32_t swLoadCount;
     28  uint32_t swUpdatedCount;
     29  uint32_t swUnregisteredCount;
     30  nsCString lastValue;
     31 
     32  uint32_t swLoad2Count;
     33  uint32_t swUpdated2Count;
     34  uint32_t swUnregistered2Count;
     35  nsCString lastValue2;
     36 };
     37 
     38 constinit mozilla::UniquePtr<HandlerStats> gHandlerStats;
     39 
     40 void MaybeCreateHandlerStats() {
     41  if (!gHandlerStats) {
     42    gHandlerStats.reset(new HandlerStats());
     43  }
     44 }
     45 
     46 void swLoaded(const ServiceWorkerRegistrationData& data,
     47              const nsACString& aValue) {
     48  MaybeCreateHandlerStats();
     49  gHandlerStats->swLoadCount++;
     50  gHandlerStats->lastValue = aValue;
     51 }
     52 
     53 void swUpdated(const ServiceWorkerRegistrationData& data) {
     54  MaybeCreateHandlerStats();
     55  gHandlerStats->swUpdatedCount++;
     56 }
     57 
     58 void swUnregistered(const ServiceWorkerRegistrationData& data) {
     59  MaybeCreateHandlerStats();
     60  gHandlerStats->swUnregisteredCount++;
     61 }
     62 
     63 void swLoaded2(const ServiceWorkerRegistrationData& data,
     64               const nsACString& aValue) {
     65  MaybeCreateHandlerStats();
     66  gHandlerStats->swLoad2Count++;
     67  gHandlerStats->lastValue2 = aValue;
     68 }
     69 
     70 void swUpdated2(const ServiceWorkerRegistrationData& data) {
     71  MaybeCreateHandlerStats();
     72  gHandlerStats->swUpdated2Count++;
     73 }
     74 
     75 void swUnregistered2(const ServiceWorkerRegistrationData& data) {
     76  MaybeCreateHandlerStats();
     77  gHandlerStats->swUnregistered2Count++;
     78 }
     79 
     80 }  // namespace
     81 
     82 class ServiceWorkerRegistrarTest : public ServiceWorkerRegistrar {
     83 public:
     84  ServiceWorkerRegistrarTest() {
     85    nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
     86                                         getter_AddRefs(mProfileDir));
     87    MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
     88    MOZ_RELEASE_ASSERT(mProfileDir);
     89 
     90    mExpandoHandlers.AppendElement(ExpandoHandler{
     91        nsCString("handler_test"), swLoaded, swUpdated, swUnregistered});
     92    mExpandoHandlers.AppendElement(ExpandoHandler{
     93        nsCString("handler_test2"), swLoaded2, swUpdated2, swUnregistered2});
     94  }
     95 
     96  nsresult TestReadData() { return ReadData(); }
     97  nsresult TestWriteData() MOZ_NO_THREAD_SAFETY_ANALYSIS {
     98    return WriteData(mData);
     99  }
    100  void TestDeleteData() { DeleteData(); }
    101 
    102  void TestRegisterServiceWorker(const ServiceWorkerRegistrationData& aData) {
    103    mozilla::MonitorAutoLock lock(mMonitor);
    104    RegisterServiceWorkerInternal(aData);
    105  }
    106 
    107  nsTArray<ServiceWorkerData>& TestGetData() MOZ_NO_THREAD_SAFETY_ANALYSIS {
    108    return mData;
    109  }
    110 };
    111 
    112 already_AddRefed<nsIFile> GetFile() {
    113  nsCOMPtr<nsIFile> file;
    114  nsresult rv =
    115      NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(file));
    116  if (NS_WARN_IF(NS_FAILED(rv))) {
    117    return nullptr;
    118  }
    119 
    120  file->Append(nsLiteralString(SERVICEWORKERREGISTRAR_FILE));
    121  return file.forget();
    122 }
    123 
    124 bool CreateFile(const nsACString& aData) {
    125  nsCOMPtr<nsIFile> file = GetFile();
    126 
    127  nsCOMPtr<nsIOutputStream> stream;
    128  nsresult rv = NS_NewLocalFileOutputStream(getter_AddRefs(stream), file);
    129  if (NS_WARN_IF(NS_FAILED(rv))) {
    130    return false;
    131  }
    132 
    133  uint32_t count;
    134  rv = stream->Write(aData.Data(), aData.Length(), &count);
    135  if (NS_WARN_IF(NS_FAILED(rv))) {
    136    return false;
    137  }
    138 
    139  if (count != aData.Length()) {
    140    return false;
    141  }
    142 
    143  return true;
    144 }
    145 
    146 TEST(ServiceWorkerRegistrar, TestNoFile)
    147 {
    148  nsCOMPtr<nsIFile> file = GetFile();
    149  ASSERT_TRUE(file)
    150  << "GetFile must return a nsIFIle";
    151 
    152  bool exists;
    153  nsresult rv = file->Exists(&exists);
    154  ASSERT_EQ(NS_OK, rv) << "nsIFile::Exists cannot fail";
    155 
    156  if (exists) {
    157    rv = file->Remove(false);
    158    ASSERT_EQ(NS_OK, rv) << "nsIFile::Remove cannot fail";
    159  }
    160 
    161  RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
    162 
    163  rv = swr->TestReadData();
    164  ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
    165 
    166  const nsTArray<ServiceWorkerRegistrar::ServiceWorkerData>& data =
    167      swr->TestGetData();
    168  ASSERT_EQ((uint32_t)0, data.Length())
    169      << "No data should be found in an empty file";
    170 }
    171 
    172 TEST(ServiceWorkerRegistrar, TestEmptyFile)
    173 {
    174  ASSERT_TRUE(CreateFile(""_ns))
    175  << "CreateFile should not fail";
    176 
    177  RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
    178 
    179  nsresult rv = swr->TestReadData();
    180  ASSERT_NE(NS_OK, rv) << "ReadData() should fail if the file is empty";
    181 
    182  const nsTArray<ServiceWorkerRegistrar::ServiceWorkerData>& data =
    183      swr->TestGetData();
    184  ASSERT_EQ((uint32_t)0, data.Length())
    185      << "No data should be found in an empty file";
    186 }
    187 
    188 TEST(ServiceWorkerRegistrar, TestRightVersionFile)
    189 {
    190  nsCString buffer;
    191  buffer.AppendInt(static_cast<uint32_t>(SERVICEWORKERREGISTRAR_VERSION));
    192  buffer.Append("\n");
    193 
    194  ASSERT_TRUE(CreateFile(buffer))
    195  << "CreateFile should not fail";
    196 
    197  RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
    198 
    199  nsresult rv = swr->TestReadData();
    200  ASSERT_EQ(NS_OK, rv)
    201      << "ReadData() should not fail when the version is correct";
    202 
    203  const nsTArray<ServiceWorkerRegistrar::ServiceWorkerData>& data =
    204      swr->TestGetData();
    205  ASSERT_EQ((uint32_t)0, data.Length())
    206      << "No data should be found in an empty file";
    207 }
    208 
    209 TEST(ServiceWorkerRegistrar, TestWrongVersionFile)
    210 {
    211  nsCString buffer;
    212  buffer.AppendInt(static_cast<uint32_t>(SERVICEWORKERREGISTRAR_VERSION));
    213  buffer.Append("bla\n");
    214 
    215  ASSERT_TRUE(CreateFile(buffer))
    216  << "CreateFile should not fail";
    217 
    218  RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
    219 
    220  nsresult rv = swr->TestReadData();
    221  ASSERT_NE(NS_OK, rv)
    222      << "ReadData() should fail when the version is not correct";
    223 
    224  const nsTArray<ServiceWorkerRegistrar::ServiceWorkerData>& data =
    225      swr->TestGetData();
    226  ASSERT_EQ((uint32_t)0, data.Length())
    227      << "No data should be found in an empty file";
    228 }
    229 
    230 TEST(ServiceWorkerRegistrar, TestReadData)
    231 {
    232  nsCString buffer;
    233  buffer.AppendInt(static_cast<uint32_t>(SERVICEWORKERREGISTRAR_VERSION));
    234  buffer.Append("\n");
    235 
    236  buffer.AppendLiteral("^inBrowser=1\n");
    237  buffer.AppendLiteral("https://scope_0.org\ncurrentWorkerURL 0\n");
    238  buffer.Append(SERVICEWORKERREGISTRAR_TRUE "\n");
    239  buffer.AppendLiteral("cacheName 0\n");
    240  buffer.AppendInt(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
    241                   16);
    242  buffer.AppendLiteral("\n");
    243  buffer.AppendInt(0);
    244  buffer.AppendLiteral("\n");
    245  buffer.AppendInt(0);
    246  buffer.AppendLiteral("\n");
    247  buffer.AppendInt(0);
    248  buffer.AppendLiteral("\n");
    249  buffer.AppendInt(0);
    250  buffer.AppendLiteral("\n");
    251  buffer.AppendLiteral("true\n");
    252  buffer.AppendInt(0);
    253  buffer.AppendLiteral("\n");
    254  buffer.AppendInt(0);
    255  buffer.AppendLiteral("\n");
    256  buffer.AppendInt(0);
    257  buffer.AppendLiteral("\n");
    258  buffer.AppendInt(0);
    259  buffer.AppendLiteral("\n");
    260  buffer.AppendInt(0);
    261  buffer.AppendLiteral("\n");
    262  buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    263 
    264  buffer.AppendLiteral("\n");
    265  buffer.AppendLiteral("https://scope_1.org\ncurrentWorkerURL 1\n");
    266  buffer.Append(SERVICEWORKERREGISTRAR_FALSE "\n");
    267  buffer.AppendLiteral("cacheName 1\n");
    268  buffer.AppendInt(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_ALL, 16);
    269  buffer.AppendLiteral("\n");
    270  PRTime ts = PR_Now();
    271  buffer.AppendInt(ts);
    272  buffer.AppendLiteral("\n");
    273  buffer.AppendInt(ts);
    274  buffer.AppendLiteral("\n");
    275  buffer.AppendInt(ts);
    276  buffer.AppendLiteral("\n");
    277  buffer.AppendInt(1);
    278  buffer.AppendLiteral("\n");
    279  buffer.AppendLiteral("false\n");
    280  buffer.AppendInt(0);
    281  buffer.AppendLiteral("\n");
    282  buffer.AppendInt(0);
    283  buffer.AppendLiteral("\n");
    284  buffer.AppendInt(0);
    285  buffer.AppendLiteral("\n");
    286  buffer.AppendInt(0);
    287  buffer.AppendLiteral("\n");
    288  buffer.AppendInt(0);
    289  buffer.AppendLiteral("\n");
    290  buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    291 
    292  ASSERT_TRUE(CreateFile(buffer))
    293  << "CreateFile should not fail";
    294 
    295  RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
    296 
    297  nsresult rv = swr->TestReadData();
    298  ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
    299 
    300  const nsTArray<ServiceWorkerRegistrar::ServiceWorkerData>& data =
    301      swr->TestGetData();
    302  ASSERT_EQ((uint32_t)2, data.Length()) << "2 entries should be found";
    303 
    304  const mozilla::ipc::PrincipalInfo& info0 = data[0].mRegistration.principal();
    305  ASSERT_EQ(info0.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo)
    306      << "First principal must be content";
    307  const mozilla::ipc::ContentPrincipalInfo& cInfo0 =
    308      data[0].mRegistration.principal();
    309 
    310  nsAutoCString suffix0;
    311  cInfo0.attrs().CreateSuffix(suffix0);
    312 
    313  ASSERT_STREQ("", suffix0.get());
    314  ASSERT_STREQ("https://scope_0.org", cInfo0.spec().get());
    315  ASSERT_STREQ("https://scope_0.org", data[0].mRegistration.scope().get());
    316  ASSERT_STREQ("currentWorkerURL 0",
    317               data[0].mRegistration.currentWorkerURL().get());
    318  ASSERT_TRUE(data[0].mRegistration.currentWorkerHandlesFetch());
    319  ASSERT_STREQ("cacheName 0",
    320               NS_ConvertUTF16toUTF8(data[0].mRegistration.cacheName()).get());
    321  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
    322            data[0].mRegistration.updateViaCache());
    323  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerInstalledTime());
    324  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerActivatedTime());
    325  ASSERT_EQ((int64_t)0, data[0].mRegistration.lastUpdateTime());
    326  ASSERT_EQ(false, data[0].mRegistration.navigationPreloadState().enabled());
    327  ASSERT_STREQ(
    328      "true",
    329      data[0].mRegistration.navigationPreloadState().headerValue().get());
    330 
    331  const mozilla::ipc::PrincipalInfo& info1 = data[1].mRegistration.principal();
    332  ASSERT_EQ(info1.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo)
    333      << "First principal must be content";
    334  const mozilla::ipc::ContentPrincipalInfo& cInfo1 =
    335      data[1].mRegistration.principal();
    336 
    337  nsAutoCString suffix1;
    338  cInfo1.attrs().CreateSuffix(suffix1);
    339 
    340  ASSERT_STREQ("", suffix1.get());
    341  ASSERT_STREQ("https://scope_1.org", cInfo1.spec().get());
    342  ASSERT_STREQ("https://scope_1.org", data[1].mRegistration.scope().get());
    343  ASSERT_STREQ("currentWorkerURL 1",
    344               data[1].mRegistration.currentWorkerURL().get());
    345  ASSERT_FALSE(data[1].mRegistration.currentWorkerHandlesFetch());
    346  ASSERT_STREQ("cacheName 1",
    347               NS_ConvertUTF16toUTF8(data[1].mRegistration.cacheName()).get());
    348  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_ALL,
    349            data[1].mRegistration.updateViaCache());
    350  ASSERT_EQ((int64_t)ts, data[1].mRegistration.currentWorkerInstalledTime());
    351  ASSERT_EQ((int64_t)ts, data[1].mRegistration.currentWorkerActivatedTime());
    352  ASSERT_EQ((int64_t)ts, data[1].mRegistration.lastUpdateTime());
    353  ASSERT_EQ(true, data[1].mRegistration.navigationPreloadState().enabled());
    354  ASSERT_STREQ(
    355      "false",
    356      data[1].mRegistration.navigationPreloadState().headerValue().get());
    357 }
    358 
    359 TEST(ServiceWorkerRegistrar, TestDeleteData)
    360 {
    361  ASSERT_TRUE(CreateFile("Foobar"_ns))
    362  << "CreateFile should not fail";
    363 
    364  RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
    365 
    366  swr->TestDeleteData();
    367 
    368  nsCOMPtr<nsIFile> file = GetFile();
    369 
    370  bool exists;
    371  nsresult rv = file->Exists(&exists);
    372  ASSERT_EQ(NS_OK, rv) << "nsIFile::Exists cannot fail";
    373 
    374  ASSERT_FALSE(exists)
    375  << "The file should not exist after a DeleteData().";
    376 }
    377 
    378 TEST(ServiceWorkerRegistrar, TestWriteData)
    379 {
    380  {
    381    RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
    382 
    383    ServiceWorkerRegistrationData reg;
    384 
    385    reg.scope() = "https://scope_write_0.org"_ns;
    386    reg.currentWorkerURL() = "currentWorkerURL write 0"_ns;
    387    reg.currentWorkerHandlesFetch() = true;
    388    reg.cacheName() = u"cacheName write 0"_ns;
    389    reg.updateViaCache() =
    390        nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS;
    391 
    392    reg.currentWorkerInstalledTime() = PR_Now();
    393    reg.currentWorkerActivatedTime() = PR_Now();
    394    reg.lastUpdateTime() = PR_Now();
    395 
    396    const auto spec = "spec write 0"_ns;
    397    reg.principal() = mozilla::ipc::ContentPrincipalInfo(
    398        mozilla::OriginAttributes(), spec, spec, mozilla::Nothing(), spec);
    399 
    400    swr->TestRegisterServiceWorker(reg);
    401 
    402    nsresult rv = swr->TestWriteData();
    403    ASSERT_EQ(NS_OK, rv) << "WriteData() should not fail";
    404  }
    405 
    406  RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
    407 
    408  nsresult rv = swr->TestReadData();
    409  ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
    410 
    411  const nsTArray<ServiceWorkerRegistrar::ServiceWorkerData>& dataArr =
    412      swr->TestGetData();
    413  ASSERT_EQ((uint32_t)1, dataArr.Length()) << "1 entries should be found";
    414 
    415  const auto& data = dataArr[0];
    416 
    417  ASSERT_EQ(data.mRegistration.principal().type(),
    418            mozilla::ipc::PrincipalInfo::TContentPrincipalInfo);
    419  const mozilla::ipc::ContentPrincipalInfo& cInfo =
    420      data.mRegistration.principal();
    421 
    422  mozilla::OriginAttributes attrs;
    423  nsAutoCString suffix, expectSuffix;
    424  attrs.CreateSuffix(expectSuffix);
    425  cInfo.attrs().CreateSuffix(suffix);
    426 
    427  ASSERT_STREQ(expectSuffix.get(), suffix.get());
    428 
    429  ASSERT_STREQ("https://scope_write_0.org", cInfo.spec().get());
    430  ASSERT_STREQ("https://scope_write_0.org", data.mRegistration.scope().get());
    431  ASSERT_STREQ("currentWorkerURL write 0",
    432               data.mRegistration.currentWorkerURL().get());
    433 
    434  ASSERT_EQ(true, data.mRegistration.currentWorkerHandlesFetch());
    435 
    436  ASSERT_STREQ("cacheName write 0",
    437               NS_ConvertUTF16toUTF8(data.mRegistration.cacheName()).get());
    438 
    439  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
    440            data.mRegistration.updateViaCache());
    441 
    442  ASSERT_NE((int64_t)0, data.mRegistration.currentWorkerInstalledTime());
    443  ASSERT_NE((int64_t)0, data.mRegistration.currentWorkerActivatedTime());
    444  ASSERT_NE((int64_t)0, data.mRegistration.lastUpdateTime());
    445 }
    446 
    447 TEST(ServiceWorkerRegistrar, TestVersion2Migration)
    448 {
    449  nsAutoCString buffer(
    450      "2"
    451      "\n");
    452 
    453  buffer.AppendLiteral("^appId=123&inBrowser=1\n");
    454  buffer.AppendLiteral(
    455      "spec 0\nhttps://scope_0.org\nscriptSpec 0\ncurrentWorkerURL "
    456      "0\nactiveCache 0\nwaitingCache 0\n");
    457  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    458 
    459  buffer.AppendLiteral("\n");
    460  buffer.AppendLiteral(
    461      "spec 1\nhttps://scope_1.org\nscriptSpec 1\ncurrentWorkerURL "
    462      "1\nactiveCache 1\nwaitingCache 1\n");
    463  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    464 
    465  ASSERT_TRUE(CreateFile(buffer))
    466  << "CreateFile should not fail";
    467 
    468  RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
    469 
    470  nsresult rv = swr->TestReadData();
    471  ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
    472 
    473  const nsTArray<ServiceWorkerRegistrar::ServiceWorkerData>& data =
    474      swr->TestGetData();
    475  ASSERT_EQ((uint32_t)2, data.Length()) << "2 entries should be found";
    476 
    477  const mozilla::ipc::PrincipalInfo& info0 = data[0].mRegistration.principal();
    478  ASSERT_EQ(info0.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo)
    479      << "First principal must be content";
    480  const mozilla::ipc::ContentPrincipalInfo& cInfo0 =
    481      data[0].mRegistration.principal();
    482 
    483  nsAutoCString suffix0;
    484  cInfo0.attrs().CreateSuffix(suffix0);
    485 
    486  ASSERT_STREQ("", suffix0.get());
    487  ASSERT_STREQ("https://scope_0.org", cInfo0.spec().get());
    488  ASSERT_STREQ("https://scope_0.org", data[0].mRegistration.scope().get());
    489  ASSERT_STREQ("currentWorkerURL 0",
    490               data[0].mRegistration.currentWorkerURL().get());
    491  ASSERT_EQ(true, data[0].mRegistration.currentWorkerHandlesFetch());
    492  ASSERT_STREQ("activeCache 0",
    493               NS_ConvertUTF16toUTF8(data[0].mRegistration.cacheName()).get());
    494  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
    495            data[0].mRegistration.updateViaCache());
    496  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerInstalledTime());
    497  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerActivatedTime());
    498  ASSERT_EQ((int64_t)0, data[0].mRegistration.lastUpdateTime());
    499 
    500  const mozilla::ipc::PrincipalInfo& info1 = data[1].mRegistration.principal();
    501  ASSERT_EQ(info1.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo)
    502      << "First principal must be content";
    503  const mozilla::ipc::ContentPrincipalInfo& cInfo1 =
    504      data[1].mRegistration.principal();
    505 
    506  nsAutoCString suffix1;
    507  cInfo1.attrs().CreateSuffix(suffix1);
    508 
    509  ASSERT_STREQ("", suffix1.get());
    510  ASSERT_STREQ("https://scope_1.org", cInfo1.spec().get());
    511  ASSERT_STREQ("https://scope_1.org", data[1].mRegistration.scope().get());
    512  ASSERT_STREQ("currentWorkerURL 1",
    513               data[1].mRegistration.currentWorkerURL().get());
    514  ASSERT_EQ(true, data[1].mRegistration.currentWorkerHandlesFetch());
    515  ASSERT_STREQ("activeCache 1",
    516               NS_ConvertUTF16toUTF8(data[1].mRegistration.cacheName()).get());
    517  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
    518            data[1].mRegistration.updateViaCache());
    519  ASSERT_EQ((int64_t)0, data[1].mRegistration.currentWorkerInstalledTime());
    520  ASSERT_EQ((int64_t)0, data[1].mRegistration.currentWorkerActivatedTime());
    521  ASSERT_EQ((int64_t)0, data[1].mRegistration.lastUpdateTime());
    522 }
    523 
    524 TEST(ServiceWorkerRegistrar, TestVersion3Migration)
    525 {
    526  nsAutoCString buffer(
    527      "3"
    528      "\n");
    529 
    530  buffer.AppendLiteral("^appId=123&inBrowser=1\n");
    531  buffer.AppendLiteral(
    532      "spec 0\nhttps://scope_0.org\ncurrentWorkerURL 0\ncacheName 0\n");
    533  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    534 
    535  buffer.AppendLiteral("\n");
    536  buffer.AppendLiteral(
    537      "spec 1\nhttps://scope_1.org\ncurrentWorkerURL 1\ncacheName 1\n");
    538  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    539 
    540  ASSERT_TRUE(CreateFile(buffer))
    541  << "CreateFile should not fail";
    542 
    543  RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
    544 
    545  nsresult rv = swr->TestReadData();
    546  ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
    547 
    548  const nsTArray<ServiceWorkerRegistrar::ServiceWorkerData>& data =
    549      swr->TestGetData();
    550  ASSERT_EQ((uint32_t)2, data.Length()) << "2 entries should be found";
    551 
    552  const mozilla::ipc::PrincipalInfo& info0 = data[0].mRegistration.principal();
    553  ASSERT_EQ(info0.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo)
    554      << "First principal must be content";
    555  const mozilla::ipc::ContentPrincipalInfo& cInfo0 =
    556      data[0].mRegistration.principal();
    557 
    558  nsAutoCString suffix0;
    559  cInfo0.attrs().CreateSuffix(suffix0);
    560 
    561  ASSERT_STREQ("", suffix0.get());
    562  ASSERT_STREQ("https://scope_0.org", cInfo0.spec().get());
    563  ASSERT_STREQ("https://scope_0.org", data[0].mRegistration.scope().get());
    564  ASSERT_STREQ("currentWorkerURL 0",
    565               data[0].mRegistration.currentWorkerURL().get());
    566  ASSERT_EQ(true, data[0].mRegistration.currentWorkerHandlesFetch());
    567  ASSERT_STREQ("cacheName 0",
    568               NS_ConvertUTF16toUTF8(data[0].mRegistration.cacheName()).get());
    569  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
    570            data[0].mRegistration.updateViaCache());
    571  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerInstalledTime());
    572  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerActivatedTime());
    573  ASSERT_EQ((int64_t)0, data[0].mRegistration.lastUpdateTime());
    574 
    575  const mozilla::ipc::PrincipalInfo& info1 = data[1].mRegistration.principal();
    576  ASSERT_EQ(info1.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo)
    577      << "First principal must be content";
    578  const mozilla::ipc::ContentPrincipalInfo& cInfo1 =
    579      data[1].mRegistration.principal();
    580 
    581  nsAutoCString suffix1;
    582  cInfo1.attrs().CreateSuffix(suffix1);
    583 
    584  ASSERT_STREQ("", suffix1.get());
    585  ASSERT_STREQ("https://scope_1.org", cInfo1.spec().get());
    586  ASSERT_STREQ("https://scope_1.org", data[1].mRegistration.scope().get());
    587  ASSERT_STREQ("currentWorkerURL 1",
    588               data[1].mRegistration.currentWorkerURL().get());
    589  ASSERT_EQ(true, data[1].mRegistration.currentWorkerHandlesFetch());
    590  ASSERT_STREQ("cacheName 1",
    591               NS_ConvertUTF16toUTF8(data[1].mRegistration.cacheName()).get());
    592  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
    593            data[1].mRegistration.updateViaCache());
    594  ASSERT_EQ((int64_t)0, data[1].mRegistration.currentWorkerInstalledTime());
    595  ASSERT_EQ((int64_t)0, data[1].mRegistration.currentWorkerActivatedTime());
    596  ASSERT_EQ((int64_t)0, data[1].mRegistration.lastUpdateTime());
    597 }
    598 
    599 TEST(ServiceWorkerRegistrar, TestVersion4Migration)
    600 {
    601  nsAutoCString buffer(
    602      "4"
    603      "\n");
    604 
    605  buffer.AppendLiteral("^appId=123&inBrowser=1\n");
    606  buffer.AppendLiteral(
    607      "https://scope_0.org\ncurrentWorkerURL 0\ncacheName 0\n");
    608  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    609 
    610  buffer.AppendLiteral("\n");
    611  buffer.AppendLiteral(
    612      "https://scope_1.org\ncurrentWorkerURL 1\ncacheName 1\n");
    613  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    614 
    615  ASSERT_TRUE(CreateFile(buffer))
    616  << "CreateFile should not fail";
    617 
    618  RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
    619 
    620  nsresult rv = swr->TestReadData();
    621  ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
    622 
    623  const nsTArray<ServiceWorkerRegistrar::ServiceWorkerData>& data =
    624      swr->TestGetData();
    625  ASSERT_EQ((uint32_t)2, data.Length()) << "2 entries should be found";
    626 
    627  const mozilla::ipc::PrincipalInfo& info0 = data[0].mRegistration.principal();
    628  ASSERT_EQ(info0.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo)
    629      << "First principal must be content";
    630  const mozilla::ipc::ContentPrincipalInfo& cInfo0 =
    631      data[0].mRegistration.principal();
    632 
    633  nsAutoCString suffix0;
    634  cInfo0.attrs().CreateSuffix(suffix0);
    635 
    636  ASSERT_STREQ("", suffix0.get());
    637  ASSERT_STREQ("https://scope_0.org", cInfo0.spec().get());
    638  ASSERT_STREQ("https://scope_0.org", data[0].mRegistration.scope().get());
    639  ASSERT_STREQ("currentWorkerURL 0",
    640               data[0].mRegistration.currentWorkerURL().get());
    641  // default is true
    642  ASSERT_EQ(true, data[0].mRegistration.currentWorkerHandlesFetch());
    643  ASSERT_STREQ("cacheName 0",
    644               NS_ConvertUTF16toUTF8(data[0].mRegistration.cacheName()).get());
    645  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
    646            data[0].mRegistration.updateViaCache());
    647  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerInstalledTime());
    648  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerActivatedTime());
    649  ASSERT_EQ((int64_t)0, data[0].mRegistration.lastUpdateTime());
    650 
    651  const mozilla::ipc::PrincipalInfo& info1 = data[1].mRegistration.principal();
    652  ASSERT_EQ(info1.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo)
    653      << "First principal must be content";
    654  const mozilla::ipc::ContentPrincipalInfo& cInfo1 =
    655      data[1].mRegistration.principal();
    656 
    657  nsAutoCString suffix1;
    658  cInfo1.attrs().CreateSuffix(suffix1);
    659 
    660  ASSERT_STREQ("", suffix1.get());
    661  ASSERT_STREQ("https://scope_1.org", cInfo1.spec().get());
    662  ASSERT_STREQ("https://scope_1.org", data[1].mRegistration.scope().get());
    663  ASSERT_STREQ("currentWorkerURL 1",
    664               data[1].mRegistration.currentWorkerURL().get());
    665  // default is true
    666  ASSERT_EQ(true, data[1].mRegistration.currentWorkerHandlesFetch());
    667  ASSERT_STREQ("cacheName 1",
    668               NS_ConvertUTF16toUTF8(data[1].mRegistration.cacheName()).get());
    669  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
    670            data[1].mRegistration.updateViaCache());
    671  ASSERT_EQ((int64_t)0, data[1].mRegistration.currentWorkerInstalledTime());
    672  ASSERT_EQ((int64_t)0, data[1].mRegistration.currentWorkerActivatedTime());
    673  ASSERT_EQ((int64_t)0, data[1].mRegistration.lastUpdateTime());
    674 }
    675 
    676 TEST(ServiceWorkerRegistrar, TestVersion5Migration)
    677 {
    678  nsAutoCString buffer(
    679      "5"
    680      "\n");
    681 
    682  buffer.AppendLiteral("^appId=123&inBrowser=1\n");
    683  buffer.AppendLiteral("https://scope_0.org\ncurrentWorkerURL 0\n");
    684  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TRUE "\n");
    685  buffer.AppendLiteral("cacheName 0\n");
    686  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    687 
    688  buffer.AppendLiteral("\n");
    689  buffer.AppendLiteral("https://scope_1.org\ncurrentWorkerURL 1\n");
    690  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_FALSE "\n");
    691  buffer.AppendLiteral("cacheName 1\n");
    692  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    693 
    694  ASSERT_TRUE(CreateFile(buffer))
    695  << "CreateFile should not fail";
    696 
    697  RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
    698 
    699  nsresult rv = swr->TestReadData();
    700  ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
    701 
    702  const nsTArray<ServiceWorkerRegistrar::ServiceWorkerData>& data =
    703      swr->TestGetData();
    704  ASSERT_EQ((uint32_t)2, data.Length()) << "2 entries should be found";
    705 
    706  const mozilla::ipc::PrincipalInfo& info0 = data[0].mRegistration.principal();
    707  ASSERT_EQ(info0.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo)
    708      << "First principal must be content";
    709  const mozilla::ipc::ContentPrincipalInfo& cInfo0 =
    710      data[0].mRegistration.principal();
    711 
    712  nsAutoCString suffix0;
    713  cInfo0.attrs().CreateSuffix(suffix0);
    714 
    715  ASSERT_STREQ("", suffix0.get());
    716  ASSERT_STREQ("https://scope_0.org", cInfo0.spec().get());
    717  ASSERT_STREQ("https://scope_0.org", data[0].mRegistration.scope().get());
    718  ASSERT_STREQ("currentWorkerURL 0",
    719               data[0].mRegistration.currentWorkerURL().get());
    720  ASSERT_TRUE(data[0].mRegistration.currentWorkerHandlesFetch());
    721  ASSERT_STREQ("cacheName 0",
    722               NS_ConvertUTF16toUTF8(data[0].mRegistration.cacheName()).get());
    723  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
    724            data[0].mRegistration.updateViaCache());
    725  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerInstalledTime());
    726  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerActivatedTime());
    727  ASSERT_EQ((int64_t)0, data[0].mRegistration.lastUpdateTime());
    728 
    729  const mozilla::ipc::PrincipalInfo& info1 = data[1].mRegistration.principal();
    730  ASSERT_EQ(info1.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo)
    731      << "First principal must be content";
    732  const mozilla::ipc::ContentPrincipalInfo& cInfo1 =
    733      data[1].mRegistration.principal();
    734 
    735  nsAutoCString suffix1;
    736  cInfo1.attrs().CreateSuffix(suffix1);
    737 
    738  ASSERT_STREQ("", suffix1.get());
    739  ASSERT_STREQ("https://scope_1.org", cInfo1.spec().get());
    740  ASSERT_STREQ("https://scope_1.org", data[1].mRegistration.scope().get());
    741  ASSERT_STREQ("currentWorkerURL 1",
    742               data[1].mRegistration.currentWorkerURL().get());
    743  ASSERT_FALSE(data[1].mRegistration.currentWorkerHandlesFetch());
    744  ASSERT_STREQ("cacheName 1",
    745               NS_ConvertUTF16toUTF8(data[1].mRegistration.cacheName()).get());
    746  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
    747            data[1].mRegistration.updateViaCache());
    748  ASSERT_EQ((int64_t)0, data[1].mRegistration.currentWorkerInstalledTime());
    749  ASSERT_EQ((int64_t)0, data[1].mRegistration.currentWorkerActivatedTime());
    750  ASSERT_EQ((int64_t)0, data[1].mRegistration.lastUpdateTime());
    751 }
    752 
    753 TEST(ServiceWorkerRegistrar, TestVersion6Migration)
    754 {
    755  nsAutoCString buffer(
    756      "6"
    757      "\n");
    758 
    759  buffer.AppendLiteral("^appId=123&inBrowser=1\n");
    760  buffer.AppendLiteral("https://scope_0.org\ncurrentWorkerURL 0\n");
    761  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TRUE "\n");
    762  buffer.AppendLiteral("cacheName 0\n");
    763  buffer.AppendInt(nsIRequest::LOAD_NORMAL, 16);
    764  buffer.AppendLiteral("\n");
    765  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    766 
    767  buffer.AppendLiteral("\n");
    768  buffer.AppendLiteral("https://scope_1.org\ncurrentWorkerURL 1\n");
    769  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_FALSE "\n");
    770  buffer.AppendLiteral("cacheName 1\n");
    771  buffer.AppendInt(nsIRequest::VALIDATE_ALWAYS, 16);
    772  buffer.AppendLiteral("\n");
    773  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    774 
    775  ASSERT_TRUE(CreateFile(buffer))
    776  << "CreateFile should not fail";
    777 
    778  RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
    779 
    780  nsresult rv = swr->TestReadData();
    781  ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
    782 
    783  const nsTArray<ServiceWorkerRegistrar::ServiceWorkerData>& data =
    784      swr->TestGetData();
    785  ASSERT_EQ((uint32_t)2, data.Length()) << "2 entries should be found";
    786 
    787  const mozilla::ipc::PrincipalInfo& info0 = data[0].mRegistration.principal();
    788  ASSERT_EQ(info0.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo)
    789      << "First principal must be content";
    790  const mozilla::ipc::ContentPrincipalInfo& cInfo0 =
    791      data[0].mRegistration.principal();
    792 
    793  nsAutoCString suffix0;
    794  cInfo0.attrs().CreateSuffix(suffix0);
    795 
    796  ASSERT_STREQ("", suffix0.get());
    797  ASSERT_STREQ("https://scope_0.org", cInfo0.spec().get());
    798  ASSERT_STREQ("https://scope_0.org", data[0].mRegistration.scope().get());
    799  ASSERT_STREQ("currentWorkerURL 0",
    800               data[0].mRegistration.currentWorkerURL().get());
    801  ASSERT_TRUE(data[0].mRegistration.currentWorkerHandlesFetch());
    802  ASSERT_STREQ("cacheName 0",
    803               NS_ConvertUTF16toUTF8(data[0].mRegistration.cacheName()).get());
    804  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_ALL,
    805            data[0].mRegistration.updateViaCache());
    806  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerInstalledTime());
    807  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerActivatedTime());
    808  ASSERT_EQ((int64_t)0, data[0].mRegistration.lastUpdateTime());
    809 
    810  const mozilla::ipc::PrincipalInfo& info1 = data[1].mRegistration.principal();
    811  ASSERT_EQ(info1.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo)
    812      << "First principal must be content";
    813  const mozilla::ipc::ContentPrincipalInfo& cInfo1 =
    814      data[1].mRegistration.principal();
    815 
    816  nsAutoCString suffix1;
    817  cInfo1.attrs().CreateSuffix(suffix1);
    818 
    819  ASSERT_STREQ("", suffix1.get());
    820  ASSERT_STREQ("https://scope_1.org", cInfo1.spec().get());
    821  ASSERT_STREQ("https://scope_1.org", data[1].mRegistration.scope().get());
    822  ASSERT_STREQ("currentWorkerURL 1",
    823               data[1].mRegistration.currentWorkerURL().get());
    824  ASSERT_FALSE(data[1].mRegistration.currentWorkerHandlesFetch());
    825  ASSERT_STREQ("cacheName 1",
    826               NS_ConvertUTF16toUTF8(data[1].mRegistration.cacheName()).get());
    827  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
    828            data[1].mRegistration.updateViaCache());
    829  ASSERT_EQ((int64_t)0, data[1].mRegistration.currentWorkerInstalledTime());
    830  ASSERT_EQ((int64_t)0, data[1].mRegistration.currentWorkerActivatedTime());
    831  ASSERT_EQ((int64_t)0, data[1].mRegistration.lastUpdateTime());
    832 }
    833 
    834 TEST(ServiceWorkerRegistrar, TestVersion7Migration)
    835 {
    836  nsAutoCString buffer(
    837      "7"
    838      "\n");
    839 
    840  buffer.AppendLiteral("^appId=123&inBrowser=1\n");
    841  buffer.AppendLiteral("https://scope_0.org\ncurrentWorkerURL 0\n");
    842  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TRUE "\n");
    843  buffer.AppendLiteral("cacheName 0\n");
    844  buffer.AppendInt(nsIRequest::LOAD_NORMAL, 16);
    845  buffer.AppendLiteral("\n");
    846  buffer.AppendInt(0);
    847  buffer.AppendLiteral("\n");
    848  buffer.AppendInt(0);
    849  buffer.AppendLiteral("\n");
    850  buffer.AppendInt(0);
    851  buffer.AppendLiteral("\n");
    852  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    853 
    854  buffer.AppendLiteral("\n");
    855  buffer.AppendLiteral("https://scope_1.org\ncurrentWorkerURL 1\n");
    856  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_FALSE "\n");
    857  buffer.AppendLiteral("cacheName 1\n");
    858  buffer.AppendInt(nsIRequest::VALIDATE_ALWAYS, 16);
    859  buffer.AppendLiteral("\n");
    860  PRTime ts = PR_Now();
    861  buffer.AppendInt(ts);
    862  buffer.AppendLiteral("\n");
    863  buffer.AppendInt(ts);
    864  buffer.AppendLiteral("\n");
    865  buffer.AppendInt(ts);
    866  buffer.AppendLiteral("\n");
    867  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    868 
    869  ASSERT_TRUE(CreateFile(buffer))
    870  << "CreateFile should not fail";
    871 
    872  RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
    873 
    874  nsresult rv = swr->TestReadData();
    875  ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
    876 
    877  const nsTArray<ServiceWorkerRegistrar::ServiceWorkerData>& data =
    878      swr->TestGetData();
    879  ASSERT_EQ((uint32_t)2, data.Length()) << "2 entries should be found";
    880 
    881  const mozilla::ipc::PrincipalInfo& info0 = data[0].mRegistration.principal();
    882  ASSERT_EQ(info0.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo)
    883      << "First principal must be content";
    884  const mozilla::ipc::ContentPrincipalInfo& cInfo0 =
    885      data[0].mRegistration.principal();
    886 
    887  nsAutoCString suffix0;
    888  cInfo0.attrs().CreateSuffix(suffix0);
    889 
    890  ASSERT_STREQ("", suffix0.get());
    891  ASSERT_STREQ("https://scope_0.org", cInfo0.spec().get());
    892  ASSERT_STREQ("https://scope_0.org", data[0].mRegistration.scope().get());
    893  ASSERT_STREQ("currentWorkerURL 0",
    894               data[0].mRegistration.currentWorkerURL().get());
    895  ASSERT_TRUE(data[0].mRegistration.currentWorkerHandlesFetch());
    896  ASSERT_STREQ("cacheName 0",
    897               NS_ConvertUTF16toUTF8(data[0].mRegistration.cacheName()).get());
    898  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_ALL,
    899            data[0].mRegistration.updateViaCache());
    900  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerInstalledTime());
    901  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerActivatedTime());
    902  ASSERT_EQ((int64_t)0, data[0].mRegistration.lastUpdateTime());
    903 
    904  const mozilla::ipc::PrincipalInfo& info1 = data[1].mRegistration.principal();
    905  ASSERT_EQ(info1.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo)
    906      << "First principal must be content";
    907  const mozilla::ipc::ContentPrincipalInfo& cInfo1 =
    908      data[1].mRegistration.principal();
    909 
    910  nsAutoCString suffix1;
    911  cInfo1.attrs().CreateSuffix(suffix1);
    912 
    913  ASSERT_STREQ("", suffix1.get());
    914  ASSERT_STREQ("https://scope_1.org", cInfo1.spec().get());
    915  ASSERT_STREQ("https://scope_1.org", data[1].mRegistration.scope().get());
    916  ASSERT_STREQ("currentWorkerURL 1",
    917               data[1].mRegistration.currentWorkerURL().get());
    918  ASSERT_FALSE(data[1].mRegistration.currentWorkerHandlesFetch());
    919  ASSERT_STREQ("cacheName 1",
    920               NS_ConvertUTF16toUTF8(data[1].mRegistration.cacheName()).get());
    921  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
    922            data[1].mRegistration.updateViaCache());
    923  ASSERT_EQ((int64_t)ts, data[1].mRegistration.currentWorkerInstalledTime());
    924  ASSERT_EQ((int64_t)ts, data[1].mRegistration.currentWorkerActivatedTime());
    925  ASSERT_EQ((int64_t)ts, data[1].mRegistration.lastUpdateTime());
    926 }
    927 
    928 TEST(ServiceWorkerRegistrar, TestDedupeRead)
    929 {
    930  nsAutoCString buffer(
    931      "3"
    932      "\n");
    933 
    934  // unique entries
    935  buffer.AppendLiteral("^inBrowser=1\n");
    936  buffer.AppendLiteral(
    937      "spec 0\nhttps://scope_0.org\ncurrentWorkerURL 0\ncacheName 0\n");
    938  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    939 
    940  buffer.AppendLiteral("\n");
    941  buffer.AppendLiteral(
    942      "spec 1\nhttps://scope_1.org\ncurrentWorkerURL 1\ncacheName 1\n");
    943  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    944 
    945  // dupe entries
    946  buffer.AppendLiteral("^inBrowser=1\n");
    947  buffer.AppendLiteral(
    948      "spec 1\nhttps://scope_0.org\ncurrentWorkerURL 0\ncacheName 0\n");
    949  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    950 
    951  buffer.AppendLiteral("^inBrowser=1\n");
    952  buffer.AppendLiteral(
    953      "spec 2\nhttps://scope_0.org\ncurrentWorkerURL 0\ncacheName 0\n");
    954  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    955 
    956  buffer.AppendLiteral("\n");
    957  buffer.AppendLiteral(
    958      "spec 3\nhttps://scope_1.org\ncurrentWorkerURL 1\ncacheName 1\n");
    959  buffer.AppendLiteral(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
    960 
    961  ASSERT_TRUE(CreateFile(buffer))
    962  << "CreateFile should not fail";
    963 
    964  RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
    965 
    966  nsresult rv = swr->TestReadData();
    967  ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
    968 
    969  const nsTArray<ServiceWorkerRegistrar::ServiceWorkerData>& data =
    970      swr->TestGetData();
    971  ASSERT_EQ((uint32_t)2, data.Length()) << "2 entries should be found";
    972 
    973  const mozilla::ipc::PrincipalInfo& info0 = data[0].mRegistration.principal();
    974  ASSERT_EQ(info0.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo)
    975      << "First principal must be content";
    976  const mozilla::ipc::ContentPrincipalInfo& cInfo0 =
    977      data[0].mRegistration.principal();
    978 
    979  nsAutoCString suffix0;
    980  cInfo0.attrs().CreateSuffix(suffix0);
    981 
    982  ASSERT_STREQ("", suffix0.get());
    983  ASSERT_STREQ("https://scope_0.org", cInfo0.spec().get());
    984  ASSERT_STREQ("https://scope_0.org", data[0].mRegistration.scope().get());
    985  ASSERT_STREQ("currentWorkerURL 0",
    986               data[0].mRegistration.currentWorkerURL().get());
    987  ASSERT_EQ(true, data[0].mRegistration.currentWorkerHandlesFetch());
    988  ASSERT_STREQ("cacheName 0",
    989               NS_ConvertUTF16toUTF8(data[0].mRegistration.cacheName()).get());
    990  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
    991            data[0].mRegistration.updateViaCache());
    992  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerInstalledTime());
    993  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerActivatedTime());
    994  ASSERT_EQ((int64_t)0, data[0].mRegistration.lastUpdateTime());
    995 
    996  const mozilla::ipc::PrincipalInfo& info1 = data[1].mRegistration.principal();
    997  ASSERT_EQ(info1.type(), mozilla::ipc::PrincipalInfo::TContentPrincipalInfo)
    998      << "First principal must be content";
    999  const mozilla::ipc::ContentPrincipalInfo& cInfo1 =
   1000      data[1].mRegistration.principal();
   1001 
   1002  nsAutoCString suffix1;
   1003  cInfo1.attrs().CreateSuffix(suffix1);
   1004 
   1005  ASSERT_STREQ("", suffix1.get());
   1006  ASSERT_STREQ("https://scope_1.org", cInfo1.spec().get());
   1007  ASSERT_STREQ("https://scope_1.org", data[1].mRegistration.scope().get());
   1008  ASSERT_STREQ("currentWorkerURL 1",
   1009               data[1].mRegistration.currentWorkerURL().get());
   1010  ASSERT_EQ(true, data[1].mRegistration.currentWorkerHandlesFetch());
   1011  ASSERT_STREQ("cacheName 1",
   1012               NS_ConvertUTF16toUTF8(data[1].mRegistration.cacheName()).get());
   1013  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
   1014            data[1].mRegistration.updateViaCache());
   1015  ASSERT_EQ((int64_t)0, data[1].mRegistration.currentWorkerInstalledTime());
   1016  ASSERT_EQ((int64_t)0, data[1].mRegistration.currentWorkerActivatedTime());
   1017  ASSERT_EQ((int64_t)0, data[1].mRegistration.lastUpdateTime());
   1018 }
   1019 
   1020 TEST(ServiceWorkerRegistrar, TestDedupeWrite)
   1021 {
   1022  {
   1023    RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
   1024 
   1025    for (int i = 0; i < 2; ++i) {
   1026      ServiceWorkerRegistrationData reg;
   1027 
   1028      reg.scope() = "https://scope_write.dedupe"_ns;
   1029      reg.type() = WorkerType::Classic;
   1030      reg.currentWorkerURL() = nsPrintfCString("currentWorkerURL write %d", i);
   1031      reg.currentWorkerHandlesFetch() = true;
   1032      reg.cacheName() =
   1033          NS_ConvertUTF8toUTF16(nsPrintfCString("cacheName write %d", i));
   1034      reg.updateViaCache() =
   1035          nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS;
   1036 
   1037      nsAutoCString spec;
   1038      spec.AppendPrintf("spec write dedupe/%d", i);
   1039 
   1040      reg.principal() = mozilla::ipc::ContentPrincipalInfo(
   1041          mozilla::OriginAttributes(), spec, spec, mozilla::Nothing(), spec);
   1042 
   1043      swr->TestRegisterServiceWorker(reg);
   1044    }
   1045 
   1046    nsresult rv = swr->TestWriteData();
   1047    ASSERT_EQ(NS_OK, rv) << "WriteData() should not fail";
   1048  }
   1049 
   1050  RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
   1051 
   1052  nsresult rv = swr->TestReadData();
   1053  ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
   1054 
   1055  // Duplicate entries should be removed.
   1056  const nsTArray<ServiceWorkerRegistrar::ServiceWorkerData>& data =
   1057      swr->TestGetData();
   1058  ASSERT_EQ((uint32_t)1, data.Length()) << "1 entry should be found";
   1059 
   1060  ASSERT_EQ(data[0].mRegistration.principal().type(),
   1061            mozilla::ipc::PrincipalInfo::TContentPrincipalInfo);
   1062  const mozilla::ipc::ContentPrincipalInfo& cInfo =
   1063      data[0].mRegistration.principal();
   1064 
   1065  mozilla::OriginAttributes attrs;
   1066  nsAutoCString suffix, expectSuffix;
   1067  attrs.CreateSuffix(expectSuffix);
   1068  cInfo.attrs().CreateSuffix(suffix);
   1069 
   1070  // Last entry passed to RegisterServiceWorkerInternal() should overwrite
   1071  // previous values.  So expect "1" in values here.
   1072  ASSERT_STREQ(expectSuffix.get(), suffix.get());
   1073  ASSERT_STREQ("https://scope_write.dedupe", cInfo.spec().get());
   1074  ASSERT_STREQ("https://scope_write.dedupe",
   1075               data[0].mRegistration.scope().get());
   1076  ASSERT_STREQ("currentWorkerURL write 1",
   1077               data[0].mRegistration.currentWorkerURL().get());
   1078  ASSERT_EQ(true, data[0].mRegistration.currentWorkerHandlesFetch());
   1079  ASSERT_STREQ("cacheName write 1",
   1080               NS_ConvertUTF16toUTF8(data[0].mRegistration.cacheName()).get());
   1081  ASSERT_EQ(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
   1082            data[0].mRegistration.updateViaCache());
   1083  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerInstalledTime());
   1084  ASSERT_EQ((int64_t)0, data[0].mRegistration.currentWorkerActivatedTime());
   1085  ASSERT_EQ((int64_t)0, data[0].mRegistration.lastUpdateTime());
   1086 }
   1087 
   1088 TEST(ServiceWorkerRegistrar, TestLoadHandler)
   1089 {
   1090  nsCString buffer;
   1091  buffer.AppendInt(static_cast<uint32_t>(SERVICEWORKERREGISTRAR_VERSION));
   1092  buffer.Append("\n");
   1093 
   1094  buffer.AppendLiteral("^inBrowser=1\n");
   1095  buffer.AppendLiteral("https://scope_0.org\ncurrentWorkerURL 0\n");
   1096  buffer.Append(SERVICEWORKERREGISTRAR_TRUE "\n");
   1097  buffer.AppendLiteral("cacheName 0\n");
   1098  buffer.AppendInt(nsIServiceWorkerRegistrationInfo::UPDATE_VIA_CACHE_IMPORTS,
   1099                   16);
   1100  buffer.AppendLiteral("\n");
   1101  buffer.AppendInt(0);
   1102  buffer.AppendLiteral("\n");
   1103  buffer.AppendInt(0);
   1104  buffer.AppendLiteral("\n");
   1105  buffer.AppendInt(0);
   1106  buffer.AppendLiteral("\n");
   1107  buffer.AppendInt(0);
   1108  buffer.AppendLiteral("\n");
   1109  buffer.AppendLiteral("true\n");
   1110  buffer.AppendInt(2);
   1111  buffer.AppendLiteral("\n");
   1112  buffer.AppendLiteral("handler_test\n");
   1113  buffer.AppendLiteral("hello world!\n");
   1114  buffer.AppendLiteral("handler_test2\n");
   1115  buffer.AppendLiteral("hello\n");
   1116  buffer.AppendInt(0);
   1117  buffer.AppendLiteral("\n");
   1118  buffer.AppendInt(0);
   1119  buffer.AppendLiteral("\n");
   1120  buffer.AppendInt(0);
   1121  buffer.AppendLiteral("\n");
   1122  buffer.AppendInt(0);
   1123  buffer.AppendLiteral("\n");
   1124  buffer.Append(SERVICEWORKERREGISTRAR_TERMINATOR "\n");
   1125 
   1126  ASSERT_TRUE(CreateFile(buffer))
   1127  << "CreateFile should not fail";
   1128 
   1129  {
   1130    RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
   1131    nsresult rv = swr->TestReadData();
   1132    ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
   1133 
   1134    ASSERT_EQ(gHandlerStats->swLoadCount, (uint32_t)1)
   1135        << "First handle correctly called";
   1136    ASSERT_EQ(gHandlerStats->lastValue, nsCString("hello world!"))
   1137        << "First handle correctly called correct value)";
   1138    ASSERT_EQ(gHandlerStats->swUnregisteredCount, (uint32_t)0)
   1139        << "No unregister calls yet";
   1140 
   1141    ASSERT_EQ(gHandlerStats->swLoad2Count, (uint32_t)1)
   1142        << "Second handle correctly called";
   1143    ASSERT_EQ(gHandlerStats->lastValue2, nsCString("hello"))
   1144        << "Second handle correctly called correct value)";
   1145    ASSERT_EQ(gHandlerStats->swUnregistered2Count, (uint32_t)0)
   1146        << "No unregister calls yet";
   1147 
   1148    rv = swr->TestWriteData();
   1149    ASSERT_EQ(NS_OK, rv) << "WriteData() should not fail";
   1150  }
   1151 
   1152  {
   1153    RefPtr<ServiceWorkerRegistrarTest> swr = new ServiceWorkerRegistrarTest;
   1154    nsresult rv = swr->TestReadData();
   1155    ASSERT_EQ(NS_OK, rv) << "ReadData() should not fail";
   1156 
   1157    ASSERT_EQ(gHandlerStats->swLoadCount, (uint32_t)2)
   1158        << "First handle correctly called";
   1159    ASSERT_EQ(gHandlerStats->lastValue, nsCString("hello world!"))
   1160        << "First handle correctly called correct value)";
   1161    ASSERT_EQ(gHandlerStats->swUnregisteredCount, (uint32_t)0)
   1162        << "No unregister calls yet";
   1163 
   1164    ASSERT_EQ(gHandlerStats->swLoad2Count, (uint32_t)2)
   1165        << "Second handle correctly called";
   1166    ASSERT_EQ(gHandlerStats->lastValue2, nsCString("hello"))
   1167        << "Second handle correctly called correct value)";
   1168    ASSERT_EQ(gHandlerStats->swUnregistered2Count, (uint32_t)0)
   1169        << "No unregister calls yet";
   1170  }
   1171 }
   1172 
   1173 int main(int argc, char** argv) {
   1174  ::testing::InitGoogleTest(&argc, argv);
   1175 
   1176  int rv = RUN_ALL_TESTS();
   1177  return rv;
   1178 }