WebCoreFrameBridge.mm 43.8 KB
Newer Older
1
/*
darin's avatar
darin committed
2
 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.  All rights reserved.
ap's avatar
ap committed
3
 * Copyright (C) 2005, 2006 Alexey Proskuryakov (ap@nypop.com)
4
 * Copyright (C) 2006 David Smith (catfish.man@gmail.com)
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */
darin's avatar
darin committed
27

darin's avatar
darin committed
28
#import "config.h"
mjs's avatar
mjs committed
29
#import "WebCoreFrameBridge.h"
30

31
#import "AXObjectCache.h"
weinig's avatar
weinig committed
32
#import "CSSHelper.h"
darin's avatar
darin committed
33
#import "Cache.h"
bdakin's avatar
bdakin committed
34
#import "ClipboardMac.h"
sullivan's avatar
sullivan committed
35
#import "ColorMac.h"
andersca's avatar
andersca committed
36
#import "DOMImplementation.h"
darin's avatar
darin committed
37
#import "DOMInternal.h"
weinig's avatar
weinig committed
38
#import "DOMWindow.h"
darin's avatar
darin committed
39
#import "DeleteSelectionCommand.h"
mjs's avatar
mjs committed
40
#import "DocLoader.h"
darin's avatar
darin committed
41
#import "DocumentFragment.h"
weinig's avatar
weinig committed
42
#import "DocumentLoader.h"
darin's avatar
darin committed
43
#import "DocumentType.h"
bdakin's avatar
bdakin committed
44
#import "Editor.h"
aliceli1's avatar
aliceli1 committed
45
#import "EditorClient.h"
darin's avatar
darin committed
46
#import "EventHandler.h"
darin's avatar
darin committed
47
#import "FloatRect.h"
bdakin's avatar
bdakin committed
48
#import "FontData.h"
weinig's avatar
weinig committed
49
#import "FormDataStreamMac.h"
mjs's avatar
mjs committed
50
#import "Frame.h"
ggaren's avatar
ggaren committed
51
#import "FrameLoader.h"
darin's avatar
darin committed
52
#import "FrameLoaderClient.h"
darin's avatar
darin committed
53
#import "FrameTree.h"
darin's avatar
darin committed
54
#import "FrameView.h"
darin's avatar
darin committed
55
#import "GraphicsContext.h"
darin's avatar
darin committed
56
#import "HTMLDocument.h"
darin's avatar
darin committed
57 58
#import "HTMLFormElement.h"
#import "HTMLInputElement.h"
darin's avatar
darin committed
59
#import "HTMLNames.h"
darin's avatar
darin committed
60
#import "HitTestResult.h"
darin's avatar
darin committed
61
#import "Image.h"
mjs's avatar
mjs committed
62
#import "LoaderNSURLExtras.h"
darin's avatar
darin committed
63
#import "MoveSelectionCommand.h"
darin's avatar
darin committed
64
#import "Page.h"
ggaren's avatar
ggaren committed
65
#import "PlatformMouseEvent.h"
weinig's avatar
weinig committed
66
#import "PlatformScreen.h"
andersca's avatar
andersca committed
67
#import "PlugInInfoStore.h"
darin's avatar
darin committed
68 69 70
#import "RenderImage.h"
#import "RenderPart.h"
#import "RenderTreeAsText.h"
darin's avatar
darin committed
71
#import "RenderView.h"
darin's avatar
darin committed
72 73
#import "RenderWidget.h"
#import "ReplaceSelectionCommand.h"
ggaren's avatar
ggaren committed
74
#import "ResourceRequest.h"
darin's avatar
darin committed
75
#import "SelectionController.h"
aliceli1's avatar
aliceli1 committed
76
#import "SmartReplace.h"
weinig's avatar
weinig committed
77
#import "SubresourceLoader.h"
oliver's avatar
 
oliver committed
78
#import "SystemTime.h"
darin's avatar
darin committed
79
#import "Text.h"
darin's avatar
darin committed
80
#import "TextEncoding.h"
darin's avatar
darin committed
81
#import "TextIterator.h"
weinig's avatar
weinig committed
82
#import "TextResourceDecoder.h"
darin's avatar
darin committed
83 84
#import "TypingCommand.h"
#import "WebCoreSystemInterface.h"
darin's avatar
darin committed
85
#import "WebCoreViewFactory.h"
darin's avatar
darin committed
86
#import "XMLTokenizer.h"
darin's avatar
darin committed
87
#import "htmlediting.h"
rjw's avatar
rjw committed
88
#import "kjs_proxy.h"
rjw's avatar
WebKit:  
rjw committed
89
#import "kjs_window.h"
darin's avatar
darin committed
90
#import "markup.h"
harrison's avatar
harrison committed
91
#import "visible_units.h"
thatcher's avatar
thatcher committed
92
#import <OpenScripting/ASRegistry.h>
ap's avatar
ap committed
93
#import <JavaScriptCore/array_instance.h>
darin's avatar
darin committed
94
#import <JavaScriptCore/date_object.h>
mjs's avatar
mjs committed
95
#import <JavaScriptCore/runtime_root.h>
beidson's avatar
beidson committed
96
#import <wtf/RetainPtr.h>
darin's avatar
darin committed
97

