Reduce copies and allocations in SharedBuffer::append
[WebKit-https.git] / Source / WebKit / mac / WebView / WebFrame.mm
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008, 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
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. 
16  *
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.
27  */
28
29 #import "WebFrameInternal.h"
30
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/CSSAnimationController.h>
60 #import <WebCore/CSSStyleDeclaration.h>
61 #import <WebCore/CachedResourceLoader.h>
62 #import <WebCore/Chrome.h>
63 #import <WebCore/ColorMac.h>
64 #import <WebCore/DatabaseManager.h>
65 #import <WebCore/DocumentFragment.h>
66 #import <WebCore/DocumentLoader.h>
67 #import <WebCore/DocumentMarkerController.h>
68 #import <WebCore/Editing.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/MIMETypeRegistry.h>
84 #import <WebCore/MainFrame.h>
85 #import <WebCore/Page.h>
86 #import <WebCore/PlatformEventFactoryMac.h>
87 #import <WebCore/PluginData.h>
88 #import <WebCore/PrintContext.h>
89 #import <WebCore/RenderView.h>
90 #import <WebCore/RenderWidget.h>
91 #import <WebCore/RenderedDocumentMarker.h>
92 #import <WebCore/RuntimeApplicationChecks.h>
93 #import <WebCore/ScriptController.h>
94 #import <WebCore/SecurityOrigin.h>
95 #import <WebCore/SmartReplace.h>
96 #import <WebCore/StyleProperties.h>
97 #import <WebCore/SubframeLoader.h>
98 #import <WebCore/TextIterator.h>
99 #import <WebCore/ThreadCheck.h>
100 #import <WebCore/VisibleUnits.h>
101 #import <WebCore/markup.h>
102 #import <WebKitSystemInterface.h>
103 #import <bindings/ScriptValue.h>
104 #import <runtime/JSCJSValue.h>
105 #import <runtime/JSLock.h>
106 #import <runtime/JSObject.h>
107 #import <wtf/CurrentTime.h>
108
109 #if PLATFORM(IOS)
110 #import "WebMailDelegate.h"
111 #import "WebResource.h"
112 #import "WebUIKitDelegate.h"
113 #import <WebCore/Document.h>
114 #import <WebCore/EditorClient.h>
115 #import <WebCore/FocusController.h>
116 #import <WebCore/Font.h>
117 #import <WebCore/FrameSelection.h>
118 #import <WebCore/HistoryController.h>
119 #import <WebCore/NodeTraversal.h>
120 #import <WebCore/RenderLayer.h>
121 #import <WebCore/TextResourceDecoder.h>
122 #import <WebCore/WAKScrollView.h>
123 #import <WebCore/WKGraphics.h>
124 #import <WebCore/WebCoreThreadRun.h>
125 #endif
126
127 #if USE(QUICK_LOOK)
128 #import <WebCore/QuickLook.h>
129 #import <WebCore/WebCoreURLResponseIOS.h>
130 #endif
131
132 using namespace WebCore;
133 using namespace HTMLNames;
134
135 using JSC::JSGlobalObject;
136 using JSC::JSLock;
137
138 /*
139 Here is the current behavior matrix for four types of navigations:
140
141 Standard Nav:
142
143  Restore form state:   YES
144  Restore scroll and focus state:  YES
145  Cache policy: NSURLRequestUseProtocolCachePolicy
146  Add to back/forward list: YES
147  
148 Back/Forward:
149
150  Restore form state:   YES
151  Restore scroll and focus state:  YES
152  Cache policy: NSURLRequestReturnCacheDataElseLoad
153  Add to back/forward list: NO
154
155 Reload (meaning only the reload button):
156
157  Restore form state:   NO
158  Restore scroll and focus state:  YES
159  Cache policy: NSURLRequestReloadIgnoringCacheData
160  Add to back/forward list: NO
161
162 Repeat load of the same URL (by any other means of navigation other than the reload button, including hitting return in the location field):
163
164  Restore form state:   NO
165  Restore scroll and focus state:  NO, reset to initial conditions
166  Cache policy: NSURLRequestReloadIgnoringCacheData
167  Add to back/forward list: NO
168 */
169
170 NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey";
171 NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey";
172 NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
173
174 NSString *WebFrameMainDocumentError = @"WebFrameMainDocumentErrorKey";
175 NSString *WebFrameHasPlugins = @"WebFrameHasPluginsKey";
176 NSString *WebFrameHasUnloadListener = @"WebFrameHasUnloadListenerKey";
177 NSString *WebFrameUsesDatabases = @"WebFrameUsesDatabasesKey";
178 NSString *WebFrameUsesGeolocation = @"WebFrameUsesGeolocationKey";
179 NSString *WebFrameUsesApplicationCache = @"WebFrameUsesApplicationCacheKey";
180 NSString *WebFrameCanSuspendActiveDOMObjects = @"WebFrameCanSuspendActiveDOMObjectsKey";
181
182 // FIXME: Remove when this key becomes publicly defined
183 NSString *NSAccessibilityEnhancedUserInterfaceAttribute = @"AXEnhancedUserInterface";
184
185 @implementation WebFramePrivate
186
187 - (void)dealloc
188 {
189     [webFrameView release];
190
191     [super dealloc];
192 }
193
194 - (void)setWebFrameView:(WebFrameView *)v
195
196     [v retain];
197     [webFrameView release];
198     webFrameView = v;
199 }
200
201 @end
202
203 EditableLinkBehavior core(WebKitEditableLinkBehavior editableLinkBehavior)
204 {
205     switch (editableLinkBehavior) {
206         case WebKitEditableLinkDefaultBehavior:
207             return EditableLinkDefaultBehavior;
208         case WebKitEditableLinkAlwaysLive:
209             return EditableLinkAlwaysLive;
210         case WebKitEditableLinkOnlyLiveWithShiftKey:
211             return EditableLinkOnlyLiveWithShiftKey;
212         case WebKitEditableLinkLiveWhenNotFocused:
213             return EditableLinkLiveWhenNotFocused;
214         case WebKitEditableLinkNeverLive:
215             return EditableLinkNeverLive;
216     }
217     ASSERT_NOT_REACHED();
218     return EditableLinkDefaultBehavior;
219 }
220
221 TextDirectionSubmenuInclusionBehavior core(WebTextDirectionSubmenuInclusionBehavior behavior)
222 {
223     switch (behavior) {
224         case WebTextDirectionSubmenuNeverIncluded:
225             return TextDirectionSubmenuNeverIncluded;
226         case WebTextDirectionSubmenuAutomaticallyIncluded:
227             return TextDirectionSubmenuAutomaticallyIncluded;
228         case WebTextDirectionSubmenuAlwaysIncluded:
229             return TextDirectionSubmenuAlwaysIncluded;
230     }
231     ASSERT_NOT_REACHED();
232     return TextDirectionSubmenuNeverIncluded;
233 }
234
235 #if PLATFORM(IOS)
236
237 Vector<Vector<String>> vectorForDictationPhrasesArray(NSArray *dictationPhrases)
238 {
239     Vector<Vector<String>> result;
240
241     for (id dictationPhrase in dictationPhrases) {
242         if (![dictationPhrase isKindOfClass:[NSArray class]])
243             continue;
244         result.append(Vector<String>());
245         for (id interpretation : (NSArray *)dictationPhrase) {
246             if (![interpretation isKindOfClass:[NSString class]])
247                 continue;
248             result.last().append((NSString *)interpretation);
249         }
250     }
251     
252     return result;
253 }
254
255 #endif
256
257 @implementation WebFrame (WebInternal)
258
259 Frame* core(WebFrame *frame)
260 {
261     return frame ? frame->_private->coreFrame : 0;
262 }
263
264 WebFrame *kit(Frame* frame)
265 {
266     if (!frame)
267         return nil;
268
269     FrameLoaderClient& frameLoaderClient = frame->loader().client();
270     if (frameLoaderClient.isEmptyFrameLoaderClient())
271         return nil;
272
273     return static_cast<WebFrameLoaderClient&>(frameLoaderClient).webFrame();
274 }
275
276 Page* core(WebView *webView)
277 {
278     return [webView page];
279 }
280
281 WebView *kit(Page* page)
282 {
283     if (!page)
284         return nil;
285
286     if (page->chrome().client().isEmptyChromeClient())
287         return nil;
288
289     return static_cast<WebChromeClient&>(page->chrome().client()).webView();
290 }
291
292 WebView *getWebView(WebFrame *webFrame)
293 {
294     Frame* coreFrame = core(webFrame);
295     if (!coreFrame)
296         return nil;
297     return kit(coreFrame->page());
298 }
299
300 + (Ref<WebCore::Frame>)_createFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView ownerElement:(HTMLFrameOwnerElement*)ownerElement
301 {
302     WebView *webView = kit(page);
303
304     WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView];
305     auto coreFrame = Frame::create(page, ownerElement, new WebFrameLoaderClient(frame));
306     [frame release];
307     frame->_private->coreFrame = coreFrame.ptr();
308
309     coreFrame.get().tree().setName(name);
310     if (ownerElement) {
311         ASSERT(ownerElement->document().frame());
312         ownerElement->document().frame()->tree().appendChild(coreFrame.get());
313     }
314
315     coreFrame.get().init();
316
317     [webView _setZoomMultiplier:[webView _realZoomMultiplier] isTextOnly:[webView _realZoomMultiplierIsTextOnly]];
318
319     return coreFrame;
320 }
321
322 + (void)_createMainFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView
323 {
324     WebView *webView = kit(page);
325
326     WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView];
327     frame->_private->coreFrame = &page->mainFrame();
328     static_cast<WebFrameLoaderClient&>(page->mainFrame().loader().client()).setWebFrame(frame);
329     [frame release];
330
331     page->mainFrame().tree().setName(name);
332     page->mainFrame().init();
333
334     [webView _setZoomMultiplier:[webView _realZoomMultiplier] isTextOnly:[webView _realZoomMultiplierIsTextOnly]];
335 }
336
337 + (Ref<WebCore::Frame>)_createSubframeWithOwnerElement:(HTMLFrameOwnerElement*)ownerElement frameName:(const String&)name frameView:(WebFrameView *)frameView
338 {
339     return [self _createFrameWithPage:ownerElement->document().frame()->page() frameName:name frameView:frameView ownerElement:ownerElement];
340 }
341
342 - (BOOL)_isIncludedInWebKitStatistics
343 {
344     return _private && _private->includedInWebKitStatistics;
345 }
346
347 #if PLATFORM(IOS)
348 static NSURL *createUniqueWebDataURL();
349
350 + (void)_createMainFrameWithSimpleHTMLDocumentWithPage:(Page*)page frameView:(WebFrameView *)frameView style:(NSString *)style
351 {
352     WebView *webView = kit(page);
353     
354     WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView];
355     frame->_private->coreFrame = &page->mainFrame();
356     static_cast<WebFrameLoaderClient&>(page->mainFrame().loader().client()).setWebFrame(frame);
357     [frame release];
358
359     frame->_private->coreFrame->initWithSimpleHTMLDocument(style, createUniqueWebDataURL());
360 }
361 #endif
362
363 - (void)_attachScriptDebugger
364 {
365     ScriptController& scriptController = _private->coreFrame->script();
366
367     // Calling ScriptController::globalObject() would create a window shell, and dispatch corresponding callbacks, which may be premature
368     // if the script debugger is attached before a document is created.  These calls use the debuggerWorld(), we will need to pass a world
369     // to be able to debug isolated worlds.
370     if (!scriptController.existingWindowShell(debuggerWorld()))
371         return;
372
373     JSGlobalObject* globalObject = scriptController.globalObject(debuggerWorld());
374     if (!globalObject)
375         return;
376
377     if (_private->scriptDebugger) {
378         ASSERT(_private->scriptDebugger.get() == globalObject->debugger());
379         return;
380     }
381
382     _private->scriptDebugger = std::make_unique<WebScriptDebugger>(globalObject);
383 }
384
385 - (void)_detachScriptDebugger
386 {
387     _private->scriptDebugger = nullptr;
388 }
389
390 - (id)_initWithWebFrameView:(WebFrameView *)fv webView:(WebView *)v
391 {
392     self = [super init];
393     if (!self)
394         return nil;
395
396     _private = [[WebFramePrivate alloc] init];
397
398     // Set includedInWebKitStatistics before calling WebFrameView _setWebFrame, since
399     // it calls WebFrame _isIncludedInWebKitStatistics.
400     if ((_private->includedInWebKitStatistics = [[v class] shouldIncludeInWebKitStatistics]))
401         ++WebFrameCount;
402
403     if (fv) {
404         [_private setWebFrameView:fv];
405         [fv _setWebFrame:self];
406     }
407
408     _private->shouldCreateRenderers = YES;
409
410     return self;
411 }
412
413 - (void)_clearCoreFrame
414 {
415     _private->coreFrame = 0;
416 }
417
418 - (void)_updateBackgroundAndUpdatesWhileOffscreen
419 {
420     WebView *webView = getWebView(self);
421     BOOL drawsBackground = [webView drawsBackground];
422 #if !PLATFORM(IOS)
423     NSColor *backgroundColor = [webView backgroundColor];
424 #else
425     CGColorRef backgroundColor = [webView backgroundColor];
426 #endif
427
428     Frame* coreFrame = _private->coreFrame;
429     for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
430         // Don't call setDrawsBackground:YES here because it may be NO because of a load
431         // in progress; WebFrameLoaderClient keeps it set to NO during the load process.
432         WebFrame *webFrame = kit(frame);
433         if (!drawsBackground)
434             [[[webFrame frameView] _scrollView] setDrawsBackground:NO];
435 #if !PLATFORM(IOS)
436         [[[webFrame frameView] _scrollView] setBackgroundColor:backgroundColor];
437 #endif
438
439         if (FrameView* view = frame->view()) {
440             view->setTransparent(!drawsBackground);
441 #if !PLATFORM(IOS)
442             Color color = colorFromNSColor([backgroundColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]);
443 #else
444             Color color = Color(backgroundColor);
445 #endif
446             view->setBaseBackgroundColor(color);
447             view->setShouldUpdateWhileOffscreen([webView shouldUpdateWhileOffscreen]);
448         }
449     }
450 }
451
452 - (void)_setInternalLoadDelegate:(id)internalLoadDelegate
453 {
454     _private->internalLoadDelegate = internalLoadDelegate;
455 }
456
457 - (id)_internalLoadDelegate
458 {
459     return _private->internalLoadDelegate;
460 }
461
462 - (void)_unmarkAllBadGrammar
463 {
464     Frame* coreFrame = _private->coreFrame;
465     for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
466         if (Document* document = frame->document())
467             document->markers().removeMarkers(DocumentMarker::Grammar);
468     }
469 }
470
471 - (void)_unmarkAllMisspellings
472 {
473 #if !PLATFORM(IOS)
474     Frame* coreFrame = _private->coreFrame;
475     for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
476         if (Document* document = frame->document())
477             document->markers().removeMarkers(DocumentMarker::Spelling);
478     }
479 #endif
480 }
481
482 - (BOOL)_hasSelection
483 {
484     id documentView = [_private->webFrameView documentView];    
485
486     // optimization for common case to avoid creating potentially large selection string
487     if ([documentView isKindOfClass:[WebHTMLView class]])
488         if (Frame* coreFrame = _private->coreFrame)
489             return coreFrame->selection().isRange();
490
491     if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
492         return [[documentView selectedString] length] > 0;
493     
494     return NO;
495 }
496
497 - (void)_clearSelection
498 {
499     id documentView = [_private->webFrameView documentView];    
500     if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
501         [documentView deselectAll];
502 }
503
504 #if !ASSERT_DISABLED
505 - (BOOL)_atMostOneFrameHasSelection
506 {
507     // FIXME: 4186050 is one known case that makes this debug check fail.
508     BOOL found = NO;
509     Frame* coreFrame = _private->coreFrame;
510     for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame))
511         if ([kit(frame) _hasSelection]) {
512             if (found)
513                 return NO;
514             found = YES;
515         }
516     return YES;
517 }
518 #endif
519
520 - (WebFrame *)_findFrameWithSelection
521 {
522     Frame* coreFrame = _private->coreFrame;
523     for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
524         WebFrame *webFrame = kit(frame);
525         if ([webFrame _hasSelection])
526             return webFrame;
527     }
528     return nil;
529 }
530
531 - (void)_clearSelectionInOtherFrames
532 {
533     // We rely on WebDocumentSelection protocol implementors to call this method when they become first 
534     // responder. It would be nicer to just notice first responder changes here instead, but there's no 
535     // notification sent when the first responder changes in general (Radar 2573089).
536     WebFrame *frameWithSelection = [[getWebView(self) mainFrame] _findFrameWithSelection];
537     if (frameWithSelection != self)
538         [frameWithSelection _clearSelection];
539
540     // While we're in the general area of selection and frames, check that there is only one now.
541     ASSERT([[getWebView(self) mainFrame] _atMostOneFrameHasSelection]);
542 }
543
544 static inline WebDataSource *dataSource(DocumentLoader* loader)
545 {
546     return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
547 }
548
549 - (WebDataSource *)_dataSource
550 {
551     return dataSource(_private->coreFrame->loader().documentLoader());
552 }
553
554 #if PLATFORM(IOS)
555 - (BOOL)_isCommitting
556 {
557     return _private->isCommitting;
558 }
559
560 - (void)_setIsCommitting:(BOOL)value
561 {
562     _private->isCommitting = value;
563 }
564 #endif
565
566 - (NSArray *)_nodesFromList:(Vector<Node*> *)nodesVector
567 {
568     size_t size = nodesVector->size();
569     NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:size];
570     for (size_t i = 0; i < size; ++i)
571         [nodes addObject:kit((*nodesVector)[i])];
572     return nodes;
573 }
574
575 - (NSString *)_selectedString
576 {
577     return _private->coreFrame->displayStringModifiedByEncoding(_private->coreFrame->editor().selectedText());
578 }
579
580 - (NSString *)_stringForRange:(DOMRange *)range
581 {
582     return plainText(core(range), TextIteratorDefaultBehavior, true);
583 }
584
585 - (BOOL)_shouldFlattenCompositingLayers:(CGContextRef)context
586 {
587 #if !PLATFORM(IOS)
588     // -currentContextDrawingToScreen returns YES for bitmap contexts.
589     BOOL isPrinting = ![NSGraphicsContext currentContextDrawingToScreen];
590     if (isPrinting)
591         return YES;
592 #endif
593
594     if (!WKCGContextIsBitmapContext(context))
595         return NO;
596
597     // If we're drawing into a bitmap, we might be snapshotting, or drawing into a layer-backed view.
598     id documentView = [_private->webFrameView documentView];
599     if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _web_isDrawingIntoLayer])
600         return NO;
601
602     return [getWebView(self) _includesFlattenedCompositingLayersWhenDrawingToBitmap];
603 }
604
605 - (void)_drawRect:(NSRect)rect contentsOnly:(BOOL)contentsOnly
606 {
607 #if !PLATFORM(IOS)
608     ASSERT([[NSGraphicsContext currentContext] isFlipped]);
609
610     CGContextRef ctx = static_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]);
611 #else
612     CGContextRef ctx = WKGetCurrentGraphicsContext();
613 #endif
614     GraphicsContext context(ctx);
615
616 #if PLATFORM(IOS)
617     // FIXME: when <rdar://problem/9034977> is fixed there will be no need to do this here.
618     WebCore::Frame *frame = core(self);
619     if (WebCore::Page* page = frame->page())
620         context.setIsAcceleratedContext(page->settings().acceleratedDrawingEnabled());
621 #endif
622
623     FrameView* view = _private->coreFrame->view();
624     
625     bool shouldFlatten = false;
626     if (Frame* parentFrame = _private->coreFrame->tree().parent()) {
627         // For subframes, we need to inherit the paint behavior from our parent
628         FrameView* parentView = parentFrame ? parentFrame->view() : 0;
629         if (parentView)
630             shouldFlatten = parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
631     } else
632         shouldFlatten = [self _shouldFlattenCompositingLayers:ctx];
633
634     PaintBehavior oldBehavior = PaintBehaviorNormal;
635     if (shouldFlatten) {
636         oldBehavior = view->paintBehavior();
637         view->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
638     }
639     
640     if (contentsOnly)
641         view->paintContents(context, enclosingIntRect(rect));
642     else
643         view->paint(context, enclosingIntRect(rect));
644
645     if (shouldFlatten)
646         view->setPaintBehavior(oldBehavior);
647 }
648
649 - (BOOL)_getVisibleRect:(NSRect*)rect
650 {
651     ASSERT_ARG(rect, rect);
652     if (RenderWidget* ownerRenderer = _private->coreFrame->ownerRenderer()) {
653         if (ownerRenderer->needsLayout())
654             return NO;
655         *rect = ownerRenderer->pixelSnappedAbsoluteClippedOverflowRect();
656         return YES;
657     }
658
659     return NO;
660 }
661
662 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string
663 {
664     return [self _stringByEvaluatingJavaScriptFromString:string forceUserGesture:true];
665 }
666
667 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture
668 {
669     if (!string)
670         return @"";
671
672     RELEASE_ASSERT(isMainThread());
673
674     ASSERT(_private->coreFrame->document());
675     RetainPtr<WebFrame> protect(self); // Executing arbitrary JavaScript can destroy the frame.
676     
677 #if PLATFORM(IOS)
678     ASSERT(WebThreadIsLockedOrDisabled());
679     JSC::ExecState* exec = _private->coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec();
680     JSC::JSLockHolder jscLock(exec);
681 #endif
682
683     JSC::JSValue result = _private->coreFrame->script().executeScript(string, forceUserGesture);
684
685     if (!_private->coreFrame) // In case the script removed our frame from the page.
686         return @"";
687
688     // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
689     // If you don't like it, use -[WebScriptObject evaluateWebScript:] or 
690     // JSEvaluateScript instead, since they have less surprising semantics.
691     if (!result || (!result.isBoolean() && !result.isString() && !result.isNumber()))
692         return @"";
693
694 #if !PLATFORM(IOS)
695     JSC::ExecState* exec = _private->coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec();
696     JSC::JSLockHolder lock(exec);
697 #endif
698     return result.toWTFString(exec);
699 }
700
701 - (NSRect)_caretRectAtPosition:(const Position&)pos affinity:(NSSelectionAffinity)affinity
702 {
703     VisiblePosition visiblePosition(pos, static_cast<EAffinity>(affinity));
704     return visiblePosition.absoluteCaretBounds();
705 }
706
707 - (NSRect)_firstRectForDOMRange:(DOMRange *)range
708 {
709    return _private->coreFrame->editor().firstRectForRange(core(range));
710 }
711
712 - (void)_scrollDOMRangeToVisible:(DOMRange *)range
713 {
714     bool insideFixed = false; // FIXME: get via firstRectForRange().
715     NSRect rangeRect = [self _firstRectForDOMRange:range];    
716     Node *startNode = core([range startContainer]);
717         
718     if (startNode && startNode->renderer()) {
719 #if !PLATFORM(IOS)
720         startNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, enclosingIntRect(rangeRect), insideFixed, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
721 #else
722         RenderLayer* layer = startNode->renderer()->enclosingLayer();
723         if (layer) {
724             layer->setAdjustForIOSCaretWhenScrolling(true);
725             startNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, enclosingIntRect(rangeRect), insideFixed, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
726             layer->setAdjustForIOSCaretWhenScrolling(false);
727             _private->coreFrame->selection().setCaretRectNeedsUpdate();
728             _private->coreFrame->selection().updateAppearance();
729         }
730 #endif
731     }
732 }
733
734 #if PLATFORM(IOS)
735 - (void)_scrollDOMRangeToVisible:(DOMRange *)range withInset:(CGFloat)inset
736 {
737     bool insideFixed = false; // FIXME: get via firstRectForRange().
738     NSRect rangeRect = NSInsetRect([self _firstRectForDOMRange:range], inset, inset);
739     Node *startNode = core([range startContainer]);
740
741     if (startNode && startNode->renderer()) {
742         RenderLayer* layer = startNode->renderer()->enclosingLayer();
743         if (layer) {
744             layer->setAdjustForIOSCaretWhenScrolling(true);
745             startNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, enclosingIntRect(rangeRect), insideFixed, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
746             layer->setAdjustForIOSCaretWhenScrolling(false);
747
748             Frame *coreFrame = core(self);
749             if (coreFrame) {
750                 FrameSelection& frameSelection = coreFrame->selection();
751                 frameSelection.setCaretRectNeedsUpdate();
752                 frameSelection.updateAppearance();
753             }
754         }
755     }
756 }
757 #endif
758
759 - (BOOL)_needsLayout
760 {
761     return _private->coreFrame->view() ? _private->coreFrame->view()->needsLayout() : false;
762 }
763
764 #if !PLATFORM(IOS)
765 - (DOMRange *)_rangeByAlteringCurrentSelection:(FrameSelection::EAlteration)alteration direction:(SelectionDirection)direction granularity:(TextGranularity)granularity
766 {
767     if (_private->coreFrame->selection().isNone())
768         return nil;
769
770     FrameSelection selection;
771     selection.setSelection(_private->coreFrame->selection().selection());
772     selection.modify(alteration, direction, granularity);
773     return kit(selection.toNormalizedRange().get());
774 }
775 #endif
776
777 - (TextGranularity)_selectionGranularity
778 {
779     return _private->coreFrame->selection().granularity();
780 }
781
782 - (NSRange)_convertToNSRange:(Range *)range
783 {
784     if (!range)
785         return NSMakeRange(NSNotFound, 0);
786
787     size_t location;
788     size_t length;
789     if (!TextIterator::getLocationAndLengthFromRange(_private->coreFrame->selection().rootEditableElementOrDocumentElement(), range, location, length))
790         return NSMakeRange(NSNotFound, 0);
791
792     return NSMakeRange(location, length);
793 }
794
795 - (PassRefPtr<Range>)_convertToDOMRange:(NSRange)nsrange
796 {
797     return [self _convertToDOMRange:nsrange rangeIsRelativeTo:WebRangeIsRelativeTo::EditableRoot];
798 }
799
800 - (PassRefPtr<Range>)_convertToDOMRange:(NSRange)nsrange rangeIsRelativeTo:(WebRangeIsRelativeTo)rangeIsRelativeTo
801 {
802     if (nsrange.location > INT_MAX)
803         return 0;
804     if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX)
805         nsrange.length = INT_MAX - nsrange.location;
806
807     if (rangeIsRelativeTo == WebRangeIsRelativeTo::EditableRoot) {
808         // Our critical assumption is that this code path is only called by input methods that
809         // concentrate on a given area containing the selection
810         // We have to do this because of text fields and textareas. The DOM for those is not
811         // directly in the document DOM, so serialization is problematic. Our solution is
812         // to use the root editable element of the selection start as the positional base.
813         // That fits with AppKit's idea of an input context.
814         Element* element = _private->coreFrame->selection().rootEditableElementOrDocumentElement();
815         if (!element)
816             return nil;
817         return TextIterator::rangeFromLocationAndLength(element, nsrange.location, nsrange.length);
818     }
819
820     ASSERT(rangeIsRelativeTo == WebRangeIsRelativeTo::Paragraph);
821
822     const VisibleSelection& selection = _private->coreFrame->selection().selection();
823     RefPtr<Range> selectedRange = selection.toNormalizedRange();
824     if (!selectedRange)
825         return 0;
826
827     RefPtr<Range> paragraphRange = makeRange(startOfParagraph(selection.visibleStart()), selection.visibleEnd());
828     if (!paragraphRange)
829         return 0;
830
831     ContainerNode& rootNode = paragraphRange.get()->startContainer().treeScope().rootNode();
832     int paragraphStartIndex = TextIterator::rangeLength(Range::create(rootNode.document(), &rootNode, 0, &paragraphRange->startContainer(), paragraphRange->startOffset()).ptr());
833     return TextIterator::rangeFromLocationAndLength(&rootNode, paragraphStartIndex + static_cast<int>(nsrange.location), nsrange.length);
834 }
835
836 - (DOMRange *)_convertNSRangeToDOMRange:(NSRange)nsrange
837 {
838     return kit([self _convertToDOMRange:nsrange].get());
839 }
840
841 - (NSRange)_convertDOMRangeToNSRange:(DOMRange *)range
842 {
843     return [self _convertToNSRange:core(range)];
844 }
845
846 - (DOMRange *)_markDOMRange
847 {
848     return kit(_private->coreFrame->editor().mark().toNormalizedRange().get());
849 }
850
851 - (DOMDocumentFragment *)_documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString
852 {
853     Frame* frame = _private->coreFrame;
854     if (!frame)
855         return nil;
856
857     Document* document = frame->document();
858     if (!document)
859         return nil;
860
861     return kit(createFragmentFromMarkup(*document, markupString, baseURLString, DisallowScriptingContent).ptr());
862 }
863
864 - (DOMDocumentFragment *)_documentFragmentWithNodesAsParagraphs:(NSArray *)nodes
865 {
866     Frame* frame = _private->coreFrame;
867     if (!frame)
868         return nil;
869
870     Document* document = frame->document();
871     if (!document)
872         return nil;
873
874     NSEnumerator *nodeEnum = [nodes objectEnumerator];
875     Vector<Node*> nodesVector;
876     DOMNode *node;
877     while ((node = [nodeEnum nextObject]))
878         nodesVector.append(core(node));
879
880     auto fragment = document->createDocumentFragment();
881
882     for (auto* node : nodesVector) {
883         auto element = createDefaultParagraphElement(*document);
884         element->appendChild(*node);
885         fragment->appendChild(element);
886     }
887
888     return kit(fragment.ptr());
889 }
890
891 - (void)_replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
892 {
893     DOMDocumentFragment *fragment = kit(_private->coreFrame->document()->createDocumentFragment().ptr());
894     [fragment appendChild:node];
895     [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle];
896 }
897
898 - (void)_insertParagraphSeparatorInQuotedContent
899 {
900     if (_private->coreFrame->selection().isNone())
901         return;
902
903     _private->coreFrame->editor().insertParagraphSeparatorInQuotedContent();
904 }
905
906 - (VisiblePosition)_visiblePositionForPoint:(NSPoint)point
907 {
908     // FIXME: Someone with access to Apple's sources could remove this needless wrapper call.
909     return _private->coreFrame->visiblePositionForPoint(IntPoint(point));
910 }
911
912 - (DOMRange *)_characterRangeAtPoint:(NSPoint)point
913 {
914     return kit(_private->coreFrame->rangeForPoint(IntPoint(point)).get());
915 }
916
917 - (DOMCSSStyleDeclaration *)_typingStyle
918 {
919     if (!_private->coreFrame)
920         return nil;
921     RefPtr<MutableStyleProperties> typingStyle = _private->coreFrame->selection().copyTypingStyle();
922     if (!typingStyle)
923         return nil;
924     return kit(typingStyle->ensureCSSStyleDeclaration());
925 }
926
927 - (void)_setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(EditAction)undoAction
928 {
929     if (!_private->coreFrame || !style)
930         return;
931     // FIXME: We shouldn't have to create a copy here.
932     Ref<MutableStyleProperties> properties(core(style)->copyProperties());
933     _private->coreFrame->editor().computeAndSetTypingStyle(properties.get(), undoAction);
934 }
935
936 #if ENABLE(DRAG_SUPPORT) && PLATFORM(MAC)
937 - (void)_dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation
938 {
939     if (!_private->coreFrame)
940         return;
941     FrameView* view = _private->coreFrame->view();
942     if (!view)
943         return;
944     // FIXME: These are fake modifier keys here, but they should be real ones instead.
945     PlatformMouseEvent event(IntPoint(windowLoc), IntPoint(globalPoint(windowLoc, [view->platformWidget() window])),
946                              LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, currentTime(), WebCore::ForceAtClick, WebCore::NoTap);
947     _private->coreFrame->eventHandler().dragSourceEndedAt(event, (DragOperation)operation);
948 }
949 #endif // ENABLE(DRAG_SUPPORT) && PLATFORM(MAC)
950
951 - (BOOL)_canProvideDocumentSource
952 {
953     Frame* frame = _private->coreFrame;
954     String mimeType = frame->document()->loader()->writer().mimeType();
955     PluginData* pluginData = frame->page() ? &frame->page()->pluginData() : 0;
956
957     if (WebCore::MIMETypeRegistry::isTextMIMEType(mimeType)
958         || Image::supportsType(mimeType)
959         || (pluginData && pluginData->supportsWebVisibleMimeType(mimeType, PluginData::AllPlugins) && frame->loader().subframeLoader().allowPlugins())
960         || (pluginData && pluginData->supportsWebVisibleMimeType(mimeType, PluginData::OnlyApplicationPlugins)))
961         return NO;
962
963     return YES;
964 }
965
966 - (BOOL)_canSaveAsWebArchive
967 {
968     // Currently, all documents that we can view source for
969     // (HTML and XML documents) can also be saved as web archives
970     return [self _canProvideDocumentSource];
971 }
972
973 - (void)_commitData:(NSData *)data
974 {
975     // FIXME: This really should be a setting.
976     Document* document = _private->coreFrame->document();
977     document->setShouldCreateRenderers(_private->shouldCreateRenderers);
978
979     _private->coreFrame->loader().documentLoader()->commitData((const char *)[data bytes], [data length]);
980 }
981
982 @end
983
984 @implementation WebFrame (WebPrivate)
985
986 // FIXME: This exists only as a convenience for Safari, consider moving there.
987 - (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor
988 {
989     Frame* coreFrame = _private->coreFrame;
990     return coreFrame && coreFrame->tree().isDescendantOf(core(ancestor));
991 }
992
993 - (void)_setShouldCreateRenderers:(BOOL)shouldCreateRenderers
994 {
995     _private->shouldCreateRenderers = shouldCreateRenderers;
996 }
997
998 #if !PLATFORM(IOS)
999 - (NSColor *)_bodyBackgroundColor
1000 #else
1001 - (CGColorRef)_bodyBackgroundColor
1002 #endif
1003 {
1004     Document* document = _private->coreFrame->document();
1005     if (!document)
1006         return nil;
1007     auto* body = document->bodyOrFrameset();
1008     if (!body)
1009         return nil;
1010     RenderObject* bodyRenderer = body->renderer();
1011     if (!bodyRenderer)
1012         return nil;
1013     Color color = bodyRenderer->style().visitedDependentColor(CSSPropertyBackgroundColor);
1014     if (!color.isValid())
1015         return nil;
1016 #if !PLATFORM(IOS)
1017     return nsColor(color);
1018 #else
1019     return cachedCGColor(color);
1020 #endif
1021 }
1022
1023 - (BOOL)_isFrameSet
1024 {
1025     Document* document = _private->coreFrame->document();
1026     return document && document->isFrameSet();
1027 }
1028
1029 - (BOOL)_firstLayoutDone
1030 {
1031     return _private->coreFrame->loader().stateMachine().firstLayoutDone();
1032 }
1033
1034 - (BOOL)_isVisuallyNonEmpty
1035 {
1036     if (FrameView* view = _private->coreFrame->view())
1037         return view->isVisuallyNonEmpty();
1038     return NO;
1039 }
1040
1041 static WebFrameLoadType toWebFrameLoadType(FrameLoadType frameLoadType)
1042 {
1043     switch (frameLoadType) {
1044     case FrameLoadType::Standard:
1045         return WebFrameLoadTypeStandard;
1046     case FrameLoadType::Back:
1047         return WebFrameLoadTypeBack;
1048     case FrameLoadType::Forward:
1049         return WebFrameLoadTypeForward;
1050     case FrameLoadType::IndexedBackForward:
1051         return WebFrameLoadTypeIndexedBackForward;
1052     case FrameLoadType::Reload:
1053         return WebFrameLoadTypeReload;
1054     case FrameLoadType::Same:
1055         return WebFrameLoadTypeSame;
1056     case FrameLoadType::RedirectWithLockedBackForwardList:
1057         return WebFrameLoadTypeInternal;
1058     case FrameLoadType::Replace:
1059         return WebFrameLoadTypeReplace;
1060     case FrameLoadType::ReloadFromOrigin:
1061         return WebFrameLoadTypeReloadFromOrigin;
1062     case FrameLoadType::ReloadExpiredOnly:
1063         ASSERT_NOT_REACHED();
1064         return WebFrameLoadTypeReload;
1065     }
1066 }
1067
1068 - (WebFrameLoadType)_loadType
1069 {
1070     return toWebFrameLoadType(_private->coreFrame->loader().loadType());
1071 }
1072
1073 #if PLATFORM(IOS)
1074 - (BOOL)needsLayout
1075 {
1076     // Needed for Mail <rdar://problem/6228038>
1077     return _private->coreFrame ? [self _needsLayout] : NO;
1078 }
1079
1080 - (void)_setLoadsSynchronously:(BOOL)flag
1081 {
1082     _private->coreFrame->loader().setLoadsSynchronously(flag);
1083 }
1084
1085 - (BOOL)_loadsSynchronously
1086 {
1087     return _private->coreFrame->loader().loadsSynchronously();
1088 }
1089
1090 // FIXME: selection
1091
1092 - (NSArray *)_rectsForRange:(DOMRange *)domRange
1093 {
1094     Range *range = core(domRange);
1095     
1096     
1097     Vector<IntRect> intRects;
1098     range->absoluteTextRects(intRects, NO);
1099     unsigned size = intRects.size();
1100     
1101     NSMutableArray *rectArray = [NSMutableArray arrayWithCapacity:size];
1102     for (unsigned i = 0; i < size; i++) {
1103         [rectArray addObject:[NSValue valueWithRect:(CGRect )intRects[i]]];
1104     }
1105     
1106     return rectArray;
1107 }
1108
1109 - (DOMRange *)_selectionRangeForFirstPoint:(CGPoint)first secondPoint:(CGPoint)second
1110 {
1111     VisiblePosition firstPos = [self _visiblePositionForPoint:first];
1112     VisiblePosition secondPos = [self _visiblePositionForPoint:second];
1113     VisibleSelection selection(firstPos, secondPos);
1114     DOMRange *range = kit(selection.toNormalizedRange().get());
1115     return range;    
1116 }
1117
1118 - (DOMRange *)_selectionRangeForPoint:(CGPoint)point
1119 {
1120     VisiblePosition pos = [self _visiblePositionForPoint:point];    
1121     VisibleSelection selection(pos);
1122     DOMRange *range = kit(selection.toNormalizedRange().get());
1123     return range;
1124 }
1125
1126 #endif // PLATFORM(IOS)
1127
1128 - (NSRange)_selectedNSRange
1129 {
1130     return [self _convertToNSRange:_private->coreFrame->selection().toNormalizedRange().get()];
1131 }
1132
1133 - (void)_selectNSRange:(NSRange)range
1134 {
1135     RefPtr<Range> domRange = [self _convertToDOMRange:range];
1136     if (domRange)
1137         _private->coreFrame->selection().setSelection(VisibleSelection(*domRange, SEL_DEFAULT_AFFINITY));
1138 }
1139
1140 - (BOOL)_isDisplayingStandaloneImage
1141 {
1142     Document* document = _private->coreFrame->document();
1143     return document && document->isImageDocument();
1144 }
1145
1146 - (unsigned)_pendingFrameUnloadEventCount
1147 {
1148     return _private->coreFrame->document()->domWindow()->pendingUnloadEventListeners();
1149 }
1150
1151 #if ENABLE(NETSCAPE_PLUGIN_API)
1152 - (void)_recursive_resumeNullEventsForAllNetscapePlugins
1153 {
1154     Frame* coreFrame = core(self);
1155     for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
1156         NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
1157         if ([documentView isKindOfClass:[WebHTMLView class]])
1158             [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins];
1159     }
1160 }
1161
1162 - (void)_recursive_pauseNullEventsForAllNetscapePlugins
1163 {
1164     Frame* coreFrame = core(self);
1165     for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
1166         NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
1167         if ([documentView isKindOfClass:[WebHTMLView class]])
1168             [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins];
1169     }
1170 }
1171 #endif
1172
1173 #if PLATFORM(IOS)
1174
1175 - (unsigned)formElementsCharacterCount
1176 {
1177     return core(self)->formElementsCharacterCount();
1178 }
1179
1180 - (void)setTimeoutsPaused:(BOOL)flag
1181 {
1182     id documentView = [_private->webFrameView documentView];    
1183     if ([documentView isKindOfClass:[WebHTMLView class]]) {
1184         if (Frame* coreFrame = _private->coreFrame)
1185             coreFrame->setTimersPaused(flag);
1186     }
1187 }
1188
1189 - (void)setPluginsPaused:(BOOL)flag
1190 {
1191     WebView *webView = getWebView(self);
1192     if (!webView)
1193         return;
1194
1195     if (flag)
1196         [webView _stopAllPlugIns];
1197     else
1198         [webView _startAllPlugIns];
1199 }
1200
1201 - (void)prepareForPause
1202 {
1203     id documentView = [_private->webFrameView documentView];    
1204     if ([documentView isKindOfClass:[WebHTMLView class]]) {
1205         if (Frame* coreFrame = _private->coreFrame)
1206             coreFrame->dispatchPageHideEventBeforePause();
1207     }
1208 }
1209
1210 - (void)resumeFromPause
1211 {
1212     id documentView = [_private->webFrameView documentView];    
1213     if ([documentView isKindOfClass:[WebHTMLView class]]) {
1214         if (Frame* coreFrame = _private->coreFrame)
1215             coreFrame->dispatchPageShowEventBeforeResume();
1216     }
1217 }
1218
1219 - (void)selectNSRange:(NSRange)range
1220 {
1221     [self _selectNSRange:range];
1222 }
1223
1224 - (void)selectWithoutClosingTypingNSRange:(NSRange)range
1225 {
1226     RefPtr<Range> domRange = [self _convertToDOMRange:range];
1227     if (domRange) {
1228         const VisibleSelection& newSelection = VisibleSelection(*domRange, SEL_DEFAULT_AFFINITY);
1229         _private->coreFrame->selection().setSelection(newSelection, 0);
1230         
1231         _private->coreFrame->editor().ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping();
1232     }
1233 }
1234
1235 - (NSRange)selectedNSRange
1236 {
1237     return [self _selectedNSRange];
1238 }
1239
1240 - (void)forceLayoutAdjustingViewSize:(BOOL)adjust
1241 {
1242     _private->coreFrame->view()->forceLayout(!adjust);
1243     if (adjust)
1244         _private->coreFrame->view()->adjustViewSize();
1245 }
1246
1247 - (void)_handleKeyEvent:(WebEvent *)event
1248 {
1249     core(self)->eventHandler().keyEvent(event);
1250 }
1251
1252 - (void)_selectAll
1253 {
1254     core(self)->selection().selectAll();
1255 }
1256
1257 - (void)_setSelectionFromNone
1258 {
1259     core(self)->selection().setSelectionFromNone();
1260 }
1261
1262 - (void)_restoreViewState
1263 {
1264     ASSERT(!WebThreadIsEnabled() || WebThreadIsLocked());
1265     _private->coreFrame->loader().client().restoreViewState();
1266 }
1267
1268 - (void)_saveViewState
1269 {
1270     ASSERT(!WebThreadIsEnabled() || WebThreadIsLocked());
1271     FrameLoader& frameLoader = _private->coreFrame->loader();
1272     auto* item = frameLoader.history().currentItem();
1273     if (item)
1274         frameLoader.client().saveViewStateToItem(*item);
1275 }
1276
1277 - (void)deviceOrientationChanged
1278 {
1279     WebThreadRun(^{
1280         if (WebCore::Frame* frame = core(self))
1281             frame->orientationChanged();
1282     });
1283 }
1284
1285 - (void)setNeedsLayout
1286 {
1287     WebCore::Frame *frame = core(self);
1288     if (frame->view())
1289         frame->view()->setNeedsLayout();
1290 }
1291
1292 - (CGSize)renderedSizeOfNode:(DOMNode *)node constrainedToWidth:(float)width
1293 {
1294     Node* n = core(node);
1295     RenderObject* renderer = n ? n->renderer() : nullptr;
1296     float w = std::min((float)renderer->maxPreferredLogicalWidth(), width);
1297     return is<RenderBox>(renderer) ? CGSizeMake(w, downcast<RenderBox>(*renderer).height()) : CGSizeMake(0, 0);
1298 }
1299
1300 - (DOMNode *)deepestNodeAtViewportLocation:(CGPoint)aViewportLocation
1301 {
1302     WebCore::Frame *frame = core(self);
1303     return kit(frame->deepestNodeAtLocation(FloatPoint(aViewportLocation)));
1304 }
1305
1306 - (DOMNode *)scrollableNodeAtViewportLocation:(CGPoint)aViewportLocation
1307 {
1308     WebCore::Frame *frame = core(self);
1309     WebCore::Node *node = frame->nodeRespondingToScrollWheelEvents(FloatPoint(aViewportLocation));
1310     return kit(node);
1311 }
1312
1313 - (DOMNode *)approximateNodeAtViewportLocation:(CGPoint *)aViewportLocation
1314 {
1315     WebCore::Frame *frame = core(self);
1316     FloatPoint viewportLocation(*aViewportLocation);
1317     FloatPoint adjustedLocation;
1318     WebCore::Node *node = frame->nodeRespondingToClickEvents(viewportLocation, adjustedLocation);
1319     *aViewportLocation = adjustedLocation;
1320     return kit(node);
1321 }
1322
1323 - (CGRect)renderRectForPoint:(CGPoint)point isReplaced:(BOOL *)isReplaced fontSize:(float *)fontSize
1324 {
1325     WebCore::Frame *frame = core(self);
1326     bool replaced = false;
1327     CGRect rect = frame->renderRectForPoint(point, &replaced, fontSize);
1328     *isReplaced = replaced;
1329     return rect;
1330 }
1331
1332 - (void)_setProhibitsScrolling:(BOOL)flag
1333 {
1334     WebCore::Frame *frame = core(self);
1335     frame->view()->setProhibitsScrolling(flag);
1336 }
1337
1338 - (void)revealSelectionAtExtent:(BOOL)revealExtent
1339 {
1340     WebCore::Frame *frame = core(self);
1341     RevealExtentOption revealExtentOption = revealExtent ? RevealExtent : DoNotRevealExtent;
1342     frame->selection().revealSelection(SelectionRevealMode::Reveal, ScrollAlignment::alignToEdgeIfNeeded, revealExtentOption);
1343 }
1344
1345 - (void)resetSelection
1346 {
1347     WebCore::Frame *frame = core(self);
1348     frame->selection().setSelection(frame->selection().selection());
1349 }
1350
1351 - (BOOL)hasEditableSelection
1352 {
1353     return core(self)->selection().selection().isContentEditable();
1354 }
1355
1356 - (int)preferredHeight
1357 {
1358     return core(self)->preferredHeight();
1359 }
1360
1361 - (int)innerLineHeight:(DOMNode *)node
1362 {
1363     if (!node)
1364         return 0;
1365
1366     auto& coreNode = *core(node);
1367
1368     coreNode.document().updateLayout();
1369
1370     auto* renderer = coreNode.renderer();
1371     if (!renderer)
1372         return 0;
1373
1374     return renderer->innerLineHeight();
1375 }
1376
1377 - (void)updateLayout
1378 {
1379     WebCore::Frame *frame = core(self);
1380     frame->updateLayout();
1381 }
1382
1383 - (void)setIsActive:(BOOL)flag
1384 {
1385     WebCore::Frame *frame = core(self);
1386     frame->page()->focusController().setActive(flag);
1387 }
1388
1389 - (void)setSelectionChangeCallbacksDisabled:(BOOL)flag
1390 {
1391     WebCore::Frame *frame = core(self);
1392     frame->setSelectionChangeCallbacksDisabled(flag);
1393 }
1394
1395 - (NSRect)caretRect
1396 {
1397     return core(self)->caretRect();
1398 }
1399
1400 - (NSRect)rectForScrollToVisible
1401 {
1402     return core(self)->rectForScrollToVisible();
1403 }
1404
1405 - (void)setCaretColor:(CGColorRef)color
1406 {
1407     Color qColor = color ? Color(color) : Color::black;
1408     WebCore::Frame *frame = core(self);
1409     frame->selection().setCaretColor(qColor);
1410 }
1411
1412 - (NSView *)documentView
1413 {
1414     WebCore::Frame *frame = core(self);
1415     return [[kit(frame) frameView] documentView];
1416 }
1417
1418 - (int)layoutCount
1419 {
1420     WebCore::Frame *frame = core(self);
1421     if (!frame || !frame->view())
1422         return 0;
1423     return frame->view()->layoutCount();
1424 }
1425
1426 - (BOOL)isTelephoneNumberParsingAllowed
1427 {
1428     Document *document = core(self)->document();
1429     return document->isTelephoneNumberParsingAllowed();
1430 }
1431
1432 - (BOOL)isTelephoneNumberParsingEnabled
1433 {
1434     Document *document = core(self)->document();
1435     return document->isTelephoneNumberParsingEnabled();
1436 }
1437
1438 - (DOMRange *)selectedDOMRange
1439 {
1440     WebCore::Frame *frame = core(self);
1441     RefPtr<WebCore::Range> range = frame->selection().toNormalizedRange();
1442     return kit(range.get());
1443 }
1444
1445 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)affinity closeTyping:(BOOL)closeTyping
1446 {
1447     WebCore::Frame *frame = core(self);
1448
1449     // Ensure the view becomes first responder.
1450     // This does not happen automatically on iOS because we don't forward
1451     // all the click events to WebKit.
1452     if (FrameView* frameView = frame->view()) {
1453         if (NSView *documentView = frameView->documentView()) {
1454             Page* page = frame->page();
1455             if (!page)
1456                 return;
1457             page->chrome().focusNSView(documentView);
1458         }
1459     }
1460
1461     frame->selection().setSelectedRange(core(range), (EAffinity)affinity, closeTyping);
1462     if (!closeTyping)
1463         frame->editor().ensureLastEditCommandHasCurrentSelectionIfOpenForMoreTyping();
1464 }
1465
1466 - (NSSelectionAffinity)selectionAffinity
1467 {
1468     WebCore::Frame *frame = core(self);
1469     return (NSSelectionAffinity)(frame->selection().selection().affinity());
1470 }
1471
1472 - (void)expandSelectionToElementContainingCaretSelection
1473 {
1474     WebCore::Frame *frame = core(self);
1475     frame->selection().expandSelectionToElementContainingCaretSelection();
1476 }
1477
1478 - (DOMRange *)elementRangeContainingCaretSelection
1479 {
1480     WebCore::Frame *frame = core(self);
1481     RefPtr<WebCore::Range> range = frame->selection().elementRangeContainingCaretSelection();
1482     return kit(range.get());
1483 }
1484
1485 - (void)expandSelectionToWordContainingCaretSelection
1486 {
1487     WebCore::Frame *frame = core(self);
1488     frame->selection().expandSelectionToWordContainingCaretSelection();
1489 }
1490
1491 - (void)expandSelectionToStartOfWordContainingCaretSelection
1492 {
1493     WebCore::Frame *frame = core(self);
1494     frame->selection().expandSelectionToStartOfWordContainingCaretSelection();
1495 }
1496
1497 - (unichar)characterInRelationToCaretSelection:(int)amount
1498 {
1499     return core(self)->selection().characterInRelationToCaretSelection(amount);
1500 }
1501
1502 - (unichar)characterBeforeCaretSelection
1503 {
1504     return core(self)->selection().characterBeforeCaretSelection();
1505 }
1506
1507 - (unichar)characterAfterCaretSelection
1508 {
1509     return core(self)->selection().characterAfterCaretSelection();
1510 }
1511
1512 - (DOMRange *)wordRangeContainingCaretSelection
1513 {
1514     WebCore::Frame *frame = core(self);
1515     RefPtr<WebCore::Range> range = frame->selection().wordRangeContainingCaretSelection();
1516     return kit(range.get());
1517 }
1518
1519 - (NSString *)wordInRange:(DOMRange *)range
1520 {
1521     if (!range)
1522         return nil;
1523     return [self _stringForRange:range];
1524 }
1525
1526 - (int)wordOffsetInRange:(DOMRange *)range
1527 {
1528     return core(self)->selection().wordOffsetInRange(core(range));
1529 }
1530
1531 - (BOOL)spaceFollowsWordInRange:(DOMRange *)range
1532 {
1533     return core(self)->selection().spaceFollowsWordInRange(core(range));
1534 }
1535
1536 - (NSArray *)wordsInCurrentParagraph
1537 {
1538     return core(self)->wordsInCurrentParagraph();
1539 }
1540
1541 - (BOOL)selectionAtDocumentStart
1542 {
1543     WebCore::Frame *frame = core(self);
1544     
1545     if (frame->selection().selection().isNone())
1546         return NO;
1547         
1548     frame->document()->updateLayout();
1549     
1550     return frame->selection().selectionAtDocumentStart();
1551 }
1552
1553 - (BOOL)selectionAtSentenceStart
1554 {
1555     WebCore::Frame *frame = core(self);
1556     
1557     if (frame->selection().selection().isNone())
1558         return NO;
1559         
1560     frame->document()->updateLayout();
1561     
1562     return frame->selection().selectionAtSentenceStart();
1563 }
1564
1565 - (BOOL)selectionAtWordStart
1566 {
1567     WebCore::Frame *frame = core(self);
1568     
1569     if (frame->selection().selection().isNone())
1570         return NO;
1571         
1572     frame->document()->updateLayout();
1573     
1574     return frame->selection().selectionAtWordStart();
1575 }
1576
1577 - (DOMRange *)rangeByMovingCurrentSelection:(int)amount
1578 {
1579     WebCore::Frame *frame = core(self);
1580     RefPtr<WebCore::Range> range = frame->selection().rangeByMovingCurrentSelection(amount);
1581     return kit(range.get());
1582 }
1583
1584 - (DOMRange *)rangeByExtendingCurrentSelection:(int)amount
1585 {
1586     WebCore::Frame *frame = core(self);
1587     RefPtr<WebCore::Range> range = frame->selection().rangeByExtendingCurrentSelection(amount);
1588     return kit(range.get());
1589 }
1590
1591 - (void)selectNSRange:(NSRange)range onElement:(DOMElement *)element
1592 {
1593     WebCore::Frame *frame = core(self);
1594
1595     Document *doc = frame->document();
1596     if (!doc)
1597         return;
1598
1599     Node* node = core(element);
1600     if (!node->isConnected())
1601         return;
1602
1603     frame->selection().selectRangeOnElement(range.location, range.length, *node);
1604 }
1605
1606 - (DOMRange *)markedTextDOMRange
1607 {
1608     WebCore::Frame *frame = core(self);
1609     if (!frame)
1610         return nil;
1611
1612     return kit(frame->editor().compositionRange().get());
1613 }
1614
1615 - (void)setMarkedText:(NSString *)text selectedRange:(NSRange)newSelRange
1616 {
1617     WebCore::Frame *frame = core(self);
1618     if (!frame)
1619         return;
1620     
1621     Vector<CompositionUnderline> underlines;
1622     frame->page()->chrome().client().suppressFormNotifications();
1623     frame->editor().setComposition(text, underlines, newSelRange.location, NSMaxRange(newSelRange));
1624     frame->page()->chrome().client().restoreFormNotifications();
1625 }
1626
1627 - (void)setMarkedText:(NSString *)text forCandidates:(BOOL)forCandidates
1628 {
1629     WebCore::Frame *frame = core(self);
1630     if (!frame)
1631         return;
1632         
1633     Vector<CompositionUnderline> underlines;
1634     frame->editor().setComposition(text, underlines, 0, [text length]);
1635 }
1636
1637 - (void)confirmMarkedText:(NSString *)text
1638 {
1639     WebCore::Frame *frame = core(self);
1640     if (!frame || !frame->editor().client())
1641         return;
1642     
1643     frame->page()->chrome().client().suppressFormNotifications();
1644     if (text)
1645         frame->editor().confirmComposition(text);
1646     else
1647         frame->editor().confirmMarkedText();
1648     frame->page()->chrome().client().restoreFormNotifications();
1649 }
1650
1651 - (void)setText:(NSString *)text asChildOfElement:(DOMElement *)element
1652 {
1653     if (!element)
1654         return;
1655         
1656     WebCore::Frame *frame = core(self);
1657     if (!frame || !frame->document())
1658         return;
1659         
1660     frame->editor().setTextAsChildOfElement(text, *core(element));
1661 }
1662
1663 - (void)setDictationPhrases:(NSArray *)dictationPhrases metadata:(id)metadata asChildOfElement:(DOMElement *)element
1664 {
1665     if (!element)
1666         return;
1667     
1668     auto* frame = core(self);
1669     if (!frame)
1670         return;
1671     
1672     frame->editor().setDictationPhrasesAsChildOfElement(vectorForDictationPhrasesArray(dictationPhrases), metadata, *core(element));
1673 }
1674
1675 - (NSArray *)interpretationsForCurrentRoot
1676 {
1677     return core(self)->interpretationsForCurrentRoot();
1678 }
1679
1680 // Collects the ranges and metadata for all of the mars voltas in the root editable element.
1681 - (void)getDictationResultRanges:(NSArray **)outRanges andMetadatas:(NSArray **)outMetadatas
1682 {
1683     ASSERT(outRanges);
1684     if (!outRanges)
1685         return;
1686     
1687     // *outRanges should not already point to an array.
1688     ASSERT(!(*outRanges));
1689     *outRanges = nil;
1690     
1691     ASSERT(outMetadatas);
1692     if (!outMetadatas)
1693         return;
1694     
1695     // *metadata should not already point to an array.
1696     ASSERT(!(*outMetadatas));
1697     *outMetadatas = nil;
1698     
1699     NSMutableArray *ranges = [NSMutableArray array];
1700     NSMutableArray *metadatas = [NSMutableArray array];
1701     
1702     Frame* frame = core(self);
1703     Document* document = frame->document();
1704
1705     const VisibleSelection& selection = frame->selection().selection();
1706     Element* root = selection.selectionType() == VisibleSelection::NoSelection ? frame->document()->bodyOrFrameset() : selection.rootEditableElement();
1707     
1708     DOMRange *previousDOMRange = nil;
1709     id previousMetadata = nil;
1710     
1711     for (Node* node = root; node; node = NodeTraversal::next(*node)) {
1712         auto markers = document->markers().markersFor(node);
1713         for (auto* marker : markers) {
1714
1715             if (marker->type() != DocumentMarker::DictationResult)
1716                 continue;
1717             
1718             id metadata = marker->metadata();
1719             
1720             // All result markers should have metadata.
1721             ASSERT(metadata);
1722             if (!metadata)
1723                 continue;
1724             
1725             RefPtr<Range> range = Range::create(*document, node, marker->startOffset(), node, marker->endOffset());
1726             DOMRange *domRange = kit(range.get());
1727             
1728             if (metadata != previousMetadata) {
1729                 [metadatas addObject:metadata];
1730                 [ranges addObject:domRange];
1731                 previousMetadata = metadata;
1732                 previousDOMRange = domRange;
1733             } else {
1734                 // It is possible for a DocumentMarker to be split by editing. Adjacent markers with the
1735                 // the same metadata are for the same result. So combine their ranges.
1736                 ASSERT(previousDOMRange == [ranges lastObject]);
1737                 [previousDOMRange retain];
1738                 [ranges removeLastObject];
1739                 DOMNode *startContainer = [domRange startContainer];
1740                 int startOffset = [domRange startOffset];
1741                 [previousDOMRange setEnd:startContainer offset:startOffset];
1742                 [ranges addObject:previousDOMRange];
1743                 [previousDOMRange release];
1744             }
1745         }
1746     }
1747     
1748     *outRanges = ranges;
1749     *outMetadatas = metadatas;
1750     
1751     return;
1752 }
1753
1754 - (id)dictationResultMetadataForRange:(DOMRange *)range
1755 {
1756     if (!range)
1757         return nil;
1758     
1759     auto markers = core(self)->document()->markers().markersInRange(core(range), DocumentMarker::DictationResult);
1760     
1761     // UIKit should only ever give us a DOMRange for a phrase with alternatives, which should not be part of more than one result.
1762     ASSERT(markers.size() <= 1);
1763     if (markers.size() == 0)
1764         return nil;
1765     
1766     return markers[0]->metadata();
1767 }
1768
1769 - (void)recursiveSetUpdateAppearanceEnabled:(BOOL)enabled
1770 {
1771     WebCore::Frame *frame = core(self);
1772     if (frame)
1773         frame->recursiveSetUpdateAppearanceEnabled(enabled);
1774 }
1775
1776 // WebCoreFrameBridge methods used by iOS applications and frameworks
1777 // FIXME: WebCoreFrameBridge is long gone. Can we remove these methods?
1778
1779 + (NSString *)stringWithData:(NSData *)data textEncodingName:(NSString *)textEncodingName
1780 {
1781     WebCore::TextEncoding encoding(textEncodingName);
1782     if (!encoding.isValid())
1783         encoding = WindowsLatin1Encoding();
1784     return encoding.decode(reinterpret_cast<const char*>([data bytes]), [data length]);
1785 }
1786
1787 - (NSRect)caretRectAtNode:(DOMNode *)node offset:(int)offset affinity:(NSSelectionAffinity)affinity
1788 {
1789     return [self _caretRectAtPosition:createLegacyEditingPosition(core(node), offset) affinity:affinity];
1790 }
1791
1792 - (DOMRange *)characterRangeAtPoint:(NSPoint)point
1793 {
1794     return [self _characterRangeAtPoint:point];
1795 }
1796
1797 - (NSRange)convertDOMRangeToNSRange:(DOMRange *)range
1798 {
1799     return [self _convertDOMRangeToNSRange:range];
1800 }
1801
1802 - (DOMRange *)convertNSRangeToDOMRange:(NSRange)nsrange
1803 {
1804     return [self _convertNSRangeToDOMRange:nsrange];
1805 }
1806
1807 - (NSRect)firstRectForDOMRange:(DOMRange *)range
1808 {
1809     return [self _firstRectForDOMRange:range];
1810 }
1811
1812 - (CTFontRef)fontForSelection:(BOOL *)hasMultipleFonts
1813 {
1814     bool multipleFonts = false;
1815     CTFontRef font = nil;
1816     if (_private->coreFrame) {
1817         const Font
1818         * fd = _private->coreFrame->editor().fontForSelection(multipleFonts);
1819         if (fd)
1820             font = fd->getCTFont();
1821     }
1822     
1823     if (hasMultipleFonts)
1824         *hasMultipleFonts = multipleFonts;
1825     return font;
1826 }
1827
1828 - (void)sendScrollEvent
1829 {
1830     ASSERT(WebThreadIsLockedOrDisabled());
1831     _private->coreFrame->eventHandler().sendScrollEvent();
1832 }
1833
1834 - (void)_userScrolled
1835 {
1836     ASSERT(WebThreadIsLockedOrDisabled());
1837     if (FrameView* view = _private->coreFrame->view())
1838         view->setWasScrolledByUser(true);
1839 }
1840
1841 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture
1842 {
1843     return [self _stringByEvaluatingJavaScriptFromString:string forceUserGesture:forceUserGesture];
1844 }
1845
1846 - (NSString *)stringForRange:(DOMRange *)range
1847 {
1848     return [self _stringForRange:range];
1849 }
1850
1851 //
1852 // FIXME: We needed to add this method for iOS due to the opensource version's inclusion of
1853 // matchStyle:YES. It seems odd that we should need to explicitly match style, given that the
1854 // fragment is being made out of plain text, which shouldn't be carrying any style of its own.
1855 // When we paste that it will pick up its style from the surrounding content. What else would
1856 // we expect? If we flipped that matchStyle bit to NO, we could probably just get rid
1857 // of this method, and call the standard WebKit version.
1858 //
1859 // There's a second problem here, too, which is that ReplaceSelectionCommand sometimes adds
1860 // redundant style.
1861 // 
1862 - (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
1863 {
1864     RefPtr<Range> range = _private->coreFrame->selection().toNormalizedRange();
1865
1866     DOMDocumentFragment* fragment = range ? kit(createFragmentFromText(*range, text).ptr()) : nil;
1867     [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle];
1868 }
1869
1870 - (void)_replaceSelectionWithWebArchive:(WebArchive *)webArchive selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1871 {
1872     NSArray* subresources = [webArchive subresources];
1873     for (WebResource* subresource in subresources) {
1874         if (![[self dataSource] subresourceForURL:[subresource URL]])
1875             [[self dataSource] addSubresource:subresource];
1876     }
1877
1878     DOMDocumentFragment* fragment = [[self dataSource] _documentFragmentWithArchive:webArchive];
1879     [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
1880 }
1881
1882 #endif // PLATFORM(IOS)
1883
1884 #if ENABLE(TEXT_AUTOSIZING)
1885 - (void)resetTextAutosizingBeforeLayout
1886 {
1887     id documentView = [_private->webFrameView documentView];    
1888     if (![documentView isKindOfClass:[WebHTMLView class]])
1889         return;
1890     
1891     Frame* coreFrame = core(self);
1892     for (Frame* frame = coreFrame; frame; frame = frame->tree().traverseNext(coreFrame)) {
1893         Document *doc = frame->document();
1894         if (!doc || !doc->renderView())
1895             continue;
1896         doc->renderView()->resetTextAutosizing();
1897     }
1898 }
1899
1900 - (void)_setVisibleSize:(CGSize)size
1901 {
1902     [self _setTextAutosizingWidth:size.width];
1903 }
1904
1905 - (void)_setTextAutosizingWidth:(CGFloat)width
1906 {
1907     WebCore::Frame* frame = core(self);
1908     Page* page = frame->page();
1909     if (!page)
1910         return;
1911
1912     page->setTextAutosizingWidth(width);
1913 }
1914 #else
1915 - (void)resetTextAutosizingBeforeLayout
1916 {
1917 }
1918
1919 - (void)_setVisibleSize:(CGSize)size
1920 {
1921 }
1922
1923 - (void)_setTextAutosizingWidth:(CGFloat)width
1924 {
1925 }
1926 #endif // ENABLE(TEXT_AUTOSIZING)
1927
1928 - (void)_replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
1929 {
1930     if (_private->coreFrame->selection().isNone() || !fragment)
1931         return;
1932     _private->coreFrame->editor().replaceSelectionWithFragment(core(fragment), selectReplacement, smartReplace, matchStyle);
1933 }
1934
1935 #if PLATFORM(IOS)
1936 - (void)removeUnchangeableStyles
1937 {
1938     _private->coreFrame->editor().removeUnchangeableStyles();
1939 }
1940
1941 - (BOOL)hasRichlyEditableSelection
1942 {
1943     return _private->coreFrame->selection().selection().isContentRichlyEditable();
1944 }
1945 #endif
1946
1947 - (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1948 {
1949     RefPtr<Range> range = _private->coreFrame->selection().toNormalizedRange();
1950     
1951     DOMDocumentFragment* fragment = range ? kit(createFragmentFromText(*range, text).ptr()) : nil;
1952     [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES];
1953 }
1954
1955 - (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
1956 {
1957     DOMDocumentFragment *fragment = [self _documentFragmentWithMarkupString:markupString baseURLString:baseURLString];
1958     [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
1959 }
1960
1961 #if !PLATFORM(IOS)
1962 // Determines whether whitespace needs to be added around aString to preserve proper spacing and
1963 // punctuation when it's inserted into the receiver's text over charRange. Returns by reference
1964 // in beforeString and afterString any whitespace that should be added, unless either or both are
1965 // nil. Both are returned as nil if aString is nil or if smart insertion and deletion are disabled.
1966 - (void)_smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString
1967 {
1968     // give back nil pointers in case of early returns
1969     if (beforeString)
1970         *beforeString = nil;
1971     if (afterString)
1972         *afterString = nil;
1973         
1974     // inspect destination
1975     Node *startContainer = core([rangeToReplace startContainer]);
1976     Node *endContainer = core([rangeToReplace endContainer]);
1977
1978     Position startPos(startContainer, [rangeToReplace startOffset], Position::PositionIsOffsetInAnchor);
1979     Position endPos(endContainer, [rangeToReplace endOffset], Position::PositionIsOffsetInAnchor);
1980
1981     VisiblePosition startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY);
1982     VisiblePosition endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY);
1983     
1984     // this check also ensures startContainer, startPos, endContainer, and endPos are non-null
1985     if (startVisiblePos.isNull() || endVisiblePos.isNull())
1986         return;
1987
1988     bool addLeadingSpace = startPos.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos);
1989     if (addLeadingSpace)
1990         if (UChar previousChar = startVisiblePos.previous().characterAfter())
1991             addLeadingSpace = !isCharacterSmartReplaceExempt(previousChar, true);
1992     
1993     bool addTrailingSpace = endPos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos);
1994     if (addTrailingSpace)
1995         if (UChar thisChar = endVisiblePos.characterAfter())
1996             addTrailingSpace = !isCharacterSmartReplaceExempt(thisChar, false);
1997     
1998     // inspect source
1999     bool hasWhitespaceAtStart = false;
2000     bool hasWhitespaceAtEnd = false;
2001     unsigned pasteLength = [pasteString length];
2002     if (pasteLength > 0) {
2003         NSCharacterSet *whiteSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
2004         
2005         if ([whiteSet characterIsMember:[pasteString characterAtIndex:0]]) {
2006             hasWhitespaceAtStart = YES;
2007         }
2008         if ([whiteSet characterIsMember:[pasteString characterAtIndex:(pasteLength - 1)]]) {
2009             hasWhitespaceAtEnd = YES;
2010         }
2011     }
2012     
2013     // issue the verdict
2014     if (beforeString && addLeadingSpace && !hasWhitespaceAtStart)
2015         *beforeString = @" ";
2016     if (afterString && addTrailingSpace && !hasWhitespaceAtEnd)
2017         *afterString = @" ";
2018 }
2019 #endif // !PLATFORM(IOS)
2020
2021 - (NSMutableDictionary *)_cacheabilityDictionary
2022 {
2023     NSMutableDictionary *result = [NSMutableDictionary dictionary];
2024     
2025     FrameLoader& frameLoader = _private->coreFrame->loader();
2026     DocumentLoader* documentLoader = frameLoader.documentLoader();
2027     if (documentLoader && !documentLoader->mainDocumentError().isNull())
2028         [result setObject:(NSError *)documentLoader->mainDocumentError() forKey:WebFrameMainDocumentError];
2029         
2030     if (frameLoader.subframeLoader().containsPlugins())
2031         [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasPlugins];
2032     
2033     if (DOMWindow* domWindow = _private->coreFrame->document()->domWindow()) {
2034         if (domWindow->hasEventListeners(eventNames().unloadEvent))
2035             [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasUnloadListener];
2036         if (domWindow->optionalApplicationCache())
2037             [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesApplicationCache];
2038     }
2039     
2040     if (Document* document = _private->coreFrame->document()) {
2041         if (DatabaseManager::singleton().hasOpenDatabases(*document))
2042             [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesDatabases];
2043         if (!document->canSuspendActiveDOMObjectsForDocumentSuspension())
2044             [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameCanSuspendActiveDOMObjects];
2045     }
2046     
2047     return result;
2048 }
2049
2050 - (BOOL)_allowsFollowingLink:(NSURL *)URL
2051 {
2052     if (!_private->coreFrame)
2053         return YES;
2054     return _private->coreFrame->document()->securityOrigin().canDisplay(URL);
2055 }
2056
2057 - (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string withGlobalObject:(JSObjectRef)globalObjectRef inScriptWorld:(WebScriptWorld *)world
2058 {
2059     if (!string)
2060         return @"";
2061
2062     if (!world)
2063         return @"";
2064
2065     // Start off with some guess at a frame and a global object, we'll try to do better...!
2066     JSDOMWindow* anyWorldGlobalObject = _private->coreFrame->script().globalObject(mainThreadNormalWorld());
2067
2068     // The global object is probably a shell object? - if so, we know how to use this!
2069     JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
2070     JSC::VM& vm = *globalObjectObj->vm();
2071     if (!strcmp(globalObjectObj->classInfo(vm)->className, "JSDOMWindowShell"))
2072         anyWorldGlobalObject = static_cast<JSDOMWindowShell*>(globalObjectObj)->window();
2073
2074     // Get the frame frome the global object we've settled on.
2075     Frame* frame = anyWorldGlobalObject->wrapped().frame();
2076     ASSERT(frame->document());
2077     RetainPtr<WebFrame> webFrame(kit(frame)); // Running arbitrary JavaScript can destroy the frame.
2078
2079     JSC::JSValue result = frame->script().executeScriptInWorld(*core(world), string, true);
2080
2081     if (!webFrame->_private->coreFrame) // In case the script removed our frame from the page.
2082         return @"";
2083
2084     // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
2085     // If you don't like it, use -[WebScriptObject evaluateWebScript:] or 
2086     // JSEvaluateScript instead, since they have less surprising semantics.
2087     if (!result || (!result.isBoolean() && !result.isString() && !result.isNumber()))
2088         return @"";
2089
2090     JSC::ExecState* exec = anyWorldGlobalObject->globalExec();
2091     JSC::JSLockHolder lock(exec);
2092     return result.toWTFString(exec);
2093 }
2094
2095 - (JSGlobalContextRef)_globalContextForScriptWorld:(WebScriptWorld *)world
2096 {
2097     Frame* coreFrame = _private->coreFrame;
2098     if (!coreFrame)
2099         return 0;
2100     DOMWrapperWorld* coreWorld = core(world);
2101     if (!coreWorld)
2102         return 0;
2103     return toGlobalRef(coreFrame->script().globalObject(*coreWorld)->globalExec());
2104 }
2105
2106 #if JSC_OBJC_API_ENABLED
2107 - (JSContext *)_javaScriptContextForScriptWorld:(WebScriptWorld *)world
2108 {
2109     JSGlobalContextRef globalContextRef = [self _globalContextForScriptWorld:world];
2110     if (!globalContextRef)
2111         return 0;
2112     return [JSContext contextWithJSGlobalContextRef:globalContextRef];
2113 }
2114 #endif
2115
2116 #if !PLATFORM(IOS)
2117 - (void)setAllowsScrollersToOverlapContent:(BOOL)flag
2118 {
2119     ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
2120     [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAllowsScrollersToOverlapContent:flag];
2121 }
2122
2123 - (void)setAlwaysHideHorizontalScroller:(BOOL)flag
2124 {
2125     ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
2126     [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAlwaysHideHorizontalScroller:flag];
2127 }
2128 - (void)setAlwaysHideVerticalScroller:(BOOL)flag
2129 {
2130     ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
2131     [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAlwaysHideVerticalScroller:flag];
2132 }
2133 #endif
2134
2135 - (void)setAccessibleName:(NSString *)name
2136 {
2137 #if HAVE(ACCESSIBILITY)
2138     if (!AXObjectCache::accessibilityEnabled())
2139         return;
2140     
2141     if (!_private->coreFrame || !_private->coreFrame->document())
2142         return;
2143     
2144     AccessibilityObject* rootObject = _private->coreFrame->document()->axObjectCache()->rootObject();
2145     if (rootObject) {
2146         String strName(name);
2147         rootObject->setAccessibleName(strName);
2148     }
2149 #endif
2150 }
2151
2152 - (BOOL)enhancedAccessibilityEnabled
2153 {
2154 #if HAVE(ACCESSIBILITY)
2155     return AXObjectCache::accessibilityEnhancedUserInterfaceEnabled();
2156 #else
2157     return NO;
2158 #endif
2159 }
2160
2161 - (void)setEnhancedAccessibility:(BOOL)enable
2162 {
2163 #if HAVE(ACCESSIBILITY)
2164     AXObjectCache::setEnhancedUserInterfaceAccessibility(enable);
2165 #endif
2166 }
2167
2168 - (NSString*)_layerTreeAsText
2169 {
2170     Frame* coreFrame = _private->coreFrame;
2171     if (!coreFrame)
2172         return @"";
2173
2174     return coreFrame->layerTreeAsText();
2175 }
2176
2177 - (id)accessibilityRoot
2178 {
2179 #if HAVE(ACCESSIBILITY)
2180     if (!AXObjectCache::accessibilityEnabled()) {
2181         AXObjectCache::enableAccessibility();
2182 #if !PLATFORM(IOS)
2183 #pragma clang diagnostic push
2184 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2185         AXObjectCache::setEnhancedUserInterfaceAccessibility([[NSApp accessibilityAttributeValue:NSAccessibilityEnhancedUserInterfaceAttribute] boolValue]);
2186 #pragma clang diagnostic pop
2187 #endif
2188     }
2189     
2190     if (!_private->coreFrame)
2191         return nil;
2192     
2193     Document* document = _private->coreFrame->document();
2194     if (!document || !document->axObjectCache())
2195         return nil;
2196     
2197     AccessibilityObject* rootObject = document->axObjectCache()->rootObjectForFrame(_private->coreFrame);
2198     if (!rootObject)
2199         return nil;
2200     
2201     // The root object will be a WebCore scroll view object. In WK1, scroll views are handled
2202     // by the system and the root object should be the web area (instead of the scroll view).
2203     if (rootObject->isAttachment() && rootObject->firstChild())
2204         return rootObject->firstChild()->wrapper();
2205     
2206     return rootObject->wrapper();
2207 #else
2208     return nil;
2209 #endif
2210 }
2211
2212 - (void)_clearOpener
2213 {
2214     Frame* coreFrame = _private->coreFrame;
2215     if (coreFrame)
2216         coreFrame->loader().setOpener(0);
2217 }
2218
2219 // Used by pagination code called from AppKit when a standalone web page is printed.
2220 - (NSArray *)_computePageRectsWithPrintScaleFactor:(float)printScaleFactor pageSize:(NSSize)pageSize
2221 {
2222     if (printScaleFactor <= 0) {
2223         LOG_ERROR("printScaleFactor has bad value %.2f", printScaleFactor);
2224         return [NSArray array];
2225     }
2226
2227     if (!_private->coreFrame)
2228         return [NSArray array];
2229     if (!_private->coreFrame->document())
2230         return [NSArray array];
2231     if (!_private->coreFrame->view())
2232         return [NSArray array];
2233     if (!_private->coreFrame->view()->documentView())
2234         return [NSArray array];
2235
2236     RenderView* root = _private->coreFrame->document()->renderView();
2237     if (!root)
2238         return [NSArray array];
2239
2240     const LayoutRect& documentRect = root->documentRect();
2241     float printWidth = root->style().isHorizontalWritingMode() ? static_cast<float>(documentRect.width()) / printScaleFactor : pageSize.width;
2242     float printHeight = root->style().isHorizontalWritingMode() ? pageSize.height : static_cast<float>(documentRect.height()) / printScaleFactor;
2243
2244     PrintContext printContext(_private->coreFrame);
2245     printContext.computePageRectsWithPageSize(FloatSize(printWidth, printHeight), true);
2246     const Vector<IntRect>& pageRects = printContext.pageRects();
2247
2248     size_t size = pageRects.size();
2249     NSMutableArray *pages = [NSMutableArray arrayWithCapacity:size];
2250     for (size_t i = 0; i < size; ++i)
2251         [pages addObject:[NSValue valueWithRect:NSRect(pageRects[i])]];
2252     return pages;
2253 }
2254
2255 #if PLATFORM(IOS)
2256
2257 - (DOMDocumentFragment *)_documentFragmentForText:(NSString *)text
2258 {
2259     return kit(createFragmentFromText(*_private->coreFrame->selection().toNormalizedRange().get(), text).ptr());
2260 }
2261
2262 - (DOMDocumentFragment *)_documentFragmentForWebArchive:(WebArchive *)webArchive
2263 {
2264     return [[self dataSource] _documentFragmentWithArchive:webArchive];
2265 }
2266
2267 - (DOMDocumentFragment *)_documentFragmentForImageData:(NSData *)data withRelativeURLPart:(NSString *)relativeURLPart andMIMEType:(NSString *)mimeType
2268 {
2269     WebResource *resource = [[WebResource alloc] initWithData:data
2270                                                           URL:[NSURL uniqueURLWithRelativePart:relativeURLPart]
2271                                                      MIMEType:mimeType
2272                                              textEncodingName:nil
2273                                                     frameName:nil];
2274     DOMDocumentFragment *fragment = [[self _dataSource] _documentFragmentWithImageResource:resource];
2275     [resource release];
2276     return fragment;
2277 }
2278
2279 - (BOOL)focusedNodeHasContent
2280 {
2281     Frame* coreFrame = _private->coreFrame;
2282    
2283     Element* root;
2284     const VisibleSelection& selection = coreFrame->selection().selection();
2285     if (selection.isNone() || !selection.isContentEditable())
2286         root = coreFrame->document()->bodyOrFrameset();
2287     else {
2288         // Can't use the focusedNode here because we want the root of the shadow tree for form elements.
2289         root = selection.rootEditableElement();
2290     }
2291     // Early return to avoid the expense of creating VisiblePositions.
2292     // FIXME: We fail to compute a root for SVG, we have a null check here so that we don't crash.
2293     if (!root || !root->hasChildNodes())
2294         return NO;
2295
2296     VisiblePosition first(createLegacyEditingPosition(root, 0));
2297     VisiblePosition last(createLegacyEditingPosition(root, root->countChildNodes()));
2298     return first != last;
2299 }
2300
2301 - (void)_dispatchDidReceiveTitle:(NSString *)title
2302 {
2303     Frame* coreFrame = _private->coreFrame;
2304     if (!coreFrame)
2305         return;
2306     coreFrame->loader().client().dispatchDidReceiveTitle({ title, LTR });
2307 }
2308
2309 #endif // PLATFORM(IOS)
2310
2311 - (JSValueRef)jsWrapperForNode:(DOMNode *)node inScriptWorld:(WebScriptWorld *)world
2312 {
2313     Frame* coreFrame = _private->coreFrame;
2314     if (!coreFrame)
2315         return 0;
2316
2317     if (!world)
2318         return 0;
2319
2320     JSDOMWindow* globalObject = coreFrame->script().globalObject(*core(world));
2321     JSC::ExecState* exec = globalObject->globalExec();
2322
2323     JSC::JSLockHolder lock(exec);
2324     return toRef(exec, toJS(exec, globalObject, core(node)));
2325 }
2326
2327 - (NSDictionary *)elementAtPoint:(NSPoint)point
2328 {
2329     Frame* coreFrame = _private->coreFrame;
2330     if (!coreFrame)
2331         return nil;
2332     return [[[WebElementDictionary alloc] initWithHitTestResult:coreFrame->eventHandler().hitTestResultAtPoint(IntPoint(point), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowUserAgentShadowContent)] autorelease];
2333 }
2334
2335 - (NSURL *)_unreachableURL
2336 {
2337     return [[self _dataSource] unreachableURL];
2338 }
2339
2340 @end
2341
2342 @implementation WebFrame
2343
2344 - (instancetype)init
2345 {
2346     return nil;
2347 }
2348
2349 // Should be deprecated.
2350 - (instancetype)initWithName:(NSString *)name webFrameView:(WebFrameView *)view webView:(WebView *)webView
2351 {
2352     return nil;
2353 }
2354
2355 - (void)dealloc
2356 {
2357     if (_private && _private->includedInWebKitStatistics)
2358         --WebFrameCount;
2359
2360     [_private release];
2361
2362     [super dealloc];
2363 }
2364
2365 - (NSString *)name
2366 {
2367     Frame* coreFrame = _private->coreFrame;
2368     if (!coreFrame)
2369         return nil;
2370     return coreFrame->tree().uniqueName();
2371 }
2372
2373 - (WebFrameView *)frameView
2374 {
2375     return _private->webFrameView;
2376 }
2377
2378 - (WebView *)webView
2379 {
2380     return getWebView(self);
2381 }
2382
2383 static bool needsMicrosoftMessengerDOMDocumentWorkaround()
2384 {
2385 #if PLATFORM(IOS)
2386     return false;
2387 #else
2388     static bool needsWorkaround = MacApplication::isMicrosoftMessenger() && [[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] compare:@"7.1" options:NSNumericSearch] == NSOrderedAscending;
2389     return needsWorkaround;
2390 #endif
2391 }
2392
2393 - (DOMDocument *)DOMDocument
2394 {
2395     if (needsMicrosoftMessengerDOMDocumentWorkaround() && !pthread_main_np())
2396         return nil;
2397
2398     Frame* coreFrame = _private->coreFrame;
2399     if (!coreFrame)
2400         return nil;
2401     
2402     // FIXME: <rdar://problem/5145841> When loading a custom view/representation 
2403     // into a web frame, the old document can still be around. This makes sure that
2404     // we'll return nil in those cases.
2405     if (![[self _dataSource] _isDocumentHTML]) 
2406         return nil; 
2407
2408     Document* document = coreFrame->document();
2409     
2410     // According to the documentation, we should return nil if the frame doesn't have a document.
2411     // While full-frame images and plugins do have an underlying HTML document, we return nil here to be
2412     // backwards compatible.
2413     if (document && (document->isPluginDocument() || document->isImageDocument()))
2414         return nil;
2415     
2416     return kit(coreFrame->document());
2417 }
2418
2419 - (DOMHTMLElement *)frameElement
2420 {
2421     Frame* coreFrame = _private->coreFrame;
2422     if (!coreFrame)
2423         return nil;
2424     return kit(coreFrame->ownerElement());
2425 }
2426
2427 - (WebDataSource *)provisionalDataSource
2428 {
2429     Frame* coreFrame = _private->coreFrame;
2430     return coreFrame ? dataSource(coreFrame->loader().provisionalDocumentLoader()) : nil;
2431 }
2432
2433 - (WebDataSource *)dataSource
2434 {
2435     Frame* coreFrame = _private->coreFrame;
2436     return coreFrame && coreFrame->loader().frameHasLoaded() ? [self _dataSource] : nil;
2437 }
2438
2439 - (void)loadRequest:(NSURLRequest *)request
2440 {
2441     Frame* coreFrame = _private->coreFrame;
2442     if (!coreFrame)
2443         return;
2444
2445     ResourceRequest resourceRequest(request);
2446     
2447     // Some users of WebKit API incorrectly use "file path as URL" style requests which are invalid.
2448     // By re-writing those URLs here we technically break the -[WebDataSource initialRequest] API
2449     // but that is necessary to implement this quirk only at the API boundary.
2450     // Note that other users of WebKit API use nil requests or requests with nil URLs or empty URLs, so we
2451     // only implement this workaround when the request had a non-nil or non-empty URL.
2452     if (!resourceRequest.url().isValid() && !resourceRequest.url().isEmpty())
2453         resourceRequest.setURL([NSURL URLWithString:[@"file:" stringByAppendingString:[[request URL] absoluteString]]]);
2454
2455     coreFrame->loader().load(FrameLoadRequest(coreFrame, resourceRequest, ShouldOpenExternalURLsPolicy::ShouldNotAllow));
2456 }
2457
2458 static NSURL *createUniqueWebDataURL()
2459 {
2460     CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
2461     NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
2462     CFRelease(UUIDRef);
2463     NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"applewebdata://%@", UUIDString]];
2464     CFRelease(UUIDString);
2465     return URL;
2466 }
2467
2468 - (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
2469 {
2470 #if PLATFORM(MAC)
2471     if (!pthread_main_np())
2472         return [[self _webkit_invokeOnMainThread] _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:unreachableURL];
2473 #endif
2474
2475     NSURL *responseURL = nil;
2476     if (baseURL)
2477         baseURL = [baseURL absoluteURL];
2478     else {
2479         baseURL = blankURL();
2480         responseURL = createUniqueWebDataURL();
2481     }
2482     
2483 #if USE(QUICK_LOOK)
2484     if (shouldUseQuickLookForMIMEType(MIMEType)) {
2485         NSURL *quickLookURL = responseURL ? responseURL : baseURL;
2486         if (auto request = registerQLPreviewConverterIfNeeded(quickLookURL, MIMEType, data)) {
2487             _private->coreFrame->loader().load(FrameLoadRequest(_private->coreFrame, request.get(), ShouldOpenExternalURLsPolicy::ShouldNotAllow));
2488             return;
2489         }
2490     }
2491 #endif
2492
2493     ResourceRequest request(baseURL);
2494
2495     ResourceResponse response(responseURL, MIMEType, [data length], encodingName);
2496     SubstituteData substituteData(WebCore::SharedBuffer::create(data), [unreachableURL absoluteURL], response, SubstituteData::SessionHistoryVisibility::Hidden);
2497
2498     _private->coreFrame->loader().load(FrameLoadRequest(_private->coreFrame, request, ShouldOpenExternalURLsPolicy::ShouldNotAllow, substituteData));
2499 }
2500
2501 - (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL
2502 {
2503     WebCoreThreadViolationCheckRoundTwo();
2504     
2505     if (!MIMEType)
2506         MIMEType = @"text/html";
2507     [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:[baseURL _webkit_URLFromURLOrSchemelessFileURL] unreachableURL:nil];
2508 }
2509
2510 - (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
2511 {
2512     NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
2513     [self _loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:baseURL unreachableURL:unreachableURL];
2514 }
2515
2516 - (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL
2517 {
2518     WebCoreThreadViolationCheckRoundTwo();
2519
2520     [self _loadHTMLString:string baseURL:[baseURL _webkit_URLFromURLOrSchemelessFileURL] unreachableURL:nil];
2521 }
2522
2523 - (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL
2524 {
2525     WebCoreThreadViolationCheckRoundTwo();
2526
2527     [self _loadHTMLString:string baseURL:[baseURL _webkit_URLFromURLOrSchemelessFileURL] unreachableURL:[unreachableURL _webkit_URLFromURLOrSchemelessFileURL]];
2528 }
2529
2530 - (void)loadArchive:(WebArchive *)archive
2531 {
2532     if (auto* coreArchive = [archive _coreLegacyWebArchive])
2533         _private->coreFrame->loader().loadArchive(*coreArchive);
2534 }
2535
2536 - (void)stopLoading
2537 {
2538     if (!_private->coreFrame)
2539         return;
2540     _private->coreFrame->loader().stopForUserCancel();
2541 }
2542
2543 - (void)reload
2544 {
2545     _private->coreFrame->loader().reload({ });
2546 }
2547
2548 - (void)reloadFromOrigin
2549 {
2550     _private->coreFrame->loader().reload(WebCore::ReloadOption::FromOrigin);
2551 }
2552
2553 - (WebFrame *)findFrameNamed:(NSString *)name
2554 {
2555     Frame* coreFrame = _private->coreFrame;
2556     if (!coreFrame)
2557         return nil;
2558     return kit(coreFrame->tree().find(name));
2559 }
2560
2561 - (WebFrame *)parentFrame
2562 {
2563     Frame* coreFrame = _private->coreFrame;
2564     if (!coreFrame)
2565         return nil;
2566     return [[kit(coreFrame->tree().parent()) retain] autorelease];
2567 }
2568
2569 - (NSArray *)childFrames
2570 {
2571     Frame* coreFrame = _private->coreFrame;
2572     if (!coreFrame)
2573         return [NSArray array];
2574     NSMutableArray *children = [NSMutableArray arrayWithCapacity:coreFrame->tree().childCount()];
2575     for (Frame* child = coreFrame->tree().firstChild(); child; child = child->tree().nextSibling())
2576         [children addObject:kit(child)];
2577     return children;
2578 }
2579
2580 - (WebScriptObject *)windowObject
2581 {
2582     Frame* coreFrame = _private->coreFrame;
2583     if (!coreFrame)
2584         return 0;
2585     return coreFrame->script().windowScriptObject();
2586 }
2587
2588 - (JSGlobalContextRef)globalContext
2589 {
2590     Frame* coreFrame = _private->coreFrame;
2591     if (!coreFrame)
2592         return 0;
2593     return toGlobalRef(coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec());
2594 }
2595
2596 #if JSC_OBJC_API_ENABLED
2597 - (JSContext *)javaScriptContext
2598 {
2599     Frame* coreFrame = _private->coreFrame;
2600     if (!coreFrame)
2601         return 0;
2602     return coreFrame->script().javaScriptContext();
2603 }
2604 #endif
2605
2606 @end