
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "modules/serviceworkers/ServiceWorkerContainer.h"

#include <memory>
#include <utility>

#include "bindings/core/v8/Dictionary.h"
#include "bindings/core/v8/ScriptFunction.h"
#include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/V8BindingForCore.h"
#include "bindings/core/v8/V8DOMException.h"
#include "bindings/core/v8/V8GCController.h"
#include "core/dom/DOMException.h"
#include "core/dom/Document.h"
#include "core/dom/ExecutionContext.h"
#include "core/page/FocusController.h"
#include "core/testing/DummyPageHolder.h"
#include "modules/serviceworkers/NavigatorServiceWorker.h"
#include "modules/serviceworkers/ServiceWorkerContainerClient.h"
#include "platform/bindings/ScriptState.h"
#include "platform/weborigin/KURL.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "platform/wtf/PtrUtil.h"
#include "platform/wtf/text/WTFString.h"
#include "public/platform/WebURL.h"
#include "public/platform/modules/serviceworker/WebServiceWorkerClientsInfo.h"
#include "public/platform/modules/serviceworker/WebServiceWorkerProvider.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "v8/include/v8.h"

namespace blink {
namespace {

// Promise-related test support.

struct StubScriptFunction {
 public:
  StubScriptFunction() : call_count_(0) {}

  // The returned ScriptFunction can outlive the StubScriptFunction,
  // but it should not be called after the StubScriptFunction dies.
  v8::Local<v8::Function> GetFunction(ScriptState* script_state) {
    return ScriptFunctionImpl::CreateFunction(script_state, *this);
  }

  size_t CallCount() { return call_count_; }
  ScriptValue Arg() { return arg_; }

 private:
  size_t call_count_;
  ScriptValue arg_;

  class ScriptFunctionImpl : public ScriptFunction {
   public:
    static v8::Local<v8::Function> CreateFunction(ScriptState* script_state,
                                                  StubScriptFunction& owner) {
      ScriptFunctionImpl* self = new ScriptFunctionImpl(script_state, owner);
      return self->BindToV8Function();
    }

   private:
    ScriptFunctionImpl(ScriptState* script_state, StubScriptFunction& owner)
        : ScriptFunction(script_state), owner_(owner) {}

    ScriptValue Call(ScriptValue arg) override {
      owner_.arg_ = arg;
      owner_.call_count_++;
      return ScriptValue();
    }

    StubScriptFunction& owner_;
  };
};

class ScriptValueTest {
 public:
  virtual ~ScriptValueTest() {}
  virtual void operator()(ScriptValue) const = 0;
};

// Runs microtasks and expects |promise| to be rejected. Calls
// |valueTest| with the value passed to |reject|, if any.
void ExpectRejected(ScriptState* script_state,
                    ScriptPromise& promise,
                    const ScriptValueTest& value_test) {
  StubScriptFunction resolved, rejected;
  promise.Then(resolved.GetFunction(script_state),
               rejected.GetFunction(script_state));
  v8::MicrotasksScope::PerformCheckpoint(promise.GetIsolate());
  EXPECT_EQ(0ul, resolved.CallCount());
  EXPECT_EQ(1ul, rejected.CallCount());
  if (rejected.CallCount())
    value_test(rejected.Arg());
}

// DOM-related test support.

// Matches a ScriptValue and a DOMException with a specific name and message.
class ExpectDOMException : public ScriptValueTest {
 public:
  ExpectDOMException(const String& expected_name,
                     const String& expected_message)
      : expected_name_(expected_name), expected_message_(expected_message) {}

  ~ExpectDOMException() override {}

  void operator()(ScriptValue value) const override {
    DOMException* exception = V8DOMException::ToImplWithTypeCheck(
        value.GetIsolate(), value.V8Value());
    EXPECT_TRUE(exception) << "the value should be a DOMException";
    if (!exception)
      return;
    EXPECT_EQ(expected_name_, exception->name());
    EXPECT_EQ(expected_message_, exception->message());
  }

