Changeset 63701 in webkit


Ignore:
Timestamp:
Jul 19, 2010 5:07:25 PM (14 years ago)
Author:
andersca@apple.com
Message:

Implement NPN_PostURLNotify
https://bugs.webkit.org/show_bug.cgi?id=42602

Reviewed by Sam Weinig.

WebCore:

Export symbols needed by WebKit2.

  • WebCore.exp.in:

WebKit2:

  • WebProcess/Plugins/Netscape/NetscapeBrowserFuncs.cpp:

(WebKit::parsePostBuffer):
Read the buffer from a file if necessary and parse it.

(WebKit::NPN_GetURLNotify):
Add extra arguments.

(WebKit::NPN_PostURLNotify):
Parse the post buffer, then call NetscapePlugin::loadURL.

  • WebProcess/Plugins/Netscape/NetscapePlugin.cpp:

(WebKit::NetscapePlugin::loadURL):
Pass the method, the header fields and form data along.

(WebKit::NetscapePlugin::allowPopups):
Just return false for now.

(WebKit::NetscapePlugin::initialize):
Pass extra arguments to loadURL.

  • WebProcess/Plugins/Netscape/NetscapePlugin.h:
  • WebProcess/Plugins/PluginController.h:

Add method, header fields and form data.

  • WebProcess/Plugins/PluginView.cpp:

