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

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

#include "base/logging.h"
#include "base/message_loop/message_loop_current.h"
#include "base/threading/thread.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/loader/origin.h"
#include "cobalt/script/environment_settings.h"
#include "cobalt/web/context.h"
#include "cobalt/web/dom_exception.h"
#include "cobalt/web/user_agent_platform_info.h"
#include "cobalt/web/window_or_worker_global_scope.h"
#include "cobalt/web/window_timers.h"
#include "cobalt/worker/service_worker_object.h"
#include "cobalt/worker/worker_location.h"
#include "cobalt/worker/worker_navigator.h"
#include "starboard/atomic.h"
#include "url/gurl.h"

namespace cobalt {
namespace worker {

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

class ScriptLoader : public base::MessageLoop::DestructionObserver {
 public:
  explicit ScriptLoader(web::Context* context) : context_(context) {
    thread_.reset(new base::Thread("ImportScriptsLoader"));
    thread_->Start();

    // Register as a destruction observer to shut down the Loaders 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.
    thread_->message_loop()->task_runner()->PostTask(
        FROM_HERE, base::Bind(&base::MessageLoop::AddDestructionObserver,
                              base::Unretained(thread_->message_loop()),
                              base::Unretained(this)));

    thread_->message_loop()->task_runner()->PostTask(
        FROM_HERE,
        base::BindOnce(
            [](loader::FetcherFactory* fetcher_factory,
               std::unique_ptr<loader::ScriptLoaderFactory>*
                   script_loader_factory_) {
              TRACE_EVENT0("cobalt::worker",
                           "ScriptLoader::ScriptLoaderFactory Task");
              script_loader_factory_->reset(new loader::ScriptLoaderFactory(
                  "ImportScriptsLoader", fetcher_factory));
            },
            context_->fetcher_factory(), &script_loader_factory_));
  }


  ~ScriptLoader() {
    if (thread_) {
      // Stop the thread. This will cause the destruction observer to be
      // notified.
      thread_->Stop();
    }
  }

  void WillDestroyCurrentMessageLoop() {
    // Destroy members that were constructed in the worker thread.
    errors_.clear();
    errors_.shrink_to_fit();
    contents_.clear();
    contents_.shrink_to_fit();
    loaders_.clear();
    loaders_.shrink_to_fit();
    script_loader_factory_.reset();
  }

  void Load(const loader::Origin& origin,
            const std::vector<GURL>& resolved_urls) {
    TRACE_EVENT0("cobalt::worker", "ScriptLoader::Load()");
    number_of_loads_ = resolved_urls.size();
    contents_.resize(resolved_urls.size());
    loaders_.resize(resolved_urls.size());
    errors_.resize(resolved_urls.size());
    if (resolved_urls.empty()) return;

    for (int i = 0; i < resolved_urls.size(); ++i) {
      const GURL& url = resolved_urls[i];
      thread_->message_loop()->task_runner()->PostTask(
          FROM_HERE, base::BindOnce(&ScriptLoader::LoaderTask,
                                    base::Unretained(this), &loaders_[i],
                                    origin, url, &contents_[i], &errors_[i]));
    }
    load_finished_.Wait();
  }

  void LoaderTask(std::unique_ptr<loader::Loader>* loader,
                  const loader::Origin& origin, const GURL& url,
                  std::unique_ptr<std::string>* content,
                  std::unique_ptr<std::string>* error) {
    TRACE_EVENT0("cobalt::worker", "ScriptLoader::LoaderTask()");
    // Todo: implement csp check (b/225037465)
    csp::SecurityCallback csp_callback = base::Bind(&PermitAnyURL);

    // If there is a request callback, call it to possibly retrieve previously
    // requested content.
    *loader = script_loader_factory_->CreateScriptLoader(
        url, origin, csp_callback,
        base::Bind(
            [](std::unique_ptr<std::string>* output_content,
               const loader::Origin& last_url_origin,
               std::unique_ptr<std::string> content) {
              *output_content = std::move(content);
            },
            content),
        base::Bind(&ScriptLoader::LoadingCompleteCallback,
                   base::Unretained(this), loader, error));
  }

