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