root/content/shell/tools/plugin/PluginTest.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


// 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 plug-in 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

/* [<][>][^][v][top][bottom][index][help] */