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

« back to all changes in this revision

Viewing changes to Source/WebKit/mac/WebView/WebResource.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) 2005, 2006, 2007, 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
 *
 
8
 * 1.  Redistributions of source code must retain the above copyright
 
9
 *     notice, this list of conditions and the following disclaimer. 
 
10
 * 2.  Redistributions in binary form must reproduce the above copyright
 
11
 *     notice, this list of conditions and the following disclaimer in the
 
12
 *     documentation and/or other materials provided with the distribution. 
 
13
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 
14
 *     its contributors may be used to endorse or promote products derived
 
15
 *     from this software without specific prior written permission. 
 
16
 *
 
17
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 
18
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
19
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
20
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 
21
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
22
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
23
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 
24
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
27
 */
 
28
 
 
29
#import "WebResourceInternal.h"
 
30
 
 
31
#import "WebFrameInternal.h"
 
32
#import "WebKitLogging.h"
 
33
#import "WebKitVersionChecks.h"
 
34
#import "WebNSDictionaryExtras.h"
 
35
#import "WebNSObjectExtras.h"
 
36
#import "WebNSURLExtras.h"
 
37
#import <JavaScriptCore/InitializeThreading.h>
 
38
#import <wtf/PassRefPtr.h>
 
39
#import <WebCore/ArchiveResource.h>
 
40
#import <WebCore/LegacyWebArchive.h>
 
41
#import <WebCore/RunLoop.h>
 
42
#import <WebCore/RuntimeApplicationChecks.h>
 
43
#import <WebCore/TextEncoding.h>
 
44
#import <WebCore/ThreadCheck.h>
 
45
#import <WebCore/WebCoreObjCExtras.h>
 
46
#import <WebCore/WebCoreURLResponse.h>
 
47
#import <wtf/MainThread.h>
 
48
 
 
49
using namespace WebCore;
 
50
 
 
51
static NSString * const WebResourceDataKey =              @"WebResourceData";
 
52
static NSString * const WebResourceFrameNameKey =         @"WebResourceFrameName";
 
53
static NSString * const WebResourceMIMETypeKey =          @"WebResourceMIMEType";
 
54
static NSString * const WebResourceURLKey =               @"WebResourceURL";
 
55
static NSString * const WebResourceTextEncodingNameKey =  @"WebResourceTextEncodingName";
 
56
static NSString * const WebResourceResponseKey =          @"WebResourceResponse";
 
57
 
 
58
@interface WebResourcePrivate : NSObject {
 
59
@public
 
60
    ArchiveResource* coreResource;
 
61
}
 
62
- (id)initWithCoreResource:(PassRefPtr<ArchiveResource>)coreResource;
 
63
@end
 
64
 
 
65
@implementation WebResourcePrivate
 
66
 
 
67
+ (void)initialize
 
68
{
 
69
    JSC::initializeThreading();
 
70
    WTF::initializeMainThreadToProcessMainThread();
 
71
    WebCore::RunLoop::initializeMainRunLoop();
 
72
    WebCoreObjCFinalizeOnMainThread(self);
 
73
}
 
74
 
 
75
- (id)init
 
76
{
 
77
    return [super init];
 
78
}
 
79
 
 
80
- (id)initWithCoreResource:(PassRefPtr<ArchiveResource>)passedResource
 
81
{
 
82
    self = [super init];
 
83
    if (!self)
 
84
        return nil;
 
85
    // Acquire the PassRefPtr<>'s ref as our own manual ref
 
86
    coreResource = passedResource.leakRef();
 
87
    return self;
 
88
}
 
89
 
 
90
- (void)dealloc
 
91
{
 
92
    if (WebCoreObjCScheduleDeallocateOnMainThread([WebResourcePrivate class], self))
 
93
        return;
 
94
 
 
95
    if (coreResource)
 
96
        coreResource->deref();
 
97
    [super dealloc];
 
98
}
 
99
 
 
100
- (void)finalize
 
101
{
 
102
    if (coreResource)
 
103
        coreResource->deref();
 
104
    [super finalize];
 
105
}
 
106
 
 
107
@end
 
108
 
 
109
@implementation WebResource
 
110
 
 
111
- (id)init
 
112
{
 
113
    self = [super init];
 
114
    if (!self)
 
115
        return nil;
 
116
    _private = [[WebResourcePrivate alloc] init];
 
117
    return self;
 
118
}
 
119
 
 
120
- (id)initWithData:(NSData *)data URL:(NSURL *)URL MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)textEncodingName frameName:(NSString *)frameName
 
