// Copyright 2017 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_context_watcher.h"

#include "base/bind.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"

namespace content {

namespace {

void DidRegisterServiceWorker(int64_t* registration_id_out,
                              blink::ServiceWorkerStatusCode status,
                              const std::string& status_message,
                              int64_t registration_id) {
  ASSERT_TRUE(registration_id_out);
  EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk, status);
  *registration_id_out = registration_id;
}

void DidUnregisterServiceWorker(blink::ServiceWorkerStatusCode* status_out,
                                blink::ServiceWorkerStatusCode status) {
  ASSERT_TRUE(status_out);
  *status_out = status;
}

class WatcherCallback {
 public:
  WatcherCallback() : weak_factory_(this) {}

  ~WatcherCallback() {}

  scoped_refptr<ServiceWorkerContextWatcher> StartWatch(
      scoped_refptr<ServiceWorkerContextWrapper> context) {
    scoped_refptr<ServiceWorkerContextWatcher> watcher =
        base::MakeRefCounted<ServiceWorkerContextWatcher>(
            context,
            base::BindRepeating(&WatcherCallback::OnRegistrationUpdated,
                                weak_factory_.GetWeakPtr()),
            base::BindRepeating(&WatcherCallback::OnVersionUpdated,
                                weak_factory_.GetWeakPtr()),
            base::BindRepeating(&WatcherCallback::OnErrorReported,
                                weak_factory_.GetWeakPtr()));
    watcher->Start();
    return watcher;
  }

  const std::map<int64_t, ServiceWorkerRegistrationInfo>& registrations()
      const {
    return registrations_;
  }

  const std::map<int64_t, std::map<int64_t, ServiceWorkerVersionInfo>>&
  versions() const {
    return versions_;
  }
  const std::map<
      int64_t,
      std::map<int64_t,
               std::vector<ServiceWorkerContextCoreObserver::ErrorInfo>>>&
  errors() const {
    return errors_;
  }

  int callback_count() const { return callback_count_; }

 private:
  void OnRegistrationUpdated(
      const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
    ++callback_count_;
    for (const auto& info : registrations) {
      if (info.delete_flag ==
          ServiceWorkerRegistrationInfo::DeleteFlag::IS_DELETED) {
        registrations_.erase(info.registration_id);
      } else {
        registrations_[info.registration_id] = info;
      }
    }
  }

  void OnVersionUpdated(const std::vector<ServiceWorkerVersionInfo>& versions) {
    ++callback_count_;
    for (const auto& info : versions) {
      versions_[info.registration_id][info.version_id] = info;
    }
  }

  void OnErrorReported(
      int64_t registration_id,
      int64_t version_id,
      const ServiceWorkerContextCoreObserver::ErrorInfo& error_info) {
    ++callback_count_;
    errors_[registration_id][version_id].push_back(error_info);
  }

  std::map<int64_t /* registration_id */, ServiceWorkerRegistrationInfo>
      registrations_;
  std::map<int64_t /* registration_id */,
           std::map<int64_t /* version_id */, ServiceWorkerVersionInfo>>
      versions_;
  std::map<int64_t /* registration_id */,
           std::map<int64_t /* version_id */,
                    std::vector<ServiceWorkerContextCoreObserver::ErrorInfo>>>
      errors_;

  int callback_count_ = 0;

  base::WeakPtrFactory<WatcherCallback> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(WatcherCallback);
};

}  // namespace

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

  void SetUp() override {
    helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
    base::RunLoop().RunUntilIdle();
  }

  void TearDown() override {
    helper_.reset();
    base::RunLoop().RunUntilIdle();
  }

 protected:
  ServiceWorkerContextCore* context() { return helper_->context(); }
  ServiceWorkerContextWrapper* context_wrapper() {
    return helper_->context_wrapper();
  }
  int64_t RegisterServiceWorker(const GURL& scope, const GURL& script_url) {
    blink::mojom::ServiceWorkerRegistrationOptions options;
    options.scope = scope;
    int64_t registration_id = blink::mojom::kInvalidServiceWorkerRegistrationId;
    context()->RegisterServiceWorker(
        script_url, options,
        base::BindOnce(&DidRegisterServiceWorker, &registration_id));
    base::RunLoop().RunUntilIdle();
    return registration_id;
  }

  blink::ServiceWorkerStatusCode UnregisterServiceWorker(const GURL& scope) {
    blink::ServiceWorkerStatusCode status =
        blink::ServiceWorkerStatusCode::kErrorFailed;
    context()->UnregisterServiceWorker(
        scope, base::BindOnce(&DidUnregisterServiceWorker, &status));
    base::RunLoop().RunUntilIdle();
    return status;
  }

  void ReportError(
      scoped_refptr<ServiceWorkerContextWatcher> watcher,
      int64_t version_id,
      const ServiceWorkerContextCoreObserver::ErrorInfo& error_info) {
    watcher->OnErrorReported(version_id, error_info);
  }

 private:
  std::unique_ptr<EmbeddedWorkerTestHelper> helper_;
  TestBrowserThreadBundle browser_thread_bundle_;

  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextWatcherTest);
};

