📄 dumprendertree.mm
字号:
signal(SIGSYS, crashHandler); /* 12: bad argument to system call */ signal(SIGPIPE, crashHandler); /* 13: write on a pipe with no reader */ signal(SIGXCPU, crashHandler); /* 24: exceeded CPU time limit */ signal(SIGXFSZ, crashHandler); /* 25: exceeded file size limit */}static void allocateGlobalControllers(){ // FIXME: We should remove these and move to the ObjC standard [Foo sharedInstance] model gNavigationController = [[NavigationController alloc] init]; frameLoadDelegate = [[FrameLoadDelegate alloc] init]; uiDelegate = [[UIDelegate alloc] init]; editingDelegate = [[EditingDelegate alloc] init]; resourceLoadDelegate = [[ResourceLoadDelegate alloc] init]; policyDelegate = [[PolicyDelegate alloc] init];}// ObjC++ doens't seem to let me pass NSObject*& sadly.static inline void releaseAndZero(NSObject** object){ [*object release]; *object = nil;}static void releaseGlobalControllers(){ releaseAndZero(&gNavigationController); releaseAndZero(&frameLoadDelegate); releaseAndZero(&editingDelegate); releaseAndZero(&resourceLoadDelegate); releaseAndZero(&uiDelegate); releaseAndZero(&policyDelegate);}static void initializeGlobalsFromCommandLineOptions(int argc, const char *argv[]){ struct option options[] = { {"notree", no_argument, &dumpTree, NO}, {"pixel-tests", no_argument, &dumpPixels, YES}, {"tree", no_argument, &dumpTree, YES}, {"threaded", no_argument, &threaded, YES}, {"complex-text", no_argument, &forceComplexText, YES}, {NULL, 0, NULL, 0} }; int option; while ((option = getopt_long(argc, (char * const *)argv, "", options, NULL)) != -1) { switch (option) { case '?': // unknown or ambiguous option case ':': // missing argument exit(1); break; } }}static void addTestPluginsToPluginSearchPath(const char* executablePath){ NSString *pwd = [[NSString stringWithUTF8String:executablePath] stringByDeletingLastPathComponent]; [WebPluginDatabase setAdditionalWebPlugInPaths:[NSArray arrayWithObject:pwd]]; [[WebPluginDatabase sharedDatabase] refresh];}static bool useLongRunningServerMode(int argc, const char *argv[]){ // This assumes you've already called getopt_long return (argc == optind+1 && strcmp(argv[optind], "-") == 0);}static void runTestingServerLoop(){ // When DumpRenderTree run in server mode, we just wait around for file names // to be passed to us and read each in turn, passing the results back to the client char filenameBuffer[2048]; while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) { char *newLineCharacter = strchr(filenameBuffer, '\n'); if (newLineCharacter) *newLineCharacter = '\0'; if (strlen(filenameBuffer) == 0) continue; runTest(filenameBuffer); }}static void prepareConsistentTestingEnvironment(){ poseAsClass("DumpRenderTreePasteboard", "NSPasteboard"); poseAsClass("DumpRenderTreeEvent", "NSEvent"); setDefaultsToConsistentValuesForTesting(); activateFonts(); if (dumpPixels) setupMainDisplayColorProfile(); allocateGlobalControllers(); makeLargeMallocFailSilently();}void dumpRenderTree(int argc, const char *argv[]){ initializeGlobalsFromCommandLineOptions(argc, argv); prepareConsistentTestingEnvironment(); addTestPluginsToPluginSearchPath(argv[0]); if (dumpPixels) installSignalHandlers(); if (forceComplexText) [WebView _setAlwaysUsesComplexTextCodePath:YES]; WebView *webView = createWebViewAndOffscreenWindow(); mainFrame = [webView mainFrame]; [[NSURLCache sharedURLCache] removeAllCachedResponses]; [WebCache empty]; // <rdar://problem/5222911> testStringByEvaluatingJavaScriptFromString(); if (threaded) startJavaScriptThreads(); if (useLongRunningServerMode(argc, argv)) { printSeparators = YES; runTestingServerLoop(); } else { printSeparators = (optind < argc-1 || (dumpPixels && dumpTree)); for (int i = optind; i != argc; ++i) runTest(argv[i]); } if (threaded) stopJavaScriptThreads(); NSWindow *window = [webView window]; [webView close]; mainFrame = nil; // Work around problem where registering drag types leaves an outstanding // "perform selector" on the window, which retains the window. It's a bit // inelegant and perhaps dangerous to just blow them all away, but in practice // it probably won't cause any trouble (and this is just a test tool, after all). [NSObject cancelPreviousPerformRequestsWithTarget:window]; [window close]; // releases when closed [webView release]; releaseGlobalControllers(); [DumpRenderTreePasteboard releaseLocalPasteboards]; // FIXME: This should be moved onto LayoutTestController and made into a HashSet if (disallowedURLs) { CFRelease(disallowedURLs); disallowedURLs = 0; } if (dumpPixels) restoreMainDisplayColorProfile(0);}int main(int argc, const char *argv[]){ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [NSApplication sharedApplication]; // Force AppKit to init itself dumpRenderTree(argc, argv); [WebCoreStatistics garbageCollectJavaScriptObjects]; [WebCoreStatistics emptyCache]; // Otherwise SVGImages trigger false positives for Frame/Node counts [pool release]; return 0;}static NSInteger compareHistoryItems(id item1, id item2, void *context){ return [[item1 target] caseInsensitiveCompare:[item2 target]];}static void dumpHistoryItem(WebHistoryItem *item, int indent, BOOL current){ int start = 0; if (current) { printf("curr->"); start = 6; } for (int i = start; i < indent; i++) putchar(' '); printf("%s", [[item URLString] UTF8String]); NSString *target = [item target]; if (target && [target length] > 0) printf(" (in frame \"%s\")", [target UTF8String]); if ([item isTargetItem]) printf(" **nav target**"); putchar('\n'); NSArray *kids = [item children]; if (kids) { // must sort to eliminate arbitrary result ordering which defeats reproducible testing kids = [kids sortedArrayUsingFunction:&compareHistoryItems context:nil]; for (unsigned i = 0; i < [kids count]; i++) dumpHistoryItem([kids objectAtIndex:i], indent+4, NO); }}static void dumpFrameScrollPosition(WebFrame *f){ NSPoint scrollPosition = [[[[f frameView] documentView] superview] bounds].origin; if (ABS(scrollPosition.x) > 0.00000001 || ABS(scrollPosition.y) > 0.00000001) { if ([f parentFrame] != nil) printf("frame '%s' ", [[f name] UTF8String]); printf("scrolled to %.f,%.f\n", scrollPosition.x, scrollPosition.y); } if (gLayoutTestController->dumpChildFrameScrollPositions()) { NSArray *kids = [f childFrames]; if (kids) for (unsigned i = 0; i < [kids count]; i++) dumpFrameScrollPosition([kids objectAtIndex:i]); }}static NSString *dumpFramesAsText(WebFrame *frame){ DOMDocument *document = [frame DOMDocument]; DOMElement *documentElement = [document documentElement]; if (!documentElement) return @""; NSMutableString *result = [[[NSMutableString alloc] init] autorelease]; // Add header for all but the main frame. if ([frame parentFrame]) result = [NSMutableString stringWithFormat:@"\n--------\nFrame: '%@'\n--------\n", [frame name]]; [result appendFormat:@"%@\n", [documentElement innerText]]; if (gLayoutTestController->dumpChildFramesAsText()) { NSArray *kids = [frame childFrames]; if (kids) { for (unsigned i = 0; i < [kids count]; i++) [result appendString:dumpFramesAsText([kids objectAtIndex:i])]; } } return result;}static NSData *dumpFrameAsPDF(WebFrame *frame){ if (!frame) return nil; // Sadly we have to dump to a file and then read from that file again // +[NSPrintOperation PDFOperationWithView:insideRect:] requires a rect and prints to a single page // likewise +[NSView dataWithPDFInsideRect:] also prints to a single continuous page // The goal of this function is to test "real" printing across multiple pages. // FIXME: It's possible there might be printing SPI to let us print a multi-page PDF to an NSData object NSString *path = @"/tmp/test.pdf"; NSMutableDictionary *printInfoDict = [NSMutableDictionary dictionaryWithDictionary:[[NSPrintInfo sharedPrintInfo] dictionary]]; [printInfoDict setObject:NSPrintSaveJob forKey:NSPrintJobDisposition]; [printInfoDict setObject:path forKey:NSPrintSavePath]; NSPrintInfo *printInfo = [[NSPrintInfo alloc] initWithDictionary:printInfoDict]; [printInfo setHorizontalPagination:NSAutoPagination]; [printInfo setVerticalPagination:NSAutoPagination]; [printInfo setVerticallyCentered:NO]; NSPrintOperation *printOperation = [NSPrintOperation printOperationWithView:[frame frameView] printInfo:printInfo]; [printOperation setShowPanels:NO]; [printOperation runOperation]; [printInfo release]; NSData *pdfData = [NSData dataWithContentsOfFile:path]; [[NSFileManager defaultManager] removeFileAtPath:path handler:nil]; return pdfData;}static void convertMIMEType(NSMutableString *mimeType){#ifdef BUILDING_ON_LEOPARD // Workaround for <rdar://problem/5539824> on Leopard if ([mimeType isEqualToString:@"text/xml"]) [mimeType setString:@"application/xml"];#endif // Workaround for <rdar://problem/6234318> with Dashcode 2.0 if ([mimeType isEqualToString:@"application/x-javascript"]) [mimeType setString:@"text/javascript"];}static void convertWebResourceDataToString(NSMutableDictionary *resource){ NSMutableString *mimeType = [resource objectForKey:@"WebResourceMIMEType"]; convertMIMEType(mimeType); if ([mimeType hasPrefix:@"text/"] || [[WebHTMLRepresentation supportedNonImageMIMETypes] containsObject:mimeType]) { NSString *textEncodingName = [resource objectForKey:@"WebResourceTextEncodingName"]; NSStringEncoding stringEncoding; if ([textEncodingName length] > 0) stringEncoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)textEncodingName)); else stringEncoding = NSUTF8StringEncoding; NSData *data = [resource objectForKey:@"WebResourceData"]; NSString *dataAsString = [[NSString alloc] initWithData:data encoding:stringEncoding]; if (dataAsString) [resource setObject:dataAsString forKey:@"WebResourceData"]; [dataAsString release]; }}static void normalizeHTTPResponseHeaderFields(NSMutableDictionary *fields){ // Normalize headers if ([fields objectForKey:@"Date"]) [fields setObject:@"Sun, 16 Nov 2008 17:00:00 GMT" forKey:@"Date"]; if ([fields objectForKey:@"Last-Modified"]) [fields setObject:@"Sun, 16 Nov 2008 16:55:00 GMT" forKey:@"Last-Modified"]; if ([fields objectForKey:@"Etag"]) [fields setObject:@"\"301925-21-45c7d72d3e780\"" forKey:@"Etag"]; if ([fields objectForKey:@"Server"]) [fields setObject:@"Apache/2.2.9 (Unix) mod_ssl/2.2.9 OpenSSL/0.9.7l PHP/5.2.6" forKey:@"Server"]; // Remove headers if ([fields objectForKey:@"Connection"]) [fields removeObjectForKey:@"Connection"]; if ([fields objectForKey:@"Keep-Alive"]) [fields removeObjectForKey:@"Keep-Alive"];}static void normalizeWebResourceURL(NSMutableString *webResourceURL){ static int fileUrlLength = [(NSString *)@"file://" length]; NSRange layoutTestsWebArchivePathRange = [webResourceURL rangeOfString:@"/LayoutTests/" options:NSBackwardsSearch]; if (layoutTestsWebArchivePathRange.location == NSNotFound) return; NSRange currentWorkingDirectoryRange = NSMakeRange(fileUrlLength, layoutTestsWebArchivePathRange.location - fileUrlLength); [webResourceURL replaceCharactersInRange:currentWorkingDirectoryRange withString:@""];}static void convertWebResourceResponseToDictionary(NSMutableDictionary *propertyList){ NSURLResponse *response = nil; NSData *responseData = [propertyList objectForKey:@"WebResourceResponse"]; // WebResourceResponseKey in WebResource.m if ([responseData isKindOfClass:[NSData class]]) { // Decode NSURLResponse NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:responseData]; response = [unarchiver decodeObjectForKey:@"WebResourceResponse"]; // WebResourceResponseKey in WebResource.m [unarchiver finishDecoding]; [unarchiver release]; } NSMutableDictionary *responseDictionary = [[NSMutableDictionary alloc] init]; NSMutableString *urlString = [[[response URL] description] mutableCopy]; normalizeWebResourceURL(urlString); [responseDictionary setObject:urlString forKey:@"URL"]; [urlString release]; NSMutableString *mimeTypeString = [[response MIMEType] mutableCopy]; convertMIMEType(mimeTypeString); [responseDictionary setObject:mimeTypeString forKey:@"MIMEType"]; [mimeTypeString release]; NSString *textEncodingName = [response textEncodingName]; if (textEncodingName) [responseDictionary setObject:textEncodingName forKey:@"textEncodingName"]; [responseDictionary setObject:[NSNumber numberWithLongLong:[response expectedContentLength]] forKey:@"expectedContentLength"]; if ([response isKindOfClass:[NSHTTPURLResponse class]]) { NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; NSMutableDictionary *allHeaderFields = [[httpResponse allHeaderFields] mutableCopy]; normalizeHTTPResponseHeaderFields(allHeaderFields);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -