// 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,
          // 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
