// 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/web/agent.h"

#include <map>
#include <memory>
#include <utility>

#include "base/observer_list.h"
#include "base/threading/thread_checker.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/loader/fetcher_factory.h"
#include "cobalt/loader/script_loader_factory.h"
#include "cobalt/script/environment_settings.h"
#include "cobalt/script/error_report.h"
#include "cobalt/script/execution_state.h"
#include "cobalt/script/global_environment.h"
#include "cobalt/script/javascript_engine.h"
#include "cobalt/script/script_runner.h"
#include "cobalt/script/wrappable.h"
#include "cobalt/web/blob.h"
#include "cobalt/web/context.h"
#include "cobalt/web/environment_settings.h"
#include "cobalt/web/url.h"
#include "cobalt/web/window_or_worker_global_scope.h"
#include "cobalt/worker/service_worker.h"
#include "cobalt/worker/service_worker_jobs.h"
#include "cobalt/worker/service_worker_object.h"
#include "cobalt/worker/service_worker_registration.h"
#include "cobalt/worker/service_worker_registration_object.h"

namespace cobalt {
namespace web {
// Private Web Context implementation. Each Agent owns a single instance of
// this class, which performs all the actual work. All functions of this class
// must be called on the message loop of the Agent thread, so they
// execute synchronously with respect to one another.
namespace {
class Impl : public Context {
 public:
  Impl(const std::string& name, const Agent::Options& options);
  virtual ~Impl();

  void AddEnvironmentSettingsChangeObserver(
      EnvironmentSettingsChangeObserver* observer) final;
  void RemoveEnvironmentSettingsChangeObserver(
      EnvironmentSettingsChangeObserver* observer) final;

  // Context
  //
  void set_message_loop(base::MessageLoop* message_loop) {
    message_loop_ = message_loop;
  }
  base::MessageLoop* message_loop() const final { return message_loop_; }
  void ShutDownJavaScriptEngine() final;
  loader::FetcherFactory* fetcher_factory() const final {
    return fetcher_factory_.get();
  }
  loader::ScriptLoaderFactory* script_loader_factory() const final {
    return script_loader_factory_.get();
  }
  script::JavaScriptEngine* javascript_engine() const final {
    return javascript_engine_.get();
  }
  script::GlobalEnvironment* global_environment() const final {
    return global_environment_.get();
  }
  script::ExecutionState* execution_state() const final {
    return execution_state_.get();
  }
  script::ScriptRunner* script_runner() const final {
    return script_runner_.get();
  }
  Blob::Registry* blob_registry() const final { return blob_registry_.get(); }
  network::NetworkModule* network_module() const final {
    DCHECK(fetcher_factory_);
    return fetcher_factory_->network_module();
  }
  worker::ServiceWorkerJobs* service_worker_jobs() const final {
    return service_worker_jobs_;
  }

  const std::string& name() const final { return name_; };
  void setup_environment_settings(
      EnvironmentSettings* environment_settings) final {
    for (auto& observer : environment_settings_change_observers_) {
      observer.OnEnvironmentSettingsChanged(!!environment_settings);
    }
    environment_settings_.reset(environment_settings);
    if (environment_settings_) environment_settings_->set_context(this);
  }

  EnvironmentSettings* environment_settings() const final {
    DCHECK_EQ(environment_settings_->context(), this);
    return environment_settings_.get();
  }

  scoped_refptr<worker::ServiceWorkerRegistration>
  LookupServiceWorkerRegistration(
      worker::ServiceWorkerRegistrationObject* registration) final;
  // https://w3c.github.io/ServiceWorker/#service-worker-registration-creation
  scoped_refptr<worker::ServiceWorkerRegistration> GetServiceWorkerRegistration(
      worker::ServiceWorkerRegistrationObject* registration) final;

  void RemoveServiceWorker(worker::ServiceWorkerObject* worker) final;
  scoped_refptr<worker::ServiceWorker> LookupServiceWorker(
      worker::ServiceWorkerObject* worker) final;
  // https://w3c.github.io/ServiceWorker/#get-the-service-worker-object
  scoped_refptr<worker::ServiceWorker> GetServiceWorker(
      worker::ServiceWorkerObject* worker) final;

  WindowOrWorkerGlobalScope* GetWindowOrWorkerGlobalScope() final;

