~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WebKit/mac/Plugins/Hosted/HostedNetscapePluginStream.mm

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2008 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. ``AS IS'' AND ANY
 
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 
24
 */
 
25
 
 
26
#if USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
 
27
 
 
28
#import "HostedNetscapePluginStream.h"
 
29
 
 
30
#import "NetscapePluginHostProxy.h"
 
31
#import "NetscapePluginInstanceProxy.h"
 
32
#import "WebFrameInternal.h"
 
33
#import "WebHostedNetscapePluginView.h"
 
34
#import "WebKitErrorsPrivate.h"
 
35
#import "WebKitPluginHost.h"
 
36
#import "WebKitSystemInterface.h"
 
37
#import "WebNSURLExtras.h"
 
38
#import "WebNSURLRequestExtras.h"
 
39
#import <WebCore/DocumentLoader.h>
 
40
#import <WebCore/Frame.h>
 
41
#import <WebCore/FrameLoader.h>
 
42
#import <WebCore/ResourceLoadScheduler.h>
 
43
#import <WebCore/SecurityOrigin.h>
 
44
#import <WebCore/SecurityPolicy.h>
 
45
#import <WebCore/WebCoreURLResponse.h>
 
46
#import <wtf/RefCountedLeakCounter.h>
 
47
 
 
48
using namespace WebCore;
 
49
 
 
50
namespace WebKit {
 
51
 
 
52
DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, hostedNetscapePluginStreamCounter, ("HostedNetscapePluginStream"));
 
53
 
 
54
HostedNetscapePluginStream::HostedNetscapePluginStream(NetscapePluginInstanceProxy* instance, uint32_t streamID, NSURLRequest *request)
 
55
    : m_instance(instance)
 
56
    , m_streamID(streamID)
 
57
    , m_request(AdoptNS, [request mutableCopy])
 
58
    , m_requestURL([request URL])
 
59
    , m_frameLoader(0)
 
60
{
 
61
    String referrer = SecurityPolicy::generateReferrerHeader(core([instance->pluginView() webFrame])->document()->referrerPolicy(), [request URL], core([instance->pluginView() webFrame])->loader()->outgoingReferrer());
 
62
    if (referrer.isEmpty())
 
63
        [m_request.get() _web_setHTTPReferrer:nil];
 
64
    else
 
65
        [m_request.get() _web_setHTTPReferrer:referrer];
 
66
 
 
67
#ifndef NDEBUG
 
68
    hostedNetscapePluginStreamCounter.increment();
 
69
#endif
 
70
}
 
71
 
 
72
HostedNetscapePluginStream::HostedNetscapePluginStream(NetscapePluginInstanceProxy* instance, WebCore::FrameLoader* frameLoader)
 
73
    : m_instance(instance)
 
74
    , m_streamID(1)
 
75
    , m_frameLoader(frameLoader)
 
76
{
 
77
#ifndef NDEBUG
 
78
    hostedNetscapePluginStreamCounter.increment();
 
79
#endif
 
80
}
 
81
 
 
82
HostedNetscapePluginStream::~HostedNetscapePluginStream()
 
83
{
 
84
#ifndef NDEBUG
 
85
    hostedNetscapePluginStreamCounter.decrement();
 
86
#endif
 
87
}
 
88
 
 
89
void HostedNetscapePluginStream::startStreamWithResponse(NSURLResponse *response)
 
90
{
 
91
    didReceiveResponse(0, response);
 
92
}
 
93
    
 
94
void HostedNetscapePluginStream::startStream(NSURL *responseURL, long long expectedContentLength, NSDate *lastModifiedDate, NSString *mimeType, NSData *headers)
 
95
{
 
96
    m_responseURL = responseURL;
 
97
    m_mimeType = mimeType;
 
98
 
 
99
    char* mimeTypeUTF8 = const_cast<char*>([mimeType UTF8String]);
 
100
    int mimeTypeUTF8Length = mimeTypeUTF8 ? strlen (mimeTypeUTF8) + 1 : 0;
 
101
    
 
102
    const char *url = [responseURL _web_URLCString];
 
103
    int urlLength = url ? strlen(url) + 1 : 0;
 
104
    
 
105
    _WKPHStartStream(m_instance->hostProxy()->port(),
 
106
                     m_instance->pluginID(),
 
107
                     m_streamID,
 
108
                     const_cast<char*>(url), urlLength,
 
109
                     expectedContentLength,
 
110
                     [lastModifiedDate timeIntervalSince1970],
 
111
                     mimeTypeUTF8, mimeTypeUTF8Length,
 
112
                     const_cast<char*>(reinterpret_cast<const char*>([headers bytes])), [headers length]);
 
113
}
 
