Fixed:
authorcblu <cblu@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 4 May 2005 18:50:56 +0000 (18:50 +0000)
committercblu <cblu@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 4 May 2005 18:50:56 +0000 (18:50 +0000)
<rdar://problem/4078417> REGRESSION (125-412): MLB gameday page doesn't update (Flash)
<rdar://problem/4072280> XMLHttpRequest calls onReadyStateChange callback with bogus status value

Reviewed by john.

Our WebKit-level caching of subresources "dumbed-down" information held in NSURLResponse. This caused some loads to lack response headers and thus disabling cache directives. Status codes were also not retained and this caused XMLHttpRequest to fail frequently. The fix is to have WebResource retain the NSURLResponse and to use the NSURLResponse when we decide to load from WebResources.

        * WebCoreSupport.subproj/WebBridge.m:
        (-[WebBridge objectLoadedFromCacheWithURL:response:data:]): call new [WebResource _initWithData:URL:response:]
        * WebView.subproj/WebBaseResourceHandleDelegate.m:
        (-[WebBaseResourceHandleDelegate _canUseResourceWithResponse:]): new, checks response cache directives
        (-[WebBaseResourceHandleDelegate loadWithRequest:]): call _canUseResourceWithResponse:
        (-[WebBaseResourceHandleDelegate saveResource]): call new [WebResource _initWithData:URL:response:]
        * WebView.subproj/WebResource.m:
        (-[WebResourcePrivate dealloc]):
        (-[WebResource initWithData:URL:MIMEType:textEncodingName:frameName:]): call renamed _initWithData:URL:MIMEType:textEncodingName:frameName:response:copyData:
        (-[WebResource initWithCoder:]): decode the NSURLReponse
        (-[WebResource encodeWithCoder:]): encode the NSURLReponse
        (-[WebResource _initWithData:URL:MIMEType:textEncodingName:frameName:response:copyData:]): take the NSURLReponse
        (-[WebResource _initWithData:URL:response:]): new
        (-[WebResource _initWithPropertyList:]): decode the NSURLReponse
        (-[WebResource _propertyListRepresentation]): encode the NSURLReponse
        (-[WebResource _response]): return ivar if we have one
        * WebView.subproj/WebResourcePrivate.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@9104 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebKit/ChangeLog
WebKit/WebCoreSupport.subproj/WebBridge.m
WebKit/WebView.subproj/WebBaseResourceHandleDelegate.m
WebKit/WebView.subproj/WebLoader.m
WebKit/WebView.subproj/WebResource.m
WebKit/WebView.subproj/WebResourcePrivate.h

index 74259217e22f9c022ab7498ef598eff74dccd12f..a9b5887deb3596dc99773ca2c03b501e157348c4 100644 (file)
@@ -1,3 +1,31 @@
+2005-05-04  Chris Blumenberg  <cblu@apple.com>
+
+       Fixed: 
+       <rdar://problem/4078417> REGRESSION (125-412): MLB gameday page doesn't update (Flash)
+       <rdar://problem/4072280> XMLHttpRequest calls onReadyStateChange callback with bogus status value
+        
+       Reviewed by john.
+
+       Our WebKit-level caching of subresources "dumbed-down" information held in NSURLResponse. This caused some loads to lack response headers and thus disabling cache directives. Status codes were also not retained and this caused XMLHttpRequest to fail frequently. The fix is to have WebResource retain the NSURLResponse and to use the NSURLResponse when we decide to load from WebResources.
+
+        * WebCoreSupport.subproj/WebBridge.m:
+        (-[WebBridge objectLoadedFromCacheWithURL:response:data:]): call new [WebResource _initWithData:URL:response:]
+        * WebView.subproj/WebBaseResourceHandleDelegate.m:
+        (-[WebBaseResourceHandleDelegate _canUseResourceWithResponse:]): new, checks response cache directives
+        (-[WebBaseResourceHandleDelegate loadWithRequest:]): call _canUseResourceWithResponse:
+        (-[WebBaseResourceHandleDelegate saveResource]): call new [WebResource _initWithData:URL:response:]
+        * WebView.subproj/WebResource.m:
+        (-[WebResourcePrivate dealloc]):
+        (-[WebResource initWithData:URL:MIMEType:textEncodingName:frameName:]): call renamed _initWithData:URL:MIMEType:textEncodingName:frameName:response:copyData:
+        (-[WebResource initWithCoder:]): decode the NSURLReponse
+        (-[WebResource encodeWithCoder:]): encode the NSURLReponse
+        (-[WebResource _initWithData:URL:MIMEType:textEncodingName:frameName:response:copyData:]): take the NSURLReponse
+        (-[WebResource _initWithData:URL:response:]): new
+        (-[WebResource _initWithPropertyList:]): decode the NSURLReponse
+        (-[WebResource _propertyListRepresentation]): encode the NSURLReponse
+        (-[WebResource _response]): return ivar if we have one
+        * WebView.subproj/WebResourcePrivate.h:
+
 2005-05-03  David Hyatt  <hyatt@apple.com>
 
        Fix object element support so that fallback content works.  With this change Safari passes the Acid2 test.
