WebDataSource.m 28.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 * Copyright (C) 2005 Apple Computer, 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.
 */
28

darin's avatar
darin committed
29
#import "WebDataSource.h"
30

darin's avatar
darin committed
31 32 33 34 35 36 37
#import "WebArchive.h"
#import "WebArchiver.h"
#import "WebDOMOperationsPrivate.h"
#import "WebDataProtocol.h"
#import "WebDataSourceInternal.h"
#import "WebDefaultResourceLoadDelegate.h"
#import "WebDocument.h"
mjs's avatar
mjs committed
38
#import "WebDownloadInternal.h"
darin's avatar
darin committed
39 40
#import "WebFrameBridge.h"
#import "WebFrameInternal.h"
mjs's avatar
mjs committed
41
#import "WebFrameLoader.h"
darin's avatar
darin committed
42 43 44 45 46 47 48 49 50 51 52 53 54
#import "WebFrameLoadDelegate.h"
#import "WebFrameView.h"
#import "WebHTMLRepresentation.h"
#import "WebHTMLViewPrivate.h"
#import "WebHistory.h"
#import "WebHistoryItemPrivate.h"
#import "WebIconDatabasePrivate.h"
#import "WebKitErrorsPrivate.h"
#import "WebKitLogging.h"
#import "WebKitNSStringExtras.h"
#import "WebKitStatisticsPrivate.h"
#import "WebNSObjectExtras.h"
#import "WebNSURLExtras.h"
mjs's avatar
mjs committed
55
#import "WebNSURLRequestExtras.h"
darin's avatar
darin committed
56
#import "WebPDFRepresentation.h"
mjs's avatar
mjs committed
57
#import "WebPreferences.h"
darin's avatar
darin committed
58 59
#import "WebResourceLoadDelegate.h"
#import "WebResourcePrivate.h"
thatcher's avatar
thatcher committed
60
#import "WebScriptDebugServerPrivate.h"
darin's avatar
darin committed
61 62
#import "WebUnarchivingState.h"
#import "WebViewInternal.h"
cblu's avatar
cblu committed
63 64
#import <Foundation/NSURLConnection.h>
#import <Foundation/NSURLRequest.h>
darin's avatar
darin committed
65 66
#import <JavaScriptCore/Assertions.h>
#import <WebKit/DOMHTML.h>
67
#import <WebKit/DOMPrivate.h>
darin's avatar
darin committed
68
#import <WebKitSystemInterface.h>
mjs's avatar
mjs committed
69
#import "WebDocumentLoadStateMac.h"
70

mjs's avatar
mjs committed
71 72 73
@interface WebDataSourcePrivate : NSObject
{
    @public
mjs's avatar
mjs committed
74
    
mjs's avatar
mjs committed
75
    WebDocumentLoadStateMac *loadState;
mjs's avatar
mjs committed
76
   
mjs's avatar
mjs committed
77 78
    id <WebDocumentRepresentation> representation;
    
mjs's avatar
mjs committed
79 80 81
    BOOL loadingFromPageCache;
    WebUnarchivingState *unarchivingState;
    NSMutableDictionary *subresources;
mjs's avatar
mjs committed
82 83 84 85 86
    
    // The time when the data source was told to start loading.
    double loadingStartedTime;
    
    BOOL primaryLoadComplete;
mjs's avatar
mjs committed
87
        
mjs's avatar
mjs committed
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
    BOOL isClientRedirect;
    
    NSString *pageTitle;
    
    NSString *encoding;
    NSString *overrideEncoding;
    
    BOOL representationFinishedLoading;
    
    // The action that triggered loading of this data source -
    // we keep this around for the benefit of the various policy
    // handlers.
    NSDictionary *triggeringAction;
    
    // The last request that we checked click policy for - kept around
    // so we can avoid asking again needlessly.
    NSURLRequest *lastCheckedRequest;
    
    // We retain all the received responses so we can play back the
    // WebResourceLoadDelegate messages if the item is loaded from the
    // page cache.
    NSMutableArray *responses;
mjs's avatar
mjs committed
110
    BOOL stopRecordingResponses;    
mjs's avatar
mjs committed
111 112 113 114
}

@end

115 116 117 118
@implementation WebDataSourcePrivate 

- (void)dealloc
{
mjs's avatar
mjs committed
119
    ASSERT(![loadState isLoading]);
tomernic's avatar
tomernic committed
120

mjs's avatar
mjs committed
121 122
    [loadState release];
    
123 124 125 126 127
    [representation release];
    [pageTitle release];
    [triggeringAction release];
    [lastCheckedRequest release];
    [responses release];
mjs's avatar
mjs committed
128
    [unarchivingState release];
129 130 131 132 133 134

    [super dealloc];
}

@end

mjs's avatar
mjs committed
135 136
@interface WebDataSource (WebFileInternal)
@end
cblu's avatar
cblu committed
137

mjs's avatar
mjs committed
138
@implementation WebDataSource (WebFileInternal)
139 140 141 142 143

