2 * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #import "WebHTMLRepresentation.h"
31 #import "DOMNodeInternal.h"
32 #import "DOMRangeInternal.h"
33 #import "WebArchive.h"
34 #import "WebBasePluginPackage.h"
35 #import "WebDataSourceInternal.h"
36 #import "WebDocumentPrivate.h"
37 #import "WebFrameInternal.h"
38 #import "WebKitNSStringExtras.h"
39 #import "WebKitStatisticsPrivate.h"
40 #import "WebNSAttributedStringExtras.h"
41 #import "WebNSObjectExtras.h"
42 #import "WebResourcePrivate.h"
44 #import <Foundation/NSURLResponse.h>
45 #import <JavaScriptCore/Assertions.h>
46 #import <WebCore/Document.h>
47 #import <WebCore/DocumentLoader.h>
48 #import <WebCore/Frame.h>
49 #import <WebCore/FrameLoader.h>
50 #import <WebCore/MIMETypeRegistry.h>
51 #import <WebCore/Range.h>
53 using namespace WebCore;
55 @interface WebHTMLRepresentationPrivate : NSObject {
57 WebDataSource *dataSource;
58 NSData *parsedArchiveData;
60 BOOL hasSentResponseToPlugin;
61 id <WebPluginManualLoader> manualLoader;
66 @implementation WebHTMLRepresentationPrivate
70 [parsedArchiveData release];
76 @implementation WebHTMLRepresentation
78 static NSArray *stringArray(const HashSet<String>& set)
80 NSMutableArray *array = [NSMutableArray arrayWithCapacity:set.size()];
81 HashSet<String>::const_iterator end = set.end();
82 for (HashSet<String>::const_iterator it = set.begin(); it != end; ++it)
83 [array addObject:(NSString *)(*it)];
87 static NSArray *concatenateArrays(NSArray *first, NSArray *second)
89 NSMutableArray *result = [[first mutableCopy] autorelease];
90 [result addObjectsFromArray:second];
94 + (NSArray *)supportedMIMETypes
96 static RetainPtr<NSArray> staticSupportedMIMETypes =
97 concatenateArrays([self supportedNonImageMIMETypes], [self supportedImageMIMETypes]);
98 return staticSupportedMIMETypes.get();
101 + (NSArray *)supportedNonImageMIMETypes
103 static RetainPtr<NSArray> staticSupportedNonImageMIMETypes =
104 stringArray(MIMETypeRegistry::getSupportedNonImageMIMETypes());
105 return staticSupportedNonImageMIMETypes.get();
108 + (NSArray *)supportedImageMIMETypes
110 static RetainPtr<NSArray> staticSupportedImageMIMETypes =
111 stringArray(MIMETypeRegistry::getSupportedImageMIMETypes());
112 return staticSupportedImageMIMETypes.get();
121 _private = [[WebHTMLRepresentationPrivate alloc] init];
123 ++WebHTMLRepresentationCount;
130 --WebHTMLRepresentationCount;
139 --WebHTMLRepresentationCount;
144 - (void)_redirectDataToManualLoader:(id<WebPluginManualLoader>)manualLoader forPluginView:(NSView *)pluginView;
146 _private->manualLoader = manualLoader;
147 _private->pluginView = pluginView;
150 - (void)setDataSource:(WebDataSource *)dataSource
152 _private->dataSource = dataSource;
155 - (BOOL)_isDisplayingWebArchive
157 return [[[_private->dataSource response] MIMEType] _webkit_isCaseInsensitiveEqualToString:@"application/x-webarchive"];
160 - (void)receivedData:(NSData *)data withDataSource:(WebDataSource *)dataSource
162 WebFrame *frame = [dataSource webFrame];
163 if (frame && ![self _isDisplayingWebArchive]) {
164 if (!_private->pluginView)
165 [frame _receivedData:data textEncodingName:[[_private->dataSource response] textEncodingName]];
167 if (_private->pluginView) {
168 if (!_private->hasSentResponseToPlugin) {
169 [_private->manualLoader pluginView:_private->pluginView receivedResponse:[dataSource response]];
170 _private->hasSentResponseToPlugin = YES;
173 [_private->manualLoader pluginView:_private->pluginView receivedData:data];
178 - (void)receivedError:(NSError *)error withDataSource:(WebDataSource *)dataSource
180 if (_private->pluginView) {
181 [_private->manualLoader pluginView:_private->pluginView receivedError:error];
185 - (void)_loadDataSourceAsWebArchive
187 WebArchive *archive = [[WebArchive alloc] initWithData:[_private->dataSource data]];
188 WebResource *mainResource = [archive mainResource];
194 NSData *data = [mainResource data];
196 [_private->parsedArchiveData release];
197 _private->parsedArchiveData = data;
199 [_private->dataSource _addToUnarchiveState:archive];
202 WebFrame *webFrame = [_private->dataSource webFrame];
207 core(webFrame)->loader()->continueLoadWithData(SharedBuffer::wrapNSData(data).get(), [mainResource MIMEType], [mainResource textEncodingName], [mainResource URL]);
210 - (void)finishedLoadingWithDataSource:(WebDataSource *)dataSource
212 WebFrame *frame = [dataSource webFrame];
214 if (_private->pluginView) {
215 [_private->manualLoader pluginViewFinishedLoading:_private->pluginView];
220 if ([self _isDisplayingWebArchive])
221 [self _loadDataSourceAsWebArchive];
223 // Telling the frame we received some data and passing nil as the data is our
224 // way to get work done that is normally done when the first bit of data is
225 // received, even for the case of a document with no data (like about:blank).
226 [frame _receivedData:nil textEncodingName:[[_private->dataSource response] textEncodingName]];
229 WebView *webView = [frame webView];
230 if ([webView isEditable])
231 core(frame)->applyEditingStyleToBodyElement();
235 - (BOOL)canProvideDocumentSource
237 return [[_private->dataSource webFrame] _canProvideDocumentSource];
240 - (BOOL)canSaveAsWebArchive
242 return [[_private->dataSource webFrame] _canSaveAsWebArchive];
245 - (NSString *)documentSource
247 if ([self _isDisplayingWebArchive])
248 return [[[NSString alloc] initWithData:_private->parsedArchiveData encoding:NSUTF8StringEncoding] autorelease];
250 return [[_private->dataSource webFrame] _stringWithData:[_private->dataSource data]];
255 return nsStringNilIfEmpty([_private->dataSource _documentLoader]->title());
258 - (DOMDocument *)DOMDocument
260 return [[_private->dataSource webFrame] DOMDocument];
263 - (NSAttributedString *)attributedText
269 - (NSAttributedString *)attributedStringFrom:(DOMNode *)startNode startOffset:(int)startOffset to:(DOMNode *)endNode endOffset:(int)endOffset
271 return [NSAttributedString _web_attributedStringFromRange:Range::create([startNode _node]->document(), [startNode _node], startOffset, [endNode _node], endOffset).get()];
274 - (DOMElement *)elementWithName:(NSString *)name inForm:(DOMElement *)form
276 return [[_private->dataSource webFrame] _elementWithName:name inForm:form];
279 - (BOOL)elementDoesAutoComplete:(DOMElement *)element
281 return [[_private->dataSource webFrame] _elementDoesAutoComplete:element];
284 - (BOOL)elementIsPassword:(DOMElement *)element
286 return [[_private->dataSource webFrame] _elementIsPassword:element];
289 - (DOMElement *)formForElement:(DOMElement *)element
291 return [[_private->dataSource webFrame] _formForElement:element];
294 - (DOMElement *)currentForm
296 return [[_private->dataSource webFrame] _currentForm];
299 - (NSArray *)controlsInForm:(DOMElement *)form
301 return [[_private->dataSource webFrame] _controlsInForm:form];
304 - (NSString *)searchForLabels:(NSArray *)labels beforeElement:(DOMElement *)element
306 return [[_private->dataSource webFrame] _searchForLabels:labels beforeElement:element];
309 - (NSString *)matchLabels:(NSArray *)labels againstElement:(DOMElement *)element
311 return [[_private->dataSource webFrame] _matchLabels:labels againstElement:element];