// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/service_worker/service_worker_storage.h"

#include <stdint.h>
#include <memory>
#include <string>
#include <utility>

#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/common/content_client.h"
#include "content/public/common/origin_util.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "ipc/ipc_message.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/disk_cache/disk_cache.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/origin_trials/origin_trial_policy.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"

using net::IOBuffer;
using net::TestCompletionCallback;
using net::WrappedIOBuffer;

namespace content {
namespace service_worker_storage_unittest {

using RegistrationData = ServiceWorkerDatabase::RegistrationData;
using ResourceRecord = ServiceWorkerDatabase::ResourceRecord;

// This is a sample public key for testing the API. The corresponding private
// key (use this to generate new samples for this test file) is:
//
//  0x83, 0x67, 0xf4, 0xcd, 0x2a, 0x1f, 0x0e, 0x04, 0x0d, 0x43, 0x13,
//  0x4c, 0x67, 0xc4, 0xf4, 0x28, 0xc9, 0x90, 0x15, 0x02, 0xe2, 0xba,
//  0xfd, 0xbb, 0xfa, 0xbc, 0x92, 0x76, 0x8a, 0x2c, 0x4b, 0xc7, 0x75,
//  0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2, 0x9a,
//  0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f, 0x64,
//  0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0
const uint8_t kTestPublicKey[] = {
    0x75, 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2,
    0x9a, 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f,
    0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0,
};

void StatusAndQuitCallback(blink::ServiceWorkerStatusCode* result,
                           base::OnceClosure quit_closure,
                           blink::ServiceWorkerStatusCode status) {
  *result = status;
  std::move(quit_closure).Run();
}

void StatusCallback(bool* was_called,
                    base::Optional<blink::ServiceWorkerStatusCode>* result,
                    blink::ServiceWorkerStatusCode status) {
  *was_called = true;
  *result = status;
}

ServiceWorkerStorage::StatusCallback MakeStatusCallback(
    bool* was_called,
    base::Optional<blink::ServiceWorkerStatusCode>* result) {
  return base::BindOnce(&StatusCallback, was_called, result);
}

void FindCallback(bool* was_called,
                  base::Optional<blink::ServiceWorkerStatusCode>* result,
                  scoped_refptr<ServiceWorkerRegistration>* found,
                  blink::ServiceWorkerStatusCode status,
                  scoped_refptr<ServiceWorkerRegistration> registration) {
  *was_called = true;
  *result = status;
  *found = std::move(registration);
}

ServiceWorkerStorage::FindRegistrationCallback MakeFindCallback(
    bool* was_called,
    base::Optional<blink::ServiceWorkerStatusCode>* result,
    scoped_refptr<ServiceWorkerRegistration>* found) {
  return base::BindOnce(&FindCallback, was_called, result, found);
}

void GetAllCallback(
    bool* was_called,
    base::Optional<blink::ServiceWorkerStatusCode>* result,
    std::vector<scoped_refptr<ServiceWorkerRegistration>>* all_out,
    blink::ServiceWorkerStatusCode status,
    const std::vector<scoped_refptr<ServiceWorkerRegistration>>& all) {
  *was_called = true;
  *result = status;
  *all_out = all;
}

void GetAllInfosCallback(
    bool* was_called,
    base::Optional<blink::ServiceWorkerStatusCode>* result,
    std::vector<ServiceWorkerRegistrationInfo>* all_out,
    blink::ServiceWorkerStatusCode status,
    const std::vector<ServiceWorkerRegistrationInfo>& all) {
  *was_called = true;
  *result = status;
  *all_out = all;
}

ServiceWorkerStorage::GetRegistrationsCallback MakeGetRegistrationsCallback(
    bool* was_called,
    base::Optional<blink::ServiceWorkerStatusCode>* status,
    std::vector<scoped_refptr<ServiceWorkerRegistration>>* all) {
  return base::BindOnce(&GetAllCallback, was_called, status, all);
}

ServiceWorkerStorage::GetRegistrationsInfosCallback
MakeGetRegistrationsInfosCallback(
    bool* was_called,
    base::Optional<blink::ServiceWorkerStatusCode>* status,
    std::vector<ServiceWorkerRegistrationInfo>* all) {
  return base::BindOnce(&GetAllInfosCallback, was_called, status, all);
}

void GetUserDataCallback(
    bool* was_called,
    std::vector<std::string>* data_out,
    base::Optional<blink::ServiceWorkerStatusCode>* status_out,
    const std::vector<std::string>& data,
    blink::ServiceWorkerStatusCode status) {
  *was_called = true;
  *data_out = data;
  *status_out = status;
}

void GetUserDataForAllRegistrationsCallback(
    bool* was_called,
    std::vector<std::pair<int64_t, std::string>>* data_out,
    base::Optional<blink::ServiceWorkerStatusCode>* status_out,
    const std::vector<std::pair<int64_t, std::string>>& data,
    blink::ServiceWorkerStatusCode status) {
  *was_called = true;
  *data_out = data;
  *status_out = status;
}

int WriteResponse(ServiceWorkerStorage* storage,
                  int64_t id,
                  const std::string& headers,
                  IOBuffer* body,
                  int length) {
  std::unique_ptr<ServiceWorkerResponseWriter> writer =
      storage->CreateResponseWriter(id);

  std::unique_ptr<net::HttpResponseInfo> info =
      std::make_unique<net::HttpResponseInfo>();
  info->request_time = base::Time::Now();
  info->response_time = base::Time::Now();
  info->was_cached = false;
  info->headers = new net::HttpResponseHeaders(headers);
  scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
      base::MakeRefCounted<HttpResponseInfoIOBuffer>(std::move(info));
  int rv = 0;
  {
    TestCompletionCallback cb;
    writer->WriteInfo(info_buffer.get(), cb.callback());
    rv = cb.WaitForResult();
    if (rv < 0)
      return rv;
  }
  {
    TestCompletionCallback cb;
    writer->WriteData(body, length, cb.callback());
    rv = cb.WaitForResult();
  }
  return rv;
}

int WriteStringResponse(ServiceWorkerStorage* storage,
                        int64_t id,
                        const std::string& headers,
                        const std::string& body) {
  scoped_refptr<IOBuffer> body_buffer =
      base::MakeRefCounted<WrappedIOBuffer>(body.data());
  return WriteResponse(storage, id, headers, body_buffer.get(), body.length());
}

int WriteBasicResponse(ServiceWorkerStorage* storage, int64_t id) {
  const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\0Content-Length: 5\0\0";
  const char kHttpBody[] = "Hello";
  std::string headers(kHttpHeaders, base::size(kHttpHeaders));
  return WriteStringResponse(storage, id, headers, std::string(kHttpBody));
}

int ReadResponseInfo(ServiceWorkerStorage* storage,
                     int64_t id,
                     HttpResponseInfoIOBuffer* info_buffer) {
  std::unique_ptr<ServiceWorkerResponseReader> reader =
      storage->CreateResponseReader(id);
  TestCompletionCallback cb;
  reader->ReadInfo(info_buffer, cb.callback());
  return cb.WaitForResult();
}

bool VerifyBasicResponse(ServiceWorkerStorage* storage,
                         int64_t id,
                         bool expected_positive_result) {
  const std::string kExpectedHttpBody("Hello");
  std::unique_ptr<ServiceWorkerResponseReader> reader =
      storage->CreateResponseReader(id);
  scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
      new HttpResponseInfoIOBuffer();
  int rv = ReadResponseInfo(storage, id, info_buffer.get());
  if (expected_positive_result)
    EXPECT_LT(0, rv);
  if (rv <= 0)
    return false;

  std::string received_body;
  const int kBigEnough = 512;
  scoped_refptr<net::IOBuffer> buffer =
      base::MakeRefCounted<IOBuffer>(kBigEnough);
  TestCompletionCallback cb;
  reader->ReadData(buffer.get(), kBigEnough, cb.callback());
  rv = cb.WaitForResult();
  EXPECT_EQ(static_cast<int>(kExpectedHttpBody.size()), rv);
  if (rv <= 0)
    return false;
  received_body.assign(buffer->data(), rv);

  bool status_match =
      std::string("HONKYDORY") ==
          info_buffer->http_info->headers->GetStatusText();
  bool data_match = kExpectedHttpBody == received_body;

  EXPECT_TRUE(status_match);
  EXPECT_TRUE(data_match);
  return status_match && data_match;
}

int WriteResponseMetadata(ServiceWorkerStorage* storage,
                          int64_t id,
                          const std::string& metadata) {
  scoped_refptr<IOBuffer> body_buffer =
      base::MakeRefCounted<WrappedIOBuffer>(metadata.data());
  std::unique_ptr<ServiceWorkerResponseMetadataWriter> metadata_writer =
      storage->CreateResponseMetadataWriter(id);
  TestCompletionCallback cb;
  metadata_writer->WriteMetadata(body_buffer.get(), metadata.length(),
                                 cb.callback());
  return cb.WaitForResult();
}

int WriteMetadata(ServiceWorkerVersion* version,
                  const GURL& url,
                  const std::string& metadata) {
  const std::vector<uint8_t> data(metadata.begin(), metadata.end());
  EXPECT_TRUE(version);
  TestCompletionCallback cb;
  version->script_cache_map()->WriteMetadata(url, data, cb.callback());
  return cb.WaitForResult();
}

int ClearMetadata(ServiceWorkerVersion* version, const GURL& url) {
  EXPECT_TRUE(version);
  TestCompletionCallback cb;
  version->script_cache_map()->ClearMetadata(url, cb.callback());
  return cb.WaitForResult();
}

bool VerifyResponseMetadata(ServiceWorkerStorage* storage,
                            int64_t id,
                            const std::string& expected_metadata) {
  std::unique_ptr<ServiceWorkerResponseReader> reader =
      storage->CreateResponseReader(id);
  scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
      new HttpResponseInfoIOBuffer();
  {
    TestCompletionCallback cb;
    reader->ReadInfo(info_buffer.get(), cb.callback());
    int rv = cb.WaitForResult();
    EXPECT_LT(0, rv);
  }
  const net::HttpResponseInfo* read_head = info_buffer->http_info.get();
  if (!read_head->metadata.get())
    return false;
  EXPECT_EQ(0, memcmp(expected_metadata.data(), read_head->metadata->data(),
                      expected_metadata.length()));
  return true;
}

class ServiceWorkerStorageTest : public testing::Test {
 public:
  ServiceWorkerStorageTest()
      : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {
  }

