1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/*
6 * Copyright (C) 2007 Apple Inc. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include "content/shell/tools/plugin/test_object.h"
31
32#include "PluginObject.h"
33
34#include <string.h>
35#include <stdlib.h>
36
37static bool testEnumerate(NPObject* npobj,
38                          NPIdentifier** value,
39                          uint32_t* count);
40static bool testHasMethod(NPObject*, NPIdentifier name);
41static bool testInvoke(NPObject*,
42                       NPIdentifier name,
43                       const NPVariant* args,
44                       uint32_t argCount,
45                       NPVariant* result);
46static bool testHasProperty(NPObject*, NPIdentifier name);
47static bool testGetProperty(NPObject*, NPIdentifier name, NPVariant*);
48static NPObject* testAllocate(NPP npp, NPClass* theClass);
49static void testDeallocate(NPObject* obj);
50static bool testConstruct(NPObject* obj,
51                          const NPVariant* args,
52                          uint32_t argCount,
53                          NPVariant* result);
54
55static NPClass g_test_class = {
56    NP_CLASS_STRUCT_VERSION, testAllocate, testDeallocate, 0,
57    testHasMethod,           testInvoke,   0,              testHasProperty,
58    testGetProperty,         0,            0,              testEnumerate,
59    testConstruct};
60
61
62static int g_test_object_count = 0;
63
64typedef struct {
65  NPObject header;
66  NPObject* testObject;
67} TestObject;
68
69static bool identifiersInitialized = false;
70
71#define NUM_ENUMERATABLE_TEST_IDENTIFIERS 2
72
73enum {
74  ID_PROPERTY_FOO = 0,
75  ID_PROPERTY_BAR,
76  ID_PROPERTY_OBJECT_POINTER,
77  ID_PROPERTY_TEST_OBJECT,
78  ID_PROPERTY_REF_COUNT,
79  NUM_TEST_IDENTIFIERS,
80};
81
82static NPIdentifier testIdentifiers[NUM_TEST_IDENTIFIERS];
83static const NPUTF8* testIdentifierNames[NUM_TEST_IDENTIFIERS] = {
84    "foo", "bar", "objectPointer", "testObject", "refCount", };
85
86#define ID_THROW_EXCEPTION_METHOD 0
87#define NUM_METHOD_IDENTIFIERS 1
88
89static NPIdentifier testMethodIdentifiers[NUM_METHOD_IDENTIFIERS];
90static const NPUTF8* testMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = {
91    "throwException", };
92
93static void initializeIdentifiers(void) {
94  browser->getstringidentifiers(
95      testIdentifierNames, NUM_TEST_IDENTIFIERS, testIdentifiers);
96  browser->getstringidentifiers(
97      testMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, testMethodIdentifiers);
98}
99
100static NPObject* testAllocate(NPP npp, NPClass* /*theClass*/) {
101  TestObject* newInstance =
102      static_cast<TestObject*>(malloc(sizeof(TestObject)));
103  newInstance->testObject = 0;
104  ++g_test_object_count;
105
106  if (!identifiersInitialized) {
107    identifiersInitialized = true;
108    initializeIdentifiers();
109  }
110
111  return reinterpret_cast<NPObject*>(newInstance);
112}
113
114static void testDeallocate(NPObject* obj) {
115  TestObject* testObject = reinterpret_cast<TestObject*>(obj);
116  if (testObject->testObject)
117    browser->releaseobject(testObject->testObject);
118
119  --g_test_object_count;
120  free(obj);
121}
122
123static bool testHasMethod(NPObject*, NPIdentifier name) {
124  for (unsigned i = 0; i < NUM_METHOD_IDENTIFIERS; i++) {
125    if (testMethodIdentifiers[i] == name)
126      return true;
127  }
128  return false;
129}
130
131static bool testInvoke(NPObject* header,
132                       NPIdentifier name,
133                       const NPVariant* /*args*/,
134                       uint32_t /*argCount*/,
135                       NPVariant* /*result*/) {
136  if (name == testMethodIdentifiers[ID_THROW_EXCEPTION_METHOD]) {
137    browser->setexception(header, "test object throwException SUCCESS");
138    return true;
139  }
140  return false;
141}
142
143static bool testHasProperty(NPObject*, NPIdentifier name) {
144  for (unsigned i = 0; i < NUM_TEST_IDENTIFIERS; i++) {
145    if (testIdentifiers[i] == name)
146      return true;
147  }
148
149  return false;
150}
151
152static bool testGetProperty(NPObject* npobj,
153                            NPIdentifier name,
154                            NPVariant* result) {
155  if (name == testIdentifiers[ID_PROPERTY_FOO]) {
156    char* mem = static_cast<char*>(browser->memalloc(4));
157    strcpy(mem, "foo");
158    STRINGZ_TO_NPVARIANT(mem, *result);
159    return true;
160  }
161  if (name == testIdentifiers[ID_PROPERTY_BAR]) {
162    char* mem = static_cast<char*>(browser->memalloc(4));
163    strcpy(mem, "bar");
164    STRINGZ_TO_NPVARIANT(mem, *result);
165    return true;
166  }
167  if (name == testIdentifiers[ID_PROPERTY_OBJECT_POINTER]) {
168    int32_t objectPointer =
169        static_cast<int32_t>(reinterpret_cast<long long>(npobj));
170
171    INT32_TO_NPVARIANT(objectPointer, *result);
172    return true;
173  }
174  if (name == testIdentifiers[ID_PROPERTY_TEST_OBJECT]) {
175    TestObject* testObject = reinterpret_cast<TestObject*>(npobj);
176    if (!testObject->testObject)
177      testObject->testObject = browser->createobject(0, &g_test_class);
178    browser->retainobject(testObject->testObject);
179    OBJECT_TO_NPVARIANT(testObject->testObject, *result);
180    return true;
181  }
182  if (name == testIdentifiers[ID_PROPERTY_REF_COUNT]) {
183    INT32_TO_NPVARIANT(npobj->referenceCount, *result);
184    return true;
185  }
186
187  return false;
188}
189
190static bool testEnumerate(NPObject* /*npobj*/,
191                          NPIdentifier** value,
192                          uint32_t* count) {
193  *count = NUM_ENUMERATABLE_TEST_IDENTIFIERS;
194
195  *value = (NPIdentifier*)browser->memalloc(NUM_ENUMERATABLE_TEST_IDENTIFIERS *
196                                            sizeof(NPIdentifier));
197  memcpy(*value,
198         testIdentifiers,
199         sizeof(NPIdentifier) * NUM_ENUMERATABLE_TEST_IDENTIFIERS);
200
201  return true;
202}
203
204static bool testConstruct(NPObject* npobj,
205                          const NPVariant* /*args*/,
206                          uint32_t /*argCount*/,
207                          NPVariant* result) {
208  browser->retainobject(npobj);
209
210  // Just return the same object.
211  OBJECT_TO_NPVARIANT(npobj, *result);
212  return true;
213}
214
215namespace content {
216
217NPClass* GetTestClass() { return &g_test_class; }
218
219int GetTestObjectCount() { return g_test_object_count; }
220
221}  // namespace content
222