index 997f70119e431bdff9b2dbe95cf5529c8b2c047c..65b1cedebb85132b5a5eac5de212c4f3a274ce27 100644 (file)
@@ -458,14 +458,7 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
 
 - (void)objectLoadedFromCacheWithURL:(NSURL *)URL response:(NSURLResponse *)response data:(NSData *)data
 {
-    // Pass NO for copyData since the data doesn't need to be copied since it won't be modified. 
-    // Copying it will also cause a performance regression. 
-    WebResource *resource = [[WebResource alloc] _initWithData:data
-                                                           URL:URL
-                                                      MIMEType:[response MIMEType]
-                                              textEncodingName:[response textEncodingName]
-                                                     frameName:nil
-                                                      copyData:NO];
+    WebResource *resource = [[WebResource alloc] _initWithData:data URL:URL response:response];
     ASSERT(resource != nil);
     [[self dataSource] addSubresource:resource];
     [resource release];
index 67a043042137712d067061ba42a595c06f483750..950ee5c652aca9c8fe2a6925c9671a2d6d1f5383 100644 (file)
@@ -164,7 +164,7 @@ static BOOL NSURLConnectionSupportsBufferedData;
     }
 }
 
-// This is copied from [NSHTTPURLProtocol _cachedResponsePassesValidityChecks] and modified for our needs.
+// The following 2 methods are copied from [NSHTTPURLProtocol _cachedResponsePassesValidityChecks] and modified for our needs.
 // FIXME: It would be nice to eventually to share this code somehow.
 - (BOOL)_canUseResourceForRequest:(NSURLRequest *)theRequest
 {
@@ -191,6 +191,17 @@ static BOOL NSURLConnectionSupportsBufferedData;
     }
 }
 
