// 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::Callback<pp::Var(const std::vector<pp::Var>&, pp::Var*)>>;
  using PropertyMap =
      std::map<std::string, base::Callback<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::Bind(&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::Bind(&InstanceSO::Normalize, base::Unretained(this))));
    methods_.insert(std::make_pair(
        "remember",
        base::Bind(&InstanceSO::Remember, base::Unretained(this))));
    methods_.insert(std::make_pair(
        "testCloneObject",
        base::Bind(&InstanceSO::TestCloneObject, base::Unretained(this))));
    methods_.insert(std::make_pair(
        "testCreateTestObject",
        base::Bind(&InstanceSO::TestCreateTestObject, base::Unretained(this))));
    methods_.insert(std::make_pair(
        "testExecuteScript",
        base::Bind(&InstanceSO::TestExecuteScript, base::Unretained(this))));
    methods_.insert(std::make_pair(
        "testGetProperty",
        base::Bind(&InstanceSO::TestGetProperty, base::Unretained(this))));
    methods_.insert(std::make_pair(
        "testPassTestObject",
        base::Bind(&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::Bind(&InstanceSO::TestPassTestObject,
                                  base::Unretained(this))));
    properties_.insert(std::make_pair(
        "testObject", base::Bind(&InstanceSO::TestObjectAccessor,
                                 base::Unretained(this))));
    properties_.insert(std::make_pair(
        "testObjectCount", base::Bind(&InstanceSO::TestObjectCountAccessor,
                                      base::Unretained(this))));
    properties_.insert(std::make_pair(
        "testGetUndefined", base::Bind(&InstanceSO::TestGetUndefinedAccessor,
                                       base::Unretained(this))));
  }
  ~InstanceSO() override {}

 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 {}

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

}  // namespace

namespace pp {

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

}  // namespace pp