darin's avatar
darin committed
98
@class NSView;
trey's avatar
trey committed
99

darin's avatar
darin committed
100
using namespace std;
darin's avatar
darin committed
101 102
using namespace WebCore;
using namespace HTMLNames;
darin's avatar
darin committed
103

ap's avatar
ap committed
104
using KJS::ArrayInstance;
darin's avatar
darin committed
105 106
using KJS::BooleanType;
using KJS::DateInstance;
darin's avatar
darin committed
107
using KJS::ExecState;
darin's avatar
darin committed
108
using KJS::GetterSetterType;
andersca's avatar
andersca committed
109
using KJS::JSImmediate;
mjs's avatar
mjs committed
110
using KJS::JSLock;
darin's avatar
darin committed
111
using KJS::JSObject;
darin's avatar
darin committed
112
using KJS::JSValue;
darin's avatar
darin committed
113
using KJS::NullType;
114 115
using KJS::NumberType;
using KJS::ObjectType;
darin's avatar
darin committed
116 117 118 119 120 121
using KJS::SavedBuiltins;
using KJS::SavedProperties;
using KJS::StringType;
using KJS::UndefinedType;
using KJS::UnspecifiedType;
using KJS::Window;
122

123
using KJS::Bindings::RootObject;
rjw's avatar
rjw committed
124

ggaren's avatar
ggaren committed
125
static PassRefPtr<RootObject> createRootObject(void* nativeHandle)
rjw's avatar
WebKit:  
rjw committed
126
{
ggaren's avatar
ggaren committed
127 128 129 130
    NSView *view = (NSView *)nativeHandle;
    WebCoreFrameBridge *bridge = [[WebCoreViewFactory sharedFactory] bridgeForView:view];
    if (!bridge)
        return 0;
rjw's avatar
WebKit:  
rjw committed
131

mjs's avatar
mjs committed
132
    Frame* frame = [bridge _frame];
ggaren@apple.com's avatar
ggaren@apple.com committed
133
    return frame->createRootObject(nativeHandle, frame->scriptProxy()->globalObject());
rjw's avatar
WebKit:  
rjw committed
134 135
}

rjw's avatar
WebKit:  
rjw committed
136 137
static pthread_t mainThread = 0;

darin's avatar
darin committed
138
static void updateRenderingForBindings(ExecState* exec, JSObject* rootObject)
rjw's avatar
rjw committed
139
{
rjw's avatar
WebKit:  
rjw committed
140 141 142 143 144 145
    if (pthread_self() != mainThread)
        return;
        
    if (!rootObject)
        return;
        
darin's avatar
darin committed
146
    Window* window = static_cast<Window*>(rootObject);
rjw's avatar
WebKit:  
rjw committed
147 148
    if (!window)
        return;
weinig's avatar
weinig committed
149 150 151 152

    if (Frame* frame = window->impl()->frame())
        if (Document* doc = frame->document())
            doc->updateRendering();
rjw's avatar
rjw committed
153 154
}

155 156 157 158
static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSValue* jsValue)
{
    NSAppleEventDescriptor* aeDesc = 0;
    switch (jsValue->type()) {
159 160
        case BooleanType:
            aeDesc = [NSAppleEventDescriptor descriptorWithBoolean:jsValue->getBoolean()];
161
            break;
162
        case StringType:
darin's avatar
darin committed
163
            aeDesc = [NSAppleEventDescriptor descriptorWithString:String(jsValue->getString())];
164 165
            break;
        case NumberType: {
ap's avatar
ap committed
166 167 168 169 170 171
            double value = jsValue->getNumber();
            int intValue = (int)value;
            if (value == intValue)
                aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeSInt32 bytes:&intValue length:sizeof(intValue)];
            else
                aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeIEEE64BitFloatingPoint bytes:&value length:sizeof(value)];
172 173 174 175 176 177 178 179 180
            break;
        }
        case ObjectType: {
            JSObject* object = jsValue->getObject();
            if (object->inherits(&DateInstance::info)) {
                DateInstance* date = static_cast<DateInstance*>(object);
                double ms = 0;
                int tzOffset = 0;
                if (date->getTime(ms, tzOffset)) {
181
                    CFAbsoluteTime utcSeconds = ms / 1000 - kCFAbsoluteTimeIntervalSince1970;
182 183 184 185 186
                    LongDateTime ldt;
                    if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt))
                        aeDesc = [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)];
                }
            }
ap's avatar
ap committed
187 188 189 190 191 192 193 194 195 196 197 198 199 200
            else if (object->inherits(&ArrayInstance::info)) {
                static HashSet<JSObject*> visitedElems;
                if (!visitedElems.contains(object)) {
                    visitedElems.add(object);
                    
                    ArrayInstance* array = static_cast<ArrayInstance*>(object);
                    aeDesc = [NSAppleEventDescriptor listDescriptor];
                    unsigned numItems = array->getLength();
                    for (unsigned i = 0; i < numItems; ++i)
                        [aeDesc insertDescriptor:aeDescFromJSValue(exec, array->getItem(i)) atIndex:0];
                    
                    visitedElems.remove(object);
                }
            }
201 202 203 204 205 206 207 208 209 210
            if (!aeDesc) {
                JSValue* primitive = object->toPrimitive(exec);
                if (exec->hadException()) {
                    exec->clearException();
                    return [NSAppleEventDescriptor nullDescriptor];
                }
                return aeDescFromJSValue(exec, primitive);
            }
            break;
        }
