• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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