// Copyright 2015 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.
//
// A simple C++ Pepper plugin for exercising deprecated PPAPI interfaces in
// Blink layout tests.
//
// Most layout tests should prefer to use the normal Blink test plugin, with the
// MIME type application/x-blink-test-plugin. For layout tests that absolutely
// need to test deprecated synchronous scripting interfaces, this plugin can be
// instantiated using the application/x-blink-deprecated-test-plugin MIME type.
//
// The plugin exposes the following interface:
//
// Attributes:
// testwindowopen: if set, the plugin will synchronously attempt to open a
// window from DidCreateInstance, and log a message if successful.
//
// keydownscript: if set, the plugin will execute the value of the attribute as
// a script on a key down.
//
// mousedownscript: if set, the plugin will execute the value of the attribute
// as a script on a mouse button down.
//
//
// Functions:
// * plugin.normalize(): synchronously calls window.pluginCallback.
//
// * plugin.remember(value): keeps a reference on |value| in the plugin.
//
// * plugin.testCloneObject(): creates and returns another instance of the
// plugin object.
//
// * plugin.testCreateTestObject(): creates and returns a new TestObject
// instance (see below).
//
// * plugin.testExecuteScript(script): synchronously evaluates |script| and
// returns the result.
//
// * plugin.testGetProperty(property): returns the property named |property|
// from the window object.
//
// * plugin.testPassTestObject(function, object): synchronously calls the
// function named |function| on the window object, passing it |object| as a
// parameter, and returns its result.
//
// * plugin.testScriptObjectInvoke(function, value): synchronously calls the
// function named |function| on the window object, passing it |value| as a
// parameter, and returns its result.
//
//
// Properties:
// * plugin.testObject (read-only): a TestObject instance (see below).
//
// * plugin.testObjectCount (read-only): the number of TestObject instance
// created.
//
// * plugin.testGetUndefined (read-only): returns undefined.
//
//
// TestObject exposes the following interface:
// Properties:
// * object.testObject (read-only: another TestObject instance.

#include <stdint.h>

#include <map>
#include <sstream>
#include <unordered_map>
#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/strings/stringprintf.h"
#include "ppapi/cpp/dev/scriptable_object_deprecated.h"
#include "ppapi/cpp/input_event.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/private/instance_private.h"
#include "ppapi/cpp/private/var_private.h"
#include "ppapi/cpp/var.h"

namespace {

class ScriptableBase : public pp::deprecated::ScriptableObject {
 public:
  explicit ScriptableBase(pp::InstancePrivate* instance)
      : instance_(instance) {}
  ~ScriptableBase() override {}

  // pp::deprecated::ScriptableObject overrides:
  bool HasMethod(const pp::Var& name, pp::Var* exception) override {
    return FindMethod(name) != methods_.end();
  }

  bool HasProperty(const pp::Var& name, pp::Var* exception) override {
    return FindProperty(name) != properties_.end();
  }

  pp::Var Call(const pp::Var& method_name,
               const std::vector<pp::Var>& args,
               pp::Var* exception) override {
    auto method = FindMethod(method_name);
    if (method != methods_.end()) {
      return method->second.Run(args, exception);
    }

    return ScriptableObject::Call(method_name, args, exception);
  }

  pp::Var GetProperty(const pp::Var& name, pp::Var* exception) override {
    auto accessor = FindProperty(name);
    if (accessor != properties_.end()) {
      pp::Var value;
      accessor->second.Run(false, &value);
      return value;
    }
    return ScriptableObject::GetProperty(name, exception);
  }

  void SetProperty(const pp::Var& name,
                   const pp::Var& value,
                   pp::Var* exception) override {
    auto accessor = FindProperty(name);
    if (accessor != properties_.end())
      accessor->second.Run(true, const_cast<pp::Var*>(&value));
    else
      ScriptableObject::SetProperty(name, value, exception);
  }

 protected:
  using MethodMap = std::map<
      std::string,
      base::RepeatingCallback<pp::Var(const std::vector<pp::Var>&, pp::Var*)>>;
  using PropertyMap =
      std::map<std::string, base::RepeatingCallback<void(bool, pp::Var*)>>;

  MethodMap::iterator FindMethod(const pp::Var& name) {
    if (!name.is_string())
      return methods_.end();
    return methods_.find(name.AsString());
  }

  PropertyMap::iterator FindProperty(const pp::Var& name) {
    if (!name.is_string())
      return properties_.end();
    return properties_.find(name.AsString());
  }