114
                     
 
115
void HostedNetscapePluginStream::didReceiveData(WebCore::NetscapePlugInStreamLoader*, const char* bytes, int length)
 
116
{
 
117
    _WKPHStreamDidReceiveData(m_instance->hostProxy()->port(),
 
118
                              m_instance->pluginID(),
 
119
                              m_streamID,
 
120
                              const_cast<char*>(bytes), length);
 
121
}
 
122
    
 
123
void HostedNetscapePluginStream::didFinishLoading(WebCore::NetscapePlugInStreamLoader*)
 
124
{
 
125
    _WKPHStreamDidFinishLoading(m_instance->hostProxy()->port(),
 
126
                                m_instance->pluginID(),
 
127
                                m_streamID);
 
128
    m_instance->disconnectStream(this);
 
129
}
 
130
    
 
131
void HostedNetscapePluginStream::didReceiveResponse(NetscapePlugInStreamLoader*, const ResourceResponse& response)
 
132
{
 
133
    NSURLResponse *r = response.nsURLResponse();
 
134
    
 
135
    NSMutableData *theHeaders = nil;
 
136
    long long expectedContentLength = [r expectedContentLength];
 
137
    
 
138
    if ([r isKindOfClass:[NSHTTPURLResponse class]]) {
 
139
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)r;
 
140
        theHeaders = [NSMutableData dataWithCapacity:1024];
 
141
        
 
142
        // FIXME: it would be nice to be able to get the raw HTTP header block.
 
143
        // This includes the HTTP version, the real status text,
 
144
        // all headers in their original order and including duplicates,
 
145
        // and all original bytes verbatim, rather than sent through Unicode translation.
 
146
        // Unfortunately NSHTTPURLResponse doesn't provide access at that low a level.
 
147
        
 
148
        [theHeaders appendBytes:"HTTP " length:5];
 
149
        char statusStr[10];
 
150
        long statusCode = [httpResponse statusCode];
 
151
        snprintf(statusStr, sizeof(statusStr), "%ld", statusCode);
 
152
        [theHeaders appendBytes:statusStr length:strlen(statusStr)];
 
153
        [theHeaders appendBytes:" OK\n" length:4];
 
154
        
 
155
        // HACK: pass the headers through as UTF-8.
 
156
        // This is not the intended behavior; we're supposed to pass original bytes verbatim.
 
157
        // But we don't have the original bytes, we have NSStrings built by the URL loading system.
 
158
        // It hopefully shouldn't matter, since RFC2616/RFC822 require ASCII-only headers,
 
159
        // but surely someone out there is using non-ASCII characters, and hopefully UTF-8 is adequate here.
 
160
        // It seems better than NSASCIIStringEncoding, which will lose information if non-ASCII is used.
 
161
        
 
162
        NSDictionary *headerDict = [httpResponse allHeaderFields];
 
163
        NSArray *keys = [[headerDict allKeys] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
 
164
        NSEnumerator *i = [keys objectEnumerator];
 
165
        NSString *k;
 
166
        while ((k = [i nextObject]) != nil) {
 
167
            NSString *v = [headerDict objectForKey:k];
 
168
            [theHeaders appendData:[k dataUsingEncoding:NSUTF8StringEncoding]];
 
169
            [theHeaders appendBytes:": " length:2];
 
170
            [theHeaders appendData:[v dataUsingEncoding:NSUTF8StringEncoding]];
 
171
            [theHeaders appendBytes:"\n" length:1];
 
172
        }
 
173
        
 
174
        // If the content is encoded (most likely compressed), then don't send its length to the plugin,
 
175
        // which is only interested in the decoded length, not yet known at the moment.
 
176
        // <rdar://problem/4470599> tracks a request for -[NSURLResponse expectedContentLength] to incorporate this logic.
 
177
        NSString *contentEncoding = (NSString *)[[(NSHTTPURLResponse *)r allHeaderFields] objectForKey:@"Content-Encoding"];
 
178
        if (contentEncoding && ![contentEncoding isEqualToString:@"identity"])
 
179
            expectedContentLength = -1;
 
180
 
 
181
        [theHeaders appendBytes:"\0" length:1];
 
182
    }
 
183
    
 
184
    startStream([r URL], expectedContentLength, WKGetNSURLResponseLastModifiedDate(r), [r MIMEType], theHeaders);
 
185
}
 
