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) 2010 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. AND ITS CONTRIBUTORS ``AS IS''
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include "PluginTest.h"
31
32#include "PluginObject.h"
33#include <string.h>
34
35#if defined(XP_UNIX) || defined(ANDROID)
36#include <unistd.h>
37#endif
38
39using namespace std;
40extern NPNetscapeFuncs *browser;
41
42static void (*shutdownFunction)();
43
44PluginTest* PluginTest::create(NPP npp, const string& identifier) {
45  if (identifier.empty())
46    return new PluginTest(npp, identifier);
47
48  CreateTestFunction createTestFunction = createTestFunctions()[identifier];
49  if (createTestFunction)
50    return createTestFunction(npp, identifier);
51
52  return 0;
53}
54
55PluginTest::PluginTest(NPP npp, const string& identifier)
56    : m_npp(npp), m_identifier(identifier) {
57  // Reset the shutdown function.
58  shutdownFunction = 0;
59}
60
61PluginTest::~PluginTest() {}
62
63void PluginTest::NP_Shutdown() {
64  if (shutdownFunction)
65    shutdownFunction();
66}
67
68void PluginTest::registerNPShutdownFunction(void (*func)()) {
69  assert(!shutdownFunction);
70  shutdownFunction = func;
71}
72
73void PluginTest::indicateTestFailure() {
74// This should really be an assert, but there's no way for the test framework
75// to know that the plug-in process crashed, so we'll just sleep for a while
76// to ensure that the test times out.
77#if defined(XP_WIN)
78  ::Sleep(100000);
79#else
80  sleep(1000);
81#endif
82}
83
84NPError PluginTest::NPP_New(NPMIMEType pluginType,
85                            uint16_t mode,
86                            int16_t argc,
87                            char* argn[],
88                            char* argv[],
89                            NPSavedData* saved) {
90  return NPERR_NO_ERROR;
91}
92
93NPError PluginTest::NPP_Destroy(NPSavedData**) { return NPERR_NO_ERROR; }
94
95NPError PluginTest::NPP_SetWindow(NPWindow*) { return NPERR_NO_ERROR; }
96
97NPError PluginTest::NPP_NewStream(NPMIMEType type,
98                                  NPStream* stream,
99                                  NPBool seekable,
100                                  uint16_t* stype) {
101  return NPERR_NO_ERROR;
102}
103
104NPError PluginTest::NPP_DestroyStream(NPStream* stream, NPReason reason) {
105  return NPERR_NO_ERROR;
106}
107
108int32_t PluginTest::NPP_WriteReady(NPStream*) { return 4096; }
109
110int32_t PluginTest::NPP_Write(NPStream*,
111                              int32_t offset,
112                              int32_t len,
113                              void* buffer) {
114  return len;
115}
116
117int16_t PluginTest::NPP_HandleEvent(void*) { return 0; }
118
119bool PluginTest::NPP_URLNotify(const char* url, NPReason, void* notifyData) {
120  // FIXME: Port the code from NPP_URLNotify in main.cpp over to always using
121  // PluginTest, so we don't have to use a return value to indicate whether the
122  // "default" NPP_URLNotify implementation should be invoked.
123  return false;
124}
125
126NPError PluginTest::NPP_GetValue(NPPVariable variable, void* value) {
127  // We don't know anything about plug-in values so just return
128  // NPERR_GENERIC_ERROR.
129  return NPERR_GENERIC_ERROR;
130}
131
132NPError PluginTest::NPP_SetValue(NPNVariable, void* value) {
133  return NPERR_GENERIC_ERROR;
134}
135
136// NPN functions.
137
138NPError PluginTest::NPN_GetURL(const char* url, const char* target) {
139  return browser->geturl(m_npp, url, target);
140}
141
142NPError PluginTest::NPN_GetURLNotify(const char* url,
143                                     const char* target,
144                                     void* notifyData) {
145  return browser->geturlnotify(m_npp, url, target, notifyData);
146}
147
148NPError PluginTest::NPN_GetValue(NPNVariable variable, void* value) {
149  return browser->getvalue(m_npp, variable, value);
150}
151
152void PluginTest::NPN_InvalidateRect(NPRect* invalidRect) {
153  browser->invalidaterect(m_npp, invalidRect);
154}
155
156bool PluginTest::NPN_Invoke(NPObject* npobj,
157                            NPIdentifier methodName,
158                            const NPVariant* args,
159                            uint32_t argCount,
160                            NPVariant* result) {
161  return browser->invoke(m_npp, npobj, methodName, args, argCount, result);
162}
163
164void* PluginTest::NPN_MemAlloc(uint32_t size) {
165  return browser->memalloc(size);
166}
167
168// NPRuntime NPN functions.
169
170NPIdentifier PluginTest::NPN_GetStringIdentifier(const NPUTF8* name) {
171  return browser->getstringidentifier(name);
172}
173
174NPIdentifier PluginTest::NPN_GetIntIdentifier(int32_t intid) {
175  return browser->getintidentifier(intid);
176}
177
178bool PluginTest::NPN_IdentifierIsString(NPIdentifier npIdentifier) {
179  return browser->identifierisstring(npIdentifier);
180}
181
182NPUTF8* PluginTest::NPN_UTF8FromIdentifier(NPIdentifier npIdentifier) {
183  return browser->utf8fromidentifier(npIdentifier);
184}
185
186int32_t PluginTest::NPN_IntFromIdentifier(NPIdentifier npIdentifier) {
187  return browser->intfromidentifier(npIdentifier);
188}
189
190NPObject* PluginTest::NPN_CreateObject(NPClass* npClass) {
191  return browser->createobject(m_npp, npClass);
192}
193
194NPObject* PluginTest::NPN_RetainObject(NPObject* npObject) {
195  return browser->retainobject(npObject);
196}
197
198void PluginTest::NPN_ReleaseObject(NPObject* npObject) {
199  browser->releaseobject(npObject);
200}
201
202bool PluginTest::NPN_GetProperty(NPObject* npObject,
203                                 NPIdentifier propertyName,
204                                 NPVariant* value) {
205  return browser->getproperty(m_npp, npObject, propertyName, value);
206}
207
208bool PluginTest::NPN_RemoveProperty(NPObject* npObject,
209                                    NPIdentifier propertyName) {
210  return browser->removeproperty(m_npp, npObject, propertyName);
211}
212
213void PluginTest::NPN_ReleaseVariantValue(NPVariant* variant) {
214  browser->releasevariantvalue(variant);
215}
216
217#ifdef XP_MACOSX
218bool PluginTest::NPN_ConvertPoint(double sourceX,
219                                  double sourceY,
220                                  NPCoordinateSpace sourceSpace,
221                                  double* destX,
222                                  double* destY,
223                                  NPCoordinateSpace destSpace) {
224  return browser->convertpoint(
225      m_npp, sourceX, sourceY, sourceSpace, destX, destY, destSpace);
226}
227#endif
228
229bool PluginTest::executeScript(const NPString* script, NPVariant* result) {
230  NPObject* windowScriptObject;
231  browser->getvalue(m_npp, NPNVWindowNPObject, &windowScriptObject);
232
233  return browser->evaluate(
234      m_npp, windowScriptObject, const_cast<NPString*>(script), result);
235}
236
237void PluginTest::executeScript(const char* script) {
238  NPString npScript;
239  npScript.UTF8Characters = script;
240  npScript.UTF8Length = strlen(script);
241
242  NPVariant browserResult;
243  executeScript(&npScript, &browserResult);
244  browser->releasevariantvalue(&browserResult);
245}
246
247void PluginTest::log(const char* format, ...) {
248  va_list args;
249  va_start(args, format);
250  pluginLogWithArguments(m_npp, format, args);
251  va_end(args);
252}
253
254NPNetscapeFuncs* PluginTest::netscapeFuncs() { return browser; }
255
256void PluginTest::waitUntilDone() {
257  executeScript("testRunner.waitUntilDone()");
258}
259
260void PluginTest::notifyDone() { executeScript("testRunner.notifyDone()"); }
261
262void PluginTest::registerCreateTestFunction(
263    const string& identifier,
264    CreateTestFunction createTestFunction) {
265  assert(!createTestFunctions().count(identifier));
266
267  createTestFunctions()[identifier] = createTestFunction;
268}
269
270std::map<std::string, PluginTest::CreateTestFunction>&
271PluginTest::createTestFunctions() {
272  static std::map<std::string, CreateTestFunction> testFunctions;
273
274  return testFunctions;
275}
276