  pp::InstancePrivate* const instance_;
  MethodMap methods_;
  PropertyMap properties_;
};

class TestObjectSO : public ScriptableBase {
 public:
  explicit TestObjectSO(pp::InstancePrivate* instance)
      : ScriptableBase(instance) {
    ++count_;
    properties_.insert(std::make_pair(
        "testObject", base::BindRepeating(&TestObjectSO::TestObjectAccessor,
                                          base::Unretained(this))));
  }
  ~TestObjectSO() override {
    --count_;
  }

  static int32_t count() { return count_; }

 private:
  void TestObjectAccessor(bool set, pp::Var* var) {
    if (set)
      return;
    if (test_object_.is_undefined())
      test_object_ = pp::VarPrivate(instance_, new TestObjectSO(instance_));
    *var = test_object_;
  }

  static int32_t count_;

  pp::VarPrivate test_object_;
};

int32_t TestObjectSO::count_ = 0;

class InstanceSO : public ScriptableBase {
 public:
  explicit InstanceSO(pp::InstancePrivate* instance)
      : ScriptableBase(instance) {
    methods_.insert(std::make_pair(
        "normalize",
        base::BindRepeating(&InstanceSO::Normalize, base::Unretained(this))));
    methods_.insert(std::make_pair(
        "remember",
        base::BindRepeating(&InstanceSO::Remember, base::Unretained(this))));
    methods_.insert(std::make_pair(
        "testCloneObject", base::BindRepeating(&InstanceSO::TestCloneObject,
                                               base::Unretained(this))));
    methods_.insert(
        std::make_pair("testCreateTestObject",
                       base::BindRepeating(&InstanceSO::TestCreateTestObject,
                                           base::Unretained(this))));
    methods_.insert(std::make_pair(
        "testExecuteScript", base::BindRepeating(&InstanceSO::TestExecuteScript,
                                                 base::Unretained(this))));
    methods_.insert(std::make_pair(
        "testGetProperty", base::BindRepeating(&InstanceSO::TestGetProperty,
                                               base::Unretained(this))));
    methods_.insert(
        std::make_pair("testPassTestObject",
                       base::BindRepeating(&InstanceSO::TestPassTestObject,
                                           base::Unretained(this))));
    // Note: the semantics of testScriptObjectInvoke are identical to the
    // semantics of testPassTestObject: call args[0] with args[1] as a
    // parameter.
    methods_.insert(
        std::make_pair("testScriptObjectInvoke",
                       base::BindRepeating(&InstanceSO::TestPassTestObject,
                                           base::Unretained(this))));
    properties_.insert(std::make_pair(
        "testObject", base::BindRepeating(&InstanceSO::TestObjectAccessor,
                                          base::Unretained(this))));
    properties_.insert(
        std::make_pair("testObjectCount",
                       base::BindRepeating(&InstanceSO::TestObjectCountAccessor,
                                           base::Unretained(this))));
    properties_.insert(std::make_pair(
        "testGetUndefined",
        base::BindRepeating(&InstanceSO::TestGetUndefinedAccessor,
                            base::Unretained(this))));
  }
  ~InstanceSO() override = default;

 private:
  // Requires no argument.
  pp::Var Normalize(const std::vector<pp::Var>& args, pp::Var* exception) {
    pp::VarPrivate object = instance_->GetWindowObject();
    return object.Call(pp::Var("pluginCallback"), exception);
  }

  // Requires 1 argument. The argument is retained into remembered_
  pp::Var Remember(const std::vector<pp::Var>& args, pp::Var* exception) {
    if (args.size() != 1) {
      *exception = pp::Var("remember requires one argument");
      return pp::Var();
    }
    remembered_ = args[0];
    return pp::Var();
  }

  // Requires no argument.
  pp::Var TestCloneObject(const std::vector<pp::Var>& args,
                          pp::Var* exception) {
    return pp::VarPrivate(instance_, new InstanceSO(instance_));
  }

  // Requires no argument.
  pp::Var TestCreateTestObject(const std::vector<pp::Var>& args,
                               pp::Var* exception) {
    return pp::VarPrivate(instance_, new TestObjectSO(instance_));
  }

  // Requires one argument. The argument is passed through as-is to
  // pp::InstancePrivate::ExecuteScript().
  pp::Var TestExecuteScript(const std::vector<pp::Var>& args,
                            pp::Var* exception) {
    if (args.size() != 1) {
      *exception = pp::Var("testExecuteScript requires one argument");
      return pp::Var();
    }
    return instance_->ExecuteScript(args[0], exception);
  }

  // Requires one or more arguments. Roughly analogous to NPN_GetProperty.
  // The arguments are the chain of properties to traverse, starting with the
  // global context.
  pp::Var TestGetProperty(const std::vector<pp::Var>& args,
                          pp::Var* exception) {
    if (args.size() < 1) {
      *exception = pp::Var("testGetProperty requires at least one argument");
      return pp::Var();
    }
    pp::VarPrivate object = instance_->GetWindowObject();
    for (const auto& arg : args) {
      if (!object.HasProperty(arg, exception))
        return pp::Var();
      object = object.GetProperty(arg, exception);
    }
    return object;
  }

  // Requires 2 or more arguments. The first argument is the name of a function
  // to invoke, and the second argument is a value to pass to that function.
  pp::Var TestPassTestObject(const std::vector<pp::Var>& args,
                             pp::Var* exception) {
    if (args.size() < 2) {
      *exception = pp::Var("testPassTestObject requires at least 2 arguments");
      return pp::Var();
    }
    pp::VarPrivate object = instance_->GetWindowObject();
    return object.Call(args[0], args[1], exception);
  }

  void TestObjectAccessor(bool set, pp::Var* var) {
    if (set)
      return;
    if (test_object_.is_undefined())
      test_object_ = pp::VarPrivate(instance_, new TestObjectSO(instance_));
    *var = test_object_;
  }

  void TestObjectCountAccessor(bool set, pp::Var* var) {
    if (set)
      return;
    *var = pp::Var(TestObjectSO::count());
  }

  void TestGetUndefinedAccessor(bool set, pp::Var* var) {
    if (set)
      return;
    *var = pp::Var();
  }

  pp::VarPrivate test_object_;
  pp::Var remembered_;
};

class BlinkDeprecatedTestInstance : public pp::InstancePrivate {
 public:
  explicit BlinkDeprecatedTestInstance(PP_Instance instance)
      : pp::InstancePrivate(instance) {}
  ~BlinkDeprecatedTestInstance() override {
    LogMessage("%s", "Destroying");
  }

  // pp::Instance overrides
  bool Init(uint32_t argc, const char* argn[], const char* argv[]) override {
    for (uint32_t i = 0; i < argc; ++i)
      attributes_[argn[i]] = argv[i];

    if (HasAttribute("testwindowopen"))
      return TestWindowOpen();

    if (HasAttribute("initscript"))
      ExecuteScript(attributes_["initscript"]);

    uint32_t event_classes = 0;
    if (HasAttribute("keydownscript"))
        event_classes |= PP_INPUTEVENT_CLASS_KEYBOARD;
    if (HasAttribute("mousedownscript"))
        event_classes |= PP_INPUTEVENT_CLASS_MOUSE;
    RequestFilteringInputEvents(event_classes);

    return true;
  }

  virtual bool HandleInputEvent(const pp::InputEvent& event) override {
    switch (event.GetType()) {
      case PP_INPUTEVENT_TYPE_MOUSEDOWN:
        if (HasAttribute("mousedownscript"))
          ExecuteScript(attributes_["mousedownscript"]);
        return true;
      case PP_INPUTEVENT_TYPE_KEYDOWN:
        if (HasAttribute("keydownscript"))
          ExecuteScript(attributes_["keydownscript"]);
        return true;
      default:
        return false;
    }
  }

  // pp::InstancePrivate overrides:
  pp::Var GetInstanceObject() override {
    if (instance_var_.is_undefined()) {
      instance_so_ = new InstanceSO(this);
      instance_var_ = pp::VarPrivate(this, instance_so_);
    }
    return instance_var_;
  }

  void NotifyTestCompletion() {
    ExecuteScript("window.testRunner.notifyDone()");
  }

  bool TestWindowOpen() {
    pp::Var result = GetWindowObject().Call(
        pp::Var("open"), pp::Var("about:blank"), pp::Var("_blank"));
    if (result.is_object())
      LogMessage("PLUGIN: WINDOW OPEN SUCCESS");
    NotifyTestCompletion();
    return true;
  }

  void LogMessage(const char* format...) {
    va_list args;
    va_start(args, format);
    LogToConsoleWithSource(PP_LOGLEVEL_LOG,
                           pp::Var("Blink Deprecated Test Plugin"),
                           pp::Var(base::StringPrintV(format, args)));
    va_end(args);
  }

 private:
  bool HasAttribute(const std::string& name) {
    return attributes_.find(name) != attributes_.end();
  }

  std::unordered_map<std::string, std::string> attributes_;
  pp::VarPrivate instance_var_;
  // Owned by |instance_var_|.
  InstanceSO* instance_so_;
};

class BlinkDeprecatedTestModule : public pp::Module {
 public:
  BlinkDeprecatedTestModule() {}
  ~BlinkDeprecatedTestModule() override {}

  pp::Instance* CreateInstance(PP_Instance instance) override {
    return new BlinkDeprecatedTestInstance(instance);
  }
};

}  // namespace

namespace pp {

Module* CreateModule() {
  return new BlinkDeprecatedTestModule();
}

}  // namespace pp
