1 /* 2 * Copyright (C) 2007, 2011 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 "config.h" 30 #import "ResourceLoadDelegate.h" 31 32 #import "DumpRenderTree.h" 33 #import "LayoutTestController.h" 34 #import <WebKit/WebKit.h> 35 #import <WebKit/WebTypesInternal.h> 36 #import <WebKit/WebDataSourcePrivate.h> 37 #import <wtf/Assertions.h> 38 39 using namespace std; 40 41 @interface NSURL (DRTExtras) 42 - (NSString *)_drt_descriptionSuitableForTestResult; 43 @end 44 45 @interface NSError (DRTExtras) 46 - (NSString *)_drt_descriptionSuitableForTestResult; 47 @end 48 49 @interface NSURLResponse (DRTExtras) 50 - (NSString *)_drt_descriptionSuitableForTestResult; 51 @end 52 53 @interface NSURLRequest (DRTExtras) 54 - (NSString *)_drt_descriptionSuitableForTestResult; 55 @end 56 57 @implementation NSError (DRTExtras) 58 - (NSString *)_drt_descriptionSuitableForTestResult 59 { 60 NSString *str = [NSString stringWithFormat:@"<NSError domain %@, code %d", [self domain], [self code]]; 61 NSURL *failingURL; 62 63 if ((failingURL = [[self userInfo] objectForKey:@"NSErrorFailingURLKey"])) 64 str = [str stringByAppendingFormat:@", failing URL \"%@\"", [failingURL _drt_descriptionSuitableForTestResult]]; 65 66 str = [str stringByAppendingFormat:@">"]; 67 68 return str; 69 } 70 71 @end 72 73 @implementation NSURL (DRTExtras) 74 75 - (NSString *)_drt_descriptionSuitableForTestResult 76 { 77 if (![self isFileURL]) 78 return [self absoluteString]; 79 80 WebDataSource *dataSource = [mainFrame dataSource]; 81 if (!dataSource) 82 dataSource = [mainFrame provisionalDataSource]; 83 84 NSString *basePath = [[[[dataSource request] URL] path] stringByDeletingLastPathComponent]; 85 86 return [[self path] substringFromIndex:[basePath length] + 1]; 87 } 88 89 @end 90 91 @implementation NSURLResponse (DRTExtras) 92 93 - (NSString *)_drt_descriptionSuitableForTestResult 94 { 95 int statusCode = 0; 96 if ([self isKindOfClass:[NSHTTPURLResponse class]]) 97 statusCode = [(NSHTTPURLResponse *)self statusCode]; 98 return [NSString stringWithFormat:@"<NSURLResponse %@, http status code %i>", [[self URL] _drt_descriptionSuitableForTestResult], statusCode]; 99 } 100 101 @end 102 103 @implementation NSURLRequest (DRTExtras) 104 105 - (NSString *)_drt_descriptionSuitableForTestResult 106 { 107 NSString *httpMethod = [self HTTPMethod]; 108 if (!httpMethod) 109 httpMethod = @"(none)"; 110 return [NSString stringWithFormat:@"<NSURLRequest URL %@, main document URL %@, http method %@>", [[self URL] _drt_descriptionSuitableForTestResult], [[self mainDocumentURL] _drt_descriptionSuitableForTestResult], httpMethod]; 111 } 112 113 @end 114 115 @implementation ResourceLoadDelegate 116 117 - webView: (WebView *)wv identifierForInitialRequest: (NSURLRequest *)request fromDataSource: (WebDataSource *)dataSource 118 { 119 ASSERT([[dataSource webFrame] dataSource] || [[dataSource webFrame] provisionalDataSource]); 120 121 if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) 122 return [[request URL] _drt_descriptionSuitableForTestResult]; 123 124 return @"<unknown>"; 125 } 126 127 -(NSURLRequest *)webView: (WebView *)wv resource:identifier willSendRequest: (NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource 128 { 129 if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) { 130 NSString *string = [NSString stringWithFormat:@"%@ - willSendRequest %@ redirectResponse %@", identifier, [request _drt_descriptionSuitableForTestResult], 131 [redirectResponse _drt_descriptionSuitableForTestResult]]; 132 printf("%s\n", [string UTF8String]); 133 } 134 135 if (!done && !gLayoutTestController->deferMainResourceDataLoad()) { 136 [dataSource _setDeferMainResourceDataLoad:false]; 137 } 138 139 if (!done && gLayoutTestController->willSendRequestReturnsNull()) 140 return nil; 141 142 if (!done && gLayoutTestController->willSendRequestReturnsNullOnRedirect() && redirectResponse) { 143 printf("Returning null for this redirect\n"); 144 return nil; 145 } 146 147 NSURL *url = [request URL]; 148 NSString *host = [url host]; 149 if (host 150 && (NSOrderedSame == [[url scheme] caseInsensitiveCompare:@"http"] || NSOrderedSame == [[url scheme] caseInsensitiveCompare:@"https"]) 151 && NSOrderedSame != [host compare:@"127.0.0.1"] 152 && NSOrderedSame != [host compare:@"255.255.255.255"] // used in some tests that expect to get back an error 153 && NSOrderedSame != [host caseInsensitiveCompare:@"localhost"]) { 154 printf("Blocked access to external URL %s\n", [[url absoluteString] cStringUsingEncoding:NSUTF8StringEncoding]); 155 return nil; 156 } 157 158 if (disallowedURLs && CFSetContainsValue(disallowedURLs, url)) 159 return nil; 160 161 NSMutableURLRequest *newRequest = [request mutableCopy]; 162 const set<string>& clearHeaders = gLayoutTestController->willSendRequestClearHeaders(); 163 for (set<string>::const_iterator header = clearHeaders.begin(); header != clearHeaders.end(); ++header) { 164 NSString *nsHeader = [[NSString alloc] initWithUTF8String:header->c_str()]; 165 [newRequest setValue:nil forHTTPHeaderField:nsHeader]; 166 [nsHeader release]; 167 } 168 const std::string& destination = gLayoutTestController->redirectionDestinationForURL([[url absoluteString] UTF8String]); 169 if (destination.length()) 170 [newRequest setURL:[NSURL URLWithString:[NSString stringWithUTF8String:destination.data()]]]; 171 172 return [newRequest autorelease]; 173 } 174 175 - (void)webView:(WebView *)wv resource:(id)identifier didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource 176 { 177 if (!gLayoutTestController->handlesAuthenticationChallenges()) { 178 NSString *string = [NSString stringWithFormat:@"%@ - didReceiveAuthenticationChallenge - Simulating cancelled authentication sheet", identifier]; 179 printf("%s\n", [string UTF8String]); 180 181 [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge]; 182 return; 183 } 184 185 const char* user = gLayoutTestController->authenticationUsername().c_str(); 186 NSString *nsUser = [NSString stringWithFormat:@"%s", user ? user : ""]; 187 188 const char* password = gLayoutTestController->authenticationPassword().c_str(); 189 NSString *nsPassword = [NSString stringWithFormat:@"%s", password ? password : ""]; 190 191 NSString *string = [NSString stringWithFormat:@"%@ - didReceiveAuthenticationChallenge - Responding with %@:%@", identifier, nsUser, nsPassword]; 192 printf("%s\n", [string UTF8String]); 193 194 [[challenge sender] useCredential:[NSURLCredential credentialWithUser:nsUser password:nsPassword persistence:NSURLCredentialPersistenceForSession] 195 forAuthenticationChallenge:challenge]; 196 } 197 198 - (void)webView:(WebView *)wv resource:(id)identifier didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge fromDataSource:(WebDataSource *)dataSource 199 { 200 } 201 202 -(void)webView: (WebView *)wv resource:identifier didReceiveResponse: (NSURLResponse *)response fromDataSource:(WebDataSource *)dataSource 203 { 204 if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) { 205 NSString *string = [NSString stringWithFormat:@"%@ - didReceiveResponse %@", identifier, [response _drt_descriptionSuitableForTestResult]]; 206 printf("%s\n", [string UTF8String]); 207 } 208 if (!done && gLayoutTestController->dumpResourceResponseMIMETypes()) 209 printf("%s has MIME type %s\n", [[[[response URL] relativePath] lastPathComponent] UTF8String], [[response MIMEType] UTF8String]); 210 } 211 212 -(void)webView: (WebView *)wv resource:identifier didReceiveContentLength: (NSInteger)length fromDataSource:(WebDataSource *)dataSource 213 { 214 } 215 216 -(void)webView: (WebView *)wv resource:identifier didFinishLoadingFromDataSource:(WebDataSource *)dataSource 217 { 218 if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) { 219 NSString *string = [NSString stringWithFormat:@"%@ - didFinishLoading", identifier]; 220 printf("%s\n", [string UTF8String]); 221 } 222 } 223 224 -(void)webView: (WebView *)wv resource:identifier didFailLoadingWithError:(NSError *)error fromDataSource:(WebDataSource *)dataSource 225 { 226 if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) { 227 NSString *string = [NSString stringWithFormat:@"%@ - didFailLoadingWithError: %@", identifier, [error _drt_descriptionSuitableForTestResult]]; 228 printf("%s\n", [string UTF8String]); 229 } 230 } 231 232 - (void)webView: (WebView *)wv plugInFailedWithError:(NSError *)error dataSource:(WebDataSource *)dataSource 233 { 234 // The call to -display here simulates the "Plug-in not found" sheet that Safari shows. 235 // It is used for platform/mac/plugins/update-widget-from-style-recalc.html 236 [wv display]; 237 } 238 239 -(NSCachedURLResponse *) webView: (WebView *)wv resource:(id)identifier willCacheResponse:(NSCachedURLResponse *)response fromDataSource:(WebDataSource *)dataSource 240 { 241 if (!done && gLayoutTestController->dumpWillCacheResponse()) { 242 NSString *string = [NSString stringWithFormat:@"%@ - willCacheResponse: called", identifier]; 243 printf("%s\n", [string UTF8String]); 244 } 245 return response; 246 } 247 248 -(BOOL)webView: (WebView*)webView shouldPaintBrokenImageForURL:(NSURL*)imageURL 249 { 250 // Only log the message when shouldPaintBrokenImage() returns NO; this avoids changing results of layout tests with failed 251 // images, e.g., security/block-test-no-port.html. 252 if (!done && gLayoutTestController->dumpResourceLoadCallbacks() && !gLayoutTestController->shouldPaintBrokenImage()) { 253 NSString *string = [NSString stringWithFormat:@"%@ - shouldPaintBrokenImage: NO", [imageURL _drt_descriptionSuitableForTestResult]]; 254 printf("%s\n", [string UTF8String]); 255 } 256 257 return gLayoutTestController->shouldPaintBrokenImage(); 258 } 259 @end 260