ap's avatar
ap committed
211 212 213
        case UndefinedType:
            aeDesc = [NSAppleEventDescriptor descriptorWithTypeCode:cMissingValue];
            break;
214
        default:
mjs's avatar
mjs committed
215
            LOG_ERROR("Unknown JavaScript type: %d", jsValue->type());
216 217 218 219 220 221 222 223 224 225 226
            // no break;
        case UnspecifiedType:
        case NullType:
        case GetterSetterType:
            aeDesc = [NSAppleEventDescriptor nullDescriptor];
            break;
    }
    
    return aeDesc;
}

mjs's avatar
mjs committed
227
@implementation WebCoreFrameBridge
darin's avatar
darin committed
228

mjs's avatar
mjs committed
229 230 231 232
static inline WebCoreFrameBridge *bridge(Frame *frame)
{
    if (!frame)
        return nil;
mjs's avatar
mjs committed
233
    return frame->bridge();
mjs's avatar
mjs committed
234 235
}

mjs's avatar
mjs committed
236 237 238
- (NSString *)domain
{
    Document *doc = m_frame->document();
darin's avatar
darin committed
239
    if (doc)
mjs's avatar
mjs committed
240 241 242 243
        return doc->domain();
    return nil;
}

mjs's avatar
mjs committed
244
+ (WebCoreFrameBridge *)bridgeForDOMDocument:(DOMDocument *)document
cblu's avatar
Tests:  
cblu committed
245
{
mjs's avatar
mjs committed
246
    return bridge([document _document]->frame());
cblu's avatar
Tests:  
cblu committed
247 248
}

ggaren's avatar
ggaren committed
249
- (id)init
darin's avatar
darin committed
250
{
ggaren's avatar
ggaren committed
251
    static bool initializedKJS;
darin's avatar
darin committed
252
    if (!initializedKJS) {
ggaren's avatar
ggaren committed
253 254
        initializedKJS = true;

darin's avatar
darin committed
255
        mainThread = pthread_self();
ggaren's avatar
ggaren committed
256
        RootObject::setCreateRootObject(createRootObject);
darin's avatar
darin committed
257 258 259
        KJS::Bindings::Instance::setDidExecuteFunction(updateRenderingForBindings);
    }
    
mjs's avatar
mjs committed
260 261
    if (!(self = [super init]))
        return nil;
darin's avatar
darin committed
262

rjw's avatar
rjw committed
263
    _shouldCreateRenderers = YES;
darin's avatar
darin committed
264 265 266
    return self;
}

mjs's avatar
mjs committed
267 268
- (void)dealloc
{
thatcher's avatar
thatcher committed
269
    ASSERT(_closed);
darin's avatar
darin committed
270 271 272
    [super dealloc];
}

darin's avatar
darin committed
273 274
- (void)finalize
{
thatcher's avatar
thatcher committed
275
    ASSERT(_closed);
darin's avatar
darin committed
276 277 278
    [super finalize];
}

thatcher's avatar
thatcher committed
279 280 281 282 283 284
- (void)close
{
    [self clearFrame];
    _closed = YES;
}

darin's avatar
darin committed
285
- (void)addData:(NSData *)data
mjs's avatar
mjs committed
286
{
darin's avatar
darin committed
287
    Document *doc = m_frame->document();
rjw's avatar
rjw committed
288
    
rjw's avatar
rjw committed
289 290 291 292
    // Document may be nil if the part is about to redirect
    // as a result of JS executing during load, i.e. one frame
    // changing another's location before the frame's document
    // has been created. 
mjs's avatar
mjs committed
293
    if (doc) {
rjw's avatar
rjw committed
294
        doc->setShouldCreateRenderers([self shouldCreateRenderers]);
darin's avatar
darin committed
295
        m_frame->loader()->addData((const char *)[data bytes], [data length]);
rjw's avatar
rjw committed
296
    }
darin's avatar
darin committed
297 298
}

cblu's avatar
cblu committed
299 300
- (BOOL)scrollOverflowInDirection:(WebScrollDirection)direction granularity:(WebScrollGranularity)granularity
{
darin's avatar
darin committed
301
    if (!m_frame)
cblu's avatar
cblu committed
302
        return NO;
darin's avatar
darin committed
303
    return m_frame->eventHandler()->scrollOverflow((ScrollDirection)direction, (ScrollGranularity)granularity);
cblu's avatar
cblu committed
304 305
}

mjs's avatar
mjs committed
306 307 308 309 310
- (void)clearFrame
{
    m_frame = 0;
}

311
- (void)createFrameViewWithNSView:(NSView *)view marginWidth:(int)mw marginHeight:(int)mh
darin's avatar
darin committed
312
{
mjs's avatar
mjs committed
313
    // If we own the view, delete the old one - otherwise the render m_frame will take care of deleting the view.
darin's avatar
darin committed
314 315
    if (m_frame)
        m_frame->setView(0);
mjs's avatar
mjs committed
316

darin's avatar
darin committed
317 318 319
    FrameView* frameView = new FrameView(m_frame);
    m_frame->setView(frameView);
    frameView->deref();
darin's avatar
darin committed
320

darin's avatar
darin committed
321
    frameView->setView(view);
darin's avatar
darin committed
322
    if (mw >= 0)
darin's avatar
darin committed
323
        frameView->setMarginWidth(mw);
darin's avatar
darin committed
324
    if (mh >= 0)
darin's avatar
darin committed
325
        frameView->setMarginHeight(mh);
darin's avatar
darin committed
326 327
}