121
{
 
122
    return [self _initWithData:data URL:URL MIMEType:MIMEType textEncodingName:textEncodingName frameName:frameName response:nil copyData:YES];
 
123
}
 
124
 
 
125
- (id)initWithCoder:(NSCoder *)decoder
 
126
{
 
127
    WebCoreThreadViolationCheckRoundTwo();
 
128
 
 
129
    self = [super init];
 
130
    if (!self)
 
131
        return nil;
 
132
 
 
133
    NSData *data = nil;
 
134
    NSURL *url = nil;
 
135
    NSString *mimeType = nil, *textEncoding = nil, *frameName = nil;
 
136
    NSURLResponse *response = nil;
 
137
    
 
138
    @try {
 
139
        id object = [decoder decodeObjectForKey:WebResourceDataKey];
 
140
        if ([object isKindOfClass:[NSData class]])
 
141
            data = object;
 
142
        object = [decoder decodeObjectForKey:WebResourceURLKey];
 
143
        if ([object isKindOfClass:[NSURL class]])
 
144
            url = object;
 
145
        object = [decoder decodeObjectForKey:WebResourceMIMETypeKey];
 
146
        if ([object isKindOfClass:[NSString class]])
 
147
            mimeType = object;
 
148
        object = [decoder decodeObjectForKey:WebResourceTextEncodingNameKey];
 
149
        if ([object isKindOfClass:[NSString class]])
 
150
            textEncoding = object;
 
151
        object = [decoder decodeObjectForKey:WebResourceFrameNameKey];
 
152
        if ([object isKindOfClass:[NSString class]])
 
153
            frameName = object;
 
154
        object = [decoder decodeObjectForKey:WebResourceResponseKey];
 
155
        if ([object isKindOfClass:[NSURLResponse class]])
 
156
            response = object;
 
157
    } @catch(id) {
 
158
        [self release];
 
159
        return nil;
 
160
    }
 
161
 
 
162
    _private = [[WebResourcePrivate alloc] initWithCoreResource:ArchiveResource::create(SharedBuffer::wrapNSData(data), url, mimeType, textEncoding, frameName, response)];
 
163
 
 
164
    return self;
 
165
}
 
166
 
 
167
- (void)encodeWithCoder:(NSCoder *)encoder
 
168
{
 
169
    ArchiveResource *resource = _private->coreResource;
 
170
    
 
171
    NSData *data = nil;
 
172
    NSURL *url = nil;
 
173
    NSString *mimeType = nil, *textEncoding = nil, *frameName = nil;
 
174
    NSURLResponse *response = nil;
 
175
    
 
176
    if (resource) {
 
177
        if (resource->data())
 
178
            data = [resource->data()->createNSData() autorelease];
 
179
        url = resource->url();
 
180
        mimeType = resource->mimeType();
 
181
        textEncoding = resource->textEncoding();
 
182
        frameName = resource->frameName();
 
183
        response = resource->response().nsURLResponse();
 
184
    }
 
185
    [encoder encodeObject:data forKey:WebResourceDataKey];
 
186
    [encoder encodeObject:url forKey:WebResourceURLKey];
 
187
    [encoder encodeObject:mimeType forKey:WebResourceMIMETypeKey];
 
188
    [encoder encodeObject:textEncoding forKey:WebResourceTextEncodingNameKey];
 
189
    [encoder encodeObject:frameName forKey:WebResourceFrameNameKey];
 
190
    [encoder encodeObject:response forKey:WebResourceResponseKey];
 
191
}
 
192
 
 
193
- (void)dealloc
 
194
{
 
195
    [_private release];
 
196
    [super dealloc];
 
197
}
 
198
 
 
199
- (id)copyWithZone:(NSZone *)zone
 
200
{
 
201
    return [self retain];
 
202
}
 
203
 
 
204
- (NSData *)data
 
205
{
 
206
#ifdef MAIL_THREAD_WORKAROUND
 
207
    if (needMailThreadWorkaround())
 
208
        return [[self _webkit_invokeOnMainThread] data];
 
209
#endif
 
210
 
 
211
    WebCoreThreadViolationCheckRoundTwo();
 
212
 
 
213
    if (!_private->coreResource)
 
214
        return nil;
 
215
    if (!_private->coreResource->data())
 
216
        return nil;
 
217
    return [_private->coreResource->data()->createNSData() autorelease];
 
218
}
 
219
 
 
220
- (NSURL *)URL
 
221
{
 
222
#ifdef MAIL_THREAD_WORKAROUND
 
223
    if (needMailThreadWorkaround())
 
224
        return [[self _webkit_invokeOnMainThread] URL];
 
225
#endif
 
226
 
 
227
    WebCoreThreadViolationCheckRoundTwo();
 
228
 
 
229
    if (!_private->coreResource)
 
230
        return nil;
 
231
    NSURL *url = _private->coreResource->url();
 
232
    return url;
 
233
}
 