- (void)_setRepresentation: (id<WebDocumentRepresentation>)representation
{
    [_private->representation release];
    _private->representation = [representation retain];
darin's avatar
darin committed
144
    _private->representationFinishedLoading = NO;
145 146
}

mjs's avatar
mjs committed
147
- (void)_prepareForLoadStart
148
{
mjs's avatar
mjs committed
149
    ASSERT(![_private->loadState isStopping]);
mjs's avatar
mjs committed
150
    [self _setPrimaryLoadComplete:NO];
151
    ASSERT([self webFrame] != nil);
mjs's avatar
mjs committed
152
    [_private->loadState clearErrors];
153 154 155 156
    
    // Mark the start loading time.
    _private->loadingStartedTime = CFAbsoluteTimeGetCurrent();
    
mjs's avatar
mjs committed
157
    [_private->loadState setLoading:YES];
mjs's avatar
mjs committed
158 159 160
    [[self _webView] _progressStarted:[self webFrame]];
    [[self _webView] _didStartProvisionalLoadForFrame:[self webFrame]];
    [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView]
161
                                     didStartProvisionalLoadForFrame:[self webFrame]];
mjs's avatar
mjs committed
162
}
163

mjs's avatar
mjs committed
164
static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class, NSArray *supportTypes)
mjs's avatar
mjs committed
165
{
mjs's avatar
mjs committed
166 167 168 169 170 171 172 173
    NSEnumerator *enumerator = [supportTypes objectEnumerator];
    ASSERT(enumerator != nil);
    NSString *mime = nil;
    while ((mime = [enumerator nextObject]) != nil) {
        // Don't clobber previously-registered classes.
        if ([allTypes objectForKey:mime] == nil)
            [allTypes setObject:class forKey:mime];
    }
mjs's avatar
mjs committed
174 175
}

mjs's avatar
mjs committed
176
+ (Class)_representationClassForMIMEType:(NSString *)MIMEType
mjs's avatar
mjs committed
177
{
mjs's avatar
mjs committed
178 179 180
    Class repClass;
    return [WebView _viewClass:nil andRepresentationClass:&repClass forMIMEType:MIMEType] ? repClass : nil;
}
mjs's avatar
mjs committed
181

mjs's avatar
mjs committed
182
- (void)_addResponse:(NSURLResponse *)r
sullivan's avatar
WebKit:  
sullivan committed
183
{
mjs's avatar
mjs committed
184 185 186 187
    if (!_private->stopRecordingResponses) {
        if (!_private->responses)
            _private->responses = [[NSMutableArray alloc] init];
        [_private->responses addObject: r];
sullivan's avatar
WebKit:  
sullivan committed
188 189 190
    }
}

mjs's avatar
mjs committed
191
@end
192

mjs's avatar
mjs committed
193
@implementation WebDataSource (WebPrivate)
darin's avatar
darin committed
194

mjs's avatar
mjs committed
195 196
- (NSError *)_mainDocumentError
{
mjs's avatar
mjs committed
197
    return [_private->loadState mainDocumentError];
198 199
}

mjs's avatar
mjs committed
200
- (void)_addSubframeArchives:(NSArray *)subframeArchives
201
{
mjs's avatar
mjs committed
202 203 204 205
    NSEnumerator *enumerator = [subframeArchives objectEnumerator];
    WebArchive *archive;
    while ((archive = [enumerator nextObject]) != nil)
        [self _addToUnarchiveState:archive];
206 207
}

mjs's avatar
mjs committed
208
- (NSFileWrapper *)_fileWrapperForURL:(NSURL *)URL
209
{
mjs's avatar
mjs committed
210 211 212 213
    if ([URL isFileURL]) {
        NSString *path = [[URL path] stringByResolvingSymlinksInPath];
        return [[[NSFileWrapper alloc] initWithPath:path] autorelease];
    }
sullivan's avatar
WebKit:  
sullivan committed
214
    
mjs's avatar
mjs committed
215 216 217
    WebResource *resource = [self subresourceForURL:URL];
    if (resource) {
        return [resource _fileWrapperRepresentation];
sullivan's avatar
WebKit:  
sullivan committed
218 219
    }
    
mjs's avatar
mjs committed
220 221 222 223 224
    NSCachedURLResponse *cachedResponse = [[self _webView] _cachedResponseForURL:URL];
    if (cachedResponse) {
        NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:[cachedResponse data]] autorelease];
        [wrapper setPreferredFilename:[[cachedResponse response] suggestedFilename]];
        return wrapper;
225
    }
mjs's avatar
mjs committed
226 227
    
    return nil;
228 229
}

mjs's avatar
mjs committed
230
@end
231

mjs's avatar
mjs committed
232
@implementation WebDataSource (WebInternal)
eseidel's avatar
eseidel committed
233

mjs's avatar
mjs committed
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
- (void)_finishedLoading
{
    _private->representationFinishedLoading = YES;
    [[self representation] finishedLoadingWithDataSource:self];
}

- (void)_receivedData:(NSData *)data
{
    [[self representation] receivedData:data withDataSource:self];
    [[[[self webFrame] frameView] documentView] dataSourceUpdated:self];
}

