2
* Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
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.
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.
29
#import "WebResourceInternal.h"
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>
49
using namespace WebCore;
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";
58
@interface WebResourcePrivate : NSObject {
60
ArchiveResource* coreResource;
62
- (id)initWithCoreResource:(PassRefPtr<ArchiveResource>)coreResource;
65
@implementation WebResourcePrivate
69
JSC::initializeThreading();
70
WTF::initializeMainThreadToProcessMainThread();
71
WebCore::RunLoop::initializeMainRunLoop();
72
WebCoreObjCFinalizeOnMainThread(self);
80
- (id)initWithCoreResource:(PassRefPtr<ArchiveResource>)passedResource
85
// Acquire the PassRefPtr<>'s ref as our own manual ref
86
coreResource = passedResource.leakRef();
92
if (WebCoreObjCScheduleDeallocateOnMainThread([WebResourcePrivate class], self))
96
coreResource->deref();
103
coreResource->deref();
109
@implementation WebResource
116
_private = [[WebResourcePrivate alloc] init];
120
- (id)initWithData:(NSData *)data URL:(NSURL *)URL MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)textEncodingName frameName:(NSString *)frameName
122
return [self _initWithData:data URL:URL MIMEType:MIMEType textEncodingName:textEncodingName frameName:frameName response:nil copyData:YES];
125
- (id)initWithCoder:(NSCoder *)decoder
127
WebCoreThreadViolationCheckRoundTwo();
135
NSString *mimeType = nil, *textEncoding = nil, *frameName = nil;
136
NSURLResponse *response = nil;
139
id object = [decoder decodeObjectForKey:WebResourceDataKey];
140
if ([object isKindOfClass:[NSData class]])
142
object = [decoder decodeObjectForKey:WebResourceURLKey];
143
if ([object isKindOfClass:[NSURL class]])
145
object = [decoder decodeObjectForKey:WebResourceMIMETypeKey];
146
if ([object isKindOfClass:[NSString class]])
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]])
154
object = [decoder decodeObjectForKey:WebResourceResponseKey];
155
if ([object isKindOfClass:[NSURLResponse class]])
162
_private = [[WebResourcePrivate alloc] initWithCoreResource:ArchiveResource::create(SharedBuffer::wrapNSData(data), url, mimeType, textEncoding, frameName, response)];
167
- (void)encodeWithCoder:(NSCoder *)encoder
169
ArchiveResource *resource = _private->coreResource;
173
NSString *mimeType = nil, *textEncoding = nil, *frameName = nil;
174
NSURLResponse *response = nil;
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();
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];
199
- (id)copyWithZone:(NSZone *)zone
201
return [self retain];
206
#ifdef MAIL_THREAD_WORKAROUND
207
if (needMailThreadWorkaround())
208
return [[self _webkit_invokeOnMainThread] data];
211
WebCoreThreadViolationCheckRoundTwo();
213
if (!_private->coreResource)
215
if (!_private->coreResource->data())
217
return [_private->coreResource->data()->createNSData() autorelease];
222
#ifdef MAIL_THREAD_WORKAROUND
223
if (needMailThreadWorkaround())
224
return [[self _webkit_invokeOnMainThread] URL];
227
WebCoreThreadViolationCheckRoundTwo();
229
if (!_private->coreResource)
231
NSURL *url = _private->coreResource->url();
235
- (NSString *)MIMEType
237
#ifdef MAIL_THREAD_WORKAROUND
238
if (needMailThreadWorkaround())
239
return [[self _webkit_invokeOnMainThread] MIMEType];
242
WebCoreThreadViolationCheckRoundTwo();
244
if (!_private->coreResource)
246
NSString *mimeType = _private->coreResource->mimeType();
250
- (NSString *)textEncodingName
252
#ifdef MAIL_THREAD_WORKAROUND
253
if (needMailThreadWorkaround())
254
return [[self _webkit_invokeOnMainThread] textEncodingName];
257
WebCoreThreadViolationCheckRoundTwo();
259
if (!_private->coreResource)
261
NSString *textEncodingName = _private->coreResource->textEncoding();
262
return textEncodingName;
265
- (NSString *)frameName
267
#ifdef MAIL_THREAD_WORKAROUND
268
if (needMailThreadWorkaround())
269
return [[self _webkit_invokeOnMainThread] frameName];
272
WebCoreThreadViolationCheckRoundTwo();
274
if (!_private->coreResource)
276
NSString *frameName = _private->coreResource->frameName();
280
- (NSString *)description
282
return [NSString stringWithFormat:@"<%@ %@>", [self className], [self URL]];
287
@implementation WebResource (WebResourceInternal)
289
- (id)_initWithCoreResource:(PassRefPtr<ArchiveResource>)coreResource
295
ASSERT(coreResource);
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()) {
304
_private = [[WebResourcePrivate alloc] initWithCoreResource:coreResource];
309
- (WebCore::ArchiveResource *)_coreResource
311
return _private->coreResource;
316
@implementation WebResource (WebResourcePrivate)
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
322
#ifdef MAIL_THREAD_WORKAROUND
323
if (needMailThreadWorkaround()) {
324
[[self _webkit_invokeOnMainThread] _ignoreWhenUnarchiving];
329
WebCoreThreadViolationCheckRoundTwo();
331
if (!_private->coreResource)
333
_private->coreResource->ignoreWhenUnarchiving();
336
- (id)_initWithData:(NSData *)data
338
MIMEType:(NSString *)MIMEType
339
textEncodingName:(NSString *)textEncodingName
340
frameName:(NSString *)frameName
341
response:(NSURLResponse *)response
342
copyData:(BOOL)copyData
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];
349
WebCoreThreadViolationCheckRoundTwo();
355
if (!data || !URL || !MIMEType) {
360
_private = [[WebResourcePrivate alloc] initWithCoreResource:ArchiveResource::create(SharedBuffer::wrapNSData(copyData ? [[data copy] autorelease] : data), URL, MIMEType, textEncodingName, frameName, response)];
365
- (id)_initWithData:(NSData *)data URL:(NSURL *)URL response:(NSURLResponse *)response
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
371
MIMEType:[response MIMEType]
372
textEncodingName:[response textEncodingName]
378
- (NSString *)_suggestedFilename
380
#ifdef MAIL_THREAD_WORKAROUND
381
if (needMailThreadWorkaround())
382
return [[self _webkit_invokeOnMainThread] _suggestedFilename];
385
WebCoreThreadViolationCheckRoundTwo();
387
if (!_private->coreResource)
389
NSString *suggestedFilename = _private->coreResource->response().suggestedFilename();
390
return suggestedFilename;
393
- (NSFileWrapper *)_fileWrapperRepresentation
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];
403
- (NSURLResponse *)_response
405
#ifdef MAIL_THREAD_WORKAROUND
406
if (needMailThreadWorkaround())
407
return [[self _webkit_invokeOnMainThread] _response];
410
WebCoreThreadViolationCheckRoundTwo();
412
NSURLResponse *response = nil;
413
if (_private->coreResource)
414
response = _private->coreResource->response().nsURLResponse();
415
return response ? response : [[[NSURLResponse alloc] init] autorelease];
418
- (NSString *)_stringValue
420
#ifdef MAIL_THREAD_WORKAROUND
421
if (needMailThreadWorkaround())
422
return [[self _webkit_invokeOnMainThread] _stringValue];
425
WebCoreThreadViolationCheckRoundTwo();
427
WebCore::TextEncoding encoding;
428
if (_private->coreResource)
429
encoding = _private->coreResource->textEncoding();
430
if (!encoding.isValid())
431
encoding = WindowsLatin1Encoding();
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);
439
#ifdef MAIL_THREAD_WORKAROUND
441
static const double newMailBundleVersion = 1050.0;
443
@implementation WebResource (WebMailThreadWorkaround)
445
+ (BOOL)_needMailThreadWorkaroundIfCalledOffMainThread
447
static BOOL isOldMail = applicationIsAppleMail() && [[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] doubleValue] < newMailBundleVersion;