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 "WebFrameBridge.h"
38 #import "WebFrameInternal.h"
39 #import "WebKitNSStringExtras.h"
40 #import "WebKitStatisticsPrivate.h"
41 #import "WebNSAttributedStringExtras.h"
42 #import "WebNSObjectExtras.h"
43 #import "WebResourcePrivate.h"
45 #import <Foundation/NSURLResponse.h>
46 #import <JavaScriptCore/Assertions.h>
47 #import <WebCore/Document.h>
48 #import <WebCore/DocumentLoader.h>
49 #import <WebCore/Frame.h>
50 #import <WebCore/FrameLoader.h>
51 #import <WebCore/MIMETypeRegistry.h>
52 #import <WebCore/Range.h>
54 using namespace WebCore;
56 @interface WebHTMLRepresentationPrivate : NSObject
59 WebDataSource *dataSource;
60 WebFrameBridge *bridge;
61 NSData *parsedArchiveData;
63 BOOL hasSentResponseToPlugin;
64 id <WebPluginManualLoader> manualLoader;
69 @implementation WebHTMLRepresentationPrivate
73 [parsedArchiveData release];
79 @implementation WebHTMLRepresentation
81 static NSArray *stringArray(const HashSet<String>& set)
83 NSMutableArray *array = [NSMutableArray arrayWithCapacity:set.size()];
84 HashSet<String>::const_iterator end = set.end();
85 for (HashSet<String>::const_iterator it = set.begin(); it != end; ++it)
86 [array addObject:(NSString *)(*it)];
90 static NSArray *concatenateArrays(NSArray *first, NSArray *second)
92 NSMutableArray *result = [[first mutableCopy] autorelease];
93 [result addObjectsFromArray:second];
97 + (NSArray *)supportedMIMETypes
99 static RetainPtr<NSArray> staticSupportedMIMETypes =
100 concatenateArrays([self supportedNonImageMIMETypes], [self supportedImageMIMETypes]);
101 return staticSupportedMIMETypes.get();
104 + (NSArray *)supportedNonImageMIMETypes
106 static RetainPtr<NSArray> staticSupportedNonImageMIMETypes =
107 stringArray(MIMETypeRegistry::getSupportedNonImageMIMETypes());
108 return staticSupportedNonImageMIMETypes.get();
111 + (NSArray *)supportedImageMIMETypes
113 static RetainPtr<NSArray> staticSupportedImageMIMETypes =
114 stringArray(MIMETypeRegistry::getSupportedImageMIMETypes());
115 return staticSupportedImageMIMETypes.get();
124 _private = [[WebHTMLRepresentationPrivate alloc] init];
126 ++WebHTMLRepresentationCount;
133 --WebHTMLRepresentationCount;
142 --WebHTMLRepresentationCount;
147 - (WebFrameBridge *)_bridge
149 return _private->bridge;
152 - (void)_redirectDataToManualLoader:(id<WebPluginManualLoader>)manualLoader forPluginView:(NSView *)pluginView;
154 _private->manualLoader = manualLoader;
155 _private->pluginView = pluginView;
158 - (void)setDataSource:(WebDataSource *)dataSource
160 _private->dataSource = dataSource;
161 _private->bridge = [[dataSource webFrame] _bridge];
164 - (BOOL)_isDisplayingWebArchive
166 return [[[_private->dataSource response] MIMEType] _webkit_isCaseInsensitiveEqualToString:@"application/x-webarchive"];
169 - (void)receivedData:(NSData *)data withDataSource:(WebDataSource *)dataSource
171 if ([dataSource webFrame] && ![self _isDisplayingWebArchive]) {
172 if (!_private->pluginView)
173 [_private->bridge receivedData:data textEncodingName:[[_private->dataSource response] textEncodingName]];
175 if (_private->pluginView) {
176 if (!_private->hasSentResponseToPlugin) {
177 [_private->manualLoader pluginView:_private->pluginView receivedResponse:[dataSource response]];
178 _private->hasSentResponseToPlugin = YES;
181 [_private->manualLoader pluginView:_private->pluginView receivedData:data];
186 - (void)receivedError:(NSError *)error withDataSource:(WebDataSource *)dataSource
188 if (_private->pluginView) {
189 [_private->manualLoader pluginView:_private->pluginView receivedError:error];
193 - (void)_loadDataSourceAsWebArchive
195 WebArchive *archive = [[WebArchive alloc] initWithData:[_private->dataSource data]];
196 WebResource *mainResource = [archive mainResource];
202 NSData *data = [mainResource data];
204 [_private->parsedArchiveData release];
205 _private->parsedArchiveData = data;
207 [_private->dataSource _addToUnarchiveState:archive];
210 WebFrame *webFrame = [_private->dataSource webFrame];
215 core(webFrame)->loader()->continueLoadWithData(SharedBuffer::wrapNSData(data).get(), [mainResource MIMEType], [mainResource textEncodingName], [mainResource URL]);
218 - (void)finishedLoadingWithDataSource:(WebDataSource *)dataSource
220 WebFrame *frame = [dataSource webFrame];
222 if (_private->pluginView) {
223 [_private->manualLoader pluginViewFinishedLoading:_private->pluginView];
228 if ([self _isDisplayingWebArchive])
229 [self _loadDataSourceAsWebArchive];
231 // Telling the bridge we received some data and passing nil as the data is our
232 // way to get work done that is normally done when the first bit of data is
233 // received, even for the case of a document with no data (like about:blank).
234 [_private->bridge receivedData:nil textEncodingName:[[_private->dataSource response] textEncodingName]];
236 WebView *webView = [frame webView];
237 if ([webView isEditable])
238 core(frame)->applyEditingStyleToBodyElement();
242 - (BOOL)canProvideDocumentSource
244 return [_private->bridge canProvideDocumentSource];
247 - (BOOL)canSaveAsWebArchive
249 return [_private->bridge canSaveAsWebArchive];
252 - (NSString *)documentSource
254 if ([self _isDisplayingWebArchive])
255 return [[[NSString alloc] initWithData:_private->parsedArchiveData encoding:NSUTF8StringEncoding] autorelease];
257 return [_private->bridge stringWithData:[_private->dataSource data]];
262 return nsStringNilIfEmpty([_private->dataSource _documentLoader]->title());
265 - (DOMDocument *)DOMDocument
267 return [[_private->bridge webFrame] DOMDocument];
270 - (NSAttributedString *)attributedText
276 - (NSAttributedString *)attributedStringFrom:(DOMNode *)startNode startOffset:(int)startOffset to:(DOMNode *)endNode endOffset:(int)endOffset
278 return [NSAttributedString _web_attributedStringFromRange:Range::create([startNode _node]->document(), [startNode _node], startOffset, [endNode _node], endOffset).get()];
281 - (DOMElement *)elementWithName:(NSString *)name inForm:(DOMElement *)form
283 return [_private->bridge elementWithName:name inForm:form];
286 - (BOOL)elementDoesAutoComplete:(DOMElement *)element
288 return [_private->bridge elementDoesAutoComplete:element];
291 - (BOOL)elementIsPassword:(DOMElement *)element
293 return [_private->bridge elementIsPassword:element];
296 - (DOMElement *)formForElement:(DOMElement *)element
298 return [_private->bridge formForElement:element];
301 - (DOMElement *)currentForm
303 return [_private->bridge currentForm];
306 - (NSArray *)controlsInForm:(DOMElement *)form
308 return [_private->bridge controlsInForm:form];
311 - (NSString *)searchForLabels:(NSArray *)labels beforeElement:(DOMElement *)element
313 return [_private->bridge searchForLabels:labels beforeElement:element];
316 - (NSString *)matchLabels:(NSArray *)labels againstElement:(DOMElement *)element
318 return [_private->bridge matchLabels:labels againstElement:element];