- (void)_setMainDocumentError:(NSError *)error
{
    if (!_private->representationFinishedLoading) {
        _private->representationFinishedLoading = YES;
        [[self representation] receivedError:error withDataSource:self];
    }
}

- (void)_clearUnarchivingState
{
    [_private->unarchivingState release];
    _private->unarchivingState = nil;
}

- (void)_revertToProvisionalState
{
    [self _setRepresentation:nil];
}

265 266 267
+ (NSMutableDictionary *)_repTypesAllowImageTypeOmission:(BOOL)allowImageTypeOmission
{
    static NSMutableDictionary *repTypes = nil;
eseidel's avatar
eseidel committed
268
    static BOOL addedImageTypes = NO;
269 270
    
    if (!repTypes) {
eseidel's avatar
eseidel committed
271
        repTypes = [[NSMutableDictionary alloc] init];
andersca's avatar
andersca committed
272
        addTypesFromClass(repTypes, [WebHTMLRepresentation class], [WebHTMLRepresentation supportedNonImageMIMETypes]);
mjs's avatar
mjs committed
273
        
274
        // Since this is a "secret default" we don't both registering it.
eseidel's avatar
eseidel committed
275 276 277
        BOOL omitPDFSupport = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitOmitPDFSupport"];
        if (!omitPDFSupport)
            addTypesFromClass(repTypes, [WebPDFRepresentation class], [WebPDFRepresentation supportedMIMETypes]);
278 279 280
    }
    
    if (!addedImageTypes && !allowImageTypeOmission) {
andersca's avatar
andersca committed
281
        addTypesFromClass(repTypes, [WebHTMLRepresentation class], [WebHTMLRepresentation supportedImageMIMETypes]);
282 283 284 285 286 287
        addedImageTypes = YES;
    }
    
    return repTypes;
}

mjs's avatar
mjs committed
288
- (void)_decidePolicyForMIMEType:(NSString *)MIMEType decisionListener:(WebPolicyDecisionListener *)listener
289
{
mjs's avatar
mjs committed
290 291 292 293 294
    WebView *wv = [self _webView];
    [[wv _policyDelegateForwarder] webView:wv decidePolicyForMIMEType:MIMEType
                                   request:[self request]
                                     frame:[self webFrame]
                          decisionListener:listener];
295 296
}

trey's avatar
trey committed
297
- (void)_receivedMainResourceError:(NSError *)error complete:(BOOL)isComplete
298
{
mjs's avatar
mjs committed
299
    // MOVABLE
mjs's avatar
mjs committed
300
    WebFrameBridge *bridge = [[self webFrame] _bridge];
bdakin's avatar
bdakin committed
301 302 303
    
    // Retain the bridge because the stop may release the last reference to it.
    [bridge retain];
mjs's avatar
mjs committed
304
    
trey's avatar
trey committed
305
    if (isComplete) {
bdakin's avatar
bdakin committed
306 307
        // FIXME: Don't want to do this if an entirely new load is going, so should check
        // that both data sources on the frame are either self or nil.
trey's avatar
trey committed
308
        // Can't call [self _bridge] because we might not have commited yet
bdakin's avatar
bdakin committed
309
        [bridge stop];
justing's avatar
justing committed
310 311
        // FIXME: WebKitErrorPlugInWillHandleLoad is a workaround for the cancel we do to prevent loading plugin content twice.  See <rdar://problem/4258008>
        if ([error code] != NSURLErrorCancelled && [error code] != WebKitErrorPlugInWillHandleLoad)
bdakin's avatar
bdakin committed
312
            [bridge handleFallbackContent];
313
    }
mjs's avatar
mjs committed
314
    
bdakin's avatar
bdakin committed
315
    [bridge release];
mjs's avatar
mjs committed
316
    
bdakin's avatar
bdakin committed
317
    [[self webFrame] _receivedMainResourceError:error];
mjs's avatar
mjs committed
318
    [_private->loadState mainReceivedError:error complete:isComplete];
319 320
}

mjs's avatar
mjs committed
321
- (void)_downloadWithLoadingConnection:(NSURLConnection *)connection request:(NSURLRequest *)request response:(NSURLResponse *)r proxy:(WKNSURLConnectionDelegateProxyPtr) proxy
322
{
mjs's avatar
mjs committed
323 324 325 326 327 328 329 330 331 332
    [WebDownload _downloadWithLoadingConnection:connection
                                        request:request
                                       response:r
                                       delegate:[[self _webView] downloadDelegate]
                                          proxy:proxy];
}

- (void)_didFailLoadingWithError:(NSError *)error forResource:(id)identifier
{
    WebView *webView = [self _webView];
333
    
mjs's avatar
mjs committed
334 335 336 337 338
    [webView _completeProgressForIdentifier:identifier];
    
    if (error)
        [[webView _resourceLoadDelegateForwarder] webView:webView resource:identifier didFailLoadingWithError:error fromDataSource:self];
}
339

mjs's avatar
mjs committed
340 341 342 343 344 345 346 347 348 349
- (void)_didFinishLoadingForResource:(id)identifier
{
    WebView *webView = [self _webView];
    
    [webView _completeProgressForIdentifier:identifier];    
    
    if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidFinishLoadingFromDataSource)
        [[webView resourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:self];
    else
        [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didFinishLoadingFromDataSource:self];
350 351
}