  void LoadingCompleteCallback(std::unique_ptr<loader::Loader>* loader,
                               std::unique_ptr<std::string>* output_error,
                               const base::Optional<std::string>& error) {
    TRACE_EVENT0("cobalt::worker", "ScriptLoader::LoadingCompleteCallback()");
    if (error) {
      output_error->reset(new std::string(std::move(error.value())));
    }
    if (!SbAtomicNoBarrier_Increment(&number_of_loads_, -1)) {
      // Clear the loader factory after this callback
      // completes.
      base::MessageLoop::current()->task_runner()->PostTask(
          FROM_HERE, base::BindOnce(
                         [](base::WaitableEvent* load_finished_) {
                           load_finished_->Signal();
                         },
                         &load_finished_));
    }
  }

  const std::unique_ptr<std::string>& GetContents(int index) {
    return contents_[index];
  }

  const std::unique_ptr<std::string>& GetError(int index) {
    return errors_[index];
  }

 private:
  web::Context* context_;
  base::WaitableEvent load_finished_ = {
      base::WaitableEvent::ResetPolicy::MANUAL,
      base::WaitableEvent::InitialState::NOT_SIGNALED};

  std::unique_ptr<base::Thread> thread_;

  std::unique_ptr<loader::ScriptLoaderFactory> script_loader_factory_;

  volatile SbAtomic32 number_of_loads_;

  std::vector<std::unique_ptr<std::string>> contents_;
  std::vector<std::unique_ptr<std::string>> errors_;
  std::vector<std::unique_ptr<loader::Loader>> loaders_;

