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