~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WebKit/mac/WebView/WebFrame.mm

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 Computer, 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 "WebFrameLoaderClient.h"
 
44
#import "WebFrameViewInternal.h"
 
45
#import "WebHTMLView.h"
 
46
#import "WebHTMLViewInternal.h"
 
47
#import "WebKitStatisticsPrivate.h"
 
48
#import "WebKitVersionChecks.h"
 
49
#import "WebNSObjectExtras.h"
 
50
#import "WebNSURLExtras.h"
 
51
#import "WebScriptDebugger.h"
 
52
#import "WebScriptWorldInternal.h"
 
53
#import "WebViewInternal.h"
 
54
#import <JavaScriptCore/APICast.h>
 
55
#import <WebCore/AXObjectCache.h>
 
56
#import <WebCore/AccessibilityObject.h>
 
57
#import <WebCore/AnimationController.h>
 
58
#import <WebCore/CSSStyleDeclaration.h>
 
59
#import <WebCore/CachedResourceLoader.h>
 
60
#import <WebCore/Chrome.h>
 
61
#import <WebCore/ColorMac.h>
 
62
#import <WebCore/DOMImplementation.h>
 
63
#import <WebCore/DatabaseContext.h>
 
64
#import <WebCore/DocumentFragment.h>
 
65
#import <WebCore/DocumentLoader.h>
 
66
#import <WebCore/DocumentMarkerController.h>
 
67
#import <WebCore/EventHandler.h>
 
68
#import <WebCore/EventNames.h>
 
69
#import <WebCore/Frame.h>
 
70
#import <WebCore/FrameLoadRequest.h>
 
71
#import <WebCore/FrameLoader.h>
 
72
#import <WebCore/FrameLoaderStateMachine.h>
 
73
#import <WebCore/FrameTree.h>
 
74
#import <WebCore/GraphicsContext.h>
 
75
#import <WebCore/HTMLFrameOwnerElement.h>
 
76
#import <WebCore/HTMLNames.h>
 
77
#import <WebCore/HistoryItem.h>
 
78
#import <WebCore/HitTestResult.h>
 
79
#import <WebCore/LegacyWebArchive.h>
 
80
#import <WebCore/Page.h>
 
81
#import <WebCore/PlatformEventFactoryMac.h>
 
82
#import <WebCore/PluginData.h>
 
83
#import <WebCore/PrintContext.h>
 
84
#import <WebCore/RenderPart.h>
 
85
#import <WebCore/RenderView.h>
 
86
#import <WebCore/RuntimeApplicationChecks.h>
 
87
#import <WebCore/ScriptValue.h>
 
88
#import <WebCore/SecurityOrigin.h>
 
89
#import <WebCore/SmartReplace.h>
 
90
#import <WebCore/TextIterator.h>
 
91
#import <WebCore/ThreadCheck.h>
 
92
#import <WebCore/htmlediting.h>
 
93
#import <WebCore/markup.h>
 
94
#import <WebCore/visible_units.h>
 
95
#import <WebKitSystemInterface.h>
 
96
#import <runtime/JSLock.h>
 
97
#import <runtime/JSObject.h>
 
98
#import <runtime/JSValue.h>
 
99
#import <wtf/CurrentTime.h>
 
100
 
 
101
using namespace std;
 
102
using namespace WebCore;
 
103
using namespace HTMLNames;
 
104
 
 
105
using JSC::JSGlobalObject;
 
106
using JSC::JSLock;
 
107
using JSC::JSValue;
 
108
 
 
109
/*
 
110
Here is the current behavior matrix for four types of navigations:
 
111
 
 
112
Standard Nav:
 
113
 
 
114
 Restore form state:   YES
 
115
 Restore scroll and focus state:  YES
 
116
 Cache policy: NSURLRequestUseProtocolCachePolicy
 
117
 Add to back/forward list: YES
 
118
 
 
119
Back/Forward:
 
120
 
 
121
 Restore form state:   YES
 
122
 Restore scroll and focus state:  YES
 
123
 Cache policy: NSURLRequestReturnCacheDataElseLoad
 
124
 Add to back/forward list: NO
 
125
 
 
126
Reload (meaning only the reload button):
 
127
 
 
128
 Restore form state:   NO
 
129
 Restore scroll and focus state:  YES
 
130
 Cache policy: NSURLRequestReloadIgnoringCacheData
 
131
 Add to back/forward list: NO
 
132
 
 
133
Repeat load of the same URL (by any other means of navigation other than the reload button, including hitting return in the location field):
 
134
 
 
135
 Restore form state:   NO
 
136
 Restore scroll and focus state:  NO, reset to initial conditions
 
137
 Cache policy: NSURLRequestReloadIgnoringCacheData
 
138
 Add to back/forward list: NO
 
139
*/
 
140
 
 
141
NSString *WebPageCacheEntryDateKey = @"WebPageCacheEntryDateKey";
 
142
NSString *WebPageCacheDataSourceKey = @"WebPageCacheDataSourceKey";
 
143
NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
 
144
 
 
145
NSString *WebFrameMainDocumentError = @"WebFrameMainDocumentErrorKey";
 
146
NSString *WebFrameHasPlugins = @"WebFrameHasPluginsKey";
 
147
NSString *WebFrameHasUnloadListener = @"WebFrameHasUnloadListenerKey";
 
148
NSString *WebFrameUsesDatabases = @"WebFrameUsesDatabasesKey";
 
149
NSString *WebFrameUsesGeolocation = @"WebFrameUsesGeolocationKey";
 
150
NSString *WebFrameUsesApplicationCache = @"WebFrameUsesApplicationCacheKey";
 
151
NSString *WebFrameCanSuspendActiveDOMObjects = @"WebFrameCanSuspendActiveDOMObjectsKey";
 
152
 
 
153
// FIXME: Remove when this key becomes publicly defined
 
154
NSString *NSAccessibilityEnhancedUserInterfaceAttribute = @"AXEnhancedUserInterface";
 
155
 
 
156
@implementation WebFramePrivate
 
157
 
 
158
- (void)dealloc
 
159
{
 
160
    [webFrameView release];
 
161
 
 
162
    delete scriptDebugger;
 
163
 
 
164
    [super dealloc];
 
165
}
 
166
 
 
167
- (void)finalize
 
168
{
 
169
    delete scriptDebugger;
 
170
 
 
171
    [super finalize];
 
172
}
 
173
 
 
174
- (void)setWebFrameView:(WebFrameView *)v 
 
175
 
176
    [v retain];
 
177
    [webFrameView release];
 
178
    webFrameView = v;
 
179
}
 
180
 
 
181
@end
 
182
 
 
183
EditableLinkBehavior core(WebKitEditableLinkBehavior editableLinkBehavior)
 
184
{
 
185
    switch (editableLinkBehavior) {
 
186
        case WebKitEditableLinkDefaultBehavior:
 
187
            return EditableLinkDefaultBehavior;
 
188
        case WebKitEditableLinkAlwaysLive:
 
189
            return EditableLinkAlwaysLive;
 
190
        case WebKitEditableLinkOnlyLiveWithShiftKey:
 
191
            return EditableLinkOnlyLiveWithShiftKey;
 
192
        case WebKitEditableLinkLiveWhenNotFocused:
 
193
            return EditableLinkLiveWhenNotFocused;
 
194
        case WebKitEditableLinkNeverLive:
 
195
            return EditableLinkNeverLive;
 
196
    }
 
197
    ASSERT_NOT_REACHED();
 
198
    return EditableLinkDefaultBehavior;
 
199
}
 
200
 
 
201
TextDirectionSubmenuInclusionBehavior core(WebTextDirectionSubmenuInclusionBehavior behavior)
 
202
{
 
203
    switch (behavior) {
 
204
        case WebTextDirectionSubmenuNeverIncluded:
 
205
            return TextDirectionSubmenuNeverIncluded;
 
206
        case WebTextDirectionSubmenuAutomaticallyIncluded:
 
207
            return TextDirectionSubmenuAutomaticallyIncluded;
 
208
        case WebTextDirectionSubmenuAlwaysIncluded:
 
209
            return TextDirectionSubmenuAlwaysIncluded;
 
210
    }
 
211
    ASSERT_NOT_REACHED();
 
212
    return TextDirectionSubmenuNeverIncluded;
 
213
}
 
214
 
 
215
@implementation WebFrame (WebInternal)
 