TEST_F(ServiceWorkerContextWatcherTest, NoServiceWorker) {
  WatcherCallback watcher_callback;
  scoped_refptr<ServiceWorkerContextWatcher> watcher =
      watcher_callback.StartWatch(context_wrapper());
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(0u, watcher_callback.registrations().size());
  EXPECT_EQ(0u, watcher_callback.versions().size());
  EXPECT_EQ(0u, watcher_callback.errors().size());
  // OnRegistrationUpdated() and OnVersionUpdated() must be called with the
  // empty initial data.
  EXPECT_EQ(2, watcher_callback.callback_count());
  watcher->Stop();
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(0u, watcher_callback.registrations().size());
  EXPECT_EQ(0u, watcher_callback.versions().size());
  EXPECT_EQ(2, watcher_callback.callback_count());
}

TEST_F(ServiceWorkerContextWatcherTest, StoredServiceWorkers) {
  GURL scope_1 = GURL("https://www1.example.com/");
  GURL script_1 = GURL("https://www1.example.com/worker.js");
  int64_t registration_id_1 = RegisterServiceWorker(scope_1, script_1);
  ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
            registration_id_1);

  GURL scope_2 = GURL("https://www2.example.com/");
  GURL script_2 = GURL("https://www2.example.com/worker.js");
  int64_t registration_id_2 = RegisterServiceWorker(scope_2, script_2);
  ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
            registration_id_2);

  WatcherCallback watcher_callback;
  scoped_refptr<ServiceWorkerContextWatcher> watcher =
      watcher_callback.StartWatch(context_wrapper());
  base::RunLoop().RunUntilIdle();

  ASSERT_EQ(2u, watcher_callback.registrations().size());
  EXPECT_EQ(scope_1,
            watcher_callback.registrations().at(registration_id_1).scope);
  EXPECT_EQ(scope_2,
            watcher_callback.registrations().at(registration_id_2).scope);
  ASSERT_EQ(2u, watcher_callback.versions().size());
  EXPECT_EQ(script_1, watcher_callback.versions()
                          .at(registration_id_1)
                          .begin()
                          ->second.script_url);
  EXPECT_EQ(script_2, watcher_callback.versions()
                          .at(registration_id_2)
                          .begin()
                          ->second.script_url);
  EXPECT_EQ(0u, watcher_callback.errors().size());

  watcher->Stop();
  base::RunLoop().RunUntilIdle();
}

TEST_F(ServiceWorkerContextWatcherTest, RegisteredServiceWorker) {
  GURL scope_1 = GURL("https://www1.example.com/");
  GURL script_1 = GURL("https://www1.example.com/worker.js");
  int64_t registration_id_1 = RegisterServiceWorker(scope_1, script_1);
  ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
            registration_id_1);

  WatcherCallback watcher_callback;
  scoped_refptr<ServiceWorkerContextWatcher> watcher =
      watcher_callback.StartWatch(context_wrapper());
  base::RunLoop().RunUntilIdle();
  ASSERT_EQ(1u, watcher_callback.registrations().size());
  EXPECT_EQ(scope_1,
            watcher_callback.registrations().at(registration_id_1).scope);
  ASSERT_EQ(1u, watcher_callback.versions().size());
  EXPECT_EQ(script_1, watcher_callback.versions()
                          .at(registration_id_1)
                          .begin()
                          ->second.script_url);
  EXPECT_EQ(0u, watcher_callback.errors().size());

  GURL scope_2 = GURL("https://www2.example.com/");
  GURL script_2 = GURL("https://www2.example.com/worker.js");
  int64_t registration_id_2 = RegisterServiceWorker(scope_2, script_2);
  ASSERT_EQ(2u, watcher_callback.registrations().size());
  EXPECT_EQ(scope_1,
            watcher_callback.registrations().at(registration_id_1).scope);
  EXPECT_EQ(scope_2,
            watcher_callback.registrations().at(registration_id_2).scope);
  ASSERT_EQ(2u, watcher_callback.versions().size());
  EXPECT_EQ(script_1, watcher_callback.versions()
                          .at(registration_id_1)
                          .begin()
                          ->second.script_url);
  EXPECT_EQ(script_2, watcher_callback.versions()
                          .at(registration_id_2)
                          .begin()
                          ->second.script_url);
  EXPECT_EQ(0u, watcher_callback.errors().size());

  watcher->Stop();
  base::RunLoop().RunUntilIdle();
}