  void SetUp() override { InitializeTestHelper(); }

  void TearDown() override {
    helper_.reset();
    disk_cache::FlushCacheThreadForTesting();
    content::RunAllTasksUntilIdle();
  }

  bool InitUserDataDirectory() {
    if (!user_data_directory_.CreateUniqueTempDir())
      return false;
    user_data_directory_path_ = user_data_directory_.GetPath();
    return true;
  }

  void InitializeTestHelper() {
    helper_.reset(new EmbeddedWorkerTestHelper(user_data_directory_path_));
    base::RunLoop().RunUntilIdle();
  }

  ServiceWorkerContextCore* context() { return helper_->context(); }
  ServiceWorkerStorage* storage() { return context()->storage(); }
  ServiceWorkerDatabase* database() { return storage()->database_.get(); }

  // A static class method for friendliness.
  static void VerifyPurgeableListStatusCallback(
      ServiceWorkerDatabase* database,
      std::set<int64_t>* purgeable_ids,
      bool* was_called,
      blink::ServiceWorkerStatusCode* result,
      blink::ServiceWorkerStatusCode status) {
    *was_called = true;
    *result = status;
    EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
              database->GetPurgeableResourceIds(purgeable_ids));
  }

 protected:
  const std::set<GURL>& registered_origins() {
    return storage()->registered_origins_;
  }

  void LazyInitialize() {
    storage()->LazyInitializeForTest(base::DoNothing());
    base::RunLoop().RunUntilIdle();
  }

  // Creates a registration with a waiting version in INSTALLED state.
  scoped_refptr<ServiceWorkerRegistration> CreateLiveRegistrationAndVersion(
      const GURL& scope,
      const GURL& script) {
    blink::mojom::ServiceWorkerRegistrationOptions options;
    options.scope = scope;
    auto registration = base::MakeRefCounted<ServiceWorkerRegistration>(
        options, storage()->NewRegistrationId(), context()->AsWeakPtr());
    auto version = base::MakeRefCounted<ServiceWorkerVersion>(
        registration.get(), script, blink::mojom::ScriptType::kClassic,
        storage()->NewVersionId(), context()->AsWeakPtr());
    std::vector<ResourceRecord> records = {
        ResourceRecord(storage()->NewResourceId(), script, 100)};
    version->script_cache_map()->SetResources(records);
    version->set_fetch_handler_existence(
        ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
    version->SetStatus(ServiceWorkerVersion::INSTALLED);
    registration->SetWaitingVersion(version);
    return registration;
  }

  blink::ServiceWorkerStatusCode StoreRegistration(
      scoped_refptr<ServiceWorkerRegistration> registration,
      scoped_refptr<ServiceWorkerVersion> version) {
    bool was_called = false;
    base::Optional<blink::ServiceWorkerStatusCode> result;
    storage()->StoreRegistration(registration.get(),
                                 version.get(),
                                 MakeStatusCallback(&was_called, &result));
    EXPECT_FALSE(was_called);  // always async
    base::RunLoop().RunUntilIdle();
    EXPECT_TRUE(was_called);
    return result.value();
  }

  blink::ServiceWorkerStatusCode DeleteRegistration(int64_t registration_id,
                                                    const GURL& origin) {
    bool was_called = false;
    base::Optional<blink::ServiceWorkerStatusCode> result;
    storage()->DeleteRegistration(
        registration_id, origin, MakeStatusCallback(&was_called, &result));
    EXPECT_FALSE(was_called);  // always async
    base::RunLoop().RunUntilIdle();
    EXPECT_TRUE(was_called);
    return result.value();
  }

  blink::ServiceWorkerStatusCode GetAllRegistrationsInfos(
      std::vector<ServiceWorkerRegistrationInfo>* registrations) {
    bool was_called = false;
    base::Optional<blink::ServiceWorkerStatusCode> result;
    storage()->GetAllRegistrationsInfos(
        MakeGetRegistrationsInfosCallback(&was_called, &result, registrations));
    EXPECT_FALSE(was_called);  // always async
    base::RunLoop().RunUntilIdle();
    EXPECT_TRUE(was_called);
    return result.value();
  }

  blink::ServiceWorkerStatusCode GetRegistrationsForOrigin(
      const GURL& origin,
      std::vector<scoped_refptr<ServiceWorkerRegistration>>* registrations) {
    bool was_called = false;
    base::Optional<blink::ServiceWorkerStatusCode> result;
    storage()->GetRegistrationsForOrigin(
        origin,
        MakeGetRegistrationsCallback(&was_called, &result, registrations));
    EXPECT_FALSE(was_called);  // always async
    base::RunLoop().RunUntilIdle();
    EXPECT_TRUE(was_called);
    return result.value();
  }

  blink::ServiceWorkerStatusCode GetUserData(
      int64_t registration_id,
      const std::vector<std::string>& keys,
      std::vector<std::string>* data) {
    bool was_called = false;
    base::Optional<blink::ServiceWorkerStatusCode> result;
    storage()->GetUserData(
        registration_id, keys,
        base::BindOnce(&GetUserDataCallback, &was_called, data, &result));
    EXPECT_FALSE(was_called);  // always async
    base::RunLoop().RunUntilIdle();
    EXPECT_TRUE(was_called);
    return result.value();
  }

  blink::ServiceWorkerStatusCode GetUserDataByKeyPrefix(
      int64_t registration_id,
      const std::string& key_prefix,
      std::vector<std::string>* data) {
    bool was_called = false;
    base::Optional<blink::ServiceWorkerStatusCode> result;
    storage()->GetUserDataByKeyPrefix(
        registration_id, key_prefix,
        base::BindOnce(&GetUserDataCallback, &was_called, data, &result));
    EXPECT_FALSE(was_called);  // always async
    base::RunLoop().RunUntilIdle();
    EXPECT_TRUE(was_called);
    return result.value();
  }

  blink::ServiceWorkerStatusCode StoreUserData(
      int64_t registration_id,
      const GURL& origin,
      const std::vector<std::pair<std::string, std::string>>& key_value_pairs) {
    bool was_called = false;
    base::Optional<blink::ServiceWorkerStatusCode> result;
    storage()->StoreUserData(registration_id, origin, key_value_pairs,
                             MakeStatusCallback(&was_called, &result));
    EXPECT_FALSE(was_called);  // always async
    base::RunLoop().RunUntilIdle();
    EXPECT_TRUE(was_called);
    return result.value();
  }

  blink::ServiceWorkerStatusCode ClearUserData(
      int64_t registration_id,
      const std::vector<std::string>& keys) {
    bool was_called = false;
    base::Optional<blink::ServiceWorkerStatusCode> result;
    storage()->ClearUserData(registration_id, keys,
                             MakeStatusCallback(&was_called, &result));
    EXPECT_FALSE(was_called);  // always async
    base::RunLoop().RunUntilIdle();
    EXPECT_TRUE(was_called);
    return result.value();
  }

  blink::ServiceWorkerStatusCode ClearUserDataByKeyPrefixes(
      int64_t registration_id,
      const std::vector<std::string>& key_prefixes) {
    bool was_called = false;
    base::Optional<blink::ServiceWorkerStatusCode> result;
    storage()->ClearUserDataByKeyPrefixes(
        registration_id, key_prefixes,
        MakeStatusCallback(&was_called, &result));
    EXPECT_FALSE(was_called);  // always async
    base::RunLoop().RunUntilIdle();
    EXPECT_TRUE(was_called);
    return result.value();
  }

  blink::ServiceWorkerStatusCode GetUserDataForAllRegistrations(
      const std::string& key,
      std::vector<std::pair<int64_t, std::string>>* data) {
    bool was_called = false;
    base::Optional<blink::ServiceWorkerStatusCode> result;
    storage()->GetUserDataForAllRegistrations(
        key, base::BindOnce(&GetUserDataForAllRegistrationsCallback,
                            &was_called, data, &result));
    EXPECT_FALSE(was_called);  // always async
    base::RunLoop().RunUntilIdle();
    EXPECT_TRUE(was_called);
    return result.value();
  }

  blink::ServiceWorkerStatusCode UpdateToActiveState(
      scoped_refptr<ServiceWorkerRegistration> registration) {
    bool was_called = false;
    base::Optional<blink::ServiceWorkerStatusCode> result;
    storage()->UpdateToActiveState(registration.get(),
                                   MakeStatusCallback(&was_called, &result));
    EXPECT_FALSE(was_called);  // always async
    base::RunLoop().RunUntilIdle();
    EXPECT_TRUE(was_called);
    return result.value();
  }

  void UpdateLastUpdateCheckTime(
      scoped_refptr<ServiceWorkerRegistration> registration) {
    storage()->UpdateLastUpdateCheckTime(registration.get());
    base::RunLoop().RunUntilIdle();
  }

  blink::ServiceWorkerStatusCode FindRegistrationForDocument(
      const GURL& document_url,
      scoped_refptr<ServiceWorkerRegistration>* registration) {
    bool was_called = false;
    base::Optional<blink::ServiceWorkerStatusCode> result;
    storage()->FindRegistrationForDocument(
        document_url, MakeFindCallback(&was_called, &result, registration));
    base::RunLoop().RunUntilIdle();
    EXPECT_TRUE(was_called);
    return result.value();
  }

  blink::ServiceWorkerStatusCode FindRegistrationForScope(
      const GURL& scope,
      scoped_refptr<ServiceWorkerRegistration>* registration) {
    bool was_called = false;
    base::Optional<blink::ServiceWorkerStatusCode> result;
    storage()->FindRegistrationForScope(
        scope, MakeFindCallback(&was_called, &result, registration));
    EXPECT_FALSE(was_called);  // always async
    base::RunLoop().RunUntilIdle();
    EXPECT_TRUE(was_called);
    return result.value();
  }

  blink::ServiceWorkerStatusCode FindRegistrationForId(
      int64_t registration_id,
      const GURL& origin,
      scoped_refptr<ServiceWorkerRegistration>* registration) {
    bool was_called = false;
    base::Optional<blink::ServiceWorkerStatusCode> result;
    storage()->FindRegistrationForId(
        registration_id, origin,
        MakeFindCallback(&was_called, &result, registration));
    base::RunLoop().RunUntilIdle();
    EXPECT_TRUE(was_called);
    return result.value();
  }

  blink::ServiceWorkerStatusCode FindRegistrationForIdOnly(
      int64_t registration_id,
      scoped_refptr<ServiceWorkerRegistration>* registration) {
    bool was_called = false;
    base::Optional<blink::ServiceWorkerStatusCode> result;
    storage()->FindRegistrationForIdOnly(
        registration_id, MakeFindCallback(&was_called, &result, registration));
    base::RunLoop().RunUntilIdle();
    EXPECT_TRUE(was_called);
    return result.value();
  }

  // Directly writes a registration using
  // ServiceWorkerDatabase::WriteRegistration rather than
  // ServiceWorkerStorage::StoreRegistration. Useful for simulating a
  // registration written by an earlier version of Chrome.
  void WriteRegistration(const RegistrationData& registration,
                         const std::vector<ResourceRecord>& resources) {
    RegistrationData deleted_version;
    std::vector<int64_t> newly_purgeable_resources;

    ASSERT_EQ(
        ServiceWorkerDatabase::STATUS_OK,
        database()->WriteRegistration(registration, resources, &deleted_version,
                                      &newly_purgeable_resources));
  }

  // user_data_directory_ must be declared first to preserve destructor order.
  base::ScopedTempDir user_data_directory_;
  base::FilePath user_data_directory_path_;
  std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
  TestBrowserThreadBundle browser_thread_bundle_;
};

TEST_F(ServiceWorkerStorageTest, DisabledStorage) {
  const GURL kScope("http://www.example.com/scope/");
  const GURL kScript("http://www.example.com/script.js");
  const GURL kDocumentUrl("http://www.example.com/scope/document.html");
  const int64_t kRegistrationId = 0;
  const int64_t kVersionId = 0;
  const int64_t kResourceId = 0;

  LazyInitialize();
  storage()->Disable();

  scoped_refptr<ServiceWorkerRegistration> found_registration;
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
            FindRegistrationForDocument(kDocumentUrl, &found_registration));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
            FindRegistrationForScope(kScope, &found_registration));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
            FindRegistrationForId(kRegistrationId, kScope.GetOrigin(),
                                  &found_registration));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
            FindRegistrationForIdOnly(kRegistrationId, &found_registration));
  EXPECT_FALSE(storage()->GetUninstallingRegistration(kScope.GetOrigin()));

  std::vector<scoped_refptr<ServiceWorkerRegistration>> found_registrations;
  EXPECT_EQ(
      blink::ServiceWorkerStatusCode::kErrorAbort,
      GetRegistrationsForOrigin(kScope.GetOrigin(), &found_registrations));

  std::vector<ServiceWorkerRegistrationInfo> all_registrations;
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
            GetAllRegistrationsInfos(&all_registrations));

  blink::mojom::ServiceWorkerRegistrationOptions options;
  options.scope = kScope;
  scoped_refptr<ServiceWorkerRegistration> live_registration =
      new ServiceWorkerRegistration(options, kRegistrationId,
                                    context()->AsWeakPtr());
  scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
      live_registration.get(), kScript, blink::mojom::ScriptType::kClassic,
      kVersionId, context()->AsWeakPtr());
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
            StoreRegistration(live_registration, live_version));

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
            UpdateToActiveState(live_registration));

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
            DeleteRegistration(kRegistrationId, kScope.GetOrigin()));

  // Response reader and writer created by the disabled storage should fail to
  // access the disk cache.
  scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
      new HttpResponseInfoIOBuffer();
  EXPECT_EQ(net::ERR_CACHE_MISS,
            ReadResponseInfo(storage(), kResourceId, info_buffer.get()));
  EXPECT_EQ(net::ERR_FAILED, WriteBasicResponse(storage(), kResourceId));
  EXPECT_EQ(net::ERR_FAILED,
            WriteResponseMetadata(storage(), kResourceId, "foo"));

  const std::string kUserDataKey = "key";
  std::vector<std::string> user_data_out;
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
            GetUserData(kRegistrationId, {kUserDataKey}, &user_data_out));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
            GetUserDataByKeyPrefix(kRegistrationId, "prefix", &user_data_out));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
            StoreUserData(kRegistrationId, kScope.GetOrigin(),
                          {{kUserDataKey, "foo"}}));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
            ClearUserData(kRegistrationId, {kUserDataKey}));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
            ClearUserDataByKeyPrefixes(kRegistrationId, {"prefix"}));
  std::vector<std::pair<int64_t, std::string>> data_list_out;
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort,
            GetUserDataForAllRegistrations(kUserDataKey, &data_list_out));

  // Next available ids should be invalid.
  EXPECT_EQ(blink::mojom::kInvalidServiceWorkerRegistrationId,
            storage()->NewRegistrationId());
  EXPECT_EQ(blink::mojom::kInvalidServiceWorkerVersionId,
            storage()->NewVersionId());
  EXPECT_EQ(kInvalidServiceWorkerResourceId, storage()->NewRegistrationId());
}

TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
  const GURL kScope("http://www.test.not/scope/");
  const GURL kDocumentUrl("http://www.test.not/scope/document.html");
  const GURL kResource1("http://www.test.not/scope/resource1.js");
  const int64_t kResource1Size = 1591234;
  const GURL kResource2("http://www.test.not/scope/resource2.js");
  const int64_t kResource2Size = 51;
  const int64_t kRegistrationId = 0;
  const int64_t kVersionId = 0;
  const base::Time kToday = base::Time::Now();
  const base::Time kYesterday = kToday - base::TimeDelta::FromDays(1);
  std::set<blink::mojom::WebFeature> used_features = {
      blink::mojom::WebFeature::kServiceWorkerControlledPage,
      blink::mojom::WebFeature::kReferrerPolicyHeader,
      blink::mojom::WebFeature::kLocationOrigin};

  scoped_refptr<ServiceWorkerRegistration> found_registration;

  // We shouldn't find anything without having stored anything.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            FindRegistrationForDocument(kDocumentUrl, &found_registration));
  EXPECT_FALSE(found_registration.get());

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            FindRegistrationForScope(kScope, &found_registration));
  EXPECT_FALSE(found_registration.get());

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            FindRegistrationForId(kRegistrationId, kScope.GetOrigin(),
                                  &found_registration));
  EXPECT_FALSE(found_registration.get());

  std::vector<ResourceRecord> resources;
  resources.push_back(ResourceRecord(1, kResource1, kResource1Size));
  resources.push_back(ResourceRecord(2, kResource2, kResource2Size));

  // Store something.
  blink::mojom::ServiceWorkerRegistrationOptions options;
  options.scope = kScope;
  scoped_refptr<ServiceWorkerRegistration> live_registration =
      new ServiceWorkerRegistration(options, kRegistrationId,
                                    context()->AsWeakPtr());
  scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
      live_registration.get(), kResource1, blink::mojom::ScriptType::kClassic,
      kVersionId, context()->AsWeakPtr());
  live_version->set_fetch_handler_existence(
      ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
  live_version->SetStatus(ServiceWorkerVersion::INSTALLED);
  live_version->script_cache_map()->SetResources(resources);
  live_version->set_used_features(
      std::set<blink::mojom::WebFeature>(used_features));
  live_registration->SetWaitingVersion(live_version);
  live_registration->set_last_update_check(kYesterday);
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            StoreRegistration(live_registration, live_version));

  // Now we should find it and get the live ptr back immediately.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForDocument(kDocumentUrl, &found_registration));
  EXPECT_EQ(live_registration, found_registration);
  EXPECT_EQ(kResource1Size + kResource2Size,
            live_registration->resources_total_size_bytes());
  EXPECT_EQ(kResource1Size + kResource2Size,
            found_registration->resources_total_size_bytes());
  EXPECT_EQ(used_features,
            found_registration->waiting_version()->used_features());
  found_registration = nullptr;

  // But FindRegistrationForScope is always async.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForScope(kScope, &found_registration));
  EXPECT_EQ(live_registration, found_registration);
  found_registration = nullptr;

  // Can be found by id too.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForId(kRegistrationId, kScope.GetOrigin(),
                                  &found_registration));
  ASSERT_TRUE(found_registration.get());
  EXPECT_EQ(kRegistrationId, found_registration->id());
  EXPECT_EQ(live_registration, found_registration);
  found_registration = nullptr;

  // Can be found by just the id too.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForIdOnly(kRegistrationId, &found_registration));
  ASSERT_TRUE(found_registration.get());
  EXPECT_EQ(kRegistrationId, found_registration->id());
  EXPECT_EQ(live_registration, found_registration);
  found_registration = nullptr;

  // Drop the live registration, but keep the version live.
  live_registration = nullptr;

  // Now FindRegistrationForDocument should be async.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForDocument(kDocumentUrl, &found_registration));
  ASSERT_TRUE(found_registration.get());
  EXPECT_EQ(kRegistrationId, found_registration->id());
  EXPECT_TRUE(found_registration->HasOneRef());

  // Check that sizes are populated correctly
  EXPECT_EQ(live_version.get(), found_registration->waiting_version());
  EXPECT_EQ(kResource1Size + kResource2Size,
            found_registration->resources_total_size_bytes());
  std::vector<ServiceWorkerRegistrationInfo> all_registrations;
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetAllRegistrationsInfos(&all_registrations));
  EXPECT_EQ(1u, all_registrations.size());
  ServiceWorkerRegistrationInfo info = all_registrations[0];
  EXPECT_EQ(kResource1Size + kResource2Size, info.stored_version_size_bytes);
  all_registrations.clear();

  // Finding by origin should provide the same result if origin is kScope.
  std::vector<scoped_refptr<ServiceWorkerRegistration>>
      registrations_for_origin;
  EXPECT_EQ(
      blink::ServiceWorkerStatusCode::kOk,
      GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin));
  EXPECT_EQ(1u, registrations_for_origin.size());
  registrations_for_origin.clear();

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
                                      &registrations_for_origin));
  EXPECT_TRUE(registrations_for_origin.empty());

  found_registration = nullptr;

  // Drop the live version too.
  live_version = nullptr;

  // And FindRegistrationForScope is always async.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForScope(kScope, &found_registration));
  ASSERT_TRUE(found_registration.get());
  EXPECT_EQ(kRegistrationId, found_registration->id());
  EXPECT_TRUE(found_registration->HasOneRef());
  EXPECT_FALSE(found_registration->active_version());
  ASSERT_TRUE(found_registration->waiting_version());
  EXPECT_EQ(kYesterday, found_registration->last_update_check());
  EXPECT_EQ(ServiceWorkerVersion::INSTALLED,
            found_registration->waiting_version()->status());

  // Update to active and update the last check time.
  scoped_refptr<ServiceWorkerVersion> temp_version =
      found_registration->waiting_version();
  temp_version->SetStatus(ServiceWorkerVersion::ACTIVATED);
  found_registration->SetActiveVersion(temp_version);
  temp_version = nullptr;
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            UpdateToActiveState(found_registration));
  found_registration->set_last_update_check(kToday);
  UpdateLastUpdateCheckTime(found_registration.get());

  found_registration = nullptr;

  // Trying to update a unstored registration to active should fail.
  scoped_refptr<ServiceWorkerRegistration> unstored_registration =
      new ServiceWorkerRegistration(options, kRegistrationId + 1,
                                    context()->AsWeakPtr());
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            UpdateToActiveState(unstored_registration));
  unstored_registration = nullptr;

  // The Find methods should return a registration with an active version
  // and the expected update time.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForDocument(kDocumentUrl, &found_registration));
  ASSERT_TRUE(found_registration.get());
  EXPECT_EQ(kRegistrationId, found_registration->id());
  EXPECT_TRUE(found_registration->HasOneRef());
  EXPECT_FALSE(found_registration->waiting_version());
  ASSERT_TRUE(found_registration->active_version());
  EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
            found_registration->active_version()->status());
  EXPECT_EQ(kToday, found_registration->last_update_check());

  // Delete from storage but with a instance still live.
  EXPECT_TRUE(context()->GetLiveVersion(kRegistrationId));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            DeleteRegistration(kRegistrationId, kScope.GetOrigin()));
  EXPECT_TRUE(context()->GetLiveVersion(kRegistrationId));

  // Should no longer be found.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            FindRegistrationForId(kRegistrationId, kScope.GetOrigin(),
                                  &found_registration));
  EXPECT_FALSE(found_registration.get());
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            FindRegistrationForIdOnly(kRegistrationId, &found_registration));
  EXPECT_FALSE(found_registration.get());

  // Deleting an unstored registration should succeed.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            DeleteRegistration(kRegistrationId + 1, kScope.GetOrigin()));
}

TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
  const GURL kScope("http://www.test.not/scope/");
  const GURL kScript("http://www.test.not/script.js");
  const GURL kDocumentUrl("http://www.test.not/scope/document.html");
  const int64_t kRegistrationId = 0;
  const int64_t kVersionId = 0;

  scoped_refptr<ServiceWorkerRegistration> found_registration;

  // Create an unstored registration.
  blink::mojom::ServiceWorkerRegistrationOptions options;
  options.scope = kScope;
  scoped_refptr<ServiceWorkerRegistration> live_registration =
      new ServiceWorkerRegistration(options, kRegistrationId,
                                    context()->AsWeakPtr());
  scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
      live_registration.get(), kScript, blink::mojom::ScriptType::kClassic,
      kVersionId, context()->AsWeakPtr());
  live_version->SetStatus(ServiceWorkerVersion::INSTALLING);
  live_registration->SetWaitingVersion(live_version);

  // Should not be findable, including by GetAllRegistrationsInfos.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            FindRegistrationForId(kRegistrationId, kScope.GetOrigin(),
                                  &found_registration));
  EXPECT_FALSE(found_registration.get());

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            FindRegistrationForIdOnly(kRegistrationId, &found_registration));
  EXPECT_FALSE(found_registration.get());

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            FindRegistrationForDocument(kDocumentUrl, &found_registration));
  EXPECT_FALSE(found_registration.get());

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            FindRegistrationForScope(kScope, &found_registration));
  EXPECT_FALSE(found_registration.get());

  std::vector<ServiceWorkerRegistrationInfo> all_registrations;
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetAllRegistrationsInfos(&all_registrations));
  EXPECT_TRUE(all_registrations.empty());

  std::vector<scoped_refptr<ServiceWorkerRegistration>>
      registrations_for_origin;
  EXPECT_EQ(
      blink::ServiceWorkerStatusCode::kOk,
      GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin));
  EXPECT_TRUE(registrations_for_origin.empty());

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
                                      &registrations_for_origin));
  EXPECT_TRUE(registrations_for_origin.empty());

  // Notify storage of it being installed.
  storage()->NotifyInstallingRegistration(live_registration.get());

  // Now should be findable.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForId(kRegistrationId, kScope.GetOrigin(),
                                  &found_registration));
  EXPECT_EQ(live_registration, found_registration);
  found_registration = nullptr;

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForIdOnly(kRegistrationId, &found_registration));
  EXPECT_EQ(live_registration, found_registration);
  found_registration = nullptr;

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForDocument(kDocumentUrl, &found_registration));
  EXPECT_EQ(live_registration, found_registration);
  found_registration = nullptr;

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForScope(kScope, &found_registration));
  EXPECT_EQ(live_registration, found_registration);
  found_registration = nullptr;

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetAllRegistrationsInfos(&all_registrations));
  EXPECT_EQ(1u, all_registrations.size());
  all_registrations.clear();

  // Finding by origin should provide the same result if origin is kScope.
  EXPECT_EQ(
      blink::ServiceWorkerStatusCode::kOk,
      GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin));
  EXPECT_EQ(1u, registrations_for_origin.size());
  registrations_for_origin.clear();

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
                                      &registrations_for_origin));
  EXPECT_TRUE(registrations_for_origin.empty());

  // Notify storage of installation no longer happening.
  storage()->NotifyDoneInstallingRegistration(
      live_registration.get(), nullptr, blink::ServiceWorkerStatusCode::kOk);

  // Once again, should not be findable.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            FindRegistrationForId(kRegistrationId, kScope.GetOrigin(),
                                  &found_registration));
  EXPECT_FALSE(found_registration.get());

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            FindRegistrationForIdOnly(kRegistrationId, &found_registration));
  EXPECT_FALSE(found_registration.get());

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            FindRegistrationForDocument(kDocumentUrl, &found_registration));
  EXPECT_FALSE(found_registration.get());

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            FindRegistrationForScope(kScope, &found_registration));
  EXPECT_FALSE(found_registration.get());

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetAllRegistrationsInfos(&all_registrations));
  EXPECT_TRUE(all_registrations.empty());

  EXPECT_EQ(
      blink::ServiceWorkerStatusCode::kOk,
      GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin));
  EXPECT_TRUE(registrations_for_origin.empty());

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
                                      &registrations_for_origin));
  EXPECT_TRUE(registrations_for_origin.empty());
}

TEST_F(ServiceWorkerStorageTest, StoreUserData) {
  const GURL kScope("http://www.test.not/scope/");
  const GURL kScript("http://www.test.not/script.js");
  LazyInitialize();

  // Store a registration.
  scoped_refptr<ServiceWorkerRegistration> live_registration =
      CreateLiveRegistrationAndVersion(kScope, kScript);
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            StoreRegistration(live_registration,
                              live_registration->waiting_version()));
  const int64_t kRegistrationId = live_registration->id();

  // Store user data associated with the registration.
  std::vector<std::string> data_out;
  EXPECT_EQ(
      blink::ServiceWorkerStatusCode::kOk,
      StoreUserData(kRegistrationId, kScope.GetOrigin(), {{"key", "data"}}));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetUserData(kRegistrationId, {"key"}, &data_out));
  ASSERT_EQ(1u, data_out.size());
  EXPECT_EQ("data", data_out[0]);
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            GetUserData(kRegistrationId, {"unknown_key"}, &data_out));
  std::vector<std::pair<int64_t, std::string>> data_list_out;
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetUserDataForAllRegistrations("key", &data_list_out));
  ASSERT_EQ(1u, data_list_out.size());
  EXPECT_EQ(kRegistrationId, data_list_out[0].first);
  EXPECT_EQ("data", data_list_out[0].second);
  data_list_out.clear();
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetUserDataForAllRegistrations("unknown_key", &data_list_out));
  EXPECT_EQ(0u, data_list_out.size());
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            ClearUserData(kRegistrationId, {"key"}));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            GetUserData(kRegistrationId, {"key"}, &data_out));

  // Write/overwrite multiple user data keys.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            StoreUserData(
                kRegistrationId, kScope.GetOrigin(),
                {{"key", "overwrite"}, {"key3", "data3"}, {"key4", "data4"}}));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            GetUserData(kRegistrationId, {"key2"}, &data_out));
  EXPECT_TRUE(data_out.empty());
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetUserData(kRegistrationId, {"key", "key3", "key4"}, &data_out));
  ASSERT_EQ(3u, data_out.size());
  EXPECT_EQ("overwrite", data_out[0]);
  EXPECT_EQ("data3", data_out[1]);
  EXPECT_EQ("data4", data_out[2]);
  // Multiple gets fail if one is not found.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            GetUserData(kRegistrationId, {"key", "key2"}, &data_out));
  EXPECT_TRUE(data_out.empty());

  // Delete multiple user data keys, even if some are not found.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            ClearUserData(kRegistrationId, {"key", "key2", "key3"}));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            GetUserData(kRegistrationId, {"key"}, &data_out));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            GetUserData(kRegistrationId, {"key2"}, &data_out));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            GetUserData(kRegistrationId, {"key3"}, &data_out));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetUserData(kRegistrationId, {"key4"}, &data_out));
  ASSERT_EQ(1u, data_out.size());
  EXPECT_EQ("data4", data_out[0]);

  // Get/delete multiple user data keys by prefixes.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            StoreUserData(kRegistrationId, kScope.GetOrigin(),
                          {{"prefixA", "data1"},
                           {"prefixA2", "data2"},
                           {"prefixB", "data3"},
                           {"prefixC", "data4"}}));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetUserDataByKeyPrefix(kRegistrationId, "prefix", &data_out));
  ASSERT_EQ(4u, data_out.size());
  EXPECT_EQ("data1", data_out[0]);
  EXPECT_EQ("data2", data_out[1]);
  EXPECT_EQ("data3", data_out[2]);
  EXPECT_EQ("data4", data_out[3]);
  EXPECT_EQ(
      blink::ServiceWorkerStatusCode::kOk,
      ClearUserDataByKeyPrefixes(kRegistrationId, {"prefixA", "prefixC"}));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetUserDataByKeyPrefix(kRegistrationId, "prefix", &data_out));
  ASSERT_EQ(1u, data_out.size());
  EXPECT_EQ("data3", data_out[0]);

  // User data should be deleted when the associated registration is deleted.
  ASSERT_EQ(
      blink::ServiceWorkerStatusCode::kOk,
      StoreUserData(kRegistrationId, kScope.GetOrigin(), {{"key", "data"}}));
  ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetUserData(kRegistrationId, {"key"}, &data_out));
  ASSERT_EQ(1u, data_out.size());
  ASSERT_EQ("data", data_out[0]);

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            DeleteRegistration(kRegistrationId, kScope.GetOrigin()));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            GetUserData(kRegistrationId, {"key"}, &data_out));
  data_list_out.clear();
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetUserDataForAllRegistrations("key", &data_list_out));
  EXPECT_EQ(0u, data_list_out.size());

  // Data access with an invalid registration id should be failed.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
            StoreUserData(blink::mojom::kInvalidServiceWorkerRegistrationId,
                          kScope.GetOrigin(), {{"key", "data"}}));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
            GetUserData(blink::mojom::kInvalidServiceWorkerRegistrationId,
                        {"key"}, &data_out));
  EXPECT_EQ(
      blink::ServiceWorkerStatusCode::kErrorFailed,
      GetUserDataByKeyPrefix(blink::mojom::kInvalidServiceWorkerRegistrationId,
                             "prefix", &data_out));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
            ClearUserData(blink::mojom::kInvalidServiceWorkerRegistrationId,
                          {"key"}));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
            ClearUserDataByKeyPrefixes(
                blink::mojom::kInvalidServiceWorkerRegistrationId, {"prefix"}));

  // Data access with an empty key should be failed.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
            StoreUserData(kRegistrationId, kScope.GetOrigin(),
                          std::vector<std::pair<std::string, std::string>>()));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
            StoreUserData(kRegistrationId, kScope.GetOrigin(),
                          {{std::string(), "data"}}));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
            StoreUserData(kRegistrationId, kScope.GetOrigin(),
                          {{std::string(), "data"}, {"key", "data"}}));
  EXPECT_EQ(
      blink::ServiceWorkerStatusCode::kErrorFailed,
      GetUserData(kRegistrationId, std::vector<std::string>(), &data_out));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
            GetUserDataByKeyPrefix(kRegistrationId, std::string(), &data_out));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
            GetUserData(kRegistrationId, {std::string()}, &data_out));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
            GetUserData(kRegistrationId, {std::string(), "key"}, &data_out));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
            ClearUserData(kRegistrationId, std::vector<std::string>()));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
            ClearUserData(kRegistrationId, {std::string()}));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
            ClearUserData(kRegistrationId, {std::string(), "key"}));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
            ClearUserDataByKeyPrefixes(kRegistrationId, {}));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
            ClearUserDataByKeyPrefixes(kRegistrationId, {std::string()}));
  data_list_out.clear();
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed,
            GetUserDataForAllRegistrations(std::string(), &data_list_out));
}

