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 "WebElementDictionary.h"
44 #import "WebFrameLoaderClient.h"
45 #import "WebFrameViewInternal.h"
46 #import "WebHTMLView.h"
47 #import "WebHTMLViewInternal.h"
48 #import "WebKitStatisticsPrivate.h"
49 #import "WebKitVersionChecks.h"
50 #import "WebNSObjectExtras.h"
51 #import "WebNSURLExtras.h"
52 #import "WebScriptDebugger.h"
53 #import "WebScriptWorldInternal.h"
54 #import "WebViewInternal.h"
55 #import <JavaScriptCore/APICast.h>
56 #import <JavaScriptCore/JSContextInternal.h>
57 #import <WebCore/AXObjectCache.h>
58 #import <WebCore/AccessibilityObject.h>
59 #import <WebCore/AnimationController.h>
60 #import <WebCore/CSSStyleDeclaration.h>
61 #import <WebCore/CachedResourceLoader.h>
62 #import <WebCore/Chrome.h>
63 #import <WebCore/ColorMac.h>
64 #import <WebCore/DOMImplementation.h>
65 #import <WebCore/DatabaseManager.h>
66 #import <WebCore/DocumentFragment.h>
67 #import <WebCore/DocumentLoader.h>
68 #import <WebCore/DocumentMarkerController.h>
69 #import <WebCore/Editor.h>
70 #import <WebCore/EventHandler.h>
71 #import <WebCore/EventNames.h>
72 #import <WebCore/Frame.h>
73 #import <WebCore/FrameLoadRequest.h>
74 #import <WebCore/FrameLoader.h>
75 #import <WebCore/FrameLoaderStateMachine.h>
76 #import <WebCore/FrameTree.h>
77 #import <WebCore/GraphicsContext.h>
78 #import <WebCore/HTMLFrameOwnerElement.h>
79 #import <WebCore/HTMLNames.h>
80 #import <WebCore/HistoryItem.h>
81 #import <WebCore/HitTestResult.h>
82 #import <WebCore/JSNode.h>
83 #import <WebCore/LegacyWebArchive.h>
84 #import <WebCore/Page.h>
85 #import <WebCore/PlatformEventFactoryMac.h>
86 #import <WebCore/PluginData.h>
87 #import <WebCore/PrintContext.h>
88 #import <WebCore/RenderPart.h>
89 #import <WebCore/RenderView.h>
90 #import <WebCore/RuntimeApplicationChecks.h>
91 #import <WebCore/ScriptController.h>
92 #import <WebCore/ScriptValue.h>
93 #import <WebCore/SecurityOrigin.h>
94 #import <WebCore/SmartReplace.h>
95 #import <WebCore/StylePropertySet.h>
96 #import <WebCore/TextIterator.h>
97 #import <WebCore/ThreadCheck.h>
98 #import <WebCore/VisibleUnits.h>
99 #import <WebCore/htmlediting.h>
100 #import <WebCore/markup.h>
101 #import <WebKitSystemInterface.h>
102 #import <runtime/JSLock.h>
103 #import <runtime/JSObject.h>
104 #import <runtime/JSCJSValue.h>
105 #import <wtf/CurrentTime.h>
107 using namespace WebCore;
108 using namespace HTMLNames;
110 using JSC::JSGlobalObject;
114 Here is the current behavior matrix for four types of navigations:
118 Restore form state: YES
119 Restore scroll and focus state: YES
120 Cache policy: NSURLRequestUseProtocolCachePolicy
121 Add to back/forward list: YES
125 Restore form state: YES
126 Restore scroll and focus state: YES
127 Cache policy: NSURLRequestReturnCacheDataElseLoad
128 Add to back/forward list: NO
130 Reload (meaning only the reload button):
132 Restore form state: NO
133 Restore scroll and focus state: YES
134 Cache policy: NSURLRequestReloadIgnoringCacheData
135 Add to back/forward list: NO
137 Repeat load of the same URL (by any other means of navigation other than the reload button, including hitting return in the location field):
139 Restore form state: NO
140 Restore scroll and focus state: NO, reset to initial conditions
141 Cache policy: NSURLRequestReloadIgnoringCacheData
142 Add to back/forward list: NO
145 NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey";
146 NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey";
147 NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
149 NSString *WebFrameMainDocumentError = @"WebFrameMainDocumentErrorKey";
150 NSString *WebFrameHasPlugins = @"WebFrameHasPluginsKey";
151 NSString *WebFrameHasUnloadListener = @"WebFrameHasUnloadListenerKey";
152 NSString *WebFrameUsesDatabases = @"WebFrameUsesDatabasesKey";
153 NSString *WebFrameUsesGeolocation = @"WebFrameUsesGeolocationKey";
154 NSString *WebFrameUsesApplicationCache = @"WebFrameUsesApplicationCacheKey";
155 NSString *WebFrameCanSuspendActiveDOMObjects = @"WebFrameCanSuspendActiveDOMObjectsKey";
157 // FIXME: Remove when this key becomes publicly defined
158 NSString *NSAccessibilityEnhancedUserInterfaceAttribute = @"AXEnhancedUserInterface";
160 @implementation WebFramePrivate
164 [webFrameView release];
166 delete scriptDebugger;
173 delete scriptDebugger;
178 - (void)setWebFrameView:(WebFrameView *)v
181 [webFrameView release];
187 EditableLinkBehavior core(WebKitEditableLinkBehavior editableLinkBehavior)
189 switch (editableLinkBehavior) {
190 case WebKitEditableLinkDefaultBehavior:
191 return EditableLinkDefaultBehavior;
192 case WebKitEditableLinkAlwaysLive:
193 return EditableLinkAlwaysLive;
194 case WebKitEditableLinkOnlyLiveWithShiftKey:
195 return EditableLinkOnlyLiveWithShiftKey;
196 case WebKitEditableLinkLiveWhenNotFocused:
197 return EditableLinkLiveWhenNotFocused;
198 case WebKitEditableLinkNeverLive:
199 return EditableLinkNeverLive;
201 ASSERT_NOT_REACHED();
202 return EditableLinkDefaultBehavior;
205 TextDirectionSubmenuInclusionBehavior core(WebTextDirectionSubmenuInclusionBehavior behavior)
208 case WebTextDirectionSubmenuNeverIncluded:
209 return TextDirectionSubmenuNeverIncluded;
210 case WebTextDirectionSubmenuAutomaticallyIncluded:
211 return TextDirectionSubmenuAutomaticallyIncluded;
212 case WebTextDirectionSubmenuAlwaysIncluded:
213 return TextDirectionSubmenuAlwaysIncluded;
215 ASSERT_NOT_REACHED();
216 return TextDirectionSubmenuNeverIncluded;
219 @implementation WebFrame (WebInternal)
221 Frame* core(WebFrame *frame)
223 return frame ? frame->_private->coreFrame : 0;
226 WebFrame *kit(Frame* frame)
231 FrameLoaderClient* frameLoaderClient = frame->loader().client();
232 if (frameLoaderClient->isEmptyFrameLoaderClient())
235 return static_cast<WebFrameLoaderClient*>(frameLoaderClient)->webFrame();
238 Page* core(WebView *webView)
240 return [webView page];
243 WebView *kit(Page* page)
248 ChromeClient* chromeClient = page->chrome().client();
249 if (chromeClient->isEmptyChromeClient())
252 return static_cast<WebChromeClient*>(chromeClient)->webView();
255 WebView *getWebView(WebFrame *webFrame)
257 Frame* coreFrame = core(webFrame);
260 return kit(coreFrame->page());
263 + (PassRefPtr<Frame>)_createFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView ownerElement:(HTMLFrameOwnerElement*)ownerElement
265 WebView *webView = kit(page);
267 WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView];
268 RefPtr<Frame> coreFrame = Frame::create(page, ownerElement, new WebFrameLoaderClient(frame));
270 frame->_private->coreFrame = coreFrame.get();
272 coreFrame->tree()->setName(name);
274 ASSERT(ownerElement->document()->frame());
275 ownerElement->document()->frame()->tree()->appendChild(coreFrame.get());
280 [webView _setZoomMultiplier:[webView _realZoomMultiplier] isTextOnly:[webView _realZoomMultiplierIsTextOnly]];
282 return coreFrame.release();
285 + (void)_createMainFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView
287 [self _createFrameWithPage:page frameName:name frameView:frameView ownerElement:0];
290 + (PassRefPtr<WebCore::Frame>)_createSubframeWithOwnerElement:(HTMLFrameOwnerElement*)ownerElement frameName:(const String&)name frameView:(WebFrameView *)frameView
292 return [self _createFrameWithPage:ownerElement->document()->frame()->page() frameName:name frameView:frameView ownerElement:ownerElement];
295 - (BOOL)_isIncludedInWebKitStatistics
297 return _private && _private->includedInWebKitStatistics;
300 - (void)_attachScriptDebugger
302 ScriptController* scriptController = _private->coreFrame->script();
304 // Calling ScriptController::globalObject() would create a window shell, and dispatch corresponding callbacks, which may be premature
305 // if the script debugger is attached before a document is created. These calls use the debuggerWorld(), we will need to pass a world
306 // to be able to debug isolated worlds.
307 if (!scriptController->existingWindowShell(debuggerWorld()))
310 JSGlobalObject* globalObject = scriptController->globalObject(debuggerWorld());
314 if (_private->scriptDebugger) {
315 ASSERT(_private->scriptDebugger == globalObject->debugger());
319 _private->scriptDebugger = new WebScriptDebugger(globalObject);
322 - (void)_detachScriptDebugger
324 if (!_private->scriptDebugger)
327 delete _private->scriptDebugger;
328 _private->scriptDebugger = 0;
331 - (id)_initWithWebFrameView:(WebFrameView *)fv webView:(WebView *)v
337 _private = [[WebFramePrivate alloc] init];
339 // Set includedInWebKitStatistics before calling WebFrameView _setWebFrame, since
340 // it calls WebFrame _isIncludedInWebKitStatistics.
341 if ((_private->includedInWebKitStatistics = [[v class] shouldIncludeInWebKitStatistics]))
345 [_private setWebFrameView:fv];
346 [fv _setWebFrame:self];
349 _private->shouldCreateRenderers = YES;
354 - (void)_clearCoreFrame
356 _private->coreFrame = 0;
359 - (void)_updateBackgroundAndUpdatesWhileOffscreen
361 WebView *webView = getWebView(self);
362 BOOL drawsBackground = [webView drawsBackground];
363 NSColor *backgroundColor = [webView backgroundColor];
365 Frame* coreFrame = _private->coreFrame;
366 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
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];
374 if (FrameView* view = frame->view()) {
375 view->setTransparent(!drawsBackground);
376 view->setBaseBackgroundColor(colorFromNSColor([backgroundColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]));
377 view->setShouldUpdateWhileOffscreen([webView shouldUpdateWhileOffscreen]);
382 - (void)_setInternalLoadDelegate:(id)internalLoadDelegate
384 _private->internalLoadDelegate = internalLoadDelegate;
387 - (id)_internalLoadDelegate
389 return _private->internalLoadDelegate;
392 - (void)_unmarkAllBadGrammar
394 Frame* coreFrame = _private->coreFrame;
395 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
396 if (Document* document = frame->document())
397 document->markers()->removeMarkers(DocumentMarker::Grammar);
401 - (void)_unmarkAllMisspellings
403 Frame* coreFrame = _private->coreFrame;
404 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
405 if (Document* document = frame->document())
406 document->markers()->removeMarkers(DocumentMarker::Spelling);
410 - (BOOL)_hasSelection
412 id documentView = [_private->webFrameView documentView];
414 // optimization for common case to avoid creating potentially large selection string
415 if ([documentView isKindOfClass:[WebHTMLView class]])
416 if (Frame* coreFrame = _private->coreFrame)
417 return coreFrame->selection()->isRange();
419 if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
420 return [[documentView selectedString] length] > 0;
425 - (void)_clearSelection
427 id documentView = [_private->webFrameView documentView];
428 if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
429 [documentView deselectAll];
433 - (BOOL)_atMostOneFrameHasSelection
435 // FIXME: 4186050 is one known case that makes this debug check fail.
437 Frame* coreFrame = _private->coreFrame;
438 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
439 if ([kit(frame) _hasSelection]) {
448 - (WebFrame *)_findFrameWithSelection
450 Frame* coreFrame = _private->coreFrame;
451 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
452 WebFrame *webFrame = kit(frame);
453 if ([webFrame _hasSelection])
459 - (void)_clearSelectionInOtherFrames
461 // We rely on WebDocumentSelection protocol implementors to call this method when they become first
462 // responder. It would be nicer to just notice first responder changes here instead, but there's no
463 // notification sent when the first responder changes in general (Radar 2573089).
464 WebFrame *frameWithSelection = [[getWebView(self) mainFrame] _findFrameWithSelection];
465 if (frameWithSelection != self)
466 [frameWithSelection _clearSelection];
468 // While we're in the general area of selection and frames, check that there is only one now.
469 ASSERT([[getWebView(self) mainFrame] _atMostOneFrameHasSelection]);
472 static inline WebDataSource *dataSource(DocumentLoader* loader)
474 return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
477 - (WebDataSource *)_dataSource
479 return dataSource(_private->coreFrame->loader().documentLoader());
482 - (NSString *)_stringWithDocumentTypeStringAndMarkupString:(NSString *)markupString
484 return String(_private->coreFrame->documentTypeString() + String(markupString));
487 - (NSArray *)_nodesFromList:(Vector<Node*> *)nodesVector
489 size_t size = nodesVector->size();
490 NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:size];
491 for (size_t i = 0; i < size; ++i)
492 [nodes addObject:kit((*nodesVector)[i])];
496 - (NSString *)_markupStringFromRange:(DOMRange *)range nodes:(NSArray **)nodes
498 // FIXME: This is always "for interchange". Is that right? See the previous method.
499 Vector<Node*> nodeList;
500 NSString *markupString = createMarkup(core(range), nodes ? &nodeList : 0, AnnotateForInterchange);
502 *nodes = [self _nodesFromList:&nodeList];
504 return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
507 - (NSString *)_selectedString
509 return _private->coreFrame->displayStringModifiedByEncoding(_private->coreFrame->editor().selectedText());
512 - (NSString *)_stringForRange:(DOMRange *)range
514 return plainText(core(range), TextIteratorDefaultBehavior, true);
517 - (BOOL)_shouldFlattenCompositingLayers:(CGContextRef)context
519 // -currentContextDrawingToScreen returns YES for bitmap contexts.
520 BOOL isPrinting = ![NSGraphicsContext currentContextDrawingToScreen];
524 if (!WKCGContextIsBitmapContext(context))
527 // If we're drawing into a bitmap, we might be snapshotting, or drawing into a layer-backed view.
528 id documentView = [_private->webFrameView documentView];
529 if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _web_isDrawingIntoLayer])
532 return [getWebView(self) _includesFlattenedCompositingLayersWhenDrawingToBitmap];
535 - (void)_drawRect:(NSRect)rect contentsOnly:(BOOL)contentsOnly
537 ASSERT([[NSGraphicsContext currentContext] isFlipped]);
539 CGContextRef ctx = static_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]);
540 GraphicsContext context(ctx);
542 FrameView* view = _private->coreFrame->view();
544 bool shouldFlatten = false;
545 if (Frame* parentFrame = _private->coreFrame->tree()->parent()) {
546 // For subframes, we need to inherit the paint behavior from our parent
547 FrameView* parentView = parentFrame ? parentFrame->view() : 0;
549 shouldFlatten = parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
551 shouldFlatten = [self _shouldFlattenCompositingLayers:ctx];
553 PaintBehavior oldBehavior = PaintBehaviorNormal;
555 oldBehavior = view->paintBehavior();
556 view->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
560 view->paintContents(&context, enclosingIntRect(rect));
562 view->paint(&context, enclosingIntRect(rect));
565 view->setPaintBehavior(oldBehavior);
568 - (BOOL)_getVisibleRect:(NSRect*)rect
570 ASSERT_ARG(rect, rect);
571 if (RenderPart* ownerRenderer = _private->coreFrame->ownerRenderer()) {
572 if (ownerRenderer->needsLayout())
574 *rect = ownerRenderer->pixelSnappedAbsoluteClippedOverflowRect();
581 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string
583 return [self _stringByEvaluatingJavaScriptFromString:string forceUserGesture:true];
586 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture
591 ASSERT(_private->coreFrame->document());
592 RetainPtr<WebFrame> protect(self); // Executing arbitrary JavaScript can destroy the frame.
594 JSC::JSValue result = _private->coreFrame->script()->executeScript(string, forceUserGesture).jsValue();
596 if (!_private->coreFrame) // In case the script removed our frame from the page.
599 // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
600 // If you don't like it, use -[WebScriptObject evaluateWebScript:] or
601 // JSEvaluateScript instead, since they have less surprising semantics.
602 if (!result || (!result.isBoolean() && !result.isString() && !result.isNumber()))
605 JSC::ExecState* exec = _private->coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec();
606 JSC::JSLockHolder lock(exec);
607 return result.toWTFString(exec);
610 - (NSRect)_caretRectAtPosition:(const Position&)pos affinity:(NSSelectionAffinity)affinity
612 VisiblePosition visiblePosition(pos, static_cast<EAffinity>(affinity));
613 return visiblePosition.absoluteCaretBounds();
616 - (NSRect)_firstRectForDOMRange:(DOMRange *)range
618 return _private->coreFrame->editor().firstRectForRange(core(range));
621 - (void)_scrollDOMRangeToVisible:(DOMRange *)range
623 NSRect rangeRect = [self _firstRectForDOMRange:range];
624 Node *startNode = core([range startContainer]);
626 if (startNode && startNode->renderer())
627 startNode->renderer()->scrollRectToVisible(enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
632 return _private->coreFrame->view() ? _private->coreFrame->view()->needsLayout() : false;
635 - (DOMRange *)_rangeByAlteringCurrentSelection:(FrameSelection::EAlteration)alteration direction:(SelectionDirection)direction granularity:(TextGranularity)granularity
637 if (_private->coreFrame->selection()->isNone())
640 FrameSelection selection;
641 selection.setSelection(_private->coreFrame->selection()->selection());
642 selection.modify(alteration, direction, granularity);
643 return kit(selection.toNormalizedRange().get());
646 - (TextGranularity)_selectionGranularity
648 return _private->coreFrame->selection()->granularity();
651 - (NSRange)_convertToNSRange:(Range *)range
654 return NSMakeRange(NSNotFound, 0);
658 if (!TextIterator::getLocationAndLengthFromRange(_private->coreFrame->selection()->rootEditableElementOrDocumentElement(), range, location, length))
659 return NSMakeRange(NSNotFound, 0);
661 return NSMakeRange(location, length);
664 - (PassRefPtr<Range>)_convertToDOMRange:(NSRange)nsrange
666 if (nsrange.location > INT_MAX)
668 if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX)
669 nsrange.length = INT_MAX - nsrange.location;
671 // our critical assumption is that we are only called by input methods that
672 // concentrate on a given area containing the selection
673 // We have to do this because of text fields and textareas. The DOM for those is not
674 // directly in the document DOM, so serialization is problematic. Our solution is
675 // to use the root editable element of the selection start as the positional base.
676 // That fits with AppKit's idea of an input context.
677 return TextIterator::rangeFromLocationAndLength(_private->coreFrame->selection()->rootEditableElementOrDocumentElement(), nsrange.location, nsrange.length);
680 - (DOMRange *)_convertNSRangeToDOMRange:(NSRange)nsrange
682 return kit([self _convertToDOMRange:nsrange].get());
685 - (NSRange)_convertDOMRangeToNSRange:(DOMRange *)range
687 return [self _convertToNSRange:core(range)];
690 - (DOMRange *)_markDOMRange
692 return kit(_private->coreFrame->editor().mark().toNormalizedRange().get());
695 // Given proposedRange, returns an extended range that includes adjacent whitespace that should
696 // be deleted along with the proposed range in order to preserve proper spacing and punctuation of
697 // the text surrounding the deletion.
698 - (DOMRange *)_smartDeleteRangeForProposedRange:(DOMRange *)proposedRange
700 Node* startContainer = core([proposedRange startContainer]);
701 Node* endContainer = core([proposedRange endContainer]);
702 if (startContainer == nil || endContainer == nil)
705 ASSERT(startContainer->document() == endContainer->document());
707 _private->coreFrame->document()->updateLayoutIgnorePendingStylesheets();
709 Position start = Position(startContainer, [proposedRange startOffset], Position::PositionIsOffsetInAnchor);
710 Position end = Position(endContainer, [proposedRange endOffset], Position::PositionIsOffsetInAnchor);
711 Position newStart = start.upstream().leadingWhitespacePosition(DOWNSTREAM, true);
712 if (newStart.isNull())
714 Position newEnd = end.downstream().trailingWhitespacePosition(DOWNSTREAM, true);
718 newStart = newStart.parentAnchoredEquivalent();
719 newEnd = newEnd.parentAnchoredEquivalent();
721 RefPtr<Range> range = _private->coreFrame->document()->createRange();
723 range->setStart(newStart.containerNode(), newStart.offsetInContainerNode(), exception);
724 range->setEnd(newStart.containerNode(), newStart.offsetInContainerNode(), exception);
725 return kit(range.get());
728 - (DOMDocumentFragment *)_documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString
730 if (!_private->coreFrame || !_private->coreFrame->document())
733 return kit(createFragmentFromMarkup(_private->coreFrame->document(), markupString, baseURLString, DisallowScriptingContent).get());
736 - (DOMDocumentFragment *)_documentFragmentWithNodesAsParagraphs:(NSArray *)nodes
738 if (!_private->coreFrame || !_private->coreFrame->document())
741 NSEnumerator *nodeEnum = [nodes objectEnumerator];
742 Vector<Node*> nodesVector;
744 while ((node = [nodeEnum nextObject]))
745 nodesVector.append(core(node));
747 return kit(createFragmentFromNodes(_private->coreFrame->document(), nodesVector).get());
750 - (void)_replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
752 DOMDocumentFragment *fragment = kit(_private->coreFrame->document()->createDocumentFragment().get());
753 [fragment appendChild:node];
754 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle];
757 - (void)_insertParagraphSeparatorInQuotedContent
759 if (_private->coreFrame->selection()->isNone())
762 _private->coreFrame->editor().insertParagraphSeparatorInQuotedContent();
765 - (VisiblePosition)_visiblePositionForPoint:(NSPoint)point
767 // FIXME: Someone with access to Apple's sources could remove this needless wrapper call.
768 return _private->coreFrame->visiblePositionForPoint(IntPoint(point));
771 - (DOMRange *)_characterRangeAtPoint:(NSPoint)point
773 return kit(_private->coreFrame->rangeForPoint(IntPoint(point)).get());
776 - (DOMCSSStyleDeclaration *)_typingStyle
778 if (!_private->coreFrame)
780 RefPtr<MutableStylePropertySet> typingStyle = _private->coreFrame->selection()->copyTypingStyle();
783 return kit(typingStyle->ensureCSSStyleDeclaration());
786 - (void)_setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(EditAction)undoAction
788 if (!_private->coreFrame || !style)
790 // FIXME: We shouldn't have to create a copy here.
791 _private->coreFrame->editor().computeAndSetTypingStyle(core(style)->copyProperties().get(), undoAction);
794 #if ENABLE(DRAG_SUPPORT)
795 - (void)_dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation
797 if (!_private->coreFrame)
799 FrameView* view = _private->coreFrame->view();
802 // FIXME: These are fake modifier keys here, but they should be real ones instead.
803 PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->platformWidget() window]),
804 LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, currentTime());
805 _private->coreFrame->eventHandler().dragSourceEndedAt(event, (DragOperation)operation);
809 - (BOOL)_canProvideDocumentSource
811 Frame* frame = _private->coreFrame;
812 String mimeType = frame->document()->loader()->writer()->mimeType();
813 PluginData* pluginData = frame->page() ? frame->page()->pluginData() : 0;
815 if (WebCore::DOMImplementation::isTextMIMEType(mimeType)
816 || Image::supportsType(mimeType)
817 || (pluginData && pluginData->supportsMimeType(mimeType, PluginData::AllPlugins) && frame->loader().subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin))
818 || (pluginData && pluginData->supportsMimeType(mimeType, PluginData::OnlyApplicationPlugins)))
824 - (BOOL)_canSaveAsWebArchive
826 // Currently, all documents that we can view source for
827 // (HTML and XML documents) can also be saved as web archives
828 return [self _canProvideDocumentSource];
831 - (void)_commitData:(NSData *)data
833 // FIXME: This really should be a setting.
834 Document* document = _private->coreFrame->document();
835 document->setShouldCreateRenderers(_private->shouldCreateRenderers);
837 _private->coreFrame->loader().documentLoader()->commitData((const char *)[data bytes], [data length]);
842 @implementation WebFrame (WebPrivate)
844 // FIXME: This exists only as a convenience for Safari, consider moving there.
845 - (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor
847 Frame* coreFrame = _private->coreFrame;
848 return coreFrame && coreFrame->tree()->isDescendantOf(core(ancestor));
851 - (void)_setShouldCreateRenderers:(BOOL)shouldCreateRenderers
853 _private->shouldCreateRenderers = shouldCreateRenderers;
856 - (NSColor *)_bodyBackgroundColor
858 Document* document = _private->coreFrame->document();
861 HTMLElement* body = document->body();
864 RenderObject* bodyRenderer = body->renderer();
867 Color color = bodyRenderer->style()->visitedDependentColor(CSSPropertyBackgroundColor);
868 if (!color.isValid())
870 return nsColor(color);
875 Document* document = _private->coreFrame->document();
876 return document && document->isFrameSet();
879 - (BOOL)_firstLayoutDone
881 return _private->coreFrame->loader().stateMachine()->firstLayoutDone();
884 - (BOOL)_isVisuallyNonEmpty
886 if (FrameView* view = _private->coreFrame->view())
887 return view->isVisuallyNonEmpty();
891 - (WebFrameLoadType)_loadType
893 return (WebFrameLoadType)_private->coreFrame->loader().loadType();
896 - (NSRange)_selectedNSRange
898 return [self _convertToNSRange:_private->coreFrame->selection()->toNormalizedRange().get()];
901 - (void)_selectNSRange:(NSRange)range
903 RefPtr<Range> domRange = [self _convertToDOMRange:range];
905 _private->coreFrame->selection()->setSelection(VisibleSelection(domRange.get(), SEL_DEFAULT_AFFINITY));
908 - (BOOL)_isDisplayingStandaloneImage
910 Document* document = _private->coreFrame->document();
911 return document && document->isImageDocument();
914 - (unsigned)_pendingFrameUnloadEventCount
916 return _private->coreFrame->document()->domWindow()->pendingUnloadEventListeners();
919 #if ENABLE(NETSCAPE_PLUGIN_API)
920 - (void)_recursive_resumeNullEventsForAllNetscapePlugins
922 Frame* coreFrame = core(self);
923 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
924 NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
925 if ([documentView isKindOfClass:[WebHTMLView class]])
926 [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins];
930 - (void)_recursive_pauseNullEventsForAllNetscapePlugins
932 Frame* coreFrame = core(self);
933 for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
934 NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
935 if ([documentView isKindOfClass:[WebHTMLView class]])
936 [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins];
941 - (void)_replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
943 if (_private->coreFrame->selection()->isNone() || !fragment)
945 _private->coreFrame->editor().replaceSelectionWithFragment(core(fragment), selectReplacement, smartReplace, matchStyle);
948 - (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
950 DOMDocumentFragment* fragment = kit(createFragmentFromText(_private->coreFrame->selection()->toNormalizedRange().get(), text).get());
951 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES];
954 - (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
956 DOMDocumentFragment *fragment = [self _documentFragmentWithMarkupString:markupString baseURLString:baseURLString];
957 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
960 // Determines whether whitespace needs to be added around aString to preserve proper spacing and
961 // punctuation when it's inserted into the receiver's text over charRange. Returns by reference
962 // in beforeString and afterString any whitespace that should be added, unless either or both are
963 // nil. Both are returned as nil if aString is nil or if smart insertion and deletion are disabled.
964 - (void)_smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString
966 // give back nil pointers in case of early returns
972 // inspect destination
973 Node *startContainer = core([rangeToReplace startContainer]);
974 Node *endContainer = core([rangeToReplace endContainer]);
976 Position startPos(startContainer, [rangeToReplace startOffset], Position::PositionIsOffsetInAnchor);
977 Position endPos(endContainer, [rangeToReplace endOffset], Position::PositionIsOffsetInAnchor);
979 VisiblePosition startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY);
980 VisiblePosition endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY);
982 // this check also ensures startContainer, startPos, endContainer, and endPos are non-null
983 if (startVisiblePos.isNull() || endVisiblePos.isNull())
986 bool addLeadingSpace = startPos.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos);
988 if (UChar previousChar = startVisiblePos.previous().characterAfter())
989 addLeadingSpace = !isCharacterSmartReplaceExempt(previousChar, true);
991 bool addTrailingSpace = endPos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos);
992 if (addTrailingSpace)
993 if (UChar thisChar = endVisiblePos.characterAfter())
994 addTrailingSpace = !isCharacterSmartReplaceExempt(thisChar, false);
997 bool hasWhitespaceAtStart = false;
998 bool hasWhitespaceAtEnd = false;
999 unsigned pasteLength = [pasteString length];
1000 if (pasteLength > 0) {
1001 NSCharacterSet *whiteSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
1003 if ([whiteSet characterIsMember:[pasteString characterAtIndex:0]]) {
1004 hasWhitespaceAtStart = YES;
1006 if ([whiteSet characterIsMember:[pasteString characterAtIndex:(pasteLength - 1)]]) {
1007 hasWhitespaceAtEnd = YES;
1011 // issue the verdict
1012 if (beforeString && addLeadingSpace && !hasWhitespaceAtStart)
1013 *beforeString = @" ";
1014 if (afterString && addTrailingSpace && !hasWhitespaceAtEnd)
1015 *afterString = @" ";
1018 - (NSMutableDictionary *)_cacheabilityDictionary
1020 NSMutableDictionary *result = [NSMutableDictionary dictionary];
1022 FrameLoader& frameLoader = _private->coreFrame->loader();
1023 DocumentLoader* documentLoader = frameLoader.documentLoader();
1024 if (documentLoader && !documentLoader->mainDocumentError().isNull())
1025 [result setObject:(NSError *)documentLoader->mainDocumentError() forKey:WebFrameMainDocumentError];
1027 if (frameLoader.subframeLoader()->containsPlugins())
1028 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasPlugins];
1030 if (DOMWindow* domWindow = _private->coreFrame->document()->domWindow()) {
1031 if (domWindow->hasEventListeners(eventNames().unloadEvent))
1032 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasUnloadListener];
1033 if (domWindow->optionalApplicationCache())
1034 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesApplicationCache];
1037 if (Document* document = _private->coreFrame->document()) {
1038 #if ENABLE(SQL_DATABASE)
1039 if (DatabaseManager::manager().hasOpenDatabases(document))
1040 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesDatabases];
1042 if (!document->canSuspendActiveDOMObjects())
1043 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameCanSuspendActiveDOMObjects];
1049 - (BOOL)_allowsFollowingLink:(NSURL *)URL
1051 if (!_private->coreFrame)
1053 return _private->coreFrame->document()->securityOrigin()->canDisplay(URL);
1056 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string withGlobalObject:(JSObjectRef)globalObjectRef inScriptWorld:(WebScriptWorld *)world
1061 // Start off with some guess at a frame and a global object, we'll try to do better...!
1062 JSDOMWindow* anyWorldGlobalObject = _private->coreFrame->script()->globalObject(mainThreadNormalWorld());
1064 // The global object is probably a shell object? - if so, we know how to use this!
1065 JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
1066 if (!strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell"))
1067 anyWorldGlobalObject = static_cast<JSDOMWindowShell*>(globalObjectObj)->window();
1069 // Get the frame frome the global object we've settled on.
1070 Frame* frame = anyWorldGlobalObject->impl()->frame();
1071 ASSERT(frame->document());
1072 RetainPtr<WebFrame> webFrame(kit(frame)); // Running arbitrary JavaScript can destroy the frame.
1074 JSC::JSValue result = frame->script()->executeScriptInWorld(core(world), string, true).jsValue();
1076 if (!webFrame->_private->coreFrame) // In case the script removed our frame from the page.
1079 // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
1080 // If you don't like it, use -[WebScriptObject evaluateWebScript:] or
1081 // JSEvaluateScript instead, since they have less surprising semantics.
1082 if (!result || (!result.isBoolean() && !result.isString() && !result.isNumber()))
1085 JSC::ExecState* exec = anyWorldGlobalObject->globalExec();
1086 JSC::JSLockHolder lock(exec);
1087 return result.toWTFString(exec);
1090 - (JSGlobalContextRef)_globalContextForScriptWorld:(WebScriptWorld *)world
1092 Frame* coreFrame = _private->coreFrame;
1095 DOMWrapperWorld* coreWorld = core(world);
1098 return toGlobalRef(coreFrame->script()->globalObject(coreWorld)->globalExec());
1101 #if JSC_OBJC_API_ENABLED
1102 - (JSContext *)_javaScriptContextForScriptWorld:(WebScriptWorld *)world
1104 JSGlobalContextRef globalContextRef = [self _globalContextForScriptWorld:world];
1105 if (!globalContextRef)
1107 return [JSContext contextWithJSGlobalContextRef:globalContextRef];
1111 - (void)setAllowsScrollersToOverlapContent:(BOOL)flag
1113 ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
1114 [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAllowsScrollersToOverlapContent:flag];
1117 - (void)setAlwaysHideHorizontalScroller:(BOOL)flag
1119 ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
1120 [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAlwaysHideHorizontalScroller:flag];
1122 - (void)setAlwaysHideVerticalScroller:(BOOL)flag
1124 ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
1125 [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAlwaysHideVerticalScroller:flag];
1128 - (void)setAccessibleName:(NSString *)name
1130 #if HAVE(ACCESSIBILITY)
1131 if (!AXObjectCache::accessibilityEnabled())
1134 if (!_private->coreFrame || !_private->coreFrame->document())
1137 AccessibilityObject* rootObject = _private->coreFrame->document()->axObjectCache()->rootObject();
1139 String strName(name);
1140 rootObject->setAccessibleName(strName);
1145 - (NSString*)_layerTreeAsText
1147 Frame* coreFrame = _private->coreFrame;
1151 return coreFrame->layerTreeAsText();
1154 - (id)accessibilityRoot
1156 #if HAVE(ACCESSIBILITY)
1157 if (!AXObjectCache::accessibilityEnabled()) {
1158 AXObjectCache::enableAccessibility();
1159 AXObjectCache::setEnhancedUserInterfaceAccessibility([[NSApp accessibilityAttributeValue:NSAccessibilityEnhancedUserInterfaceAttribute] boolValue]);
1162 if (!_private->coreFrame || !_private->coreFrame->document())
1165 AccessibilityObject* rootObject = _private->coreFrame->document()->axObjectCache()->rootObjectForFrame(_private->coreFrame);
1169 // The root object will be a WebCore scroll view object. In WK1, scroll views are handled
1170 // by the system and the root object should be the web area (instead of the scroll view).
1171 if (rootObject->isAttachment() && rootObject->firstChild())
1172 return rootObject->firstChild()->wrapper();
1174 return rootObject->wrapper();
1180 - (void)_clearOpener
1182 Frame* coreFrame = _private->coreFrame;
1184 coreFrame->loader().setOpener(0);
1187 // Used by pagination code called from AppKit when a standalone web page is printed.
1188 - (NSArray *)_computePageRectsWithPrintScaleFactor:(float)printScaleFactor pageSize:(NSSize)pageSize
1190 if (printScaleFactor <= 0) {
1191 LOG_ERROR("printScaleFactor has bad value %.2f", printScaleFactor);
1192 return [NSArray array];
1195 if (!_private->coreFrame)
1196 return [NSArray array];
1197 if (!_private->coreFrame->document())
1198 return [NSArray array];
1199 if (!_private->coreFrame->view())
1200 return [NSArray array];
1201 if (!_private->coreFrame->view()->documentView())
1202 return [NSArray array];
1204 RenderView* root = toRenderView(_private->coreFrame->document()->renderer());
1206 return [NSArray array];
1208 const LayoutRect& documentRect = root->documentRect();
1209 float printWidth = root->style()->isHorizontalWritingMode() ? static_cast<float>(documentRect.width()) / printScaleFactor : pageSize.width;
1210 float printHeight = root->style()->isHorizontalWritingMode() ? pageSize.height : static_cast<float>(documentRect.height()) / printScaleFactor;
1212 PrintContext printContext(_private->coreFrame);
1213 printContext.computePageRectsWithPageSize(FloatSize(printWidth, printHeight), true);
1214 const Vector<IntRect>& pageRects = printContext.pageRects();
1216 size_t size = pageRects.size();
1217 NSMutableArray *pages = [NSMutableArray arrayWithCapacity:size];
1218 for (size_t i = 0; i < size; ++i)
1219 [pages addObject:[NSValue valueWithRect:NSRect(pageRects[i])]];
1223 - (JSValueRef)jsWrapperForNode:(DOMNode *)node inScriptWorld:(WebScriptWorld *)world
1225 Frame* coreFrame = _private->coreFrame;
1229 JSDOMWindow* globalObject = coreFrame->script()->globalObject(core(world));
1230 JSC::ExecState* exec = globalObject->globalExec();
1232 JSC::JSLockHolder lock(exec);
1233 return toRef(exec, toJS(exec, globalObject, core(node)));
1236 - (NSDictionary *)elementAtPoint:(NSPoint)point
1238 Frame* coreFrame = _private->coreFrame;
1241 return [[[WebElementDictionary alloc] initWithHitTestResult:coreFrame->eventHandler().hitTestResultAtPoint(IntPoint(point), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent)] autorelease];
1244 - (NSURL *)_unreachableURL
1246 return [[self _dataSource] unreachableURL];
1251 @implementation WebFrame
1258 // Should be deprecated.
1259 - (id)initWithName:(NSString *)name webFrameView:(WebFrameView *)view webView:(WebView *)webView
1266 if (_private && _private->includedInWebKitStatistics)
1276 if (_private && _private->includedInWebKitStatistics)
1284 Frame* coreFrame = _private->coreFrame;
1287 return coreFrame->tree()->uniqueName();
1290 - (WebFrameView *)frameView
1292 return _private->webFrameView;
1295 - (WebView *)webView
1297 return getWebView(self);
1300 static bool needsMicrosoftMessengerDOMDocumentWorkaround()
1302 static bool needsWorkaround = applicationIsMicrosoftMessenger() && [[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] compare:@"7.1" options:NSNumericSearch] == NSOrderedAscending;
1303 return needsWorkaround;
1306 - (DOMDocument *)DOMDocument
1308 if (needsMicrosoftMessengerDOMDocumentWorkaround() && !pthread_main_np())
1311 Frame* coreFrame = _private->coreFrame;
1315 // FIXME: <rdar://problem/5145841> When loading a custom view/representation
1316 // into a web frame, the old document can still be around. This makes sure that
1317 // we'll return nil in those cases.
1318 if (![[self _dataSource] _isDocumentHTML])
1321 Document* document = coreFrame->document();
1323 // According to the documentation, we should return nil if the frame doesn't have a document.
1324 // While full-frame images and plugins do have an underlying HTML document, we return nil here to be
1325 // backwards compatible.
1326 if (document && (document->isPluginDocument() || document->isImageDocument()))
1329 return kit(coreFrame->document());
1332 - (DOMHTMLElement *)frameElement
1334 Frame* coreFrame = _private->coreFrame;
1337 return kit(coreFrame->ownerElement());
1340 - (WebDataSource *)provisionalDataSource
1342 Frame* coreFrame = _private->coreFrame;
1343 return coreFrame ? dataSource(coreFrame->loader().provisionalDocumentLoader()) : nil;
1346 - (WebDataSource *)dataSource
1348 Frame* coreFrame = _private->coreFrame;
1349 return coreFrame && coreFrame->loader().frameHasLoaded() ? [self _dataSource] : nil;
1352 - (void)loadRequest:(NSURLRequest *)request
1354 Frame* coreFrame = _private->coreFrame;
1358 ResourceRequest resourceRequest(request);
1360 // Some users of WebKit API incorrectly use "file path as URL" style requests which are invalid.
1361 // By re-writing those URLs here we technically break the -[WebDataSource initialRequest] API
1362 // but that is necessary to implement this quirk only at the API boundary.
1363 // Note that other users of WebKit API use nil requests or requests with nil URLs or empty URLs, so we
1364 // only implement this workaround when the request had a non-nil or non-empty URL.
1365 if (!resourceRequest.url().isValid() && !resourceRequest.url().isEmpty())
1366 resourceRequest.setURL([NSURL URLWithString:[@"file:" stringByAppendingString:[[request URL] absoluteString]]]);
1368 coreFrame->loader().load(FrameLoadRequest(coreFrame, resourceRequest));
1371 static NSURL *createUniqueWebDataURL()
1373 CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
1374 NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
1376 NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"applewebdata://%@", UUIDString]];
1377 CFRelease(UUIDString);
1381 - (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
1383 if (!pthread_main_np())
1384 return [[self _webkit_invokeOnMainThread] _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:unreachableURL];
1388 baseURL = blankURL();
1389 responseURL = createUniqueWebDataURL();
1392 ResourceRequest request([baseURL absoluteURL]);
1394 // hack because Mail checks for this property to detect data / archive loads
1395 [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest(UpdateHTTPBody)];
1397 SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData(data), MIMEType, encodingName, [unreachableURL absoluteURL], responseURL);
1399 _private->coreFrame->loader().load(FrameLoadRequest(_private->coreFrame, request, substituteData));
1403 - (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL
1405 WebCoreThreadViolationCheckRoundTwo();
1408 MIMEType = @"text/html";
1409 [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:[baseURL _webkit_URLFromURLOrSchemelessFileURL] unreachableURL:nil];
1412 - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
1414 NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
1415 [self _loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:baseURL unreachableURL:unreachableURL];
1418 - (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL
1420 WebCoreThreadViolationCheckRoundTwo();
1422 [self _loadHTMLString:string baseURL:[baseURL _webkit_URLFromURLOrSchemelessFileURL] unreachableURL:nil];
1425 - (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL
1427 WebCoreThreadViolationCheckRoundTwo();
1429 [self _loadHTMLString:string baseURL:[baseURL _webkit_URLFromURLOrSchemelessFileURL] unreachableURL:[unreachableURL _webkit_URLFromURLOrSchemelessFileURL]];
1432 - (void)loadArchive:(WebArchive *)archive
1434 if (LegacyWebArchive* coreArchive = [archive _coreLegacyWebArchive])
1435 _private->coreFrame->loader().loadArchive(coreArchive);
1440 if (!_private->coreFrame)
1442 _private->coreFrame->loader().stopForUserCancel();
1447 if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_RELOAD_FROM_ORIGIN) && applicationIsSafari())
1448 _private->coreFrame->loader().reload(GetCurrentKeyModifiers() & shiftKey);
1450 _private->coreFrame->loader().reload(false);
1453 - (void)reloadFromOrigin
1455 _private->coreFrame->loader().reload(true);
1458 - (WebFrame *)findFrameNamed:(NSString *)name
1460 Frame* coreFrame = _private->coreFrame;
1463 return kit(coreFrame->tree()->find(name));
1466 - (WebFrame *)parentFrame
1468 Frame* coreFrame = _private->coreFrame;
1471 return [[kit(coreFrame->tree()->parent()) retain] autorelease];
1474 - (NSArray *)childFrames
1476 Frame* coreFrame = _private->coreFrame;
1478 return [NSArray array];
1479 NSMutableArray *children = [NSMutableArray arrayWithCapacity:coreFrame->tree()->childCount()];
1480 for (Frame* child = coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling())
1481 [children addObject:kit(child)];
1485 - (WebScriptObject *)windowObject
1487 Frame* coreFrame = _private->coreFrame;
1490 return coreFrame->script()->windowScriptObject();
1493 - (JSGlobalContextRef)globalContext
1495 Frame* coreFrame = _private->coreFrame;
1498 return toGlobalRef(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec());
1501 #if JSC_OBJC_API_ENABLED
1502 - (JSContext *)javaScriptContext
1504 Frame* coreFrame = _private->coreFrame;
1507 return coreFrame->script()->javaScriptContext();