+- (BOOL)_canUseResourceWithResponse:(NSURLResponse *)theResponse
+{
+    if ([theResponse _mustRevalidate]) {
+        return NO;
+    } else if ([theResponse _calculatedExpiration] - CFAbsoluteTimeGetCurrent() < 1) {
+        return NO;
+    } else {
+        return YES;
+    }
+}
+
 - (BOOL)loadWithRequest:(NSURLRequest *)r
 {
     ASSERT(connection == nil);
@@ -215,11 +226,15 @@ static BOOL NSURLConnectionSupportsBufferedData;
     
     if ([[r URL] isEqual:originalURL] && [self _canUseResourceForRequest:r]) {
         resource = [dataSource subresourceForURL:originalURL];
-        if (resource) {
-            [resource retain];
-            // Deliver the resource after a delay because callers don't expect to receive callbacks while calling this method.
-            [self deliverResourceAfterDelay];
-            return YES;
+        if (resource != nil) {
+            if ([self _canUseResourceWithResponse:[resource _response]]) {
+                [resource retain];
+                // Deliver the resource after a delay because callers don't expect to receive callbacks while calling this method.
+                [self deliverResourceAfterDelay];
+                return YES;
+            } else {
+                resource = nil;
+            }
         }
     }
     
@@ -305,15 +320,9 @@ static BOOL NSURLConnectionSupportsBufferedData;
     if (resource == nil) {
         NSData *data = [self resourceData];
         if ([data length] > 0) {
-            // Don't have WebResource copy the data since the data is a NSMutableData that we know won't get modified. 
             ASSERT(originalURL);
             ASSERT([response MIMEType]);
-            WebResource *newResource = [[WebResource alloc] _initWithData:data
-                                                                      URL:originalURL
-                                                                 MIMEType:[response MIMEType]
-                                                         textEncodingName:[response textEncodingName]
-                                                                frameName:nil
-                                                                 copyData:NO];
+            WebResource *newResource = [[WebResource alloc] _initWithData:data URL:originalURL response:response];
             if (newResource != nil) {
                 [dataSource addSubresource:newResource];
                 [newResource release];
index 67a043042137712d067061ba42a595c06f483750..950ee5c652aca9c8fe2a6925c9671a2d6d1f5383 100644 (file)
@@ -164,7 +164,7 @@ static BOOL NSURLConnectionSupportsBufferedData;
     }
 }
 
-// This is copied from [NSHTTPURLProtocol _cachedResponsePassesValidityChecks] and modified for our needs.
+// The following 2 methods are copied from [NSHTTPURLProtocol _cachedResponsePassesValidityChecks] and modified for our needs.
 // FIXME: It would be nice to eventually to share this code somehow.
 - (BOOL)_canUseResourceForRequest:(NSURLRequest *)theRequest
 {
@@ -191,6 +191,17 @@ static BOOL NSURLConnectionSupportsBufferedData;
     }
 }
 
+- (BOOL)_canUseResourceWithResponse:(NSURLResponse *)theResponse
+{
+    if ([theResponse _mustRevalidate]) {
+        return NO;
+    } else if ([theResponse _calculatedExpiration] - CFAbsoluteTimeGetCurrent() < 1) {
+        return NO;
+    } else {
+        return YES;
+    }
+}
+
 - (BOOL)loadWithRequest:(NSURLRequest *)r
 {
     ASSERT(connection == nil);
@@ -215,11 +226,15 @@ static BOOL NSURLConnectionSupportsBufferedData;
     
     if ([[r URL] isEqual:originalURL] && [self _canUseResourceForRequest:r]) {
         resource = [dataSource subresourceForURL:originalURL];
-        if (resource) {
-            [resource retain];
-            // Deliver the resource after a delay because callers don't expect to receive callbacks while calling this method.
-            [self deliverResourceAfterDelay];
-            return YES;
+        if (resource != nil) {
+            if ([self _canUseResourceWithResponse:[resource _response]]) {
+                [resource retain];
+                // Deliver the resource after a delay because callers don't expect to receive callbacks while calling this method.
+                [self deliverResourceAfterDelay];
+                return YES;
+            } else {
+                resource = nil;
+            }
         }
     }
     
@@ -305,15 +320,9 @@ static BOOL NSURLConnectionSupportsBufferedData;
     if (resource == nil) {
         NSData *data = [self resourceData];
         if ([data length] > 0) {
-            // Don't have WebResource copy the data since the data is a NSMutableData that we know won't get modified. 
             ASSERT(originalURL);
             ASSERT([response MIMEType]);
-            WebResource *newResource = [[WebResource alloc] _initWithData:data
-                                                                      URL:originalURL
-                                                                 MIMEType:[response MIMEType]
-                                                         textEncodingName:[response textEncodingName]
-                                                                frameName:nil
-                                                                 copyData:NO];
+            WebResource *newResource = [[WebResource alloc] _initWithData:data URL:originalURL response:response];
             if (newResource != nil) {
                 [dataSource addSubresource:newResource];
                 [newResource release];
index 285d28a5524e031a6cb98cde62d13b7d61719d2f..c5ff886c40ae5d0056fd626633196606204d6a9b 100644 (file)
@@ -14,6 +14,7 @@ NSString *WebResourceFrameNameKey =         @"WebResourceFrameName";
 NSString *WebResourceMIMETypeKey =          @"WebResourceMIMEType";
 NSString *WebResourceURLKey =               @"WebResourceURL";
 NSString *WebResourceTextEncodingNameKey =  @"WebResourceTextEncodingName";
+NSString *WebResourceResponseKey =          @"WebResourceResponse";
 
 #define WebResourceVersion 1
 
@@ -25,6 +26,7 @@ NSString *WebResourceTextEncodingNameKey =  @"WebResourceTextEncodingName";
     NSString *frameName;
     NSString *MIMEType;
     NSString *textEncodingName;
+    NSURLResponse *response;
 }
 @end
 
@@ -37,6 +39,7 @@ NSString *WebResourceTextEncodingNameKey =  @"WebResourceTextEncodingName";
     [frameName release];
     [MIMEType release];
     [textEncodingName release];
+    [response release];
     [super dealloc];
 }
 
@@ -53,7 +56,7 @@ NSString *WebResourceTextEncodingNameKey =  @"WebResourceTextEncodingName";
 
 - (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 copyData:YES];
+    return [self _initWithData:data URL:URL MIMEType:MIMEType textEncodingName:textEncodingName frameName:frameName response:nil copyData:YES];
 }
 
 - (id)initWithCoder:(NSCoder *)decoder
@@ -65,6 +68,7 @@ NSString *WebResourceTextEncodingNameKey =  @"WebResourceTextEncodingName";
         _private->MIMEType = [[decoder decodeObjectForKey:WebResourceMIMETypeKey] retain];
         _private->textEncodingName = [[decoder decodeObjectForKey:WebResourceTextEncodingNameKey] retain];
         _private->frameName = [[decoder decodeObjectForKey:WebResourceFrameNameKey] retain];
+        _private->response = [[decoder decodeObjectForKey:WebResourceResponseKey] retain];
     NS_HANDLER
         [self release];
         return nil;
@@ -78,7 +82,8 @@ NSString *WebResourceTextEncodingNameKey =  @"WebResourceTextEncodingName";
     [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->frameName forKey:WebResourceFrameNameKey];
+    [encoder encodeObject:_private->response forKey:WebResourceResponseKey];
 }
 
 - (void)dealloc
@@ -155,7 +160,13 @@ NSString *WebResourceTextEncodingNameKey =  @"WebResourceTextEncodingName";
     return propertyLists;
 }
 
-- (id)_initWithData:(NSData *)data URL:(NSURL *)URL MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)textEncodingName frameName:(NSString *)frameName copyData:(BOOL)copyData
+- (id)_initWithData:(NSData *)data 
+                URL:(NSURL *)URL 
+           MIMEType:(NSString *)MIMEType 
+   textEncodingName:(NSString *)textEncodingName 
+          frameName:(NSString *)frameName 
+           response:(NSURLResponse *)response
+           copyData:(BOOL)copyData
 {
     [self init];    
     
@@ -179,23 +190,49 @@ NSString *WebResourceTextEncodingNameKey =  @"WebResourceTextEncodingName";
     
     _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 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];
+        response = [unarchiver decodeObjectForKey:WebResourceResponseKey];
+        [unarchiver finishDecoding];
+        [unarchiver release];    
+    }
+
     NSData *data = [propertyList objectForKey:WebResourceDataKey];
     NSString *URLString = [propertyList _web_stringForKey:WebResourceURLKey];