// The *_BeforeInitialize tests exercise the API before LazyInitialize() is
// called.
TEST_F(ServiceWorkerStorageTest, StoreUserData_BeforeInitialize) {
  const int kRegistrationId = 0;
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            StoreUserData(kRegistrationId, GURL("https://example.com"),
                          {{"key", "data"}}));
}

TEST_F(ServiceWorkerStorageTest, GetUserData_BeforeInitialize) {
  const int kRegistrationId = 0;
  std::vector<std::string> data_out;
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            GetUserData(kRegistrationId, {"key"}, &data_out));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorNotFound,
            GetUserDataByKeyPrefix(kRegistrationId, "prefix", &data_out));
}

TEST_F(ServiceWorkerStorageTest, ClearUserData_BeforeInitialize) {
  const int kRegistrationId = 0;
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            ClearUserData(kRegistrationId, {"key"}));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            ClearUserDataByKeyPrefixes(kRegistrationId, {"prefix"}));
}

TEST_F(ServiceWorkerStorageTest,
       GetUserDataForAllRegistrations_BeforeInitialize) {
  std::vector<std::pair<int64_t, std::string>> data_list_out;
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            GetUserDataForAllRegistrations("key", &data_list_out));
  EXPECT_TRUE(data_list_out.empty());
}

class ServiceWorkerResourceStorageTest : public ServiceWorkerStorageTest {
 public:
  void SetUp() override {
    ServiceWorkerStorageTest::SetUp();
    LazyInitialize();

    scope_ = GURL("http://www.test.not/scope/");
    script_ = GURL("http://www.test.not/script.js");
    import_ = GURL("http://www.test.not/import.js");
    document_url_ = GURL("http://www.test.not/scope/document.html");
    registration_id_ = storage()->NewRegistrationId();
    version_id_ = storage()->NewVersionId();
    resource_id1_ = storage()->NewResourceId();
    resource_id2_ = storage()->NewResourceId();
    resource_id1_size_ = 239193;
    resource_id2_size_ = 59923;

    // Cons up a new registration+version with two script resources.
    RegistrationData data;
    data.registration_id = registration_id_;
    data.scope = scope_;
    data.script = script_;
    data.version_id = version_id_;
    data.is_active = false;
    std::vector<ResourceRecord> resources;
    resources.push_back(
        ResourceRecord(resource_id1_, script_, resource_id1_size_));
    resources.push_back(
        ResourceRecord(resource_id2_, import_, resource_id2_size_));
    registration_ = storage()->GetOrCreateRegistration(data, resources);
    registration_->waiting_version()->SetStatus(ServiceWorkerVersion::NEW);

    // Add the resources ids to the uncommitted list.
    storage()->StoreUncommittedResourceId(resource_id1_);
    storage()->StoreUncommittedResourceId(resource_id2_);
    base::RunLoop().RunUntilIdle();
    std::set<int64_t> verify_ids;
    EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
              database()->GetUncommittedResourceIds(&verify_ids));
    EXPECT_EQ(2u, verify_ids.size());

    // And dump something in the disk cache for them.
    WriteBasicResponse(storage(), resource_id1_);
    WriteBasicResponse(storage(), resource_id2_);
    EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
    EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));

    // Storing the registration/version should take the resources ids out
    // of the uncommitted list.
    EXPECT_EQ(
        blink::ServiceWorkerStatusCode::kOk,
        StoreRegistration(registration_, registration_->waiting_version()));
    verify_ids.clear();
    EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
              database()->GetUncommittedResourceIds(&verify_ids));
    EXPECT_TRUE(verify_ids.empty());
  }

 protected:
  GURL scope_;
  GURL script_;
  GURL import_;
  GURL document_url_;
  int64_t registration_id_;
  int64_t version_id_;
  int64_t resource_id1_;
  uint64_t resource_id1_size_;
  int64_t resource_id2_;
  uint64_t resource_id2_size_;
  scoped_refptr<ServiceWorkerRegistration> registration_;
};

class ServiceWorkerResourceStorageDiskTest
    : public ServiceWorkerResourceStorageTest {
 public:
  void SetUp() override {
    ASSERT_TRUE(InitUserDataDirectory());
    ServiceWorkerResourceStorageTest::SetUp();
  }
};

TEST_F(ServiceWorkerResourceStorageTest,
       WriteMetadataWithServiceWorkerResponseMetadataWriter) {
  const char kMetadata1[] = "Test metadata";
  const char kMetadata2[] = "small";
  int64_t new_resource_id_ = storage()->NewResourceId();
  // Writing metadata to nonexistent resoirce ID must fail.
  EXPECT_GE(0, WriteResponseMetadata(storage(), new_resource_id_, kMetadata1));

  // Check metadata is written.
  EXPECT_EQ(static_cast<int>(strlen(kMetadata1)),
            WriteResponseMetadata(storage(), resource_id1_, kMetadata1));
  EXPECT_TRUE(VerifyResponseMetadata(storage(), resource_id1_, kMetadata1));
  EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));

  // Check metadata is written and truncated.
  EXPECT_EQ(static_cast<int>(strlen(kMetadata2)),
            WriteResponseMetadata(storage(), resource_id1_, kMetadata2));
  EXPECT_TRUE(VerifyResponseMetadata(storage(), resource_id1_, kMetadata2));
  EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));

  // Check metadata is deleted.
  EXPECT_EQ(0, WriteResponseMetadata(storage(), resource_id1_, ""));
  EXPECT_FALSE(VerifyResponseMetadata(storage(), resource_id1_, ""));
  EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
}

TEST_F(ServiceWorkerResourceStorageTest,
       WriteMetadataWithServiceWorkerScriptCacheMap) {
  const char kMetadata1[] = "Test metadata";
  const char kMetadata2[] = "small";
  ServiceWorkerVersion* version = registration_->waiting_version();
  EXPECT_TRUE(version);

  // Writing metadata to nonexistent URL must fail.
  EXPECT_GE(0,
            WriteMetadata(version, GURL("http://www.test.not/nonexistent.js"),
                          kMetadata1));
  // Clearing metadata of nonexistent URL must fail.
  EXPECT_GE(0,
            ClearMetadata(version, GURL("http://www.test.not/nonexistent.js")));

  // Check metadata is written.
  EXPECT_EQ(static_cast<int>(strlen(kMetadata1)),
            WriteMetadata(version, script_, kMetadata1));
  EXPECT_TRUE(VerifyResponseMetadata(storage(), resource_id1_, kMetadata1));
  EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));

  // Check metadata is written and truncated.
  EXPECT_EQ(static_cast<int>(strlen(kMetadata2)),
            WriteMetadata(version, script_, kMetadata2));
  EXPECT_TRUE(VerifyResponseMetadata(storage(), resource_id1_, kMetadata2));
  EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));

  // Check metadata is deleted.
  EXPECT_EQ(0, ClearMetadata(version, script_));
  EXPECT_FALSE(VerifyResponseMetadata(storage(), resource_id1_, ""));
  EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
}

TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_NoLiveVersion) {
  bool was_called = false;
  blink::ServiceWorkerStatusCode result =
      blink::ServiceWorkerStatusCode::kErrorFailed;
  std::set<int64_t> verify_ids;

  registration_->SetWaitingVersion(nullptr);
  registration_ = nullptr;

  // Deleting the registration should result in the resources being added to the
  // purgeable list and then doomed in the disk cache and removed from that
  // list.
  storage()->DeleteRegistration(
      registration_id_, scope_.GetOrigin(),
      base::BindOnce(&VerifyPurgeableListStatusCallback,
                     base::Unretained(database()), &verify_ids, &was_called,
                     &result));
  base::RunLoop().RunUntilIdle();
  ASSERT_TRUE(was_called);
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, result);
  EXPECT_EQ(2u, verify_ids.size());
  verify_ids.clear();
  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
            database()->GetPurgeableResourceIds(&verify_ids));
  EXPECT_TRUE(verify_ids.empty());

  EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
  EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
}

TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_WaitingVersion) {
  bool was_called = false;
  blink::ServiceWorkerStatusCode result =
      blink::ServiceWorkerStatusCode::kErrorFailed;
  std::set<int64_t> verify_ids;

  // Deleting the registration should result in the resources being added to the
  // purgeable list and then doomed in the disk cache and removed from that
  // list.
  storage()->DeleteRegistration(
      registration_->id(), scope_.GetOrigin(),
      base::BindOnce(&VerifyPurgeableListStatusCallback,
                     base::Unretained(database()), &verify_ids, &was_called,
                     &result));
  base::RunLoop().RunUntilIdle();
  ASSERT_TRUE(was_called);
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, result);
  EXPECT_EQ(2u, verify_ids.size());
  verify_ids.clear();
  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
            database()->GetPurgeableResourceIds(&verify_ids));
  EXPECT_EQ(2u, verify_ids.size());

  EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, false));
  EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, false));

  // Doom the version, now it happens.
  registration_->waiting_version()->Doom();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, result);
  EXPECT_EQ(2u, verify_ids.size());
  verify_ids.clear();
  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
            database()->GetPurgeableResourceIds(&verify_ids));
  EXPECT_TRUE(verify_ids.empty());

  EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
  EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
}

TEST_F(ServiceWorkerResourceStorageTest, DeleteRegistration_ActiveVersion) {
  // Promote the worker to active and add a controllee.
  registration_->SetActiveVersion(registration_->waiting_version());
  storage()->UpdateToActiveState(registration_.get(), base::DoNothing());
  ServiceWorkerRemoteProviderEndpoint remote_endpoint;
  std::unique_ptr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow(
      33 /* dummy render process id */, 1 /* dummy provider_id */,
      true /* is_parent_frame_secure */, context()->AsWeakPtr(),
      &remote_endpoint);
  registration_->active_version()->AddControllee(host.get());

  bool was_called = false;
  blink::ServiceWorkerStatusCode result =
      blink::ServiceWorkerStatusCode::kErrorFailed;
  std::set<int64_t> verify_ids;

  // Deleting the registration should move the resources to the purgeable list
  // but keep them available.
  storage()->DeleteRegistration(
      registration_->id(), scope_.GetOrigin(),
      base::BindOnce(&VerifyPurgeableListStatusCallback,
                     base::Unretained(database()), &verify_ids, &was_called,
                     &result));
  base::RunLoop().RunUntilIdle();
  ASSERT_TRUE(was_called);
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, result);
  EXPECT_EQ(2u, verify_ids.size());
  verify_ids.clear();
  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
            database()->GetPurgeableResourceIds(&verify_ids));
  EXPECT_EQ(2u, verify_ids.size());

  EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
  EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));

  // Removing the controllee should cause the resources to be deleted.
  registration_->active_version()->RemoveControllee(host.get()->client_uuid());
  registration_->active_version()->Doom();
  base::RunLoop().RunUntilIdle();
  verify_ids.clear();
  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
            database()->GetPurgeableResourceIds(&verify_ids));
  EXPECT_TRUE(verify_ids.empty());

  EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
  EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
}

TEST_F(ServiceWorkerResourceStorageDiskTest, CleanupOnRestart) {
  // Promote the worker to active and add a controllee.
  registration_->SetActiveVersion(registration_->waiting_version());
  registration_->SetWaitingVersion(nullptr);
  storage()->UpdateToActiveState(registration_.get(), base::DoNothing());
  ServiceWorkerRemoteProviderEndpoint remote_endpoint;
  std::unique_ptr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow(
      33 /* dummy render process id */, 1 /* dummy provider_id */,
      true /* is_parent_frame_secure */, context()->AsWeakPtr(),
      &remote_endpoint);
  registration_->active_version()->AddControllee(host.get());

  bool was_called = false;
  blink::ServiceWorkerStatusCode result =
      blink::ServiceWorkerStatusCode::kErrorFailed;
  std::set<int64_t> verify_ids;

  // Deleting the registration should move the resources to the purgeable list
  // but keep them available.
  storage()->DeleteRegistration(
      registration_->id(), scope_.GetOrigin(),
      base::BindOnce(&VerifyPurgeableListStatusCallback,
                     base::Unretained(database()), &verify_ids, &was_called,
                     &result));
  base::RunLoop().RunUntilIdle();
  ASSERT_TRUE(was_called);
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, result);
  EXPECT_EQ(2u, verify_ids.size());
  verify_ids.clear();
  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
            database()->GetPurgeableResourceIds(&verify_ids));
  EXPECT_EQ(2u, verify_ids.size());

  EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, true));
  EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, true));

  // Also add an uncommitted resource.
  int64_t kStaleUncommittedResourceId = storage()->NewResourceId();
  storage()->StoreUncommittedResourceId(kStaleUncommittedResourceId);
  base::RunLoop().RunUntilIdle();
  verify_ids.clear();
  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
            database()->GetUncommittedResourceIds(&verify_ids));
  EXPECT_EQ(1u, verify_ids.size());
  WriteBasicResponse(storage(), kStaleUncommittedResourceId);
  EXPECT_TRUE(
      VerifyBasicResponse(storage(), kStaleUncommittedResourceId, true));

  // Simulate browser shutdown. The purgeable and uncommitted resources are now
  // stale.
  InitializeTestHelper();
  LazyInitialize();

  // Store a new uncommitted resource. This triggers stale resource cleanup.
  int64_t kNewResourceId = storage()->NewResourceId();
  WriteBasicResponse(storage(), kNewResourceId);
  storage()->StoreUncommittedResourceId(kNewResourceId);
  base::RunLoop().RunUntilIdle();

  // The stale resources should be purged, but the new resource should persist.
  verify_ids.clear();
  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
            database()->GetUncommittedResourceIds(&verify_ids));
  ASSERT_EQ(1u, verify_ids.size());
  EXPECT_EQ(kNewResourceId, *verify_ids.begin());

  // Purging resources needs interactions with SimpleCache's worker thread,
  // so single RunUntilIdle() call may not be sufficient.
  while (storage()->is_purge_pending_)
    base::RunLoop().RunUntilIdle();

  verify_ids.clear();
  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
            database()->GetPurgeableResourceIds(&verify_ids));
  EXPECT_TRUE(verify_ids.empty());
  EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
  EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
  EXPECT_FALSE(
      VerifyBasicResponse(storage(), kStaleUncommittedResourceId, false));
  EXPECT_TRUE(VerifyBasicResponse(storage(), kNewResourceId, true));
}

TEST_F(ServiceWorkerResourceStorageDiskTest, DeleteAndStartOver) {
  EXPECT_FALSE(storage()->IsDisabled());
  ASSERT_TRUE(base::DirectoryExists(storage()->GetDiskCachePath()));
  ASSERT_TRUE(base::DirectoryExists(storage()->GetDatabasePath()));

  base::RunLoop run_loop;
  blink::ServiceWorkerStatusCode status =
      blink::ServiceWorkerStatusCode::kErrorFailed;
  storage()->DeleteAndStartOver(
      base::BindOnce(&StatusAndQuitCallback, &status, run_loop.QuitClosure()));
  run_loop.Run();

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
  EXPECT_TRUE(storage()->IsDisabled());
  EXPECT_FALSE(base::DirectoryExists(storage()->GetDiskCachePath()));
  EXPECT_FALSE(base::DirectoryExists(storage()->GetDatabasePath()));
}

TEST_F(ServiceWorkerResourceStorageDiskTest,
       DeleteAndStartOver_UnrelatedFileExists) {
  EXPECT_FALSE(storage()->IsDisabled());
  ASSERT_TRUE(base::DirectoryExists(storage()->GetDiskCachePath()));
  ASSERT_TRUE(base::DirectoryExists(storage()->GetDatabasePath()));

  // Create an unrelated file in the database directory to make sure such a file
  // does not prevent DeleteAndStartOver.
  base::FilePath file_path;
  ASSERT_TRUE(
      base::CreateTemporaryFileInDir(storage()->GetDatabasePath(), &file_path));
  ASSERT_TRUE(base::PathExists(file_path));

  base::RunLoop run_loop;
  blink::ServiceWorkerStatusCode status =
      blink::ServiceWorkerStatusCode::kErrorFailed;
  storage()->DeleteAndStartOver(
      base::BindOnce(&StatusAndQuitCallback, &status, run_loop.QuitClosure()));
  run_loop.Run();

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
  EXPECT_TRUE(storage()->IsDisabled());
  EXPECT_FALSE(base::DirectoryExists(storage()->GetDiskCachePath()));
  EXPECT_FALSE(base::DirectoryExists(storage()->GetDatabasePath()));
}

TEST_F(ServiceWorkerResourceStorageDiskTest,
       DeleteAndStartOver_OpenedFileExists) {
  EXPECT_FALSE(storage()->IsDisabled());
  ASSERT_TRUE(base::DirectoryExists(storage()->GetDiskCachePath()));
  ASSERT_TRUE(base::DirectoryExists(storage()->GetDatabasePath()));

  // Create an unrelated opened file in the database directory to make sure such
  // a file does not prevent DeleteAndStartOver on non-Windows platforms.
  base::FilePath file_path;
  base::ScopedFILE file(base::CreateAndOpenTemporaryFileInDir(
      storage()->GetDatabasePath(), &file_path));
  ASSERT_TRUE(file);
  ASSERT_TRUE(base::PathExists(file_path));

  base::RunLoop run_loop;
  blink::ServiceWorkerStatusCode status =
      blink::ServiceWorkerStatusCode::kErrorNotFound;
  storage()->DeleteAndStartOver(
      base::BindOnce(&StatusAndQuitCallback, &status, run_loop.QuitClosure()));
  run_loop.Run();

#if defined(OS_WIN)
  // On Windows, deleting the directory containing an opened file should fail.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed, status);
  EXPECT_TRUE(storage()->IsDisabled());
  EXPECT_TRUE(base::DirectoryExists(storage()->GetDiskCachePath()));
  EXPECT_TRUE(base::DirectoryExists(storage()->GetDatabasePath()));
#else
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
  EXPECT_TRUE(storage()->IsDisabled());
  EXPECT_FALSE(base::DirectoryExists(storage()->GetDiskCachePath()));
  EXPECT_FALSE(base::DirectoryExists(storage()->GetDatabasePath()));
#endif
}

