blob: 9866d3905901792d9b85149942dcb69e6c279ad1 [file] [log] [blame]
/*
* Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "WebResourcePrivate.h"
#import "WebFrameBridge.h"
#import "WebNSDictionaryExtras.h"
#import "WebNSURLExtras.h"
#import <WebCore/WebCoreURLResponse.h>
static NSString * const WebResourceDataKey = @"WebResourceData";
static NSString * const WebResourceFrameNameKey = @"WebResourceFrameName";
static NSString * const WebResourceMIMETypeKey = @"WebResourceMIMEType";
static NSString * const WebResourceURLKey = @"WebResourceURL";
static NSString * const WebResourceTextEncodingNameKey = @"WebResourceTextEncodingName";
static NSString * const WebResourceResponseKey = @"WebResourceResponse";
#define WebResourceVersion 1
@interface WebResourcePrivate : NSObject
{
@public
NSData *data;
NSURL *URL;
NSString *frameName;
NSString *MIMEType;
NSString *textEncodingName;
NSURLResponse *response;
BOOL shouldIgnoreWhenUnarchiving;
}
@end
@implementation WebResourcePrivate
- (void)dealloc
{
[data release];
[URL release];
[frameName release];
[MIMEType release];
[textEncodingName release];
[response release];
[super dealloc];
}
@end
@implementation WebResource
- (id)init
{
self = [super init];
if (!self)
return nil;
_private = [[WebResourcePrivate alloc] init];
return self;
}
- (id)initWithData:(NSData *)data URL:(NSURL *)URL MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)textEncodingName frameName:(NSString *)frameName
{
return [self _initWithData:data URL:URL MIMEType:MIMEType textEncodingName:textEncodingName frameName:frameName response:nil copyData:YES];
}
- (id)initWithCoder:(NSCoder *)decoder
{
self = [self init];
if (!self)
return nil;
@try {
id object = [decoder decodeObjectForKey:WebResourceDataKey];
if ([object isKindOfClass:[NSData class]])
_private->data = [object retain];
object = [decoder decodeObjectForKey:WebResourceURLKey];
if ([object isKindOfClass:[NSURL class]])
_private->URL = [object retain];
object = [decoder decodeObjectForKey:WebResourceMIMETypeKey];
if ([object isKindOfClass:[NSString class]])
_private->MIMEType = [object retain];
object = [decoder decodeObjectForKey:WebResourceTextEncodingNameKey];
if ([object isKindOfClass:[NSString class]])
_private->textEncodingName = [object retain];
object = [decoder decodeObjectForKey:WebResourceFrameNameKey];
if ([object isKindOfClass:[NSString class]])
_private->frameName = [object retain];
object = [decoder decodeObjectForKey:WebResourceResponseKey];
if ([object isKindOfClass:[NSURLResponse class]])
_private->response = [object retain];
} @catch(id) {
[self release];
return nil;
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeObject:_private->data forKey:WebResourceDataKey];
[encoder encodeObject:_private->URL forKey:WebResourceURLKey];
[encoder encodeObject:_private->MIMEType forKey:WebResourceMIMETypeKey];
[encoder encodeObject:_private->textEncodingName forKey:WebResourceTextEncodingNameKey];
[encoder encodeObject:_private->frameName forKey:WebResourceFrameNameKey];
[encoder encodeObject:_private->response forKey:WebResourceResponseKey];
}
- (void)dealloc
{
[_private release];
[super dealloc];
}
- (id)copyWithZone:(NSZone *)zone
{
return [self retain];
}
- (NSData *)data
{
return _private->data;
}
- (NSURL *)URL
{
return _private->URL;
}
- (NSString *)MIMEType
{
return _private->MIMEType;
}
- (NSString *)textEncodingName
{
return _private->textEncodingName;
}
- (NSString *)frameName
{
return _private->frameName;
}
- (id)description
{
return [NSString stringWithFormat:@"<%@ %@>", [self className], [self URL]];
}
@end
@implementation WebResource (WebResourcePrivate)
// SPI for Mail (5066325)
- (void)_ignoreWhenUnarchiving
{
_private->shouldIgnoreWhenUnarchiving = YES;
}
- (BOOL)_shouldIgnoreWhenUnarchiving
{
return _private->shouldIgnoreWhenUnarchiving;
}
+ (NSArray *)_resourcesFromPropertyLists:(NSArray *)propertyLists
{
if (![propertyLists isKindOfClass:[NSArray class]]) {
return nil;
}
NSEnumerator *enumerator = [propertyLists objectEnumerator];
NSMutableArray *resources = [NSMutableArray array];
NSDictionary *propertyList;
while ((propertyList = [enumerator nextObject]) != nil) {
WebResource *resource = [[WebResource alloc] _initWithPropertyList:propertyList];
if (resource) {
[resources addObject:resource];
[resource release];
}
}
return resources;
}
+ (NSArray *)_propertyListsFromResources:(NSArray *)resources
{
NSEnumerator *enumerator = [resources objectEnumerator];
NSMutableArray *propertyLists = [NSMutableArray array];
WebResource *resource;
while ((resource = [enumerator nextObject]) != nil) {
[propertyLists addObject:[resource _propertyListRepresentation]];
}
return propertyLists;
}
- (id)_initWithData:(NSData *)data
URL:(NSURL *)URL
MIMEType:(NSString *)MIMEType
textEncodingName:(NSString *)textEncodingName
frameName:(NSString *)frameName
response:(NSURLResponse *)response
copyData:(BOOL)copyData
{
[self init];
if (!data) {
[self release];
return nil;
}
_private->data = copyData ? [data copy] : [data retain];
if (!URL) {
[self release];
return nil;
}
_private->URL = [URL copy];
if (!MIMEType) {
[self release];
return nil;
}
_private->MIMEType = [MIMEType copy];
_private->textEncodingName = [textEncodingName copy];
_private->frameName = [frameName copy];
_private->response = [response retain];
return self;
}
- (id)_initWithData:(NSData *)data URL:(NSURL *)URL response:(NSURLResponse *)response
{
// Pass NO for copyData since the data doesn't need to be copied since we know that callers will no longer modify it.
// Copying it will also cause a performance regression.
return [self _initWithData:data
URL:URL
MIMEType:[response _webcore_MIMEType]
textEncodingName:[response textEncodingName]
frameName:nil
response:response
copyData:NO];
}
- (id)_initWithPropertyList:(id)propertyList
{
if (![propertyList isKindOfClass:[NSDictionary class]]) {
[self release];
return nil;
}
NSURLResponse *response = nil;
NSData *responseData = [propertyList objectForKey:WebResourceResponseKey];
if ([responseData isKindOfClass:[NSData class]]) {
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:responseData];
@try {
id responseObject = [unarchiver decodeObjectForKey:WebResourceResponseKey];
if ([responseObject isKindOfClass:[NSURLResponse class]])
response = responseObject;
[unarchiver finishDecoding];
} @catch(id) {
response = nil;
}
[unarchiver release];
}
NSData *data = [propertyList objectForKey:WebResourceDataKey];
NSString *URLString = [propertyList _webkit_stringForKey:WebResourceURLKey];
return [self _initWithData:[data isKindOfClass:[NSData class]] ? data : nil
URL:URLString ? [NSURL _web_URLWithDataAsString:URLString] : nil
MIMEType:[propertyList _webkit_stringForKey:WebResourceMIMETypeKey]
textEncodingName:[propertyList _webkit_stringForKey:WebResourceTextEncodingNameKey]
frameName:[propertyList _webkit_stringForKey:WebResourceFrameNameKey]
response:response
copyData:NO];
}
- (NSFileWrapper *)_fileWrapperRepresentation
{
NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:_private->data] autorelease];
NSString *preferredFilename = [_private->response suggestedFilename];
if (!preferredFilename || ![preferredFilename length])
preferredFilename = [_private->URL _webkit_suggestedFilenameWithMIMEType:_private->MIMEType];
[wrapper setPreferredFilename:preferredFilename];
return wrapper;
}
- (id)_propertyListRepresentation
{
NSMutableDictionary *propertyList = [NSMutableDictionary dictionary];
[propertyList setObject:_private->data forKey:WebResourceDataKey];
[propertyList setObject:[_private->URL _web_originalDataAsString] forKey:WebResourceURLKey];
[propertyList setObject:_private->MIMEType forKey:WebResourceMIMETypeKey];
if (_private->textEncodingName != nil) {
[propertyList setObject:_private->textEncodingName forKey:WebResourceTextEncodingNameKey];
}
if (_private->frameName != nil) {
[propertyList setObject:_private->frameName forKey:WebResourceFrameNameKey];
}
if (_private->response != nil) {
NSMutableData *responseData = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:responseData];
[archiver encodeObject:_private->response forKey:WebResourceResponseKey];
[archiver finishEncoding];
[archiver release];
[propertyList setObject:responseData forKey:WebResourceResponseKey];
[responseData release];
}
return propertyList;
}
- (NSURLResponse *)_response
{
if (_private->response != nil) {
return _private->response;
}
return [[[NSURLResponse alloc] initWithURL:_private->URL
MIMEType:_private->MIMEType
expectedContentLength:[_private->data length]
textEncodingName:_private->textEncodingName] autorelease];
}
- (NSString *)_stringValue
{
NSString *textEncodingName = [self textEncodingName];
return [WebFrameBridge stringWithData:_private->data textEncodingName:textEncodingName];
}
@end