cblu's avatar
Tests:  
cblu committed
328 329
- (NSString *)_stringWithDocumentTypeStringAndMarkupString:(NSString *)markupString
{
mjs's avatar
mjs committed
330
    return m_frame->documentTypeString() + markupString;
cblu's avatar
Tests:  
cblu committed
331 332
}

darin's avatar
darin committed
333
- (NSArray *)nodesFromList:(Vector<Node*> *)nodesVector
cblu's avatar
cblu committed
334
{
darin's avatar
darin committed
335 336 337
    size_t size = nodesVector->size();
    NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:size];
    for (size_t i = 0; i < size; ++i)
darin's avatar
darin committed
338
        [nodes addObject:[DOMNode _wrapNode:(*nodesVector)[i]]];
cblu's avatar
cblu committed
339 340 341 342 343
    return nodes;
}

- (NSString *)markupStringFromNode:(DOMNode *)node nodes:(NSArray **)nodes
{
darin's avatar
darin committed
344
    // FIXME: This is never "for interchange". Is that right? See the next method.
darin's avatar
darin committed
345
    Vector<Node*> nodeList;
oliver's avatar
oliver committed
346
    NSString *markupString = createMarkup([node _node], IncludeNode, nodes ? &nodeList : 0);
mjs's avatar
mjs committed
347
    if (nodes)
darin's avatar
darin committed
348
        *nodes = [self nodesFromList:&nodeList];
mjs's avatar
mjs committed
349

cblu's avatar
Tests:  
cblu committed
350
    return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
cblu's avatar
Tests:  
cblu committed
351 352
}

cblu's avatar
cblu committed
353
- (NSString *)markupStringFromRange:(DOMRange *)range nodes:(NSArray **)nodes
cblu's avatar
Tests:  
cblu committed
354
{
darin's avatar
darin committed
355
    // FIXME: This is always "for interchange". Is that right? See the previous method.
darin's avatar
darin committed
356
    Vector<Node*> nodeList;
oliver's avatar
oliver committed
357
    NSString *markupString = createMarkup([range _range], nodes ? &nodeList : 0, AnnotateForInterchange);
mjs's avatar
mjs committed
358
    if (nodes)
darin's avatar
darin committed
359
        *nodes = [self nodesFromList:&nodeList];
mjs's avatar
mjs committed
360

cblu's avatar
Tests:  
cblu committed
361
    return [self _stringWithDocumentTypeStringAndMarkupString:markupString];
cblu's avatar
cblu committed
362 363
}

cblu's avatar
cblu committed
364
- (NSString *)selectedString
365
{
366
    String text = m_frame->selectedText();
darin's avatar
darin committed
367
    text.replace('\\', m_frame->backslashAsCurrencySymbol());
antti's avatar
antti committed
368
    return text;
369 370
}

darin's avatar
darin committed
371 372
- (NSString *)stringForRange:(DOMRange *)range
{
antti's avatar
antti committed
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
    // This will give a system malloc'd buffer that can be turned directly into an NSString
    unsigned length;
    UChar* buf = plainTextToMallocAllocatedBuffer([range _range], length);
    
    if (!buf)
        return [NSString string];
    
    UChar backslashAsCurrencySymbol = m_frame->backslashAsCurrencySymbol();
    if (backslashAsCurrencySymbol != '\\')
        for (unsigned n = 0; n < length; n++) 
            if (buf[n] == '\\')
                buf[n] = backslashAsCurrencySymbol;

    // Transfer buffer ownership to NSString
    return [[[NSString alloc] initWithCharactersNoCopy:buf length:length freeWhenDone:YES] autorelease];
darin's avatar
darin committed
388 389
}

darin's avatar
darin committed
390
- (void)reapplyStylesForDeviceType:(WebCoreDeviceType)deviceType
darin's avatar
darin committed
391
{
darin's avatar
darin committed
392 393
    if (m_frame->view())
        m_frame->view()->setMediaType(deviceType == WebCoreDeviceScreen ? "screen" : "print");
darin's avatar
darin committed
394
    Document *doc = m_frame->document();
395 396
    if (doc)
        doc->setPrinting(deviceType == WebCoreDevicePrinter);
397
    m_frame->reapplyStyles();
darin's avatar
darin committed
398 399
}

sullivan's avatar
sullivan committed
400
- (void)forceLayoutAdjustingViewSize:(BOOL)flag
darin's avatar
darin committed
401
{
adele's avatar
adele committed
402
    m_frame->forceLayout(!flag);
darin's avatar
darin committed
403 404
    if (flag)
        m_frame->view()->adjustViewSize();
trey's avatar
trey committed
405 406
}

sullivan's avatar
sullivan committed
407
- (void)forceLayoutWithMinimumPageWidth:(float)minPageWidth maximumPageWidth:(float)maxPageWidth adjustingViewSize:(BOOL)flag
trey's avatar
trey committed
408
{
hyatt's avatar
hyatt committed
409
    m_frame->forceLayoutWithPageWidthRange(minPageWidth, maxPageWidth, flag);
darin's avatar
darin committed
410 411
}