mjs's avatar
mjs committed
352
- (void)_didReceiveData:(NSData *)data contentLength:(int)lengthReceived forResource:(id)identifier
mjs's avatar
mjs committed
353
{
mjs's avatar
mjs committed
354 355 356 357 358 359 360 361
    WebView *webView = [self _webView];
    
    [webView _incrementProgressForIdentifier:identifier data:data];
    
    if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveContentLength)
        [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:self];
    else
        [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveContentLength:(WebNSUInteger)lengthReceived fromDataSource:self];
mjs's avatar
mjs committed
362 363
}

mjs's avatar
mjs committed
364
- (void)_didReceiveResponse:(NSURLResponse *)r forResource:(id)identifier
mjs's avatar
mjs committed
365 366
{
    WebView *webView = [self _webView];
mjs's avatar
mjs committed
367 368 369 370 371 372 373 374 375 376
    
    [self _addResponse:r];
    
    [webView _incrementProgressForIdentifier:identifier response:r];
    
    if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveResponse)
        [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:self];
    else
        [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveResponse:r fromDataSource:self];
}
mjs's avatar
mjs committed
377

mjs's avatar
mjs committed
378 379 380 381 382 383
- (void)_didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier
{
    WebView *webView = [self _webView];
    
    if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidCancelAuthenticationChallenge)
        [[webView resourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:self];
mjs's avatar
mjs committed
384
    else
mjs's avatar
mjs committed
385
        [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didCancelAuthenticationChallenge:currentWebChallenge fromDataSource:self];
mjs's avatar
mjs committed
386 387
}

