// 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/net_fetcher.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_consts.h"
#include "cobalt/worker/worker_location.h"
#include "cobalt/worker/worker_navigator.h"
#include "net/base/mime_util.h"
#include "starboard/atomic.h"
#include "url/gurl.h"

namespace cobalt {
namespace worker {

namespace {

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(web::CspDelegate* csp_delegate, 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),
                         csp_delegate, &loaders_[i], origin, url, &contents_[i],
                         &errors_[i]));
    }
    load_finished_.Wait();
  }

  void LoaderTask(web::CspDelegate* csp_delegate,
                  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()");
    csp::SecurityCallback csp_callback =
        base::Bind(&web::CspDelegate::CanLoad, base::Unretained(csp_delegate),
                   web::CspDelegate::kWorker);

    bool skip_fetch_intercept =
        context_->GetWindowOrWorkerGlobalScope()->IsServiceWorker();
    // 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::UpdateOnResponseStarted,
                   base::Unretained(this), error),
        base::Bind(&ScriptLoader::LoadingCompleteCallback,
                   base::Unretained(this), loader, error),
        net::HttpRequestHeaders(), skip_fetch_intercept);
  }

  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::ThreadTaskRunnerHandle::Get()->PostTask(
          FROM_HERE, base::BindOnce(
                         [](base::WaitableEvent* load_finished_) {
                           load_finished_->Signal();
                         },
                         &load_finished_));
    }
  }

  bool UpdateOnResponseStarted(
      std::unique_ptr<std::string>* error, loader::Fetcher* fetcher,
      const scoped_refptr<net::HttpResponseHeaders>& headers) {
    std::string content_type;
    bool mime_type_is_javascript = false;
    if (headers->GetNormalizedHeader("Content-type", &content_type)) {
      for (auto mime_type : WorkerConsts::kJavaScriptMimeTypes) {
        if (net::MatchesMimeType(mime_type, content_type)) {
          mime_type_is_javascript = true;
          break;
        }
      }
    }
    if (content_type.empty()) {
      error->reset(new std::string(
          base::StringPrintf(WorkerConsts::kServiceWorkerRegisterNoMIMEError)));
    } else if (!mime_type_is_javascript) {
      error->reset(new std::string(
          base::StringPrintf(WorkerConsts::kServiceWorkerRegisterBadMIMEError,
                             content_type.c_str())));
    }
    return true;
  }

  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,
    const web::WindowOrWorkerGlobalScope::Options& options)
    : web::WindowOrWorkerGlobalScope(settings, options),
      location_(new WorkerLocation(settings->creation_url())),
      navigator_(new WorkerNavigator(settings)) {
  set_navigator_base(navigator_);
}

bool WorkerGlobalScope::InitializePolicyContainerCallback(
    loader::Fetcher* fetcher,
    const scoped_refptr<net::HttpResponseHeaders>& headers) {
  DCHECK(headers);
  // https://html.spec.whatwg.org/commit-snapshots/465a6b672c703054de278b0f8133eb3ad33d93f4/#initialize-worker-policy-container
  // 1. If workerGlobalScope's url is local but its scheme is not "blob":
  //   1. Assert: workerGlobalScope's owner set's size is 1.
  //   2. Set workerGlobalScope's policy container to a clone of
  //      workerGlobalScope's owner set[0]'s relevant settings object's policy
  //      container.
  // 2. Otherwise, set workerGlobalScope's policy container to the result of
  //    creating a policy container from a fetch response given response and
  //    environment.
  // Steps from create a policy container from a fetch response:
  // https://html.spec.whatwg.org/commit-snapshots/465a6b672c703054de278b0f8133eb3ad33d93f4/#creating-a-policy-container-from-a-fetch-response
  // 1. If response's URL's scheme is "blob", then return a clone of response's
  //    URL's blob URL entry's environment's policy container.
  // 2. Let result be a new policy container.
  // 3. Set result's CSP list to the result of parsing a response's Content
  //    Security Policies given response.
  // 4. If environment is non-null, then set result's embedder policy to the
  //    result of obtaining an embedder policy given response and environment.
  //    Otherwise, set it to "unsafe-none".
  // 5. Set result's referrer policy to the result of parsing the
  //    `Referrer-Policy` header given response. [REFERRERPOLICY]
  // 6. Return result.

  // Steps 3-6. Since csp_delegate doesn't fully mirror PolicyContainer, we
  // don't create a new one here and return it. Instead we update the existing
  // one for this worker and return true for success and false for failure.
  csp::ResponseHeaders csp_headers(headers);
  if (csp_delegate()->OnReceiveHeaders(csp_headers)) {
    return true;
  }
  // Only NetFetchers are expected to call this, since only they have the
  // response headers.
  loader::NetFetcher* net_fetcher =
      fetcher ? base::polymorphic_downcast<loader::NetFetcher*>(fetcher)
              : nullptr;
  net::URLFetcher* url_fetcher =
      net_fetcher ? net_fetcher->url_fetcher() : nullptr;
  const GURL& url = url_fetcher ? url_fetcher->GetURL()
                                : environment_settings()->creation_url();
  LOG(INFO) << "Failure receiving Content Security Policy headers for URL: "
            << url << ".";
  // Return true regardless of CSP headers being received to continue loading
  // the response.
  return true;
}

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://www.w3.org/TR/2022/CRD-service-workers-20220712/#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(csp_delegate(), 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];
    //   8.21.1.5. Set updatedResourceMap[importRequest’s url] to
    //             fetchedResponse.
    // Note: The headers of imported scripts aren't used anywhere.
    auto result = new_resource_map->insert(std::make_pair(
        url, ScriptResource(std::move(script_loader.GetContents(index)))));
    // Assert that the insert was successful.
    DCHECK(result.second);
    //   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 (*result.first->second.content !=
        *(previous_resource_map.find(url)->second.content)) {
      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(csp_delegate(), 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.
        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
