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