 private:
  String expected_name_;
  String expected_message_;
};

// Service Worker-specific tests.

class NotReachedWebServiceWorkerProvider : public WebServiceWorkerProvider {
 public:
  ~NotReachedWebServiceWorkerProvider() override {}

  void RegisterServiceWorker(
      const WebURL& pattern,
      const WebURL& script_url,
      mojom::ServiceWorkerUpdateViaCache update_via_cache,
      std::unique_ptr<WebServiceWorkerRegistrationCallbacks> callbacks)
      override {
    ADD_FAILURE()
        << "the provider should not be called to register a Service Worker";
  }

  bool ValidateScopeAndScriptURL(const WebURL& scope,
                                 const WebURL& script_url,
                                 WebString* error_message) override {
    return true;
  }
};

class ServiceWorkerContainerTest : public ::testing::Test {
 protected:
  ServiceWorkerContainerTest() : page_(DummyPageHolder::Create()) {}

  ~ServiceWorkerContainerTest() override {
    page_.reset();
    V8GCController::CollectAllGarbageForTesting(GetIsolate());
  }

  ExecutionContext* GetExecutionContext() { return &(page_->GetDocument()); }
  NavigatorServiceWorker* GetNavigatorServiceWorker() {
    return NavigatorServiceWorker::From(page_->GetDocument());
  }
  v8::Isolate* GetIsolate() { return v8::Isolate::GetCurrent(); }
  ScriptState* GetScriptState() {
    return ToScriptStateForMainWorld(page_->GetDocument().GetFrame());
  }

  void Provide(std::unique_ptr<WebServiceWorkerProvider> provider) {
    Supplement<Document>::ProvideTo(
        page_->GetDocument(), ServiceWorkerContainerClient::SupplementName(),
        new ServiceWorkerContainerClient(page_->GetDocument(),
                                         std::move(provider)));
  }

  void SetPageURL(const String& url) {
    // For URL completion.
    page_->GetDocument().SetURL(KURL(NullURL(), url));

    // The basis for security checks.
    page_->GetDocument().SetSecurityOrigin(
        SecurityOrigin::CreateFromString(url));

    if (url.StartsWith("https://") || url.StartsWith("http://localhost/")) {
      page_->GetDocument().SetSecureContextStateForTesting(
          SecureContextState::kSecure);
    }
  }

  void TestRegisterRejected(const String& script_url,
                            const String& scope,
                            const ScriptValueTest& value_test) {
    // When the registration is rejected, a register call must not reach
    // the provider.
    Provide(std::make_unique<NotReachedWebServiceWorkerProvider>());

    ServiceWorkerContainer* container = ServiceWorkerContainer::Create(
        GetExecutionContext(), GetNavigatorServiceWorker());
    ScriptState::Scope script_scope(GetScriptState());
    RegistrationOptions options;
    options.setScope(scope);
    ScriptPromise promise =
        container->registerServiceWorker(GetScriptState(), script_url, options);
    ExpectRejected(GetScriptState(), promise, value_test);
  }

  void TestGetRegistrationRejected(const String& document_url,
                                   const ScriptValueTest& value_test) {
    Provide(std::make_unique<NotReachedWebServiceWorkerProvider>());

    ServiceWorkerContainer* container = ServiceWorkerContainer::Create(
        GetExecutionContext(), GetNavigatorServiceWorker());
    ScriptState::Scope script_scope(GetScriptState());
    ScriptPromise promise =
        container->getRegistration(GetScriptState(), document_url);
    ExpectRejected(GetScriptState(), promise, value_test);
  }