  base::Optional<std::string> error_;
};

}  // namespace

WorkerGlobalScope::WorkerGlobalScope(script::EnvironmentSettings* settings)
    : web::WindowOrWorkerGlobalScope(
          settings, /*stat_tracker=*/NULL,
          // Using default options for CSP
          web::WindowOrWorkerGlobalScope::Options(
              // TODO (b/233788170): once application state is
              // available, update this to use the actual state.
              base::ApplicationState::kApplicationStateStarted)),
      location_(new WorkerLocation(settings->creation_url())),
      navigator_(new WorkerNavigator(settings)) {
  set_navigator_base(navigator_);
}

void WorkerGlobalScope::ImportScripts(const std::vector<std::string>& urls,
                                      script::ExceptionState* exception_state) {
  ImportScriptsInternal(urls, exception_state, URLLookupCallback(),
                        ResponseCallback());
}

bool WorkerGlobalScope::LoadImportsAndReturnIfUpdated(
    const ScriptResourceMap& previous_resource_map,
    ScriptResourceMap* new_resource_map) {
  bool has_updated_resources = false;
  // Steps from Algorithm for Update:
  //   https://w3c.github.io/ServiceWorker/#update-algorithm
  //   8.21.1. For each importUrl -> storedResponse of newestWorker’s script
  //           resource map:
  std::vector<GURL> request_urls;
  for (const auto& resource_map_entry : previous_resource_map) {
    //   8.21.1.1. If importUrl is url, then continue.
    if (new_resource_map->find(resource_map_entry.first) !=
        new_resource_map->end()) {
      continue;
    }
    request_urls.push_back(resource_map_entry.first);
  }

  //   8.21.1.2. Let importRequest be a new request whose url is importUrl,
  //             client is job’s client, destination is "script", parser
  //             metadata is "not parser-inserted", synchronous flag is set,
  //             and whose use-URL-credentials flag is set.
  //   8.21.1.3. Set importRequest’s cache mode to "no-cache" if any of the
  //             following are true:
  //               - registration’s update via cache mode is "none".
  //               - job’s force bypass cache flag is set.
  //               - registration is stale.
  //   8.21.1.4. Let fetchedResponse be the result of fetching importRequest.
  web::EnvironmentSettings* settings = environment_settings();
  const GURL& base_url = settings->base_url();
  loader::Origin origin = loader::Origin(base_url.GetOrigin());
  ScriptLoader script_loader(settings->context());
  script_loader.Load(origin, request_urls);

  for (int index = 0; index < request_urls.size(); ++index) {
    const auto& error = script_loader.GetError(index);
    if (error) continue;
    const GURL& url = request_urls[index];
    const std::unique_ptr<std::string>& script =
        script_loader.GetContents(index);
    //   8.21.1.5. Set updatedResourceMap[importRequest’s url] to
    //             fetchedResponse.
    (*new_resource_map)[url].reset(new std::string(*script.get()));
    //   8.21.1.6. Set fetchedResponse to fetchedResponse’s unsafe response.
    //   8.21.1.7. If fetchedResponse’s cache state is not
    //             "local", set registration’s last update check time to the
    //             current time.
    //   8.21.1.8. If fetchedResponse is a bad import script response, continue.
    //   8.21.1.9. If fetchedResponse’s body is not byte-for-byte identical with
    //             storedResponse’s unsafe response's body, set
    //             hasUpdatedResources to true.
    DCHECK(previous_resource_map.find(url) != previous_resource_map.end());
    if (*script != *(previous_resource_map.find(url)->second)) {
      has_updated_resources = true;
    }
  }
  return has_updated_resources;
}

void WorkerGlobalScope::ImportScriptsInternal(
    const std::vector<std::string>& urls,
    script::ExceptionState* exception_state,
    URLLookupCallback url_lookup_callback, ResponseCallback response_callback) {
  // Algorithm for import scripts into worker global scope:
  //   https://html.spec.whatwg.org/multipage/workers.html#import-scripts-into-worker-global-scope

  // 1. If worker global scope's type is "module", throw a TypeError exception.
  // Cobalt does not support "module" type scripts.

  // 2. Let settings object be the current settings object.
  web::EnvironmentSettings* settings = environment_settings();
  DCHECK(settings->context()
             ->message_loop()
             ->task_runner()
             ->BelongsToCurrentThread());

  // 3. If urls is empty, return.
  if (urls.empty()) return;

  // 4. Parse each value in urls relative to settings object. If any fail, throw
  //    a "SyntaxError" DOMException.
  std::vector<GURL> request_urls;
  std::vector<std::string*> looked_up_content;
  request_urls.reserve(urls.size());
  std::vector<GURL> resolved_urls(urls.size());
  std::vector<int> request_url_indexes(urls.size());

  const GURL& base_url = settings->base_url();
  for (int index = 0; index < urls.size(); ++index) {
    const std::string& url = urls[index];
    resolved_urls[index] = base_url.Resolve(url);
    if (resolved_urls[index].is_empty()) {
      web::DOMException::Raise(web::DOMException::kSyntaxErr, exception_state);
      return;
    }
    std::string* content =
        url_lookup_callback
            ? url_lookup_callback.Run(resolved_urls[index], exception_state)
            : nullptr;
    // Return if the url lookup callback has set the exception state.
    if (exception_state->is_exception_set()) return;
    if (content) {
      // Store the result of the url lookup callback.
      request_url_indexes[index] = -1;
      looked_up_content.push_back(content);
    } else {
      // Add the url to the list to pass to ScriptLoader for loading.
      request_url_indexes[index] = request_urls.size();
      request_urls.push_back(resolved_urls[index]);
    }
  }

  loader::Origin origin = loader::Origin(base_url.GetOrigin());

  // 5. For each url in the resulting URL records, run these substeps:
  // 5.1. Fetch a classic worker-imported script given url and settings
  //      object, passing along any custom perform the fetch steps provided.
  //      If this succeeds, let script be the result. Otherwise, rethrow the
  //      exception.
  ScriptLoader script_loader(settings->context());
  script_loader.Load(origin, request_urls);

  // 5. For each url in the resulting URL records, run these substeps:
  int content_lookup_index = 0;
  for (int index = 0; index < resolved_urls.size(); ++index) {
    int request_index = request_url_indexes[index];
    std::string* script = nullptr;

    if (request_index == -1) {
      // The content at this index was received from the url lookup callback.
      script = looked_up_content[content_lookup_index++];
    } else {
      const auto& error = script_loader.GetError(request_index);
      if (error) {
        LOG(WARNING) << "Script Loading Failed : " << *error;
        web::DOMException::Raise(web::DOMException::kNetworkErr, *error,
                                 exception_state);
        break;
      }
      script = script_loader.GetContents(request_index).get();
    }
    // 5.2. Run the classic script script, with the rethrow errors argument
    //      set to true.
    if (script) {
      if (response_callback) {
        script = response_callback.Run(resolved_urls[index], script);
      }
      bool succeeded = false;
      std::string retval;
      if (script) {
        bool mute_errors = false;
        const base::SourceLocation script_location(resolved_urls[index].spec(),
                                                   1, 1);
        retval = settings->context()->script_runner()->Execute(
            *script, script_location, mute_errors, &succeeded);
      }
      if (!succeeded) {
        // TODO(): Handle script execution errors.
        LOG(WARNING) << "Script Execution Failed : " << retval;
        web::DOMException::Raise(web::DOMException::kSyntaxErr,
                                 exception_state);
        return;
      }
    }
  }
  // If an exception was thrown or if the script was prematurely aborted, then
  // abort all these steps, letting the exception or aborting continue to be
  // processed by the calling script.
}

}  // namespace worker
}  // namespace cobalt