216
 
 
217
Frame* core(WebFrame *frame)
 
218
{
 
219
    return frame ? frame->_private->coreFrame : 0;
 
220
}
 
221
 
 
222
WebFrame *kit(Frame* frame)
 
223
{
 
224
    return frame ? static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame() : nil;
 
225
}
 
226
 
 
227
Page* core(WebView *webView)
 
228
{
 
229
    return [webView page];
 
230
}
 
231
 
 
232
WebView *kit(Page* page)
 
233
{
 
234
    return page ? static_cast<WebView*>(page->chrome()->client()->webView()) : nil;
 
235
}
 
236
 
 
237
WebView *getWebView(WebFrame *webFrame)
 
238
{
 
239
    Frame* coreFrame = core(webFrame);
 
240
    if (!coreFrame)
 
241
        return nil;
 
242
    return kit(coreFrame->page());
 
243
}
 
244
 
 
245
+ (PassRefPtr<Frame>)_createFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView ownerElement:(HTMLFrameOwnerElement*)ownerElement
 
246
{
 
247
    WebView *webView = kit(page);
 
248
 
 
249
    WebFrame *frame = [[self alloc] _initWithWebFrameView:frameView webView:webView];
 
250
    RefPtr<Frame> coreFrame = Frame::create(page, ownerElement, new WebFrameLoaderClient(frame));
 
251
    [frame release];
 
252
    frame->_private->coreFrame = coreFrame.get();
 
253
 
 
254
    coreFrame->tree()->setName(name);
 
255
    if (ownerElement) {
 
256
        ASSERT(ownerElement->document()->frame());
 
257
        ownerElement->document()->frame()->tree()->appendChild(coreFrame.get());
 
258
    }
 
259
 
 
260
    coreFrame->init();
 
261
 
 
262
    [webView _setZoomMultiplier:[webView _realZoomMultiplier] isTextOnly:[webView _realZoomMultiplierIsTextOnly]];
 
263
 
 
264
    return coreFrame.release();
 
265
}
 
266
 
 
267
+ (void)_createMainFrameWithPage:(Page*)page frameName:(const String&)name frameView:(WebFrameView *)frameView
 
268
{
 
269
    [self _createFrameWithPage:page frameName:name frameView:frameView ownerElement:0];
 
270
}
 
271
 
 
272
+ (PassRefPtr<WebCore::Frame>)_createSubframeWithOwnerElement:(HTMLFrameOwnerElement*)ownerElement frameName:(const String&)name frameView:(WebFrameView *)frameView
 
273
{
 
274
    return [self _createFrameWithPage:ownerElement->document()->frame()->page() frameName:name frameView:frameView ownerElement:ownerElement];
 
275
}
 
276
 
 
277
- (BOOL)_isIncludedInWebKitStatistics
 
278
{
 
279
    return _private && _private->includedInWebKitStatistics;
 
280
}
 
281
 
 
282
- (void)_attachScriptDebugger
 
283
{
 
284
    ScriptController* scriptController = _private->coreFrame->script();
 
285
 
 
286
    // Calling ScriptController::globalObject() would create a window shell, and dispatch corresponding callbacks, which may be premature
 
287
    // if the script debugger is attached before a document is created.  These calls use the debuggerWorld(), we will need to pass a world
 
288
    // to be able to debug isolated worlds.
 
289
    if (!scriptController->existingWindowShell(debuggerWorld()))
 
290
        return;
 
291
 
 
292
    JSGlobalObject* globalObject = scriptController->globalObject(debuggerWorld());
 
293
    if (!globalObject)
 
294
        return;
 
295
 
 
296
    if (_private->scriptDebugger) {
 
297
        ASSERT(_private->scriptDebugger == globalObject->debugger());
 
298
        return;
 
299
    }
 
300
 
 
301
    _private->scriptDebugger = new WebScriptDebugger(globalObject);
 
302
}
 
303
 
 
304
- (void)_detachScriptDebugger
 
305
{
 
306
    if (!_private->scriptDebugger)
 
307
        return;
 
308
 
 
309
    delete _private->scriptDebugger;
 
310
    _private->scriptDebugger = 0;
 
311
}
 
312
 
 
313
- (id)_initWithWebFrameView:(WebFrameView *)fv webView:(WebView *)v
 
314
{
 
315
    self = [super init];
 
316
    if (!self)
 
317
        return nil;
 
318
 
 
319
    _private = [[WebFramePrivate alloc] init];
 
320
 
 
321
    // Set includedInWebKitStatistics before calling WebFrameView _setWebFrame, since
 
322
    // it calls WebFrame _isIncludedInWebKitStatistics.
 
323
    if ((_private->includedInWebKitStatistics = [[v class] shouldIncludeInWebKitStatistics]))
 
324
        ++WebFrameCount;
 
325
 
 
326
    if (fv) {
 
327
        [_private setWebFrameView:fv];
 
328
        [fv _setWebFrame:self];
 
329
    }
 
330
 
 
331
    _private->shouldCreateRenderers = YES;
 
332
 
 
333
    return self;
 
334
}
 
335
 
 
336
- (void)_clearCoreFrame
 
337
{
 
338
    _private->coreFrame = 0;
 
339
}
 
340
 
 
341
- (void)_updateBackgroundAndUpdatesWhileOffscreen
 
342
{
 
343
    WebView *webView = getWebView(self);
 
344
    BOOL drawsBackground = [webView drawsBackground];
 
345
    NSColor *backgroundColor = [webView backgroundColor];
 
346
 
 
347
    Frame* coreFrame = _private->coreFrame;
 
348
    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
 
349
        // Don't call setDrawsBackground:YES here because it may be NO because of a load
 
350
        // in progress; WebFrameLoaderClient keeps it set to NO during the load process.
 
351
        WebFrame *webFrame = kit(frame);
 
352
        if (!drawsBackground)
 
353
            [[[webFrame frameView] _scrollView] setDrawsBackground:NO];
 
354
        [[[webFrame frameView] _scrollView] setBackgroundColor:backgroundColor];
 
355
        id documentView = [[webFrame frameView] documentView];
 
356
        if ([documentView respondsToSelector:@selector(setDrawsBackground:)])
 
357
            [documentView setDrawsBackground:drawsBackground];
 
358
        if ([documentView respondsToSelector:@selector(setBackgroundColor:)])
 
359
            [documentView setBackgroundColor:backgroundColor];
 
360
 
 
361
        if (FrameView* view = frame->view()) {
 
362
            view->setTransparent(!drawsBackground);
 
363
            view->setBaseBackgroundColor(colorFromNSColor([backgroundColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]));
 
364
            view->setShouldUpdateWhileOffscreen([webView shouldUpdateWhileOffscreen]);
 
365
        }
 
366
    }
 
367
}
 
368
 
 
369
- (void)_setInternalLoadDelegate:(id)internalLoadDelegate
 
370
{
 
371
    _private->internalLoadDelegate = internalLoadDelegate;
 
372
}
 
373
 
 
374
- (id)_internalLoadDelegate
 
375
{
 
376
    return _private->internalLoadDelegate;
 
377
}
 
378
 
 
379
- (void)_unmarkAllBadGrammar
 
380
{
 
381
    Frame* coreFrame = _private->coreFrame;
 
382
    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
 
383
        if (Document* document = frame->document())
 
384
            document->markers()->removeMarkers(DocumentMarker::Grammar);
 
385
    }
 
386
}
 
387
 
 
388
- (void)_unmarkAllMisspellings
 
389
{
 
390
    Frame* coreFrame = _private->coreFrame;
 
391
    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
 
392
        if (Document* document = frame->document())
 
393
            document->markers()->removeMarkers(DocumentMarker::Spelling);
 
394
    }
 
395
}
 
396
 
 
397
- (BOOL)_hasSelection
 
398
{
 
399
    id documentView = [_private->webFrameView documentView];    
 
400
 
 
401
    // optimization for common case to avoid creating potentially large selection string
 
402
    if ([documentView isKindOfClass:[WebHTMLView class]])
 
403
        if (Frame* coreFrame = _private->coreFrame)
 
404
            return coreFrame->selection()->isRange();
 
405
 
 
406
    if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
 
407
        return [[documentView selectedString] length] > 0;
 
408
    
 
409
    return NO;
 
410
}
 
411
 
 
412
- (void)_clearSelection
 