 private:
  std::unique_ptr<DummyPageHolder> page_;
};

TEST_F(ServiceWorkerContainerTest, Register_NonSecureOriginIsRejected) {
  SetPageURL("http://www.example.com/");
  TestRegisterRejected(
      "http://www.example.com/worker.js", "http://www.example.com/",
      ExpectDOMException(
          "SecurityError",
          "Only secure origins are allowed (see: https://goo.gl/Y0ZkNV)."));
}

TEST_F(ServiceWorkerContainerTest, Register_CrossOriginScriptIsRejected) {
  SetPageURL("https://www.example.com");
  TestRegisterRejected(
      "https://www.example.com:8080/",  // Differs by port
      "https://www.example.com/",
      ExpectDOMException("SecurityError",
                         "Failed to register a ServiceWorker: The origin of "
                         "the provided scriptURL "
                         "('https://www.example.com:8080') does not match the "
                         "current origin ('https://www.example.com')."));
}

TEST_F(ServiceWorkerContainerTest, Register_CrossOriginScopeIsRejected) {
  SetPageURL("https://www.example.com");
  TestRegisterRejected(
      "https://www.example.com",
      "wss://www.example.com/",  // Differs by protocol
      ExpectDOMException("SecurityError",
                         "Failed to register a ServiceWorker: The origin of "
                         "the provided scope ('wss://www.example.com') does "
                         "not match the current origin "
                         "('https://www.example.com')."));
}

TEST_F(ServiceWorkerContainerTest, GetRegistration_NonSecureOriginIsRejected) {
  SetPageURL("http://www.example.com/");
  TestGetRegistrationRejected(
      "http://www.example.com/",
      ExpectDOMException(
          "SecurityError",
          "Only secure origins are allowed (see: https://goo.gl/Y0ZkNV)."));
}

TEST_F(ServiceWorkerContainerTest, GetRegistration_CrossOriginURLIsRejected) {
  SetPageURL("https://www.example.com/");
  TestGetRegistrationRejected(
      "https://foo.example.com/",  // Differs by host
      ExpectDOMException("SecurityError",
                         "Failed to get a ServiceWorkerRegistration: The "
                         "origin of the provided documentURL "
                         "('https://foo.example.com') does not match the "
                         "current origin ('https://www.example.com')."));
}

class StubWebServiceWorkerProvider {
 public:
  StubWebServiceWorkerProvider()
      : register_call_count_(0),
        get_registration_call_count_(0),
        update_via_cache_(mojom::ServiceWorkerUpdateViaCache::kImports) {}

  // Creates a WebServiceWorkerProvider. This can outlive the
  // StubWebServiceWorkerProvider, but |registerServiceWorker| and
  // other methods must not be called after the
  // StubWebServiceWorkerProvider dies.
  std::unique_ptr<WebServiceWorkerProvider> Provider() {
    return WTF::WrapUnique(new WebServiceWorkerProviderImpl(*this));
  }

  size_t RegisterCallCount() { return register_call_count_; }
  const WebURL& RegisterScope() { return register_scope_; }
  const WebURL& RegisterScriptURL() { return register_script_url_; }
  size_t GetRegistrationCallCount() { return get_registration_call_count_; }
  const WebURL& GetRegistrationURL() { return get_registration_url_; }
  mojom::ServiceWorkerUpdateViaCache UpdateViaCache() const {
    return update_via_cache_;
  }

 private:
  class WebServiceWorkerProviderImpl : public WebServiceWorkerProvider {
   public:
    WebServiceWorkerProviderImpl(StubWebServiceWorkerProvider& owner)
        : owner_(owner) {}

    ~WebServiceWorkerProviderImpl() override {}

    void RegisterServiceWorker(
        const WebURL& pattern,
        const WebURL& script_url,
        mojom::ServiceWorkerUpdateViaCache update_via_cache,
        std::unique_ptr<WebServiceWorkerRegistrationCallbacks> callbacks)
        override {
      owner_.register_call_count_++;
      owner_.register_scope_ = pattern;
      owner_.register_script_url_ = script_url;
      owner_.update_via_cache_ = update_via_cache;
      registration_callbacks_to_delete_.push_back(std::move(callbacks));
    }

    void GetRegistration(
        const WebURL& document_url,
        std::unique_ptr<WebServiceWorkerGetRegistrationCallbacks> callbacks)
        override {
      owner_.get_registration_call_count_++;
      owner_.get_registration_url_ = document_url;
      get_registration_callbacks_to_delete_.push_back(std::move(callbacks));
    }