hyatt's avatar
hyatt committed
412 413
- (void)sendScrollEvent
{
mjs's avatar
mjs committed
414
    m_frame->sendScrollEvent();
hyatt's avatar
hyatt committed
415 416
}

darin's avatar
darin committed
417
- (void)drawRect:(NSRect)rect
darin's avatar
darin committed
418
{
darin's avatar
darin committed
419 420 421
    PlatformGraphicsContext* platformContext = static_cast<PlatformGraphicsContext*>([[NSGraphicsContext currentContext] graphicsPort]);
    ASSERT([[NSGraphicsContext currentContext] isFlipped]);
    GraphicsContext context(platformContext);
422
    
darin's avatar
darin committed
423
    m_frame->paint(&context, enclosingIntRect(rect));
darin's avatar
darin committed
424 425
}

sullivan's avatar
sullivan committed
426
// Used by pagination code called from AppKit when a standalone web page is printed.
427
- (NSArray*)computePageRectsWithPrintWidthScaleFactor:(float)printWidthScaleFactor printHeight:(float)printHeight
sullivan's avatar
sullivan committed
428 429
{
    NSMutableArray* pages = [NSMutableArray arrayWithCapacity:5];
sullivan's avatar
sullivan committed
430
    if (printWidthScaleFactor <= 0) {
mjs's avatar
mjs committed
431
        LOG_ERROR("printWidthScaleFactor has bad value %.2f", printWidthScaleFactor);
432
        return pages;
sullivan's avatar
sullivan committed
433 434 435
    }
    
    if (printHeight <= 0) {
mjs's avatar
mjs committed
436
        LOG_ERROR("printHeight has bad value %.2f", printHeight);
sullivan's avatar
sullivan committed
437 438
        return pages;
    }
mjs's avatar
mjs committed
439

440
    if (!m_frame || !m_frame->document() || !m_frame->view()) return pages;
441
    RenderView* root = static_cast<RenderView *>(m_frame->document()->renderer());
442 443
    if (!root) return pages;
    
444
    FrameView* view = m_frame->view();
bdakin's avatar
bdakin committed
445 446 447
    if (!view)
        return pages;

sullivan's avatar
sullivan committed
448 449 450
    NSView* documentView = view->getDocumentView();
    if (!documentView)
        return pages;
mjs's avatar
mjs committed
451

sullivan's avatar
sullivan committed
452
    float currPageHeight = printHeight;
453 454 455
    float docHeight = root->layer()->height();
    float docWidth = root->layer()->width();
    float printWidth = docWidth/printWidthScaleFactor;
sullivan's avatar
sullivan committed
456 457 458
    
    // We need to give the part the opportunity to adjust the page height at each step.
    for (float i = 0; i < docHeight; i += currPageHeight) {
darin's avatar
darin committed
459
        float proposedBottom = min(docHeight, i + printHeight);
mjs's avatar
mjs committed
460
        m_frame->adjustPageHeight(&proposedBottom, i, proposedBottom, i);
darin's avatar
darin committed
461
        currPageHeight = max(1.0f, proposedBottom - i);
hyatt's avatar
hyatt committed
462 463 464 465
        for (float j = 0; j < docWidth; j += printWidth) {
            NSValue* val = [NSValue valueWithRect: NSMakeRect(j, i, printWidth, currPageHeight)];
            [pages addObject: val];
        }
sullivan's avatar
sullivan committed
466 467 468 469 470 471
    }
    
    return pages;
}

// This is to support the case where a webview is embedded in the view that's being printed
trey's avatar
trey committed
472 473
- (void)adjustPageHeightNew:(float *)newBottom top:(float)oldTop bottom:(float)oldBottom limit:(float)bottomLimit
{
mjs's avatar
mjs committed
474
    m_frame->adjustPageHeight(newBottom, oldTop, oldBottom, bottomLimit);
darin's avatar
darin committed
475 476
}

darin's avatar
darin committed
477
- (NSObject *)copyRenderNode:(RenderObject *)node copier:(id <WebCoreRenderTreeCopier>)copier
darin's avatar
darin committed
478 479
{
    NSMutableArray *children = [[NSMutableArray alloc] init];
darin's avatar
darin committed
480
    for (RenderObject *child = node->firstChild(); child; child = child->nextSibling()) {
darin's avatar
darin committed
481 482
        [children addObject:[self copyRenderNode:child copier:copier]];
    }
483
          
darin's avatar
darin committed
484 485
    NSString *name = [[NSString alloc] initWithUTF8String:node->renderName()];
    
486 487
    RenderWidget* renderWidget = node->isWidget() ? static_cast<RenderWidget*>(node) : 0;
    Widget* widget = renderWidget ? renderWidget->widget() : 0;
darin's avatar
darin committed
488 489
    NSView *view = widget ? widget->getView() : nil;
    
490
    int nx, ny;
491
    node->absolutePosition(nx, ny);
darin's avatar
darin committed
492
    NSObject *copiedNode = [copier nodeWithName:name
darin's avatar
darin committed
493
                                       position:NSMakePoint(nx,ny)
darin's avatar
darin committed
494 495 496 497 498 499 500 501 502 503 504 505
                                           rect:NSMakeRect(node->xPos(), node->yPos(), node->width(), node->height())
                                           view:view
                                       children:children];
    
    [name release];
    [children release];
    
    return copiedNode;
}