413
{
 
414
    id documentView = [_private->webFrameView documentView];    
 
415
    if ([documentView conformsToProtocol:@protocol(WebDocumentText)])
 
416
        [documentView deselectAll];
 
417
}
 
418
 
 
419
#if !ASSERT_DISABLED
 
420
- (BOOL)_atMostOneFrameHasSelection
 
421
{
 
422
    // FIXME: 4186050 is one known case that makes this debug check fail.
 
423
    BOOL found = NO;
 
424
    Frame* coreFrame = _private->coreFrame;
 
425
    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame))
 
426
        if ([kit(frame) _hasSelection]) {
 
427
            if (found)
 
428
                return NO;
 
429
            found = YES;
 
430
        }
 
431
    return YES;
 
432
}
 
433
#endif
 
434
 
 
435
- (WebFrame *)_findFrameWithSelection
 
436
{
 
437
    Frame* coreFrame = _private->coreFrame;
 
438
    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
 
439
        WebFrame *webFrame = kit(frame);
 
440
        if ([webFrame _hasSelection])
 
441
            return webFrame;
 
442
    }
 
443
    return nil;
 
444
}
 
445
 
 
446
- (void)_clearSelectionInOtherFrames
 
447
{
 
448
    // We rely on WebDocumentSelection protocol implementors to call this method when they become first 
 
449
    // responder. It would be nicer to just notice first responder changes here instead, but there's no 
 
450
    // notification sent when the first responder changes in general (Radar 2573089).
 
451
    WebFrame *frameWithSelection = [[getWebView(self) mainFrame] _findFrameWithSelection];
 
452
    if (frameWithSelection != self)
 
453
        [frameWithSelection _clearSelection];
 
454
 
 
455
    // While we're in the general area of selection and frames, check that there is only one now.
 
456
    ASSERT([[getWebView(self) mainFrame] _atMostOneFrameHasSelection]);
 
457
}
 
458
 
 
459
static inline WebDataSource *dataSource(DocumentLoader* loader)
 
460
{
 
461
    return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
 
462
}
 
463
 
 
464
- (WebDataSource *)_dataSource
 
465
{
 
466
    return dataSource(_private->coreFrame->loader()->documentLoader());
 
467
}
 
468
 
 
469
- (NSString *)_stringWithDocumentTypeStringAndMarkupString:(NSString *)markupString
 
470
{
 
471
    return String(_private->coreFrame->documentTypeString() + String(markupString));
 
472
}
 
473
 
 
474
- (NSArray *)_nodesFromList:(Vector<Node*> *)nodesVector
 
475
{
 
476
    size_t size = nodesVector->size();
 
477
    NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:size];
 
478
    for (size_t i = 0; i < size; ++i)
 
479
        [nodes addObject:kit((*nodesVector)[i])];
 
480
    return nodes;
 
481
}
 
482
 
 
483
- (NSString *)_markupStringFromRange:(DOMRange *)range nodes:(NSArray **)nodes
 
484
{
 
485
    // FIXME: This is always "for interchange". Is that right? See the previous method.
 
486
    Vector<Node*> nodeList;
 
487
    NSString *markupString = createMarkup(core(range), nodes ? &nodeList : 0, AnnotateForInterchange);
 
488
    if (nodes)
 
489
        *nodes = [self _nodesFromList:&nodeList];
 
490
 
 
491
    return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
 
492
}
 
493
 
 
494
- (NSString *)_selectedString
 
495
{
 
496
    return _private->coreFrame->displayStringModifiedByEncoding(_private->coreFrame->editor()->selectedText());
 
497
}
 
498
 
 
499
- (NSString *)_stringForRange:(DOMRange *)range
 
500
{
 
501
    return plainText(core(range), TextIteratorDefaultBehavior, true);
 
502
}
 
503
 
 
504
- (BOOL)_shouldFlattenCompositingLayers:(CGContextRef)context
 
505
{
 
506
    // -currentContextDrawingToScreen returns YES for bitmap contexts.
 
507
    BOOL isPrinting = ![NSGraphicsContext currentContextDrawingToScreen];
 
508
    if (isPrinting)
 
509
        return YES;
 
510
 
 
511
    if (!WKCGContextIsBitmapContext(context))
 
512
        return NO;
 
513
 
 
514
    // If we're drawing into a bitmap, we might be snapshotting, or drawing into a layer-backed view.
 
515
    id documentView = [_private->webFrameView documentView];
 
516
    if ([documentView isKindOfClass:[WebHTMLView class]] && [(WebHTMLView *)documentView _web_isDrawingIntoLayer])
 
517
        return NO;
 
518
 
 
519
    return [getWebView(self) _includesFlattenedCompositingLayersWhenDrawingToBitmap];
 
520
}
 
521
 
 
522
- (void)_drawRect:(NSRect)rect contentsOnly:(BOOL)contentsOnly
 
523
{
 
524
    ASSERT([[NSGraphicsContext currentContext] isFlipped]);
 
525
 
 
526
    CGContextRef ctx = static_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]);
 
527
    GraphicsContext context(ctx);
 
528
 
 
529
    FrameView* view = _private->coreFrame->view();
 
530
    
 
531
    bool shouldFlatten = false;
 
532
    if (Frame* parentFrame = _private->coreFrame->tree()->parent()) {
 
533
        // For subframes, we need to inherit the paint behavior from our parent
 
534
        FrameView* parentView = parentFrame ? parentFrame->view() : 0;
 
535
        if (parentView)
 
536
            shouldFlatten = parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
 
537
    } else
 
538
        shouldFlatten = [self _shouldFlattenCompositingLayers:ctx];
 
539
 
 
540
    PaintBehavior oldBehavior = PaintBehaviorNormal;
 
541
    if (shouldFlatten) {
 
542
        oldBehavior = view->paintBehavior();
 
543
        view->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
 
544
    }
 
545
    
 
546
    if (contentsOnly)
 
547
        view->paintContents(&context, enclosingIntRect(rect));
 
548
    else
 
549
        view->paint(&context, enclosingIntRect(rect));
 
550
 
 
551
    if (shouldFlatten)
 
552
        view->setPaintBehavior(oldBehavior);
 
553
}
 
554
 
 
555
- (BOOL)_getVisibleRect:(NSRect*)rect
 
556
{
 
557
    ASSERT_ARG(rect, rect);
 
558
    if (RenderPart* ownerRenderer = _private->coreFrame->ownerRenderer()) {
 
559
        if (ownerRenderer->needsLayout())
 
560
            return NO;
 
561
        *rect = ownerRenderer->pixelSnappedAbsoluteClippedOverflowRect();
 
562
        return YES;
 
563
    }
 
564
 
 
565
    return NO;
 
566
}
 
