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 "WebArchiveInternal.h"
39 #import "WebChromeClient.h"
40 #import "WebDataSourceInternal.h"
41 #import "WebDocumentLoaderMac.h"
42 #import "WebDynamicScrollBarsView.h"
43 #import "WebFrameLoaderClient.h"
44 #import "WebFrameViewInternal.h"
45 #import "WebHTMLView.h"
46 #import "WebHTMLViewInternal.h"
47 #import "WebKitStatisticsPrivate.h"
48 #import "WebKitVersionChecks.h"
49 #import "WebNSObjectExtras.h"
50 #import "WebNSURLExtras.h"
51 #import "WebScriptDebugger.h"
52 #import "WebScriptWorldInternal.h"
53 #import "WebViewInternal.h"
54 #import <JavaScriptCore/APICast.h>
55 #import <WebCore/AXObjectCache.h>
56 #import <WebCore/AccessibilityObject.h>
57 #import <WebCore/AnimationController.h>
58 #import <WebCore/CSSMutableStyleDeclaration.h>
59 #import <WebCore/CachedResourceLoader.h>
60 #import <WebCore/Chrome.h>
61 #import <WebCore/ColorMac.h>
62 #import <WebCore/DOMImplementation.h>
63 #import <WebCore/DocumentFragment.h>
64 #import <WebCore/DocumentLoader.h>
65 #import <WebCore/DocumentMarkerController.h>
66 #import <WebCore/EventHandler.h>
67 #import <WebCore/EventNames.h>
68 #import <WebCore/Frame.h>
69 #import <WebCore/FrameLoader.h>
70 #import <WebCore/FrameLoaderStateMachine.h>
71 #import <WebCore/FrameTree.h>
72 #import <WebCore/GraphicsContext.h>
73 #import <WebCore/HTMLFrameOwnerElement.h>
74 #import <WebCore/HTMLNames.h>
75 #import <WebCore/HistoryItem.h>
76 #import <WebCore/HitTestResult.h>
77 #import <WebCore/LegacyWebArchive.h>
78 #import <WebCore/Page.h>
79 #import <WebCore/PluginData.h>
80 #import <WebCore/PrintContext.h>
81 #import <WebCore/RenderLayer.h>
82 #import <WebCore/RenderPart.h>
83 #import <WebCore/RenderView.h>
84 #import <WebCore/ReplaceSelectionCommand.h>
85 #import <WebCore/RuntimeApplicationChecks.h>
86 #import <WebCore/ScriptValue.h>
87 #import <WebCore/SecurityOrigin.h>
88 #import <WebCore/SmartReplace.h>
89 #import <WebCore/SVGDocumentExtensions.h>
90 #import <WebCore/SVGSMILElement.h>
91 #import <WebCore/TextIterator.h>
92 #import <WebCore/ThreadCheck.h>
93 #import <WebCore/TypingCommand.h>
94 #import <WebCore/htmlediting.h>
95 #import <WebCore/markup.h>
96 #import <WebCore/visible_units.h>
97 #import <WebKitSystemInterface.h>
98 #import <runtime/JSLock.h>
99 #import <runtime/JSObject.h>
100 #import <runtime/JSValue.h>
101 #import <wtf/CurrentTime.h>
104 using namespace WebCore;
105 using namespace HTMLNames;
107 using JSC::JSGlobalObject;
110 using JSC::SilenceAssertionsOnly;
113 Here is the current behavior matrix for four types of navigations:
117 Restore form state: YES
118 Restore scroll and focus state: YES
119 Cache policy: NSURLRequestUseProtocolCachePolicy
120 Add to back/forward list: YES
124 Restore form state: YES
125 Restore scroll and focus state: YES
126 Cache policy: NSURLRequestReturnCacheDataElseLoad
127 Add to back/forward list: NO
129 Reload (meaning only the reload button):
131 Restore form state: NO
132 Restore scroll and focus state: YES
133 Cache policy: NSURLRequestReloadIgnoringCacheData
134 Add to back/forward list: NO
136 Repeat load of the same URL (by any other means of navigation other than the reload button, including hitting return in the location field):
138 Restore form state: NO
139 Restore scroll and focus state: NO, reset to initial conditions
140 Cache policy: NSURLRequestReloadIgnoringCacheData
141 Add to back/forward list: NO
144 NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey";
145 NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey";
146 NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
148 NSString *WebFrameMainDocumentError = @"WebFrameMainDocumentErrorKey";
149 NSString *WebFrameHasPlugins = @"WebFrameHasPluginsKey";
150 NSString *WebFrameHasUnloadListener = @"WebFrameHasUnloadListenerKey";
151 NSString *WebFrameUsesDatabases = @"WebFrameUsesDatabasesKey";
152 NSString *WebFrameUsesGeolocation = @"WebFrameUsesGeolocationKey";
153 NSString *WebFrameUsesApplicationCache = @"WebFrameUsesApplicationCacheKey";
154 NSString *WebFrameCanSuspendActiveDOMObjects = @"WebFrameCanSuspendActiveDOMObjectsKey";
156 // FIXME: Remove when this key becomes publicly defined
157 NSString *NSAccessibilityEnhancedUserInterfaceAttribute = @"AXEnhancedUserInterface";
159 @implementation WebFramePrivate
163 [webFrameView release];
165 delete scriptDebugger;
172 delete scriptDebugger;
177 - (void)setWebFrameView:(WebFrameView *)v
180 [webFrameView release];
186 EditableLinkBehavior core(WebKitEditableLinkBehavior editableLinkBehavior)
188 switch (editableLinkBehavior) {
189 case WebKitEditableLinkDefaultBehavior:
190 return EditableLinkDefaultBehavior;
191 case WebKitEditableLinkAlwaysLive:
192 return EditableLinkAlwaysLive;
193 case WebKitEditableLinkOnlyLiveWithShiftKey:
194 return EditableLinkOnlyLiveWithShiftKey;
195 case WebKitEditableLinkLiveWhenNotFocused:
196 return EditableLinkLiveWhenNotFocused;
197 case WebKitEditableLinkNeverLive:
198 return EditableLinkNeverLive;
200 ASSERT_NOT_REACHED();
201 return EditableLinkDefaultBehavior;
204 WebCore::EditingBehaviorType core(WebKitEditingBehavior behavior)
207 case WebKitEditingMacBehavior:
208 return WebCore::EditingMacBehavior;
209 case WebKitEditingWinBehavior:
210 return WebCore::EditingWindowsBehavior;
211 case WebKitEditingUnixBehavior:
212 return WebCore::EditingUnixBehavior;
214 ASSERT_NOT_REACHED();
215 return WebCore::EditingMacBehavior;
218 TextDirectionSubmenuInclusionBehavior core(WebTextDirectionSubmenuInclusionBehavior behavior)
221 case WebTextDirectionSubmenuNeverIncluded:
222 return TextDirectionSubmenuNeverIncluded;
223 case WebTextDirectionSubmenuAutomaticallyIncluded:
224 return TextDirectionSubmenuAutomaticallyIncluded;
225 case WebTextDirectionSubmenuAlwaysIncluded:
226 return TextDirectionSubmenuAlwaysIncluded;
228 ASSERT_NOT_REACHED();
229 return TextDirectionSubmenuNeverIncluded;
232 @implementation WebFrame (WebInternal)
234 Frame* core(WebFrame *frame)
236 return frame ? frame->_private->coreFrame : 0;
239 WebFrame *kit(Frame* frame)
241 return frame ? static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame() : nil;
244 Page* core(WebView *webView)
246 return [webView page];
249 WebView *kit(Page* page)
251 return page ? static_cast<WebView*>(page->chrome()->client()->webView()) : nil;
254 WebView *getWebView(WebFrame *webFrame)
256 Frame* coreFrame = core(webFrame);
259 return kit(coreFrame->page());
262 + (PassRefPtr<Frame>)_createFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView ownerElement:(HTMLFrameOwnerElement*)ownerElement
264 WebView *webView = kit(page);
266 WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView];
267 RefPtr<Frame> coreFrame = Frame::create(page, ownerElement, new WebFrameLoaderClient(frame));
269 frame->_private->coreFrame = coreFrame.get();
271 coreFrame->tree()->setName(name);
273 ASSERT(ownerElement->document()->frame());
274 ownerElement->document()->frame()->tree()->appendChild(coreFrame.get());
279 [webView _setZoomMultiplier:[webView _realZoomMultiplier] isTextOnly:[webView _realZoomMultiplierIsTextOnly]];
281 return coreFrame.release();
284 + (void)_createMainFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView
286 [self _createFrameWithPage:page frameName:name frameView:frameView ownerElement:0];
289 + (PassRefPtr<WebCore::Frame>)_createSubframeWithOwnerElement:(HTMLFrameOwnerElement*)ownerElement frameName:(const String&)name frameView:(WebFrameView *)frameView
291 return [self _createFrameWithPage:ownerElement->document()->frame()->page() frameName:name frameView:frameView ownerElement:ownerElement];
294 - (BOOL)_isIncludedInWebKitStatistics
296 return _private && _private->includedInWebKitStatistics;
299 - (void)_attachScriptDebugger
301 ScriptController* scriptController = _private->coreFrame->script();
303 // Calling ScriptController::globalObject() would create a window shell, and dispatch corresponding callbacks, which may be premature
304 // if the script debugger is attached before a document is created. These calls use the debuggerWorld(), we will need to pass a world
305 // to be able to debug isolated worlds.
306 if (!scriptController->existingWindowShell(debuggerWorld()))
309 JSGlobalObject* globalObject = scriptController->globalObject(debuggerWorld());
313 if (_private->scriptDebugger) {
314 ASSERT(_private->scriptDebugger == globalObject->debugger());
318 _private->scriptDebugger = new WebScriptDebugger(globalObject);
321 - (void)_detachScriptDebugger
323 if (!_private->scriptDebugger)
326 delete _private->scriptDebugger;
327 _private->scriptDebugger = 0;
330 - (id)_initWithWebFrameView:(WebFrameView *)fv webView:(WebView *)v
336 _private = [[WebFramePrivate alloc] init];
338 // Set includedInWebKitStatistics before calling WebFrameView _setWebFrame, since
339 // it calls WebFrame _isIncludedInWebKitStatistics.
340 if ((_private->includedInWebKitStatistics = [[v class] shouldIncludeInWebKitStatistics]))
344 [_private setWebFrameView:fv];
345 [fv _setWebFrame:self];
348 _private->shouldCreateRenderers = YES;
353 - (void)_clearCoreFrame
355 _private->coreFrame = 0;
358 - (void)_updateBackgroundAndUpdatesWhileOffscreen
360 WebView *webView = getWebView(self);
361 BOOL drawsBackground = [webView drawsBackground];
362 NSColor *backgroundColor = [webView backgroundColor];
364 Frame* coreFrame = _private->coreFrame;
365 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
366 if ([webView _usesDocumentViews]) {
367 // Don't call setDrawsBackground:YES here because it may be NO because of a load
368 // in progress; WebFrameLoaderClient keeps it set to NO during the load process.
369 WebFrame *webFrame = kit(frame);
370 if (!drawsBackground)
371 [[[webFrame frameView] _scrollView] setDrawsBackground:NO];
372 [[[webFrame frameView] _scrollView] setBackgroundColor:backgroundColor];
373 id documentView = [[webFrame frameView] documentView];
374 if ([documentView respondsToSelector:@selector(setDrawsBackground:)])
375 [documentView setDrawsBackground:drawsBackground];
376 if ([documentView respondsToSelector:@selector(setBackgroundColor:)])
377 [documentView setBackgroundColor:backgroundColor];
380 if (FrameView* view = frame->view()) {
381 view->setTransparent(!drawsBackground);
382 view->setBaseBackgroundColor(colorFromNSColor([backgroundColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]));
383 view->setShouldUpdateWhileOffscreen([webView shouldUpdateWhileOffscreen]);
388 - (void)_setInternalLoadDelegate:(id)internalLoadDelegate
390 _private->internalLoadDelegate = internalLoadDelegate;
393 - (id)_internalLoadDelegate
395 return _private->internalLoadDelegate;
398 - (void)_unmarkAllBadGrammar
400 Frame* coreFrame = _private->coreFrame;
401 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
402 if (Document* document = frame->document())
403 document->markers()->removeMarkers(DocumentMarker::Grammar);
407 - (void)_unmarkAllMisspellings
409 Frame* coreFrame = _private->coreFrame;
410 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
411 if (Document* document = frame->document())
412 document->markers()->removeMarkers(DocumentMarker::Spelling);
416 - (BOOL)_hasSelection
418 if ([getWebView(self) _usesDocumentViews]) {
419 id documentView = [_private->webFrameView documentView];
421 // optimization for common case to avoid creating potentially large selection string
422 if ([documentView isKindOfClass:[WebHTMLView class]])
423 if (Frame* coreFrame = _private->coreFrame)
424 return coreFrame->selection()->isRange();
426 if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
427 return [[documentView selectedString] length] > 0;
432 Frame* coreFrame = _private->coreFrame;
433 return coreFrame && coreFrame->selection()->isRange();
436 - (void)_clearSelection
438 ASSERT([getWebView(self) _usesDocumentViews]);
439 id documentView = [_private->webFrameView documentView];
440 if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
441 [documentView deselectAll];
445 - (BOOL)_atMostOneFrameHasSelection
447 // FIXME: 4186050 is one known case that makes this debug check fail.
449 Frame* coreFrame = _private->coreFrame;
450 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
451 if ([kit(frame) _hasSelection]) {
460 - (WebFrame *)_findFrameWithSelection
462 Frame* coreFrame = _private->coreFrame;
463 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
464 WebFrame *webFrame = kit(frame);
465 if ([webFrame _hasSelection])
471 - (void)_clearSelectionInOtherFrames
473 // We rely on WebDocumentSelection protocol implementors to call this method when they become first
474 // responder. It would be nicer to just notice first responder changes here instead, but there's no
475 // notification sent when the first responder changes in general (Radar 2573089).
476 WebFrame *frameWithSelection = [[getWebView(self) mainFrame] _findFrameWithSelection];
477 if (frameWithSelection != self)
478 [frameWithSelection _clearSelection];
480 // While we're in the general area of selection and frames, check that there is only one now.
481 ASSERT([[getWebView(self) mainFrame] _atMostOneFrameHasSelection]);
484 static inline WebDataSource *dataSource(DocumentLoader* loader)
486 return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
489 - (WebDataSource *)_dataSource
491 return dataSource(_private->coreFrame->loader()->documentLoader());
494 - (NSString *)_stringWithDocumentTypeStringAndMarkupString:(NSString *)markupString
496 return String(_private->coreFrame->documentTypeString() + String(markupString));
499 - (NSArray *)_nodesFromList:(Vector<Node*> *)nodesVector
501 size_t size = nodesVector->size();
502 NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:size];
503 for (size_t i = 0; i < size; ++i)
504 [nodes addObject:kit((*nodesVector)[i])];
508 - (NSString *)_markupStringFromRange:(DOMRange *)range nodes:(NSArray **)nodes
510 // FIXME: This is always "for interchange". Is that right? See the previous method.
511 Vector<Node*> nodeList;
512 NSString *markupString = createMarkup(core(range), nodes ? &nodeList : 0, AnnotateForInterchange);
514 *nodes = [self _nodesFromList:&nodeList];
516 return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
519 - (NSString *)_selectedString
521 return _private->coreFrame->displayStringModifiedByEncoding(_private->coreFrame->editor()->selectedText());
524 - (NSString *)_stringForRange:(DOMRange *)range
526 // This will give a system malloc'd buffer that can be turned directly into an NSString
528 UChar* buf = plainTextToMallocAllocatedBuffer(core(range), length, true);
531 return [NSString string];
533 // Transfer buffer ownership to NSString
534 return [[[NSString alloc] initWithCharactersNoCopy:buf length:length freeWhenDone:YES] autorelease];
537 - (BOOL)_shouldFlattenCompositingLayers:(CGContextRef)context
539 // -currentContextDrawingToScreen returns YES for bitmap contexts.
540 BOOL isPrinting = ![NSGraphicsContext currentContextDrawingToScreen];
544 if (!WKCGContextIsBitmapContext(context))
547 // If we're drawing into a bitmap, we might be snapshotting, or drawing into a layer-backed view.
548 if ([getWebView(self) _usesDocumentViews]) {
549 id documentView = [_private->webFrameView documentView];
550 if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _web_isDrawingIntoLayer])
554 return [getWebView(self) _includesFlattenedCompositingLayersWhenDrawingToBitmap];
557 - (void)_drawRect:(NSRect)rect contentsOnly:(BOOL)contentsOnly
559 ASSERT([[NSGraphicsContext currentContext] isFlipped]);
561 CGContextRef ctx = static_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]);
562 GraphicsContext context(ctx);
564 FrameView* view = _private->coreFrame->view();
566 bool shouldFlatten = false;
567 if (Frame* parentFrame = _private->coreFrame->tree()->parent()) {
568 // For subframes, we need to inherit the paint behavior from our parent
569 FrameView* parentView = parentFrame ? parentFrame->view() : 0;
571 shouldFlatten = parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
573 shouldFlatten = [self _shouldFlattenCompositingLayers:ctx];
575 PaintBehavior oldBehavior = PaintBehaviorNormal;
577 oldBehavior = view->paintBehavior();
578 view->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
582 view->paintContents(&context, enclosingIntRect(rect));
584 view->paint(&context, enclosingIntRect(rect));
587 view->setPaintBehavior(oldBehavior);
590 - (BOOL)_getVisibleRect:(NSRect*)rect
592 ASSERT_ARG(rect, rect);
593 if (RenderPart* ownerRenderer = _private->coreFrame->ownerRenderer()) {
594 if (ownerRenderer->needsLayout())
596 *rect = ownerRenderer->absoluteClippedOverflowRect();
603 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string
605 return [self _stringByEvaluatingJavaScriptFromString:string forceUserGesture:true];
608 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture
610 ASSERT(_private->coreFrame->document());
611 RetainPtr<WebFrame> protect(self); // Executing arbitrary JavaScript can destroy the frame.
613 JSValue result = _private->coreFrame->script()->executeScript(string, forceUserGesture).jsValue();
615 if (!_private->coreFrame) // In case the script removed our frame from the page.
618 // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
619 // If you don't like it, use -[WebScriptObject evaluateWebScript:] or
620 // JSEvaluateScript instead, since they have less surprising semantics.
621 if (!result || (!result.isBoolean() && !result.isString() && !result.isNumber()))
624 JSLock lock(SilenceAssertionsOnly);
625 return ustringToString(result.toString(_private->coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec()));
628 - (NSRect)_caretRectAtPosition:(const Position&)pos affinity:(NSSelectionAffinity)affinity
630 VisiblePosition visiblePosition(pos, static_cast<EAffinity>(affinity));
631 return visiblePosition.absoluteCaretBounds();
634 - (NSRect)_firstRectForDOMRange:(DOMRange *)range
636 return _private->coreFrame->editor()->firstRectForRange(core(range));
639 - (void)_scrollDOMRangeToVisible:(DOMRange *)range
641 NSRect rangeRect = [self _firstRectForDOMRange:range];
642 Node *startNode = core([range startContainer]);
644 if (startNode && startNode->renderer()) {
645 RenderLayer *layer = startNode->renderer()->enclosingLayer();
647 layer->scrollRectToVisible(enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
653 return _private->coreFrame->view() ? _private->coreFrame->view()->needsLayout() : false;
656 - (DOMRange *)_rangeByAlteringCurrentSelection:(FrameSelection::EAlteration)alteration direction:(SelectionDirection)direction granularity:(TextGranularity)granularity
658 if (_private->coreFrame->selection()->isNone())
661 FrameSelection selection;
662 selection.setSelection(_private->coreFrame->selection()->selection());
663 selection.modify(alteration, direction, granularity);
664 return kit(selection.toNormalizedRange().get());
667 - (TextGranularity)_selectionGranularity
669 return _private->coreFrame->selection()->granularity();
672 - (NSRange)_convertToNSRange:(Range *)range
675 return NSMakeRange(NSNotFound, 0);
679 if (!TextIterator::locationAndLengthFromRange(range, location, length))
680 return NSMakeRange(NSNotFound, 0);
682 return NSMakeRange(location, length);
685 - (PassRefPtr<Range>)_convertToDOMRange:(NSRange)nsrange
687 if (nsrange.location > INT_MAX)
689 if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX)
690 nsrange.length = INT_MAX - nsrange.location;
692 // our critical assumption is that we are only called by input methods that
693 // concentrate on a given area containing the selection
694 // We have to do this because of text fields and textareas. The DOM for those is not
695 // directly in the document DOM, so serialization is problematic. Our solution is
696 // to use the root editable element of the selection start as the positional base.
697 // That fits with AppKit's idea of an input context.
698 Element* selectionRoot = _private->coreFrame->selection()->rootEditableElement();
699 Element* scope = selectionRoot ? selectionRoot : _private->coreFrame->document()->documentElement();
700 return TextIterator::rangeFromLocationAndLength(scope, nsrange.location, nsrange.length);
703 - (DOMRange *)convertNSRangeToDOMRange:(NSRange)nsrange
705 // This method exists to maintain compatibility with Leopard's Dictionary.app. <rdar://problem/6002160>
706 return [self _convertNSRangeToDOMRange:nsrange];
709 - (DOMRange *)_convertNSRangeToDOMRange:(NSRange)nsrange
711 return kit([self _convertToDOMRange:nsrange].get());
714 - (NSRange)convertDOMRangeToNSRange:(DOMRange *)range
716 // This method exists to maintain compatibility with Leopard's Dictionary.app. <rdar://problem/6002160>
717 return [self _convertDOMRangeToNSRange:range];
720 - (NSRange)_convertDOMRangeToNSRange:(DOMRange *)range
722 return [self _convertToNSRange:core(range)];
725 - (DOMRange *)_markDOMRange
727 return kit(_private->coreFrame->editor()->mark().toNormalizedRange().get());
730 // Given proposedRange, returns an extended range that includes adjacent whitespace that should
731 // be deleted along with the proposed range in order to preserve proper spacing and punctuation of
732 // the text surrounding the deletion.
733 - (DOMRange *)_smartDeleteRangeForProposedRange:(DOMRange *)proposedRange
735 Node* startContainer = core([proposedRange startContainer]);
736 Node* endContainer = core([proposedRange endContainer]);
737 if (startContainer == nil || endContainer == nil)
740 ASSERT(startContainer->document() == endContainer->document());
742 _private->coreFrame->document()->updateLayoutIgnorePendingStylesheets();
744 Position start = Position(startContainer, [proposedRange startOffset], Position::PositionIsOffsetInAnchor);
745 Position end = Position(endContainer, [proposedRange endOffset], Position::PositionIsOffsetInAnchor);
746 Position newStart = start.upstream().leadingWhitespacePosition(DOWNSTREAM, true);
747 if (newStart.isNull())
749 Position newEnd = end.downstream().trailingWhitespacePosition(DOWNSTREAM, true);
753 newStart = newStart.parentAnchoredEquivalent();
754 newEnd = newEnd.parentAnchoredEquivalent();
756 RefPtr<Range> range = _private->coreFrame->document()->createRange();
758 range->setStart(newStart.containerNode(), newStart.offsetInContainerNode(), exception);
759 range->setEnd(newStart.containerNode(), newStart.offsetInContainerNode(), exception);
760 return kit(range.get());
763 - (DOMDocumentFragment *)_documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString
765 if (!_private->coreFrame || !_private->coreFrame->document())
768 return kit(createFragmentFromMarkup(_private->coreFrame->document(), markupString, baseURLString, FragmentScriptingNotAllowed).get());
771 - (DOMDocumentFragment *)_documentFragmentWithNodesAsParagraphs:(NSArray *)nodes
773 if (!_private->coreFrame || !_private->coreFrame->document())
776 NSEnumerator *nodeEnum = [nodes objectEnumerator];
777 Vector<Node*> nodesVector;
779 while ((node = [nodeEnum nextObject]))
780 nodesVector.append(core(node));
782 return kit(createFragmentFromNodes(_private->coreFrame->document(), nodesVector).get());
785 - (void)_replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
787 DOMDocumentFragment *fragment = kit(_private->coreFrame->document()->createDocumentFragment().get());
788 [fragment appendChild:node];
789 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle];
792 - (void)_insertParagraphSeparatorInQuotedContent
794 if (_private->coreFrame->selection()->isNone())
797 TypingCommand::insertParagraphSeparatorInQuotedContent(_private->coreFrame->document());
798 _private->coreFrame->selection()->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
801 - (VisiblePosition)_visiblePositionForPoint:(NSPoint)point
803 // FIXME: Someone with access to Apple's sources could remove this needless wrapper call.
804 return _private->coreFrame->visiblePositionForPoint(IntPoint(point));
807 - (DOMRange *)_characterRangeAtPoint:(NSPoint)point
809 return kit(_private->coreFrame->rangeForPoint(IntPoint(point)).get());
812 - (DOMCSSStyleDeclaration *)_typingStyle
814 if (!_private->coreFrame)
816 RefPtr<CSSMutableStyleDeclaration> typingStyle = _private->coreFrame->selection()->copyTypingStyle();
819 return kit(typingStyle.get());
822 - (void)_setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(EditAction)undoAction
824 if (!_private->coreFrame)
826 _private->coreFrame->editor()->computeAndSetTypingStyle(core(style), undoAction);
829 - (void)_dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation
831 if (!_private->coreFrame)
833 FrameView* view = _private->coreFrame->view();
836 ASSERT([getWebView(self) _usesDocumentViews]);
837 // FIXME: These are fake modifier keys here, but they should be real ones instead.
838 PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->platformWidget() window]),
839 LeftButton, MouseEventMoved, 0, false, false, false, false, currentTime());
840 _private->coreFrame->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation);
843 - (BOOL)_canProvideDocumentSource
845 Frame* frame = _private->coreFrame;
846 String mimeType = frame->document()->loader()->writer()->mimeType();
847 PluginData* pluginData = frame->page() ? frame->page()->pluginData() : 0;
849 if (WebCore::DOMImplementation::isTextMIMEType(mimeType) ||
850 Image::supportsType(mimeType) ||
851 (pluginData && pluginData->supportsMimeType(mimeType)))
857 - (BOOL)_canSaveAsWebArchive
859 // Currently, all documents that we can view source for
860 // (HTML and XML documents) can also be saved as web archives
861 return [self _canProvideDocumentSource];
864 - (void)_commitData:(NSData *)data
866 // FIXME: This really should be a setting.
867 Document* document = _private->coreFrame->document();
868 document->setShouldCreateRenderers(_private->shouldCreateRenderers);
870 _private->coreFrame->loader()->documentLoader()->commitData((const char *)[data bytes], [data length]);
875 @implementation WebFrame (WebPrivate)
877 // FIXME: This exists only as a convenience for Safari, consider moving there.
878 - (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor
880 Frame* coreFrame = _private->coreFrame;
881 return coreFrame && coreFrame->tree()->isDescendantOf(core(ancestor));
884 - (void)_setShouldCreateRenderers:(BOOL)shouldCreateRenderers
886 _private->shouldCreateRenderers = shouldCreateRenderers;
889 - (NSColor *)_bodyBackgroundColor
891 Document* document = _private->coreFrame->document();
894 HTMLElement* body = document->body();
897 RenderObject* bodyRenderer = body->renderer();
900 Color color = bodyRenderer->style()->visitedDependentColor(CSSPropertyBackgroundColor);
901 if (!color.isValid())
903 return nsColor(color);
908 Document* document = _private->coreFrame->document();
909 return document && document->isFrameSet();
912 - (BOOL)_firstLayoutDone
914 return _private->coreFrame->loader()->stateMachine()->firstLayoutDone();
917 - (BOOL)_isVisuallyNonEmpty
919 if (FrameView* view = _private->coreFrame->view())
920 return view->isVisuallyNonEmpty();
924 - (WebFrameLoadType)_loadType
926 return (WebFrameLoadType)_private->coreFrame->loader()->loadType();
929 - (NSRange)_selectedNSRange
931 return [self _convertToNSRange:_private->coreFrame->selection()->toNormalizedRange().get()];
934 - (void)_selectNSRange:(NSRange)range
936 RefPtr<Range> domRange = [self _convertToDOMRange:range];
938 _private->coreFrame->selection()->setSelection(VisibleSelection(domRange.get(), SEL_DEFAULT_AFFINITY));
941 - (BOOL)_isDisplayingStandaloneImage
943 Document* document = _private->coreFrame->document();
944 return document && document->isImageDocument();
947 - (unsigned)_pendingFrameUnloadEventCount
949 return _private->coreFrame->domWindow()->pendingUnloadEventListeners();
952 - (void)_setIsDisconnected:(bool)isDisconnected
954 _private->coreFrame->setIsDisconnected(isDisconnected);
957 - (void)_setExcludeFromTextSearch:(bool)exclude
959 _private->coreFrame->setExcludeFromTextSearch(exclude);
962 #if ENABLE(NETSCAPE_PLUGIN_API)
963 - (void)_recursive_resumeNullEventsForAllNetscapePlugins
965 Frame* coreFrame = core(self);
966 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
967 NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
968 if ([documentView isKindOfClass:[WebHTMLView class]])
969 [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins];
973 - (void)_recursive_pauseNullEventsForAllNetscapePlugins
975 Frame* coreFrame = core(self);
976 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
977 NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
978 if ([documentView isKindOfClass:[WebHTMLView class]])
979 [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins];
984 - (BOOL)_pauseAnimation:(NSString*)name onNode:(DOMNode *)node atTime:(NSTimeInterval)time
986 Frame* frame = core(self);
990 AnimationController* controller = frame->animation();
994 Node* coreNode = core(node);
995 if (!coreNode || !coreNode->renderer())
998 return controller->pauseAnimationAtTime(coreNode->renderer(), name, time);
1001 - (BOOL)_pauseTransitionOfProperty:(NSString*)name onNode:(DOMNode*)node atTime:(NSTimeInterval)time
1003 Frame* frame = core(self);
1007 AnimationController* controller = frame->animation();
1011 Node* coreNode = core(node);
1012 if (!coreNode || !coreNode->renderer())
1015 return controller->pauseTransitionAtTime(coreNode->renderer(), name, time);
1018 // Pause a given SVG animation on the target node at a specific time.
1019 // This method is only intended to be used for testing the SVG animation system.
1020 - (BOOL)_pauseSVGAnimation:(NSString*)elementId onSMILNode:(DOMNode *)node atTime:(NSTimeInterval)time
1022 Frame* frame = core(self);
1026 Document* document = frame->document();
1027 if (!document || !document->svgExtensions())
1030 Node* coreNode = core(node);
1031 if (!coreNode || !SVGSMILElement::isSMILElement(coreNode))
1035 return document->accessSVGExtensions()->sampleAnimationAtTime(elementId, static_cast<SVGSMILElement*>(coreNode), time);
1041 - (unsigned) _numberOfActiveAnimations
1043 Frame* frame = core(self);
1047 AnimationController* controller = frame->animation();
1051 return controller->numberOfActiveAnimations(frame->document());
1054 - (void) _suspendAnimations
1056 Frame* frame = core(self);
1060 frame->animation()->suspendAnimations();
1063 - (void) _resumeAnimations
1065 Frame* frame = core(self);
1069 frame->animation()->resumeAnimations();
1072 - (void)_replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
1074 if (_private->coreFrame->selection()->isNone() || !fragment)
1076 ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::PreventNesting;
1077 if (selectReplacement)
1078 options |= ReplaceSelectionCommand::SelectReplacement;
1080 options |= ReplaceSelectionCommand::SmartReplace;
1082 options |= ReplaceSelectionCommand::MatchStyle;
1083 applyCommand(ReplaceSelectionCommand::create(_private->coreFrame->document(), core(fragment), options));
1084 _private->coreFrame->selection()->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
1087 - (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1089 DOMDocumentFragment* fragment = kit(createFragmentFromText(_private->coreFrame->selection()->toNormalizedRange().get(), text).get());
1090 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES];
1093 - (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1095 DOMDocumentFragment *fragment = [self _documentFragmentWithMarkupString:markupString baseURLString:baseURLString];
1096 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
1099 // Determines whether whitespace needs to be added around aString to preserve proper spacing and
1100 // punctuation when it's inserted into the receiver's text over charRange. Returns by reference
1101 // in beforeString and afterString any whitespace that should be added, unless either or both are
1102 // nil. Both are returned as nil if aString is nil or if smart insertion and deletion are disabled.
1103 - (void)_smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString
1105 // give back nil pointers in case of early returns
1107 *beforeString = nil;
1111 // inspect destination
1112 Node *startContainer = core([rangeToReplace startContainer]);
1113 Node *endContainer = core([rangeToReplace endContainer]);
1115 Position startPos(startContainer, [rangeToReplace startOffset], Position::PositionIsOffsetInAnchor);
1116 Position endPos(endContainer, [rangeToReplace endOffset], Position::PositionIsOffsetInAnchor);
1118 VisiblePosition startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY);
1119 VisiblePosition endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY);
1121 // this check also ensures startContainer, startPos, endContainer, and endPos are non-null
1122 if (startVisiblePos.isNull() || endVisiblePos.isNull())
1125 bool addLeadingSpace = startPos.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos);
1126 if (addLeadingSpace)
1127 if (UChar previousChar = startVisiblePos.previous().characterAfter())
1128 addLeadingSpace = !isCharacterSmartReplaceExempt(previousChar, true);
1130 bool addTrailingSpace = endPos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos);
1131 if (addTrailingSpace)
1132 if (UChar thisChar = endVisiblePos.characterAfter())
1133 addTrailingSpace = !isCharacterSmartReplaceExempt(thisChar, false);
1136 bool hasWhitespaceAtStart = false;
1137 bool hasWhitespaceAtEnd = false;
1138 unsigned pasteLength = [pasteString length];
1139 if (pasteLength > 0) {
1140 NSCharacterSet *whiteSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
1142 if ([whiteSet characterIsMember:[pasteString characterAtIndex:0]]) {
1143 hasWhitespaceAtStart = YES;
1145 if ([whiteSet characterIsMember:[pasteString characterAtIndex:(pasteLength - 1)]]) {
1146 hasWhitespaceAtEnd = YES;
1150 // issue the verdict
1151 if (beforeString && addLeadingSpace && !hasWhitespaceAtStart)
1152 *beforeString = @" ";
1153 if (afterString && addTrailingSpace && !hasWhitespaceAtEnd)
1154 *afterString = @" ";
1157 - (NSMutableDictionary *)_cacheabilityDictionary
1159 NSMutableDictionary *result = [NSMutableDictionary dictionary];
1161 FrameLoader* frameLoader = _private->coreFrame->loader();
1162 DocumentLoader* documentLoader = frameLoader->documentLoader();
1163 if (documentLoader && !documentLoader->mainDocumentError().isNull())
1164 [result setObject:(NSError *)documentLoader->mainDocumentError() forKey:WebFrameMainDocumentError];
1166 if (frameLoader->subframeLoader()->containsPlugins())
1167 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasPlugins];
1169 if (DOMWindow* domWindow = _private->coreFrame->domWindow()) {
1170 if (domWindow->hasEventListeners(eventNames().unloadEvent))
1171 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasUnloadListener];
1173 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
1174 if (domWindow->optionalApplicationCache())
1175 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesApplicationCache];
1179 if (Document* document = _private->coreFrame->document()) {
1180 #if ENABLE(DATABASE)
1181 if (document->hasOpenDatabases())
1182 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesDatabases];
1185 if (document->usingGeolocation())
1186 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesGeolocation];
1188 if (!document->canSuspendActiveDOMObjects())
1189 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameCanSuspendActiveDOMObjects];
1195 - (BOOL)_allowsFollowingLink:(NSURL *)URL
1197 if (!_private->coreFrame)
1199 return _private->coreFrame->document()->securityOrigin()->canDisplay(URL);
1202 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string withGlobalObject:(JSObjectRef)globalObjectRef inScriptWorld:(WebScriptWorld *)world
1204 // Start off with some guess at a frame and a global object, we'll try to do better...!
1205 JSDOMWindow* anyWorldGlobalObject = _private->coreFrame->script()->globalObject(mainThreadNormalWorld());
1207 // The global object is probably a shell object? - if so, we know how to use this!
1208 JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
1209 if (!strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell"))
1210 anyWorldGlobalObject = static_cast<JSDOMWindowShell*>(globalObjectObj)->window();
1212 // Get the frame frome the global object we've settled on.
1213 Frame* frame = anyWorldGlobalObject->impl()->frame();
1214 ASSERT(frame->document());
1215 RetainPtr<WebFrame> webFrame(kit(frame)); // Running arbitrary JavaScript can destroy the frame.
1217 JSValue result = frame->script()->executeScriptInWorld(core(world), string, true).jsValue();
1219 if (!webFrame->_private->coreFrame) // In case the script removed our frame from the page.
1222 // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
1223 // If you don't like it, use -[WebScriptObject evaluateWebScript:] or
1224 // JSEvaluateScript instead, since they have less surprising semantics.
1225 if (!result || (!result.isBoolean() && !result.isString() && !result.isNumber()))
1228 JSLock lock(SilenceAssertionsOnly);
1229 return ustringToString(result.toString(anyWorldGlobalObject->globalExec()));
1232 - (JSGlobalContextRef)_globalContextForScriptWorld:(WebScriptWorld *)world
1234 Frame* coreFrame = _private->coreFrame;
1237 DOMWrapperWorld* coreWorld = core(world);
1240 return toGlobalRef(coreFrame->script()->globalObject(coreWorld)->globalExec());
1243 - (void)setAllowsScrollersToOverlapContent:(BOOL)flag
1245 ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
1246 [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAllowsScrollersToOverlapContent:flag];
1249 - (void)setAlwaysHideHorizontalScroller:(BOOL)flag
1251 ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
1252 [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAlwaysHideHorizontalScroller:flag];
1254 - (void)setAlwaysHideVerticalScroller:(BOOL)flag
1256 ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
1257 [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAlwaysHideVerticalScroller:flag];
1260 - (void)setAccessibleName:(NSString *)name
1262 #if HAVE(ACCESSIBILITY)
1263 if (!AXObjectCache::accessibilityEnabled())
1266 if (!_private->coreFrame || !_private->coreFrame->document())
1269 AccessibilityObject* rootObject = _private->coreFrame->document()->axObjectCache()->rootObject();
1271 String strName(name);
1272 rootObject->setAccessibleName(strName);
1277 - (NSString*)_layerTreeAsText
1279 Frame* coreFrame = _private->coreFrame;
1283 return coreFrame->layerTreeAsText();
1286 - (BOOL)hasSpellingMarker:(int)from length:(int)length
1288 Frame* coreFrame = core(self);
1291 return coreFrame->editor()->selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
1294 - (BOOL)hasGrammarMarker:(int)from length:(int)length
1296 Frame* coreFrame = core(self);
1299 return coreFrame->editor()->selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
1302 - (id)accessibilityRoot
1304 #if HAVE(ACCESSIBILITY)
1305 if (!AXObjectCache::accessibilityEnabled()) {
1306 AXObjectCache::enableAccessibility();
1307 AXObjectCache::setEnhancedUserInterfaceAccessibility([[NSApp accessibilityAttributeValue:NSAccessibilityEnhancedUserInterfaceAttribute] boolValue]);
1310 if (!_private->coreFrame || !_private->coreFrame->document())
1313 AccessibilityObject* rootObject = _private->coreFrame->document()->axObjectCache()->rootObjectForFrame(_private->coreFrame);
1317 // The root object will be a WebCore scroll view object. In WK1, scroll views are handled
1318 // by the system and the root object should be the web area (instead of the scroll view).
1319 if (rootObject->isAttachment() && rootObject->firstChild())
1320 return rootObject->firstChild()->wrapper();
1322 return rootObject->wrapper();
1328 - (void)_clearOpener
1330 Frame* coreFrame = _private->coreFrame;
1332 coreFrame->loader()->setOpener(0);
1335 // Used by pagination code called from AppKit when a standalone web page is printed.
1336 - (NSArray *)_computePageRectsWithPrintScaleFactor:(float)printScaleFactor pageSize:(NSSize)pageSize
1338 if (printScaleFactor <= 0) {
1339 LOG_ERROR("printScaleFactor has bad value %.2f", printScaleFactor);
1340 return [NSArray array];
1343 if (!_private->coreFrame)
1344 return [NSArray array];
1345 if (!_private->coreFrame->document())
1346 return [NSArray array];
1347 if (!_private->coreFrame->view())
1348 return [NSArray array];
1349 if (!_private->coreFrame->view()->documentView())
1350 return [NSArray array];
1352 RenderView* root = toRenderView(_private->coreFrame->document()->renderer());
1354 return [NSArray array];
1356 const IntRect& documentRect = root->documentRect();
1357 float printWidth = root->style()->isHorizontalWritingMode() ? documentRect.width() / printScaleFactor : pageSize.width;
1358 float printHeight = root->style()->isHorizontalWritingMode() ? pageSize.height : documentRect.height() / printScaleFactor;
1360 PrintContext printContext(_private->coreFrame);
1361 printContext.computePageRectsWithPageSize(FloatSize(printWidth, printHeight), true);
1362 const Vector<IntRect>& pageRects = printContext.pageRects();
1364 size_t size = pageRects.size();
1365 NSMutableArray *pages = [NSMutableArray arrayWithCapacity:size];
1366 for (size_t i = 0; i < size; ++i)
1367 [pages addObject:[NSValue valueWithRect:NSRect(pageRects[i])]];
1373 @implementation WebFrame
1380 // Should be deprecated.
1381 - (id)initWithName:(NSString *)name webFrameView:(WebFrameView *)view webView:(WebView *)webView
1388 if (_private && _private->includedInWebKitStatistics)
1398 if (_private && _private->includedInWebKitStatistics)
1406 Frame* coreFrame = _private->coreFrame;
1409 return coreFrame->tree()->uniqueName();
1412 - (WebFrameView *)frameView
1414 ASSERT(!getWebView(self) || [getWebView(self) _usesDocumentViews]);
1415 return _private->webFrameView;
1418 - (WebView *)webView
1420 return getWebView(self);
1423 static bool needsMicrosoftMessengerDOMDocumentWorkaround()
1425 static bool needsWorkaround = applicationIsMicrosoftMessenger() && [[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] compare:@"7.1" options:NSNumericSearch] == NSOrderedAscending;
1426 return needsWorkaround;
1429 - (DOMDocument *)DOMDocument
1431 if (needsMicrosoftMessengerDOMDocumentWorkaround() && !pthread_main_np())
1434 Frame* coreFrame = _private->coreFrame;
1438 // FIXME: <rdar://problem/5145841> When loading a custom view/representation
1439 // into a web frame, the old document can still be around. This makes sure that
1440 // we'll return nil in those cases.
1441 if (![[self _dataSource] _isDocumentHTML])
1444 Document* document = coreFrame->document();
1446 // According to the documentation, we should return nil if the frame doesn't have a document.
1447 // While full-frame images and plugins do have an underlying HTML document, we return nil here to be
1448 // backwards compatible.
1449 if (document && (document->isPluginDocument() || document->isImageDocument()))
1452 return kit(coreFrame->document());
1455 - (DOMHTMLElement *)frameElement
1457 Frame* coreFrame = _private->coreFrame;
1460 return kit(coreFrame->ownerElement());
1463 - (WebDataSource *)provisionalDataSource
1465 Frame* coreFrame = _private->coreFrame;
1466 return coreFrame ? dataSource(coreFrame->loader()->provisionalDocumentLoader()) : nil;
1469 - (WebDataSource *)dataSource
1471 Frame* coreFrame = _private->coreFrame;
1472 return coreFrame && coreFrame->loader()->frameHasLoaded() ? [self _dataSource] : nil;
1475 - (void)loadRequest:(NSURLRequest *)request
1477 Frame* coreFrame = _private->coreFrame;
1480 coreFrame->loader()->load(request, false);
1483 static NSURL *createUniqueWebDataURL()
1485 CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
1486 NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
1488 NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"applewebdata://%@", UUIDString]];
1489 CFRelease(UUIDString);
1493 - (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
1495 if (!pthread_main_np())
1496 return [[self _webkit_invokeOnMainThread] _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:unreachableURL];
1500 baseURL = blankURL();
1501 responseURL = createUniqueWebDataURL();
1504 ResourceRequest request([baseURL absoluteURL]);
1506 // hack because Mail checks for this property to detect data / archive loads
1507 [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest()];
1509 SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData(data), MIMEType, encodingName, [unreachableURL absoluteURL], responseURL);
1511 _private->coreFrame->loader()->load(request, substituteData, false);
1515 - (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL
1517 WebCoreThreadViolationCheckRoundTwo();
1520 MIMEType = @"text/html";
1521 [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:nil];
1524 - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
1526 NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
1527 [self _loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:baseURL unreachableURL:unreachableURL];
1530 - (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL
1532 WebCoreThreadViolationCheckRoundTwo();
1534 [self _loadHTMLString:string baseURL:baseURL unreachableURL:nil];
1537 - (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL
1539 WebCoreThreadViolationCheckRoundTwo();
1541 [self _loadHTMLString:string baseURL:baseURL unreachableURL:unreachableURL];
1544 - (void)loadArchive:(WebArchive *)archive
1546 if (LegacyWebArchive* coreArchive = [archive _coreLegacyWebArchive])
1547 _private->coreFrame->loader()->loadArchive(coreArchive);
1552 if (!_private->coreFrame)
1554 _private->coreFrame->loader()->stopForUserCancel();
1559 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_RELOAD_FROM_ORIGIN) && applicationIsSafari())
1560 _private->coreFrame->loader()->reload(GetCurrentKeyModifiers() & shiftKey);
1562 _private->coreFrame->loader()->reload(false);
1565 - (void)reloadFromOrigin
1567 _private->coreFrame->loader()->reload(true);
1570 - (WebFrame *)findFrameNamed:(NSString *)name
1572 Frame* coreFrame = _private->coreFrame;
1575 return kit(coreFrame->tree()->find(name));
1578 - (WebFrame *)parentFrame
1580 Frame* coreFrame = _private->coreFrame;
1583 return [[kit(coreFrame->tree()->parent()) retain] autorelease];
1586 - (NSArray *)childFrames
1588 Frame* coreFrame = _private->coreFrame;
1590 return [NSArray array];
1591 NSMutableArray *children = [NSMutableArray arrayWithCapacity:coreFrame->tree()->childCount()];
1592 for (Frame* child = coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1593 [children addObject:kit(child)];
1597 - (WebScriptObject *)windowObject
1599 Frame* coreFrame = _private->coreFrame;
1602 return coreFrame->script()->windowScriptObject();
1605 - (JSGlobalContextRef)globalContext
1607 Frame* coreFrame = _private->coreFrame;
1610 return toGlobalRef(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec());