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