567
 
 
568
- (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string
 
569
{
 
570
    return [self _stringByEvaluatingJavaScriptFromString:string forceUserGesture:true];
 
571
}
 
572
 
 
573
- (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture
 
574
{
 
575
    if (!string)
 
576
        return @"";
 
577
 
 
578
    ASSERT(_private->coreFrame->document());
 
579
    RetainPtr<WebFrame> protect(self); // Executing arbitrary JavaScript can destroy the frame.
 
580
    
 
581
    JSValue result = _private->coreFrame->script()->executeScript(string, forceUserGesture).jsValue();
 
582
 
 
583
    if (!_private->coreFrame) // In case the script removed our frame from the page.
 
584
        return @"";
 
585
 
 
586
    // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
 
587
    // If you don't like it, use -[WebScriptObject evaluateWebScript:] or 
 
588
    // JSEvaluateScript instead, since they have less surprising semantics.
 
589
    if (!result || (!result.isBoolean() && !result.isString() && !result.isNumber()))
 
590
        return @"";
 
591
 
 
592
    JSC::ExecState* exec = _private->coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec();
 
593
    JSC::JSLockHolder lock(exec);
 
594
    return result.toWTFString(exec);
 
595
}
 
596
 
 
597
- (NSRect)_caretRectAtPosition:(const Position&)pos affinity:(NSSelectionAffinity)affinity
 
598
{
 
599
    VisiblePosition visiblePosition(pos, static_cast<EAffinity>(affinity));
 
600
    return visiblePosition.absoluteCaretBounds();
 
601
}
 
602
 
 
603
- (NSRect)_firstRectForDOMRange:(DOMRange *)range
 
604
{
 
605
   return _private->coreFrame->editor()->firstRectForRange(core(range));
 
606
}
 
607
 
 
608
- (void)_scrollDOMRangeToVisible:(DOMRange *)range
 
609
{
 
610
    NSRect rangeRect = [self _firstRectForDOMRange:range];    
 
611
    Node *startNode = core([range startContainer]);
 
612
        
 
613
    if (startNode && startNode->renderer())
 
614
        startNode->renderer()->scrollRectToVisible(enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
 
615
}
 
616
 
 
617
- (BOOL)_needsLayout
 
618
{
 
619
    return _private->coreFrame->view() ? _private->coreFrame->view()->needsLayout() : false;
 
620
}
 
621
 
 
622
- (DOMRange *)_rangeByAlteringCurrentSelection:(FrameSelection::EAlteration)alteration direction:(SelectionDirection)direction granularity:(TextGranularity)granularity
 
623
{
 
624
    if (_private->coreFrame->selection()->isNone())
 
625
        return nil;
 
626
 
 
627
    FrameSelection selection;
 
628
    selection.setSelection(_private->coreFrame->selection()->selection());
 
629
    selection.modify(alteration, direction, granularity);
 
630
    return kit(selection.toNormalizedRange().get());
 
631
}
 
632
 
 
633
- (TextGranularity)_selectionGranularity
 
634
{
 
635
    return _private->coreFrame->selection()->granularity();
 
636
}
 
637
 
 
638
- (NSRange)_convertToNSRange:(Range *)range
 
639
{
 
640
    if (!range)
 
641
        return NSMakeRange(NSNotFound, 0);
 
642
 
 
643
    size_t location;
 
644
    size_t length;
 
645
    if (!TextIterator::getLocationAndLengthFromRange(_private->coreFrame->selection()->rootEditableElementOrDocumentElement(), range, location, length))
 
646
        return NSMakeRange(NSNotFound, 0);
 
647
 
 
648
    return NSMakeRange(location, length);
 
649
}
 
650
 
 
651
- (PassRefPtr<Range>)_convertToDOMRange:(NSRange)nsrange
 
652
{
 
653
    if (nsrange.location > INT_MAX)
 
654
        return 0;
 
655
    if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX)
 
656
        nsrange.length = INT_MAX - nsrange.location;
 
657
 
 
658
    // our critical assumption is that we are only called by input methods that
 
659
    // concentrate on a given area containing the selection
 
660
    // We have to do this because of text fields and textareas. The DOM for those is not
 
661
    // directly in the document DOM, so serialization is problematic. Our solution is
 
662
    // to use the root editable element of the selection start as the positional base.
 
663
    // That fits with AppKit's idea of an input context.
 
664
    return TextIterator::rangeFromLocationAndLength(_private->coreFrame->selection()->rootEditableElementOrDocumentElement(), nsrange.location, nsrange.length);
 
665
}
 
666
 
 
667
- (DOMRange *)_convertNSRangeToDOMRange:(NSRange)nsrange
 
668
{
 
669
    return kit([self _convertToDOMRange:nsrange].get());
 
670
}
 
671
 
 
672
- (NSRange)_convertDOMRangeToNSRange:(DOMRange *)range
 
673
{
 
674
    return [self _convertToNSRange:core(range)];
 
675
}
 
676
 
 
677
- (DOMRange *)_markDOMRange
 
678
{
 
679
    return kit(_private->coreFrame->editor()->mark().toNormalizedRange().get());
 
680
}
 
681
 
 
682
// Given proposedRange, returns an extended range that includes adjacent whitespace that should
 
683
// be deleted along with the proposed range in order to preserve proper spacing and punctuation of
 
684
// the text surrounding the deletion.
 
685
- (DOMRange *)_smartDeleteRangeForProposedRange:(DOMRange *)proposedRange
 
686
{
 
687
    Node* startContainer = core([proposedRange startContainer]);
 
688
    Node* endContainer = core([proposedRange endContainer]);
 
689
    if (startContainer == nil || endContainer == nil)
 
690
        return nil;
 
691
 
 
692
    ASSERT(startContainer->document() == endContainer->document());
 
693
    
 
694
    _private->coreFrame->document()->updateLayoutIgnorePendingStylesheets();
 
695
 
 
696
    Position start = Position(startContainer, [proposedRange startOffset], Position::PositionIsOffsetInAnchor);
 
697
    Position end = Position(endContainer, [proposedRange endOffset], Position::PositionIsOffsetInAnchor);
 
698
    Position newStart = start.upstream().leadingWhitespacePosition(DOWNSTREAM, true);
 
699
    if (newStart.isNull())
 
700
        newStart = start;
 
701
    Position newEnd = end.downstream().trailingWhitespacePosition(DOWNSTREAM, true);
 
702
    if (newEnd.isNull())
 
703
        newEnd = end;
 
704
 
 
705
    newStart = newStart.parentAnchoredEquivalent();
 
706
    newEnd = newEnd.parentAnchoredEquivalent();
 
707
 
 
708
    RefPtr<Range> range = _private->coreFrame->document()->createRange();
 
709
    int exception = 0;
 
710
    range->setStart(newStart.containerNode(), newStart.offsetInContainerNode(), exception);
 
711
    range->setEnd(newStart.containerNode(), newStart.offsetInContainerNode(), exception);
 
712
    return kit(range.get());
 
713
}
 
714
 
 
715
- (DOMDocumentFragment *)_documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString 
 
716
{
 
717
    if (!_private->coreFrame || !_private->coreFrame->document())
 
718
        return nil;
 
719
 
 
720
    return kit(createFragmentFromMarkup(_private->coreFrame->document(), markupString, baseURLString, DisallowScriptingContent).get());
 
721
}
 
722
 
 
723
- (DOMDocumentFragment *)_documentFragmentWithNodesAsParagraphs:(NSArray *)nodes
 
724
{
 
725
    if (!_private->coreFrame || !_private->coreFrame->document())
 
726
        return nil;
 
727
    
 
728
    NSEnumerator *nodeEnum = [nodes objectEnumerator];
 
729
    Vector<Node*> nodesVector;
 
730
    DOMNode *node;
 
731
    while ((node = [nodeEnum nextObject]))
 
732
        nodesVector.append(core(node));
 
733
    
 
734
    return kit(createFragmentFromNodes(_private->coreFrame->document(), nodesVector).get());
 
735
}
 
736
 
 
737
- (void)_replaceSelectionWithNode:(DOMNode *)node selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
 
738
{
 
739
    DOMDocumentFragment *fragment = kit(_private->coreFrame->document()->createDocumentFragment().get());
 
740
    [fragment appendChild:node];
 
741
    [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:matchStyle];
 
742
}
 
743
 
 
744
- (void)_insertParagraphSeparatorInQuotedContent
 
745
{
 
746
    if (_private->coreFrame->selection()->isNone())
 
747
        return;
 
748
 
 
749
    _private->coreFrame->editor()->insertParagraphSeparatorInQuotedContent();
 
750
}
 
751
 
 
752
- (VisiblePosition)_visiblePositionForPoint:(NSPoint)point
 
753
{
 
754
    // FIXME: Someone with access to Apple's sources could remove this needless wrapper call.
 
755
    return _private->coreFrame->visiblePositionForPoint(IntPoint(point));
 
756
}
 
757
 
 
758
- (DOMRange *)_characterRangeAtPoint:(NSPoint)point
 
759
{
 
760
    return kit(_private->coreFrame->rangeForPoint(IntPoint(point)).get());
 
761
}
 
762
 
 
763
- (DOMCSSStyleDeclaration *)_typingStyle
 
764
{
 
765
    if (!_private->coreFrame)
 
766
        return nil;
 
767
    RefPtr<StylePropertySet> typingStyle = _private->coreFrame->selection()->copyTypingStyle();
 
768
    if (!typingStyle)
 
769
        return nil;
 
770
    return kit(typingStyle->ensureCSSStyleDeclaration());
 
771
}
 
772
 
 
773
- (void)_setTypingStyle:(DOMCSSStyleDeclaration *)style withUndoAction:(EditAction)undoAction
 
774
{
 
775
    if (!_private->coreFrame || !style)
 
776
        return;
 
777
    // FIXME: We shouldn't have to create a copy here.
 
778
    _private->coreFrame->editor()->computeAndSetTypingStyle(core(style)->copy().get(), undoAction);
 
779
}
 
780
 
 
781
#if ENABLE(DRAG_SUPPORT)
 
782
- (void)_dragSourceEndedAt:(NSPoint)windowLoc operation:(NSDragOperation)operation
 
783
{
 
784
    if (!_private->coreFrame)
 
785
        return;
 
786
    FrameView* view = _private->coreFrame->view();
 
787
    if (!view)
 
788
        return;
 
789
    // FIXME: These are fake modifier keys here, but they should be real ones instead.
 
790
    PlatformMouseEvent event(IntPoint(windowLoc), globalPoint(windowLoc, [view->platformWidget() window]),
 
791
        LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, currentTime());
 
792
    _private->coreFrame->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation);
 
793
}
 
794
#endif
 
795
 
 
796
- (BOOL)_canProvideDocumentSource
 
797
{
 
798
    Frame* frame = _private->coreFrame;
 
799
    String mimeType = frame->document()->loader()->writer()->mimeType();
 
800
    PluginData* pluginData = frame->page() ? frame->page()->pluginData() : 0;
 
801
 
 
802
    if (WebCore::DOMImplementation::isTextMIMEType(mimeType) ||
 
803
        Image::supportsType(mimeType) ||
 
804
        (pluginData && pluginData->supportsMimeType(mimeType)))
 
805
        return NO;
 
806
 
 
807
    return YES;
 
808
}
 
809
 
 
810
- (BOOL)_canSaveAsWebArchive
 
811
{
 
812
    // Currently, all documents that we can view source for
 
813
    // (HTML and XML documents) can also be saved as web archives
 
814
    return [self _canProvideDocumentSource];
 
815
}
 
816
 
 
817
- (void)_commitData:(NSData *)data
 
818
{
 
819
    // FIXME: This really should be a setting.
 
820
    Document* document = _private->coreFrame->document();
 
821
    document->setShouldCreateRenderers(_private->shouldCreateRenderers);
 
822
 
 
823
    _private->coreFrame->loader()->documentLoader()->commitData((const char *)[data bytes], [data length]);
 
824
}
 
825
 
 
826
@end
 
827
 
 
828
@implementation WebFrame (WebPrivate)
 
829
 
 
830
// FIXME: This exists only as a convenience for Safari, consider moving there.
 
831
- (BOOL)_isDescendantOfFrame:(WebFrame *)ancestor
 
832
{
 
833
    Frame* coreFrame = _private->coreFrame;
 
834
    return coreFrame && coreFrame->tree()->isDescendantOf(core(ancestor));
 
835
}
 
836
 
 
837
- (void)_setShouldCreateRenderers:(BOOL)shouldCreateRenderers
 
838
{
 
839
    _private->shouldCreateRenderers = shouldCreateRenderers;
 
840
}
 
841
 
 
842
- (NSColor *)_bodyBackgroundColor
 
843
{
 
844
    Document* document = _private->coreFrame->document();
 
845
    if (!document)
 
846
        return nil;
 
847
    HTMLElement* body = document->body();
 
848
    if (!body)
 
849
        return nil;
 
850
    RenderObject* bodyRenderer = body->renderer();
 
851
    if (!bodyRenderer)
 
852
        return nil;
 
853
    Color color = bodyRenderer->style()->visitedDependentColor(CSSPropertyBackgroundColor);
 
854
    if (!color.isValid())
 
855
        return nil;
 
856
    return nsColor(color);
 
857
}
 
858
 
 
859
- (BOOL)_isFrameSet
 
860
{
 
861
    Document* document = _private->coreFrame->document();
 
862
    return document && document->isFrameSet();
 
863
}
 
864
 
 
865
- (BOOL)_firstLayoutDone
 
866
{
 
867
    return _private->coreFrame->loader()->stateMachine()->firstLayoutDone();
 
868
}
 
869
 
 
870
- (BOOL)_isVisuallyNonEmpty
 
871
{
 
872
    if (FrameView* view = _private->coreFrame->view())
 
873
        return view->isVisuallyNonEmpty();
 
874
    return NO;
 
875
}
 
876
 
 
877
- (WebFrameLoadType)_loadType
 
878
{
 
879
    return (WebFrameLoadType)_private->coreFrame->loader()->loadType();
 
880
}
 
881
 
 
882
- (NSRange)_selectedNSRange
 
883
{
 
884
    return [self _convertToNSRange:_private->coreFrame->selection()->toNormalizedRange().get()];
 
885
}
 
886
 
 
887
- (void)_selectNSRange:(NSRange)range
 
888
{
 
889
    RefPtr<Range> domRange = [self _convertToDOMRange:range];
 
890
    if (domRange)
 
891
        _private->coreFrame->selection()->setSelection(VisibleSelection(domRange.get(), SEL_DEFAULT_AFFINITY));
 
892
}
 
893
 
 
894
- (BOOL)_isDisplayingStandaloneImage
 
895
{
 
896
    Document* document = _private->coreFrame->document();
 
897
    return document && document->isImageDocument();
 
898
}
 
899
 
 
900
- (unsigned)_pendingFrameUnloadEventCount
 
901
{
 
902
    return _private->coreFrame->document()->domWindow()->pendingUnloadEventListeners();
 
903
}
 
904
 
 
905
#if ENABLE(NETSCAPE_PLUGIN_API)
 
906
- (void)_recursive_resumeNullEventsForAllNetscapePlugins
 
907
{
 
908
    Frame* coreFrame = core(self);
 
909
    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
 
910
        NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
 
911
        if ([documentView isKindOfClass:[WebHTMLView class]])
 
912
            [(WebHTMLView *)documentView _resumeNullEventsForAllNetscapePlugins];
 
913
    }
 
914
}
 
