1 /*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "NetscapeBrowserFuncs.h"
28
29 #include "NPRuntimeUtilities.h"
30 #include "NetscapePlugin.h"
31 #include "PluginController.h"
32 #include <WebCore/HTTPHeaderMap.h>
33 #include <WebCore/IdentifierRep.h>
34 #include <WebCore/NotImplemented.h>
35 #include <WebCore/SharedBuffer.h>
36 #include <utility>
37
38 #if PLATFORM(QT)
39 #include <QX11Info>
40 #elif PLATFORM(GTK)
41 #include <gdk/gdkx.h>
42 #endif
43
44 using namespace WebCore;
45 using namespace std;
46
47 namespace WebKit {
48
49 // Helper class for delaying destruction of a plug-in.
50 class PluginDestructionProtector {
51 public:
PluginDestructionProtector(NetscapePlugin * plugin)52 explicit PluginDestructionProtector(NetscapePlugin* plugin)
53 : m_protector(static_cast<Plugin*>(plugin)->controller())
54 {
55 }
56
57 private:
58 PluginController::PluginDestructionProtector m_protector;
59 };
60
startsWithBlankLine(const char * bytes,unsigned length)61 static bool startsWithBlankLine(const char* bytes, unsigned length)
62 {
63 return length > 0 && bytes[0] == '\n';
64 }
65
locationAfterFirstBlankLine(const char * bytes,unsigned length)66 static int locationAfterFirstBlankLine(const char* bytes, unsigned length)
67 {
68 for (unsigned i = 0; i < length - 4; i++) {
69 // Support for Acrobat. It sends "\n\n".
70 if (bytes[i] == '\n' && bytes[i + 1] == '\n')
71 return i + 2;
72
73 // Returns the position after 2 CRLF's or 1 CRLF if it is the first line.
74 if (bytes[i] == '\r' && bytes[i + 1] == '\n') {
75 i += 2;
76 if (i == 2)
77 return i;
78
79 if (bytes[i] == '\n') {
80 // Support for Director. It sends "\r\n\n" (3880387).
81 return i + 1;
82 }
83
84 if (bytes[i] == '\r' && bytes[i + 1] == '\n') {
85 // Support for Flash. It sends "\r\n\r\n" (3758113).
86 return i + 2;
87 }
88 }
89 }
90
91 return -1;
92 }
93
findEndOfLine(const char * bytes,unsigned length)94 static const char* findEndOfLine(const char* bytes, unsigned length)
95 {
96 // According to the HTTP specification EOL is defined as
97 // a CRLF pair. Unfortunately, some servers will use LF
98 // instead. Worse yet, some servers will use a combination
99 // of both (e.g. <header>CRLFLF<body>), so findEOL needs
100 // to be more forgiving. It will now accept CRLF, LF or
101 // CR.
102 //
103 // It returns 0 if EOLF is not found or it will return
104 // a pointer to the first terminating character.
105 for (unsigned i = 0; i < length; i++) {
106 if (bytes[i] == '\n')
107 return bytes + i;
108 if (bytes[i] == '\r') {
109 // Check to see if spanning buffer bounds
110 // (CRLF is across reads). If so, wait for
111 // next read.
112 if (i + 1 == length)
113 break;
114
115 return bytes + i;
116 }
117 }
118
119 return 0;
120 }
121
capitalizeRFC822HeaderFieldName(const String & name)122 static String capitalizeRFC822HeaderFieldName(const String& name)
123 {
124 bool capitalizeCharacter = true;
125 String result;
126
127 for (unsigned i = 0; i < name.length(); i++) {
128 UChar c;
129
130 if (capitalizeCharacter && name[i] >= 'a' && name[i] <= 'z')
131 c = toASCIIUpper(name[i]);
132 else if (!capitalizeCharacter && name[i] >= 'A' && name[i] <= 'Z')
133 c = toASCIILower(name[i]);
134 else
135 c = name[i];
136
137 if (name[i] == '-')
138 capitalizeCharacter = true;
139 else
140 capitalizeCharacter = false;
141
142 result.append(c);
143 }
144
145 return result;
146 }
147
parseRFC822HeaderFields(const char * bytes,unsigned length)148 static HTTPHeaderMap parseRFC822HeaderFields(const char* bytes, unsigned length)
149 {
150 String lastHeaderKey;
151 HTTPHeaderMap headerFields;
152
153 // Loop over lines until we're past the header, or we can't find any more end-of-lines
154 while (const char* endOfLine = findEndOfLine(bytes, length)) {
155 const char* line = bytes;
156 int lineLength = endOfLine - bytes;
157
158 // Move bytes to the character after the terminator as returned by findEndOfLine.
159 bytes = endOfLine + 1;
160 if ((*endOfLine == '\r') && (*bytes == '\n'))
161 bytes++; // Safe since findEndOfLine won't return a spanning CRLF.
162
163 length -= (bytes - line);
164 if (!lineLength) {
165 // Blank line; we're at the end of the header
166 break;
167 }
168
169 if (*line == ' ' || *line == '\t') {
170 // Continuation of the previous header
171 if (lastHeaderKey.isNull()) {
172 // malformed header; ignore it and continue
173 continue;
174 }
175
176 // Merge the continuation of the previous header
177 String currentValue = headerFields.get(lastHeaderKey);
178 String newValue(line, lineLength);
179
180 headerFields.set(lastHeaderKey, currentValue + newValue);
181 } else {
182 // Brand new header
183 const char* colon = line;
184 while (*colon != ':' && colon != endOfLine)
185 colon++;
186
187 if (colon == endOfLine) {
188 // malformed header; ignore it and continue
189 continue;
190 }
191
192 lastHeaderKey = capitalizeRFC822HeaderFieldName(String(line, colon - line));
193 String value;
194
195 for (colon++; colon != endOfLine; colon++) {
196 if (*colon != ' ' && *colon != '\t')
197 break;
198 }
199 if (colon == endOfLine)
200 value = "";
201 else
202 value = String(colon, endOfLine - colon);
203
204 String oldValue = headerFields.get(lastHeaderKey);
205 if (!oldValue.isNull()) {
206 String tmp = oldValue;
207 tmp += ", ";
208 tmp += value;
209 value = tmp;
210 }
211
212 headerFields.set(lastHeaderKey, value);
213 }
214 }
215
216 return headerFields;
217 }
218
parsePostBuffer(bool isFile,const char * buffer,uint32_t length,bool parseHeaders,HTTPHeaderMap & headerFields,Vector<uint8_t> & bodyData)219 static NPError parsePostBuffer(bool isFile, const char *buffer, uint32_t length, bool parseHeaders, HTTPHeaderMap& headerFields, Vector<uint8_t>& bodyData)
220 {
221 RefPtr<SharedBuffer> fileContents;
222 const char* postBuffer = 0;
223 uint32_t postBufferSize = 0;
224
225 if (isFile) {
226 fileContents = SharedBuffer::createWithContentsOfFile(String::fromUTF8(buffer));
227 if (!fileContents)
228 return NPERR_FILE_NOT_FOUND;
229
230 postBuffer = fileContents->data();
231 postBufferSize = fileContents->size();
232
233 // FIXME: The NPAPI spec states that the file should be deleted here.
234 } else {
235 postBuffer = buffer;
236 postBufferSize = length;
237 }
238
239 if (parseHeaders) {
240 if (startsWithBlankLine(postBuffer, postBufferSize)) {
241 postBuffer++;
242 postBufferSize--;
243 } else {
244 int location = locationAfterFirstBlankLine(postBuffer, postBufferSize);
245 if (location != -1) {
246 // If the blank line is somewhere in the middle of the buffer, everything before is the header
247 headerFields = parseRFC822HeaderFields(postBuffer, location);
248 unsigned dataLength = postBufferSize - location;
249
250 // Sometimes plugins like to set Content-Length themselves when they post,
251 // but WebFoundation does not like that. So we will remove the header
252 // and instead truncate the data to the requested length.
253 String contentLength = headerFields.get("Content-Length");
254
255 if (!contentLength.isNull())
256 dataLength = min(contentLength.toInt(), (int)dataLength);
257 headerFields.remove("Content-Length");
258
259 postBuffer += location;
260 postBufferSize = dataLength;
261
262 }
263 }
264 }
265
266 ASSERT(bodyData.isEmpty());
267 bodyData.append(postBuffer, postBufferSize);
268
269 return NPERR_NO_ERROR;
270 }
271
makeURLString(const char * url)272 static String makeURLString(const char* url)
273 {
274 String urlString(url);
275
276 // Strip return characters.
277 urlString.replace('\r', "");
278 urlString.replace('\n', "");
279
280 return urlString;
281 }
282
NPN_GetURL(NPP npp,const char * url,const char * target)283 static NPError NPN_GetURL(NPP npp, const char* url, const char* target)
284 {
285 if (!url)
286 return NPERR_GENERIC_ERROR;
287
288 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
289 plugin->loadURL("GET", makeURLString(url), target, HTTPHeaderMap(), Vector<uint8_t>(), false, 0);
290
291 return NPERR_GENERIC_ERROR;
292 }
293
NPN_PostURL(NPP npp,const char * url,const char * target,uint32_t len,const char * buf,NPBool file)294 static NPError NPN_PostURL(NPP npp, const char* url, const char* target, uint32_t len, const char* buf, NPBool file)
295 {
296 HTTPHeaderMap headerFields;
297 Vector<uint8_t> postData;
298
299 // NPN_PostURL only allows headers if the post buffer points to a file.
300 bool parseHeaders = file;
301
302 NPError error = parsePostBuffer(file, buf, len, parseHeaders, headerFields, postData);
303 if (error != NPERR_NO_ERROR)
304 return error;
305
306 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
307 plugin->loadURL("POST", makeURLString(url), target, headerFields, postData, false, 0);
308 return NPERR_NO_ERROR;
309 }
310
NPN_RequestRead(NPStream * stream,NPByteRange * rangeList)311 static NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList)
312 {
313 notImplemented();
314 return NPERR_GENERIC_ERROR;
315 }
316
NPN_NewStream(NPP instance,NPMIMEType type,const char * target,NPStream ** stream)317 static NPError NPN_NewStream(NPP instance, NPMIMEType type, const char* target, NPStream** stream)
318 {
319 notImplemented();
320 return NPERR_GENERIC_ERROR;
321 }
322
NPN_Write(NPP instance,NPStream * stream,int32_t len,void * buffer)323 static int32_t NPN_Write(NPP instance, NPStream* stream, int32_t len, void* buffer)
324 {
325 notImplemented();
326 return -1;
327 }
328
NPN_DestroyStream(NPP npp,NPStream * stream,NPReason reason)329 static NPError NPN_DestroyStream(NPP npp, NPStream* stream, NPReason reason)
330 {
331 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
332
333 return plugin->destroyStream(stream, reason);
334 }
335
NPN_Status(NPP npp,const char * message)336 static void NPN_Status(NPP npp, const char* message)
337 {
338 String statusbarText;
339 if (!message)
340 statusbarText = "";
341 else
342 statusbarText = String::fromUTF8WithLatin1Fallback(message, strlen(message));
343
344 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
345 plugin->setStatusbarText(statusbarText);
346 }
347
NPN_UserAgent(NPP npp)348 static const char* NPN_UserAgent(NPP npp)
349 {
350 return NetscapePlugin::userAgent(npp);
351 }
352
NPN_MemAlloc(uint32_t size)353 static void* NPN_MemAlloc(uint32_t size)
354 {
355 return npnMemAlloc(size);
356 }
357
NPN_MemFree(void * ptr)358 static void NPN_MemFree(void* ptr)
359 {
360 npnMemFree(ptr);
361 }
362
NPN_MemFlush(uint32_t size)363 static uint32_t NPN_MemFlush(uint32_t size)
364 {
365 return 0;
366 }
367
NPN_ReloadPlugins(NPBool reloadPages)368 static void NPN_ReloadPlugins(NPBool reloadPages)
369 {
370 notImplemented();
371 }
372
NPN_GetJavaEnv(void)373 static JRIEnv* NPN_GetJavaEnv(void)
374 {
375 notImplemented();
376 return 0;
377 }
378
NPN_GetJavaPeer(NPP instance)379 static jref NPN_GetJavaPeer(NPP instance)
380 {
381 notImplemented();
382 return 0;
383 }
384
NPN_GetURLNotify(NPP npp,const char * url,const char * target,void * notifyData)385 static NPError NPN_GetURLNotify(NPP npp, const char* url, const char* target, void* notifyData)
386 {
387 if (!url)
388 return NPERR_GENERIC_ERROR;
389
390 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
391 plugin->loadURL("GET", makeURLString(url), target, HTTPHeaderMap(), Vector<uint8_t>(), true, notifyData);
392
393 return NPERR_NO_ERROR;
394 }
395
NPN_PostURLNotify(NPP npp,const char * url,const char * target,uint32_t len,const char * buf,NPBool file,void * notifyData)396 static NPError NPN_PostURLNotify(NPP npp, const char* url, const char* target, uint32_t len, const char* buf, NPBool file, void* notifyData)
397 {
398 HTTPHeaderMap headerFields;
399 Vector<uint8_t> postData;
400 NPError error = parsePostBuffer(file, buf, len, true, headerFields, postData);
401 if (error != NPERR_NO_ERROR)
402 return error;
403
404 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
405 plugin->loadURL("POST", makeURLString(url), target, headerFields, postData, true, notifyData);
406 return NPERR_NO_ERROR;
407 }
408
409 #if PLATFORM(MAC)
410 // true if the browser supports hardware compositing of Core Animation plug-ins.
411 static const unsigned WKNVSupportsCompositingCoreAnimationPluginsBool = 74656;
412
413 // The Core Animation render server port.
414 static const unsigned WKNVCALayerRenderServerPort = 71879;
415
416 #endif
417
NPN_GetValue(NPP npp,NPNVariable variable,void * value)418 static NPError NPN_GetValue(NPP npp, NPNVariable variable, void *value)
419 {
420 switch (variable) {
421 case NPNVWindowNPObject: {
422 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
423 PluginDestructionProtector protector(plugin.get());
424
425 NPObject* windowNPObject = plugin->windowScriptNPObject();
426 if (!windowNPObject)
427 return NPERR_GENERIC_ERROR;
428
429 *(NPObject**)value = windowNPObject;
430 break;
431 }
432 case NPNVPluginElementNPObject: {
433 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
434 PluginDestructionProtector protector(plugin.get());
435
436 NPObject* pluginElementNPObject = plugin->pluginElementNPObject();
437 *(NPObject**)value = pluginElementNPObject;
438 break;
439 }
440 case NPNVprivateModeBool: {
441 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
442
443 *(NPBool*)value = plugin->isPrivateBrowsingEnabled();
444 break;
445 }
446 #if PLATFORM(MAC)
447 case NPNVsupportsCoreGraphicsBool:
448 // Always claim to support the Core Graphics drawing model.
449 *(NPBool*)value = true;
450 break;
451
452 case WKNVSupportsCompositingCoreAnimationPluginsBool:
453 case NPNVsupportsCoreAnimationBool: {
454 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
455
456 *(NPBool*)value = plugin->isAcceleratedCompositingEnabled();
457 break;
458 }
459 case NPNVsupportsCocoaBool:
460 // Always claim to support the Cocoa event model.
461 *(NPBool*)value = true;
462 break;
463
464 case WKNVCALayerRenderServerPort: {
465 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
466
467 *(mach_port_t*)value = plugin->compositingRenderServerPort();
468 break;
469 }
470
471 #ifndef NP_NO_QUICKDRAW
472 case NPNVsupportsQuickDrawBool:
473 // We don't support the QuickDraw drawing model.
474 *(NPBool*)value = false;
475 break;
476 #endif
477 #ifndef NP_NO_CARBON
478 case NPNVsupportsCarbonBool:
479 // FIXME: We should support the Carbon event model.
480 *(NPBool*)value = false;
481 break;
482 #endif
483 #elif PLATFORM(WIN)
484 case NPNVnetscapeWindow: {
485 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
486 *reinterpret_cast<HWND*>(value) = plugin->containingWindow();
487 break;
488 }
489 case NPNVSupportsWindowless:
490 *(NPBool*)value = true;
491 break;
492 #elif PLUGIN_ARCHITECTURE(X11)
493 case NPNVxDisplay:
494 #if PLATFORM(QT)
495 *reinterpret_cast<Display**>(value) = QX11Info::display();
496 break;
497 #elif PLATFORM(GTK)
498 *reinterpret_cast<Display**>(value) = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
499 break;
500 #else
501 goto default;
502 #endif
503 case NPNVSupportsXEmbedBool:
504 *static_cast<NPBool*>(value) = true;
505 break;
506 case NPNVSupportsWindowless:
507 *static_cast<NPBool*>(value) = true;
508 break;
509
510 case NPNVToolkit: {
511 const uint32_t expectedGTKToolKitVersion = 2;
512
513 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
514 *reinterpret_cast<uint32_t*>(value) = plugin->quirks().contains(PluginQuirks::RequiresGTKToolKit) ?
515 expectedGTKToolKitVersion : 0;
516 break;
517 }
518
519 // TODO: implement NPNVnetscapeWindow once we want to support windowed plugins.
520 #endif
521 default:
522 notImplemented();
523 return NPERR_GENERIC_ERROR;
524 }
525
526 return NPERR_NO_ERROR;
527 }
528
NPN_SetValue(NPP npp,NPPVariable variable,void * value)529 static NPError NPN_SetValue(NPP npp, NPPVariable variable, void *value)
530 {
531 switch (variable) {
532 #if PLATFORM(MAC)
533 case NPPVpluginDrawingModel: {
534 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
535
536 NPDrawingModel drawingModel = static_cast<NPDrawingModel>(reinterpret_cast<uintptr_t>(value));
537 return plugin->setDrawingModel(drawingModel);
538 }
539
540 case NPPVpluginEventModel: {
541 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
542
543 NPEventModel eventModel = static_cast<NPEventModel>(reinterpret_cast<uintptr_t>(value));
544 return plugin->setEventModel(eventModel);
545 }
546 #endif
547
548 case NPPVpluginWindowBool: {
549 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
550 plugin->setIsWindowed(value);
551 return NPERR_NO_ERROR;
552 }
553
554 case NPPVpluginTransparentBool: {
555 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
556 plugin->setIsTransparent(value);
557 return NPERR_NO_ERROR;
558 }
559
560 default:
561 notImplemented();
562 return NPERR_GENERIC_ERROR;
563 }
564 }
565
NPN_InvalidateRect(NPP npp,NPRect * invalidRect)566 static void NPN_InvalidateRect(NPP npp, NPRect* invalidRect)
567 {
568 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
569 plugin->invalidate(invalidRect);
570 }
571
NPN_InvalidateRegion(NPP npp,NPRegion invalidRegion)572 static void NPN_InvalidateRegion(NPP npp, NPRegion invalidRegion)
573 {
574 // FIXME: We could at least figure out the bounding rectangle of the invalid region.
575 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
576 plugin->invalidate(0);
577 }
578
NPN_ForceRedraw(NPP instance)579 static void NPN_ForceRedraw(NPP instance)
580 {
581 notImplemented();
582 }
583
NPN_GetStringIdentifier(const NPUTF8 * name)584 static NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name)
585 {
586 return static_cast<NPIdentifier>(IdentifierRep::get(name));
587 }
588
NPN_GetStringIdentifiers(const NPUTF8 ** names,int32_t nameCount,NPIdentifier * identifiers)589 static void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers)
590 {
591 ASSERT(names);
592 ASSERT(identifiers);
593
594 if (!names || !identifiers)
595 return;
596
597 for (int32_t i = 0; i < nameCount; ++i)
598 identifiers[i] = NPN_GetStringIdentifier(names[i]);
599 }
600
NPN_GetIntIdentifier(int32_t intid)601 static NPIdentifier NPN_GetIntIdentifier(int32_t intid)
602 {
603 return static_cast<NPIdentifier>(IdentifierRep::get(intid));
604 }
605
NPN_IdentifierIsString(NPIdentifier identifier)606 static bool NPN_IdentifierIsString(NPIdentifier identifier)
607 {
608 return static_cast<IdentifierRep*>(identifier)->isString();
609 }
610
NPN_UTF8FromIdentifier(NPIdentifier identifier)611 static NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier)
612 {
613 const char* string = static_cast<IdentifierRep*>(identifier)->string();
614 if (!string)
615 return 0;
616
617 uint32_t stringLength = strlen(string);
618 char* utf8String = npnMemNewArray<char>(stringLength + 1);
619 memcpy(utf8String, string, stringLength);
620 utf8String[stringLength] = '\0';
621
622 return utf8String;
623 }
624
NPN_IntFromIdentifier(NPIdentifier identifier)625 static int32_t NPN_IntFromIdentifier(NPIdentifier identifier)
626 {
627 return static_cast<IdentifierRep*>(identifier)->number();
628 }
629
NPN_CreateObject(NPP npp,NPClass * npClass)630 static NPObject* NPN_CreateObject(NPP npp, NPClass *npClass)
631 {
632 return createNPObject(npp, npClass);
633 }
634
NPN_RetainObject(NPObject * npObject)635 static NPObject *NPN_RetainObject(NPObject *npObject)
636 {
637 retainNPObject(npObject);
638 return npObject;
639 }
640
NPN_ReleaseObject(NPObject * npObject)641 static void NPN_ReleaseObject(NPObject *npObject)
642 {
643 releaseNPObject(npObject);
644 }
645
NPN_Invoke(NPP,NPObject * npObject,NPIdentifier methodName,const NPVariant * arguments,uint32_t argumentCount,NPVariant * result)646 static bool NPN_Invoke(NPP, NPObject *npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
647 {
648 if (npObject->_class->invoke)
649 return npObject->_class->invoke(npObject, methodName, arguments, argumentCount, result);
650
651 return false;
652 }
653
NPN_InvokeDefault(NPP,NPObject * npObject,const NPVariant * arguments,uint32_t argumentCount,NPVariant * result)654 static bool NPN_InvokeDefault(NPP, NPObject *npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
655 {
656 if (npObject->_class->invokeDefault)
657 return npObject->_class->invokeDefault(npObject, arguments, argumentCount, result);
658
659 return false;
660 }
661
NPN_Evaluate(NPP npp,NPObject * npObject,NPString * script,NPVariant * result)662 static bool NPN_Evaluate(NPP npp, NPObject *npObject, NPString *script, NPVariant* result)
663 {
664 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
665 PluginDestructionProtector protector(plugin.get());
666
667 String scriptString = String::fromUTF8WithLatin1Fallback(script->UTF8Characters, script->UTF8Length);
668
669 return plugin->evaluate(npObject, scriptString, result);
670 }
671
NPN_GetProperty(NPP npp,NPObject * npObject,NPIdentifier propertyName,NPVariant * result)672 static bool NPN_GetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, NPVariant* result)
673 {
674 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
675 PluginDestructionProtector protector(plugin.get());
676
677 if (npObject->_class->getProperty)
678 return npObject->_class->getProperty(npObject, propertyName, result);
679
680 return false;
681 }
682
NPN_SetProperty(NPP npp,NPObject * npObject,NPIdentifier propertyName,const NPVariant * value)683 static bool NPN_SetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, const NPVariant* value)
684 {
685 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
686 PluginDestructionProtector protector(plugin.get());
687
688 if (npObject->_class->setProperty)
689 return npObject->_class->setProperty(npObject, propertyName, value);
690
691 return false;
692 }
693
NPN_RemoveProperty(NPP npp,NPObject * npObject,NPIdentifier propertyName)694 static bool NPN_RemoveProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName)
695 {
696 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
697 PluginDestructionProtector protector(plugin.get());
698
699 if (npObject->_class->removeProperty)
700 return npObject->_class->removeProperty(npObject, propertyName);
701
702 return false;
703 }
704
NPN_HasProperty(NPP npp,NPObject * npObject,NPIdentifier propertyName)705 static bool NPN_HasProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName)
706 {
707 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
708 PluginDestructionProtector protector(plugin.get());
709
710 if (npObject->_class->hasProperty)
711 return npObject->_class->hasProperty(npObject, propertyName);
712
713 return false;
714 }
715
NPN_HasMethod(NPP npp,NPObject * npObject,NPIdentifier methodName)716 static bool NPN_HasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName)
717 {
718 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
719 PluginDestructionProtector protector(plugin.get());
720
721 if (npObject->_class->hasMethod)
722 return npObject->_class->hasMethod(npObject, methodName);
723
724 return false;
725 }
726
NPN_ReleaseVariantValue(NPVariant * variant)727 static void NPN_ReleaseVariantValue(NPVariant* variant)
728 {
729 releaseNPVariantValue(variant);
730 }
731
NPN_SetException(NPObject *,const NPUTF8 * message)732 static void NPN_SetException(NPObject*, const NPUTF8* message)
733 {
734 NetscapePlugin::setException(message);
735 }
736
NPN_PushPopupsEnabledState(NPP npp,NPBool enabled)737 static void NPN_PushPopupsEnabledState(NPP npp, NPBool enabled)
738 {
739 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
740 plugin->pushPopupsEnabledState(enabled);
741 }
742
NPN_PopPopupsEnabledState(NPP npp)743 static void NPN_PopPopupsEnabledState(NPP npp)
744 {
745 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
746 plugin->popPopupsEnabledState();
747 }
748
NPN_Enumerate(NPP npp,NPObject * npObject,NPIdentifier ** identifiers,uint32_t * identifierCount)749 static bool NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifiers, uint32_t* identifierCount)
750 {
751 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
752 PluginDestructionProtector protector(plugin.get());
753
754 if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(npObject->_class) && npObject->_class->enumerate)
755 return npObject->_class->enumerate(npObject, identifiers, identifierCount);
756
757 return false;
758 }
759
NPN_PluginThreadAsyncCall(NPP instance,void (* func)(void *),void * userData)760 static void NPN_PluginThreadAsyncCall(NPP instance, void (*func) (void*), void* userData)
761 {
762 notImplemented();
763 }
764
NPN_Construct(NPP npp,NPObject * npObject,const NPVariant * arguments,uint32_t argumentCount,NPVariant * result)765 static bool NPN_Construct(NPP npp, NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
766 {
767 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
768 PluginDestructionProtector protector(plugin.get());
769
770 if (NP_CLASS_STRUCT_VERSION_HAS_CTOR(npObject->_class) && npObject->_class->construct)
771 return npObject->_class->construct(npObject, arguments, argumentCount, result);
772
773 return false;
774 }
775
copyCString(const CString & string,char ** value,uint32_t * len)776 static NPError copyCString(const CString& string, char** value, uint32_t* len)
777 {
778 ASSERT(!string.isNull());
779 ASSERT(value);
780 ASSERT(len);
781
782 *value = npnMemNewArray<char>(string.length());
783 if (!*value)
784 return NPERR_GENERIC_ERROR;
785
786 memcpy(*value, string.data(), string.length());
787 *len = string.length();
788 return NPERR_NO_ERROR;
789 }
790
NPN_GetValueForURL(NPP npp,NPNURLVariable variable,const char * url,char ** value,uint32_t * len)791 static NPError NPN_GetValueForURL(NPP npp, NPNURLVariable variable, const char* url, char** value, uint32_t* len)
792 {
793 if (!value || !len)
794 return NPERR_GENERIC_ERROR;
795
796 switch (variable) {
797 case NPNURLVCookie: {
798 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
799 PluginDestructionProtector protector(plugin.get());
800
801 String cookies = plugin->cookiesForURL(makeURLString(url));
802 if (cookies.isNull())
803 return NPERR_GENERIC_ERROR;
804
805 return copyCString(cookies.utf8(), value, len);
806 }
807
808 case NPNURLVProxy: {
809 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
810 PluginDestructionProtector protector(plugin.get());
811
812 String proxies = plugin->proxiesForURL(makeURLString(url));
813 if (proxies.isNull())
814 return NPERR_GENERIC_ERROR;
815
816 return copyCString(proxies.utf8(), value, len);
817 }
818 default:
819 notImplemented();
820 return NPERR_GENERIC_ERROR;
821 }
822 }
823
NPN_SetValueForURL(NPP npp,NPNURLVariable variable,const char * url,const char * value,uint32_t len)824 static NPError NPN_SetValueForURL(NPP npp, NPNURLVariable variable, const char* url, const char* value, uint32_t len)
825 {
826 switch (variable) {
827 case NPNURLVCookie: {
828 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
829 PluginDestructionProtector protector(plugin.get());
830
831 plugin->setCookiesForURL(makeURLString(url), String(value, len));
832 return NPERR_NO_ERROR;
833 }
834
835 case NPNURLVProxy:
836 // Can't set the proxy for a URL.
837 return NPERR_GENERIC_ERROR;
838
839 default:
840 notImplemented();
841 return NPERR_GENERIC_ERROR;
842 }
843 }
844
NPN_GetAuthenticationInfo(NPP instance,const char * protocol,const char * host,int32_t port,const char * scheme,const char * realm,char ** username,uint32_t * ulen,char ** password,uint32_t * plen)845 static NPError NPN_GetAuthenticationInfo(NPP instance, const char* protocol, const char* host, int32_t port, const char* scheme,
846 const char* realm, char** username, uint32_t* ulen, char** password, uint32_t* plen)
847 {
848 notImplemented();
849 return NPERR_GENERIC_ERROR;
850 }
851
NPN_ScheduleTimer(NPP instance,uint32_t interval,NPBool repeat,void (* timerFunc)(NPP npp,uint32_t timerID))852 static uint32_t NPN_ScheduleTimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID))
853 {
854 notImplemented();
855 return NPERR_GENERIC_ERROR;
856 }
857
NPN_UnscheduleTimer(NPP instance,uint32_t timerID)858 static void NPN_UnscheduleTimer(NPP instance, uint32_t timerID)
859 {
860 notImplemented();
861 }
862
863 #if PLATFORM(MAC)
NPN_PopUpContextMenu(NPP npp,NPMenu * menu)864 static NPError NPN_PopUpContextMenu(NPP npp, NPMenu* menu)
865 {
866 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
867
868 return plugin->popUpContextMenu(menu);
869 }
870
NPN_ConvertPoint(NPP npp,double sourceX,double sourceY,NPCoordinateSpace sourceSpace,double * destX,double * destY,NPCoordinateSpace destSpace)871 static NPBool NPN_ConvertPoint(NPP npp, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double* destX, double* destY, NPCoordinateSpace destSpace)
872 {
873 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
874
875 double destinationX;
876 double destinationY;
877
878 bool returnValue = plugin->convertPoint(sourceX, sourceY, sourceSpace, destinationX, destinationY, destSpace);
879
880 if (destX)
881 *destX = destinationX;
882 if (destY)
883 *destY = destinationY;
884
885 return returnValue;
886 }
887 #endif
888
initializeBrowserFuncs(NPNetscapeFuncs & netscapeFuncs)889 static void initializeBrowserFuncs(NPNetscapeFuncs &netscapeFuncs)
890 {
891 netscapeFuncs.size = sizeof(NPNetscapeFuncs);
892 netscapeFuncs.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
893
894 netscapeFuncs.geturl = NPN_GetURL;
895 netscapeFuncs.posturl = NPN_PostURL;
896 netscapeFuncs.requestread = NPN_RequestRead;
897 netscapeFuncs.newstream = NPN_NewStream;
898 netscapeFuncs.write = NPN_Write;
899 netscapeFuncs.destroystream = NPN_DestroyStream;
900 netscapeFuncs.status = NPN_Status;
901 netscapeFuncs.uagent = NPN_UserAgent;
902 netscapeFuncs.memalloc = NPN_MemAlloc;
903 netscapeFuncs.memfree = NPN_MemFree;
904 netscapeFuncs.memflush = NPN_MemFlush;
905 netscapeFuncs.reloadplugins = NPN_ReloadPlugins;
906 netscapeFuncs.getJavaEnv = NPN_GetJavaEnv;
907 netscapeFuncs.getJavaPeer = NPN_GetJavaPeer;
908 netscapeFuncs.geturlnotify = NPN_GetURLNotify;
909 netscapeFuncs.posturlnotify = NPN_PostURLNotify;
910 netscapeFuncs.getvalue = NPN_GetValue;
911 netscapeFuncs.setvalue = NPN_SetValue;
912 netscapeFuncs.invalidaterect = NPN_InvalidateRect;
913 netscapeFuncs.invalidateregion = NPN_InvalidateRegion;
914 netscapeFuncs.forceredraw = NPN_ForceRedraw;
915
916 netscapeFuncs.getstringidentifier = NPN_GetStringIdentifier;
917 netscapeFuncs.getstringidentifiers = NPN_GetStringIdentifiers;
918 netscapeFuncs.getintidentifier = NPN_GetIntIdentifier;
919 netscapeFuncs.identifierisstring = NPN_IdentifierIsString;
920 netscapeFuncs.utf8fromidentifier = NPN_UTF8FromIdentifier;
921 netscapeFuncs.intfromidentifier = NPN_IntFromIdentifier;
922 netscapeFuncs.createobject = NPN_CreateObject;
923 netscapeFuncs.retainobject = NPN_RetainObject;
924 netscapeFuncs.releaseobject = NPN_ReleaseObject;
925 netscapeFuncs.invoke = NPN_Invoke;
926 netscapeFuncs.invokeDefault = NPN_InvokeDefault;
927 netscapeFuncs.evaluate = NPN_Evaluate;
928 netscapeFuncs.getproperty = NPN_GetProperty;
929 netscapeFuncs.setproperty = NPN_SetProperty;
930 netscapeFuncs.removeproperty = NPN_RemoveProperty;
931 netscapeFuncs.hasproperty = NPN_HasProperty;
932 netscapeFuncs.hasmethod = NPN_HasMethod;
933 netscapeFuncs.releasevariantvalue = NPN_ReleaseVariantValue;
934 netscapeFuncs.setexception = NPN_SetException;
935 netscapeFuncs.pushpopupsenabledstate = NPN_PushPopupsEnabledState;
936 netscapeFuncs.poppopupsenabledstate = NPN_PopPopupsEnabledState;
937 netscapeFuncs.enumerate = NPN_Enumerate;
938 netscapeFuncs.pluginthreadasynccall = NPN_PluginThreadAsyncCall;
939 netscapeFuncs.construct = NPN_Construct;
940 netscapeFuncs.getvalueforurl = NPN_GetValueForURL;
941 netscapeFuncs.setvalueforurl = NPN_SetValueForURL;
942 netscapeFuncs.getauthenticationinfo = NPN_GetAuthenticationInfo;
943 netscapeFuncs.scheduletimer = NPN_ScheduleTimer;
944 netscapeFuncs.unscheduletimer = NPN_UnscheduleTimer;
945 #if PLATFORM(MAC)
946 netscapeFuncs.popupcontextmenu = NPN_PopUpContextMenu;
947 netscapeFuncs.convertpoint = NPN_ConvertPoint;
948 #else
949 netscapeFuncs.popupcontextmenu = 0;
950 netscapeFuncs.convertpoint = 0;
951 #endif
952 }
953
netscapeBrowserFuncs()954 NPNetscapeFuncs* netscapeBrowserFuncs()
955 {
956 static NPNetscapeFuncs netscapeFuncs;
957 static bool initialized = false;
958
959 if (!initialized) {
960 initializeBrowserFuncs(netscapeFuncs);
961 initialized = true;
962 }
963
964 return &netscapeFuncs;
965 }
966
967 } // namespace WebKit
968