TEST_F(ServiceWorkerContextWatcherTest, UnregisteredServiceWorker) {
  GURL scope_1 = GURL("https://www1.example.com/");
  GURL script_1 = GURL("https://www1.example.com/worker.js");
  int64_t registration_id_1 = RegisterServiceWorker(scope_1, script_1);
  ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
            registration_id_1);

  GURL scope_2 = GURL("https://www2.example.com/");
  GURL script_2 = GURL("https://www2.example.com/worker.js");
  int64_t registration_id_2 = RegisterServiceWorker(scope_2, script_2);

  WatcherCallback watcher_callback;
  scoped_refptr<ServiceWorkerContextWatcher> watcher =
      watcher_callback.StartWatch(context_wrapper());
  base::RunLoop().RunUntilIdle();

  ASSERT_EQ(2u, watcher_callback.registrations().size());
  EXPECT_EQ(scope_1,
            watcher_callback.registrations().at(registration_id_1).scope);
  EXPECT_EQ(scope_2,
            watcher_callback.registrations().at(registration_id_2).scope);
  ASSERT_EQ(2u, watcher_callback.versions().size());

  ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk,
            UnregisterServiceWorker(scope_1));

  ASSERT_EQ(1u, watcher_callback.registrations().size());
  EXPECT_EQ(scope_2,
            watcher_callback.registrations().at(registration_id_2).scope);

  watcher->Stop();
  base::RunLoop().RunUntilIdle();
}

TEST_F(ServiceWorkerContextWatcherTest, ErrorReport) {
  GURL scope = GURL("https://www1.example.com/");
  GURL script = GURL("https://www1.example.com/worker.js");
  int64_t registration_id = RegisterServiceWorker(scope, script);
  ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);

  WatcherCallback watcher_callback;
  scoped_refptr<ServiceWorkerContextWatcher> watcher =
      watcher_callback.StartWatch(context_wrapper());
  base::RunLoop().RunUntilIdle();
  ASSERT_EQ(1u, watcher_callback.registrations().size());
  EXPECT_EQ(scope, watcher_callback.registrations().at(registration_id).scope);
  ASSERT_EQ(1u, watcher_callback.versions().size());
  EXPECT_EQ(script, watcher_callback.versions()
                        .at(registration_id)
                        .begin()
                        ->second.script_url);
  int64_t version_id =
      watcher_callback.versions().at(registration_id).begin()->first;
  EXPECT_EQ(0u, watcher_callback.errors().size());

  base::string16 message(base::ASCIIToUTF16("HELLO"));
  ReportError(
      watcher, version_id,
      ServiceWorkerContextCoreObserver::ErrorInfo(message, 0, 0, script));
  base::RunLoop().RunUntilIdle();
  ASSERT_EQ(1u, watcher_callback.errors().size());
  ASSERT_EQ(1u, watcher_callback.errors().at(registration_id).size());
  ASSERT_EQ(
      1u, watcher_callback.errors().at(registration_id).at(version_id).size());
  EXPECT_EQ(message, watcher_callback.errors()
                         .at(registration_id)
                         .at(version_id)[0]
                         .error_message);

  watcher->Stop();
  base::RunLoop().RunUntilIdle();
}

// This test checks that even if ServiceWorkerContextWatcher::Stop() is called
// quickly after Start() is called, the crash (crbug.com/727877) should not
// happen.
TEST_F(ServiceWorkerContextWatcherTest, StopQuickly) {
  WatcherCallback watcher_callback;
  scoped_refptr<ServiceWorkerContextWatcher> watcher =
      watcher_callback.StartWatch(context_wrapper());
  watcher->Stop();

  int callback_count = watcher_callback.callback_count();
  GURL scope = GURL("https://www1.example.com/");
  GURL script = GURL("https://www1.example.com/worker.js");
  int64_t registration_id = RegisterServiceWorker(scope, script);
  ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(callback_count, watcher_callback.callback_count());
}

// This test checks that any callbacks should not be executed after
// ServiceWorkerContextWatcher::Stop() is called.
TEST_F(ServiceWorkerContextWatcherTest, Race) {
  GURL scope = GURL("https://www1.example.com/");
  GURL script = GURL("https://www1.example.com/worker.js");
  int64_t registration_id = RegisterServiceWorker(scope, script);
  ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, registration_id);
  base::RunLoop().RunUntilIdle();

  WatcherCallback watcher_callback;
  scoped_refptr<ServiceWorkerContextWatcher> watcher =
      watcher_callback.StartWatch(context_wrapper());
  base::RunLoop().RunUntilIdle();
  watcher->Stop();

  int callback_count = watcher_callback.callback_count();
  base::string16 message(base::ASCIIToUTF16("HELLO"));
  ReportError(
      watcher, 0 /*version_id*/,
      ServiceWorkerContextCoreObserver::ErrorInfo(message, 0, 0, script));
  base::RunLoop().RunUntilIdle();
  EXPECT_EQ(callback_count, watcher_callback.callback_count());
}

}  // namespace content