915
 
 
916
- (void)_recursive_pauseNullEventsForAllNetscapePlugins
 
917
{
 
918
    Frame* coreFrame = core(self);
 
919
    for (Frame* frame = coreFrame; frame; frame = frame->tree()->traverseNext(coreFrame)) {
 
920
        NSView <WebDocumentView> *documentView = [[kit(frame) frameView] documentView];
 
921
        if ([documentView isKindOfClass:[WebHTMLView class]])
 
922
            [(WebHTMLView *)documentView _pauseNullEventsForAllNetscapePlugins];
 
923
    }
 
924
}
 
925
#endif
 
926
 
 
927
- (BOOL)_pauseAnimation:(NSString*)name onNode:(DOMNode *)node atTime:(NSTimeInterval)time
 
928
{
 
929
    Frame* frame = core(self);
 
930
    if (!frame)
 
931
        return false;
 
932
 
 
933
    AnimationController* controller = frame->animation();
 
934
    if (!controller)
 
935
        return false;
 
936
 
 
937
    Node* coreNode = core(node);
 
938
    if (!coreNode || !coreNode->renderer())
 
939
        return false;
 
940
 
 
941
    return controller->pauseAnimationAtTime(coreNode->renderer(), name, time);
 
942
}
 
943
 
 
944
- (BOOL)_pauseTransitionOfProperty:(NSString*)name onNode:(DOMNode*)node atTime:(NSTimeInterval)time
 
945
{
 
946
    Frame* frame = core(self);
 
947
    if (!frame)
 
948
        return false;
 
949
 
 
950
    AnimationController* controller = frame->animation();
 
951
    if (!controller)
 
952
        return false;
 
953
 
 
954
    Node* coreNode = core(node);
 
955
    if (!coreNode || !coreNode->renderer())
 
956
        return false;
 
957
 
 
958
    return controller->pauseTransitionAtTime(coreNode->renderer(), name, time);
 
959
}
 
960
 
 
961
- (unsigned) _numberOfActiveAnimations
 
962
{
 
963
    Frame* frame = core(self);
 
964
    if (!frame)
 
965
        return false;
 
966
 
 
967
    AnimationController* controller = frame->animation();
 
968
    if (!controller)
 
969
        return false;
 
970
 
 
971
    return controller->numberOfActiveAnimations(frame->document());
 
972
}
 
973
 
 
974
- (void)_replaceSelectionWithFragment:(DOMDocumentFragment *)fragment selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace matchStyle:(BOOL)matchStyle
 
975
{
 
976
    if (_private->coreFrame->selection()->isNone() || !fragment)
 
977
        return;
 
978
    _private->coreFrame->editor()->replaceSelectionWithFragment(core(fragment), selectReplacement, smartReplace, matchStyle);
 
979
}
 