234
 
 
235
- (NSString *)MIMEType
 
236
{
 
237
#ifdef MAIL_THREAD_WORKAROUND
 
238
    if (needMailThreadWorkaround())
 
239
        return [[self _webkit_invokeOnMainThread] MIMEType];
 
240
#endif
 
241
 
 
242
    WebCoreThreadViolationCheckRoundTwo();
 
243
 
 
244
    if (!_private->coreResource)
 
245
        return nil;
 
246
    NSString *mimeType = _private->coreResource->mimeType();
 
247
    return mimeType;
 
248
}
 
249
 
 
250
- (NSString *)textEncodingName
 
251
{
 
252
#ifdef MAIL_THREAD_WORKAROUND
 
253
    if (needMailThreadWorkaround())
 
254
        return [[self _webkit_invokeOnMainThread] textEncodingName];
 
255
#endif
 
256
 
 
257
    WebCoreThreadViolationCheckRoundTwo();
 
258
 
 
259
    if (!_private->coreResource)
 
260
        return nil;
 
261
    NSString *textEncodingName = _private->coreResource->textEncoding();
 
262
    return textEncodingName;
 
263
}
 
264
 
 
265
- (NSString *)frameName
 
266
{
 
267
#ifdef MAIL_THREAD_WORKAROUND
 
268
    if (needMailThreadWorkaround())
 
269
        return [[self _webkit_invokeOnMainThread] frameName];
 
270
#endif
 
271
 
 
272
    WebCoreThreadViolationCheckRoundTwo();
 
273
 
 
274
    if (!_private->coreResource)
 
275
        return nil;
 
276
    NSString *frameName = _private->coreResource->frameName();
 
277
    return frameName;
 
278
}
 
279
 
 
280
- (NSString *)description
 
281
{
 
282
    return [NSString stringWithFormat:@"<%@ %@>", [self className], [self URL]];
 
283
}
 
284
 
 
285
@end
 
286
 
 
287
@implementation WebResource (WebResourceInternal)
 
288
 
 
289
- (id)_initWithCoreResource:(PassRefPtr<ArchiveResource>)coreResource
 
290
{
 
291
    self = [super init];
 
292
    if (!self)
 
293
        return nil;
 
294
            
 
295
    ASSERT(coreResource);
 
296
    
 
297
    // WebResources should not be init'ed with nil data, and doing so breaks certain uses of NSHTMLReader
 
298
    // See <rdar://problem/5820157> for more info
 
299
    if (!coreResource->data()) {
 
300
        [self release];
 
301
        return nil;
 
302
    }
 
303
    
 
304
    _private = [[WebResourcePrivate alloc] initWithCoreResource:coreResource];
 
305
            
 
306
    return self;
 
307
}
 
308
 
 
309
- (WebCore::ArchiveResource *)_coreResource
 
310
{
 
311
    return _private->coreResource;
 
312
}
 
313
 
 
314
@end
 
315
 
 
316
@implementation WebResource (WebResourcePrivate)
 
317
 
 
318
// SPI for Mail (5066325)
 
319
// FIXME: This "ignoreWhenUnarchiving" concept is an ugly one - can we find a cleaner solution for those who need this SPI?
 
320
- (void)_ignoreWhenUnarchiving
 
321
{
 
322
#ifdef MAIL_THREAD_WORKAROUND
 
323
    if (needMailThreadWorkaround()) {
 
324
        [[self _webkit_invokeOnMainThread] _ignoreWhenUnarchiving];
 
325
        return;
 
326
    }
 
327
#endif
 
328
 
 
329
    WebCoreThreadViolationCheckRoundTwo();
 
330
 
 
331
    if (!_private->coreResource)
 
332
        return;
 
333
    _private->coreResource->ignoreWhenUnarchiving();
 
334
}
 
335
 
 
336
- (id)_initWithData:(NSData *)data 
 
337
                URL:(NSURL *)URL 
 
338
           MIMEType:(NSString *)MIMEType 
 
339
   textEncodingName:(NSString *)textEncodingName 
 
340
          frameName:(NSString *)frameName 
 
341
           response:(NSURLResponse *)response
 
342
           copyData:(BOOL)copyData
 