- (NSObject *)copyRenderTree:(id <WebCoreRenderTreeCopier>)copier
{
mjs's avatar
mjs committed
506
    RenderObject *renderer = m_frame->renderer();
darin's avatar
darin committed
507 508 509 510 511 512 513 514
    if (!renderer) {
        return nil;
    }
    return [self copyRenderNode:renderer copier:copier];
}

- (void)installInFrame:(NSView *)view
{
mjs's avatar
mjs committed
515
    // If this isn't the main frame, it must have a render m_frame set, or it
mjs's avatar
mjs committed
516
    // won't ever get installed in the view hierarchy.
darin's avatar
darin committed
517
    ASSERT(m_frame == m_frame->page()->mainFrame() || m_frame->ownerElement());
mjs's avatar
mjs committed
518

mjs's avatar
mjs committed
519
    m_frame->view()->setView(view);
mjs's avatar
mjs committed
520 521 522
    // FIXME: frame tries to do this too, is it needed?
    if (m_frame->ownerRenderer()) {
        m_frame->ownerRenderer()->setWidget(m_frame->view());
523
        // Now the render part owns the view, so we don't any more.
darin's avatar
darin committed
524
    }
525

ggaren's avatar
ggaren committed
526
    m_frame->view()->initScrollbars();
darin's avatar
darin committed
527 528
}

darin's avatar
darin committed
529
static HTMLInputElement* inputElementFromDOMElement(DOMElement* element)
trey's avatar
trey committed
530
{
darin's avatar
darin committed
531
    Node* node = [element _node];
532
    if (node->hasTagName(inputTag))
darin's avatar
darin committed
533
        return static_cast<HTMLInputElement*>(node);
trey's avatar
trey committed
534 535
    return nil;
}
trey's avatar
trey committed
536

darin's avatar
darin committed
537
static HTMLFormElement *formElementFromDOMElement(DOMElement *element)
trey's avatar
trey committed
538
{
darin's avatar
darin committed
539
    Node *node = [element _node];
540 541 542 543
    // This should not be necessary, but an XSL file on
    // maps.google.com crashes otherwise because it is an xslt file
    // that contains <form> elements that aren't in any namespace, so
    // they come out as generic CML elements
544
    if (node && node->hasTagName(formTag)) {
darin's avatar
darin committed
545
        return static_cast<HTMLFormElement *>(node);
trey's avatar
trey committed
546 547 548 549
    }
    return nil;
}

kocienda's avatar
Tests:  
kocienda committed
550
- (DOMElement *)elementWithName:(NSString *)name inForm:(DOMElement *)form
trey's avatar
trey committed
551
{
darin's avatar
darin committed
552
    HTMLFormElement *formElement = formElementFromDOMElement(form);
trey's avatar
trey committed
553
    if (formElement) {
darin's avatar
darin committed
554
        Vector<HTMLGenericFormElement*>& elements = formElement->formElements;
mjs's avatar
mjs committed
555
        AtomicString targetName = name;
mjs's avatar
mjs committed
556
        for (unsigned int i = 0; i < elements.size(); i++) {
darin's avatar
darin committed
557
            HTMLGenericFormElement *elt = elements[i];
trey's avatar
trey committed
558
            // Skip option elements, other duds
mjs's avatar
mjs committed
559
            if (elt->name() == targetName)
darin's avatar
darin committed
560
                return [DOMElement _wrapElement:elt];
trey's avatar
trey committed
561 562 563 564 565
        }
    }
    return nil;
}

kocienda's avatar
Tests:  
kocienda committed
566
- (BOOL)elementDoesAutoComplete:(DOMElement *)element
trey's avatar
trey committed
567
{
darin's avatar
darin committed
568
    HTMLInputElement *inputElement = inputElementFromDOMElement(element);
trey's avatar
trey committed
569
    return inputElement != nil
darin's avatar
darin committed
570
        && inputElement->inputType() == HTMLInputElement::TEXT
trey's avatar
trey committed
571 572 573
        && inputElement->autoComplete();
}

kocienda's avatar
Tests:  
kocienda committed
574
- (BOOL)elementIsPassword:(DOMElement *)element
trey's avatar
trey committed
575
{
darin's avatar
darin committed
576
    HTMLInputElement *inputElement = inputElementFromDOMElement(element);
trey's avatar
trey committed
577
    return inputElement != nil
darin's avatar
darin committed
578
        && inputElement->inputType() == HTMLInputElement::PASSWORD;
trey's avatar
trey committed
579 580
}

kocienda's avatar
Tests:  
kocienda committed
581
- (DOMElement *)formForElement:(DOMElement *)element;
trey's avatar
trey committed
582
{
darin's avatar
darin committed
583
    HTMLInputElement *inputElement = inputElementFromDOMElement(element);
trey's avatar
trey committed
584
    if (inputElement) {
darin's avatar
darin committed
585
        HTMLFormElement *formElement = inputElement->form();
trey's avatar
trey committed
586
        if (formElement) {
darin's avatar
darin committed
587
            return [DOMElement _wrapElement:formElement];
trey's avatar
trey committed
588 589 590
        }
    }
    return nil;
trey's avatar
trey committed
591 592
}