  const UserAgentPlatformInfo* platform_info() const final {
    return platform_info_;
  }
  std::string GetUserAgent() const final {
    return network_module()->GetUserAgent();
  }
  std::string GetPreferredLanguage() const final {
    return network_module()->preferred_language();
  }

  // https://w3c.github.io/ServiceWorker/#dfn-control
  bool is_controlled_by(worker::ServiceWorkerObject* worker) const final {
    // When a service worker client has a non-null active service worker, it is
    // said to be controlled by that active service worker.
    return active_service_worker() && (active_service_worker() == worker);
  }

  // https://html.spec.whatwg.org/multipage/webappapis.html#concept-environment-active-service-worker
  void set_active_service_worker(
      const scoped_refptr<worker::ServiceWorkerObject>& worker) final {
    active_service_worker_ = worker;
    // Also hold a reference to the registration that contains this worker.
    containing_service_worker_registration_ =
        worker ? worker->containing_service_worker_registration() : nullptr;
  }
  const scoped_refptr<worker::ServiceWorkerObject>& active_service_worker()
      const final {
    return active_service_worker_;
  }
  scoped_refptr<worker::ServiceWorkerObject>& active_service_worker() final {
    return active_service_worker_;
  }


 private:
  // Injects a list of attributes into the Web Context's global object.
  void InjectGlobalObjectAttributes(
      const Agent::Options::InjectedGlobalObjectAttributes& attributes);

  // Thread checker ensures all calls to the Context are made from the same
  // thread that it is created in.
  THREAD_CHECKER(thread_checker_);

  // The message loop for the web context.
  base::MessageLoop* message_loop_ = nullptr;

  // Name of the web instance.
  std::string name_;
  // FetcherFactory that is used to create a fetcher according to URL.
  std::unique_ptr<loader::FetcherFactory> fetcher_factory_;

  // Todo: b/225410588 This is not used by WebModule. Should live in a
  // better place.
  // LoaderFactory that is used to acquire references to resources from a URL.
  std::unique_ptr<loader::ScriptLoaderFactory> script_loader_factory_;

  // JavaScript engine for the browser.
  std::unique_ptr<script::JavaScriptEngine> javascript_engine_;

  // JavaScript Global Object for the browser. There should be one per window,
  // but since there is only one window, we can have one per browser.
  scoped_refptr<script::GlobalEnvironment> global_environment_;

  // Used by |Console| to obtain a JavaScript stack trace.
  std::unique_ptr<script::ExecutionState> execution_state_;

  // Interface for the document to execute JavaScript code.
  std::unique_ptr<script::ScriptRunner> script_runner_;

  // Object to register and retrieve Blob objects with a string key.
  std::unique_ptr<Blob::Registry> blob_registry_;

  // Environment Settings object
  std::unique_ptr<EnvironmentSettings> environment_settings_;

  // The service worker registration object map.
  //   https://w3c.github.io/ServiceWorker/#environment-settings-object-service-worker-registration-object-map
  std::map<worker::ServiceWorkerRegistrationObject*,
           scoped_refptr<worker::ServiceWorkerRegistration>>
      service_worker_registration_object_map_;

  // The service worker object map.
  //   https://w3c.github.io/ServiceWorker/#environment-settings-object-service-worker-object-map
  std::map<worker::ServiceWorkerObject*, scoped_refptr<worker::ServiceWorker>>
      service_worker_object_map_;

  worker::ServiceWorkerJobs* service_worker_jobs_;
  const web::UserAgentPlatformInfo* platform_info_;

  // https://html.spec.whatwg.org/multipage/webappapis.html#concept-environment-active-service-worker
  // Note: When a service worker is unregistered from the last client, this will
  // hold the last reference until the current page is unloaded.
  scoped_refptr<worker::ServiceWorkerObject> active_service_worker_;
  scoped_refptr<worker::ServiceWorkerRegistrationObject>
      containing_service_worker_registration_;