343
{
 
344
#ifdef MAIL_THREAD_WORKAROUND
 
345
    if (needMailThreadWorkaround())
 
346
        return [[self _webkit_invokeOnMainThread] _initWithData:data URL:URL MIMEType:MIMEType textEncodingName:textEncodingName frameName:frameName response:response copyData:copyData];
 
347
#endif
 
348
 
 
349
    WebCoreThreadViolationCheckRoundTwo();
 
350
 
 
351
    self = [super init];
 
352
    if (!self)
 
353
        return nil;
 
354
    
 
355
    if (!data || !URL || !MIMEType) {
 
356
        [self release];
 
357
        return nil;
 
358
    }
 
359
 
 
360
    _private = [[WebResourcePrivate alloc] initWithCoreResource:ArchiveResource::create(SharedBuffer::wrapNSData(copyData ? [[data copy] autorelease] : data), URL, MIMEType, textEncodingName, frameName, response)];
 
361
 
 
362
    return self;
 
363
}
 
364
 
 
365
- (id)_initWithData:(NSData *)data URL:(NSURL *)URL response:(NSURLResponse *)response
 
366
{
 
367
    // Pass NO for copyData since the data doesn't need to be copied since we know that callers will no longer modify it.
 
368
    // Copying it will also cause a performance regression.
 
369
    return [self _initWithData:data
 
370
                           URL:URL
 
371
                      MIMEType:[response MIMEType]
 
372
              textEncodingName:[response textEncodingName]
 
373
                     frameName:nil
 
374
                      response:response
 
375
                      copyData:NO];
 
376
}
 
377
 
 
378
- (NSString *)_suggestedFilename
 
379
{
 
380
#ifdef MAIL_THREAD_WORKAROUND
 
381
    if (needMailThreadWorkaround())
 
382
        return [[self _webkit_invokeOnMainThread] _suggestedFilename];
 
383
#endif
 
384
 
 
385
    WebCoreThreadViolationCheckRoundTwo();
 
386
 
 
387
    if (!_private->coreResource)
 
388
        return nil;
 
389
    NSString *suggestedFilename = _private->coreResource->response().suggestedFilename();
 
390
    return suggestedFilename;
 
391
}
 
392
 
 
393
- (NSFileWrapper *)_fileWrapperRepresentation
 
394
{
 
395
    NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:[self data]] autorelease];
 
396
    NSString *filename = [self _suggestedFilename];
 
397
    if (!filename || ![filename length])
 
398
        filename = [[self URL] _webkit_suggestedFilenameWithMIMEType:[self MIMEType]];
 
399
    [wrapper setPreferredFilename:filename];
 
400
    return wrapper;
 
401
}
 
402
 
 
403
- (NSURLResponse *)_response
 
404
{
 
405
#ifdef MAIL_THREAD_WORKAROUND
 
406
    if (needMailThreadWorkaround())
 
407
        return [[self _webkit_invokeOnMainThread] _response];
 
408
#endif
 
409
 
 
410
    WebCoreThreadViolationCheckRoundTwo();
 
411
 
 
412
    NSURLResponse *response = nil;
 
413
    if (_private->coreResource)
 
414
        response = _private->coreResource->response().nsURLResponse();
 
415
    return response ? response : [[[NSURLResponse alloc] init] autorelease];        
 
416
}
 
417
 
 
418
- (NSString *)_stringValue
 
419
{
 
420
#ifdef MAIL_THREAD_WORKAROUND
 
421
    if (needMailThreadWorkaround())
 
422
        return [[self _webkit_invokeOnMainThread] _stringValue];
 
423
#endif
 
424
 
 
425
    WebCoreThreadViolationCheckRoundTwo();
 
426
 
 
427
    WebCore::TextEncoding encoding;
 
428
    if (_private->coreResource)
 
429
        encoding = _private->coreResource->textEncoding();
 
430
    if (!encoding.isValid())
 
431
        encoding = WindowsLatin1Encoding();
 
432
    
 
433
    SharedBuffer* coreData = _private->coreResource ? _private->coreResource->data() : 0;
 
434
    return encoding.decode(reinterpret_cast<const char*>(coreData ? coreData->data() : 0), coreData ? coreData->size() : 0);
 
435
}
 
436
 
 
437
@end
 
438
 
 
439
#ifdef MAIL_THREAD_WORKAROUND
 
440
 
 
441
static const double newMailBundleVersion = 1050.0;
 
442
 
 
443
@implementation WebResource (WebMailThreadWorkaround)
 
444
 
 
445
+ (BOOL)_needMailThreadWorkaroundIfCalledOffMainThread
 
446
{
 
447
    static BOOL isOldMail = applicationIsAppleMail() && [[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] doubleValue] < newMailBundleVersion;
 
448
    return isOldMail;
 
449
}
 
450
 
 
451
@end
 
452
 
 
453
#endif