980
 
 
981
- (void)_replaceSelectionWithText:(NSString *)text selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
 
982
{   
 
983
    DOMDocumentFragment* fragment = kit(createFragmentFromText(_private->coreFrame->selection()->toNormalizedRange().get(), text).get());
 
984
    [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:YES];
 
985
}
 
986
 
 
987
- (void)_replaceSelectionWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString selectReplacement:(BOOL)selectReplacement smartReplace:(BOOL)smartReplace
 
988
{
 
989
    DOMDocumentFragment *fragment = [self _documentFragmentWithMarkupString:markupString baseURLString:baseURLString];
 
990
    [self _replaceSelectionWithFragment:fragment selectReplacement:selectReplacement smartReplace:smartReplace matchStyle:NO];
 
991
}
 
992
 
 
993
// Determines whether whitespace needs to be added around aString to preserve proper spacing and
 
994
// punctuation when it's inserted into the receiver's text over charRange. Returns by reference
 
995
// in beforeString and afterString any whitespace that should be added, unless either or both are
 
996
// nil. Both are returned as nil if aString is nil or if smart insertion and deletion are disabled.
 
997
- (void)_smartInsertForString:(NSString *)pasteString replacingRange:(DOMRange *)rangeToReplace beforeString:(NSString **)beforeString afterString:(NSString **)afterString
 
998
{
 
999
    // give back nil pointers in case of early returns
 
1000
    if (beforeString)
 
1001
        *beforeString = nil;
 
1002
    if (afterString)
 
1003
        *afterString = nil;
 
1004
        
 
1005
    // inspect destination
 
1006
    Node *startContainer = core([rangeToReplace startContainer]);
 
1007
    Node *endContainer = core([rangeToReplace endContainer]);
 
1008
 
 
1009
    Position startPos(startContainer, [rangeToReplace startOffset], Position::PositionIsOffsetInAnchor);
 
1010
    Position endPos(endContainer, [rangeToReplace endOffset], Position::PositionIsOffsetInAnchor);
 
1011
 
 
1012
    VisiblePosition startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY);
 
1013
    VisiblePosition endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY);
 
1014
    
 
1015
    // this check also ensures startContainer, startPos, endContainer, and endPos are non-null
 
1016
    if (startVisiblePos.isNull() || endVisiblePos.isNull())
 
1017
        return;
 
1018
 
 
1019
    bool addLeadingSpace = startPos.leadingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isStartOfParagraph(startVisiblePos);
 
1020
    if (addLeadingSpace)
 
1021
        if (UChar previousChar = startVisiblePos.previous().characterAfter())
 
1022
            addLeadingSpace = !isCharacterSmartReplaceExempt(previousChar, true);
 
1023
    
 
1024
    bool addTrailingSpace = endPos.trailingWhitespacePosition(VP_DEFAULT_AFFINITY, true).isNull() && !isEndOfParagraph(endVisiblePos);
 
1025
    if (addTrailingSpace)
 
1026
        if (UChar thisChar = endVisiblePos.characterAfter())
 
1027
            addTrailingSpace = !isCharacterSmartReplaceExempt(thisChar, false);
 
1028
    
 
1029
    // inspect source
 
1030
    bool hasWhitespaceAtStart = false;
 
1031
    bool hasWhitespaceAtEnd = false;
 
1032
    unsigned pasteLength = [pasteString length];
 
1033
    if (pasteLength > 0) {
 
1034
        NSCharacterSet *whiteSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
 
1035
        
 
1036
        if ([whiteSet characterIsMember:[pasteString characterAtIndex:0]]) {
 
1037
            hasWhitespaceAtStart = YES;
 
1038
        }
 
1039
        if ([whiteSet characterIsMember:[pasteString characterAtIndex:(pasteLength - 1)]]) {
 
1040
            hasWhitespaceAtEnd = YES;
 
1041
        }
 
1042
    }
 
1043
    
 
1044
    // issue the verdict
 
1045
    if (beforeString && addLeadingSpace && !hasWhitespaceAtStart)
 
1046
        *beforeString = @" ";
 
1047
    if (afterString && addTrailingSpace && !hasWhitespaceAtEnd)
 
1048
        *afterString = @" ";
 
1049
}
 
1050
 
 
1051
- (NSMutableDictionary *)_cacheabilityDictionary
 
1052
{
 
1053
    NSMutableDictionary *result = [NSMutableDictionary dictionary];
 
1054
    
 
1055
    FrameLoader* frameLoader = _private->coreFrame->loader();
 
1056
    DocumentLoader* documentLoader = frameLoader->documentLoader();
 
1057
    if (documentLoader && !documentLoader->mainDocumentError().isNull())
 
1058
        [result setObject:(NSError *)documentLoader->mainDocumentError() forKey:WebFrameMainDocumentError];
 
1059
        
 
1060
    if (frameLoader->subframeLoader()->containsPlugins())
 
1061
        [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasPlugins];
 
1062
    
 
1063
    if (DOMWindow* domWindow = _private->coreFrame->document()->domWindow()) {
 
1064
        if (domWindow->hasEventListeners(eventNames().unloadEvent))
 
1065
            [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameHasUnloadListener];
 
1066
        if (domWindow->optionalApplicationCache())
 
1067
            [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesApplicationCache];
 
1068
    }
 
1069
    
 
1070
    if (Document* document = _private->coreFrame->document()) {
 
1071
#if ENABLE(SQL_DATABASE)
 
1072
        if (DatabaseContext::hasOpenDatabases(document))
 
1073
            [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameUsesDatabases];
 
1074
#endif
 
1075
        if (!document->canSuspendActiveDOMObjects())
 
1076
            [result setObject:[NSNumber numberWithBool:YES] forKey:WebFrameCanSuspendActiveDOMObjects];
 
1077
    }
 
1078
    
 
1079
    return result;
 
1080
}
 
1081
 
 
1082
- (BOOL)_allowsFollowingLink:(NSURL *)URL
 
1083
{
 
1084
    if (!_private->coreFrame)
 
1085
        return YES;
 
1086
    return _private->coreFrame->document()->securityOrigin()->canDisplay(URL);
 
1087
}
 
1088
 
 
1089
- (NSString *)_stringByEvaluatingJavaScriptFromString:(NSString *)string withGlobalObject:(JSObjectRef)globalObjectRef inScriptWorld:(WebScriptWorld *)world
 