  base::ObserverList<Context::EnvironmentSettingsChangeObserver>::Unchecked
      environment_settings_change_observers_;
};

Impl::Impl(const std::string& name, const Agent::Options& options)
    : name_(name) {
  TRACE_EVENT0("cobalt::web", "Agent::Impl::Impl()");
  service_worker_jobs_ = options.service_worker_jobs;
  platform_info_ = options.platform_info;
  blob_registry_.reset(new Blob::Registry);

  fetcher_factory_.reset(new loader::FetcherFactory(
      options.network_module, options.extra_web_file_dir,
      URL::MakeBlobResolverCallback(blob_registry_.get()),
      options.read_cache_callback));
  DCHECK(fetcher_factory_);

  script_loader_factory_.reset(new loader::ScriptLoaderFactory(
      name.c_str(), fetcher_factory_.get(), options.thread_priority));
  DCHECK(script_loader_factory_);

  javascript_engine_ =
      script::JavaScriptEngine::CreateEngine(options.javascript_engine_options);
  DCHECK(javascript_engine_);

  global_environment_ = javascript_engine_->CreateGlobalEnvironment();
  DCHECK(global_environment_);

  global_environment_->AddRoot(blob_registry_.get());

  execution_state_ =
      script::ExecutionState::CreateExecutionState(global_environment_);
  DCHECK(execution_state_);

  script_runner_ =
      script::ScriptRunner::CreateScriptRunner(global_environment_);
  DCHECK(script_runner_);

  // Schedule the injected global attributes to be added later, to ensure they
  // are added after the global object is created.
  if (!options.injected_global_object_attributes.empty()) {
    DCHECK(base::MessageLoop::current());
    base::MessageLoop::current()->task_runner()->PostTask(
        FROM_HERE,
        base::Bind(&Impl::InjectGlobalObjectAttributes, base::Unretained(this),
                   options.injected_global_object_attributes));
  }
}

void Impl::ShutDownJavaScriptEngine() {
  // TODO: Disentangle shutdown of the JS engine with the various tracking and
  // caching in the WebModule.

  set_active_service_worker(nullptr);
  service_worker_object_map_.clear();
  service_worker_registration_object_map_.clear();

  if (global_environment_) {
    global_environment_->SetReportEvalCallback(base::Closure());
    global_environment_->SetReportErrorCallback(
        script::GlobalEnvironment::ReportErrorCallback());
  }

  setup_environment_settings(nullptr);
  environment_settings_change_observers_.Clear();
  blob_registry_.reset();
  script_runner_.reset();
  execution_state_.reset();
  global_environment_ = NULL;
  javascript_engine_.reset();
  fetcher_factory_.reset();
  script_loader_factory_.reset();
}

Impl::~Impl() { ShutDownJavaScriptEngine(); }

void Impl::AddEnvironmentSettingsChangeObserver(
    Context::EnvironmentSettingsChangeObserver* observer) {
  environment_settings_change_observers_.AddObserver(observer);
}

void Impl::RemoveEnvironmentSettingsChangeObserver(
    Context::EnvironmentSettingsChangeObserver* observer) {
  environment_settings_change_observers_.RemoveObserver(observer);
}

void Impl::InjectGlobalObjectAttributes(
    const Agent::Options::InjectedGlobalObjectAttributes& attributes) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(global_environment_);

