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

#include <string>
#include <utility>

#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/task_runner.h"
#include "base/threading/thread.h"
#include "cobalt/browser/user_agent_platform_info.h"
#include "cobalt/script/environment_settings.h"
#include "cobalt/web/error_event.h"
#include "cobalt/web/message_port.h"
#include "cobalt/worker/dedicated_worker_global_scope.h"
#include "cobalt/worker/worker_global_scope.h"
#include "cobalt/worker/worker_options.h"
#include "cobalt/worker/worker_settings.h"

#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/v8c_exception_state.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "v8/include/v8.h"

namespace cobalt {
namespace worker {

namespace {
bool PermitAnyURL(const GURL&, bool) { return true; }
}  // namespace

Worker::Worker(const Options& options) : options_(options) {
  // Algorithm for 'run a worker'
  //   https://html.spec.whatwg.org/commit-snapshots/465a6b672c703054de278b0f8133eb3ad33d93f4/#run-a-worker
  // 1. Let is shared be true if worker is a SharedWorker object, and false
  //    otherwise.
  is_shared_ = options.is_shared;
  // 2. Let owner be the relevant owner to add given outside settings.
  // 3. Let parent worker global scope be null.
  // 4. If owner is a WorkerGlobalScope object (i.e., we are creating a nested
  //    dedicated worker), then set parent worker global scope to owner.
  // 5. Let unsafeWorkerCreationTime be the unsafe shared current time.
  // 6. Let agent be the result of obtaining a dedicated/shared worker agent
  //    given outside settings and is shared. Run the rest of these steps in
  //    that agent.
  web_agent_.reset(new web::Agent(
      options.web_options,
      base::Bind(&Worker::Initialize, base::Unretained(this)), this));
}

void Worker::WillDestroyCurrentMessageLoop() {
#if defined(ENABLE_DEBUGGER)
  debug_module_.reset();
#endif  // ENABLE_DEBUGGER
  // Destroy members that were constructed in the worker thread.
  loader_.reset();
  worker_global_scope_ = nullptr;
  message_port_ = nullptr;
  content_.reset();
  error_.reset();
}

Worker::~Worker() { Abort(); }

void Worker::Initialize(web::Context* context) {
  // Algorithm for 'run a worker':
  //   https://html.spec.whatwg.org/commit-snapshots/465a6b672c703054de278b0f8133eb3ad33d93f4/#run-a-worker
  // 7. Let realm execution context be the result of creating a new
  //    JavaScript realm given agent and the following customizations:
  web_context_ = context;
  //    . For the global object, if is shared is true, create a new
  //      SharedWorkerGlobalScope object. Otherwise, create a new
  //      DedicatedWorkerGlobalScope object.
  web_context_->setup_environment_settings(
      new WorkerSettings(options_.outside_port));
  // From algorithm for to setup up a worker environment settings object:
  //   https://html.spec.whatwg.org/commit-snapshots/465a6b672c703054de278b0f8133eb3ad33d93f4/#set-up-a-worker-environment-settings-object
  // 5. Set settings object's creation URL to worker global scope's url.
  web_context_->environment_settings()->set_creation_url(options_.url);
  // Continue algorithm for 'run a worker'.
  // 8. Let worker global scope be the global object of realm execution
  //    context's Realm component.
  scoped_refptr<DedicatedWorkerGlobalScope> dedicated_worker_global_scope =
      new DedicatedWorkerGlobalScope(web_context_->environment_settings(),
                                     false);
  worker_global_scope_ = dedicated_worker_global_scope;
  // 9. Set up a worker environment settings object with realm execution
  //    context, outside settings, and unsafeWorkerCreationTime, and let
  //    inside settings be the result.
  web_context_->global_environment()->CreateGlobalObject(
      dedicated_worker_global_scope, web_context_->environment_settings());
  DCHECK(!web_context_->GetWindowOrWorkerGlobalScope()->IsWindow());
  DCHECK(web_context_->GetWindowOrWorkerGlobalScope()->IsDedicatedWorker());
  DCHECK(!web_context_->GetWindowOrWorkerGlobalScope()->IsServiceWorker());
  DCHECK(web_context_->GetWindowOrWorkerGlobalScope()->GetWrappableType() ==
         base::GetTypeId<DedicatedWorkerGlobalScope>());
  DCHECK_EQ(dedicated_worker_global_scope,
            base::polymorphic_downcast<DedicatedWorkerGlobalScope*>(
                web_context_->GetWindowOrWorkerGlobalScope()));

#if defined(ENABLE_DEBUGGER)
  debug_module_.reset(new debug::backend::DebugModule(
      nullptr /* debugger_hooks */, web_context_->global_environment(),
      nullptr /* render_overlay */, nullptr /* resource_provider */,
      nullptr /* window */, nullptr /* debugger_state */));
#endif  // ENABLE_DEBUGGER

  // 10. Set worker global scope's name to the value of options's name member.
  dedicated_worker_global_scope->set_name(options_.web_options.name);
  // 11. Append owner to worker global scope's owner set.
  // 12. If is shared is true, then:
  //     1. Set worker global scope's constructor origin to outside settings's
  //        origin.
  //     2. Set worker global scope's constructor url to url.
  //     3. Set worker global scope's type to the value of options's type
  //        member.
  //     4. Set worker global scope's credentials to the value of options's
  //        credentials member.
  // 13. Let destination be "sharedworker" if is shared is true, and
  // "worker" otherwise.
  // 14. Obtain script

  Obtain();
}

// Fetch and Run classic script
void Worker::Obtain() {
  // Algorithm for 'run a worker'
  //   https://html.spec.whatwg.org/commit-snapshots/465a6b672c703054de278b0f8133eb3ad33d93f4/#run-a-worker
  // 14. Obtain script by switching on the value of options's type member:
  //     - "classic"
  //         Fetch a classic worker script given url, outside settings,
  //         destination, and inside settings.
  //     - "module"
  //         Fetch a module worker script graph given url, outside settings,
  //         destination, the value of the credentials member of options, and
  //         inside settings.

  //     In both cases, to perform the fetch given request, perform the
  //     following steps if the is top-level flag is set:
  //     1. Set request's reserved client to inside settings.
  //     2. Fetch request, and asynchronously wait to run the remaining steps as
  //        part of fetch's process response for the response response.
  const GURL& url = web_context_->environment_settings()->creation_url();
  loader::Origin origin = loader::Origin(url.GetOrigin());

  // Todo: implement csp check (b/225037465)
  csp::SecurityCallback csp_callback = base::Bind(&PermitAnyURL);

  loader_ = web_context_->script_loader_factory()->CreateScriptLoader(
      url, origin, csp_callback,
      base::Bind(&Worker::OnContentProduced, base::Unretained(this)),
      base::Bind(&Worker::OnLoadingComplete, base::Unretained(this)));
}

void Worker::OnContentProduced(const loader::Origin& last_url_origin,
                               std::unique_ptr<std::string> content) {
  // Algorithm for 'run a worker'
  //   https://html.spec.whatwg.org/commit-snapshots/465a6b672c703054de278b0f8133eb3ad33d93f4/#run-a-worker
  DCHECK(content);
  // 14.3. "Set worker global scope's url to response's url."
  worker_global_scope_->set_url(
      web_context_->environment_settings()->creation_url());
  // 14.4 - 14.10 initialize worker global scope
  worker_global_scope_->Initialize();
  // 14.11. Asynchronously complete the perform the fetch steps with response.
  content_ = std::move(content);
}

void Worker::OnLoadingComplete(const base::Optional<std::string>& error) {
  // Algorithm for 'run a worker'
  //   https://html.spec.whatwg.org/commit-snapshots/465a6b672c703054de278b0f8133eb3ad33d93f4/#run-a-worker
  error_ = error;
  //     If the algorithm asynchronously completes with null or with a script
  //     whose error to rethrow is non-null, then:
  if (error_ || !content_) {
    //     1. Queue a global task on the DOM manipulation task source given
    //        worker's relevant global object to fire an event named error at
    //        worker.
    options_.outside_settings->context()
        ->message_loop()
        ->task_runner()
        ->PostTask(FROM_HERE,
                   base::BindOnce(
                       [](web::WindowOrWorkerGlobalScope* global_scope) {
                         global_scope->DispatchEvent(new web::ErrorEvent());
                       },
                       base::Unretained(options_.outside_settings->context()
                                            ->GetWindowOrWorkerGlobalScope())));
    if (error_) {
      LOG(WARNING) << "Script loading failed : " << *error;
    } else {
      LOG(WARNING) << "Script loading failed : no content received.";
    }
    //     2. Run the environment discarding steps for inside settings.
    //     3. Return.
    return;
  }
  OnReadyToExecute();
}

void Worker::OnReadyToExecute() {
  DCHECK(content_);
  Execute(*content_,
          base::SourceLocation(
              web_context_->environment_settings()->base_url().spec(), 1, 1));
  content_.reset();
}

void Worker::Execute(const std::string& content,
                     const base::SourceLocation& script_location) {
  // Algorithm for 'run a worker'
  //   https://html.spec.whatwg.org/commit-snapshots/465a6b672c703054de278b0f8133eb3ad33d93f4/#run-a-worker
  // 15. Associate worker with worker global scope.
  // Done at step 8.
  // 16. Let inside port be a new MessagePort object in inside settings's Realm.
  // 17. Associate inside port with worker global scope.
  message_port_ = new web::MessagePort(worker_global_scope_);
  // 18. Entangle outside port and inside port.
  // TODO(b/226640425): Implement this when Message Ports can be entangled.
  // 19. Create a new WorkerLocation object and associate it with worker global
  //     scope.
  // 20. Closing orphan workers: Start monitoring the worker such that no sooner
  //     than it stops being a protected worker, and no later than it stops
  //     being a permissible worker, worker global scope's closing flag is set
  //     to true.
  // 21. Suspending workers: Start monitoring the worker, such that whenever
  //     worker global scope's closing flag is false and the worker is a
  //     suspendable worker, the user agent suspends execution of script in that
  //     worker until such time as either the closing flag switches to true or
  //     the worker stops being a suspendable worker.
  // 22. Set inside settings's execution ready flag.
  execution_ready_.Signal();
  // 23. If script is a classic script, then run the classic script script.
  //     Otherwise, it is a module script; run the module script script.

  bool mute_errors = false;
  bool succeeded = false;
  std::string retval = web_context_->script_runner()->Execute(
      content, script_location, mute_errors, &succeeded);
  if (!succeeded) {
    LOG(WARNING) << "Script execution failed : " << retval;
    options_.outside_settings->context()
        ->GetWindowOrWorkerGlobalScope()
        ->DispatchEvent(new web::Event(base::Tokens::error()));
  }

  // 24. Enable outside port's port message queue.
  // TODO(b/226640425): Implement this when Message Ports can be entangled.
  // 25. If is shared is false, enable the port message queue of the worker's
  //     implicit port.
  // 26. If is shared is true, then queue a global task on DOM manipulation task
  //     source given worker global scope to fire an event named connect at
  //     worker global scope, using MessageEvent, with the data attribute
  //     initialized to the empty string, the ports attribute initialized to a
  //     new frozen array containing inside port, and the source attribute
  //     initialized to inside port.
  // 27. Enable the client message queue of the ServiceWorkerContainer object
  //     whose associated service worker client is worker global scope's
  //     relevant settings object.
  // TODO(b/226640425): Implement this when Message Ports can be entangled.
  // 28. Event loop: Run the responsible event loop specified by inside settings
  //     until it is destroyed.
}

void Worker::Abort() {
  // Algorithm for 'run a worker'
  //   https://html.spec.whatwg.org/commit-snapshots/465a6b672c703054de278b0f8133eb3ad33d93f4/#run-a-worker
  // 29. Clear the worker global scope's map of active timers.
  if (worker_global_scope_) {
    DCHECK(message_loop());
    message_loop()->task_runner()->PostBlockingTask(
        FROM_HERE, base::Bind(
                       [](WorkerGlobalScope* worker_global_scope) {
                         worker_global_scope->DestroyTimers();
                       },
                       base::Unretained(worker_global_scope_.get())));
  }
  // 30. Disentangle all the ports in the list of the worker's ports.
  // 31. Empty worker global scope's owner set.
  if (web_agent_) {
    DCHECK(message_loop());
    web_agent_->WaitUntilDone();
    web_agent_.reset();
    web_context_ = nullptr;
  }
}

// Algorithm for 'Terminate a worker'
//   https://html.spec.whatwg.org/commit-snapshots/465a6b672c703054de278b0f8133eb3ad33d93f4/#terminate-a-worker
void Worker::Terminate() {
  // 1. Set the worker's WorkerGlobalScope object's closing flag to true.
  if (worker_global_scope_) {
    worker_global_scope_->set_closing_flag(true);
  }
  // 2. If there are any tasks queued in the WorkerGlobalScope object's relevant
  //    agent's event loop's task queues, discard them without processing them.
  // 3. Abort the script currently running in the worker.
  Abort();
  // 4. If the worker's WorkerGlobalScope object is actually a
  //    DedicatedWorkerGlobalScope object (i.e. the worker is a dedicated
  //    worker), then empty the port message queue of the port that the worker's
  //    implicit port is entangled with.
  // TODO(b/226640425): Implement this when Message Ports can be entangled.
}

void Worker::PostMessage(const script::ValueHandleHolder& message) {
  DCHECK(message_loop());
  auto serialized_message = script::SerializeScriptValue(message);
  if (base::MessageLoop::current() != message_loop()) {
    // Block until the worker thread is ready to execute code to handle the
    // event.
    execution_ready_.Wait();
    message_loop()->task_runner()->PostTask(
        FROM_HERE, base::BindOnce(&web::MessagePort::PostMessageSerialized,
                                  message_port()->AsWeakPtr(),
                                  std::move(serialized_message)));
  } else {
    DCHECK(execution_ready_.IsSignaled());
    message_port()->PostMessageSerialized(std::move(serialized_message));
  }
}

}  // namespace worker
}  // namespace cobalt