mjs's avatar
mjs committed
388
- (void)_didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)currentWebChallenge forResource:(id)identifier
mjs's avatar
mjs committed
389 390
{
    WebView *webView = [self _webView];
mjs's avatar
mjs committed
391 392 393 394 395 396
    
    if ([webView _resourceLoadDelegateImplementations].delegateImplementsDidReceiveAuthenticationChallenge)
        [[webView resourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:self];
    else
        [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier didReceiveAuthenticationChallenge:currentWebChallenge fromDataSource:self];
}
mjs's avatar
mjs committed
397

mjs's avatar
mjs committed
398 399 400 401
- (NSURLRequest *)_willSendRequest:(NSMutableURLRequest *)clientRequest forResource:(id)identifier redirectResponse:(NSURLResponse *)redirectResponse
{
    WebView *webView = [self _webView];
    
mjs's avatar
mjs committed
402
    [clientRequest _web_setHTTPUserAgent:[webView userAgentForURL:[clientRequest URL]]];
mjs's avatar
mjs committed
403
    
mjs's avatar
mjs committed
404 405 406 407 408 409
    if ([webView _resourceLoadDelegateImplementations].delegateImplementsWillSendRequest)
        return [[webView resourceLoadDelegate] webView:webView resource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDataSource:self];
    else
        return [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView resource:identifier willSendRequest:clientRequest redirectResponse:redirectResponse fromDataSource:self];
}        

mjs's avatar
mjs committed
410
- (id)_identifierForInitialRequest:(NSURLRequest *)clientRequest
mjs's avatar
mjs committed
411 412
{
    WebView *webView = [self _webView];
mjs's avatar
mjs committed
413 414 415 416 417 418 419 420
    
    // The identifier is released after the last callback, rather than in dealloc
    // to avoid potential cycles.
    if ([webView _resourceLoadDelegateImplementations].delegateImplementsIdentifierForRequest)
        return [[[webView resourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:self] retain];
    else
        return [[[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:webView identifierForInitialRequest:clientRequest fromDataSource:self] retain];
}
mjs's avatar
mjs committed
421

mjs's avatar
mjs committed
422 423 424 425 426 427 428 429 430
- (WebResource *)_archivedSubresourceForURL:(NSURL *)URL
{
    return [_private->unarchivingState archivedResourceForURL:URL];
}

- (void)_startLoading
{
    [self _prepareForLoadStart];
    
mjs's avatar
mjs committed
431
    if ([[_private->loadState frameLoader] isLoadingMainResource])
mjs's avatar
mjs committed
432 433 434 435 436 437 438
        return;
    
    _private->loadingFromPageCache = NO;
    
    id identifier;
    id resourceLoadDelegate = [[self _webView] resourceLoadDelegate];
    if ([resourceLoadDelegate respondsToSelector:@selector(webView:identifierForInitialRequest:fromDataSource:)])
mjs's avatar
mjs committed
439
        identifier = [resourceLoadDelegate webView:[self _webView] identifierForInitialRequest:[_private->loadState originalRequest] fromDataSource:self];
mjs's avatar
mjs committed
440
    else
mjs's avatar
mjs committed
441
        identifier = [[WebDefaultResourceLoadDelegate sharedResourceLoadDelegate] webView:[self _webView] identifierForInitialRequest:[_private->loadState originalRequest] fromDataSource:self];
mjs's avatar
mjs committed
442
    
mjs's avatar
mjs committed
443 444
    if (![[_private->loadState frameLoader] startLoadingMainResourceWithRequest:[_private->loadState request] identifier:identifier])
        [_private->loadState updateLoading];
mjs's avatar
mjs committed
445 446
}

mjs's avatar
mjs committed
447 448 449 450
- (void)_stopRecordingResponses
{
    _private->stopRecordingResponses = YES;
}
mjs's avatar
mjs committed
451

mjs's avatar
mjs committed
452
- (double)_loadingStartedTime
mjs's avatar
mjs committed
453
{
mjs's avatar
mjs committed
454 455
    return _private->loadingStartedTime;
}
mjs's avatar
mjs committed
456

mjs's avatar
mjs committed
457 458 459 460 461
- (void)_replaceSelectionWithArchive:(WebArchive *)archive selectReplacement:(BOOL)selectReplacement
{
    DOMDocumentFragment *fragment = [self _documentFragmentWithArchive:archive];
    if (fragment)
        [[self _bridge] replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:NO matchStyle:NO];
mjs's avatar
mjs committed
462 463
}

mjs's avatar
mjs committed
464
- (DOMDocumentFragment *)_documentFragmentWithArchive:(WebArchive *)archive
mjs's avatar
mjs committed
465
{
mjs's avatar
mjs committed
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
    ASSERT(archive);
    WebResource *mainResource = [archive mainResource];
    if (mainResource) {
        NSString *MIMEType = [mainResource MIMEType];
        if ([WebView canShowMIMETypeAsHTML:MIMEType]) {
            NSString *markupString = [[NSString alloc] initWithData:[mainResource data] encoding:NSUTF8StringEncoding];
            // FIXME: seems poor form to do this as a side effect of getting a document fragment
            [self _addToUnarchiveState:archive];
            DOMDocumentFragment *fragment = [[self _bridge] documentFragmentWithMarkupString:markupString baseURLString:[[mainResource URL] _web_originalDataAsString]];
            [markupString release];
            return fragment;
        } else if ([[WebFrameBridge supportedImageResourceMIMETypes] containsObject:MIMEType]) {
            return [self _documentFragmentWithImageResource:mainResource];
            
        }
    }
    return nil;
}
mjs's avatar
mjs committed
484

mjs's avatar
mjs committed
485 486 487 488 489 490 491 492 493
- (DOMDocumentFragment *)_documentFragmentWithImageResource:(WebResource *)resource
{
    DOMElement *imageElement = [self _imageElementWithImageResource:resource];
    if (!imageElement)
        return 0;
    DOMDocumentFragment *fragment = [[[self _bridge] DOMDocument] createDocumentFragment];
    [fragment appendChild:imageElement];
    return fragment;
}
mjs's avatar
mjs committed
494

mjs's avatar
mjs committed
495 496 497 498 499 500 501 502 503 504 505
- (DOMElement *)_imageElementWithImageResource:(WebResource *)resource
{
    if (!resource)
        return 0;
    
    [self addSubresource:resource];
    
    DOMElement *imageElement = [[[self _bridge] DOMDocument] createElement:@"img"];
    
    // FIXME: calling _web_originalDataAsString on a file URL returns an absolute path. Workaround this.
    NSURL *URL = [resource URL];
506
    [imageElement setAttribute:@"src" value:[URL isFileURL] ? [URL absoluteString] : [URL _web_originalDataAsString]];
mjs's avatar
mjs committed
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
    
    return imageElement;
}

- (NSString *)_title
{
    return _private->pageTitle;
}

// May return nil if not initialized with a URL.
- (NSURL *)_URL
{
    return [[self request] URL];
}

- (void)_loadFromPageCache:(NSDictionary *)pageCache
{
    [self _prepareForLoadStart];
    _private->loadingFromPageCache = YES;
mjs's avatar
mjs committed
526
    [_private->loadState setCommitted:YES];
mjs's avatar
mjs committed
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
    [[self webFrame] _commitProvisionalLoad:pageCache];
}

- (WebArchive *)_popSubframeArchiveWithName:(NSString *)frameName
{
    return [_private->unarchivingState popSubframeArchiveWithFrameName:frameName];
}

- (void)_setIsClientRedirect:(BOOL)flag
{
    _private->isClientRedirect = flag;
}

- (void)_setLastCheckedRequest:(NSURLRequest *)request
{
    NSURLRequest *oldRequest = _private->lastCheckedRequest;
    _private->lastCheckedRequest = [request copy];
    [oldRequest release];
}

- (NSURLRequest *)_lastCheckedRequest
{
    // It's OK not to make a copy here because we know the caller
    // isn't going to modify this request
    return [[_private->lastCheckedRequest retain] autorelease];
}

- (WebFrameBridge *)_bridge
mjs's avatar
mjs committed
555
{
mjs's avatar
mjs committed
556
    ASSERT([_private->loadState isCommitted]);
mjs's avatar
mjs committed
557
    return [[self webFrame] _bridge];
mjs's avatar
mjs committed
558 559
}

mjs's avatar
mjs committed
560
- (WebView *)_webView
mjs's avatar
mjs committed
561
{
mjs's avatar
mjs committed
562
    return [[[_private->loadState frameLoader] webFrame] webView];
mjs's avatar
mjs committed
563 564
}

mjs's avatar
mjs committed
565
- (NSDictionary *)_triggeringAction
mjs's avatar
mjs committed
566
{
mjs's avatar
mjs committed
567
    return [[_private->triggeringAction retain] autorelease];
mjs's avatar
mjs committed
568 569
}

mjs's avatar
mjs committed
570
- (void)_setTriggeringAction:(NSDictionary *)action
mjs's avatar
mjs committed
571
{
mjs's avatar
mjs committed
572 573 574
    [action retain];
    [_private->triggeringAction release];
    _private->triggeringAction = action;
mjs's avatar
mjs committed
575 576
}

mjs's avatar
mjs committed
577
- (BOOL)_isDocumentHTML
578
{
mjs's avatar
mjs committed
579 580
    NSString *MIMEType = [[self response] MIMEType];
    return [WebView canShowMIMETypeAsHTML:MIMEType];
581 582
}

mjs's avatar
mjs committed
583
- (void)_stopLoadingWithError:(NSError *)error
584
{
mjs's avatar
mjs committed
585
    [[_private->loadState frameLoader] stopLoadingWithError:error];
586 587
}

mjs's avatar
mjs committed
588
- (void)_setPrimaryLoadComplete:(BOOL)flag
589
{
mjs's avatar
mjs committed
590 591 592
    _private->primaryLoadComplete = flag;
    
    if (flag) {
mjs's avatar
mjs committed
593 594 595
        if ([[_private->loadState frameLoader] isLoadingMainResource]) {
            [_private->loadState setMainResourceData:[[_private->loadState frameLoader] mainResourceData]];
            [[_private->loadState frameLoader] releaseMainResourceLoader];
mjs's avatar
mjs committed
596 597
        }
        
mjs's avatar
mjs committed
598
        [_private->loadState updateLoading];
tomernic's avatar
tomernic committed
599

mjs's avatar
mjs committed
600 601 602
        if ([WebScriptDebugServer listenerCount])
            [[WebScriptDebugServer sharedScriptDebugServer] webView:[[self webFrame] webView] didLoadMainResourceForDataSource:self];
    }
603 604
}

mjs's avatar
mjs committed
605
- (NSArray *)_responses
606
{
mjs's avatar
mjs committed
607
    return _private->responses;
608 609 610 611 612 613 614
}

- (BOOL)_loadingFromPageCache
{
    return _private->loadingFromPageCache;
}

mjs's avatar
mjs committed
615
-(void)_makeRepresentation
616
{
mjs's avatar
mjs committed
617 618 619 620 621 622 623
    Class repClass = [[self class] _representationClassForMIMEType:[[self response] MIMEType]];
    
    // Check if the data source was already bound?
    if (![[self representation] isKindOfClass:repClass]) {
        id newRep = repClass != nil ? [[repClass alloc] init] : nil;
        [self _setRepresentation:(id <WebDocumentRepresentation>)newRep];
        [newRep release];
624
    }
mjs's avatar
mjs committed
625 626
    
    [_private->representation setDataSource:self];
627 628
}

mjs's avatar
mjs committed
629
- (BOOL)_isClientRedirect
630
{
mjs's avatar
mjs committed
631
    return _private->isClientRedirect;
632 633
}

mjs's avatar
mjs committed
634
- (NSURL *)_URLForHistory
635
{
mjs's avatar
mjs committed
636 637 638
    // Return the URL to be used for history and B/F list.
    // Returns nil for WebDataProtocol URLs that aren't alternates 
    // for unreachable URLs, because these can't be stored in history.
mjs's avatar
mjs committed
639 640 641
    NSURL *URL = [[_private->loadState originalRequestCopy] URL];
    if ([WebDataProtocol _webIsDataProtocolURL:URL])
        URL = [[_private->loadState originalRequestCopy] _webDataRequestUnreachableURL];
mjs's avatar
mjs committed
642 643
    
    return [URL _webkit_canonicalize];
644 645
}

mjs's avatar
mjs committed
646
- (void)_addToUnarchiveState:(WebArchive *)archive
647
{
mjs's avatar
mjs committed
648 649 650
    if (!_private->unarchivingState)
        _private->unarchivingState = [[WebUnarchivingState alloc] init];
    [_private->unarchivingState addArchive:archive];
651 652
}

mjs's avatar
mjs committed
653
- (void)_setOverrideEncoding:(NSString *)overrideEncoding
654
{
mjs's avatar
mjs committed
655 656 657
    NSString *copy = [overrideEncoding copy];
    [_private->overrideEncoding release];
    _private->overrideEncoding = copy;
658 659
}

mjs's avatar
mjs committed
660
- (NSString *)_overrideEncoding
justing's avatar
justing committed
661
{
mjs's avatar
mjs committed
662
    return [[_private->overrideEncoding copy] autorelease];
justing's avatar
justing committed
663 664
}

mjs's avatar
mjs committed
665
- (void)_setTitle:(NSString *)title
justing's avatar
justing committed
666
{
mjs's avatar
mjs committed
667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683
    NSString *trimmed;
    if (title == nil) {
        trimmed = nil;
    } else {
        trimmed = [title _webkit_stringByTrimmingWhitespace];
        if ([trimmed length] == 0)
            trimmed = nil;
    }
    if (trimmed == nil) {
        if (_private->pageTitle == nil)
            return;
    } else {
        if ([_private->pageTitle isEqualToString:trimmed])
            return;
    }
    
    if (!trimmed || [trimmed length] == 0)
justing's avatar
justing committed
684 685
        return;
    
mjs's avatar
mjs committed
686 687 688 689
    [[self _webView] _willChangeValueForKey:_WebMainFrameTitleKey];
    [_private->pageTitle release];
    _private->pageTitle = [trimmed copy];
    [[self _webView] _didChangeValueForKey:_WebMainFrameTitleKey];
justing's avatar
justing committed
690
    
mjs's avatar
mjs committed
691
    // The title doesn't get communicated to the WebView until we are committed.
mjs's avatar
mjs committed
692
    if ([_private->loadState isCommitted]) {
mjs's avatar
mjs committed
693 694 695 696 697 698 699 700 701 702 703 704 705 706
        NSURL *URLForHistory = [self _URLForHistory];
        if (URLForHistory != nil) {
            WebHistoryItem *entry = [[WebHistory optionalSharedHistory] itemForURL:URLForHistory];
            [entry setTitle: _private->pageTitle];
            
            // Must update the entries in the back-forward list too.  This must go through the WebFrame because
            // it has the right notion of the current b/f item.
            [[self webFrame] _setTitle:_private->pageTitle];
            
            [[self _webView] setMainFrameDocumentReady:YES];    // update observers with new DOMDocument
            [[[self _webView] _frameLoadDelegateForwarder] webView:[self _webView]
                                                   didReceiveTitle:_private->pageTitle
                                                          forFrame:[self webFrame]];
        }
justing's avatar
justing committed
707
    }
mjs's avatar
mjs committed
708 709
}

mjs's avatar
mjs committed
710 711 712 713
- (WebDocumentLoadState *)_documentLoadState
{
    return _private->loadState;
}
714

mjs's avatar
mjs committed
715
- (id)_initWithDocumentLoadState:(WebDocumentLoadStateMac *)loadState
716
{
darin's avatar
darin committed
717 718 719 720 721
    self = [super init];
    if (!self) {
        return nil;
    }
    
darin's avatar
darin committed
722
    _private = [[WebDataSourcePrivate alloc] init];
mjs's avatar
mjs committed
723
    
mjs's avatar
mjs committed
724
    _private->loadState = [loadState retain];
mjs's avatar
mjs committed
725 726 727
        
    LOG(Loading, "creating datasource for %@", [[_private->loadState request] URL]);
    WKSupportsMultipartXMixedReplace([_private->loadState request]);
mjs's avatar
mjs committed
728
    
darin's avatar
darin committed
729 730
    ++WebDataSourceCount;
    
731
    return self;
mjs's avatar
mjs committed
732 733 734 735 736 737 738 739 740 741
    
}

@end

@implementation WebDataSource

-(id)initWithRequest:(NSURLRequest *)request
{
    return [self _initWithDocumentLoadState:[[WebDocumentLoadState alloc] initWithRequest:request]];
742 743
}

744 745
- (void)dealloc
{
mjs's avatar
mjs committed
746
    ASSERT([[_private->loadState frameLoader] activeDataSource] != self || ![[_private->loadState frameLoader] isLoading]);
mjs's avatar
mjs committed
747

darin's avatar
darin committed
748 749
    --WebDataSourceCount;
    
750
    [_private release];
darin's avatar
darin committed
751
    
rjw's avatar
rjw committed
752
    [super dealloc];
753
}
754

755 756 757 758 759 760 761
- (void)finalize
{
    --WebDataSourceCount;

    [super finalize];
}

cblu's avatar
 
cblu committed
762 763
- (NSData *)data
{
mjs's avatar
mjs committed
764
    return [_private->loadState mainResourceData];
cblu's avatar
 
cblu committed
765 766
}

mjs's avatar
mjs committed
767
- (id <WebDocumentRepresentation>)representation
cblu's avatar
 
cblu committed
768 769 770
{
    return _private->representation;
}
771

darin's avatar
darin committed
772
- (WebFrame *)webFrame
cblu's avatar
cblu committed
773
{
mjs's avatar
mjs committed
774
    return [[_private->loadState frameLoader] webFrame];
cblu's avatar
cblu committed
775 776
}

kocienda's avatar
Tests:  
kocienda committed
777
-(NSURLRequest *)initialRequest
rjw's avatar
WebKit:  
rjw committed
778
{
mjs's avatar
mjs committed
779
    NSURLRequest *clientRequest = [[_private->loadState originalRequest] _webDataRequestExternalRequest];
rjw's avatar
WebKit:  
rjw committed
780
    if (!clientRequest)
mjs's avatar
mjs committed
781
        clientRequest = [_private->loadState originalRequest];
rjw's avatar
WebKit:  
rjw committed
782
    return clientRequest;
rjw's avatar
WebKit:  
rjw committed
783 784
}

kocienda's avatar
kocienda committed
785
-(NSMutableURLRequest *)request
kocienda's avatar
kocienda committed
786
{
mjs's avatar
mjs committed
787
    return [_private->loadState request];
kocienda's avatar
kocienda committed
788
}
789

kocienda's avatar
Tests:  
kocienda committed
790
- (NSURLResponse *)response
cblu's avatar
WebKit:  
cblu committed
791
{
mjs's avatar
mjs committed
792
    return [_private->loadState response];
cblu's avatar
WebKit:  
cblu committed
793 794
}

rjw's avatar
rjw committed
795 796 797 798
- (NSString *)textEncodingName
{
    NSString *textEncodingName = [self _overrideEncoding];

mjs's avatar
mjs committed
799
    if (!textEncodingName)
rjw's avatar
rjw committed
800
        textEncodingName = [[self response] textEncodingName];
mjs's avatar
mjs committed
801

rjw's avatar
rjw committed
802 803 804
    return textEncodingName;
}

805 806 807
// Returns YES if there are any pending loads.
- (BOOL)isLoading
{
darin's avatar
darin committed
808 809
    // Once a frame has loaded, we no longer need to consider subresources,
    // but we still need to consider subframes.
mjs's avatar
mjs committed
810
    if ([[[self webFrame] _frameLoader] state] != WebFrameStateComplete) {
mjs's avatar
mjs committed
811
        if (!_private->primaryLoadComplete && [_private->loadState isLoading])
darin's avatar
darin committed
812
            return YES;
mjs's avatar
mjs committed
813
        if ([[_private->loadState frameLoader] isLoadingSubresources])
darin's avatar
darin committed
814
            return YES;
815 816
        if (![[[self webFrame] _bridge] doneProcessingData])
            return YES;
darin's avatar
darin committed
817
    }
818

mjs's avatar
mjs committed
819
    return [[self webFrame] _subframeIsLoading];
820 821 822 823 824
}

// Returns nil or the page title.
- (NSString *)pageTitle
{
825
    return [[self representation] title];
826 827
}

sullivan's avatar
WebKit:  
sullivan committed
828 829
- (NSURL *)unreachableURL
{
mjs's avatar
mjs committed
830
    return [[_private->loadState originalRequest] _webDataRequestUnreachableURL];
sullivan's avatar
WebKit:  
sullivan committed
831 832
}

cblu's avatar
cblu committed
833 834
- (WebArchive *)webArchive
{
mjs's avatar
mjs committed
835
    // it makes no sense to grab a WebArchive from an uncommitted document.
mjs's avatar
mjs committed
836
    if (![_private->loadState isCommitted])
mjs's avatar
mjs committed
837 838
        return nil;

mjs's avatar
mjs committed
839
    return [WebArchiver archiveFrame:[self webFrame]];
cblu's avatar
cblu committed
840 841 842 843 844 845 846 847 848 849 850 851 852 853
}

- (WebResource *)mainResource
{
    NSURLResponse *response = [self response];
    return [[[WebResource alloc] initWithData:[self data]
                                          URL:[response URL] 
                                     MIMEType:[response MIMEType]
                             textEncodingName:[response textEncodingName]
                                    frameName:[[self webFrame] name]] autorelease];
}

- (NSArray *)subresources
{
mjs's avatar
mjs committed
854 855 856 857 858 859 860 861 862 863 864 865
    NSArray *datas;
    NSArray *responses;
    [[self _bridge] getAllResourceDatas:&datas andResponses:&responses];
    ASSERT([datas count] == [responses count]);

    NSMutableArray *subresources = [[NSMutableArray alloc] initWithCapacity:[datas count]];
    for (unsigned i = 0; i < [datas count]; ++i) {
        NSURLResponse *response = [responses objectAtIndex:i];
        [subresources addObject:[[[WebResource alloc] _initWithData:[datas objectAtIndex:i] URL:[response URL] response:response] autorelease]];
    }

    return [subresources autorelease];
cblu's avatar
cblu committed
866 867 868 869
}

- (WebResource *)subresourceForURL:(NSURL *)URL
{
mjs's avatar
mjs committed
870 871 872 873
    NSData *data;
    NSURLResponse *response;
    if (![[self _bridge] getData:&data andResponse:&response forURL:URL])
        return nil;
mjs's avatar
mjs committed
874

mjs's avatar
mjs committed
875
    return [[[WebResource alloc] _initWithData:data URL:URL response:response] autorelease];
cblu's avatar
cblu committed
876 877 878 879
}

- (void)addSubresource:(WebResource *)subresource
{
mjs's avatar
mjs committed
880 881 882 883 884
    if (subresource) {
        if (!_private->unarchivingState)
            _private->unarchivingState = [[WebUnarchivingState alloc] init];
        [_private->unarchivingState addResource:subresource];
    }
cblu's avatar
cblu committed
885 886
}

887
@end