diff -r 000000000000 -r dd21522fd290 webengine/osswebengine/WebKit/WebView/WebArchiver.mm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webengine/osswebengine/WebKit/WebView/WebArchiver.mm Mon Mar 30 12:54:55 2009 +0300 @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2006 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. + */ + +#import "WebArchiver.h" + +#import "WebArchive.h" +#import "WebDOMOperationsPrivate.h" +#import "WebDataSource.h" +#import "WebDocument.h" +#import "WebFrame.h" +#import "WebFrameBridge.h" +#import "WebFrameInternal.h" +#import "WebResource.h" +#import +#import +#import +#import + +using namespace WebCore; + +@implementation WebArchiver + ++ (NSArray *)_subframeArchivesForFrame:(WebFrame *)frame +{ + NSEnumerator *enumerator = [[frame childFrames] objectEnumerator]; + NSMutableArray *subframeArchives = [NSMutableArray array]; + WebFrame *childFrame; + while ((childFrame = [enumerator nextObject])) { + WebArchive *childFrameArchive = [self archiveFrame:childFrame]; + if (childFrameArchive) + [subframeArchives addObject:childFrameArchive]; + } + + return subframeArchives; +} + ++ (WebArchive *)archiveFrame:(WebFrame *)frame; +{ + return [[[WebArchive alloc] initWithMainResource:[[frame _dataSource] mainResource] + subresources:[[frame _dataSource] subresources] + subframeArchives:[self _subframeArchivesForFrame:frame]] autorelease]; +} + ++ (WebArchive *)archiveMainResourceForFrame:(WebFrame *)frame; +{ + return [[[WebArchive alloc] initWithMainResource:[[frame _dataSource] mainResource] + subresources:nil + subframeArchives:nil] autorelease]; +} + ++ (WebArchive *)_archiveCurrentStateForFrame:(WebFrame *)frame +{ + if ([frame DOMDocument]) + return [self archiveNode:[frame DOMDocument]]; + + return [self archiveFrame:frame]; +} + ++ (WebArchive *)_archiveWithMarkupString:(NSString *)markupString fromFrame:(WebFrame *)frame nodes:(NSArray *)nodes +{ + NSURLResponse *response = [[frame _dataSource] response]; + NSURL *responseURL = [response URL]; + + // it's possible to have a response without a URL here + // + if (!responseURL) + responseURL = [NSURL URLWithString:@""]; + + WebResource *mainResource = [[WebResource alloc] initWithData:[markupString dataUsingEncoding:NSUTF8StringEncoding] + URL:responseURL + MIMEType:[response MIMEType] + textEncodingName:@"UTF-8" + frameName:[frame name]]; + + NSMutableArray *subframeArchives = [[NSMutableArray alloc] init]; + NSMutableArray *subresources = [[NSMutableArray alloc] init]; + NSMutableSet *uniqueSubresources = [[NSMutableSet alloc] init]; + NSEnumerator *enumerator = [nodes objectEnumerator]; + DOMNode *node; + while ((node = [enumerator nextObject]) != nil) { + WebFrame *childFrame; + if (([node isKindOfClass:[DOMHTMLFrameElement class]] || + [node isKindOfClass:[DOMHTMLIFrameElement class]] || + [node isKindOfClass:[DOMHTMLObjectElement class]]) && + ((childFrame = [(DOMHTMLFrameElement *)node contentFrame]) != nil)) { + [subframeArchives addObject:[self _archiveCurrentStateForFrame:childFrame]]; + } else { + NSEnumerator *enumerator = [[node _subresourceURLs] objectEnumerator]; + NSURL *URL; + while ((URL = [enumerator nextObject]) != nil) { + if ([uniqueSubresources containsObject:URL]) + continue; + [uniqueSubresources addObject:URL]; + WebResource *subresource = [[frame _dataSource] subresourceForURL:URL]; + if (subresource) + [subresources addObject:subresource]; + else + // FIXME: should do something better than spew to console here + LOG_ERROR("Failed to archive subresource for %@", URL); + } + } + } + + WebArchive *archive = [[[WebArchive alloc] initWithMainResource:mainResource subresources:subresources subframeArchives:subframeArchives] autorelease]; + [mainResource release]; + [uniqueSubresources release]; + [subresources release]; + [subframeArchives release]; + + return archive; +} + ++ (WebArchive *)archiveRange:(DOMRange *)range +{ + WebFrameBridge *bridge = [range _bridge]; + WebFrame *frame = [bridge webFrame]; + NSArray *nodes; + NSString *markupString = [bridge markupStringFromRange:range nodes:&nodes]; + return [self _archiveWithMarkupString:markupString fromFrame:frame nodes:nodes]; +} + ++ (WebArchive *)archiveNode:(DOMNode *)node +{ + WebFrame *frame = [[node ownerDocument] webFrame]; + WebFrameBridge *bridge = [frame _bridge]; + NSArray *nodes; + NSString *markupString = [bridge markupStringFromNode:node nodes:&nodes]; + return [self _archiveWithMarkupString:markupString fromFrame:frame nodes:nodes]; +} + ++ (WebArchive *)archiveSelectionInFrame:(WebFrame *)frame +{ + Frame* coreFrame = core(frame); + if (!coreFrame) + return nil; + + WebFrameBridge *bridge = [frame _bridge]; + NSArray *nodes; + NSString *markupString = [bridge markupStringFromRange:kit(coreFrame->selectionController()->toRange().get()) nodes:&nodes]; + WebArchive *archive = [self _archiveWithMarkupString:markupString fromFrame:frame nodes:nodes]; + + if (coreFrame->isFrameSet()) { + // Wrap the frameset document in an iframe so it can be pasted into + // another document (which will have a body or frameset of its own). + + NSString *iframeMarkup = [[NSString alloc] initWithFormat:@"", [[[frame _dataSource] response] URL]]; + WebResource *iframeResource = [[WebResource alloc] initWithData:[iframeMarkup dataUsingEncoding:NSUTF8StringEncoding] + URL:[NSURL URLWithString:@"about:blank"] + MIMEType:@"text/html" + textEncodingName:@"UTF-8" + frameName:nil]; + + NSArray *subframeArchives = [NSArray arrayWithObject:archive]; + archive = [[[WebArchive alloc] initWithMainResource:iframeResource subresources:nil subframeArchives:subframeArchives] autorelease]; + + [iframeResource release]; + [iframeMarkup release]; + } + + return archive; +} + +@end +