  for (Agent::Options::InjectedGlobalObjectAttributes::const_iterator iter =
           attributes.begin();
       iter != attributes.end(); ++iter) {
    global_environment_->Bind(iter->first,
                              iter->second.Run(environment_settings()));
  }
}

scoped_refptr<worker::ServiceWorkerRegistration>
Impl::LookupServiceWorkerRegistration(
    worker::ServiceWorkerRegistrationObject* registration) {
  scoped_refptr<worker::ServiceWorkerRegistration> worker_registration;
  if (!registration) {
    return worker_registration;
  }
  auto registration_lookup =
      service_worker_registration_object_map_.find(registration);
  if (registration_lookup != service_worker_registration_object_map_.end()) {
    worker_registration = registration_lookup->second;
  }
  return worker_registration;
}

scoped_refptr<worker::ServiceWorkerRegistration>
Impl::GetServiceWorkerRegistration(
    worker::ServiceWorkerRegistrationObject* registration) {
  // Algorithm for 'get the service worker registration object':
  //   https://w3c.github.io/ServiceWorker/#get-the-service-worker-registration-object
  scoped_refptr<worker::ServiceWorkerRegistration> worker_registration;
  if (!registration) {
    // Return undefined when registration is null.
    return worker_registration;
  }

  // 1. Let objectMap be environment’s service worker registration object map.
  // 2. If objectMap[registration] does not exist, then:
  auto registration_lookup =
      service_worker_registration_object_map_.find(registration);
  if (registration_lookup == service_worker_registration_object_map_.end()) {
    // 2.1. Let registrationObject be a new ServiceWorkerRegistration in
    // environment’s Realm.
    // 2.2. Set registrationObject’s service worker registration to
    // registration.
    // 2.3. Set registrationObject’s installing attribute to null.
    // 2.4. Set registrationObject’s waiting attribute to null.
    // 2.5. Set registrationObject’s active attribute to null.
    worker_registration = new worker::ServiceWorkerRegistration(
        environment_settings(), registration);

    // 2.6. If registration’s installing worker is not null, then set
    // registrationObject’s installing attribute to the result of getting the
    // service worker object that represents registration’s installing worker in
    // environment.
    if (registration->installing_worker()) {
      worker_registration->set_installing(
          GetServiceWorker(registration->installing_worker()));
    }

    // 2.7. If registration’s waiting worker is not null, then set
    // registrationObject’s waiting attribute to the result of getting the
    // service worker object that represents registration’s waiting worker in
    // environment.
    if (registration->waiting_worker()) {
      worker_registration->set_waiting(
          GetServiceWorker(registration->waiting_worker()));
    }

    // 2.8. If registration’s active worker is not null, then set
    // registrationObject’s active attribute to the result of getting the
    // service worker object that represents registration’s active worker in
    // environment.
    if (registration->active_worker()) {
      worker_registration->set_active(
          GetServiceWorker(registration->active_worker()));
    }

    // 2.9. Set objectMap[registration] to registrationObject.
    service_worker_registration_object_map_.insert(
        std::make_pair(registration, worker_registration));
  } else {
    worker_registration = registration_lookup->second;
  }
  // 3. Return objectMap[registration].
  return worker_registration;
}


void Impl::RemoveServiceWorker(worker::ServiceWorkerObject* worker) {
  service_worker_object_map_.erase(worker);
}

scoped_refptr<worker::ServiceWorker> Impl::LookupServiceWorker(
    worker::ServiceWorkerObject* worker) {
  // Algorithm for 'get the service worker object':
  //   https://w3c.github.io/ServiceWorker/#get-the-service-worker-object
  scoped_refptr<worker::ServiceWorker> service_worker;

  if (!worker) {
    // Return undefined when worker is null.
    return service_worker;
  }

  // 1. Let objectMap be environment’s service worker object map.
  // 2. If objectMap[serviceWorker] does not exist, then:
  auto worker_lookup = service_worker_object_map_.find(worker);
  if (worker_lookup != service_worker_object_map_.end()) {
    service_worker = worker_lookup->second;
  }
  return service_worker;
}

scoped_refptr<worker::ServiceWorker> Impl::GetServiceWorker(
    worker::ServiceWorkerObject* worker) {
  // Algorithm for 'get the service worker object':
  //   https://w3c.github.io/ServiceWorker/#get-the-service-worker-object
  scoped_refptr<worker::ServiceWorker> service_worker;

  if (!worker) {
    // Return undefined when worker is null.
    return service_worker;
  }

  // 1. Let objectMap be environment’s service worker object map.
  // 2. If objectMap[serviceWorker] does not exist, then:
  auto worker_lookup = service_worker_object_map_.find(worker);
  if (worker_lookup == service_worker_object_map_.end()) {
    // 2.1. Let serviceWorkerObj be a new ServiceWorker in environment’s Realm,
    // and associate it with serviceWorker.
    // 2.2. Set serviceWorkerObj’s state to serviceWorker’s state.
    service_worker = new worker::ServiceWorker(environment_settings(), worker);

    // 2.3. Set objectMap[serviceWorker] to serviceWorkerObj.
    service_worker_object_map_.insert(std::make_pair(worker, service_worker));
  } else {
    service_worker = worker_lookup->second;
  }

  // 3. Return objectMap[serviceWorker].
  return service_worker;
}

WindowOrWorkerGlobalScope* Impl::GetWindowOrWorkerGlobalScope() {
  script::Wrappable* global_wrappable =
      global_environment()->global_wrappable();
  if (!global_wrappable) {
    return nullptr;
  }
  DCHECK(global_wrappable->IsWrappable());
  DCHECK_EQ(script::Wrappable::JSObjectType::kObject,
            global_wrappable->GetJSObjectType());

  return base::polymorphic_downcast<WindowOrWorkerGlobalScope*>(
      global_wrappable);
}

// Signals the given WaitableEvent.
void SignalWaitableEvent(base::WaitableEvent* event) { event->Signal(); }
}  // namespace

void Agent::WillDestroyCurrentMessageLoop() { context_.reset(); }

Agent::Agent(const std::string& name) : thread_(name) {}

void Agent::Stop() {
  DCHECK(message_loop());
  DCHECK(thread_.IsRunning());

  if (context() && context()->service_worker_jobs()) {
    context()->service_worker_jobs()->UnregisterWebContext(context());
  }

  // Ensure that the destruction observer got added before stopping the thread.
  destruction_observer_added_.Wait();
  // Stop the thread. This will cause the destruction observer to be notified.
  thread_.Stop();
}

Agent::~Agent() {
  DCHECK(!thread_.IsRunning());
  if (thread_.IsRunning()) {
    Stop();
  }
}

void Agent::Run(const Options& options, InitializeCallback initialize_callback,
                DestructionObserver* destruction_observer) {
  // Start the dedicated thread and create the internal implementation
  // object on that thread.
  base::Thread::Options thread_options(base::MessageLoop::TYPE_DEFAULT,
                                       options.stack_size);
  thread_options.priority = options.thread_priority;
  if (!thread_.StartWithOptions(thread_options)) return;
  DCHECK(message_loop());

  message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&Agent::InitializeTaskInThread, base::Unretained(this),
                 options, initialize_callback));

  if (destruction_observer) {
    message_loop()->task_runner()->PostTask(
        FROM_HERE, base::Bind(&base::MessageLoop::AddDestructionObserver,
                              base::Unretained(message_loop()),
                              base::Unretained(destruction_observer)));
  }
  // Register as a destruction observer to shut down the Web Agent once all
  // pending tasks have been executed and the message loop is about to be
  // destroyed. This allows us to safely stop the thread, drain the task queue,
  // then destroy the internal components before the message loop is reset.
  // No posted tasks will be executed once the thread is stopped.
  message_loop()->task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&base::MessageLoop::AddDestructionObserver,
                 base::Unretained(message_loop()), base::Unretained(this)));

  // This works almost like a PostBlockingTask, except that any blocking that
  // may be necessary happens when Stop() is called instead of right now.
  message_loop()->task_runner()->PostTask(
      FROM_HERE, base::Bind(&SignalWaitableEvent,
                            base::Unretained(&destruction_observer_added_)));
}