kocienda's avatar
Tests:  
kocienda committed
593
- (DOMElement *)currentForm
trey's avatar
trey committed
594
{
darin's avatar
darin committed
595
    return [DOMElement _wrapElement:m_frame->currentForm()];
trey's avatar
trey committed
596 597
}

kocienda's avatar
Tests:  
kocienda committed
598
- (NSArray *)controlsInForm:(DOMElement *)form
trey's avatar
trey committed
599 600
{
    NSMutableArray *results = nil;
darin's avatar
darin committed
601
    HTMLFormElement *formElement = formElementFromDOMElement(form);
trey's avatar
trey committed
602
    if (formElement) {
darin's avatar
darin committed
603
        Vector<HTMLGenericFormElement*>& elements = formElement->formElements;
mjs's avatar
mjs committed
604
        for (unsigned int i = 0; i < elements.size(); i++) {
mjs's avatar
mjs committed
605
            if (elements.at(i)->isEnumeratable()) { // Skip option elements, other duds
darin's avatar
darin committed
606
                DOMElement *de = [DOMElement _wrapElement:elements.at(i)];
sullivan's avatar
sullivan committed
607 608 609 610
                if (!results) {
                    results = [NSMutableArray arrayWithObject:de];
                } else {
                    [results addObject:de];
trey's avatar
trey committed
611 612 613 614 615 616 617
                }
            }
        }
    }
    return results;
}

kocienda's avatar
Tests:  
kocienda committed
618
- (NSString *)searchForLabels:(NSArray *)labels beforeElement:(DOMElement *)element
trey's avatar
trey committed
619
{
darin's avatar
darin committed
620
    return m_frame->searchForLabelsBeforeElement(labels, [element _element]);
trey's avatar
trey committed
621 622
}

kocienda's avatar
Tests:  
kocienda committed
623
- (NSString *)matchLabels:(NSArray *)labels againstElement:(DOMElement *)element
trey's avatar
trey committed
624
{
darin's avatar
darin committed
625
    return m_frame->matchLabelsAgainstElement(labels, [element _element]);
trey's avatar
trey committed
626 627
}

cblu's avatar
cblu committed
628
- (NSURL *)URLWithAttributeString:(NSString *)string
cblu's avatar
cblu committed
629
{
darin's avatar
darin committed
630
    Document *doc = m_frame->document();
631
    if (!doc)
cblu's avatar
cblu committed
632
        return nil;
mjs's avatar
mjs committed
633
    // FIXME: is parseURL appropriate here?
634
    DeprecatedString rel = parseURL(string).deprecatedString();
mjs's avatar
mjs committed
635
    return KURL(doc->completeURL(rel)).getNSURL();
cblu's avatar
cblu committed
636 637
}

sullivan's avatar
sullivan committed
638
- (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection
639
{
sullivan's avatar
sullivan committed
640
    return m_frame->findString(string, forward, caseFlag, wrapFlag, startInSelection);
641 642
}

sullivan's avatar
sullivan committed
643
- (unsigned)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag limit:(unsigned)limit
sullivan's avatar
sullivan committed
644
{
sullivan's avatar
sullivan committed
645
    return m_frame->markAllMatchesForText(string, caseFlag, limit);
sullivan's avatar
sullivan committed
646 647
}

sullivan's avatar
sullivan committed
648 649 650 651 652 653 654 655 656 657 658
- (BOOL)markedTextMatchesAreHighlighted
{
    return m_frame->markedTextMatchesAreHighlighted();
}

- (void)setMarkedTextMatchesAreHighlighted:(BOOL)doHighlight
{
    m_frame->setMarkedTextMatchesAreHighlighted(doHighlight);
}

- (void)unmarkAllTextMatches
sullivan's avatar
sullivan committed
659
{
darin's avatar
darin committed
660
    Document *doc = m_frame->document();
sullivan's avatar
sullivan committed
661 662 663 664 665 666
    if (!doc) {
        return;
    }
    doc->removeMarkers(DocumentMarker::TextMatch);
}

667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
- (NSArray *)rectsForTextMatches
{
    Document *doc = m_frame->document();
    if (!doc)
        return [NSArray array];
    
    NSMutableArray *result = [NSMutableArray array];
    Vector<IntRect> rects = doc->renderedRectsForMarkers(DocumentMarker::TextMatch);
    unsigned count = rects.size();
    for (unsigned index = 0; index < count; ++index)
        [result addObject:[NSValue valueWithRect:rects[index]]];
    
    return result;
}

darin's avatar
darin committed
682 683
- (void)setTextSizeMultiplier:(float)multiplier
{
darin's avatar
darin committed
684
    int newZoomFactor = (int)rint(multiplier * 100);
mjs's avatar
mjs committed
685
    if (m_frame->zoomFactor() == newZoomFactor) {
darin's avatar
darin committed
686 687
        return;
    }
mjs's avatar
mjs committed
688
    m_frame->setZoomFactor(newZoomFactor);
darin's avatar
darin committed
689 690
}

darin's avatar
darin committed
691
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)string
kdecker's avatar
kdecker committed
692 693 694 695 696
{
    return [self stringByEvaluatingJavaScriptFromString:string forceUserGesture:true];
}

- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)string forceUserGesture:(BOOL)forceUserGesture
darin's avatar
darin committed
697
{
mjs's avatar
mjs committed
698
    ASSERT(m_frame->document());
ggaren's avatar
ggaren committed
699
    
andersca's avatar
andersca committed
700
    JSValue* result = m_frame->loader()->executeScript(string, forceUserGesture);
ggaren's avatar
ggaren committed
701

ggaren's avatar
ggaren committed
702 703
    if (!m_frame) // In case the script removed our frame from the page.
        return @"";
andersca's avatar
andersca committed
704

ggaren's avatar
ggaren committed
705 706 707 708 709
    // This bizarre set of rules matches behavior from WebKit for Safari 2.0.
    // If you don't like it, use -[WebScriptObject evaluateWebScript:] or 
    // JSEvaluateScript instead, since they have less surprising semantics.
    if (!result || !result->isBoolean() && !result->isString() && !result->isNumber())
        return @"";
andersca's avatar
andersca committed
710

darin's avatar
darin committed
711
    JSLock lock;
ggaren@apple.com's avatar
ggaren@apple.com committed
712
    return String(result->toString(m_frame->scriptProxy()->globalObject()->globalExec()));
darin's avatar
darin committed
713 714
}

715 716
- (NSAppleEventDescriptor *)aeDescByEvaluatingJavaScriptFromString:(NSString *)string
{
mjs's avatar
mjs committed
717
    ASSERT(m_frame->document());
andersca's avatar
andersca committed
718
    ASSERT(m_frame == m_frame->page()->mainFrame());
andersca's avatar
andersca committed
719
    JSValue* result = m_frame->loader()->executeScript(string, true);
720 721 722
    if (!result) // FIXME: pass errors
        return 0;
    JSLock lock;
ggaren@apple.com's avatar
ggaren@apple.com committed
723
    return aeDescFromJSValue(m_frame->scriptProxy()->globalObject()->globalExec(), result);
724 725
}

kocienda's avatar
kocienda committed
726
- (NSRect)caretRectAtNode:(DOMNode *)node offset:(int)offset affinity:(NSSelectionAffinity)affinity
trey's avatar
trey committed
727
{
darin's avatar
darin committed
728
    return [node _node]->renderer()->caretRect(offset, static_cast<EAffinity>(affinity));
trey's avatar
trey committed
729
}
darin's avatar
darin committed
730

mjs's avatar
mjs committed
731 732
- (NSRect)firstRectForDOMRange:(DOMRange *)range
{
oliver's avatar
oliver committed
733
   return m_frame->firstRectForRange([range _range]);
mjs's avatar
mjs committed
734
}
trey's avatar
trey committed
735

736 737 738 739 740 741 742 743 744 745 746 747
- (void)scrollDOMRangeToVisible:(DOMRange *)range
{
    NSRect rangeRect = [self firstRectForDOMRange:range];    
    Node *startNode = [[range startContainer] _node];
        
    if (startNode && startNode->renderer()) {
        RenderLayer *layer = startNode->renderer()->enclosingLayer();
        if (layer)
            layer->scrollRectToVisible(enclosingIntRect(rangeRect), RenderLayer::gAlignToEdgeIfNeeded, RenderLayer::gAlignToEdgeIfNeeded);
    }
}

cblu's avatar
cblu committed
748 749
- (NSURL *)baseURL
{
darin's avatar
darin committed
750
    return m_frame->loader()->completeURL(m_frame->document()->baseURL()).getNSURL();
cblu's avatar
cblu committed
751 752
}

darin's avatar
darin committed
753
- (NSString *)stringWithData:(NSData *)data
cblu's avatar
cblu committed
754
{
darin's avatar
darin committed
755 756 757
    Document* doc = m_frame->document();
    if (!doc)
        return nil;
darin's avatar
darin committed
758
    TextResourceDecoder* decoder = doc->decoder();
darin's avatar
darin committed
759 760 761
    if (!decoder)
        return nil;
    return decoder->encoding().decode(reinterpret_cast<const char*>([data bytes]), [data length]);
cblu's avatar
cblu committed
762 763 764 765
}

+ (NSString *)stringWithData:(NSData *)data textEncodingName:(NSString *)textEncodingName
{
kdecker's avatar
 
kdecker committed
766 767 768 769
    WebCore::TextEncoding encoding(textEncodingName);
    if (!encoding.isValid())
        encoding = WindowsLatin1Encoding();
    return encoding.decode(reinterpret_cast<const char*>([data bytes]), [data length]);
cblu's avatar
cblu committed
770 771
}

darin's avatar
darin committed
772 773
- (BOOL)needsLayout
{
774
    return m_frame->view() ? m_frame->view()->needsLayout() : false;
darin's avatar
darin committed
775 776
}

777 778
- (void)setNeedsLayout
{
779 780
    if (m_frame->view())
        m_frame->view()->setNeedsLayout();
781 782
}

darin's avatar
darin committed
783 784
- (NSString *)renderTreeAsExternalRepresentation
{
mjs's avatar
mjs committed
785
    return externalRepresentation(m_frame->renderer()).getNSString();