// 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/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:
  explicit Impl(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 Agent::Options& options) : name_(options.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(
      options.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 Options& options, InitializeCallback initialize_callback,
             DestructionObserver* destruction_observer)
    : thread_(options.name) {
  // 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::Initialize, 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_)));
}

Agent::~Agent() {
  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();
}

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

Context* Agent::CreateContext(const Options& options,
                              base::MessageLoop* message_loop) {
  auto* context = new Impl(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