(WebKit::PluginView::loadURL):
Set the method, add the header fields and set the body.

Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r63699 r63701  
     12010-07-19  Anders Carlsson  <andersca@apple.com>
     2
     3        Reviewed by Sam Weinig.
     4
     5        Implement NPN_PostURLNotify
     6        https://bugs.webkit.org/show_bug.cgi?id=42602
     7
     8        Export symbols needed by WebKit2.
     9
     10        * WebCore.exp.in:
     11
    1122010-07-19  Tony Gentilcore  <tonyg@chromium.org>
    213
  • trunk/WebCore/WebCore.exp.in

    r63638 r63701  
    264264__ZN7WebCore12SharedBuffer10wrapNSDataEP6NSData
    265265__ZN7WebCore12SharedBuffer12createNSDataEv
     266__ZN7WebCore12SharedBuffer24createWithContentsOfFileERKNS_6StringE
    266267__ZN7WebCore12SharedBufferD1Ev
    267268__ZN7WebCore12TextEncodingC1ERKNS_6StringE
     
    410411__ZN7WebCore19CSSStyleDeclaration11setPropertyERKNS_6StringES3_Ri
    411412__ZN7WebCore19InspectorController34inspectorStartsAttachedSettingNameEv
     413__ZN7WebCore19ResourceRequestBase11setHTTPBodyEN3WTF10PassRefPtrINS_8FormDataEEE
    412414__ZN7WebCore19ResourceRequestBase13setHTTPMethodERKNS_6StringE
     415__ZN7WebCore19ResourceRequestBase19addHTTPHeaderFieldsERKNS_13HTTPHeaderMapE
    413416__ZN7WebCore19ResourceRequestBase6setURLERKNS_4KURLE
    414417__ZN7WebCore19SelectionController10setFocusedEb
     
    629632__ZN7WebCore8Document36updateLayoutIgnorePendingStylesheetsEv
    630633__ZN7WebCore8Document4headEv
     634__ZN7WebCore8FormData6createEPKvm
    631635__ZN7WebCore8FormDataD1Ev
    632636__ZN7WebCore8IntPointC1ERK8_NSPoint
     
    838842__ZNK7WebCore13ContainerNode14childNodeCountEv
    839843__ZNK7WebCore13ContainerNode9childNodeEj
     844__ZNK7WebCore13HTTPHeaderMap3getEPKc
    840845__ZNK7WebCore13HitTestResult10isLiveLinkEv
    841846__ZNK7WebCore13HitTestResult10isSelectedEv
  • trunk/WebKit2/ChangeLog

    r63682 r63701  
     12010-07-19  Anders Carlsson  <andersca@apple.com>
     2
     3        Reviewed by Sam Weinig.
     4
     5        Implement NPN_PostURLNotify
     6        https://bugs.webkit.org/show_bug.cgi?id=42602
     7
     8        * WebProcess/Plugins/Netscape/NetscapeBrowserFuncs.cpp:
     9        (WebKit::parsePostBuffer):
     10        Read the buffer from a file if necessary and parse it.
     11
     12        (WebKit::NPN_GetURLNotify):
     13        Add extra arguments.
     14
     15        (WebKit::NPN_PostURLNotify):
     16        Parse the post buffer, then call NetscapePlugin::loadURL.
     17
     18        * WebProcess/Plugins/Netscape/NetscapePlugin.cpp:
     19        (WebKit::NetscapePlugin::loadURL):
     20        Pass the method, the header fields and form data along.
     21
     22        (WebKit::NetscapePlugin::allowPopups):
     23        Just return false for now.
     24
     25        (WebKit::NetscapePlugin::initialize):
     26        Pass extra arguments to loadURL.
     27
     28        * WebProcess/Plugins/Netscape/NetscapePlugin.h:
     29        * WebProcess/Plugins/PluginController.h:
     30        Add method, header fields and form data.
     31
     32        * WebProcess/Plugins/PluginView.cpp:
     33        (WebKit::PluginView::loadURL):
     34        Set the method, add the header fields and set the body.
     35
    1362010-07-19  Sam Weinig  <sam@webkit.org>
    237
  • trunk/WebKit2/WebProcess/Plugins/Netscape/NetscapeBrowserFuncs.cpp

    r63636 r63701  
    2929#include "NetscapePlugin.h"
    3030#include "NotImplemented.h"
     31#include <WebCore/HTTPHeaderMap.h>
    3132#include <WebCore/IdentifierRep.h>
     33#include <WebCore/SharedBuffer.h>
     34#include <utility>
    3235
    3336using namespace WebCore;
     37using namespace std;
    3438
    3539namespace WebKit {
    36    
     40
     41static bool startsWithBlankLine(const char* bytes, unsigned length)
     42{
     43    return length > 0 && bytes[0] == '\n';
     44}
     45
     46static 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
     74static 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
     102static 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
     128static 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   
     199static 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    } else {
     213        postBuffer = buffer;
     214        postBufferSize = length;
     215    }
     216
     217    if (parseHeaders) {
     218        if (startsWithBlankLine(postBuffer, postBufferSize)) {
     219            postBuffer++;
     220            postBufferSize--;
     221        } else {
     222            int location = locationAfterFirstBlankLine(postBuffer, postBufferSize);
     223            if (location != -1) {
     224                // If the blank line is somewhere in the middle of the buffer, everything before is the header
     225                headerFields = parseRFC822HeaderFields(postBuffer, location);
     226                unsigned dataLength = postBufferSize - location;
     227               
     228                // Sometimes plugins like to set Content-Length themselves when they post,
     229                // but WebFoundation does not like that. So we will remove the header
     230                // and instead truncate the data to the requested length.
     231                String contentLength = headerFields.get("Content-Length");
     232               
     233                if (!contentLength.isNull())
     234                    dataLength = min(contentLength.toInt(), (int)dataLength);
     235                headerFields.remove("Content-Length");
     236               
     237                postBuffer += location;
     238                postBufferSize = dataLength;
     239               
     240            }
     241        }
     242    }
     243
     244    ASSERT(bodyData.isEmpty());
     245    bodyData.append(postBuffer, postBufferSize);
     246
     247    return NPERR_NO_ERROR;
     248}
     249
    37250static NPError NPN_GetURL(NPP instance, const char* url, const char* target)
    38251{
     
    139352
    140353    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
    141     plugin->loadURL(makeURLString(url), target, true, notifyData);
     354    plugin->loadURL("GET", makeURLString(url), target, HTTPHeaderMap(), Vector<char>(), true, notifyData);
    142355   
    143356    return NPERR_NO_ERROR;
    144357}
    145358
    146 static NPError NPN_PostURLNotify(NPP instance, const char* url, const char* target, uint32_t len, const char* buf, NPBool file, void* notifyData)
    147 {
     359static NPError NPN_PostURLNotify(NPP npp, const char* url, const char* target, uint32_t len, const char* buf, NPBool file, void* notifyData)
     360{
     361    HTTPHeaderMap headerFields;
     362    Vector<char> postData;
     363    NPError error = parsePostBuffer(file, buf, len, true, headerFields, postData);
     364    if (error != NPERR_NO_ERROR)
     365        return error;
     366
     367    RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
     368    plugin->loadURL("POST", makeURLString(url), target, headerFields, postData, true, notifyData);
     369    return NPERR_NO_ERROR;
     370   
    148371    notImplemented();
    149372    return NPERR_GENERIC_ERROR;
  • trunk/WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.cpp

    r63629 r63701  
    2929#include "PluginController.h"
    3030#include <WebCore/GraphicsContext.h>
     31#include <WebCore/HTTPHeaderMap.h>
    3132#include <WebCore/IntRect.h>
    3233#include <WebCore/KURL.h>
     
    102103}
    103104
    104 void NetscapePlugin::loadURL(const String& urlString, const String& target, bool sendNotification, void* notificationData)
     105void NetscapePlugin::loadURL(const String& method, const String& urlString, const String& target, const HTTPHeaderMap& headerFields, const Vector<char>& httpBody,
     106                             bool sendNotification, void* notificationData)
    105107{
    106108    uint64_t requestID = ++m_nextRequestID;
    107 
    108     // FIXME: Handle popups.
    109     bool allowPopups = false;
    110     m_pluginController->loadURL(requestID, urlString, target, allowPopups);
    111    
     109   
     110    m_pluginController->loadURL(requestID, method, urlString, target, headerFields, httpBody, allowPopups());
     111
    112112    if (target.isNull()) {
    113113        // The browser is going to send the data in a stream, create a plug-in stream.
     
    250250}
    251251
     252bool NetscapePlugin::allowPopups() const
     253{
     254    // FIXME: Handle popups.
     255    return false;
     256}
     257
    252258bool NetscapePlugin::initialize(PluginController* pluginController, const Parameters& parameters)
    253259{
     
    299305    // Load the src URL if needed.
    300306    if (!parameters.url.isEmpty() && shouldLoadSrcURL())
    301         loadURL(parameters.url.string(), String(), false, 0);
     307        loadURL("GET", parameters.url.string(), String(), HTTPHeaderMap(), Vector<char>(), false, 0);
    302308   
    303309    return true;
  • trunk/WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.h

    r63629 r63701  
    3232#include <WebCore/StringHash.h>
    3333
     34namespace WebCore {
     35    class HTTPHeaderMap;
     36}
     37
    3438namespace WebKit {
    3539
     
    5357    void invalidate(const NPRect*);
    5458    const char* userAgent();
    55     void loadURL(const WebCore::String& urlString, const WebCore::String& target, bool sendNotification, void* notificationData);
     59    void loadURL(const WebCore::String& method, const WebCore::String& urlString, const WebCore::String& target, const WebCore::HTTPHeaderMap& headerFields,
     60                 const Vector<char>& httpBody, bool sendNotification, void* notificationData);
    5661    NPError destroyStream(NPStream*, NPReason);
    5762
     
    8085    bool shouldLoadSrcURL();
    8186    NetscapePluginStream* streamFromID(uint64_t streamID);
     87    void stopAllStreams();
     88    bool allowPopups() const;
    8289
    8390    bool platformPostInitialize();
    8491    void platformPaint(WebCore::GraphicsContext*, const WebCore::IntRect& dirtyRect);
    85 
    86     void stopAllStreams();
    8792
    8893    // Plugin
  • trunk/WebKit2/WebProcess/Plugins/PluginController.h

    r63629 r63701  
    3030
    3131namespace WebCore {
     32    class HTTPHeaderMap;
    3233    class IntRect;
    3334    class KURL;
     
    5253    //
    5354    // If the URL is a JavaScript URL, the JavaScript code will be evaluated and the result sent back using Plugin::didEvaluateJavaScript.
    54     virtual void loadURL(uint64_t requestID, const WebCore::String& urlString, const WebCore::String& target, bool allowPopups) = 0;
     55    virtual void loadURL(uint64_t requestID, const WebCore::String& method, const WebCore::String& urlString, const WebCore::String& target,
     56                         const WebCore::HTTPHeaderMap& headerFields, const Vector<char>& httpBody, bool allowPopups) = 0;
    5557
    5658    /// Cancels the load of a stream that was requested by loadURL.
  • trunk/WebKit2/WebProcess/Plugins/PluginView.cpp

    r63631 r63701  
    521521}
    522522
    523 void PluginView::loadURL(uint64_t requestID, const String& urlString, const String& target, bool allowPopups)
     523void PluginView::loadURL(uint64_t requestID, const String& method, const String& urlString, const String& target,
     524                         const HTTPHeaderMap& headerFields, const Vector<char>& httpBody, bool allowPopups)
    524525{
    525526    FrameLoadRequest frameLoadRequest;
    526527    frameLoadRequest.setFrameName(target);
    527     frameLoadRequest.resourceRequest().setHTTPMethod("GET");
     528    frameLoadRequest.resourceRequest().setHTTPMethod(method);
    528529    frameLoadRequest.resourceRequest().setURL(m_pluginElement->document()->completeURL(urlString));
    529    
     530    frameLoadRequest.resourceRequest().addHTTPHeaderFields(headerFields);
     531    frameLoadRequest.resourceRequest().setHTTPBody(FormData::create(httpBody.data(), httpBody.size()));
     532
    530533    m_pendingURLRequests.append(URLRequest::create(requestID, frameLoadRequest, allowPopups));
    531534    m_pendingURLRequestsTimer.startOneShot(0);
  • trunk/WebKit2/WebProcess/Plugins/PluginView.h

    r63631 r63701  
    9393    virtual void invalidate(const WebCore::IntRect&);
    9494    virtual WebCore::String userAgent(const WebCore::KURL&);
    95     virtual void loadURL(uint64_t requestID, const WebCore::String& urlString, const WebCore::String& target, bool allowPopups);
     95    virtual void loadURL(uint64_t requestID, const WebCore::String& method, const WebCore::String& urlString, const WebCore::String& target,
     96                         const WebCore::HTTPHeaderMap& headerFields, const Vector<char>& httpBody, bool allowPopups);
    9697    virtual void cancelStreamLoad(uint64_t streamID);
    9798    virtual NPObject* windowScriptNPObject();
Note: See TracChangeset for help on using the changeset viewer.