    bool ValidateScopeAndScriptURL(const WebURL& scope,
                                   const WebURL& script_url,
                                   WebString* error_message) override {
      return true;
    }

   private:
    StubWebServiceWorkerProvider& owner_;
    Vector<std::unique_ptr<WebServiceWorkerRegistrationCallbacks>>
        registration_callbacks_to_delete_;
    Vector<std::unique_ptr<WebServiceWorkerGetRegistrationCallbacks>>
        get_registration_callbacks_to_delete_;
  };

 private:
  size_t register_call_count_;
  WebURL register_scope_;
  WebURL register_script_url_;
  size_t get_registration_call_count_;
  WebURL get_registration_url_;
  mojom::ServiceWorkerUpdateViaCache update_via_cache_;
};

TEST_F(ServiceWorkerContainerTest,
       RegisterUnregister_NonHttpsSecureOriginDelegatesToProvider) {
  SetPageURL("http://localhost/x/index.html");

  StubWebServiceWorkerProvider stub_provider;
  Provide(stub_provider.Provider());

  ServiceWorkerContainer* container = ServiceWorkerContainer::Create(
      GetExecutionContext(), GetNavigatorServiceWorker());

  // register
  {
    ScriptState::Scope script_scope(GetScriptState());
    RegistrationOptions options;
    options.setScope("y/");
    container->registerServiceWorker(GetScriptState(), "/x/y/worker.js",
                                     options);

    EXPECT_EQ(1ul, stub_provider.RegisterCallCount());
    EXPECT_EQ(WebURL(KURL(NullURL(), "http://localhost/x/y/")),
              stub_provider.RegisterScope());
    EXPECT_EQ(WebURL(KURL(NullURL(), "http://localhost/x/y/worker.js")),
              stub_provider.RegisterScriptURL());
    EXPECT_EQ(mojom::ServiceWorkerUpdateViaCache::kImports,
              stub_provider.UpdateViaCache());
  }
}

TEST_F(ServiceWorkerContainerTest,
       GetRegistration_OmittedDocumentURLDefaultsToPageURL) {
  SetPageURL("http://localhost/x/index.html");

  StubWebServiceWorkerProvider stub_provider;
  Provide(stub_provider.Provider());

  ServiceWorkerContainer* container = ServiceWorkerContainer::Create(
      GetExecutionContext(), GetNavigatorServiceWorker());

  {
    ScriptState::Scope script_scope(GetScriptState());
    container->getRegistration(GetScriptState(), "");
    EXPECT_EQ(1ul, stub_provider.GetRegistrationCallCount());
    EXPECT_EQ(WebURL(KURL(NullURL(), "http://localhost/x/index.html")),
              stub_provider.GetRegistrationURL());
    EXPECT_EQ(mojom::ServiceWorkerUpdateViaCache::kImports,
              stub_provider.UpdateViaCache());
  }
}

TEST_F(ServiceWorkerContainerTest,
       RegisterUnregister_UpdateViaCacheOptionDelegatesToProvider) {
  SetPageURL("http://localhost/x/index.html");

  StubWebServiceWorkerProvider stub_provider;
  Provide(stub_provider.Provider());

  ServiceWorkerContainer* container = ServiceWorkerContainer::Create(
      GetExecutionContext(), GetNavigatorServiceWorker());

  // register
  {
    ScriptState::Scope script_scope(GetScriptState());
    RegistrationOptions options;
    options.setUpdateViaCache("none");
    container->registerServiceWorker(GetScriptState(), "/x/y/worker.js",
                                     options);

    EXPECT_EQ(1ul, stub_provider.RegisterCallCount());
    EXPECT_EQ(WebURL(KURL(KURL(), "http://localhost/x/y/")),
              stub_provider.RegisterScope());
    EXPECT_EQ(WebURL(KURL(KURL(), "http://localhost/x/y/worker.js")),
              stub_provider.RegisterScriptURL());
    EXPECT_EQ(mojom::ServiceWorkerUpdateViaCache::kNone,
              stub_provider.UpdateViaCache());
  }
}

}  // namespace
}  // namespace blink