void Agent::InitializeTaskInThread(const Options& options,
                                   InitializeCallback initialize_callback) {
  DCHECK_EQ(base::MessageLoop::current(), message_loop());
  context_.reset(
      CreateContext(thread_.thread_name(), options, thread_.message_loop()));
  initialize_callback.Run(context_.get());
}

Context* Agent::CreateContext(const std::string& name, const Options& options,
                              base::MessageLoop* message_loop) {
  auto* context = new Impl(name, options);
  context->set_message_loop(message_loop);
  if (options.service_worker_jobs) {
    options.service_worker_jobs->RegisterWebContext(context);
  }
  return context;
}

void Agent::WaitUntilDone() {
  DCHECK(message_loop());
  if (base::MessageLoop::current() != message_loop()) {
    message_loop()->task_runner()->PostBlockingTask(
        FROM_HERE, base::Bind(&Agent::WaitUntilDone, base::Unretained(this)));
    return;
  }
  DCHECK_EQ(base::MessageLoop::current(), message_loop());
}

void Agent::RequestJavaScriptHeapStatistics(
    const JavaScriptHeapStatisticsCallback& callback) {
  TRACE_EVENT0("cobalt::web", "Agent::RequestJavaScriptHeapStatistics()");
  DCHECK(message_loop());
  if (base::MessageLoop::current() != message_loop()) {
    message_loop()->task_runner()->PostTask(
        FROM_HERE, base::Bind(&Agent::RequestJavaScriptHeapStatistics,
                              base::Unretained(this), callback));
    return;
  }
  script::HeapStatistics heap_statistics =
      context_->javascript_engine()->GetHeapStatistics();
  callback.Run(heap_statistics);
}

}  // namespace web
}  // namespace cobalt
