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