WebKit2/WebProcess/Plugins/Netscape/NetscapeBrowserFuncs.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     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 "NetscapeBrowserFuncs.h"
       
    27 
       
    28 #include "NPRuntimeUtilities.h"
       
    29 #include "NetscapePlugin.h"
       
    30 #include "NotImplemented.h"
       
    31 #include <WebCore/HTTPHeaderMap.h>
       
    32 #include <WebCore/IdentifierRep.h>
       
    33 #include <WebCore/SharedBuffer.h>
       
    34 #include <utility>
       
    35 
       
    36 using namespace WebCore;
       
    37 using namespace std;
       
    38 
       
    39 namespace WebKit {
       
    40 
       
    41 static bool startsWithBlankLine(const char* bytes, unsigned length)
       
    42 {
       
    43     return length > 0 && bytes[0] == '\n';
       
    44 }
       
    45 
       
    46 static int locationAfterFirstBlankLine(const char* bytes, unsigned length)
       
    47 {
       
    48     for (unsigned i = 0; i < length - 4; i++) {
       
    49         // Support for Acrobat. It sends "\n\n".
       
    50         if (bytes[i] == '\n' && bytes[i + 1] == '\n')
       
    51             return i + 2;
       
    52         
       
    53         // Returns the position after 2 CRLF's or 1 CRLF if it is the first line.
       
    54         if (bytes[i] == '\r' && bytes[i + 1] == '\n') {
       
    55             i += 2;
       
    56             if (i == 2)
       
    57                 return i;
       
    58 
       
    59             if (bytes[i] == '\n') {
       
    60                 // Support for Director. It sends "\r\n\n" (3880387).
       
    61                 return i + 1;
       
    62             }
       
    63 
       
    64             if (bytes[i] == '\r' && bytes[i + 1] == '\n') {
       
    65                 // Support for Flash. It sends "\r\n\r\n" (3758113).
       
    66                 return i + 2;
       
    67             }
       
    68         }
       
    69     }
       
    70 
       
    71     return -1;
       
    72 }
       
    73 
       
    74 static const char* findEndOfLine(const char* bytes, unsigned length)
       
    75 {
       
    76     // According to the HTTP specification EOL is defined as
       
    77     // a CRLF pair. Unfortunately, some servers will use LF
       
    78     // instead. Worse yet, some servers will use a combination
       
    79     // of both (e.g. <header>CRLFLF<body>), so findEOL needs
       
    80     // to be more forgiving. It will now accept CRLF, LF or
       
    81     // CR.
       
    82     //
       
    83     // It returns 0 if EOLF is not found or it will return
       
    84     // a pointer to the first terminating character.
       
    85     for (unsigned i = 0; i < length; i++) {
       
    86         if (bytes[i] == '\n')
       
    87             return bytes + i;
       
    88         if (bytes[i] == '\r') {
       
    89             // Check to see if spanning buffer bounds
       
    90             // (CRLF is across reads). If so, wait for
       
    91             // next read.
       
    92             if (i + 1 == length)
       
    93                 break;
       
    94 
       
    95             return bytes + i;
       
    96         }
       
    97     }
       
    98 
       
    99     return 0;
       
   100 }
       
   101 
       
   102 static String capitalizeRFC822HeaderFieldName(const String& name)
       
   103 {
       
   104     bool capitalizeCharacter = true;
       
   105     String result;
       
   106 
       
   107     for (unsigned i = 0; i < name.length(); i++) {
       
   108         UChar c;
       
   109 
       
   110         if (capitalizeCharacter && name[i] >= 'a' && name[i] <= 'z')
       
   111             c = toASCIIUpper(name[i]);
       
   112         else if (!capitalizeCharacter && name[i] >= 'A' && name[i] <= 'Z')
       
   113             c = toASCIILower(name[i]);
       
   114         else
       
   115             c = name[i];
       
   116 
       
   117         if (name[i] == '-')
       
   118             capitalizeCharacter = true;
       
   119         else
       
   120             capitalizeCharacter = false;
       
   121 
       
   122         result.append(c);
       
   123     }
       
   124 
       
   125     return result;
       
   126 }
       
   127 
       
   128 static HTTPHeaderMap parseRFC822HeaderFields(const char* bytes, unsigned length)
       
   129 {
       
   130     String lastHeaderKey;
       
   131     HTTPHeaderMap headerFields;
       
   132 
       
   133     // Loop over lines until we're past the header, or we can't find any more end-of-lines
       
   134     while (const char* endOfLine = findEndOfLine(bytes, length)) {
       
   135         const char* line = bytes;
       
   136         int lineLength = endOfLine - bytes;
       
   137 
       
   138         // Move bytes to the character after the terminator as returned by findEndOfLine.
       
   139         bytes = endOfLine + 1;
       
   140         if ((*endOfLine == '\r') && (*bytes == '\n'))
       
   141             bytes++; // Safe since findEndOfLine won't return a spanning CRLF.
       
   142 
       
   143         length -= (bytes - line);
       
   144         if (!lineLength) {
       
   145             // Blank line; we're at the end of the header
       
   146             break;
       
   147         }
       
   148 
       
   149         if (*line == ' ' || *line == '\t') {
       
   150             // Continuation of the previous header
       
   151             if (lastHeaderKey.isNull()) {
       
   152                 // malformed header; ignore it and continue
       
   153                 continue;
       
   154             } 
       
   155             
       
   156             // Merge the continuation of the previous header
       
   157             String currentValue = headerFields.get(lastHeaderKey);
       
   158             String newValue(line, lineLength);
       
   159             
       
   160             headerFields.set(lastHeaderKey, currentValue + newValue);
       
   161         } else {
       
   162             // Brand new header
       
   163             const char* colon = line;
       
   164             while (*colon != ':' && colon != endOfLine)
       
   165                 colon++;
       
   166 
       
   167             if (colon == endOfLine) {
       
   168                 // malformed header; ignore it and continue
       
   169                 continue;
       
   170             }
       
   171 
       
   172             lastHeaderKey = capitalizeRFC822HeaderFieldName(String(line, colon - line));
       
   173             String value;
       
   174             
       
   175             for (colon++; colon != endOfLine; colon++) {
       
   176                 if (*colon != ' ' && *colon != '\t')
       
   177                     break;
       
   178             }
       
   179             if (colon == endOfLine)
       
   180                 value = "";
       
   181             else
       
   182                 value = String(colon, endOfLine - colon);
       
   183             
       
   184             String oldValue = headerFields.get(lastHeaderKey);
       
   185             if (!oldValue.isNull()) {
       
   186                 String tmp = oldValue;
       
   187                 tmp += ", ";
       
   188                 tmp += value;
       
   189                 value = tmp;
       
   190             }
       
   191             
       
   192             headerFields.set(lastHeaderKey, value);
       
   193         }
       
   194     }
       
   195 
       
   196     return headerFields;
       
   197 }
       
   198     
       
   199 static NPError parsePostBuffer(bool isFile, const char *buffer, uint32_t length, bool parseHeaders, HTTPHeaderMap& headerFields, Vector<char>& bodyData)
       
   200 {
       
   201     RefPtr<SharedBuffer> fileContents;
       
   202     const char* postBuffer = 0;
       
   203     uint32_t postBufferSize = 0;
       
   204 
       
   205     if (isFile) {
       
   206         fileContents = SharedBuffer::createWithContentsOfFile(String::fromUTF8(buffer));
       
   207         if (!fileContents)
       
   208             return NPERR_FILE_NOT_FOUND;
       
   209 
       
   210         postBuffer = fileContents->data();
       
   211         postBufferSize = fileContents->size();
       
   212 
       
   213         // FIXME: The NPAPI spec states that the file should be deleted here.
       
   214     } else {
       
   215         postBuffer = buffer;
       
   216         postBufferSize = length;
       
   217     }
       
   218 
       
   219     if (parseHeaders) {
       
   220         if (startsWithBlankLine(postBuffer, postBufferSize)) {
       
   221             postBuffer++;
       
   222             postBufferSize--;
       
   223         } else {
       
   224             int location = locationAfterFirstBlankLine(postBuffer, postBufferSize);
       
   225             if (location != -1) {
       
   226                 // If the blank line is somewhere in the middle of the buffer, everything before is the header
       
   227                 headerFields = parseRFC822HeaderFields(postBuffer, location);
       
   228                 unsigned dataLength = postBufferSize - location;
       
   229                 
       
   230                 // Sometimes plugins like to set Content-Length themselves when they post,
       
   231                 // but WebFoundation does not like that. So we will remove the header
       
   232                 // and instead truncate the data to the requested length.
       
   233                 String contentLength = headerFields.get("Content-Length");
       
   234                 
       
   235                 if (!contentLength.isNull())
       
   236                     dataLength = min(contentLength.toInt(), (int)dataLength);
       
   237                 headerFields.remove("Content-Length");
       
   238                 
       
   239                 postBuffer += location;
       
   240                 postBufferSize = dataLength;
       
   241                 
       
   242             }
       
   243         }
       
   244     }
       
   245 
       
   246     ASSERT(bodyData.isEmpty());
       
   247     bodyData.append(postBuffer, postBufferSize);
       
   248 
       
   249     return NPERR_NO_ERROR;
       
   250 }
       
   251 
       
   252 static String makeURLString(const char* url)
       
   253 {
       
   254     String urlString(url);
       
   255     
       
   256     // Strip return characters.
       
   257     urlString.replace('\r', "");
       
   258     urlString.replace('\n', "");
       
   259 
       
   260     return urlString;
       
   261 }
       
   262 
       
   263 static NPError NPN_GetURL(NPP npp, const char* url, const char* target)
       
   264 {
       
   265     if (!url)
       
   266         return NPERR_GENERIC_ERROR;
       
   267     
       
   268     RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
       
   269     plugin->loadURL("GET", makeURLString(url), target, HTTPHeaderMap(), Vector<char>(), false, 0);
       
   270     
       
   271     return NPERR_GENERIC_ERROR;
       
   272 }
       
   273 
       
   274 static NPError NPN_PostURL(NPP npp, const char* url, const char* target, uint32_t len, const char* buf, NPBool file)
       
   275 {
       
   276     HTTPHeaderMap headerFields;
       
   277     Vector<char> postData;
       
   278     
       
   279     // NPN_PostURL only allows headers if the post buffer points to a file.
       
   280     bool parseHeaders = file;
       
   281 
       
   282     NPError error = parsePostBuffer(file, buf, len, parseHeaders, headerFields, postData);
       
   283     if (error != NPERR_NO_ERROR)
       
   284         return error;
       
   285 
       
   286     RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
       
   287     plugin->loadURL("POST", makeURLString(url), target, headerFields, postData, false, 0);
       
   288     return NPERR_NO_ERROR;
       
   289 }
       
   290 
       
   291 static NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList)
       
   292 {
       
   293     notImplemented();
       
   294     return NPERR_GENERIC_ERROR;
       
   295 }
       
   296 
       
   297 static NPError NPN_NewStream(NPP instance, NPMIMEType type, const char* target, NPStream** stream)
       
   298 {
       
   299     notImplemented();
       
   300     return NPERR_GENERIC_ERROR;
       
   301 }
       
   302     
       
   303 static int32_t NPN_Write(NPP instance, NPStream* stream, int32_t len, void* buffer)
       
   304 {
       
   305     notImplemented();    
       
   306     return -1;
       
   307 }
       
   308     
       
   309 static NPError NPN_DestroyStream(NPP npp, NPStream* stream, NPReason reason)
       
   310 {
       
   311     RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
       
   312     
       
   313     return plugin->destroyStream(stream, reason);
       
   314 }
       
   315 
       
   316 static void NPN_Status(NPP instance, const char* message)
       
   317 {
       
   318     notImplemented();
       
   319 }
       
   320     
       
   321 static const char* NPN_UserAgent(NPP npp)
       
   322 {
       
   323     if (!npp)
       
   324         return 0;
       
   325     
       
   326     RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
       
   327     return plugin->userAgent();
       
   328 }
       
   329 
       
   330 static void* NPN_MemAlloc(uint32_t size)
       
   331 {
       
   332     // We could use fastMalloc here, but there might be plug-ins that mix NPN_MemAlloc/NPN_MemFree with malloc and free,
       
   333     // so having them be equivalent seems like a good idea.
       
   334     return malloc(size);
       
   335 }
       
   336 
       
   337 static void NPN_MemFree(void* ptr)
       
   338 {
       
   339     // We could use fastFree here, but there might be plug-ins that mix NPN_MemAlloc/NPN_MemFree with malloc and free,
       
   340     // so having them be equivalent seems like a good idea.
       
   341     free(ptr);
       
   342 }
       
   343 
       
   344 static uint32_t NPN_MemFlush(uint32_t size)
       
   345 {
       
   346     return 0;
       
   347 }
       
   348 
       
   349 static void NPN_ReloadPlugins(NPBool reloadPages)
       
   350 {
       
   351     notImplemented();
       
   352 }
       
   353 
       
   354 static JRIEnv* NPN_GetJavaEnv(void)
       
   355 {
       
   356     notImplemented();
       
   357     return 0;
       
   358 }
       
   359 
       
   360 static jref NPN_GetJavaPeer(NPP instance)
       
   361 {
       
   362     notImplemented();
       
   363     return 0;
       
   364 }
       
   365 
       
   366 static NPError NPN_GetURLNotify(NPP npp, const char* url, const char* target, void* notifyData)
       
   367 {
       
   368     if (!url)
       
   369         return NPERR_GENERIC_ERROR;
       
   370 
       
   371     RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
       
   372     plugin->loadURL("GET", makeURLString(url), target, HTTPHeaderMap(), Vector<char>(), true, notifyData);
       
   373     
       
   374     return NPERR_NO_ERROR;
       
   375 }
       
   376 
       
   377 static NPError NPN_PostURLNotify(NPP npp, const char* url, const char* target, uint32_t len, const char* buf, NPBool file, void* notifyData)
       
   378 {
       
   379     HTTPHeaderMap headerFields;
       
   380     Vector<char> postData;
       
   381     NPError error = parsePostBuffer(file, buf, len, true, headerFields, postData);
       
   382     if (error != NPERR_NO_ERROR)
       
   383         return error;
       
   384 
       
   385     RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
       
   386     plugin->loadURL("POST", makeURLString(url), target, headerFields, postData, true, notifyData);
       
   387     return NPERR_NO_ERROR;
       
   388 }
       
   389 
       
   390 static NPError NPN_GetValue(NPP npp, NPNVariable variable, void *value)
       
   391 {
       
   392     switch (variable) {
       
   393         case NPNVWindowNPObject: {
       
   394             RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
       
   395 
       
   396             NPObject* windowNPObject = plugin->windowScriptNPObject();
       
   397             *(NPObject**)value = windowNPObject;
       
   398             break;
       
   399         }
       
   400         case NPNVPluginElementNPObject: {
       
   401             RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
       
   402 
       
   403             NPObject* pluginElementNPObject = plugin->pluginElementNPObject();
       
   404             *(NPObject**)value = pluginElementNPObject;
       
   405             break;
       
   406         }
       
   407 #if PLATFORM(MAC)
       
   408         case NPNVsupportsCoreGraphicsBool:
       
   409             // Always claim to support the Core Graphics drawing model.
       
   410             *(NPBool *)value = true;
       
   411             break;
       
   412 
       
   413         case NPNVsupportsCocoaBool:
       
   414             // Always claim to support the Cocoa event model.
       
   415             *(NPBool *)value = true;
       
   416             break;
       
   417 #endif
       
   418         default:
       
   419             notImplemented();
       
   420             return NPERR_GENERIC_ERROR;
       
   421     }
       
   422 
       
   423     return NPERR_NO_ERROR;
       
   424 }
       
   425 
       
   426 static NPError NPN_SetValue(NPP npp, NPPVariable variable, void *value)
       
   427 {
       
   428     switch (variable) {
       
   429 #if PLATFORM(MAC)
       
   430         case NPPVpluginDrawingModel: {
       
   431             RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
       
   432             
       
   433             NPDrawingModel drawingModel = static_cast<NPDrawingModel>(reinterpret_cast<uintptr_t>(value));
       
   434             return plugin->setDrawingModel(drawingModel);
       
   435         }
       
   436 
       
   437         case NPPVpluginEventModel: {
       
   438             RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
       
   439             
       
   440             NPEventModel eventModel = static_cast<NPEventModel>(reinterpret_cast<uintptr_t>(value));
       
   441             return plugin->setEventModel(eventModel);
       
   442         }
       
   443 #endif
       
   444 
       
   445         default:
       
   446             notImplemented();
       
   447             return NPERR_GENERIC_ERROR;
       
   448     }
       
   449     
       
   450     return NPERR_NO_ERROR;
       
   451 }
       
   452 
       
   453 static void NPN_InvalidateRect(NPP npp, NPRect* invalidRect)
       
   454 {
       
   455     RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
       
   456     plugin->invalidate(invalidRect);
       
   457 }
       
   458 
       
   459 static void NPN_InvalidateRegion(NPP npp, NPRegion invalidRegion)
       
   460 {
       
   461     // FIXME: We could at least figure out the bounding rectangle of the invalid region.
       
   462     RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
       
   463     plugin->invalidate(0);
       
   464 }
       
   465 
       
   466 static void NPN_ForceRedraw(NPP instance)
       
   467 {
       
   468     notImplemented();
       
   469 }
       
   470 
       
   471 static NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name)
       
   472 {
       
   473     return static_cast<NPIdentifier>(IdentifierRep::get(name));
       
   474 }
       
   475     
       
   476 static void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers)
       
   477 {
       
   478     ASSERT(names);
       
   479     ASSERT(identifiers);
       
   480 
       
   481     if (!names || !identifiers)
       
   482         return;
       
   483 
       
   484     for (int32_t i = 0; i < nameCount; ++i)
       
   485         identifiers[i] = NPN_GetStringIdentifier(names[i]);
       
   486 }
       
   487 
       
   488 static NPIdentifier NPN_GetIntIdentifier(int32_t intid)
       
   489 {
       
   490     return static_cast<NPIdentifier>(IdentifierRep::get(intid));
       
   491 }
       
   492 
       
   493 static bool NPN_IdentifierIsString(NPIdentifier identifier)
       
   494 {
       
   495     return static_cast<IdentifierRep*>(identifier)->isString();
       
   496 }
       
   497 
       
   498 static NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier)
       
   499 {
       
   500     const char* string = static_cast<IdentifierRep*>(identifier)->string();
       
   501     if (!string)
       
   502         return 0;
       
   503 
       
   504     uint32_t stringLength = strlen(string);
       
   505     char* utf8String = static_cast<char*>(NPN_MemAlloc(stringLength + 1));
       
   506     memcpy(utf8String, string, stringLength);
       
   507     utf8String[stringLength] = '\0';
       
   508     
       
   509     return utf8String;
       
   510 }
       
   511 
       
   512 static int32_t NPN_IntFromIdentifier(NPIdentifier identifier)
       
   513 {
       
   514     return static_cast<IdentifierRep*>(identifier)->number();
       
   515 }
       
   516 
       
   517 static NPObject* NPN_CreateObject(NPP npp, NPClass *npClass)
       
   518 {
       
   519     return createNPObject(npp, npClass);
       
   520 }
       
   521 
       
   522 static NPObject *NPN_RetainObject(NPObject *npObject)
       
   523 {
       
   524     retainNPObject(npObject);
       
   525     return npObject;
       
   526 }
       
   527 
       
   528 static void NPN_ReleaseObject(NPObject *npObject)
       
   529 {
       
   530     releaseNPObject(npObject);
       
   531 }
       
   532 
       
   533 static bool NPN_Invoke(NPP npp, NPObject *npobj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result)
       
   534 {
       
   535     notImplemented();
       
   536     return false;
       
   537 }
       
   538 
       
   539 static bool NPN_InvokeDefault(NPP npp, NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)
       
   540 {
       
   541     notImplemented();
       
   542     return false;
       
   543 }
       
   544 
       
   545 static bool NPN_Evaluate(NPP npp, NPObject *npobj, NPString *script, NPVariant *result)
       
   546 {
       
   547     notImplemented();
       
   548     return false;
       
   549 }
       
   550 
       
   551 static bool NPN_GetProperty(NPP npp, NPObject *npObject, NPIdentifier propertyName, NPVariant *result)
       
   552 {
       
   553     if (npObject->_class->hasProperty && npObject->_class->getProperty) {
       
   554         if (npObject->_class->hasProperty(npObject, propertyName))
       
   555             return npObject->_class->getProperty(npObject, propertyName, result);
       
   556     }
       
   557     
       
   558     VOID_TO_NPVARIANT(*result);
       
   559     return false;
       
   560 }
       
   561 
       
   562 static bool NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName, const NPVariant *value)
       
   563 {
       
   564     notImplemented();
       
   565     return false;
       
   566 }
       
   567 
       
   568 static bool NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName)
       
   569 {
       
   570     notImplemented();
       
   571     return false;
       
   572 }
       
   573 
       
   574 static bool NPN_HasProperty(NPP npp, NPObject *npObject, NPIdentifier propertyName)
       
   575 {
       
   576     if (npObject->_class->hasProperty)
       
   577         return npObject->_class->hasProperty(npObject, propertyName);
       
   578 
       
   579     return false;
       
   580 }
       
   581 
       
   582 static bool NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName)
       
   583 {
       
   584     notImplemented();
       
   585     return false;
       
   586 }
       
   587 
       
   588 static void NPN_ReleaseVariantValue(NPVariant *variant)
       
   589 {
       
   590     releaseNPVariantValue(variant);
       
   591 }
       
   592 
       
   593 static void NPN_SetException(NPObject *npobj, const NPUTF8 *message)
       
   594 {
       
   595     notImplemented();
       
   596 }
       
   597 
       
   598 static void NPN_PushPopupsEnabledState(NPP instance, NPBool enabled)
       
   599 {
       
   600     notImplemented();
       
   601 }
       
   602     
       
   603 static void NPN_PopPopupsEnabledState(NPP instance)
       
   604 {
       
   605     notImplemented();
       
   606 }
       
   607     
       
   608 static bool NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier, uint32_t *count)
       
   609 {
       
   610     notImplemented();
       
   611     return false;
       
   612 }
       
   613 
       
   614 static void NPN_PluginThreadAsyncCall(NPP instance, void (*func) (void *), void *userData)
       
   615 {
       
   616     notImplemented();
       
   617 }
       
   618 
       
   619 static bool NPN_Construct(NPP npp, NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result)
       
   620 {
       
   621     notImplemented();
       
   622     return false;
       
   623 }
       
   624 
       
   625 static NPError NPN_GetValueForURL(NPP instance, NPNURLVariable variable, const char *url, char **value, uint32_t *len)
       
   626 {
       
   627     notImplemented();
       
   628     return NPERR_GENERIC_ERROR;
       
   629 }
       
   630 
       
   631 static NPError NPN_SetValueForURL(NPP instance, NPNURLVariable variable, const char *url, const char *value, uint32_t len)
       
   632 {
       
   633     notImplemented();
       
   634     return NPERR_GENERIC_ERROR;
       
   635 }
       
   636 
       
   637 static NPError NPN_GetAuthenticationInfo(NPP instance, const char *protocol, const char *host, int32_t port, const char *scheme, 
       
   638                                          const char *realm, char **username, uint32_t *ulen, char **password, uint32_t *plen)
       
   639 {
       
   640     notImplemented();
       
   641     return NPERR_GENERIC_ERROR;
       
   642 }
       
   643 
       
   644 static uint32_t NPN_ScheduleTimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID))
       
   645 {
       
   646     notImplemented();
       
   647     return NPERR_GENERIC_ERROR;
       
   648 }
       
   649 
       
   650 static void NPN_UnscheduleTimer(NPP instance, uint32_t timerID)
       
   651 {
       
   652     notImplemented();
       
   653 }
       
   654 
       
   655 static NPError NPN_PopUpContextMenu(NPP instance, NPMenu* menu)
       
   656 {
       
   657     notImplemented();
       
   658     return NPERR_GENERIC_ERROR;
       
   659 }
       
   660 
       
   661 static NPBool NPN_ConvertPoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace)
       
   662 {
       
   663     notImplemented();
       
   664     return false;
       
   665 }
       
   666 
       
   667 static void initializeBrowserFuncs(NPNetscapeFuncs &netscapeFuncs)
       
   668 {
       
   669     netscapeFuncs.size = sizeof(NPNetscapeFuncs);
       
   670     netscapeFuncs.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
       
   671     
       
   672     netscapeFuncs.geturl = NPN_GetURL;
       
   673     netscapeFuncs.posturl = NPN_PostURL;
       
   674     netscapeFuncs.requestread = NPN_RequestRead;
       
   675     netscapeFuncs.newstream = NPN_NewStream;
       
   676     netscapeFuncs.write = NPN_Write;
       
   677     netscapeFuncs.destroystream = NPN_DestroyStream;
       
   678     netscapeFuncs.status = NPN_Status;
       
   679     netscapeFuncs.uagent = NPN_UserAgent;
       
   680     netscapeFuncs.memalloc = NPN_MemAlloc;
       
   681     netscapeFuncs.memfree = NPN_MemFree;
       
   682     netscapeFuncs.memflush = NPN_MemFlush;
       
   683     netscapeFuncs.reloadplugins = NPN_ReloadPlugins;
       
   684     netscapeFuncs.getJavaEnv = NPN_GetJavaEnv;
       
   685     netscapeFuncs.getJavaPeer = NPN_GetJavaPeer;
       
   686     netscapeFuncs.geturlnotify = NPN_GetURLNotify;
       
   687     netscapeFuncs.posturlnotify = NPN_PostURLNotify;
       
   688     netscapeFuncs.getvalue = NPN_GetValue;
       
   689     netscapeFuncs.setvalue = NPN_SetValue;
       
   690     netscapeFuncs.invalidaterect = NPN_InvalidateRect;
       
   691     netscapeFuncs.invalidateregion = NPN_InvalidateRegion;
       
   692     netscapeFuncs.forceredraw = NPN_ForceRedraw;
       
   693     
       
   694     netscapeFuncs.getstringidentifier = NPN_GetStringIdentifier;
       
   695     netscapeFuncs.getstringidentifiers = NPN_GetStringIdentifiers;
       
   696     netscapeFuncs.getintidentifier = NPN_GetIntIdentifier;
       
   697     netscapeFuncs.identifierisstring = NPN_IdentifierIsString;
       
   698     netscapeFuncs.utf8fromidentifier = NPN_UTF8FromIdentifier;
       
   699     netscapeFuncs.intfromidentifier = NPN_IntFromIdentifier;
       
   700     netscapeFuncs.createobject = NPN_CreateObject;
       
   701     netscapeFuncs.retainobject = NPN_RetainObject;
       
   702     netscapeFuncs.releaseobject = NPN_ReleaseObject;
       
   703     netscapeFuncs.invoke = NPN_Invoke;
       
   704     netscapeFuncs.invokeDefault = NPN_InvokeDefault;
       
   705     netscapeFuncs.evaluate = NPN_Evaluate;
       
   706     netscapeFuncs.getproperty = NPN_GetProperty;
       
   707     netscapeFuncs.setproperty = NPN_SetProperty;
       
   708     netscapeFuncs.removeproperty = NPN_RemoveProperty;
       
   709     netscapeFuncs.hasproperty = NPN_HasProperty;
       
   710     netscapeFuncs.hasmethod = NPN_HasMethod;
       
   711     netscapeFuncs.releasevariantvalue = NPN_ReleaseVariantValue;
       
   712     netscapeFuncs.setexception = NPN_SetException;
       
   713     netscapeFuncs.pushpopupsenabledstate = NPN_PushPopupsEnabledState;
       
   714     netscapeFuncs.poppopupsenabledstate = NPN_PopPopupsEnabledState;
       
   715     netscapeFuncs.enumerate = NPN_Enumerate;
       
   716     netscapeFuncs.pluginthreadasynccall = NPN_PluginThreadAsyncCall;
       
   717     netscapeFuncs.construct = NPN_Construct;
       
   718     netscapeFuncs.getvalueforurl = NPN_GetValueForURL;
       
   719     netscapeFuncs.setvalueforurl = NPN_SetValueForURL;
       
   720     netscapeFuncs.getauthenticationinfo = NPN_GetAuthenticationInfo;
       
   721     netscapeFuncs.scheduletimer = NPN_ScheduleTimer;
       
   722     netscapeFuncs.unscheduletimer = NPN_UnscheduleTimer;
       
   723     netscapeFuncs.popupcontextmenu = NPN_PopUpContextMenu;
       
   724     netscapeFuncs.convertpoint = NPN_ConvertPoint;
       
   725 }
       
   726     
       
   727 NPNetscapeFuncs* netscapeBrowserFuncs()
       
   728 {
       
   729     static NPNetscapeFuncs netscapeFuncs;
       
   730     static bool initialized = false;
       
   731     
       
   732     if (!initialized) {
       
   733         initializeBrowserFuncs(netscapeFuncs);
       
   734         initialized = true;
       
   735     }
       
   736 
       
   737     return &netscapeFuncs;
       
   738 }
       
   739 
       
   740 } // namespace WebKit