TEST_F(ServiceWorkerResourceStorageTest, UpdateRegistration) {
  // Promote the worker to active worker and add a controllee.
  registration_->SetActiveVersion(registration_->waiting_version());
  storage()->UpdateToActiveState(registration_.get(), base::DoNothing());
  ServiceWorkerRemoteProviderEndpoint remote_endpoint;
  std::unique_ptr<ServiceWorkerProviderHost> host = CreateProviderHostForWindow(
      33 /* dummy render process id */, 1 /* dummy provider_id */,
      true /* is_parent_frame_secure */, helper_->context()->AsWeakPtr(),
      &remote_endpoint);
  registration_->active_version()->AddControllee(host.get());

  bool was_called = false;
  blink::ServiceWorkerStatusCode result =
      blink::ServiceWorkerStatusCode::kErrorFailed;
  std::set<int64_t> verify_ids;

  // Make an updated registration.
  scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
      registration_.get(), script_, blink::mojom::ScriptType::kClassic,
      storage()->NewVersionId(), context()->AsWeakPtr());
  live_version->SetStatus(ServiceWorkerVersion::NEW);
  registration_->SetWaitingVersion(live_version);
  std::vector<ResourceRecord> records;
  records.push_back(ResourceRecord(10, live_version->script_url(), 100));
  live_version->script_cache_map()->SetResources(records);
  live_version->set_fetch_handler_existence(
      ServiceWorkerVersion::FetchHandlerExistence::EXISTS);

  // Writing the registration should move the old version's resources to the
  // purgeable list but keep them available.
  storage()->StoreRegistration(
      registration_.get(), registration_->waiting_version(),
      base::BindOnce(&VerifyPurgeableListStatusCallback,
                     base::Unretained(database()), &verify_ids, &was_called,
                     &result));
  base::RunLoop().RunUntilIdle();
  ASSERT_TRUE(was_called);
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, result);
  EXPECT_EQ(2u, verify_ids.size());
  verify_ids.clear();
  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
            database()->GetPurgeableResourceIds(&verify_ids));
  EXPECT_EQ(2u, verify_ids.size());

  EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id1_, false));
  EXPECT_TRUE(VerifyBasicResponse(storage(), resource_id2_, false));

  // Removing the controllee should cause the old version's resources to be
  // deleted.
  registration_->active_version()->RemoveControllee(host.get()->client_uuid());
  registration_->active_version()->Doom();
  base::RunLoop().RunUntilIdle();
  verify_ids.clear();
  EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
            database()->GetPurgeableResourceIds(&verify_ids));
  EXPECT_TRUE(verify_ids.empty());

  EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id1_, false));
  EXPECT_FALSE(VerifyBasicResponse(storage(), resource_id2_, false));
}

TEST_F(ServiceWorkerStorageTest, FindRegistration_LongestScopeMatch) {
  LazyInitialize();
  const GURL kDocumentUrl("http://www.example.com/scope/foo");
  scoped_refptr<ServiceWorkerRegistration> found_registration;

  // Registration for "/scope/".
  const GURL kScope1("http://www.example.com/scope/");
  const GURL kScript1("http://www.example.com/script1.js");
  scoped_refptr<ServiceWorkerRegistration> live_registration1 =
      CreateLiveRegistrationAndVersion(kScope1, kScript1);

  // Registration for "/scope/foo".
  const GURL kScope2("http://www.example.com/scope/foo");
  const GURL kScript2("http://www.example.com/script2.js");
  scoped_refptr<ServiceWorkerRegistration> live_registration2 =
      CreateLiveRegistrationAndVersion(kScope2, kScript2);

  // Registration for "/scope/foobar".
  const GURL kScope3("http://www.example.com/scope/foobar");
  const GURL kScript3("http://www.example.com/script3.js");
  scoped_refptr<ServiceWorkerRegistration> live_registration3 =
      CreateLiveRegistrationAndVersion(kScope3, kScript3);

  // Notify storage of them being installed.
  storage()->NotifyInstallingRegistration(live_registration1.get());
  storage()->NotifyInstallingRegistration(live_registration2.get());
  storage()->NotifyInstallingRegistration(live_registration3.get());

  // Find a registration among installing ones.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForDocument(kDocumentUrl, &found_registration));
  EXPECT_EQ(live_registration2, found_registration);
  found_registration = nullptr;

  // Store registrations.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            StoreRegistration(live_registration1,
                              live_registration1->waiting_version()));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            StoreRegistration(live_registration2,
                              live_registration2->waiting_version()));
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            StoreRegistration(live_registration3,
                              live_registration3->waiting_version()));

  // Notify storage of installations no longer happening.
  storage()->NotifyDoneInstallingRegistration(
      live_registration1.get(), nullptr, blink::ServiceWorkerStatusCode::kOk);
  storage()->NotifyDoneInstallingRegistration(
      live_registration2.get(), nullptr, blink::ServiceWorkerStatusCode::kOk);
  storage()->NotifyDoneInstallingRegistration(
      live_registration3.get(), nullptr, blink::ServiceWorkerStatusCode::kOk);

  // Find a registration among installed ones.
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForDocument(kDocumentUrl, &found_registration));
  EXPECT_EQ(live_registration2, found_registration);
}

// Test fixture that uses disk storage, rather than memory. Useful for tests
// that test persistence by simulating browser shutdown and restart.
class ServiceWorkerStorageDiskTest : public ServiceWorkerStorageTest {
 public:
  void SetUp() override {
    ASSERT_TRUE(InitUserDataDirectory());
    ServiceWorkerStorageTest::SetUp();
  }
};

TEST_F(ServiceWorkerStorageTest, OriginTrialsAbsentEntryAndEmptyEntry) {
  const GURL origin1("http://www1.example.com");
  const GURL scope1("http://www1.example.com/foo/");
  RegistrationData data1;
  data1.registration_id = 100;
  data1.scope = scope1;
  data1.script = GURL(origin1.spec() + "/script.js");
  data1.version_id = 1000;
  data1.is_active = true;
  data1.resources_total_size_bytes = 100;
  // Don't set origin_trial_tokens to simulate old database entry.
  std::vector<ResourceRecord> resources1;
  resources1.push_back(ResourceRecord(1, data1.script, 100));
  WriteRegistration(data1, resources1);

  const GURL origin2("http://www2.example.com");
  const GURL scope2("http://www2.example.com/foo/");
  RegistrationData data2;
  data2.registration_id = 200;
  data2.scope = scope2;
  data2.script = GURL(origin2.spec() + "/script.js");
  data2.version_id = 2000;
  data2.is_active = true;
  data2.resources_total_size_bytes = 200;
  // Set empty origin_trial_tokens.
  data2.origin_trial_tokens = blink::TrialTokenValidator::FeatureToTokensMap();
  std::vector<ResourceRecord> resources2;
  resources2.push_back(ResourceRecord(2, data2.script, 200));
  WriteRegistration(data2, resources2);

  scoped_refptr<ServiceWorkerRegistration> found_registration;

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForDocument(scope1, &found_registration));
  ASSERT_TRUE(found_registration->active_version());
  // origin_trial_tokens must be unset.
  EXPECT_FALSE(found_registration->active_version()->origin_trial_tokens());

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForDocument(scope2, &found_registration));
  ASSERT_TRUE(found_registration->active_version());
  // Empty origin_trial_tokens must exist.
  ASSERT_TRUE(found_registration->active_version()->origin_trial_tokens());
  EXPECT_TRUE(
      found_registration->active_version()->origin_trial_tokens()->empty());
}

class ServiceWorkerStorageOriginTrialsDiskTest
    : public ServiceWorkerStorageTest {
 public:
  ServiceWorkerStorageOriginTrialsDiskTest() {
    blink::TrialTokenValidator::SetOriginTrialPolicyGetter(base::BindRepeating(
        [](blink::OriginTrialPolicy* policy) { return policy; },
        base::Unretained(&origin_trial_policy_)));
  }
  ~ServiceWorkerStorageOriginTrialsDiskTest() override {
    blink::TrialTokenValidator::ResetOriginTrialPolicyGetter();
  }
  void SetUp() override {
    ASSERT_TRUE(InitUserDataDirectory());
    ServiceWorkerStorageTest::SetUp();
  }

 private:
  class TestOriginTrialPolicy : public blink::OriginTrialPolicy {
   public:
    bool IsOriginTrialsSupported() const override { return true; }
    base::StringPiece GetPublicKey() const override {
      return base::StringPiece(reinterpret_cast<const char*>(kTestPublicKey),
                               base::size(kTestPublicKey));
    }
    bool IsOriginSecure(const GURL& url) const override {
      return content::IsOriginSecure(url);
    }
  };
  TestOriginTrialPolicy origin_trial_policy_;
};