1090
{
 
1091
    if (!string)
 
1092
        return @"";
 
1093
 
 
1094
    // Start off with some guess at a frame and a global object, we'll try to do better...!
 
1095
    JSDOMWindow* anyWorldGlobalObject = _private->coreFrame->script()->globalObject(mainThreadNormalWorld());
 
1096
 
 
1097
    // The global object is probably a shell object? - if so, we know how to use this!
 
1098
    JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
 
1099
    if (!strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell"))
 
1100
        anyWorldGlobalObject = static_cast<JSDOMWindowShell*>(globalObjectObj)->window();
 
1101
 
 
1102
    // Get the frame frome the global object we've settled on.
 
1103
    Frame* frame = anyWorldGlobalObject->impl()->frame();
 
1104
    ASSERT(frame->document());
 
1105
    RetainPtr<WebFrame> webFrame(kit(frame)); // Running arbitrary JavaScript can destroy the frame.
 
1106
 
 
1107
    JSValue result = frame->script()->executeScriptInWorld(core(world), string, true).jsValue();
 
1108
 
 
1109
    if (!webFrame->_private->coreFrame) // In case the script removed our frame from the page.
 
1110
        return @"";
 
1111
 
 
1112
    // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
 
1113
    // If you don't like it, use -[WebScriptObject evaluateWebScript:] or 
 
1114
    // JSEvaluateScript instead, since they have less surprising semantics.
 
1115
    if (!result || (!result.isBoolean() && !result.isString() && !result.isNumber()))
 
1116
        return @"";
 
1117
 
 
1118
    JSC::ExecState* exec = anyWorldGlobalObject->globalExec();
 
1119
    JSC::JSLockHolder lock(exec);
 
1120
    return result.toWTFString(exec);
 
1121
}
 
1122
 
 
1123
- (JSGlobalContextRef)_globalContextForScriptWorld:(WebScriptWorld *)world
 
1124
{
 
1125
    Frame* coreFrame = _private->coreFrame;
 
1126
    if (!coreFrame)
 
1127
        return 0;
 
1128
    DOMWrapperWorld* coreWorld = core(world);
 
1129
    if (!coreWorld)
 
1130
        return 0;
 
1131
    return toGlobalRef(coreFrame->script()->globalObject(coreWorld)->globalExec());
 
1132
}
 
1133
 
 
1134
- (void)setAllowsScrollersToOverlapContent:(BOOL)flag
 
1135
{
 
1136
    ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
 
1137
    [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAllowsScrollersToOverlapContent:flag];
 
1138
}
 
1139
 
 
1140
- (void)setAlwaysHideHorizontalScroller:(BOOL)flag
 
1141
{
 
1142
    ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
 
1143
    [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAlwaysHideHorizontalScroller:flag];
 
1144
}
 
1145
- (void)setAlwaysHideVerticalScroller:(BOOL)flag
 
1146
{
 
1147
    ASSERT([[[self frameView] _scrollView] isKindOfClass:[WebDynamicScrollBarsView class]]);
 
1148
    [(WebDynamicScrollBarsView *)[[self frameView] _scrollView] setAlwaysHideVerticalScroller:flag];
 
1149
}
 
1150
 
 
1151
- (void)setAccessibleName:(NSString *)name
 
1152
{
 
1153
#if HAVE(ACCESSIBILITY)
 
1154
    if (!AXObjectCache::accessibilityEnabled())
 
1155
        return;
 
1156
    
 
1157
    if (!_private->coreFrame || !_private->coreFrame->document())
 
1158
        return;
 
1159
    
 
1160
    AccessibilityObject* rootObject = _private->coreFrame->document()->axObjectCache()->rootObject();
 
1161
    if (rootObject) {
 
1162
        String strName(name);
 
1163
        rootObject->setAccessibleName(strName);
 
1164
    }
 
1165
#endif
 
1166
}
 
1167
 
 
1168
- (NSString*)_layerTreeAsText
 
1169
{
 
1170
    Frame* coreFrame = _private->coreFrame;
 
1171
    if (!coreFrame)
 
1172
        return @"";
 
1173
 
 
1174
    return coreFrame->layerTreeAsText();
 
1175
}
 
1176
 
 
1177
- (id)accessibilityRoot
 
1178
{
 
1179
#if HAVE(ACCESSIBILITY)
 
1180
    if (!AXObjectCache::accessibilityEnabled()) {
 
1181
        AXObjectCache::enableAccessibility();
 
1182
        AXObjectCache::setEnhancedUserInterfaceAccessibility([[NSApp accessibilityAttributeValue:NSAccessibilityEnhancedUserInterfaceAttribute] boolValue]);
 
1183
    }
 
1184
    
 
1185
    if (!_private->coreFrame || !_private->coreFrame->document())
 
1186
        return nil;
 
1187
    
 
1188
    AccessibilityObject* rootObject = _private->coreFrame->document()->axObjectCache()->rootObjectForFrame(_private->coreFrame);
 
1189
    if (!rootObject)
 
1190
        return nil;
 
1191
    
 
1192
    // The root object will be a WebCore scroll view object. In WK1, scroll views are handled
 
1193
    // by the system and the root object should be the web area (instead of the scroll view).
 
1194
    if (rootObject->isAttachment() && rootObject->firstChild())
 
1195
        return rootObject->firstChild()->wrapper();
 
1196
    
 
1197
    return rootObject->wrapper();
 
1198
#else
 
1199
    return nil;
 
1200
#endif
 
1201
}
 
1202
 
 
1203
- (void)_clearOpener
 
1204
{
 
1205
    Frame* coreFrame = _private->coreFrame;
 
1206
    if (coreFrame)
 
1207
        coreFrame->loader()->setOpener(0);
 
1208
}
 
1209
 
 
1210
// Used by pagination code called from AppKit when a standalone web page is printed.
 
1211
- (NSArray *)_computePageRectsWithPrintScaleFactor:(float)printScaleFactor pageSize:(NSSize)pageSize
 
1212
{
 
1213
    if (printScaleFactor <= 0) {
 
1214
        LOG_ERROR("printScaleFactor has bad value %.2f", printScaleFactor);
 
1215
        return [NSArray array];
 
1216
    }
 
1217
 
 
1218
    if (!_private->coreFrame)
 
1219
        return [NSArray array];
 
1220
    if (!_private->coreFrame->document())
 
1221
        return [NSArray array];
 
1222
    if (!_private->coreFrame->view())
 
1223
        return [NSArray array];
 
1224
    if (!_private->coreFrame->view()->documentView())
 
1225
        return [NSArray array];
 
1226
 
 
1227
    RenderView* root = toRenderView(_private->coreFrame->document()->renderer());
 
1228
    if (!root)
 
1229
        return [NSArray array];
 
1230
 
 
1231
    const LayoutRect& documentRect = root->documentRect();
 
1232
    float printWidth = root->style()->isHorizontalWritingMode() ? static_cast<float>(documentRect.width()) / printScaleFactor : pageSize.width;
 
1233
    float printHeight = root->style()->isHorizontalWritingMode() ? pageSize.height : static_cast<float>(documentRect.height()) / printScaleFactor;
 
1234
 
 
1235
    PrintContext printContext(_private->coreFrame);
 
1236
    printContext.computePageRectsWithPageSize(FloatSize(printWidth, printHeight), true);
 
1237
    const Vector<IntRect>& pageRects = printContext.pageRects();
 
1238
 
 
1239
    size_t size = pageRects.size();
 
1240
    NSMutableArray *pages = [NSMutableArray arrayWithCapacity:size];
 
1241
    for (size_t i = 0; i < size; ++i)
 
1242
        [pages addObject:[NSValue valueWithRect:NSRect(pageRects[i])]];
 
1243
    return pages;
 
1244
}
 
1245
 
 
1246
@end
 
1247
 
 
1248
@implementation WebFrame
 
1249
 
 
1250
- (id)init
 
1251
{
 
1252
    return nil;
 
1253
}
 
1254
 
 
1255
// Should be deprecated.
 
1256
- (id)initWithName:(NSString *)name webFrameView:(WebFrameView *)view webView:(WebView *)webView
 
1257
{
 
1258
    return nil;
 
1259
}
 
1260
 
 
1261
- (void)dealloc
 
1262
{
 
1263
    if (_private && _private->includedInWebKitStatistics)
 
1264
        --WebFrameCount;
 
1265
 
 
1266
    [_private release];
 
1267
 
 
1268
    [super dealloc];
 
1269
}
 
1270
 
 
1271
- (void)finalize
 
1272
{
 
1273
    if (_private && _private->includedInWebKitStatistics)
 
1274
        --WebFrameCount;
 
1275
 
 
1276
    [super finalize];
 
1277
}
 
1278
 
 
1279
- (NSString *)name
 
1280
{
 
1281
    Frame* coreFrame = _private->coreFrame;
 
1282
    if (!coreFrame)
 
1283
        return nil;
 
1284
    return coreFrame->tree()->uniqueName();
 
1285
}
 
1286
 
 
1287
- (WebFrameView *)frameView
 
1288
{
 
1289
    return _private->webFrameView;
 
1290
}
 
1291
 
 
1292
- (WebView *)webView
 
1293
{
 
1294
    return getWebView(self);
 
1295
}
 
1296
 
 
1297
static bool needsMicrosoftMessengerDOMDocumentWorkaround()
 
1298
{
 
1299
    static bool needsWorkaround = applicationIsMicrosoftMessenger() && [[[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey] compare:@"7.1" options:NSNumericSearch] == NSOrderedAscending;
 
1300
    return needsWorkaround;
 
1301
}
 
1302
 
 
1303
- (DOMDocument *)DOMDocument
 
1304
{
 
1305
    if (needsMicrosoftMessengerDOMDocumentWorkaround() && !pthread_main_np())
 
1306
        return nil;
 
1307
 
 
1308
    Frame* coreFrame = _private->coreFrame;
 
1309
    if (!coreFrame)
 
1310
        return nil;
 
1311
    
 
1312
    // FIXME: <rdar://problem/5145841> When loading a custom view/representation 
 
1313
    // into a web frame, the old document can still be around. This makes sure that
 
1314
    // we'll return nil in those cases.
 
1315
    if (![[self _dataSource] _isDocumentHTML]) 
 
1316
        return nil; 
 
1317
 
 
1318
    Document* document = coreFrame->document();
 
1319
    
 
1320
    // According to the documentation, we should return nil if the frame doesn't have a document.
 
1321
    // While full-frame images and plugins do have an underlying HTML document, we return nil here to be
 
1322
    // backwards compatible.
 
1323
    if (document && (document->isPluginDocument() || document->isImageDocument()))
 
1324
        return nil;
 
1325
    
 
1326
    return kit(coreFrame->document());
 
1327
}
 
1328
 
 
1329
- (DOMHTMLElement *)frameElement
 
1330
{
 
1331
    Frame* coreFrame = _private->coreFrame;
 
1332
    if (!coreFrame)
 
1333
        return nil;
 
1334
    return kit(coreFrame->ownerElement());
 
1335
}
 
1336
 
 
1337
- (WebDataSource *)provisionalDataSource
 
1338
{
 
1339
    Frame* coreFrame = _private->coreFrame;
 
1340
    return coreFrame ? dataSource(coreFrame->loader()->provisionalDocumentLoader()) : nil;
 
1341
}
 
1342
 
 
1343
- (WebDataSource *)dataSource
 
1344
{
 
1345
    Frame* coreFrame = _private->coreFrame;
 
1346
    return coreFrame && coreFrame->loader()->frameHasLoaded() ? [self _dataSource] : nil;
 
1347
}
 
1348
 
 
1349
- (void)loadRequest:(NSURLRequest *)request
 
1350
{
 
1351
    Frame* coreFrame = _private->coreFrame;
 
1352
    if (!coreFrame)
 
1353
        return;
 
1354
 
 
1355
    ResourceRequest resourceRequest(request);
 
1356
    
 
1357
    // Some users of WebKit API incorrectly use "file path as URL" style requests which are invalid.
 
1358
    // By re-writing those URLs here we technically break the -[WebDataSource initialRequest] API
 
1359
    // but that is necessary to implement this quirk only at the API boundary.
 
1360
    // Note that other users of WebKit API use nil requests or requests with nil URLs or empty URLs, so we
 
1361
    // only implement this workaround when the request had a non-nil or non-empty URL.
 
1362
    if (!resourceRequest.url().isValid() && !resourceRequest.url().isEmpty())
 
1363
        resourceRequest.setURL([NSURL URLWithString:[@"file:" stringByAppendingString:[[request URL] absoluteString]]]);
 
1364
 
 
1365
    coreFrame->loader()->load(FrameLoadRequest(coreFrame, resourceRequest));
 
1366
}
 
1367
 
 
1368
static NSURL *createUniqueWebDataURL()
 
1369
{
 
1370
    CFUUIDRef UUIDRef = CFUUIDCreate(kCFAllocatorDefault);
 
1371
    NSString *UUIDString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, UUIDRef);
 
1372
    CFRelease(UUIDRef);
 
1373
    NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:@"applewebdata://%@", UUIDString]];
 
