2 * Copyright (C) 2005, 2006, 2007, 2008 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 "WebFrameInternal.h"
31 #import "DOMCSSStyleDeclarationInternal.h"
32 #import "DOMDocumentFragmentInternal.h"
33 #import "DOMDocumentInternal.h"
34 #import "DOMElementInternal.h"
35 #import "DOMHTMLElementInternal.h"
36 #import "DOMNodeInternal.h"
37 #import "DOMRangeInternal.h"
38 #import "WebChromeClient.h"
39 #import "WebDataSourceInternal.h"
40 #import "WebDocumentLoaderMac.h"
41 #import "WebFrameLoaderClient.h"
42 #import "WebFrameViewInternal.h"
43 #import "WebHTMLViewInternal.h"
44 #import "WebKitLogging.h"
45 #import "WebKitStatisticsPrivate.h"
46 #import "WebNSURLExtras.h"
47 #import "WebScriptDebugger.h"
48 #import "WebViewInternal.h"
49 #import <JavaScriptCore/APICast.h>
50 #import <JavaScriptCore/array_object.h>
51 #import <JavaScriptCore/date_object.h>
52 #import <WebCore/AXObjectCache.h>
53 #import <WebCore/ColorMac.h>
54 #import <WebCore/DOMImplementation.h>
55 #import <WebCore/DocLoader.h>
56 #import <WebCore/DocumentFragment.h>
57 #import <WebCore/Editor.h>
58 #import <WebCore/EventHandler.h>
59 #import <WebCore/Frame.h>
60 #import <WebCore/FrameLoader.h>
61 #import <WebCore/FrameTree.h>
62 #import <WebCore/GraphicsContext.h>
63 #import <WebCore/HTMLFrameOwnerElement.h>
64 #import <WebCore/HTMLInputElement.h>
65 #import <WebCore/HistoryItem.h>
66 #import <WebCore/HitTestResult.h>
67 #import <WebCore/Page.h>
68 #import <WebCore/PluginData.h>
69 #import <WebCore/RenderTreeAsText.h>
70 #import <WebCore/RenderView.h>
71 #import <WebCore/RenderWidget.h>
72 #import <WebCore/ReplaceSelectionCommand.h>
73 #import <WebCore/SimpleFontData.h>
74 #import <WebCore/SmartReplace.h>
75 #import <WebCore/SystemTime.h>
76 #import <WebCore/TextIterator.h>
77 #import <WebCore/TextResourceDecoder.h>
78 #import <WebCore/TypingCommand.h>
79 #import <WebCore/htmlediting.h>
80 #import <WebCore/kjs_proxy.h>
81 #import <WebCore/markup.h>
82 #import <WebCore/visible_units.h>
85 using namespace WebCore;
86 using namespace HTMLNames;
88 using KJS::ArrayInstance;
89 using KJS::BooleanType;
90 using KJS::DateInstance;
92 using KJS::GetterSetterType;
93 using KJS::JSGlobalObject;
98 using KJS::NumberType;
99 using KJS::ObjectType;
100 using KJS::StringType;
101 using KJS::UndefinedType;
102 using KJS::UnspecifiedType;
105 Here is the current behavior matrix for four types of navigations:
109 Restore form state: YES
110 Restore scroll and focus state: YES
111 Cache policy: NSURLRequestUseProtocolCachePolicy
112 Add to back/forward list: YES
116 Restore form state: YES
117 Restore scroll and focus state: YES
118 Cache policy: NSURLRequestReturnCacheDataElseLoad
119 Add to back/forward list: NO
121 Reload (meaning only the reload button):
123 Restore form state: NO
124 Restore scroll and focus state: YES
125 Cache policy: NSURLRequestReloadIgnoringCacheData
126 Add to back/forward list: NO
128 Repeat load of the same URL (by any other means of navigation other than the reload button, including hitting return in the location field):
130 Restore form state: NO
131 Restore scroll and focus state: NO, reset to initial conditions
132 Cache policy: NSURLRequestReloadIgnoringCacheData
133 Add to back/forward list: NO
136 NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey";
137 NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey";
138 NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
140 @interface NSView (WebFramePluginHosting)
141 - (void)setWebFrame:(WebFrame *)webFrame;
144 @implementation WebFramePrivate
148 [webFrameView release];
150 delete scriptDebugger;
157 delete scriptDebugger;
162 - (void)setWebFrameView:(WebFrameView *)v
165 [webFrameView release];
171 CSSStyleDeclaration* core(DOMCSSStyleDeclaration *declaration)
173 return [declaration _CSSStyleDeclaration];
176 DOMCSSStyleDeclaration *kit(WebCore::CSSStyleDeclaration* declaration)
178 return [DOMCSSStyleDeclaration _wrapCSSStyleDeclaration:declaration];
181 Element* core(DOMElement *element)
183 return [element _element];
186 DOMElement *kit(Element* element)
188 return [DOMElement _wrapElement:element];
191 Node* core(DOMNode *node)
196 DOMNode *kit(Node* node)
198 return [DOMNode _wrapNode:node];
201 DOMNode *kit(PassRefPtr<Node> node)
203 return [DOMNode _wrapNode:node.get()];
206 Document* core(DOMDocument *document)
208 return [document _document];
211 DOMDocument *kit(Document* document)
213 return [DOMDocument _wrapDocument:document];
216 HTMLElement* core(DOMHTMLElement *element)
218 return [element _HTMLElement];
221 DOMHTMLElement *kit(HTMLElement *element)
223 return [DOMHTMLElement _wrapHTMLElement:element];
226 Range* core(DOMRange *range)
228 return [range _range];
231 DOMRange *kit(Range* range)
233 return [DOMRange _wrapRange:range];
236 EditableLinkBehavior core(WebKitEditableLinkBehavior editableLinkBehavior)
238 switch (editableLinkBehavior) {
239 case WebKitEditableLinkDefaultBehavior:
240 return EditableLinkDefaultBehavior;
241 case WebKitEditableLinkAlwaysLive:
242 return EditableLinkAlwaysLive;
243 case WebKitEditableLinkOnlyLiveWithShiftKey:
244 return EditableLinkOnlyLiveWithShiftKey;
245 case WebKitEditableLinkLiveWhenNotFocused:
246 return EditableLinkLiveWhenNotFocused;
247 case WebKitEditableLinkNeverLive:
248 return EditableLinkNeverLive;
250 ASSERT_NOT_REACHED();
251 return EditableLinkDefaultBehavior;
254 @implementation WebFrame (WebInternal)
256 Frame* core(WebFrame *frame)
258 return frame ? frame->_private->coreFrame : 0;
261 WebFrame *kit(Frame* frame)
263 return frame ? static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame() : nil;
266 Page* core(WebView *webView)
268 return [webView page];
271 WebView *kit(Page* page)
273 return page ? static_cast<WebChromeClient*>(page->chrome()->client())->webView() : nil;
276 WebView *getWebView(WebFrame *webFrame)
278 Frame* coreFrame = core(webFrame);
281 return kit(coreFrame->page());
284 + (PassRefPtr<Frame>)_createFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView ownerElement:(HTMLFrameOwnerElement*)ownerElement
286 WebView *webView = kit(page);
288 WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView];
289 RefPtr<Frame> coreFrame = new Frame(page, ownerElement, new WebFrameLoaderClient(frame));
291 frame->_private->coreFrame = coreFrame.get();
293 coreFrame->tree()->setName(name);
296 [webView _setZoomMultiplier:[webView _realZoomMultiplier] isTextOnly:[webView _realZoomMultiplierIsTextOnly]];
298 return coreFrame.release();
301 + (void)_createMainFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView
303 [self _createFrameWithPage:page frameName:name frameView:frameView ownerElement:0];
306 + (PassRefPtr<WebCore::Frame>)_createSubframeWithOwnerElement:(HTMLFrameOwnerElement*)ownerElement frameName:(const String&)name frameView:(WebFrameView *)frameView
308 return [self _createFrameWithPage:ownerElement->document()->frame()->page() frameName:name frameView:frameView ownerElement:ownerElement];
312 In the case of saving state about a page with frames, we store a tree of items that mirrors the frame tree.
313 The item that was the target of the user's navigation is designated as the "targetItem".
314 When this method is called with doClip=YES we're able to create the whole tree except for the target's children,
315 which will be loaded in the future. That part of the tree will be filled out as the child loads are committed.
318 + (CFAbsoluteTime)_timeOfLastCompletedLoad
320 return FrameLoader::timeOfLastCompletedLoad() - kCFAbsoluteTimeIntervalSince1970;
323 - (void)_loadURL:(NSURL *)URL referrer:(NSString *)referrer intoChild:(WebFrame *)childFrame
326 HistoryItem* parentItem = core(self)->loader()->currentHistoryItem();
327 FrameLoadType loadType = [self _frameLoader]->loadType();
328 FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedHistory;
330 // If we're moving in the backforward list, we might want to replace the content
331 // of this child frame with whatever was there at that point.
332 // Reload will maintain the frame contents, LoadSame will not.
333 if (parentItem && parentItem->children().size() &&
334 (isBackForwardLoadType(loadType)
335 || loadType == FrameLoadTypeReload
336 || loadType == FrameLoadTypeReloadAllowingStaleData))
338 HistoryItem* childItem = parentItem->childItemWithName([childFrame name]);
340 // Use the original URL to ensure we get all the side-effects, such as
341 // onLoad handlers, of any redirects that happened. An example of where
342 // this is needed is Radar 3213556.
343 URL = [NSURL _web_URLWithDataAsString:childItem->originalURLString()];
344 // These behaviors implied by these loadTypes should apply to the child frames
345 childLoadType = loadType;
347 if (isBackForwardLoadType(loadType))
348 // For back/forward, remember this item so we can traverse any child items as child frames load
349 core(childFrame)->loader()->setProvisionalHistoryItem(childItem);
351 // For reload, just reinstall the current item, since a new child frame was created but we won't be creating a new BF item
352 core(childFrame)->loader()->setCurrentHistoryItem(childItem);
356 WebArchive *archive = [[self _dataSource] _popSubframeArchiveWithName:[childFrame name]];
358 [childFrame loadArchive:archive];
360 [childFrame _frameLoader]->load([URL absoluteURL], referrer, childLoadType,
365 - (void)_viewWillMoveToHostWindow:(NSWindow *)hostWindow
367 Frame* coreFrame = core(self);
368 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
369 [[[kit(frame) frameView] documentView] viewWillMoveToHostWindow:hostWindow];
372 - (void)_viewDidMoveToHostWindow
374 Frame* coreFrame = core(self);
375 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
376 [[[kit(frame) frameView] documentView] viewDidMoveToHostWindow];
379 - (void)_addChild:(WebFrame *)child
381 core(self)->tree()->appendChild(adoptRef(core(child)));
382 if ([child _dataSource])
383 [[child _dataSource] _documentLoader]->setOverrideEncoding([[self _dataSource] _documentLoader]->overrideEncoding());
386 - (int)_numPendingOrLoadingRequests:(BOOL)recurse
388 return core(self)->loader()->numPendingOrLoadingRequests(recurse);
391 - (void)_attachScriptDebugger
393 if (_private->scriptDebugger)
396 JSGlobalObject* globalObject = core(self)->scriptProxy()->globalObject();
400 _private->scriptDebugger = new WebScriptDebugger(globalObject);
403 - (void)_detachScriptDebugger
405 if (!_private->scriptDebugger)
408 delete _private->scriptDebugger;
409 _private->scriptDebugger = 0;
412 - (id)_initWithWebFrameView:(WebFrameView *)fv webView:(WebView *)v
418 _private = [[WebFramePrivate alloc] init];
421 [_private setWebFrameView:fv];
422 [fv _setWebFrame:self];
425 _private->shouldCreateRenderers = YES;
432 - (NSArray *)_documentViews
434 NSMutableArray *result = [NSMutableArray array];
435 Frame* coreFrame = core(self);
436 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
437 id docView = [[kit(frame) frameView] documentView];
439 [result addObject:docView];
444 - (void)_updateBackground
446 BOOL drawsBackground = [getWebView(self) drawsBackground];
447 NSColor *backgroundColor = [getWebView(self) backgroundColor];
449 Frame* coreFrame = core(self);
450 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
451 WebFrame *webFrame = kit(frame);
452 // Never call setDrawsBackground:YES here on the scroll view or the background color will
453 // flash between pages loads. setDrawsBackground:YES will be called in _frameLoadCompleted.
454 if (!drawsBackground)
455 [[[webFrame frameView] _scrollView] setDrawsBackground:NO];
456 [[[webFrame frameView] _scrollView] setBackgroundColor:backgroundColor];
457 id documentView = [[webFrame frameView] documentView];
458 if ([documentView respondsToSelector:@selector(setDrawsBackground:)])
459 [documentView setDrawsBackground:drawsBackground];
460 if ([documentView respondsToSelector:@selector(setBackgroundColor:)])
461 [documentView setBackgroundColor:backgroundColor];
462 [self _setDrawsBackground:drawsBackground];
463 [self _setBaseBackgroundColor:backgroundColor];
467 - (void)_setInternalLoadDelegate:(id)internalLoadDelegate
469 _private->internalLoadDelegate = internalLoadDelegate;
472 - (id)_internalLoadDelegate
474 return _private->internalLoadDelegate;
477 #ifndef BUILDING_ON_TIGER
478 - (void)_unmarkAllBadGrammar
480 Frame* coreFrame = core(self);
481 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
482 Document *doc = frame->document();
486 doc->removeMarkers(DocumentMarker::Grammar);
491 - (void)_unmarkAllMisspellings
493 Frame* coreFrame = core(self);
494 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
495 Document *doc = frame->document();
499 doc->removeMarkers(DocumentMarker::Spelling);
503 - (BOOL)_hasSelection
505 id documentView = [_private->webFrameView documentView];
507 // optimization for common case to avoid creating potentially large selection string
508 if ([documentView isKindOfClass:[WebHTMLView class]])
509 if (Frame* coreFrame = core(self))
510 return coreFrame->selectionController()->isRange();
512 if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
513 return [[documentView selectedString] length] > 0;
518 - (void)_clearSelection
520 id documentView = [_private->webFrameView documentView];
521 if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
522 [documentView deselectAll];
526 - (BOOL)_atMostOneFrameHasSelection
528 // FIXME: 4186050 is one known case that makes this debug check fail.
530 Frame* coreFrame = core(self);
531 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
532 if ([kit(frame) _hasSelection]) {
541 - (WebFrame *)_findFrameWithSelection
543 Frame* coreFrame = core(self);
544 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
545 if ([kit(frame) _hasSelection])
550 - (void)_clearSelectionInOtherFrames
552 // We rely on WebDocumentSelection protocol implementors to call this method when they become first
553 // responder. It would be nicer to just notice first responder changes here instead, but there's no
554 // notification sent when the first responder changes in general (Radar 2573089).
555 WebFrame *frameWithSelection = [[getWebView(self) mainFrame] _findFrameWithSelection];
556 if (frameWithSelection != self)
557 [frameWithSelection _clearSelection];
559 // While we're in the general area of selection and frames, check that there is only one now.
560 ASSERT([[getWebView(self) mainFrame] _atMostOneFrameHasSelection]);
565 Frame* coreFrame = core(self);
568 return coreFrame == coreFrame->page()->mainFrame() ;
571 - (FrameLoader*)_frameLoader
573 Frame* frame = core(self);
574 return frame ? frame->loader() : 0;
577 static inline WebDataSource *dataSource(DocumentLoader* loader)
579 return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
582 - (WebDataSource *)_dataSourceForDocumentLoader:(DocumentLoader*)loader
584 return dataSource(loader);
587 - (void)_addDocumentLoader:(DocumentLoader*)loader toUnarchiveState:(WebArchive *)archive
589 [dataSource(loader) _addToUnarchiveState:archive];
592 - (WebDataSource *)_dataSource
594 FrameLoader* frameLoader = [self _frameLoader];
599 return dataSource(frameLoader->documentLoader());
602 #if ENABLE(NETSCAPE_PLUGIN_API)
603 - (void)_recursive_resumeNullEventsForAllNetscapePlugins
605 Frame* coreFrame = core(self);
606 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
607 NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
608 if ([documentView isKindOfClass:[WebHTMLView class]])
609 [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins];
613 - (void)_recursive_pauseNullEventsForAllNetscapePlugins
615 Frame* coreFrame = core(self);
616 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
617 NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
618 if ([documentView isKindOfClass:[WebHTMLView class]])
619 [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins];
624 static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue* jsValue)
626 NSAppleEventDescriptor* aeDesc = 0;
627 switch (jsValue->type()) {
629 aeDesc = [NSAppleEventDescriptor descriptorWithBoolean:jsValue->getBoolean()];
632 aeDesc = [NSAppleEventDescriptor descriptorWithString:String(jsValue->getString())];
635 double value = jsValue->getNumber();
636 int intValue = (int)value;
637 if (value == intValue)
638 aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt32 bytes:&intValue length:sizeof(intValue)];
640 aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&value length:sizeof(value)];
644 JSObject* object = jsValue->getObject();
645 if (object->inherits(&DateInstance::info)) {
646 DateInstance* date = static_cast<DateInstance*>(object);
649 if (date->getTime(ms, tzOffset)) {
650 CFAbsoluteTime utcSeconds = ms / 1000 - kCFAbsoluteTimeIntervalSince1970;
652 if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt))
653 aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)];
656 else if (object->inherits(&ArrayInstance::info)) {
657 static HashSet<JSObject*> visitedElems;
658 if (!visitedElems.contains(object)) {
659 visitedElems.add(object);
661 ArrayInstance* array = static_cast<ArrayInstance*>(object);
662 aeDesc = [NSAppleEventDescriptor listDescriptor];
663 unsigned numItems = array->getLength();
664 for (unsigned i = 0; i < numItems; ++i)
665 [aeDesc insertDescriptor:aeDescFromJSValue(exec, array->getItem(i)) atIndex:0];
667 visitedElems.remove(object);
671 JSValue* primitive = object->toPrimitive(exec);
672 if (exec->hadException()) {
673 exec->clearException();
674 return [NSAppleEventDescriptor nullDescriptor];
676 return aeDescFromJSValue(exec, primitive);
681 aeDesc = [NSAppleEventDescriptor descriptorWithTypeCode:cMissingValue];
684 LOG_ERROR("Unknown JavaScript type: %d", jsValue->type());
686 case UnspecifiedType:
688 case GetterSetterType:
689 aeDesc = [NSAppleEventDescriptor nullDescriptor];
696 - (NSString *)_domain
698 Document *doc = _private->coreFrame->document();
700 return doc->domain();
704 - (void)_addData:(NSData *)data
706 Document *doc = _private->coreFrame->document();
708 // Document may be nil if the part is about to redirect
709 // as a result of JS executing during load, i.e. one frame
710 // changing another's location before the frame's document
713 doc->setShouldCreateRenderers(_private->shouldCreateRenderers);
714 _private->coreFrame->loader()->addData((const char *)[data bytes], [data length]);
718 - (NSString *)_stringWithDocumentTypeStringAndMarkupString:(NSString *)markupString
720 return _private->coreFrame->documentTypeString() + markupString;
723 - (NSArray *)_nodesFromList:(Vector<Node*> *)nodesVector
725 size_t size = nodesVector->size();
726 NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:size];
727 for (size_t i = 0; i < size; ++i)
728 [nodes addObject:[DOMNode _wrapNode:(*nodesVector)[i]]];
732 - (NSString *)_markupStringFromNode:(DOMNode *)node nodes:(NSArray **)nodes
734 // FIXME: This is never "for interchange". Is that right? See the next method.
735 Vector<Node*> nodeList;
736 NSString *markupString = createMarkup([node _node], IncludeNode, nodes ? &nodeList : 0);
738 *nodes = [self _nodesFromList:&nodeList];
740 return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
743 - (NSString *)_markupStringFromRange:(DOMRange *)range nodes:(NSArray **)nodes
745 // FIXME: This is always "for interchange". Is that right? See the previous method.
746 Vector<Node*> nodeList;
747 NSString *markupString = createMarkup([range _range], nodes ? &nodeList : 0, AnnotateForInterchange);
749 *nodes = [self _nodesFromList:&nodeList];
751 return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
754 - (NSString *)_selectedString
756 String text = _private->coreFrame->selectedText();
757 text.replace('\\', _private->coreFrame->backslashAsCurrencySymbol());
761 - (NSString *)_stringForRange:(DOMRange *)range
763 // This will give a system malloc'd buffer that can be turned directly into an NSString
765 UChar* buf = plainTextToMallocAllocatedBuffer([range _range], length);
768 return [NSString string];
770 UChar backslashAsCurrencySymbol = _private->coreFrame->backslashAsCurrencySymbol();
771 if (backslashAsCurrencySymbol != '\\')
772 for (unsigned n = 0; n < length; n++)
774 buf[n] = backslashAsCurrencySymbol;
776 // Transfer buffer ownership to NSString
777 return [[[NSString alloc] initWithCharactersNoCopy:buf length:length freeWhenDone:YES] autorelease];
780 - (void)_forceLayoutAdjustingViewSize:(BOOL)flag
782 _private->coreFrame->forceLayout(!flag);
784 _private->coreFrame->view()->adjustViewSize();
787 - (void)_forceLayoutWithMinimumPageWidth:(float)minPageWidth maximumPageWidth:(float)maxPageWidth adjustingViewSize:(BOOL)flag
789 _private->coreFrame->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth, flag);
792 - (void)_sendScrollEvent
794 _private->coreFrame->sendScrollEvent();
797 - (void)_drawRect:(NSRect)rect
799 PlatformGraphicsContext* platformContext = static_cast<PlatformGraphicsContext*>([[NSGraphicsContext currentContext] graphicsPort]);
800 ASSERT([[NSGraphicsContext currentContext] isFlipped]);
801 GraphicsContext context(platformContext);
803 _private->coreFrame->paint(&context, enclosingIntRect(rect));
806 // Used by pagination code called from AppKit when a standalone web page is printed.
807 - (NSArray*)_computePageRectsWithPrintWidthScaleFactor:(float)printWidthScaleFactor printHeight:(float)printHeight
809 NSMutableArray* pages = [NSMutableArray arrayWithCapacity:5];
810 if (printWidthScaleFactor <= 0) {
811 LOG_ERROR("printWidthScaleFactor has bad value %.2f", printWidthScaleFactor);
815 if (printHeight <= 0) {
816 LOG_ERROR("printHeight has bad value %.2f", printHeight);
820 if (!_private->coreFrame || !_private->coreFrame->document() || !_private->coreFrame->view()) return pages;
821 RenderView* root = static_cast<RenderView *>(_private->coreFrame->document()->renderer());
822 if (!root) return pages;
824 FrameView* view = _private->coreFrame->view();
828 NSView* documentView = view->documentView();
832 float currPageHeight = printHeight;
833 float docHeight = root->layer()->height();
834 float docWidth = root->layer()->width();
835 float printWidth = docWidth/printWidthScaleFactor;
837 // We need to give the part the opportunity to adjust the page height at each step.
838 for (float i = 0; i < docHeight; i += currPageHeight) {
839 float proposedBottom = min(docHeight, i + printHeight);
840 _private->coreFrame->adjustPageHeight(&proposedBottom, i, proposedBottom, i);
841 currPageHeight = max(1.0f, proposedBottom - i);
842 for (float j = 0; j < docWidth; j += printWidth) {
843 NSValue* val = [NSValue valueWithRect: NSMakeRect(j, i, printWidth, currPageHeight)];
844 [pages addObject: val];
851 // This is to support the case where a webview is embedded in the view that's being printed
852 - (void)_adjustPageHeightNew:(float *)newBottom top:(float)oldTop bottom:(float)oldBottom limit:(float)bottomLimit
854 _private->coreFrame->adjustPageHeight(newBottom, oldTop, oldBottom, bottomLimit);
857 - (NSObject *)_copyRenderNode:(RenderObject *)node copier:(id <WebCoreRenderTreeCopier>)copier
859 NSMutableArray *children = [[NSMutableArray alloc] init];
860 for (RenderObject *child = node->firstChild(); child; child = child->nextSibling()) {
861 [children addObject:[self _copyRenderNode:child copier:copier]];
864 NSString *name = [[NSString alloc] initWithUTF8String:node->renderName()];
866 RenderWidget* renderWidget = node->isWidget() ? static_cast<RenderWidget*>(node) : 0;
867 Widget* widget = renderWidget ? renderWidget->widget() : 0;
868 NSView *view = widget ? widget->getView() : nil;
871 node->absolutePosition(nx, ny);
872 NSObject *copiedNode = [copier nodeWithName:name
873 position:NSMakePoint(nx,ny)
874 rect:NSMakeRect(node->xPos(), node->yPos(), node->width(), node->height())
884 - (NSObject *)_copyRenderTree:(id <WebCoreRenderTreeCopier>)copier
886 RenderObject *renderer = _private->coreFrame->renderer();
890 return [self _copyRenderNode:renderer copier:copier];
893 static HTMLInputElement* inputElementFromDOMElement(DOMElement* element)
895 Node* node = [element _node];
896 if (node->hasTagName(inputTag))
897 return static_cast<HTMLInputElement*>(node);
901 static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
903 Node *node = [element _node];
904 // This should not be necessary, but an XSL file on
905 // maps.google.com crashes otherwise because it is an xslt file
906 // that contains <form> elements that aren't in any namespace, so
907 // they come out as generic CML elements
908 if (node && node->hasTagName(formTag)) {
909 return static_cast<HTMLFormElement *>(node);
914 - (DOMElement *)_elementWithName:(NSString *)name inForm:(DOMElement *)form
916 HTMLFormElement *formElement = formElementFromDOMElement(form);
918 Vector<HTMLGenericFormElement*>& elements = formElement->formElements;
919 AtomicString targetName = name;
920 for (unsigned int i = 0; i < elements.size(); i++) {
921 HTMLGenericFormElement *elt = elements[i];
922 // Skip option elements, other duds
923 if (elt->name() == targetName)
924 return [DOMElement _wrapElement:elt];
930 - (BOOL)_elementDoesAutoComplete:(DOMElement *)element
932 HTMLInputElement *inputElement = inputElementFromDOMElement(element);
933 return inputElement != nil
934 && inputElement->inputType() == HTMLInputElement::TEXT
935 && inputElement->autoComplete();
938 - (BOOL)_elementIsPassword:(DOMElement *)element
940 HTMLInputElement *inputElement = inputElementFromDOMElement(element);
941 return inputElement != nil
942 && inputElement->inputType() == HTMLInputElement::PASSWORD;
945 - (DOMElement *)_formForElement:(DOMElement *)element;
947 HTMLInputElement *inputElement = inputElementFromDOMElement(element);
949 HTMLFormElement *formElement = inputElement->form();
951 return [DOMElement _wrapElement:formElement];
957 - (DOMElement *)_currentForm
959 return [DOMElement _wrapElement:_private->coreFrame->currentForm()];
962 - (NSArray *)_controlsInForm:(DOMElement *)form
964 NSMutableArray *results = nil;
965 HTMLFormElement *formElement = formElementFromDOMElement(form);
967 Vector<HTMLGenericFormElement*>& elements = formElement->formElements;
968 for (unsigned int i = 0; i < elements.size(); i++) {
969 if (elements.at(i)->isEnumeratable()) { // Skip option elements, other duds
970 DOMElement *de = [DOMElement _wrapElement:elements.at(i)];
972 results = [NSMutableArray arrayWithObject:de];
974 [results addObject:de];
982 - (NSString *)_searchForLabels:(NSArray *)labels beforeElement:(DOMElement *)element
984 return _private->coreFrame->searchForLabelsBeforeElement(labels, [element _element]);
987 - (NSString *)_matchLabels:(NSArray *)labels againstElement:(DOMElement *)element
989 return _private->coreFrame->matchLabelsAgainstElement(labels, [element _element]);
992 - (NSURL *)_URLWithAttributeString:(NSString *)string
994 Document* doc = _private->coreFrame->document();
997 // FIXME: is parseURL appropriate here?
998 return doc->completeURL(parseURL(string));
1001 - (BOOL)_searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection
1003 return _private->coreFrame->findString(string, forward, caseFlag, wrapFlag, startInSelection);
1006 - (unsigned)_markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag limit:(unsigned)limit
1008 return _private->coreFrame->markAllMatchesForText(string, caseFlag, limit);
1011 - (BOOL)_markedTextMatchesAreHighlighted
1013 return _private->coreFrame->markedTextMatchesAreHighlighted();
1016 - (void)_setMarkedTextMatchesAreHighlighted:(BOOL)doHighlight
1018 _private->coreFrame->setMarkedTextMatchesAreHighlighted(doHighlight);
1021 - (void)_unmarkAllTextMatches
1023 Document *doc = _private->coreFrame->document();
1027 doc->removeMarkers(DocumentMarker::TextMatch);
1030 - (NSArray *)_rectsForTextMatches
1032 Document *doc = _private->coreFrame->document();
1034 return [NSArray array];
1036 NSMutableArray *result = [NSMutableArray array];
1037 Vector<IntRect> rects = doc->renderedRectsForMarkers(DocumentMarker::TextMatch);
1038 unsigned count = rects.size();
1039 for (unsigned index = 0; index < count; ++index)
1040 [result addObject:[NSValue valueWithRect:rects[index]]];
1045 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string
1047 return [self _stringByEvaluatingJavaScriptFromString:string forceUserGesture:true];
1050 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture
1052 ASSERT(_private->coreFrame->document());
1054 JSValue* result = _private->coreFrame->loader()->executeScript(string, forceUserGesture);
1056 if (!_private->coreFrame) // In case the script removed our frame from the page.
1059 // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
1060 // If you don't like it, use -[WebScriptObject evaluateWebScript:] or
1061 // JSEvaluateScript instead, since they have less surprising semantics.
1062 if (!result || !result->isBoolean() && !result->isString() && !result->isNumber())
1066 return String(result->toString(_private->coreFrame->scriptProxy()->globalObject()->globalExec()));
1069 - (NSAppleEventDescriptor *)_aeDescByEvaluatingJavaScriptFromString:(NSString *)string
1071 ASSERT(_private->coreFrame->document());
1072 ASSERT(_private->coreFrame == _private->coreFrame->page()->mainFrame());
1073 JSValue* result = _private->coreFrame->loader()->executeScript(string, true);
1074 if (!result) // FIXME: pass errors
1077 return aeDescFromJSValue(_private->coreFrame->scriptProxy()->globalObject()->globalExec(), result);
1080 - (NSRect)_caretRectAtNode:(DOMNode *)node offset:(int)offset affinity:(NSSelectionAffinity)affinity
1082 return [node _node]->renderer()->caretRect(offset, static_cast<EAffinity>(affinity));
1085 - (NSRect)_firstRectForDOMRange:(DOMRange *)range
1087 return _private->coreFrame->firstRectForRange([range _range]);
1090 - (void)_scrollDOMRangeToVisible:(DOMRange *)range
1092 NSRect rangeRect = [self _firstRectForDOMRange:range];
1093 Node *startNode = [[range startContainer] _node];
1095 if (startNode && startNode->renderer()) {
1096 RenderLayer *layer = startNode->renderer()->enclosingLayer();
1098 layer->scrollRectToVisible(enclosingIntRect(rangeRect), RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignToEdgeIfNeeded);
1104 return _private->coreFrame->document()->baseURL();
1107 - (NSString *)_stringWithData:(NSData *)data
1109 Document* doc = _private->coreFrame->document();
1112 TextResourceDecoder* decoder = doc->decoder();
1115 return decoder->encoding().decode(reinterpret_cast<const char*>([data bytes]), [data length]);
1118 + (NSString *)_stringWithData:(NSData *)data textEncodingName:(NSString *)textEncodingName
1120 WebCore::TextEncoding encoding(textEncodingName);
1121 if (!encoding.isValid())
1122 encoding = WindowsLatin1Encoding();
1123 return encoding.decode(reinterpret_cast<const char*>([data bytes]), [data length]);
1126 - (BOOL)_needsLayout
1128 return _private->coreFrame->view() ? _private->coreFrame->view()->needsLayout() : false;
1131 - (NSString *)_renderTreeAsExternalRepresentation
1133 return externalRepresentation(_private->coreFrame->renderer());
1136 - (id)_accessibilityTree
1138 AXObjectCache::enableAccessibility();
1139 if (!_private->coreFrame || !_private->coreFrame->document())
1141 RenderView* root = static_cast<RenderView *>(_private->coreFrame->document()->renderer());
1144 return _private->coreFrame->document()->axObjectCache()->get(root);
1147 - (void)_setBaseBackgroundColor:(NSColor *)backgroundColor
1149 if (_private->coreFrame && _private->coreFrame->view()) {
1150 Color color = colorFromNSColor([backgroundColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]);
1151 _private->coreFrame->view()->setBaseBackgroundColor(color);
1155 - (void)_setDrawsBackground:(BOOL)drawsBackground
1157 if (_private->coreFrame && _private->coreFrame->view())
1158 _private->coreFrame->view()->setTransparent(!drawsBackground);
1161 - (DOMRange *)_rangeByAlteringCurrentSelection:(SelectionController::EAlteration)alteration direction:(SelectionController::EDirection)direction granularity:(TextGranularity)granularity
1163 if (_private->coreFrame->selectionController()->isNone())
1166 SelectionController selectionController;
1167 selectionController.setSelection(_private->coreFrame->selectionController()->selection());
1168 selectionController.modify(alteration, direction, granularity);
1169 return [DOMRange _wrapRange:selectionController.toRange().get()];
1172 - (TextGranularity)_selectionGranularity
1174 return _private->coreFrame->selectionGranularity();
1177 - (NSRange)_convertToNSRange:(Range *)range
1179 if (!range || !range->startContainer())
1180 return NSMakeRange(NSNotFound, 0);
1182 Element* selectionRoot = _private->coreFrame->selectionController()->rootEditableElement();
1183 Element* scope = selectionRoot ? selectionRoot : _private->coreFrame->document()->documentElement();
1185 // Mouse events may cause TSM to attempt to create an NSRange for a portion of the view
1186 // that is not inside the current editable region. These checks ensure we don't produce
1187 // potentially invalid data when responding to such requests.
1188 if (range->startContainer() != scope && !range->startContainer()->isDescendantOf(scope))
1189 return NSMakeRange(NSNotFound, 0);
1190 if (range->endContainer() != scope && !range->endContainer()->isDescendantOf(scope))
1191 return NSMakeRange(NSNotFound, 0);
1193 RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
1194 ASSERT(testRange->startContainer() == scope);
1195 int startPosition = TextIterator::rangeLength(testRange.get());
1198 testRange->setEnd(range->endContainer(), range->endOffset(), ec);
1199 ASSERT(testRange->startContainer() == scope);
1200 int endPosition = TextIterator::rangeLength(testRange.get());
1202 return NSMakeRange(startPosition, endPosition - startPosition);
1205 - (PassRefPtr<Range>)_convertToDOMRange:(NSRange)nsrange
1207 if (nsrange.location > INT_MAX)
1209 if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX)
1210 nsrange.length = INT_MAX - nsrange.location;
1212 // our critical assumption is that we are only called by input methods that
1213 // concentrate on a given area containing the selection
1214 // We have to do this because of text fields and textareas. The DOM for those is not
1215 // directly in the document DOM, so serialization is problematic. Our solution is
1216 // to use the root editable element of the selection start as the positional base.
1217 // That fits with AppKit's idea of an input context.
1218 Element* selectionRoot = _private->coreFrame->selectionController()->rootEditableElement();
1219 Element* scope = selectionRoot ? selectionRoot : _private->coreFrame->document()->documentElement();
1220 return TextIterator::rangeFromLocationAndLength(scope, nsrange.location, nsrange.length);
1223 - (DOMRange *)_convertNSRangeToDOMRange:(NSRange)nsrange
1225 return [DOMRange _wrapRange:[self _convertToDOMRange:nsrange].get()];
1228 - (NSRange)_convertDOMRangeToNSRange:(DOMRange *)range
1230 return [self _convertToNSRange:[range _range]];
1233 - (DOMRange *)_markDOMRange
1235 return [DOMRange _wrapRange:_private->coreFrame->mark().toRange().get()];
1238 - (NSRange)_markedTextNSRange
1240 return [self _convertToNSRange:_private->coreFrame->editor()->compositionRange().get()];
1243 // Given proposedRange, returns an extended range that includes adjacent whitespace that should
1244 // be deleted along with the proposed range in order to preserve proper spacing and punctuation of
1245 // the text surrounding the deletion.
1246 - (DOMRange *)_smartDeleteRangeForProposedRange:(DOMRange *)proposedRange
1248 Node *startContainer = [[proposedRange startContainer] _node];
1249 Node *endContainer = [[proposedRange endContainer] _node];
1250 if (startContainer == nil || endContainer == nil)
1253 ASSERT(startContainer->document() == endContainer->document());
1255 _private->coreFrame->document()->updateLayoutIgnorePendingStylesheets();
1257 Position start(startContainer, [proposedRange startOffset]);
1258 Position end(endContainer, [proposedRange endOffset]);
1259 Position newStart = start.upstream().leadingWhitespacePosition(DOWNSTREAM, true);
1260 if (newStart.isNull())
1262 Position newEnd = end.downstream().trailingWhitespacePosition(DOWNSTREAM, true);
1263 if (newEnd.isNull())
1266 newStart = rangeCompliantEquivalent(newStart);
1267 newEnd = rangeCompliantEquivalent(newEnd);
1269 RefPtr<Range> range = _private->coreFrame->document()->createRange();
1271 range->setStart(newStart.node(), newStart.offset(), exception);
1272 range->setEnd(newStart.node(), newStart.offset(), exception);
1273 return [DOMRange _wrapRange:range.get()];
1276 // Determines whether whitespace needs to be added around aString to preserve proper spacing and
1277 // punctuation when it’s inserted into the receiver’s text over charRange. Returns by reference
1278 // in beforeString and afterString any whitespace that should be added, unless either or both are
1279 // nil. Both are returned as nil if aString is nil or if smart insertion and deletion are disabled.
1280 - (void)_smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString
1282 // give back nil pointers in case of early returns
1284 *beforeString = nil;
1288 // inspect destination
1289 Node *startContainer = [[rangeToReplace startContainer] _node];
1290 Node *endContainer = [[rangeToReplace endContainer] _node];
1292 Position startPos(startContainer, [rangeToReplace startOffset]);
1293 Position endPos(endContainer, [rangeToReplace endOffset]);
1295 VisiblePosition startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY);
1296 VisiblePosition endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY);
1298 // this check also ensures startContainer, startPos, endContainer, and endPos are non-null
1299 if (startVisiblePos.isNull() || endVisiblePos.isNull())
1302 bool addLeadingSpace = startPos.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos);
1303 if (addLeadingSpace)
1304 if (UChar previousChar = startVisiblePos.previous().characterAfter())
1305 addLeadingSpace = !isCharacterSmartReplaceExempt(previousChar, true);
1307 bool addTrailingSpace = endPos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos);
1308 if (addTrailingSpace)
1309 if (UChar thisChar = endVisiblePos.characterAfter())
1310 addTrailingSpace = !isCharacterSmartReplaceExempt(thisChar, false);
1313 bool hasWhitespaceAtStart = false;
1314 bool hasWhitespaceAtEnd = false;
1315 unsigned pasteLength = [pasteString length];
1316 if (pasteLength > 0) {
1317 NSCharacterSet *whiteSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
1319 if ([whiteSet characterIsMember:[pasteString characterAtIndex:0]]) {
1320 hasWhitespaceAtStart = YES;
1322 if ([whiteSet characterIsMember:[pasteString characterAtIndex:(pasteLength - 1)]]) {
1323 hasWhitespaceAtEnd = YES;
1327 // issue the verdict
1328 if (beforeString && addLeadingSpace && !hasWhitespaceAtStart)
1329 *beforeString = @" ";
1330 if (afterString && addTrailingSpace && !hasWhitespaceAtEnd)
1331 *afterString = @" ";
1334 - (DOMDocumentFragment *)_documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString
1336 if (!_private->coreFrame || !_private->coreFrame->document())
1339 return [DOMDocumentFragment _wrapDocumentFragment:createFragmentFromMarkup(_private->coreFrame->document(), markupString, baseURLString).get()];
1342 - (DOMDocumentFragment *)_documentFragmentWithText:(NSString *)text inContext:(DOMRange *)context
1344 return [DOMDocumentFragment _wrapDocumentFragment:createFragmentFromText([context _range], text).get()];
1347 - (DOMDocumentFragment *)_documentFragmentWithNodesAsParagraphs:(NSArray *)nodes
1349 if (!_private->coreFrame || !_private->coreFrame->document())
1352 NSEnumerator *nodeEnum = [nodes objectEnumerator];
1353 Vector<Node*> nodesVector;
1355 while ((node = [nodeEnum nextObject]))
1356 nodesVector.append([node _node]);
1358 return [DOMDocumentFragment _wrapDocumentFragment:createFragmentFromNodes(_private->coreFrame->document(), nodesVector).get()];
1361 - (void)_replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
1363 if (_private->coreFrame->selectionController()->isNone() || !fragment)
1366 applyCommand(new ReplaceSelectionCommand(_private->coreFrame->document(), [fragment _documentFragment], selectReplacement, smartReplace, matchStyle));
1367 _private->coreFrame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
1370 - (void)_replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
1372 DOMDocumentFragment *fragment = [DOMDocumentFragment _wrapDocumentFragment:_private->coreFrame->document()->createDocumentFragment().get()];
1373 [fragment appendChild:node];
1374 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle];
1377 - (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1379 DOMDocumentFragment *fragment = [self _documentFragmentWithMarkupString:markupString baseURLString:baseURLString];
1380 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
1383 - (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1385 [self _replaceSelectionWithFragment:[self _documentFragmentWithText:text
1386 inContext:[DOMRange _wrapRange:_private->coreFrame->selectionController()->toRange().get()]]
1387 selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES];
1390 - (void)_insertParagraphSeparatorInQuotedContent
1392 if (_private->coreFrame->selectionController()->isNone())
1395 TypingCommand::insertParagraphSeparatorInQuotedContent(_private->coreFrame->document());
1396 _private->coreFrame->revealSelection(RenderLayer::gAlignToEdgeIfNeeded);
1399 - (VisiblePosition)_visiblePositionForPoint:(NSPoint)point
1401 IntPoint outerPoint(point);
1402 HitTestResult result = _private->coreFrame->eventHandler()->hitTestResultAtPoint(outerPoint, true);
1403 Node* node = result.innerNode();
1405 return VisiblePosition();
1406 RenderObject* renderer = node->renderer();
1408 return VisiblePosition();
1409 VisiblePosition visiblePos = renderer->positionForCoordinates(result.localPoint().x(), result.localPoint().y());
1410 if (visiblePos.isNull())
1411 visiblePos = VisiblePosition(Position(node, 0));
1415 - (DOMRange *)_characterRangeAtPoint:(NSPoint)point
1417 VisiblePosition position = [self _visiblePositionForPoint:point];
1418 if (position.isNull())
1421 VisiblePosition previous = position.previous();
1422 if (previous.isNotNull()) {
1423 DOMRange *previousCharacterRange = [DOMRange _wrapRange:makeRange(previous, position).get()];
1424 NSRect rect = [self _firstRectForDOMRange:previousCharacterRange];
1425 if (NSPointInRect(point, rect))
1426 return previousCharacterRange;
1429 VisiblePosition next = position.next();
1430 if (next.isNotNull()) {
1431 DOMRange *nextCharacterRange = [DOMRange _wrapRange:makeRange(position, next).get()];
1432 NSRect rect = [self _firstRectForDOMRange:nextCharacterRange];
1433 if (NSPointInRect(point, rect))
1434 return nextCharacterRange;
1440 - (DOMCSSStyleDeclaration *)_typingStyle
1442 if (!_private->coreFrame || !_private->coreFrame->typingStyle())
1444 return [DOMCSSStyleDeclaration _wrapCSSStyleDeclaration:_private->coreFrame->typingStyle()->copy().get()];
1447 - (void)_setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(EditAction)undoAction
1449 if (!_private->coreFrame)
1451 _private->coreFrame->computeAndSetTypingStyle([style _CSSStyleDeclaration], undoAction);
1454 - (NSFont *)_fontForSelection:(BOOL *)hasMultipleFonts
1456 bool multipleFonts = false;
1458 if (_private->coreFrame) {
1459 const SimpleFontData* fd = _private->coreFrame->editor()->fontForSelection(multipleFonts);
1461 font = fd->getNSFont();
1464 if (hasMultipleFonts)
1465 *hasMultipleFonts = multipleFonts;
1469 - (void)_dragSourceMovedTo:(NSPoint)windowLoc
1471 if (!_private->coreFrame)
1473 FrameView* view = _private->coreFrame->view();
1476 // FIXME: These are fake modifier keys here, but they should be real ones instead.
1477 PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->getView() window]),
1478 LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime());
1479 _private->coreFrame->eventHandler()->dragSourceMovedTo(event);
1482 - (void)_dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation
1484 if (!_private->coreFrame)
1486 FrameView* view = _private->coreFrame->view();
1489 // FIXME: These are fake modifier keys here, but they should be real ones instead.
1490 PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->getView() window]),
1491 LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime());
1492 _private->coreFrame->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation);
1495 - (BOOL)_getData:(NSData **)data andResponse:(NSURLResponse **)response forURL:(NSString *)url
1497 Document* doc = _private->coreFrame->document();
1501 CachedResource* resource = doc->docLoader()->cachedResource(url);
1505 SharedBuffer* buffer = resource->data();
1507 *data = [buffer->createNSData() autorelease];
1511 *response = resource->response().nsURLResponse();
1515 - (void)_getAllResourceDatas:(NSArray **)datas andResponses:(NSArray **)responses
1517 Document* doc = _private->coreFrame->document();
1519 NSArray* emptyArray = [NSArray array];
1520 *datas = emptyArray;
1521 *responses = emptyArray;
1525 const HashMap<String, CachedResource*>& allResources = doc->docLoader()->allCachedResources();
1527 NSMutableArray *d = [[NSMutableArray alloc] initWithCapacity:allResources.size()];
1528 NSMutableArray *r = [[NSMutableArray alloc] initWithCapacity:allResources.size()];
1530 HashMap<String, CachedResource*>::const_iterator end = allResources.end();
1531 for (HashMap<String, CachedResource*>::const_iterator it = allResources.begin(); it != end; ++it) {
1532 SharedBuffer* buffer = it->second->data();
1535 data = buffer->createNSData();
1537 data = [[NSData alloc] init];
1540 [r addObject:it->second->response().nsURLResponse()];
1543 *datas = [d autorelease];
1544 *responses = [r autorelease];
1547 - (BOOL)_canProvideDocumentSource
1549 String mimeType = _private->coreFrame->loader()->responseMIMEType();
1551 if (WebCore::DOMImplementation::isTextMIMEType(mimeType) ||
1552 Image::supportsType(mimeType) ||
1553 (_private->coreFrame->page() && _private->coreFrame->page()->pluginData()->supportsMimeType(mimeType)))
1559 - (BOOL)_canSaveAsWebArchive
1561 // Currently, all documents that we can view source for
1562 // (HTML and XML documents) can also be saved as web archives
1563 return [self _canProvideDocumentSource];
1566 - (void)_receivedData:(NSData *)data textEncodingName:(NSString *)textEncodingName
1568 // Set the encoding. This only needs to be done once, but it's harmless to do it again later.
1570 if (_private->coreFrame)
1571 encoding = _private->coreFrame->loader()->documentLoader()->overrideEncoding();
1572 bool userChosen = !encoding.isNull();
1573 if (encoding.isNull())
1574 encoding = textEncodingName;
1575 _private->coreFrame->loader()->setEncoding(encoding, userChosen);
1576 [self _addData:data];
1581 @implementation WebFrame (WebPrivate)
1583 // FIXME: Yhis exists only as a convenience for Safari, consider moving there.
1584 - (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor
1586 Frame* coreFrame = core(self);
1587 return coreFrame && coreFrame->tree()->isDescendantOf(core(ancestor));
1590 - (void)_setShouldCreateRenderers:(BOOL)shouldCreateRenderers
1592 _private->shouldCreateRenderers = shouldCreateRenderers;
1595 - (NSColor *)_bodyBackgroundColor
1597 Document* document = core(self)->document();
1600 HTMLElement* body = document->body();
1603 RenderObject* bodyRenderer = body->renderer();
1606 Color color = bodyRenderer->style()->backgroundColor();
1607 if (!color.isValid())
1609 return nsColor(color);
1614 return core(self)->isFrameSet();
1617 - (BOOL)_firstLayoutDone
1619 return [self _frameLoader]->firstLayoutDone();
1622 - (WebFrameLoadType)_loadType
1624 return (WebFrameLoadType)[self _frameLoader]->loadType();
1627 - (NSRange)_selectedNSRange
1629 return [self _convertToNSRange:_private->coreFrame->selectionController()->toRange().get()];
1632 - (void)_selectNSRange:(NSRange)range
1634 RefPtr<Range> domRange = [self _convertToDOMRange:range];
1636 _private->coreFrame->selectionController()->setSelection(Selection(domRange.get(), SEL_DEFAULT_AFFINITY));
1639 - (BOOL)_isDisplayingStandaloneImage
1641 Document* document = core(self)->document();
1642 return document && document->isImageDocument();
1647 @implementation WebFrame
1654 // Should be deprecated.
1655 - (id)initWithName:(NSString *)name webFrameView:(WebFrameView *)view webView:(WebView *)webView
1675 Frame* coreFrame = core(self);
1678 return coreFrame->tree()->name();
1681 - (WebFrameView *)frameView
1683 return _private->webFrameView;
1686 - (WebView *)webView
1688 return getWebView(self);
1691 - (DOMDocument *)DOMDocument
1693 Frame* coreFrame = core(self);
1697 // FIXME: <rdar://problem/5145841> When loading a custom view/representation
1698 // into a web frame, the old document can still be around. This makes sure that
1699 // we'll return nil in those cases.
1700 if (![[self _dataSource] _isDocumentHTML])
1703 Document* document = coreFrame->document();
1705 // According to the documentation, we should return nil if the frame doesn't have a document.
1706 // While full-frame images and plugins do have an underlying HTML document, we return nil here to be
1707 // backwards compatible.
1708 if (document && (document->isPluginDocument() || document->isImageDocument()))
1711 return kit(coreFrame->document());
1714 - (DOMHTMLElement *)frameElement
1716 Frame* coreFrame = core(self);
1719 return kit(coreFrame->ownerElement());
1722 - (WebDataSource *)provisionalDataSource
1724 FrameLoader* frameLoader = [self _frameLoader];
1725 return frameLoader ? dataSource(frameLoader->provisionalDocumentLoader()) : nil;
1728 - (WebDataSource *)dataSource
1730 FrameLoader* loader = [self _frameLoader];
1731 if (!loader || !loader->frameHasLoaded())
1734 return [self _dataSource];
1737 - (void)loadRequest:(NSURLRequest *)request
1739 [self _frameLoader]->load(request);
1742 static NSURL *createUniqueWebDataURL()
1744 CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
1745 NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
1747 NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"applewebdata://%@", UUIDString]];
1748 CFRelease(UUIDString);
1752 - (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
1756 baseURL = blankURL();
1757 responseURL = createUniqueWebDataURL();
1760 ResourceRequest request([baseURL absoluteURL]);
1762 // hack because Mail checks for this property to detect data / archive loads
1763 [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest()];
1765 SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData(data), MIMEType, encodingName, [unreachableURL absoluteURL], responseURL);
1767 [self _frameLoader]->load(request, substituteData);
1771 - (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL
1774 MIMEType = @"text/html";
1775 [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:nil];
1778 - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
1780 NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
1781 [self _loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:baseURL unreachableURL:unreachableURL];
1784 - (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL
1786 [self _loadHTMLString:string baseURL:baseURL unreachableURL:nil];
1789 - (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL
1791 [self _loadHTMLString:string baseURL:baseURL unreachableURL:unreachableURL];
1794 - (void)loadArchive:(WebArchive *)archive
1796 WebResource *mainResource = [archive mainResource];
1798 SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData([mainResource data]), [mainResource MIMEType], [mainResource textEncodingName], KURL());
1799 ResourceRequest request([mainResource URL]);
1801 // hack because Mail checks for this property to detect data / archive loads
1802 [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest()];
1804 RefPtr<DocumentLoader> documentLoader = core(self)->loader()->client()->createDocumentLoader(request, substituteData);
1806 [dataSource(documentLoader.get()) _addToUnarchiveState:archive];
1808 [self _frameLoader]->load(documentLoader.get());
1814 if (FrameLoader* frameLoader = [self _frameLoader])
1815 frameLoader->stopForUserCancel();
1820 [self _frameLoader]->reload();
1823 - (WebFrame *)findFrameNamed:(NSString *)name
1825 Frame* coreFrame = core(self);
1828 return kit(coreFrame->tree()->find(name));
1831 - (WebFrame *)parentFrame
1833 Frame* coreFrame = core(self);
1836 return [[kit(coreFrame->tree()->parent()) retain] autorelease];
1839 - (NSArray *)childFrames
1841 Frame* coreFrame = core(self);
1843 return [NSArray array];
1844 NSMutableArray *children = [NSMutableArray arrayWithCapacity:coreFrame->tree()->childCount()];
1845 for (Frame* child = coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1846 [children addObject:kit(child)];
1850 - (WebScriptObject *)windowObject
1852 Frame* coreFrame = core(self);
1855 return coreFrame->windowScriptObject();
1858 - (JSGlobalContextRef)globalContext
1860 Frame* coreFrame = core(self);
1863 return toGlobalRef(coreFrame->scriptProxy()->globalObject()->globalExec());