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

/*
 * Copyright (C) 2010 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef PluginTest_h
#define PluginTest_h

#include <assert.h>
#include <bindings/npfunctions.h>
#include <map>
#include <string>

// Helper classes for implementing has_member
typedef char (&no_tag)[1];
typedef char (&yes_tag)[2];

#define DEFINE_HAS_MEMBER_CHECK(member, returnType, argumentTypes)             \
  template <typename T, returnType(T::*member) argumentTypes>                  \
  struct pmf_##member##_helper {};                                             \
  template <typename T>                                                        \
  no_tag has_member_##member##_helper(...);                                    \
  template <typename T>                                                        \
  yes_tag has_member_##member##_helper(pmf_##member##_helper<T, &T::member>*); \
  template <typename T>                                                        \
  struct has_member_##member {                                                 \
    static const bool value =                                                  \
        sizeof(has_member_##member##_helper<T>(0)) == sizeof(yes_tag);         \
  };

DEFINE_HAS_MEMBER_CHECK(hasMethod, bool, (NPIdentifier methodName));
DEFINE_HAS_MEMBER_CHECK(
    invoke,
    bool,
    (NPIdentifier methodName, const NPVariant*, uint32_t, NPVariant* result));
DEFINE_HAS_MEMBER_CHECK(invokeDefault,
                        bool,
                        (const NPVariant*, uint32_t, NPVariant* result));
DEFINE_HAS_MEMBER_CHECK(hasProperty, bool, (NPIdentifier propertyName));
DEFINE_HAS_MEMBER_CHECK(getProperty,
                        bool,
                        (NPIdentifier propertyName, NPVariant* result));
DEFINE_HAS_MEMBER_CHECK(removeProperty, bool, (NPIdentifier propertyName));

class PluginTest {
 public:
  static PluginTest* create(NPP, const std::string& identifier);
  virtual ~PluginTest();

  static void NP_Shutdown();

  // NPP functions.
  virtual NPError NPP_New(NPMIMEType pluginType,
                          uint16_t mode,
                          int16_t argc,
                          char* argn[],
                          char* argv[],
                          NPSavedData* saved);
  virtual NPError NPP_Destroy(NPSavedData**);
  virtual NPError NPP_SetWindow(NPWindow*);
  virtual NPError NPP_NewStream(NPMIMEType,
                                NPStream*,
                                NPBool seekable,
                                uint16_t* stype);
  virtual NPError NPP_DestroyStream(NPStream*, NPReason);
  virtual int32_t NPP_WriteReady(NPStream*);
  virtual int32_t NPP_Write(NPStream*,
                            int32_t offset,
                            int32_t len,
                            void* buffer);
  virtual int16_t NPP_HandleEvent(void* event);
  virtual bool NPP_URLNotify(const char* url, NPReason, void* notifyData);
  virtual NPError NPP_GetValue(NPPVariable, void* value);
  virtual NPError NPP_SetValue(NPNVariable, void* value);

  // NPN functions.
  NPError NPN_GetURL(const char* url, const char* target);
  NPError NPN_GetURLNotify(const char* url,
                           const char* target,
                           void* notifyData);
  NPError NPN_GetValue(NPNVariable, void* value);
  void NPN_InvalidateRect(NPRect* invalidRect);
  bool NPN_Invoke(NPObject*,
                  NPIdentifier methodName,
                  const NPVariant* args,
                  uint32_t argCount,
                  NPVariant* result);
  void* NPN_MemAlloc(uint32_t size);

  // NPRuntime NPN functions.
  NPIdentifier NPN_GetStringIdentifier(const NPUTF8* name);
  NPIdentifier NPN_GetIntIdentifier(int32_t intid);
  bool NPN_IdentifierIsString(NPIdentifier);
  NPUTF8* NPN_UTF8FromIdentifier(NPIdentifier);
  int32_t NPN_IntFromIdentifier(NPIdentifier);

  NPObject* NPN_CreateObject(NPClass*);
  NPObject* NPN_RetainObject(NPObject*);
  void NPN_ReleaseObject(NPObject*);
  bool NPN_GetProperty(NPObject*, NPIdentifier propertyName, NPVariant* value);
  bool NPN_RemoveProperty(NPObject*, NPIdentifier propertyName);
  void NPN_ReleaseVariantValue(NPVariant*);

#ifdef XP_MACOSX
  bool NPN_ConvertPoint(double sourceX,
                        double sourceY,
                        NPCoordinateSpace sourceSpace,
                        double* destX,
                        double* destY,
                        NPCoordinateSpace destSpace);
#endif

  bool executeScript(const NPString*, NPVariant* result);
  void executeScript(const char*);
  void log(const char* format, ...);

  void registerNPShutdownFunction(void (*)());

  static void indicateTestFailure();

  template <typename TestClassTy>
  class Register {
   public:
    Register(const std::string& identifier) {
      registerCreateTestFunction(identifier, Register::create);
    }

   private:
    static PluginTest* create(NPP npp, const std::string& identifier) {
      return new TestClassTy(npp, identifier);
    }
  };

 protected:
  PluginTest(NPP npp, const std::string& identifier);

  // FIXME: A plugin test shouldn't need to know about it's NPP. Make this
  // private.
  NPP m_npp;

  const std::string& identifier() const { return m_identifier; }

  static NPNetscapeFuncs* netscapeFuncs();

  void waitUntilDone();
  void notifyDone();

  // NPObject helper template.
  template <typename T>
  struct Object : NPObject {
   public:
    static NPObject* create(PluginTest* pluginTest) {
      Object* object =
          static_cast<Object*>(pluginTest->NPN_CreateObject(npClass()));

      object->m_pluginTest = pluginTest;
      return object;
    }

    // These should never be called.
    bool hasMethod(NPIdentifier methodName) {
      assert(false);
      return false;
    }

    bool invoke(NPIdentifier methodName,
                const NPVariant*,
                uint32_t,
                NPVariant* result) {
      assert(false);
      return false;
    }

    bool invokeDefault(const NPVariant*, uint32_t, NPVariant* result) {
      assert(false);
      return false;
    }

    bool hasProperty(NPIdentifier propertyName) {
      assert(false);
      return false;
    }

    bool getProperty(NPIdentifier propertyName, NPVariant* result) {
      assert(false);
      return false;
    }

    bool removeProperty(NPIdentifier propertyName) {
      assert(false);
      return false;
    }

    // Helper functions.
    bool identifierIs(NPIdentifier identifier, const char* value) {
      return pluginTest()->NPN_GetStringIdentifier(value) == identifier;
    }

   protected:
    Object() : m_pluginTest(0) {}

    virtual ~Object() {}

    PluginTest* pluginTest() const { return m_pluginTest; }

   private:
    static NPObject* NP_Allocate(NPP npp, NPClass* aClass) { return new T; }

    static void NP_Deallocate(NPObject* npObject) {
      delete static_cast<T*>(npObject);
    }

    static bool NP_HasMethod(NPObject* npObject, NPIdentifier methodName) {
      return static_cast<T*>(npObject)->hasMethod(methodName);
    }

    static bool NP_Invoke(NPObject* npObject,
                          NPIdentifier methodName,
                          const NPVariant* arguments,
                          uint32_t argumentCount,
                          NPVariant* result) {
      return static_cast<T*>(npObject)
          ->invoke(methodName, arguments, argumentCount, result);
    }

    static bool NP_InvokeDefault(NPObject* npObject,
                                 const NPVariant* arguments,
                                 uint32_t argumentCount,
                                 NPVariant* result) {
      return static_cast<T*>(npObject)
          ->invokeDefault(arguments, argumentCount, result);
    }

    static bool NP_HasProperty(NPObject* npObject, NPIdentifier propertyName) {
      return static_cast<T*>(npObject)->hasProperty(propertyName);
    }

    static bool NP_GetProperty(NPObject* npObject,
                               NPIdentifier propertyName,
                               NPVariant* result) {
      return static_cast<T*>(npObject)->getProperty(propertyName, result);
    }

    static bool NP_RemoveProperty(NPObject* npObject,
                                  NPIdentifier propertyName) {
      return static_cast<T*>(npObject)->removeProperty(propertyName);
    }

    static NPClass* npClass() {
      static NPClass npClass = {
          NP_CLASS_STRUCT_VERSION, NP_Allocate, NP_Deallocate,
          0,  // NPClass::invalidate
          has_member_hasMethod<T>::value ? NP_HasMethod : 0,
          has_member_invoke<T>::value ? NP_Invoke : 0,
          has_member_invokeDefault<T>::value ? NP_InvokeDefault : 0,
          has_member_hasProperty<T>::value ? NP_HasProperty : 0,
          has_member_getProperty<T>::value ? NP_GetProperty : 0,
          0,  // NPClass::setProperty
          has_member_removeProperty<T>::value ? NP_RemoveProperty : 0,
          0,  // NPClass::enumerate
          0   // NPClass::construct
      };

      return &npClass;
    };

    PluginTest* m_pluginTest;
  };

 private:
  typedef PluginTest* (*CreateTestFunction)(NPP, const std::string&);

  static void registerCreateTestFunction(const std::string&,
                                         CreateTestFunction);
  static std::map<std::string, CreateTestFunction>& createTestFunctions();

  std::string m_identifier;
};

#endif  // PluginTest_h
