2 * Copyright (C) 2005, 2006, 2007, 2008, 2015 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 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/FrameLoadRequest.h>
73 #import <WebCore/FrameLoader.h>
74 #import <WebCore/FrameLoaderStateMachine.h>
75 #import <WebCore/FrameTree.h>
76 #import <WebCore/GraphicsContext.h>
77 #import <WebCore/HTMLFrameOwnerElement.h>
78 #import <WebCore/HTMLNames.h>
79 #import <WebCore/HistoryItem.h>
80 #import <WebCore/HitTestResult.h>
81 #import <WebCore/JSNode.h>
82 #import <WebCore/LegacyWebArchive.h>
83 #import <WebCore/MainFrame.h>
84 #import <WebCore/Page.h>
85 #import <WebCore/PlatformEventFactoryMac.h>
86 #import <WebCore/PluginData.h>
87 #import <WebCore/PrintContext.h>
88 #import <WebCore/RenderView.h>
89 #import <WebCore/RenderWidget.h>
90 #import <WebCore/RenderedDocumentMarker.h>
91 #import <WebCore/RuntimeApplicationChecks.h>
92 #import <WebCore/ScriptController.h>
93 #import <WebCore/SecurityOrigin.h>
94 #import <WebCore/SmartReplace.h>
95 #import <WebCore/StyleProperties.h>
96 #import <WebCore/SubframeLoader.h>
97 #import <WebCore/TextIterator.h>
98 #import <WebCore/ThreadCheck.h>
99 #import <WebCore/VisibleUnits.h>
100 #import <WebCore/htmlediting.h>
101 #import <WebCore/markup.h>
102 #import <WebKitSystemInterface.h>
103 #import <bindings/ScriptValue.h>
104 #import <runtime/JSLock.h>
105 #import <runtime/JSObject.h>
106 #import <runtime/JSCJSValue.h>
107 #import <wtf/CurrentTime.h>
110 #import "WebMailDelegate.h"
111 #import "WebResource.h"
112 #import "WebUIKitDelegate.h"
113 #import <WebCore/Document.h>
114 #import <WebCore/Editor.h>
115 #import <WebCore/EditorClient.h>
116 #import <WebCore/FocusController.h>
117 #import <WebCore/Font.h>
118 #import <WebCore/FrameSelection.h>
119 #import <WebCore/HistoryController.h>
120 #import <WebCore/NodeTraversal.h>
121 #import <WebCore/RenderLayer.h>
122 #import <WebCore/TextResourceDecoder.h>
123 #import <WebCore/WAKScrollView.h>
124 #import <WebCore/WKGraphics.h>
125 #import <WebCore/WebCoreThreadRun.h>
129 #import <WebCore/QuickLook.h>
130 #import <WebCore/WebCoreURLResponseIOS.h>
133 using namespace WebCore;
134 using namespace HTMLNames;
136 using JSC::JSGlobalObject;
140 Here is the current behavior matrix for four types of navigations:
144 Restore form state: YES
145 Restore scroll and focus state: YES
146 Cache policy: NSURLRequestUseProtocolCachePolicy
147 Add to back/forward list: YES
151 Restore form state: YES
152 Restore scroll and focus state: YES
153 Cache policy: NSURLRequestReturnCacheDataElseLoad
154 Add to back/forward list: NO
156 Reload (meaning only the reload button):
158 Restore form state: NO
159 Restore scroll and focus state: YES
160 Cache policy: NSURLRequestReloadIgnoringCacheData
161 Add to back/forward list: NO
163 Repeat load of the same URL (by any other means of navigation other than the reload button, including hitting return in the location field):
165 Restore form state: NO
166 Restore scroll and focus state: NO, reset to initial conditions
167 Cache policy: NSURLRequestReloadIgnoringCacheData
168 Add to back/forward list: NO
171 NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey";
172 NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey";
173 NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
175 NSString *WebFrameMainDocumentError = @"WebFrameMainDocumentErrorKey";
176 NSString *WebFrameHasPlugins = @"WebFrameHasPluginsKey";
177 NSString *WebFrameHasUnloadListener = @"WebFrameHasUnloadListenerKey";
178 NSString *WebFrameUsesDatabases = @"WebFrameUsesDatabasesKey";
179 NSString *WebFrameUsesGeolocation = @"WebFrameUsesGeolocationKey";
180 NSString *WebFrameUsesApplicationCache = @"WebFrameUsesApplicationCacheKey";
181 NSString *WebFrameCanSuspendActiveDOMObjects = @"WebFrameCanSuspendActiveDOMObjectsKey";
183 // FIXME: Remove when this key becomes publicly defined
184 NSString *NSAccessibilityEnhancedUserInterfaceAttribute = @"AXEnhancedUserInterface";
186 @implementation WebFramePrivate
190 [webFrameView release];
195 - (void)setWebFrameView:(WebFrameView *)v
198 [webFrameView release];
204 EditableLinkBehavior core(WebKitEditableLinkBehavior editableLinkBehavior)
206 switch (editableLinkBehavior) {
207 case WebKitEditableLinkDefaultBehavior:
208 return EditableLinkDefaultBehavior;
209 case WebKitEditableLinkAlwaysLive:
210 return EditableLinkAlwaysLive;
211 case WebKitEditableLinkOnlyLiveWithShiftKey:
212 return EditableLinkOnlyLiveWithShiftKey;
213 case WebKitEditableLinkLiveWhenNotFocused:
214 return EditableLinkLiveWhenNotFocused;
215 case WebKitEditableLinkNeverLive:
216 return EditableLinkNeverLive;
218 ASSERT_NOT_REACHED();
219 return EditableLinkDefaultBehavior;
222 TextDirectionSubmenuInclusionBehavior core(WebTextDirectionSubmenuInclusionBehavior behavior)
225 case WebTextDirectionSubmenuNeverIncluded:
226 return TextDirectionSubmenuNeverIncluded;
227 case WebTextDirectionSubmenuAutomaticallyIncluded:
228 return TextDirectionSubmenuAutomaticallyIncluded;
229 case WebTextDirectionSubmenuAlwaysIncluded:
230 return TextDirectionSubmenuAlwaysIncluded;
232 ASSERT_NOT_REACHED();
233 return TextDirectionSubmenuNeverIncluded;
238 Vector<Vector<String>> vectorForDictationPhrasesArray(NSArray *dictationPhrases)
240 Vector<Vector<String>> result;
242 for (id dictationPhrase in dictationPhrases) {
243 if (![dictationPhrase isKindOfClass:[NSArray class]])
245 result.append(Vector<String>());
246 for (id interpretation : (NSArray *)dictationPhrase) {
247 if (![interpretation isKindOfClass:[NSString class]])
249 result.last().append((NSString *)interpretation);
258 @implementation WebFrame (WebInternal)
260 Frame* core(WebFrame *frame)
262 return frame ? frame->_private->coreFrame : 0;
265 WebFrame *kit(Frame* frame)
270 FrameLoaderClient& frameLoaderClient = frame->loader().client();
271 if (frameLoaderClient.isEmptyFrameLoaderClient())
274 return static_cast<WebFrameLoaderClient&>(frameLoaderClient).webFrame();
277 Page* core(WebView *webView)
279 return [webView page];
282 WebView *kit(Page* page)
287 if (page->chrome().client().isEmptyChromeClient())
290 return static_cast<WebChromeClient&>(page->chrome().client()).webView();
293 WebView *getWebView(WebFrame *webFrame)
295 Frame* coreFrame = core(webFrame);
298 return kit(coreFrame->page());
301 + (Ref<WebCore::Frame>)_createFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView ownerElement:(HTMLFrameOwnerElement*)ownerElement
303 WebView *webView = kit(page);
305 WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView];
306 Ref<WebCore::Frame> coreFrame = Frame::create(page, ownerElement, new WebFrameLoaderClient(frame));
308 frame->_private->coreFrame = coreFrame.ptr();
310 coreFrame.get().tree().setName(name);
312 ASSERT(ownerElement->document().frame());
313 ownerElement->document().frame()->tree().appendChild(coreFrame.ptr());
316 coreFrame.get().init();
318 [webView _setZoomMultiplier:[webView _realZoomMultiplier] isTextOnly:[webView _realZoomMultiplierIsTextOnly]];
323 + (void)_createMainFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView
325 WebView *webView = kit(page);
327 WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView];
328 frame->_private->coreFrame = &page->mainFrame();
329 static_cast<WebFrameLoaderClient&>(page->mainFrame().loader().client()).setWebFrame(frame);
332 page->mainFrame().tree().setName(name);
333 page->mainFrame().init();
335 [webView _setZoomMultiplier:[webView _realZoomMultiplier] isTextOnly:[webView _realZoomMultiplierIsTextOnly]];
338 + (Ref<WebCore::Frame>)_createSubframeWithOwnerElement:(HTMLFrameOwnerElement*)ownerElement frameName:(const String&)name frameView:(WebFrameView *)frameView
340 return [self _createFrameWithPage:ownerElement->document().frame()->page() frameName:name frameView:frameView ownerElement:ownerElement];
343 - (BOOL)_isIncludedInWebKitStatistics
345 return _private && _private->includedInWebKitStatistics;
349 static NSURL *createUniqueWebDataURL();
351 + (void)_createMainFrameWithSimpleHTMLDocumentWithPage:(Page*)page frameView:(WebFrameView *)frameView style:(NSString *)style
353 WebView *webView = kit(page);
355 WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView];
356 frame->_private->coreFrame = &page->mainFrame();
357 static_cast<WebFrameLoaderClient&>(page->mainFrame().loader().client()).setWebFrame(frame);
360 frame->_private->coreFrame->initWithSimpleHTMLDocument(style, createUniqueWebDataURL());
364 - (void)_attachScriptDebugger
366 ScriptController& scriptController = _private->coreFrame->script();
368 // Calling ScriptController::globalObject() would create a window shell, and dispatch corresponding callbacks, which may be premature
369 // if the script debugger is attached before a document is created. These calls use the debuggerWorld(), we will need to pass a world
370 // to be able to debug isolated worlds.
371 if (!scriptController.existingWindowShell(debuggerWorld()))
374 JSGlobalObject* globalObject = scriptController.globalObject(debuggerWorld());
378 if (_private->scriptDebugger) {
379 ASSERT(_private->scriptDebugger.get() == globalObject->debugger());
383 _private->scriptDebugger = std::make_unique<WebScriptDebugger>(globalObject);
386 - (void)_detachScriptDebugger
388 _private->scriptDebugger = nullptr;
391 - (id)_initWithWebFrameView:(WebFrameView *)fv webView:(WebView *)v
397 _private = [[WebFramePrivate alloc] init];
399 // Set includedInWebKitStatistics before calling WebFrameView _setWebFrame, since
400 // it calls WebFrame _isIncludedInWebKitStatistics.
401 if ((_private->includedInWebKitStatistics = [[v class] shouldIncludeInWebKitStatistics]))
405 [_private setWebFrameView:fv];
406 [fv _setWebFrame:self];
409 _private->shouldCreateRenderers = YES;
414 - (void)_clearCoreFrame
416 _private->coreFrame = 0;
419 - (void)_updateBackgroundAndUpdatesWhileOffscreen
421 WebView *webView = getWebView(self);
422 BOOL drawsBackground = [webView drawsBackground];
424 NSColor *backgroundColor = [webView backgroundColor];
426 CGColorRef backgroundColor = [webView backgroundColor];
429 Frame* coreFrame = _private->coreFrame;
430 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
431 // Don't call setDrawsBackground:YES here because it may be NO because of a load
432 // in progress; WebFrameLoaderClient keeps it set to NO during the load process.
433 WebFrame *webFrame = kit(frame);
434 if (!drawsBackground)
435 [[[webFrame frameView] _scrollView] setDrawsBackground:NO];
437 [[[webFrame frameView] _scrollView] setBackgroundColor:backgroundColor];
440 if (FrameView* view = frame->view()) {
441 view->setTransparent(!drawsBackground);
443 Color color = colorFromNSColor([backgroundColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]);
445 Color color = Color(backgroundColor);
447 view->setBaseBackgroundColor(color);
448 view->setShouldUpdateWhileOffscreen([webView shouldUpdateWhileOffscreen]);
453 - (void)_setInternalLoadDelegate:(id)internalLoadDelegate
455 _private->internalLoadDelegate = internalLoadDelegate;
458 - (id)_internalLoadDelegate
460 return _private->internalLoadDelegate;
463 - (void)_unmarkAllBadGrammar
465 Frame* coreFrame = _private->coreFrame;
466 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
467 if (Document* document = frame->document())
468 document->markers().removeMarkers(DocumentMarker::Grammar);
472 - (void)_unmarkAllMisspellings
475 Frame* coreFrame = _private->coreFrame;
476 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
477 if (Document* document = frame->document())
478 document->markers().removeMarkers(DocumentMarker::Spelling);
483 - (BOOL)_hasSelection
485 id documentView = [_private->webFrameView documentView];
487 // optimization for common case to avoid creating potentially large selection string
488 if ([documentView isKindOfClass:[WebHTMLView class]])
489 if (Frame* coreFrame = _private->coreFrame)
490 return coreFrame->selection().isRange();
492 if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
493 return [[documentView selectedString] length] > 0;
498 - (void)_clearSelection
500 id documentView = [_private->webFrameView documentView];
501 if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
502 [documentView deselectAll];
506 - (BOOL)_atMostOneFrameHasSelection
508 // FIXME: 4186050 is one known case that makes this debug check fail.
510 Frame* coreFrame = _private->coreFrame;
511 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame))
512 if ([kit(frame) _hasSelection]) {
521 - (WebFrame *)_findFrameWithSelection
523 Frame* coreFrame = _private->coreFrame;
524 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
525 WebFrame *webFrame = kit(frame);
526 if ([webFrame _hasSelection])
532 - (void)_clearSelectionInOtherFrames
534 // We rely on WebDocumentSelection protocol implementors to call this method when they become first
535 // responder. It would be nicer to just notice first responder changes here instead, but there's no
536 // notification sent when the first responder changes in general (Radar 2573089).
537 WebFrame *frameWithSelection = [[getWebView(self) mainFrame] _findFrameWithSelection];
538 if (frameWithSelection != self)
539 [frameWithSelection _clearSelection];
541 // While we're in the general area of selection and frames, check that there is only one now.
542 ASSERT([[getWebView(self) mainFrame] _atMostOneFrameHasSelection]);
545 static inline WebDataSource *dataSource(DocumentLoader* loader)
547 return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
550 - (WebDataSource *)_dataSource
552 return dataSource(_private->coreFrame->loader().documentLoader());
556 - (BOOL)_isCommitting
558 return _private->isCommitting;
561 - (void)_setIsCommitting:(BOOL)value
563 _private->isCommitting = value;
567 - (NSArray *)_nodesFromList:(Vector<Node*> *)nodesVector
569 size_t size = nodesVector->size();
570 NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:size];
571 for (size_t i = 0; i < size; ++i)
572 [nodes addObject:kit((*nodesVector)[i])];
576 - (NSString *)_selectedString
578 return _private->coreFrame->displayStringModifiedByEncoding(_private->coreFrame->editor().selectedText());
581 - (NSString *)_stringForRange:(DOMRange *)range
583 return plainText(core(range), TextIteratorDefaultBehavior, true);
586 - (BOOL)_shouldFlattenCompositingLayers:(CGContextRef)context
589 // -currentContextDrawingToScreen returns YES for bitmap contexts.
590 BOOL isPrinting = ![NSGraphicsContext currentContextDrawingToScreen];
595 if (!WKCGContextIsBitmapContext(context))
598 // If we're drawing into a bitmap, we might be snapshotting, or drawing into a layer-backed view.
599 id documentView = [_private->webFrameView documentView];
600 if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _web_isDrawingIntoLayer])
603 return [getWebView(self) _includesFlattenedCompositingLayersWhenDrawingToBitmap];
606 - (void)_drawRect:(NSRect)rect contentsOnly:(BOOL)contentsOnly
609 ASSERT([[NSGraphicsContext currentContext] isFlipped]);
611 CGContextRef ctx = static_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]);
613 CGContextRef ctx = WKGetCurrentGraphicsContext();
615 GraphicsContext context(ctx);
618 // FIXME: when <rdar://problem/9034977> is fixed there will be no need to do this here.
619 WebCore::Frame *frame = core(self);
620 if (WebCore::Page* page = frame->page())
621 context.setIsAcceleratedContext(page->settings().acceleratedDrawingEnabled());
624 FrameView* view = _private->coreFrame->view();
626 bool shouldFlatten = false;
627 if (Frame* parentFrame = _private->coreFrame->tree().parent()) {
628 // For subframes, we need to inherit the paint behavior from our parent
629 FrameView* parentView = parentFrame ? parentFrame->view() : 0;
631 shouldFlatten = parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
633 shouldFlatten = [self _shouldFlattenCompositingLayers:ctx];
635 PaintBehavior oldBehavior = PaintBehaviorNormal;
637 oldBehavior = view->paintBehavior();
638 view->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
642 view->paintContents(context, enclosingIntRect(rect));
644 view->paint(context, enclosingIntRect(rect));
647 view->setPaintBehavior(oldBehavior);
650 - (BOOL)_getVisibleRect:(NSRect*)rect
652 ASSERT_ARG(rect, rect);
653 if (RenderWidget* ownerRenderer = _private->coreFrame->ownerRenderer()) {
654 if (ownerRenderer->needsLayout())
656 *rect = ownerRenderer->pixelSnappedAbsoluteClippedOverflowRect();
663 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string
665 return [self _stringByEvaluatingJavaScriptFromString:string forceUserGesture:true];
668 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture
673 RELEASE_ASSERT(isMainThread());
675 ASSERT(_private->coreFrame->document());
676 RetainPtr<WebFrame> protect(self); // Executing arbitrary JavaScript can destroy the frame.
679 ASSERT(WebThreadIsLockedOrDisabled());
680 JSC::ExecState* exec = _private->coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec();
681 JSC::JSLockHolder jscLock(exec);
684 JSC::JSValue result = _private->coreFrame->script().executeScript(string, forceUserGesture);
686 if (!_private->coreFrame) // In case the script removed our frame from the page.
689 // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
690 // If you don't like it, use -[WebScriptObject evaluateWebScript:] or
691 // JSEvaluateScript instead, since they have less surprising semantics.
692 if (!result || (!result.isBoolean() && !result.isString() && !result.isNumber()))
696 JSC::ExecState* exec = _private->coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec();
697 JSC::JSLockHolder lock(exec);
699 return result.toWTFString(exec);
702 - (NSRect)_caretRectAtPosition:(const Position&)pos affinity:(NSSelectionAffinity)affinity
704 VisiblePosition visiblePosition(pos, static_cast<EAffinity>(affinity));
705 return visiblePosition.absoluteCaretBounds();
708 - (NSRect)_firstRectForDOMRange:(DOMRange *)range
710 return _private->coreFrame->editor().firstRectForRange(core(range));
713 - (void)_scrollDOMRangeToVisible:(DOMRange *)range
715 NSRect rangeRect = [self _firstRectForDOMRange:range];
716 Node *startNode = core([range startContainer]);
718 if (startNode && startNode->renderer()) {
720 startNode->renderer()->scrollRectToVisible(enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
722 RenderLayer* layer = startNode->renderer()->enclosingLayer();
724 layer->setAdjustForIOSCaretWhenScrolling(true);
725 startNode->renderer()->scrollRectToVisible(enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
726 layer->setAdjustForIOSCaretWhenScrolling(false);
727 _private->coreFrame->selection().setCaretRectNeedsUpdate();
728 _private->coreFrame->selection().updateAppearance();
735 - (void)_scrollDOMRangeToVisible:(DOMRange *)range withInset:(CGFloat)inset
737 NSRect rangeRect = NSInsetRect([self _firstRectForDOMRange:range], inset, inset);
738 Node *startNode = core([range startContainer]);
740 if (startNode && startNode->renderer()) {
741 RenderLayer* layer = startNode->renderer()->enclosingLayer();
743 layer->setAdjustForIOSCaretWhenScrolling(true);
744 startNode->renderer()->scrollRectToVisible(enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
745 layer->setAdjustForIOSCaretWhenScrolling(false);
747 Frame *coreFrame = core(self);
749 FrameSelection& frameSelection = coreFrame->selection();
750 frameSelection.setCaretRectNeedsUpdate();
751 frameSelection.updateAppearance();
760 return _private->coreFrame->view() ? _private->coreFrame->view()->needsLayout() : false;
764 - (DOMRange *)_rangeByAlteringCurrentSelection:(FrameSelection::EAlteration)alteration direction:(SelectionDirection)direction granularity:(TextGranularity)granularity
766 if (_private->coreFrame->selection().isNone())
769 FrameSelection selection;
770 selection.setSelection(_private->coreFrame->selection().selection());
771 selection.modify(alteration, direction, granularity);
772 return kit(selection.toNormalizedRange().get());
776 - (TextGranularity)_selectionGranularity
778 return _private->coreFrame->selection().granularity();
781 - (NSRange)_convertToNSRange:(Range *)range
784 return NSMakeRange(NSNotFound, 0);
788 if (!TextIterator::getLocationAndLengthFromRange(_private->coreFrame->selection().rootEditableElementOrDocumentElement(), range, location, length))
789 return NSMakeRange(NSNotFound, 0);
791 return NSMakeRange(location, length);
794 - (PassRefPtr<Range>)_convertToDOMRange:(NSRange)nsrange
796 return [self _convertToDOMRange:nsrange rangeIsRelativeTo:WebRangeIsRelativeTo::EditableRoot];
799 - (PassRefPtr<Range>)_convertToDOMRange:(NSRange)nsrange rangeIsRelativeTo:(WebRangeIsRelativeTo)rangeIsRelativeTo
801 if (nsrange.location > INT_MAX)
803 if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX)
804 nsrange.length = INT_MAX - nsrange.location;
806 if (rangeIsRelativeTo == WebRangeIsRelativeTo::EditableRoot) {
807 // Our critical assumption is that this code path is only called by input methods that
808 // concentrate on a given area containing the selection
809 // We have to do this because of text fields and textareas. The DOM for those is not
810 // directly in the document DOM, so serialization is problematic. Our solution is
811 // to use the root editable element of the selection start as the positional base.
812 // That fits with AppKit's idea of an input context.
813 Element* element = _private->coreFrame->selection().rootEditableElementOrDocumentElement();
816 return TextIterator::rangeFromLocationAndLength(element, nsrange.location, nsrange.length);
819 ASSERT(rangeIsRelativeTo == WebRangeIsRelativeTo::Paragraph);
821 const VisibleSelection& selection = _private->coreFrame->selection().selection();
822 RefPtr<Range> selectedRange = selection.toNormalizedRange();
826 RefPtr<Range> paragraphRange = makeRange(startOfParagraph(selection.visibleStart()), selection.visibleEnd());
830 ContainerNode& rootNode = paragraphRange.get()->startContainer().treeScope().rootNode();
831 int paragraphStartIndex = TextIterator::rangeLength(Range::create(rootNode.document(), &rootNode, 0, ¶graphRange->startContainer(), paragraphRange->startOffset()).ptr());
832 return TextIterator::rangeFromLocationAndLength(&rootNode, paragraphStartIndex + static_cast<int>(nsrange.location), nsrange.length);
835 - (DOMRange *)_convertNSRangeToDOMRange:(NSRange)nsrange
837 return kit([self _convertToDOMRange:nsrange].get());
840 - (NSRange)_convertDOMRangeToNSRange:(DOMRange *)range
842 return [self _convertToNSRange:core(range)];
845 - (DOMRange *)_markDOMRange
847 return kit(_private->coreFrame->editor().mark().toNormalizedRange().get());
850 // Given proposedRange, returns an extended range that includes adjacent whitespace that should
851 // be deleted along with the proposed range in order to preserve proper spacing and punctuation of
852 // the text surrounding the deletion.
853 - (DOMRange *)_smartDeleteRangeForProposedRange:(DOMRange *)proposedRange
855 Node* startContainer = core([proposedRange startContainer]);
856 Node* endContainer = core([proposedRange endContainer]);
857 if (startContainer == nil || endContainer == nil)
860 ASSERT(&startContainer->document() == &endContainer->document());
862 _private->coreFrame->document()->updateLayoutIgnorePendingStylesheets();
864 Position start = Position(startContainer, [proposedRange startOffset], Position::PositionIsOffsetInAnchor);
865 Position end = Position(endContainer, [proposedRange endOffset], Position::PositionIsOffsetInAnchor);
866 Position newStart = start.upstream().leadingWhitespacePosition(DOWNSTREAM, true);
867 if (newStart.isNull())
869 Position newEnd = end.downstream().trailingWhitespacePosition(DOWNSTREAM, true);
873 newStart = newStart.parentAnchoredEquivalent();
874 newEnd = newEnd.parentAnchoredEquivalent();
876 Ref<Range> range = _private->coreFrame->document()->createRange();
877 if (newStart.containerNode()) {
879 range->setStart(*newStart.containerNode(), newStart.offsetInContainerNode(), exception);
880 range->setEnd(*newStart.containerNode(), newStart.offsetInContainerNode(), exception);
882 return kit(range.ptr());
885 - (DOMDocumentFragment *)_documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString
887 Frame* frame = _private->coreFrame;
891 Document* document = frame->document();
895 return kit(createFragmentFromMarkup(*document, markupString, baseURLString, DisallowScriptingContent).ptr());
898 - (DOMDocumentFragment *)_documentFragmentWithNodesAsParagraphs:(NSArray *)nodes
900 Frame* frame = _private->coreFrame;
904 Document* document = frame->document();
908 NSEnumerator *nodeEnum = [nodes objectEnumerator];
909 Vector<Node*> nodesVector;
911 while ((node = [nodeEnum nextObject]))
912 nodesVector.append(core(node));
914 auto fragment = document->createDocumentFragment();
916 for (auto* node : nodesVector) {
917 auto element = createDefaultParagraphElement(*document);
918 element->appendChild(*node);
919 fragment->appendChild(element);
922 return kit(fragment.ptr());
925 - (void)_replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
927 DOMDocumentFragment *fragment = kit(_private->coreFrame->document()->createDocumentFragment().ptr());
928 [fragment appendChild:node];
929 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle];
932 - (void)_insertParagraphSeparatorInQuotedContent
934 if (_private->coreFrame->selection().isNone())
937 _private->coreFrame->editor().insertParagraphSeparatorInQuotedContent();
940 - (VisiblePosition)_visiblePositionForPoint:(NSPoint)point
942 // FIXME: Someone with access to Apple's sources could remove this needless wrapper call.
943 return _private->coreFrame->visiblePositionForPoint(IntPoint(point));
946 - (DOMRange *)_characterRangeAtPoint:(NSPoint)point
948 return kit(_private->coreFrame->rangeForPoint(IntPoint(point)).get());
951 - (DOMCSSStyleDeclaration *)_typingStyle
953 if (!_private->coreFrame)
955 RefPtr<MutableStyleProperties> typingStyle = _private->coreFrame->selection().copyTypingStyle();
958 return kit(typingStyle->ensureCSSStyleDeclaration());
961 - (void)_setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(EditAction)undoAction
963 if (!_private->coreFrame || !style)
965 // FIXME: We shouldn't have to create a copy here.
966 Ref<MutableStyleProperties> properties(core(style)->copyProperties());
967 _private->coreFrame->editor().computeAndSetTypingStyle(properties.get(), undoAction);
970 #if ENABLE(DRAG_SUPPORT)
971 - (void)_dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation
973 if (!_private->coreFrame)
975 FrameView* view = _private->coreFrame->view();
978 // FIXME: These are fake modifier keys here, but they should be real ones instead.
979 PlatformMouseEvent event(IntPoint(windowLoc), IntPoint(globalPoint(windowLoc, [view->platformWidget() window])),
980 LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, currentTime(), WebCore::ForceAtClick);
981 _private->coreFrame->eventHandler().dragSourceEndedAt(event, (DragOperation)operation);
985 - (BOOL)_canProvideDocumentSource
987 Frame* frame = _private->coreFrame;
988 String mimeType = frame->document()->loader()->writer().mimeType();
989 PluginData* pluginData = frame->page() ? &frame->page()->pluginData() : 0;
991 if (WebCore::DOMImplementation::isTextMIMEType(mimeType)
992 || Image::supportsType(mimeType)
993 || (pluginData && pluginData->supportsWebVisibleMimeType(mimeType, PluginData::AllPlugins) && frame->loader().subframeLoader().allowPlugins())
994 || (pluginData && pluginData->supportsWebVisibleMimeType(mimeType, PluginData::OnlyApplicationPlugins)))
1000 - (BOOL)_canSaveAsWebArchive
1002 // Currently, all documents that we can view source for
1003 // (HTML and XML documents) can also be saved as web archives
1004 return [self _canProvideDocumentSource];
1007 - (void)_commitData:(NSData *)data
1009 // FIXME: This really should be a setting.
1010 Document* document = _private->coreFrame->document();
1011 document->setShouldCreateRenderers(_private->shouldCreateRenderers);
1013 _private->coreFrame->loader().documentLoader()->commitData((const char *)[data bytes], [data length]);
1018 @implementation WebFrame (WebPrivate)
1020 // FIXME: This exists only as a convenience for Safari, consider moving there.
1021 - (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor
1023 Frame* coreFrame = _private->coreFrame;
1024 return coreFrame && coreFrame->tree().isDescendantOf(core(ancestor));
1027 - (void)_setShouldCreateRenderers:(BOOL)shouldCreateRenderers
1029 _private->shouldCreateRenderers = shouldCreateRenderers;
1033 - (NSColor *)_bodyBackgroundColor
1035 - (CGColorRef)_bodyBackgroundColor
1038 Document* document = _private->coreFrame->document();
1041 auto* body = document->bodyOrFrameset();
1044 RenderObject* bodyRenderer = body->renderer();
1047 Color color = bodyRenderer->style().visitedDependentColor(CSSPropertyBackgroundColor);
1048 if (!color.isValid())
1051 return nsColor(color);
1053 return cachedCGColor(color);
1059 Document* document = _private->coreFrame->document();
1060 return document && document->isFrameSet();
1063 - (BOOL)_firstLayoutDone
1065 return _private->coreFrame->loader().stateMachine().firstLayoutDone();
1068 - (BOOL)_isVisuallyNonEmpty
1070 if (FrameView* view = _private->coreFrame->view())
1071 return view->isVisuallyNonEmpty();
1075 static WebFrameLoadType toWebFrameLoadType(FrameLoadType frameLoadType)
1077 switch (frameLoadType) {
1078 case FrameLoadType::Standard:
1079 return WebFrameLoadTypeStandard;
1080 case FrameLoadType::Back:
1081 return WebFrameLoadTypeBack;
1082 case FrameLoadType::Forward:
1083 return WebFrameLoadTypeForward;
1084 case FrameLoadType::IndexedBackForward:
1085 return WebFrameLoadTypeIndexedBackForward;
1086 case FrameLoadType::Reload:
1087 return WebFrameLoadTypeReload;
1088 case FrameLoadType::Same:
1089 return WebFrameLoadTypeSame;
1090 case FrameLoadType::RedirectWithLockedBackForwardList:
1091 return WebFrameLoadTypeInternal;
1092 case FrameLoadType::Replace:
1093 return WebFrameLoadTypeReplace;
1094 case FrameLoadType::ReloadFromOrigin:
1095 return WebFrameLoadTypeReloadFromOrigin;
1099 - (WebFrameLoadType)_loadType
1101 return toWebFrameLoadType(_private->coreFrame->loader().loadType());
1107 // Needed for Mail <rdar://problem/6228038>
1108 return _private->coreFrame ? [self _needsLayout] : NO;
1111 - (void)_setLoadsSynchronously:(BOOL)flag
1113 _private->coreFrame->loader().setLoadsSynchronously(flag);
1116 - (BOOL)_loadsSynchronously
1118 return _private->coreFrame->loader().loadsSynchronously();
1123 - (NSArray *)_rectsForRange:(DOMRange *)domRange
1125 Range *range = core(domRange);
1128 Vector<IntRect> intRects;
1129 range->absoluteTextRects(intRects, NO);
1130 unsigned size = intRects.size();
1132 NSMutableArray *rectArray = [NSMutableArray arrayWithCapacity:size];
1133 for (unsigned i = 0; i < size; i++) {
1134 [rectArray addObject:[NSValue valueWithRect:(CGRect )intRects[i]]];
1140 - (DOMRange *)_selectionRangeForFirstPoint:(CGPoint)first secondPoint:(CGPoint)second
1142 VisiblePosition firstPos = [self _visiblePositionForPoint:first];
1143 VisiblePosition secondPos = [self _visiblePositionForPoint:second];
1144 VisibleSelection selection(firstPos, secondPos);
1145 DOMRange *range = kit(selection.toNormalizedRange().get());
1149 - (DOMRange *)_selectionRangeForPoint:(CGPoint)point
1151 VisiblePosition pos = [self _visiblePositionForPoint:point];
1152 VisibleSelection selection(pos);
1153 DOMRange *range = kit(selection.toNormalizedRange().get());
1157 #endif // PLATFORM(IOS)
1159 - (NSRange)_selectedNSRange
1161 return [self _convertToNSRange:_private->coreFrame->selection().toNormalizedRange().get()];
1164 - (void)_selectNSRange:(NSRange)range
1166 RefPtr<Range> domRange = [self _convertToDOMRange:range];
1168 _private->coreFrame->selection().setSelection(VisibleSelection(*domRange, SEL_DEFAULT_AFFINITY));
1171 - (BOOL)_isDisplayingStandaloneImage
1173 Document* document = _private->coreFrame->document();
1174 return document && document->isImageDocument();
1177 - (unsigned)_pendingFrameUnloadEventCount
1179 return _private->coreFrame->document()->domWindow()->pendingUnloadEventListeners();
1182 #if ENABLE(NETSCAPE_PLUGIN_API)
1183 - (void)_recursive_resumeNullEventsForAllNetscapePlugins
1185 Frame* coreFrame = core(self);
1186 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
1187 NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
1188 if ([documentView isKindOfClass:[WebHTMLView class]])
1189 [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins];
1193 - (void)_recursive_pauseNullEventsForAllNetscapePlugins
1195 Frame* coreFrame = core(self);
1196 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
1197 NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
1198 if ([documentView isKindOfClass:[WebHTMLView class]])
1199 [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins];
1205 - (unsigned)formElementsCharacterCount
1207 WebCore::Frame *frame = core(self);
1208 return frame->formElementsCharacterCount();
1211 - (void)setTimeoutsPaused:(BOOL)flag
1213 id documentView = [_private->webFrameView documentView];
1214 if ([documentView isKindOfClass:[WebHTMLView class]]) {
1215 if (Frame* coreFrame = _private->coreFrame)
1216 coreFrame->setTimersPaused(flag);
1220 - (void)setPluginsPaused:(BOOL)flag
1222 WebView *webView = getWebView(self);
1227 [webView _stopAllPlugIns];
1229 [webView _startAllPlugIns];
1232 - (void)prepareForPause
1234 id documentView = [_private->webFrameView documentView];
1235 if ([documentView isKindOfClass:[WebHTMLView class]]) {
1236 if (Frame* coreFrame = _private->coreFrame)
1237 coreFrame->dispatchPageHideEventBeforePause();
1241 - (void)resumeFromPause
1243 id documentView = [_private->webFrameView documentView];
1244 if ([documentView isKindOfClass:[WebHTMLView class]]) {
1245 if (Frame* coreFrame = _private->coreFrame)
1246 coreFrame->dispatchPageShowEventBeforeResume();
1250 - (void)selectNSRange:(NSRange)range
1252 [self _selectNSRange:range];
1255 - (void)selectWithoutClosingTypingNSRange:(NSRange)range
1257 RefPtr<Range> domRange = [self _convertToDOMRange:range];
1259 const VisibleSelection& newSelection = VisibleSelection(*domRange, SEL_DEFAULT_AFFINITY);
1260 _private->coreFrame->selection().setSelection(newSelection, 0);
1262 _private->coreFrame->editor().ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping();
1266 - (NSRange)selectedNSRange
1268 return [self _selectedNSRange];
1271 - (void)forceLayoutAdjustingViewSize:(BOOL)adjust
1273 _private->coreFrame->view()->forceLayout(!adjust);
1275 _private->coreFrame->view()->adjustViewSize();
1278 - (void)_handleKeyEvent:(WebEvent *)event
1280 core(self)->eventHandler().keyEvent(event);
1285 core(self)->selection().selectAll();
1288 - (void)_setSelectionFromNone
1290 core(self)->selection().setSelectionFromNone();
1293 - (void)_restoreViewState
1295 ASSERT(!WebThreadIsEnabled() || WebThreadIsLocked());
1296 _private->coreFrame->loader().client().restoreViewState();
1299 - (void)_saveViewState
1301 ASSERT(!WebThreadIsEnabled() || WebThreadIsLocked());
1302 FrameLoader& frameLoader = _private->coreFrame->loader();
1303 auto* item = frameLoader.history().currentItem();
1305 frameLoader.client().saveViewStateToItem(*item);
1308 - (void)deviceOrientationChanged
1311 if (WebCore::Frame* frame = core(self))
1312 frame->orientationChanged();
1316 - (void)sendOrientationChangeEvent:(int)newOrientation
1318 [self deviceOrientationChanged];
1321 - (void)setNeedsLayout
1323 WebCore::Frame *frame = core(self);
1325 frame->view()->setNeedsLayout();
1328 - (CGSize)renderedSizeOfNode:(DOMNode *)node constrainedToWidth:(float)width
1330 Node* n = core(node);
1331 RenderObject* renderer = n ? n->renderer() : nullptr;
1332 float w = std::min((float)renderer->maxPreferredLogicalWidth(), width);
1333 return is<RenderBox>(renderer) ? CGSizeMake(w, downcast<RenderBox>(*renderer).height()) : CGSizeMake(0, 0);
1336 - (DOMNode *)deepestNodeAtViewportLocation:(CGPoint)aViewportLocation
1338 WebCore::Frame *frame = core(self);
1339 return kit(frame->deepestNodeAtLocation(FloatPoint(aViewportLocation)));
1342 - (DOMNode *)scrollableNodeAtViewportLocation:(CGPoint)aViewportLocation
1344 WebCore::Frame *frame = core(self);
1345 WebCore::Node *node = frame->nodeRespondingToScrollWheelEvents(FloatPoint(aViewportLocation));
1349 - (DOMNode *)approximateNodeAtViewportLocation:(CGPoint *)aViewportLocation
1351 WebCore::Frame *frame = core(self);
1352 FloatPoint viewportLocation(*aViewportLocation);
1353 FloatPoint adjustedLocation;
1354 WebCore::Node *node = frame->nodeRespondingToClickEvents(viewportLocation, adjustedLocation);
1355 *aViewportLocation = adjustedLocation;
1359 - (CGRect)renderRectForPoint:(CGPoint)point isReplaced:(BOOL *)isReplaced fontSize:(float *)fontSize
1361 WebCore::Frame *frame = core(self);
1362 bool replaced = false;
1363 CGRect rect = frame->renderRectForPoint(point, &replaced, fontSize);
1364 *isReplaced = replaced;
1368 - (void)_setProhibitsScrolling:(BOOL)flag
1370 WebCore::Frame *frame = core(self);
1371 frame->view()->setProhibitsScrolling(flag);
1374 - (void)revealSelectionAtExtent:(BOOL)revealExtent
1376 WebCore::Frame *frame = core(self);
1377 RevealExtentOption revealExtentOption = revealExtent ? RevealExtent : DoNotRevealExtent;
1378 frame->selection().revealSelection(ScrollAlignment::alignToEdgeIfNeeded, revealExtentOption);
1381 - (void)resetSelection
1383 WebCore::Frame *frame = core(self);
1384 frame->selection().setSelection(frame->selection().selection());
1387 - (BOOL)hasEditableSelection
1389 WebCore::Frame *frame = core(self);
1390 return frame->selection().selection().isContentEditable();
1393 - (int)preferredHeight
1395 WebCore::Frame *frame = core(self);
1396 return frame->preferredHeight();
1399 - (int)innerLineHeight:(DOMNode *)node
1401 WebCore::Frame *frame = core(self);
1402 return frame->innerLineHeight(node);
1405 - (void)updateLayout
1407 WebCore::Frame *frame = core(self);
1408 frame->updateLayout();
1411 - (void)setIsActive:(BOOL)flag
1413 WebCore::Frame *frame = core(self);
1414 frame->page()->focusController().setActive(flag);
1417 - (void)setSelectionChangeCallbacksDisabled:(BOOL)flag
1419 WebCore::Frame *frame = core(self);
1420 frame->setSelectionChangeCallbacksDisabled(flag);
1425 WebCore::Frame *frame = core(self);
1426 return frame->caretRect();
1429 - (NSRect)rectForScrollToVisible
1431 WebCore::Frame *frame = core(self);
1432 return frame->rectForScrollToVisible();
1435 - (void)setCaretColor:(CGColorRef)color
1437 Color qColor = color ? Color(color) : Color::black;
1438 WebCore::Frame *frame = core(self);
1439 frame->selection().setCaretColor(qColor);
1442 - (NSView *)documentView
1444 WebCore::Frame *frame = core(self);
1445 return [[kit(frame) frameView] documentView];
1450 WebCore::Frame *frame = core(self);
1451 if (!frame || !frame->view())
1453 return frame->view()->layoutCount();
1456 - (BOOL)isTelephoneNumberParsingAllowed
1458 Document *document = core(self)->document();
1459 return document->isTelephoneNumberParsingAllowed();
1462 - (BOOL)isTelephoneNumberParsingEnabled
1464 Document *document = core(self)->document();
1465 return document->isTelephoneNumberParsingEnabled();
1468 - (DOMRange *)selectedDOMRange
1470 WebCore::Frame *frame = core(self);
1471 RefPtr<WebCore::Range> range = frame->selection().toNormalizedRange();
1472 return kit(range.get());
1475 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)affinity closeTyping:(BOOL)closeTyping
1477 WebCore::Frame *frame = core(self);
1479 // Ensure the view becomes first responder.
1480 // This does not happen automatically on iOS because we don't forward
1481 // all the click events to WebKit.
1482 if (FrameView* frameView = frame->view()) {
1483 if (NSView *documentView = frameView->documentView()) {
1484 Page* page = frame->page();
1487 page->chrome().focusNSView(documentView);
1491 frame->selection().setSelectedRange(core(range), (EAffinity)affinity, closeTyping);
1493 frame->editor().ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping();
1496 - (NSSelectionAffinity)selectionAffinity
1498 WebCore::Frame *frame = core(self);
1499 return (NSSelectionAffinity)(frame->selection().selection().affinity());
1502 - (void)expandSelectionToElementContainingCaretSelection
1504 WebCore::Frame *frame = core(self);
1505 frame->selection().expandSelectionToElementContainingCaretSelection();
1508 - (DOMRange *)elementRangeContainingCaretSelection
1510 WebCore::Frame *frame = core(self);
1511 RefPtr<WebCore::Range> range = frame->selection().elementRangeContainingCaretSelection();
1512 return kit(range.get());
1515 - (void)expandSelectionToWordContainingCaretSelection
1517 WebCore::Frame *frame = core(self);
1518 frame->selection().expandSelectionToWordContainingCaretSelection();
1521 - (void)expandSelectionToStartOfWordContainingCaretSelection
1523 WebCore::Frame *frame = core(self);
1524 frame->selection().expandSelectionToStartOfWordContainingCaretSelection();
1527 - (unichar)characterInRelationToCaretSelection:(int)amount
1529 WebCore::Frame *frame = core(self);
1530 return frame->selection().characterInRelationToCaretSelection(amount);
1533 - (unichar)characterBeforeCaretSelection
1535 WebCore::Frame *frame = core(self);
1536 return frame->selection().characterBeforeCaretSelection();
1539 - (unichar)characterAfterCaretSelection
1541 WebCore::Frame *frame = core(self);
1542 return frame->selection().characterAfterCaretSelection();
1545 - (DOMRange *)wordRangeContainingCaretSelection
1547 WebCore::Frame *frame = core(self);
1548 RefPtr<WebCore::Range> range = frame->selection().wordRangeContainingCaretSelection();
1549 return kit(range.get());
1552 - (NSString *)wordInRange:(DOMRange *)range
1556 return [self _stringForRange:range];
1559 - (int)wordOffsetInRange:(DOMRange *)range
1561 WebCore::Frame *frame = core(self);
1562 return frame->selection().wordOffsetInRange(core(range));
1565 - (BOOL)spaceFollowsWordInRange:(DOMRange *)range
1567 WebCore::Frame *frame = core(self);
1568 return frame->selection().spaceFollowsWordInRange(core(range));
1571 - (NSArray *)wordsInCurrentParagraph
1573 WebCore::Frame *frame = core(self);
1574 return frame->wordsInCurrentParagraph();
1577 - (BOOL)selectionAtDocumentStart
1579 WebCore::Frame *frame = core(self);
1581 if (frame->selection().selection().isNone())
1584 frame->document()->updateLayout();
1586 return frame->selection().selectionAtDocumentStart();
1589 - (BOOL)selectionAtSentenceStart
1591 WebCore::Frame *frame = core(self);
1593 if (frame->selection().selection().isNone())
1596 frame->document()->updateLayout();
1598 return frame->selection().selectionAtSentenceStart();
1601 - (BOOL)selectionAtWordStart
1603 WebCore::Frame *frame = core(self);
1605 if (frame->selection().selection().isNone())
1608 frame->document()->updateLayout();
1610 return frame->selection().selectionAtWordStart();
1613 - (DOMRange *)rangeByMovingCurrentSelection:(int)amount
1615 WebCore::Frame *frame = core(self);
1616 RefPtr<WebCore::Range> range = frame->selection().rangeByMovingCurrentSelection(amount);
1617 return kit(range.get());
1620 - (DOMRange *)rangeByExtendingCurrentSelection:(int)amount
1622 WebCore::Frame *frame = core(self);
1623 RefPtr<WebCore::Range> range = frame->selection().rangeByExtendingCurrentSelection(amount);
1624 return kit(range.get());
1627 - (void)selectNSRange:(NSRange)range onElement:(DOMElement *)element
1629 WebCore::Frame *frame = core(self);
1631 Document *doc = frame->document();
1635 Node* node = core(element);
1636 if (!node->inDocument())
1639 frame->selection().selectRangeOnElement(range.location, range.length, *node);
1642 - (DOMRange *)markedTextDOMRange
1644 WebCore::Frame *frame = core(self);
1648 return kit(frame->editor().compositionRange().get());
1651 - (void)setMarkedText:(NSString *)text selectedRange:(NSRange)newSelRange
1653 WebCore::Frame *frame = core(self);
1657 Vector<CompositionUnderline> underlines;
1658 frame->page()->chrome().client().suppressFormNotifications();
1659 frame->editor().setComposition(text, underlines, newSelRange.location, NSMaxRange(newSelRange));
1660 frame->page()->chrome().client().restoreFormNotifications();
1663 - (void)setMarkedText:(NSString *)text forCandidates:(BOOL)forCandidates
1665 WebCore::Frame *frame = core(self);
1669 Vector<CompositionUnderline> underlines;
1670 frame->editor().setComposition(text, underlines, 0, [text length]);
1673 - (void)confirmMarkedText:(NSString *)text
1675 WebCore::Frame *frame = core(self);
1676 if (!frame || !frame->editor().client())
1679 frame->page()->chrome().client().suppressFormNotifications();
1681 frame->editor().confirmComposition(text);
1683 frame->editor().confirmMarkedText();
1684 frame->page()->chrome().client().restoreFormNotifications();
1687 - (void)setText:(NSString *)text asChildOfElement:(DOMElement *)element
1692 WebCore::Frame *frame = core(self);
1693 if (!frame || !frame->document())
1696 frame->editor().setTextAsChildOfElement(text, *core(element));
1699 - (void)setDictationPhrases:(NSArray *)dictationPhrases metadata:(id)metadata asChildOfElement:(DOMElement *)element
1704 auto* frame = core(self);
1708 frame->editor().setDictationPhrasesAsChildOfElement(vectorForDictationPhrasesArray(dictationPhrases), metadata, *core(element));
1711 - (NSArray *)interpretationsForCurrentRoot
1713 return core(self)->interpretationsForCurrentRoot();
1716 // Collects the ranges and metadata for all of the mars voltas in the root editable element.
1717 - (void)getDictationResultRanges:(NSArray **)outRanges andMetadatas:(NSArray **)outMetadatas
1723 // *outRanges should not already point to an array.
1724 ASSERT(!(*outRanges));
1727 ASSERT(outMetadatas);
1731 // *metadata should not already point to an array.
1732 ASSERT(!(*outMetadatas));
1733 *outMetadatas = nil;
1735 NSMutableArray *ranges = [NSMutableArray array];
1736 NSMutableArray *metadatas = [NSMutableArray array];
1738 Frame* frame = core(self);
1739 Document* document = frame->document();
1741 const VisibleSelection& selection = frame->selection().selection();
1742 Element* root = selection.selectionType() == VisibleSelection::NoSelection ? frame->document()->bodyOrFrameset() : selection.rootEditableElement();
1744 DOMRange *previousDOMRange = nil;
1745 id previousMetadata = nil;
1747 for (Node* node = root; node; node = NodeTraversal::next(*node)) {
1748 auto markers = document->markers().markersFor(node);
1749 for (auto* marker : markers) {
1751 if (marker->type() != DocumentMarker::DictationResult)
1754 id metadata = marker->metadata();
1756 // All result markers should have metadata.
1761 RefPtr<Range> range = Range::create(*document, node, marker->startOffset(), node, marker->endOffset());
1762 DOMRange *domRange = kit(range.get());
1764 if (metadata != previousMetadata) {
1765 [metadatas addObject:metadata];
1766 [ranges addObject:domRange];
1767 previousMetadata = metadata;
1768 previousDOMRange = domRange;
1770 // It is possible for a DocumentMarker to be split by editing. Adjacent markers with the
1771 // the same metadata are for the same result. So combine their ranges.
1772 ASSERT(previousDOMRange == [ranges lastObject]);
1773 [previousDOMRange retain];
1774 [ranges removeLastObject];
1775 DOMNode *startContainer = [domRange startContainer];
1776 int startOffset = [domRange startOffset];
1777 [previousDOMRange setEnd:startContainer offset:startOffset];
1778 [ranges addObject:previousDOMRange];
1779 [previousDOMRange release];
1784 *outRanges = ranges;
1785 *outMetadatas = metadatas;
1790 - (id)dictationResultMetadataForRange:(DOMRange *)range
1795 auto markers = core(self)->document()->markers().markersInRange(core(range), DocumentMarker::DictationResult);
1797 // UIKit should only ever give us a DOMRange for a phrase with alternatives, which should not be part of more than one result.
1798 ASSERT(markers.size() <= 1);
1799 if (markers.size() == 0)
1802 return markers[0]->metadata();
1805 - (void)recursiveSetUpdateAppearanceEnabled:(BOOL)enabled
1807 WebCore::Frame *frame = core(self);
1809 frame->recursiveSetUpdateAppearanceEnabled(enabled);
1812 // WebCoreFrameBridge methods used by iOS applications and frameworks
1813 // FIXME: WebCoreFrameBridge is long gone. Can we remove these methods?
1815 + (NSString *)stringWithData:(NSData *)data textEncodingName:(NSString *)textEncodingName
1817 WebCore::TextEncoding encoding(textEncodingName);
1818 if (!encoding.isValid())
1819 encoding = WindowsLatin1Encoding();
1820 return encoding.decode(reinterpret_cast<const char*>([data bytes]), [data length]);
1823 - (NSRect)caretRectAtNode:(DOMNode *)node offset:(int)offset affinity:(NSSelectionAffinity)affinity
1825 return [self _caretRectAtPosition:createLegacyEditingPosition(core(node), offset) affinity:affinity];
1828 - (DOMRange *)characterRangeAtPoint:(NSPoint)point
1830 return [self _characterRangeAtPoint:point];
1833 - (NSRange)convertDOMRangeToNSRange:(DOMRange *)range
1835 return [self _convertDOMRangeToNSRange:range];
1838 - (DOMRange *)convertNSRangeToDOMRange:(NSRange)nsrange
1840 return [self _convertNSRangeToDOMRange:nsrange];
1843 - (NSRect)firstRectForDOMRange:(DOMRange *)range
1845 return [self _firstRectForDOMRange:range];
1848 - (CTFontRef)fontForSelection:(BOOL *)hasMultipleFonts
1850 bool multipleFonts = false;
1851 CTFontRef font = nil;
1852 if (_private->coreFrame) {
1854 * fd = _private->coreFrame->editor().fontForSelection(multipleFonts);
1856 font = fd->getCTFont();
1859 if (hasMultipleFonts)
1860 *hasMultipleFonts = multipleFonts;
1864 - (void)sendScrollEvent
1866 ASSERT(WebThreadIsLockedOrDisabled());
1867 _private->coreFrame->eventHandler().sendScrollEvent();
1870 - (void)_userScrolled
1872 ASSERT(WebThreadIsLockedOrDisabled());
1873 if (FrameView* view = _private->coreFrame->view())
1874 view->setWasScrolledByUser(true);
1877 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture
1879 return [self _stringByEvaluatingJavaScriptFromString:string forceUserGesture:forceUserGesture];
1882 - (NSString *)stringForRange:(DOMRange *)range
1884 return [self _stringForRange:range];
1888 // FIXME: We needed to add this method for iOS due to the opensource version's inclusion of
1889 // matchStyle:YES. It seems odd that we should need to explicitly match style, given that the
1890 // fragment is being made out of plain text, which shouldn't be carrying any style of its own.
1891 // When we paste that it will pick up its style from the surrounding content. What else would
1892 // we expect? If we flipped that matchStyle bit to NO, we could probably just get rid
1893 // of this method, and call the standard WebKit version.
1895 // There's a second problem here, too, which is that ReplaceSelectionCommand sometimes adds
1898 - (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
1900 RefPtr<Range> range = _private->coreFrame->selection().toNormalizedRange();
1902 DOMDocumentFragment* fragment = range ? kit(createFragmentFromText(*range, text).ptr()) : nil;
1903 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle];
1906 - (void)_replaceSelectionWithWebArchive:(WebArchive *)webArchive selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1908 NSArray* subresources = [webArchive subresources];
1909 for (WebResource* subresource in subresources) {
1910 if (![[self dataSource] subresourceForURL:[subresource URL]])
1911 [[self dataSource] addSubresource:subresource];
1914 DOMDocumentFragment* fragment = [[self dataSource] _documentFragmentWithArchive:webArchive];
1915 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
1918 #endif // PLATFORM(IOS)
1920 #if ENABLE(IOS_TEXT_AUTOSIZING)
1921 - (void)resetTextAutosizingBeforeLayout
1923 id documentView = [_private->webFrameView documentView];
1924 if (![documentView isKindOfClass:[WebHTMLView class]])
1927 Frame* coreFrame = core(self);
1928 for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
1929 Document *doc = frame->document();
1930 if (!doc || !doc->renderView())
1932 doc->renderView()->resetTextAutosizing();
1936 - (void)_setVisibleSize:(CGSize)size
1938 [self _setTextAutosizingWidth:size.width];
1941 - (void)_setTextAutosizingWidth:(CGFloat)width
1943 WebCore::Frame* frame = core(self);
1944 Page* page = frame->page();
1948 page->setTextAutosizingWidth(width);
1951 - (void)resetTextAutosizingBeforeLayout
1955 - (void)_setVisibleSize:(CGSize)size
1959 - (void)_setTextAutosizingWidth:(CGFloat)width
1962 #endif // ENABLE(IOS_TEXT_AUTOSIZING)
1964 - (void)_replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
1966 if (_private->coreFrame->selection().isNone() || !fragment)
1968 _private->coreFrame->editor().replaceSelectionWithFragment(core(fragment), selectReplacement, smartReplace, matchStyle);
1972 - (void)removeUnchangeableStyles
1974 _private->coreFrame->editor().removeUnchangeableStyles();
1977 - (BOOL)hasRichlyEditableSelection
1979 return _private->coreFrame->selection().selection().isContentRichlyEditable();
1983 - (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1985 RefPtr<Range> range = _private->coreFrame->selection().toNormalizedRange();
1987 DOMDocumentFragment* fragment = range ? kit(createFragmentFromText(*range, text).ptr()) : nil;
1988 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES];
1991 - (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1993 DOMDocumentFragment *fragment = [self _documentFragmentWithMarkupString:markupString baseURLString:baseURLString];
1994 [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
1998 // Determines whether whitespace needs to be added around aString to preserve proper spacing and
1999 // punctuation when it's inserted into the receiver's text over charRange. Returns by reference
2000 // in beforeString and afterString any whitespace that should be added, unless either or both are
2001 // nil. Both are returned as nil if aString is nil or if smart insertion and deletion are disabled.
2002 - (void)_smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString
2004 // give back nil pointers in case of early returns
2006 *beforeString = nil;
2010 // inspect destination
2011 Node *startContainer = core([rangeToReplace startContainer]);
2012 Node *endContainer = core([rangeToReplace endContainer]);
2014 Position startPos(startContainer, [rangeToReplace startOffset], Position::PositionIsOffsetInAnchor);
2015 Position endPos(endContainer, [rangeToReplace endOffset], Position::PositionIsOffsetInAnchor);
2017 VisiblePosition startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY);
2018 VisiblePosition endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY);
2020 // this check also ensures startContainer, startPos, endContainer, and endPos are non-null
2021 if (startVisiblePos.isNull() || endVisiblePos.isNull())
2024 bool addLeadingSpace = startPos.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos);
2025 if (addLeadingSpace)
2026 if (UChar previousChar = startVisiblePos.previous().characterAfter())
2027 addLeadingSpace = !isCharacterSmartReplaceExempt(previousChar, true);
2029 bool addTrailingSpace = endPos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos);
2030 if (addTrailingSpace)
2031 if (UChar thisChar = endVisiblePos.characterAfter())
2032 addTrailingSpace = !isCharacterSmartReplaceExempt(thisChar, false);
2035 bool hasWhitespaceAtStart = false;
2036 bool hasWhitespaceAtEnd = false;
2037 unsigned pasteLength = [pasteString length];
2038 if (pasteLength > 0) {
2039 NSCharacterSet *whiteSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
2041 if ([whiteSet characterIsMember:[pasteString characterAtIndex:0]]) {
2042 hasWhitespaceAtStart = YES;
2044 if ([whiteSet characterIsMember:[pasteString characterAtIndex:(pasteLength - 1)]]) {
2045 hasWhitespaceAtEnd = YES;
2049 // issue the verdict
2050 if (beforeString && addLeadingSpace && !hasWhitespaceAtStart)
2051 *beforeString = @" ";
2052 if (afterString && addTrailingSpace && !hasWhitespaceAtEnd)
2053 *afterString = @" ";
2055 #endif // !PLATFORM(IOS)
2057 - (NSMutableDictionary *)_cacheabilityDictionary
2059 NSMutableDictionary *result = [NSMutableDictionary dictionary];
2061 FrameLoader& frameLoader = _private->coreFrame->loader();
2062 DocumentLoader* documentLoader = frameLoader.documentLoader();
2063 if (documentLoader && !documentLoader->mainDocumentError().isNull())
2064 [result setObject:(NSError *)documentLoader->mainDocumentError() forKey:WebFrameMainDocumentError];
2066 if (frameLoader.subframeLoader().containsPlugins())
2067 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasPlugins];
2069 if (DOMWindow* domWindow = _private->coreFrame->document()->domWindow()) {
2070 if (domWindow->hasEventListeners(eventNames().unloadEvent))
2071 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasUnloadListener];
2072 if (domWindow->optionalApplicationCache())
2073 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesApplicationCache];
2076 if (Document* document = _private->coreFrame->document()) {
2077 if (DatabaseManager::singleton().hasOpenDatabases(document))
2078 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesDatabases];
2079 if (!document->canSuspendActiveDOMObjectsForDocumentSuspension())
2080 [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameCanSuspendActiveDOMObjects];
2086 - (BOOL)_allowsFollowingLink:(NSURL *)URL
2088 if (!_private->coreFrame)
2090 return _private->coreFrame->document()->securityOrigin()->canDisplay(URL);
2093 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string withGlobalObject:(JSObjectRef)globalObjectRef inScriptWorld:(WebScriptWorld *)world
2101 // Start off with some guess at a frame and a global object, we'll try to do better...!
2102 JSDOMWindow* anyWorldGlobalObject = _private->coreFrame->script().globalObject(mainThreadNormalWorld());
2104 // The global object is probably a shell object? - if so, we know how to use this!
2105 JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
2106 if (!strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell"))
2107 anyWorldGlobalObject = static_cast<JSDOMWindowShell*>(globalObjectObj)->window();
2109 // Get the frame frome the global object we've settled on.
2110 Frame* frame = anyWorldGlobalObject->wrapped().frame();
2111 ASSERT(frame->document());
2112 RetainPtr<WebFrame> webFrame(kit(frame)); // Running arbitrary JavaScript can destroy the frame.
2114 JSC::JSValue result = frame->script().executeScriptInWorld(*core(world), string, true);
2116 if (!webFrame->_private->coreFrame) // In case the script removed our frame from the page.
2119 // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
2120 // If you don't like it, use -[WebScriptObject evaluateWebScript:] or
2121 // JSEvaluateScript instead, since they have less surprising semantics.
2122 if (!result || (!result.isBoolean() && !result.isString() && !result.isNumber()))
2125 JSC::ExecState* exec = anyWorldGlobalObject->globalExec();
2126 JSC::JSLockHolder lock(exec);
2127 return result.toWTFString(exec);
2130 - (JSGlobalContextRef)_globalContextForScriptWorld:(WebScriptWorld *)world
2132 Frame* coreFrame = _private->coreFrame;
2135 DOMWrapperWorld* coreWorld = core(world);
2138 return toGlobalRef(coreFrame->script().globalObject(*coreWorld)->globalExec());
2141 #if JSC_OBJC_API_ENABLED
2142 - (JSContext *)_javaScriptContextForScriptWorld:(WebScriptWorld *)world
2144 JSGlobalContextRef globalContextRef = [self _globalContextForScriptWorld:world];
2145 if (!globalContextRef)
2147 return [JSContext contextWithJSGlobalContextRef:globalContextRef];
2152 - (void)setAllowsScrollersToOverlapContent:(BOOL)flag
2154 ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
2155 [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAllowsScrollersToOverlapContent:flag];
2158 - (void)setAlwaysHideHorizontalScroller:(BOOL)flag
2160 ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
2161 [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAlwaysHideHorizontalScroller:flag];
2163 - (void)setAlwaysHideVerticalScroller:(BOOL)flag
2165 ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
2166 [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAlwaysHideVerticalScroller:flag];
2170 - (void)setAccessibleName:(NSString *)name
2172 #if HAVE(ACCESSIBILITY)
2173 if (!AXObjectCache::accessibilityEnabled())
2176 if (!_private->coreFrame || !_private->coreFrame->document())
2179 AccessibilityObject* rootObject = _private->coreFrame->document()->axObjectCache()->rootObject();
2181 String strName(name);
2182 rootObject->setAccessibleName(strName);
2187 - (BOOL)enhancedAccessibilityEnabled
2189 #if HAVE(ACCESSIBILITY)
2190 return AXObjectCache::accessibilityEnhancedUserInterfaceEnabled();
2196 - (void)setEnhancedAccessibility:(BOOL)enable
2198 #if HAVE(ACCESSIBILITY)
2199 AXObjectCache::setEnhancedUserInterfaceAccessibility(enable);
2203 - (NSString*)_layerTreeAsText
2205 Frame* coreFrame = _private->coreFrame;
2209 return coreFrame->layerTreeAsText();
2212 - (id)accessibilityRoot
2214 #if HAVE(ACCESSIBILITY)
2215 if (!AXObjectCache::accessibilityEnabled()) {
2216 AXObjectCache::enableAccessibility();
2218 #pragma clang diagnostic push
2219 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2220 AXObjectCache::setEnhancedUserInterfaceAccessibility([[NSApp accessibilityAttributeValue:NSAccessibilityEnhancedUserInterfaceAttribute] boolValue]);
2221 #pragma clang diagnostic pop
2225 if (!_private->coreFrame)
2228 Document* document = _private->coreFrame->document();
2229 if (!document || !document->axObjectCache())
2232 AccessibilityObject* rootObject = document->axObjectCache()->rootObjectForFrame(_private->coreFrame);
2236 // The root object will be a WebCore scroll view object. In WK1, scroll views are handled
2237 // by the system and the root object should be the web area (instead of the scroll view).
2238 if (rootObject->isAttachment() && rootObject->firstChild())
2239 return rootObject->firstChild()->wrapper();
2241 return rootObject->wrapper();
2247 - (void)_clearOpener
2249 Frame* coreFrame = _private->coreFrame;
2251 coreFrame->loader().setOpener(0);
2254 // Used by pagination code called from AppKit when a standalone web page is printed.
2255 - (NSArray *)_computePageRectsWithPrintScaleFactor:(float)printScaleFactor pageSize:(NSSize)pageSize
2257 if (printScaleFactor <= 0) {
2258 LOG_ERROR("printScaleFactor has bad value %.2f", printScaleFactor);
2259 return [NSArray array];
2262 if (!_private->coreFrame)
2263 return [NSArray array];
2264 if (!_private->coreFrame->document())
2265 return [NSArray array];
2266 if (!_private->coreFrame->view())
2267 return [NSArray array];
2268 if (!_private->coreFrame->view()->documentView())
2269 return [NSArray array];
2271 RenderView* root = _private->coreFrame->document()->renderView();
2273 return [NSArray array];
2275 const LayoutRect& documentRect = root->documentRect();
2276 float printWidth = root->style().isHorizontalWritingMode() ? static_cast<float>(documentRect.width()) / printScaleFactor : pageSize.width;
2277 float printHeight = root->style().isHorizontalWritingMode() ? pageSize.height : static_cast<float>(documentRect.height()) / printScaleFactor;
2279 PrintContext printContext(_private->coreFrame);
2280 printContext.computePageRectsWithPageSize(FloatSize(printWidth, printHeight), true);
2281 const Vector<IntRect>& pageRects = printContext.pageRects();
2283 size_t size = pageRects.size();
2284 NSMutableArray *pages = [NSMutableArray arrayWithCapacity:size];
2285 for (size_t i = 0; i < size; ++i)
2286 [pages addObject:[NSValue valueWithRect:NSRect(pageRects[i])]];
2291 - (DOMDocumentFragment *)_documentFragmentForText:(NSString *)text
2293 return kit(createFragmentFromText(*_private->coreFrame->selection().toNormalizedRange().get(), text).ptr());
2296 - (DOMDocumentFragment *)_documentFragmentForWebArchive:(WebArchive *)webArchive
2298 return [[self dataSource] _documentFragmentWithArchive:webArchive];
2301 - (DOMDocumentFragment *)_documentFragmentForImageData:(NSData *)data withRelativeURLPart:(NSString *)relativeURLPart andMIMEType:(NSString *)mimeType
2303 WebResource *resource = [[WebResource alloc] initWithData:data
2304 URL:[NSURL uniqueURLWithRelativePart:relativeURLPart]
2306 textEncodingName:nil
2308 DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
2313 - (BOOL)focusedNodeHasContent
2315 Frame* coreFrame = _private->coreFrame;
2318 const VisibleSelection& selection = coreFrame->selection().selection();
2319 if (selection.isNone() || !selection.isContentEditable())
2320 root = coreFrame->document()->bodyOrFrameset();
2322 // Can't use the focusedNode here because we want the root of the shadow tree for form elements.
2323 root = selection.rootEditableElement();
2325 // Early return to avoid the expense of creating VisiblePositions.
2326 // FIXME: We fail to compute a root for SVG, we have a null check here so that we don't crash.
2327 if (!root || !root->hasChildNodes())
2330 VisiblePosition first(createLegacyEditingPosition(root, 0));
2331 VisiblePosition last(createLegacyEditingPosition(root, root->countChildNodes()));
2332 return first != last;
2335 - (void)_dispatchDidReceiveTitle:(NSString *)title
2337 Frame* coreFrame = _private->coreFrame;
2340 coreFrame->loader().client().dispatchDidReceiveTitle(StringWithDirection(title, LTR));
2342 #endif // PLATFORM(IOS)
2344 - (JSValueRef)jsWrapperForNode:(DOMNode *)node inScriptWorld:(WebScriptWorld *)world
2346 Frame* coreFrame = _private->coreFrame;
2353 JSDOMWindow* globalObject = coreFrame->script().globalObject(*core(world));
2354 JSC::ExecState* exec = globalObject->globalExec();
2356 JSC::JSLockHolder lock(exec);
2357 return toRef(exec, toJS(exec, globalObject, core(node)));
2360 - (NSDictionary *)elementAtPoint:(NSPoint)point
2362 Frame* coreFrame = _private->coreFrame;
2365 return [[[WebElementDictionary alloc] initWithHitTestResult:coreFrame->eventHandler().hitTestResultAtPoint(IntPoint(point), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowUserAgentShadowContent)] autorelease];
2368 - (NSURL *)_unreachableURL
2370 return [[self _dataSource] unreachableURL];
2375 @implementation WebFrame
2377 - (instancetype)init
2382 // Should be deprecated.
2383 - (instancetype)initWithName:(NSString *)name webFrameView:(WebFrameView *)view webView:(WebView *)webView
2390 if (_private && _private->includedInWebKitStatistics)
2400 Frame* coreFrame = _private->coreFrame;
2403 return coreFrame->tree().uniqueName();
2406 - (WebFrameView *)frameView
2408 return _private->webFrameView;
2411 - (WebView *)webView
2413 return getWebView(self);
2416 static bool needsMicrosoftMessengerDOMDocumentWorkaround()
2421 static bool needsWorkaround = MacApplication::isMicrosoftMessenger() && [[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] compare:@"7.1" options:NSNumericSearch] == NSOrderedAscending;
2422 return needsWorkaround;
2426 - (DOMDocument *)DOMDocument
2428 if (needsMicrosoftMessengerDOMDocumentWorkaround() && !pthread_main_np())
2431 Frame* coreFrame = _private->coreFrame;
2435 // FIXME: <rdar://problem/5145841> When loading a custom view/representation
2436 // into a web frame, the old document can still be around. This makes sure that
2437 // we'll return nil in those cases.
2438 if (![[self _dataSource] _isDocumentHTML])
2441 Document* document = coreFrame->document();
2443 // According to the documentation, we should return nil if the frame doesn't have a document.
2444 // While full-frame images and plugins do have an underlying HTML document, we return nil here to be
2445 // backwards compatible.
2446 if (document && (document->isPluginDocument() || document->isImageDocument()))
2449 return kit(coreFrame->document());
2452 - (DOMHTMLElement *)frameElement
2454 Frame* coreFrame = _private->coreFrame;
2457 return kit(coreFrame->ownerElement());
2460 - (WebDataSource *)provisionalDataSource
2462 Frame* coreFrame = _private->coreFrame;
2463 return coreFrame ? dataSource(coreFrame->loader().provisionalDocumentLoader()) : nil;
2466 - (WebDataSource *)dataSource
2468 Frame* coreFrame = _private->coreFrame;
2469 return coreFrame && coreFrame->loader().frameHasLoaded() ? [self _dataSource] : nil;
2472 - (void)loadRequest:(NSURLRequest *)request
2474 Frame* coreFrame = _private->coreFrame;
2478 ResourceRequest resourceRequest(request);
2480 // Some users of WebKit API incorrectly use "file path as URL" style requests which are invalid.
2481 // By re-writing those URLs here we technically break the -[WebDataSource initialRequest] API
2482 // but that is necessary to implement this quirk only at the API boundary.
2483 // Note that other users of WebKit API use nil requests or requests with nil URLs or empty URLs, so we
2484 // only implement this workaround when the request had a non-nil or non-empty URL.
2485 if (!resourceRequest.url().isValid() && !resourceRequest.url().isEmpty())
2486 resourceRequest.setURL([NSURL URLWithString:[@"file:" stringByAppendingString:[[request URL] absoluteString]]]);
2488 coreFrame->loader().load(FrameLoadRequest(coreFrame, resourceRequest, ShouldOpenExternalURLsPolicy::ShouldNotAllow));
2491 static NSURL *createUniqueWebDataURL()
2493 CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
2494 NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
2496 NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"applewebdata://%@", UUIDString]];
2497 CFRelease(UUIDString);
2501 - (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
2504 if (!pthread_main_np())
2505 return [[self _webkit_invokeOnMainThread] _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:unreachableURL];
2508 NSURL *responseURL = nil;
2510 baseURL = [baseURL absoluteURL];
2512 baseURL = blankURL();
2513 responseURL = createUniqueWebDataURL();
2517 if (shouldUseQuickLookForMIMEType(MIMEType)) {
2518 NSURL *quickLookURL = responseURL ? responseURL : baseURL;
2519 if (auto request = registerQLPreviewConverterIfNeeded(quickLookURL, MIMEType, data)) {
2520 _private->coreFrame->loader().load(FrameLoadRequest(_private->coreFrame, request.get(), ShouldOpenExternalURLsPolicy::ShouldNotAllow));
2526 ResourceRequest request(baseURL);
2529 // hack because Mail checks for this property to detect data / archive loads
2530 [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest(UpdateHTTPBody)];
2533 ResourceResponse response(responseURL, MIMEType, [data length], encodingName);
2534 SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData(data), [unreachableURL absoluteURL], response, SubstituteData::SessionHistoryVisibility::Hidden);
2536 _private->coreFrame->loader().load(FrameLoadRequest(_private->coreFrame, request, ShouldOpenExternalURLsPolicy::ShouldNotAllow, substituteData));
2539 - (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL
2541 WebCoreThreadViolationCheckRoundTwo();
2544 MIMEType = @"text/html";
2545 [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:[baseURL _webkit_URLFromURLOrSchemelessFileURL] unreachableURL:nil];
2548 - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
2550 NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
2551 [self _loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:baseURL unreachableURL:unreachableURL];
2554 - (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL
2556 WebCoreThreadViolationCheckRoundTwo();
2558 [self _loadHTMLString:string baseURL:[baseURL _webkit_URLFromURLOrSchemelessFileURL] unreachableURL:nil];
2561 - (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL
2563 WebCoreThreadViolationCheckRoundTwo();
2565 [self _loadHTMLString:string baseURL:[baseURL _webkit_URLFromURLOrSchemelessFileURL] unreachableURL:[unreachableURL _webkit_URLFromURLOrSchemelessFileURL]];
2568 - (void)loadArchive:(WebArchive *)archive
2570 if (LegacyWebArchive* coreArchive = [archive _coreLegacyWebArchive])
2571 _private->coreFrame->loader().loadArchive(coreArchive);
2576 if (!_private->coreFrame)
2578 _private->coreFrame->loader().stopForUserCancel();
2583 _private->coreFrame->loader().reload(false);
2586 - (void)reloadFromOrigin
2588 _private->coreFrame->loader().reload(true);
2591 - (WebFrame *)findFrameNamed:(NSString *)name
2593 Frame* coreFrame = _private->coreFrame;
2596 return kit(coreFrame->tree().find(name));
2599 - (WebFrame *)parentFrame
2601 Frame* coreFrame = _private->coreFrame;
2604 return [[kit(coreFrame->tree().parent()) retain] autorelease];
2607 - (NSArray *)childFrames
2609 Frame* coreFrame = _private->coreFrame;
2611 return [NSArray array];
2612 NSMutableArray *children = [NSMutableArray arrayWithCapacity:coreFrame->tree().childCount()];
2613 for (Frame* child = coreFrame->tree().firstChild(); child; child = child->tree().nextSibling())
2614 [children addObject:kit(child)];
2618 - (WebScriptObject *)windowObject
2620 Frame* coreFrame = _private->coreFrame;
2623 return coreFrame->script().windowScriptObject();
2626 - (JSGlobalContextRef)globalContext
2628 Frame* coreFrame = _private->coreFrame;
2631 return toGlobalRef(coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec());
2634 #if JSC_OBJC_API_ENABLED
2635 - (JSContext *)javaScriptContext
2637 Frame* coreFrame = _private->coreFrame;
2640 return coreFrame->script().javaScriptContext();