// Copyright 2022 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/worker/service_worker_registration_map.h"

#include <list>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_util.h"
#include "base/synchronization/lock.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/script/exception_message.h"
#include "cobalt/script/promise.h"
#include "cobalt/script/script_value.h"
#include "cobalt/worker/service_worker_jobs.h"
#include "cobalt/worker/service_worker_registration_object.h"
#include "cobalt/worker/service_worker_update_via_cache.h"
#include "url/gurl.h"
#include "url/origin.h"


namespace cobalt {
namespace worker {

namespace {

// Returns the serialized URL excluding the fragment.
std::string SerializeExcludingFragment(const GURL& url) {
  GURL::Replacements replacements;
  replacements.ClearUsername();
  replacements.ClearPassword();
  replacements.ClearQuery();
  replacements.ClearRef();
  return base::TrimString(url.ReplaceComponents(replacements).spec(), "/",
                          base::TrimPositions::TRIM_TRAILING)
      .as_string();
}

}  // namespace

ServiceWorkerRegistrationMap::ServiceWorkerRegistrationMap(
    const ServiceWorkerPersistentSettings::Options& options) {
  service_worker_persistent_settings_.reset(
      new ServiceWorkerPersistentSettings(options));
  DCHECK(service_worker_persistent_settings_);

  // TODO(b/259731731) For now do not read from persisted settings until
  // activation of persisted registrations works.
  ReadPersistentSettings();
}

void ServiceWorkerRegistrationMap::ReadPersistentSettings() {
  service_worker_persistent_settings_->ReadServiceWorkerRegistrationMapSettings(
      registration_map_);
}

scoped_refptr<ServiceWorkerRegistrationObject>
ServiceWorkerRegistrationMap::MatchServiceWorkerRegistration(
    const url::Origin& storage_key, const GURL& client_url) {
  TRACE_EVENT0(
      "cobalt::worker",
      "ServiceWorkerRegistrationMap::MatchServiceWorkerRegistration()");
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  // Algorithm for Match Service Worker Registration:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#scope-match-algorithm
  GURL matching_scope;

  // 1. Run the following steps atomically.
  {
    base::AutoLock lock(mutex_);

    // 2. Let clientURLString be serialized clientURL.
    std::string client_url_string(client_url.spec());

    // 3. Let matchingScopeString be the empty string.
    std::string matching_scope_string;

    // 4. Let scopeStringSet be an empty list.
    std::list<std::string> scope_string_set;

    // 5. For each (entry storage key, entry scope) → registration of
    // registration map:
    for (const auto& entry : registration_map_) {
      // 5.1. If storage key equals entry storage key, then append entry scope
      // to the end of scopeStringSet.
      if (entry.first.first == storage_key) {
        scope_string_set.push_back(entry.first.second);
      }
    }

    // 6. Set matchingScopeString to the longest value in scopeStringSet which
    // the value of clientURLString starts with, if it exists.
    for (const auto& scope_string : scope_string_set) {
      // TODO(b/234659851): Verify whether this is the expected behavior, where
      // a substring of the scope string is compared with the client url string.
      bool starts_with =
          client_url_string.substr(0, scope_string.length()) == scope_string;
      if (starts_with &&
          (scope_string.length() > matching_scope_string.length())) {
        matching_scope_string = scope_string;
      }
    }

    // 7. Let matchingScope be null.
    // 8. If matchingScopeString is not the empty string, then:
    if (!matching_scope_string.empty()) {
      // 8.1. Set matchingScope to the result of parsing matchingScopeString.
      matching_scope = GURL(matching_scope_string);

      // 8.2. Assert: matchingScope’s origin and clientURL’s origin are same
      // origin.
      DCHECK_EQ(url::Origin::Create(matching_scope),
                url::Origin::Create(client_url));
    }
  }
  // 9. Return the result of running Get Registration given storage key and
  // matchingScope.
  return GetRegistration(storage_key, matching_scope);
}

scoped_refptr<ServiceWorkerRegistrationObject>
ServiceWorkerRegistrationMap::GetRegistration(const url::Origin& storage_key,
                                              const GURL& scope) {
  TRACE_EVENT0("cobalt::worker",
               "ServiceWorkerRegistrationMap::GetRegistration()");
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  // Algorithm for Get Registration:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#get-registration-algorithm

  // 1. Run the following steps atomically.
  base::AutoLock lock(mutex_);

  // 2. Let scopeString be the empty string.
  std::string scope_string;

  // 3. If scope is not null, set scopeString to serialized scope with the
  // exclude fragment flag set.
  if (!scope.is_empty()) {
    scope_string = SerializeExcludingFragment(scope);
  }

  RegistrationMapKey registration_key(storage_key, scope_string);
  // 4. For each (entry storage key, entry scope) → registration of registration
  // map:
  for (const auto& entry : registration_map_) {
    // 4.1. If storage key equals entry storage key and scopeString matches
    // entry scope, then return registration.
    if (entry.first == registration_key) {
      return entry.second.get();
    }
  }

  // 5. Return null.
  return nullptr;
}

std::vector<scoped_refptr<ServiceWorkerRegistrationObject>>
ServiceWorkerRegistrationMap::GetRegistrations(const url::Origin& storage_key) {
  TRACE_EVENT0("cobalt::worker",
               "ServiceWorkerRegistrationMap::GetRegistrations()");
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  base::AutoLock lock(mutex_);
  std::vector<scoped_refptr<ServiceWorkerRegistrationObject>> result;
  for (const auto& entry : registration_map_) {
    if (entry.first.first == storage_key) {
      result.push_back(std::move(entry.second));
    }
  }
  return result;
}

scoped_refptr<ServiceWorkerRegistrationObject>
ServiceWorkerRegistrationMap::SetRegistration(
    const url::Origin& storage_key, const GURL& scope,
    const ServiceWorkerUpdateViaCache& update_via_cache) {
  TRACE_EVENT0("cobalt::worker",
               "ServiceWorkerRegistrationMap::SetRegistration()");
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  // Algorithm for Set Registration:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#set-registration-algorithm

  // 1. Run the following steps atomically.
  base::AutoLock lock(mutex_);

  // 2. Let scopeString be serialized scope with the exclude fragment flag set.
  std::string scope_string = SerializeExcludingFragment(scope);

  // 3. Let registration be a new service worker registration whose storage key
  // is set to storage key, scope url is set to scope, and update via cache mode
  // is set to updateViaCache.
  scoped_refptr<ServiceWorkerRegistrationObject> registration(
      new ServiceWorkerRegistrationObject(storage_key, scope,
                                          update_via_cache));

  // 4. Set registration map[(storage key, scopeString)] to registration.
  RegistrationMapKey registration_key(storage_key, scope_string);
  registration_map_.insert(std::make_pair(
      registration_key,
      scoped_refptr<ServiceWorkerRegistrationObject>(registration)));

  // 5. Return registration.
  return registration;
}

void ServiceWorkerRegistrationMap::RemoveRegistration(
    const url::Origin& storage_key, const GURL& scope) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  std::string scope_string = SerializeExcludingFragment(scope);
  RegistrationMapKey registration_key(storage_key, scope_string);
  auto entry = registration_map_.find(registration_key);
  DCHECK(entry != registration_map_.end());
  if (entry != registration_map_.end()) {
    registration_map_.erase(entry);
    service_worker_persistent_settings_
        ->RemoveServiceWorkerRegistrationObjectSettings(registration_key);
  }
}

bool ServiceWorkerRegistrationMap::IsUnregistered(
    ServiceWorkerRegistrationObject* registration) {
  // A service worker registration is said to be unregistered if registration
  // map[this service worker registration's (storage key, serialized scope url)]
  // is not this service worker registration.
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#dfn-service-worker-registration-unregistered
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (!registration) return true;
  std::string scope_string =
      SerializeExcludingFragment(registration->scope_url());
  RegistrationMapKey registration_key(registration->storage_key(),
                                      scope_string);
  auto entry = registration_map_.find(registration_key);
  if (entry == registration_map_.end()) return true;

  return entry->second.get() != registration;
}

void ServiceWorkerRegistrationMap::HandleUserAgentShutdown(
    ServiceWorkerJobs* jobs) {
  TRACE_EVENT0("cobalt::worker",
               "ServiceWorkerRegistrationMap::HandleUserAgentShutdown()");
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  // Algorithm for Handle User Agent Shutdown:
  //   https://www.w3.org/TR/2022/CRD-service-workers-20220712/#on-user-agent-shutdown-algorithm

  // 1. For each (storage key, scope) -> registration of registration map:
  for (auto& entry : registration_map_) {
    const scoped_refptr<ServiceWorkerRegistrationObject>& registration =
        entry.second;
    // 1.1. If registration’s installing worker installingWorker is not null,
    // then:
    if (registration->installing_worker()) {
      // 1.1.1. If registration’s waiting worker is null and registration’s
      // active worker is null, invoke Clear Registration with registration and
      // continue to the next iteration of the loop.
      if (!registration->waiting_worker() && !registration->active_worker()) {
        jobs->ClearRegistration(registration);
        continue;
      } else {
        // 1.1.2. Else, set installingWorker to null.
        registration->set_installing_worker(nullptr);
      }
    }

    if (registration->waiting_worker()) {
      // 1.2. If registration’s waiting worker is not null, run the following
      // substep in parallel:

      // 1.2.1. Invoke Activate with registration.
      jobs->Activate(registration);
    }
  }
}

void ServiceWorkerRegistrationMap::AbortAllActive() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  for (auto entry : registration_map_) {
    entry.second->AbortAll();
  }
}

void ServiceWorkerRegistrationMap::PersistRegistration(
    const url::Origin& storage_key, const GURL& scope) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  std::string scope_string = SerializeExcludingFragment(scope);
  RegistrationMapKey registration_key(storage_key, scope_string);
  auto entry = registration_map_.find(registration_key);
  if (entry != registration_map_.end()) {
    service_worker_persistent_settings_
        ->WriteServiceWorkerRegistrationObjectSettings(registration_key,
                                                       entry->second);
  } else {
    service_worker_persistent_settings_
        ->RemoveServiceWorkerRegistrationObjectSettings(registration_key);
  }
}

}  // namespace worker
}  // namespace cobalt