1374
    CFRelease(UUIDString);
 
1375
    return URL;
 
1376
}
 
1377
 
 
1378
- (void)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
 
1379
{
 
1380
    if (!pthread_main_np())
 
1381
        return [[self _webkit_invokeOnMainThread] _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:baseURL unreachableURL:unreachableURL];
 
1382
    
 
1383
    KURL responseURL;
 
1384
    if (!baseURL) {
 
1385
        baseURL = blankURL();
 
1386
        responseURL = createUniqueWebDataURL();
 
1387
    }
 
1388
    
 
1389
    ResourceRequest request([baseURL absoluteURL]);
 
1390
 
 
1391
    // hack because Mail checks for this property to detect data / archive loads
 
1392
    [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)request.nsURLRequest()];
 
1393
 
 
1394
    SubstituteData substituteData(WebCore::SharedBuffer::wrapNSData(data), MIMEType, encodingName, [unreachableURL absoluteURL], responseURL);
 
1395
 
 
1396
    _private->coreFrame->loader()->load(FrameLoadRequest(_private->coreFrame, request, substituteData));
 
1397
}
 
1398
 
 
1399
 
 
1400
- (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)encodingName baseURL:(NSURL *)baseURL
 
1401
{
 
1402
    WebCoreThreadViolationCheckRoundTwo();
 
1403
    
 
1404
    if (!MIMEType)
 
1405
        MIMEType = @"text/html";
 
1406
    [self _loadData:data MIMEType:MIMEType textEncodingName:encodingName baseURL:[baseURL _webkit_URLFromURLOrSchemelessFileURL] unreachableURL:nil];
 
1407
}
 
1408
 
 
1409
- (void)_loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL unreachableURL:(NSURL *)unreachableURL
 
1410
{
 
1411
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
 
1412
    [self _loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:baseURL unreachableURL:unreachableURL];
 
1413
}
 
1414
 
 
1415
- (void)loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL
 
1416
{
 
1417
    WebCoreThreadViolationCheckRoundTwo();
 
1418
 
 
1419
    [self _loadHTMLString:string baseURL:[baseURL _webkit_URLFromURLOrSchemelessFileURL] unreachableURL:nil];
 
1420
}
 
1421
 
 
1422
- (void)loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL
 
1423
{
 
1424
    WebCoreThreadViolationCheckRoundTwo();
 
1425
 
 
1426
    [self _loadHTMLString:string baseURL:[baseURL _webkit_URLFromURLOrSchemelessFileURL] unreachableURL:[unreachableURL _webkit_URLFromURLOrSchemelessFileURL]];
 
1427
}
 
1428
 
 
1429
- (void)loadArchive:(WebArchive *)archive
 
1430
{
 
1431
    if (LegacyWebArchive* coreArchive = [archive _coreLegacyWebArchive])
 
1432
        _private->coreFrame->loader()->loadArchive(coreArchive);
 
1433
}
 
1434
 
 
1435
- (void)stopLoading
 
1436
{
 
1437
    if (!_private->coreFrame)
 
1438
        return;
 
1439
    _private->coreFrame->loader()->stopForUserCancel();
 
1440
}
 
1441
 
 
1442
- (void)reload
 
1443
{
 
1444
    if (!WebKitLinkedOnOrAfter(WEBKIT_FIRST_VERSION_WITH_RELOAD_FROM_ORIGIN) && applicationIsSafari())
 
1445
        _private->coreFrame->loader()->reload(GetCurrentKeyModifiers() & shiftKey);
 
1446
    else
 
1447
        _private->coreFrame->loader()->reload(false);
 
1448
}
 
1449
 
 
1450
- (void)reloadFromOrigin
 
1451
{
 
1452
    _private->coreFrame->loader()->reload(true);
 
1453
}
 
1454
 
 
1455
- (WebFrame *)findFrameNamed:(NSString *)name
 
1456
{
 
1457
    Frame* coreFrame = _private->coreFrame;
 
1458
    if (!coreFrame)
 
1459
        return nil;
 
1460
    return kit(coreFrame->tree()->find(name));
 
1461
}
 
1462
 
 
1463
- (WebFrame *)parentFrame
 
1464
{
 
1465
    Frame* coreFrame = _private->coreFrame;
 
1466
    if (!coreFrame)
 
1467
        return nil;
 
1468
    return [[kit(coreFrame->tree()->parent()) retain] autorelease];
 
1469
}
 
1470
 
 
1471
- (NSArray *)childFrames
 
1472
{
 
1473
    Frame* coreFrame = _private->coreFrame;
 
1474
    if (!coreFrame)
 
1475
        return [NSArray array];
 
1476
    NSMutableArray *children = [NSMutableArray arrayWithCapacity:coreFrame->tree()->childCount()];
 
1477
    for (Frame* child = coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling())
 
1478
        [children addObject:kit(child)];
 
1479
    return children;
 
1480
}
 
1481
 
 
1482
- (WebScriptObject *)windowObject
 
1483
{
 
1484
    Frame* coreFrame = _private->coreFrame;
 
1485
    if (!coreFrame)
 
1486
        return 0;
 
1487
    return coreFrame->script()->windowScriptObject();
 
1488
}
 
1489
 
 
1490
- (JSGlobalContextRef)globalContext
 
1491
{
 
1492
    Frame* coreFrame = _private->coreFrame;
 
1493
    if (!coreFrame)
 
1494
        return 0;
 
1495
    return toGlobalRef(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec());
 
1496
}
 
1497
 
 
1498
@end