186
 
 
187
NPReason HostedNetscapePluginStream::reasonForError(NSError *error)
 
188
{
 
189
    if (!error)
 
190
        return NPRES_DONE;
 
191
 
 
192
    if ([[error domain] isEqualToString:NSURLErrorDomain] && [error code] == NSURLErrorCancelled)
 
193
        return NPRES_USER_BREAK;
 
194
 
 
195
    return NPRES_NETWORK_ERR;
 
196
}
 
197
 
 
198
void HostedNetscapePluginStream::didFail(WebCore::NetscapePlugInStreamLoader*, const WebCore::ResourceError& error)
 
199
{
 
200
    if (NetscapePluginHostProxy* hostProxy = m_instance->hostProxy())
 
201
        _WKPHStreamDidFail(hostProxy->port(), m_instance->pluginID(), m_streamID, reasonForError(error));
 
202
    m_instance->disconnectStream(this);
 
203
}
 
204
 
 
205
bool HostedNetscapePluginStream::wantsAllStreams() const
 
206
{
 
207
    // FIXME: Implement.
 
208
    return false;
 
209
}
 
210
 
 
211
void HostedNetscapePluginStream::start()
 
212
{
 
213
    ASSERT(m_request);
 
214
    ASSERT(!m_frameLoader);
 
215
    ASSERT(!m_loader);
 
216
    
 
217
    m_loader = resourceLoadScheduler()->schedulePluginStreamLoad(core([m_instance->pluginView() webFrame]), this, m_request.get());
 
218
}
 
219
 
 
220
void HostedNetscapePluginStream::stop()
 
221
{
 
222
    ASSERT(!m_frameLoader);
 
223
    
 
224
    if (!m_loader->isDone())
 
225
        m_loader->cancel(m_loader->cancelledError());
 
226
}
 
227
    
 
228
void HostedNetscapePluginStream::cancelLoad(NPReason reason)
 
229
{
 
230
    cancelLoad(errorForReason(reason));
 
231
}
 
232
 
 
233
void HostedNetscapePluginStream::cancelLoad(NSError *error)
 
234
{
 
235
    if (m_frameLoader) {
 
236
        ASSERT(!m_loader);
 
237
        
 
238
        DocumentLoader* documentLoader = m_frameLoader->activeDocumentLoader();
 
239
        if (documentLoader && documentLoader->isLoadingMainResource())
 
240
            documentLoader->cancelMainResourceLoad(error);
 
241
        return;
 
242
    }
 
243
 
 
244
    if (!m_loader->isDone()) {
 
245
        // Cancelling the load will disconnect the stream so there's no need to do it explicitly.
 
246
        m_loader->cancel(error);
 
247
    } else
 
248
        m_instance->disconnectStream(this);
 
249
}
 
250
 
 
251
NSError *HostedNetscapePluginStream::pluginCancelledConnectionError() const
 
252
{
 
253
    return [[[NSError alloc] _initWithPluginErrorCode:WebKitErrorPlugInCancelledConnection
 
254
                                           contentURL:m_responseURL ? m_responseURL.get() : m_requestURL.get()
 
255
                                        pluginPageURL:nil
 
256
                                           pluginName:[[m_instance->pluginView() pluginPackage] pluginInfo].name
 
257
                                             MIMEType:m_mimeType.get()] autorelease];
 
258
}
 
259
 
 
260
NSError *HostedNetscapePluginStream::errorForReason(NPReason reason) const
 
261
{
 
262
    if (reason == NPRES_DONE)
 
263
        return nil;
 
264
 
 
265
    if (reason == NPRES_USER_BREAK)
 
266
        return [NSError _webKitErrorWithDomain:NSURLErrorDomain
 
267
                                          code:NSURLErrorCancelled 
 
268
                                           URL:m_responseURL ? m_responseURL.get() : m_requestURL.get()];
 
269
 
 
270
    return pluginCancelledConnectionError();
 
271
}
 
272
 
 
273
} // namespace WebKit
 
274
 
 
275
#endif // USE(PLUGIN_HOST_PROCESS) && ENABLE(NETSCAPE_PLUGIN_API)
 
276