TEST_F(ServiceWorkerStorageOriginTrialsDiskTest, FromMainScript) {
  LazyInitialize();
  const GURL kScope("https://valid.example.com/scope");
  const GURL kScript("https://valid.example.com/script.js");
  const int64_t kRegistrationId = 1;
  const int64_t kVersionId = 1;
  blink::mojom::ServiceWorkerRegistrationOptions options;
  options.scope = kScope;
  scoped_refptr<ServiceWorkerRegistration> registration =
      new ServiceWorkerRegistration(options, kRegistrationId,
                                    context()->AsWeakPtr());
  scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
      registration.get(), kScript, blink::mojom::ScriptType::kClassic,
      kVersionId, context()->AsWeakPtr());

  net::HttpResponseInfo http_info;
  http_info.ssl_info.cert =
      net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
  EXPECT_TRUE(http_info.ssl_info.is_valid());
  // SSL3 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
  http_info.ssl_info.connection_status = 0x300039;

  const std::string kHTTPHeaderLine("HTTP/1.1 200 OK\n\n");
  const std::string kOriginTrial("Origin-Trial: ");
  // Token for Feature1 which expires 2033-05-18.
  // generate_token.py valid.example.com Feature1 --expire-timestamp=2000000000
  // TODO(horo): Generate this sample token during the build.
  const std::string kFeature1Token(
      "AtiUXksymWhTv5ipBE7853JytiYb0RMj3wtEBjqu3PeufQPwV1oEaNjHt4R/oEBfcK0UiWlA"
      "P2b9BE2/eThqcAYAAABYeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5leGFtcGxlLmNvbTo0"
      "NDMiLCAiZmVhdHVyZSI6ICJGZWF0dXJlMSIsICJleHBpcnkiOiAyMDAwMDAwMDAwfQ==");
  // Token for Feature2 which expires 2033-05-18.
  // generate_token.py valid.example.com Feature2 --expire-timestamp=2000000000
  // TODO(horo): Generate this sample token during the build.
  const std::string kFeature2Token1(
      "ApmHVC6Dpez0KQNBy13o6cGuoB5AgzOLN0keQMyAN5mjebCwR0MA8/IyjKQIlyom2RuJVg/u"
      "LmnqEpldfewkbA8AAABYeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5leGFtcGxlLmNvbTo0"
      "NDMiLCAiZmVhdHVyZSI6ICJGZWF0dXJlMiIsICJleHBpcnkiOiAyMDAwMDAwMDAwfQ==");
  // Token for Feature2 which expires 2036-07-18.
  // generate_token.py valid.example.com Feature2 --expire-timestamp=2100000000
  // TODO(horo): Generate this sample token during the build.
  const std::string kFeature2Token2(
      "AmV2SSxrYstE2zSwZToy7brAbIJakd146apC/6+VDflLmc5yDfJlHGILe5+ZynlcliG7clOR"
      "fHhXCzS5Lh1v4AAAAABYeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5leGFtcGxlLmNvbTo0"
      "NDMiLCAiZmVhdHVyZSI6ICJGZWF0dXJlMiIsICJleHBpcnkiOiAyMTAwMDAwMDAwfQ==");
  // Token for Feature3 which expired 2001-09-09.
  // generate_token.py valid.example.com Feature3 --expire-timestamp=1000000000
  const std::string kFeature3ExpiredToken(
      "AtSAc03z4qvid34W4MHMxyRFUJKlubZ+P5cs5yg6EiBWcagVbnm5uBgJMJN34pag7D5RywGV"
      "ol2RFf+4Sdm1hQ4AAABYeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5leGFtcGxlLmNvbTo0"
      "NDMiLCAiZmVhdHVyZSI6ICJGZWF0dXJlMyIsICJleHBpcnkiOiAxMDAwMDAwMDAwfQ==");
  http_info.headers = base::MakeRefCounted<net::HttpResponseHeaders>("");
  http_info.headers->AddHeader(kOriginTrial + kFeature1Token);
  http_info.headers->AddHeader(kOriginTrial + kFeature2Token1);
  http_info.headers->AddHeader(kOriginTrial + kFeature2Token2);
  http_info.headers->AddHeader(kOriginTrial + kFeature3ExpiredToken);
  version->SetMainScriptHttpResponseInfo(http_info);
  ASSERT_TRUE(version->origin_trial_tokens());
  const blink::TrialTokenValidator::FeatureToTokensMap& tokens =
      *version->origin_trial_tokens();
  ASSERT_EQ(2UL, tokens.size());
  ASSERT_EQ(1UL, tokens.at("Feature1").size());
  EXPECT_EQ(kFeature1Token, tokens.at("Feature1")[0]);
  ASSERT_EQ(2UL, tokens.at("Feature2").size());
  EXPECT_EQ(kFeature2Token1, tokens.at("Feature2")[0]);
  EXPECT_EQ(kFeature2Token2, tokens.at("Feature2")[1]);

  std::vector<ResourceRecord> record;
  record.push_back(ResourceRecord(1, kScript, 100));
  version->script_cache_map()->SetResources(record);
  version->set_fetch_handler_existence(
      ServiceWorkerVersion::FetchHandlerExistence::EXISTS);
  version->SetStatus(ServiceWorkerVersion::INSTALLED);
  registration->SetActiveVersion(version);

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            StoreRegistration(registration, version));

  // Simulate browser shutdown and restart.
  registration = nullptr;
  version = nullptr;
  InitializeTestHelper();
  LazyInitialize();

  scoped_refptr<ServiceWorkerRegistration> found_registration;
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForDocument(kScope, &found_registration));
  ASSERT_TRUE(found_registration->active_version());
  const blink::TrialTokenValidator::FeatureToTokensMap& found_tokens =
      *found_registration->active_version()->origin_trial_tokens();
  ASSERT_EQ(2UL, found_tokens.size());
  ASSERT_EQ(1UL, found_tokens.at("Feature1").size());
  EXPECT_EQ(kFeature1Token, found_tokens.at("Feature1")[0]);
  ASSERT_EQ(2UL, found_tokens.at("Feature2").size());
  EXPECT_EQ(kFeature2Token1, found_tokens.at("Feature2")[0]);
  EXPECT_EQ(kFeature2Token2, found_tokens.at("Feature2")[1]);
}

// Tests loading a registration that has no navigation preload state.
TEST_F(ServiceWorkerStorageTest, AbsentNavigationPreloadState) {
  const GURL origin1("http://www1.example.com");
  const GURL scope1("http://www1.example.com/foo/");
  RegistrationData data1;
  data1.registration_id = 100;
  data1.scope = scope1;
  data1.script = GURL(origin1.spec() + "/script.js");
  data1.version_id = 1000;
  data1.is_active = true;
  data1.resources_total_size_bytes = 100;
  // Don't set navigation preload state to simulate old database entry.
  std::vector<ResourceRecord> resources1;
  resources1.push_back(ResourceRecord(1, data1.script, 100));
  WriteRegistration(data1, resources1);

  scoped_refptr<ServiceWorkerRegistration> found_registration;
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForDocument(scope1, &found_registration));
  const blink::mojom::NavigationPreloadState& registration_state =
      found_registration->navigation_preload_state();
  EXPECT_FALSE(registration_state.enabled);
  EXPECT_EQ("true", registration_state.header);
  ASSERT_TRUE(found_registration->active_version());
  const blink::mojom::NavigationPreloadState& state =
      found_registration->active_version()->navigation_preload_state();
  EXPECT_FALSE(state.enabled);
  EXPECT_EQ("true", state.header);
}

TEST_F(ServiceWorkerStorageDiskTest, RegisteredOriginCount) {
  {
    base::HistogramTester histogram_tester;
    LazyInitialize();
    EXPECT_TRUE(registered_origins().empty());
    histogram_tester.ExpectUniqueSample("ServiceWorker.RegisteredOriginCount",
                                        0, 1);
  }

  std::pair<GURL, GURL> scope_and_script_pairs[] = {
      {GURL("https://www.example.com/scope/"),
       GURL("https://www.example.com/script.js")},
      {GURL("https://www.example.com/scope/foo"),
       GURL("https://www.example.com/script.js")},
      {GURL("https://www.test.com/scope/foobar"),
       GURL("https://www.test.com/script.js")},
      {GURL("https://example.com/scope/"),
       GURL("https://example.com/script.js")},
  };
  std::vector<scoped_refptr<ServiceWorkerRegistration>> registrations;
  for (const auto& pair : scope_and_script_pairs) {
    registrations.emplace_back(
        CreateLiveRegistrationAndVersion(pair.first, pair.second));
  }

  // Store all registrations.
  for (const auto& registration : registrations) {
    EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
              StoreRegistration(registration, registration->waiting_version()));
  }

  // Simulate browser shutdown and restart.
  registrations.clear();
  InitializeTestHelper();
  {
    base::HistogramTester histogram_tester;
    LazyInitialize();
    EXPECT_EQ(3UL, registered_origins().size());
    histogram_tester.ExpectUniqueSample("ServiceWorker.RegisteredOriginCount",
                                        3, 1);
  }

  // Re-initializing shouldn't re-record the histogram.
  {
    base::HistogramTester histogram_tester;
    LazyInitialize();
    EXPECT_EQ(3UL, registered_origins().size());
    histogram_tester.ExpectTotalCount("ServiceWorker.RegisteredOriginCount", 0);
  }
}

// Tests loading a registration with a disabled navigation preload
// state.
TEST_F(ServiceWorkerStorageDiskTest, DisabledNavigationPreloadState) {
  LazyInitialize();
  const GURL kScope("https://valid.example.com/scope");
  const GURL kScript("https://valid.example.com/script.js");
  scoped_refptr<ServiceWorkerRegistration> registration =
      CreateLiveRegistrationAndVersion(kScope, kScript);
  ServiceWorkerVersion* version = registration->waiting_version();
  version->SetStatus(ServiceWorkerVersion::ACTIVATED);
  registration->SetActiveVersion(version);
  registration->EnableNavigationPreload(false);

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            StoreRegistration(registration, version));

  // Simulate browser shutdown and restart.
  registration = nullptr;
  version = nullptr;
  InitializeTestHelper();
  LazyInitialize();

  scoped_refptr<ServiceWorkerRegistration> found_registration;
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForDocument(kScope, &found_registration));
  const blink::mojom::NavigationPreloadState& registration_state =
      found_registration->navigation_preload_state();
  EXPECT_FALSE(registration_state.enabled);
  EXPECT_EQ("true", registration_state.header);
  ASSERT_TRUE(found_registration->active_version());
  const blink::mojom::NavigationPreloadState& state =
      found_registration->active_version()->navigation_preload_state();
  EXPECT_FALSE(state.enabled);
  EXPECT_EQ("true", state.header);
}

// Tests loading a registration with an enabled navigation preload state, as
// well as a custom header value.
TEST_F(ServiceWorkerStorageDiskTest, EnabledNavigationPreloadState) {
  LazyInitialize();
  const GURL kScope("https://valid.example.com/scope");
  const GURL kScript("https://valid.example.com/script.js");
  const std::string kHeaderValue("custom header value");
  scoped_refptr<ServiceWorkerRegistration> registration =
      CreateLiveRegistrationAndVersion(kScope, kScript);
  ServiceWorkerVersion* version = registration->waiting_version();
  version->SetStatus(ServiceWorkerVersion::ACTIVATED);
  registration->SetActiveVersion(version);
  registration->EnableNavigationPreload(true);
  registration->SetNavigationPreloadHeader(kHeaderValue);

  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            StoreRegistration(registration, version));

  // Simulate browser shutdown and restart.
  registration = nullptr;
  version = nullptr;
  InitializeTestHelper();
  LazyInitialize();

  scoped_refptr<ServiceWorkerRegistration> found_registration;
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
            FindRegistrationForDocument(kScope, &found_registration));
  const blink::mojom::NavigationPreloadState& registration_state =
      found_registration->navigation_preload_state();
  EXPECT_TRUE(registration_state.enabled);
  EXPECT_EQ(kHeaderValue, registration_state.header);
  ASSERT_TRUE(found_registration->active_version());
  const blink::mojom::NavigationPreloadState& state =
      found_registration->active_version()->navigation_preload_state();
  EXPECT_TRUE(state.enabled);
  EXPECT_EQ(kHeaderValue, state.header);
}

}  // namespace service_worker_storage_unittest
}  // namespace content