-    return [self initWithData:[data isKindOfClass:[NSData class]] ? data : nil
-                          URL:URLString ? [NSURL _web_URLWithDataAsString:URLString] : nil
-                     MIMEType:[propertyList _web_stringForKey:WebResourceMIMETypeKey]
-             textEncodingName:[propertyList _web_stringForKey:WebResourceTextEncodingNameKey]
-                    frameName:[propertyList _web_stringForKey:WebResourceFrameNameKey]];
+    return [self _initWithData:[data isKindOfClass:[NSData class]] ? data : nil
+                           URL:URLString ? [NSURL _web_URLWithDataAsString:URLString] : nil
+                      MIMEType:[propertyList _web_stringForKey:WebResourceMIMETypeKey]
+              textEncodingName:[propertyList _web_stringForKey:WebResourceTextEncodingNameKey]
+                     frameName:[propertyList _web_stringForKey:WebResourceFrameNameKey]
+                      response:response
+                      copyData:NO];
 }
 
 - (NSFileWrapper *)_fileWrapperRepresentation
@@ -211,17 +248,29 @@ NSString *WebResourceTextEncodingNameKey =  @"WebResourceTextEncodingName";
     [propertyList setObject:_private->data forKey:WebResourceDataKey];
     [propertyList setObject:[_private->URL _web_originalDataAsString] forKey:WebResourceURLKey];
     [propertyList setObject:_private->MIMEType forKey:WebResourceMIMETypeKey];
-    if (_private->textEncodingName) {
+    if (_private->textEncodingName != nil) {
         [propertyList setObject:_private->textEncodingName forKey:WebResourceTextEncodingNameKey];
     }
-    if (_private->frameName) {
+    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]
@@ -240,4 +289,3 @@ NSString *WebResourceTextEncodingNameKey =  @"WebResourceTextEncodingName";
 }
 
 @end
-
index f2df9576984ab81a7cd7ea463e648adf159b453d..81296b876b484a88e0a3c86c171eeda0e7c57f86 100644 (file)
@@ -9,7 +9,15 @@
 
 @interface WebResource (WebResourcePrivate)
 
-- (id)_initWithData:(NSData *)data URL:(NSURL *)URL MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)textEncodingName frameName:(NSString *)frameName copyData:(BOOL)copyData;
+- (id)_initWithData:(NSData *)data 
+                URL:(NSURL *)URL 
+           MIMEType:(NSString *)MIMEType 
+   textEncodingName:(NSString *)textEncodingName 
+          frameName:(NSString *)frameName 
+           response:(NSURLResponse *)response
+           copyData:(BOOL)copyData;
+
+- (id)_initWithData:(NSData *)data URL:(NSURL *)URL response:(NSURLResponse *)response;
 
 + (NSArray *)_resourcesFromPropertyLists:(NSArray *)propertyLists;
 + (NSArray *)_propertyListsFromResources:(NSArray *)resources;