WebBaseNetscapePluginView.m 26.5 KB
Newer Older
1
/*	
2
        WebBaseNetscapePluginView.m
3 4
	Copyright 2002, Apple, Inc. All rights reserved.
*/
cblu's avatar
cblu committed
5

6
#import <WebKit/WebBaseNetscapePluginView.h>
darin's avatar
darin committed
7
#import <WebKit/WebController.h>
8
#import <WebKit/WebControllerPrivate.h>
9
#import <WebKit/WebDataSource.h>
darin's avatar
darin committed
10 11
#import <WebKit/WebFrame.h>
#import <WebKit/WebFramePrivate.h>
12
#import <WebKit/WebKitLogging.h>
13 14
#import <WebKit/WebNetscapePluginStream.h>
#import <WebKit/WebNetscapePluginNullEventSender.h>
15 16
#import <WebKit/WebNullPluginView.h>
#import <WebKit/WebNSViewExtras.h>
17
#import <WebKit/WebNetscapePluginPackage.h>
18
#import <WebKit/WebView.h>
19
#import <WebKit/WebWindowOperationsDelegate.h>
20

21 22
#import <WebFoundation/WebAssertions.h>
#import <WebFoundation/WebHTTPResourceRequest.h>
darin's avatar
darin committed
23 24
#import <WebFoundation/WebNSStringExtras.h>
#import <WebFoundation/WebNSURLExtras.h>
darin's avatar
darin committed
25

cblu's avatar
cblu committed
26
#import <AppKit/NSEvent_Private.h>
27

cblu's avatar
 
cblu committed
28 29
#import <Carbon/Carbon.h>

30
@implementation WebBaseNetscapePluginView
31

darin's avatar
darin committed
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
#pragma mark EVENTS

+ (void)getCarbonEvent:(EventRecord *)carbonEvent
{
    carbonEvent->what = nullEvent;
    carbonEvent->message = 0;
    carbonEvent->when = TickCount();
    GetGlobalMouse(&carbonEvent->where);
    carbonEvent->modifiers = GetCurrentKeyModifiers();
    if (!Button())
        carbonEvent->modifiers |= btnState;
}

- (void)getCarbonEvent:(EventRecord *)carbonEvent
{
    [[self class] getCarbonEvent:carbonEvent];
}

cblu's avatar
cblu committed
50
- (EventModifiers)modifiersForEvent:(NSEvent *)event
darin's avatar
darin committed
51 52 53
{
    EventModifiers modifiers;
    unsigned int modifierFlags = [event modifierFlags];
cblu's avatar
cblu committed
54
    NSEventType eventType = [event type];
darin's avatar
darin committed
55 56 57
    
    modifiers = 0;
    
cblu's avatar
cblu committed
58
    if (eventType != NSLeftMouseDown && eventType != NSRightMouseDown)
darin's avatar
darin committed
59 60 61 62 63 64 65 66 67 68 69 70 71 72
        modifiers |= btnState;
    
    if (modifierFlags & NSCommandKeyMask)
        modifiers |= cmdKey;
    
    if (modifierFlags & NSShiftKeyMask)
        modifiers |= shiftKey;

    if (modifierFlags & NSAlphaShiftKeyMask)
        modifiers |= alphaLock;

    if (modifierFlags & NSAlternateKeyMask)
        modifiers |= optionKey;

cblu's avatar
cblu committed
73
    if (modifierFlags & NSControlKeyMask || eventType == NSRightMouseDown)
darin's avatar
darin committed
74
        modifiers |= controlKey;
cblu's avatar
cblu committed
75
    
darin's avatar
darin committed
76 77 78
    return modifiers;
}

cblu's avatar
cblu committed
79
- (void)getCarbonEvent:(EventRecord *)carbonEvent withEvent:(NSEvent *)cocoaEvent
darin's avatar
darin committed
80
{
81
    if ([cocoaEvent _eventRef] && ConvertEventRefToEventRecord([cocoaEvent _eventRef], carbonEvent)) {
cblu's avatar
cblu committed
82 83
        return;
    }
84 85 86 87 88 89 90 91 92
    
    NSPoint where = [[cocoaEvent window] convertBaseToScreen:[cocoaEvent locationInWindow]];
        
    carbonEvent->what = nullEvent;
    carbonEvent->message = 0;
    carbonEvent->when = (UInt32)([cocoaEvent timestamp] * 60); // seconds to ticks
    carbonEvent->where.h = (short)where.x;
    carbonEvent->where.v = (short)(NSMaxY([[[NSScreen screens] objectAtIndex:0] frame]) - where.y);
    carbonEvent->modifiers = [self modifiersForEvent:cocoaEvent];
darin's avatar
darin committed
93 94
}

95
- (UInt32)keyMessageForEvent:(NSEvent *)event
96
{
97 98 99
    NSData *data = [[event characters] dataUsingEncoding:CFStringConvertEncodingToNSStringEncoding(CFStringGetSystemEncoding())];
    if (!data) {
        return 0;
100
    }
101 102 103 104
    UInt8 characterCode;
    [data getBytes:&characterCode length:1];
    UInt16 keyCode = [event keyCode];
    return keyCode << 8 | characterCode;
105 106
}

107 108
- (BOOL)sendEvent:(EventRecord *)event
{
109
    BOOL defers = [[self controller] _defersCallbacks];
110
    if (!defers) {
111
        [[self controller] _setDefersCallbacks:YES];
112 113
    }

114 115 116
    BOOL acceptedEvent = NO;
    if (NPP_HandleEvent) {
        acceptedEvent = NPP_HandleEvent(instance, event);
cblu's avatar
cblu committed
117
    }
118 119

    if (!defers) {
120
        [[self controller] _setDefersCallbacks:NO];
121 122 123 124 125 126
    }
    
    return acceptedEvent;
}

- (void)sendActivateEvent:(BOOL)activate
darin's avatar
darin committed
127 128 129 130 131
{
    EventRecord event;
    
    [self getCarbonEvent:&event];
    event.what = activateEvt;
132
    WindowRef windowRef = [[self window] windowRef];
133
    event.message = (UInt32)windowRef;
darin's avatar
darin committed
134
    if (activate)
135
        event.modifiers |= activeFlag;
darin's avatar
darin committed
136
    
cblu's avatar
cblu committed
137 138
    BOOL acceptedEvent;
    acceptedEvent = [self sendEvent:&event]; 
darin's avatar
darin committed
139
    
cblu's avatar
cblu committed
140
    LOG(Plugins, "NPP_HandleEvent(activateEvent): %d  isActive: %d", acceptedEvent, activate);
darin's avatar
darin committed
141 142
}

143
- (BOOL)sendUpdateEvent
darin's avatar
darin committed
144 145 146 147 148
{
    EventRecord event;
    
    [self getCarbonEvent:&event];
    event.what = updateEvt;
149
    WindowRef windowRef = [[self window] windowRef];
150
    event.message = (UInt32)windowRef;
darin's avatar
darin committed
151

152
    BOOL acceptedEvent = [self sendEvent:&event];
cblu's avatar
cblu committed
153

154
    LOG(Plugins, "NPP_HandleEvent(updateEvt): %d", acceptedEvent);
155

156
    return acceptedEvent;
darin's avatar
darin committed
157 158
}

159
- (BOOL)acceptsFirstResponder
darin's avatar
darin committed
160 161 162 163 164 165 166 167 168 169 170
{
    return YES;
}

- (BOOL)becomeFirstResponder
{
    EventRecord event;
    
    [self getCarbonEvent:&event];
    event.what = getFocusEvent;
    
cblu's avatar
cblu committed
171 172
    BOOL acceptedEvent;
    acceptedEvent = [self sendEvent:&event]; 
darin's avatar
darin committed
173
    
174
    LOG(Plugins, "NPP_HandleEvent(getFocusEvent): %d", acceptedEvent);
darin's avatar
darin committed
175 176 177 178 179 180 181 182 183 184
    return YES;
}

- (BOOL)resignFirstResponder
{
    EventRecord event;
    
    [self getCarbonEvent:&event];
    event.what = loseFocusEvent;
    
cblu's avatar
cblu committed
185 186
    BOOL acceptedEvent;
    acceptedEvent = [self sendEvent:&event]; 
darin's avatar
darin committed
187
    
188
    LOG(Plugins, "NPP_HandleEvent(loseFocusEvent): %d", acceptedEvent);
darin's avatar
darin committed
189 190 191
    return YES;
}

192
- (void)mouseDown:(NSEvent *)theEvent
darin's avatar
darin committed
193 194
{
    EventRecord event;
cblu's avatar
cblu committed
195

cblu's avatar
cblu committed
196
    [self getCarbonEvent:&event withEvent:theEvent];
darin's avatar
darin committed
197
    event.what = mouseDown;
cblu's avatar
cblu committed
198

cblu's avatar
cblu committed
199 200
    BOOL acceptedEvent;
    acceptedEvent = [self sendEvent:&event]; 
201
    
202
    LOG(Plugins, "NPP_HandleEvent(mouseDown): %d pt.v=%d, pt.h=%d", acceptedEvent, event.where.v, event.where.h);
darin's avatar
darin committed
203 204
}

205
- (void)mouseUp:(NSEvent *)theEvent
darin's avatar
darin committed
206 207 208
{
    EventRecord event;
    
cblu's avatar
cblu committed
209
    [self getCarbonEvent:&event withEvent:theEvent];
darin's avatar
darin committed
210 211
    event.what = mouseUp;

cblu's avatar
cblu committed
212 213
    BOOL acceptedEvent;
    acceptedEvent = [self sendEvent:&event]; 
darin's avatar
darin committed
214
    
215
    LOG(Plugins, "NPP_HandleEvent(mouseUp): %d pt.v=%d, pt.h=%d", acceptedEvent, event.where.v, event.where.h);
darin's avatar
darin committed
216 217 218 219 220 221 222 223 224
}

- (void)mouseEntered:(NSEvent *)theEvent
{
    EventRecord event;
    
    [self getCarbonEvent:&event withEvent:theEvent];
    event.what = adjustCursorEvent;

cblu's avatar
cblu committed
225 226
    BOOL acceptedEvent;
    acceptedEvent = [self sendEvent:&event]; 
darin's avatar
darin committed
227
    
228
    LOG(Plugins, "NPP_HandleEvent(mouseEntered): %d", acceptedEvent);
darin's avatar
darin committed
229 230 231 232 233
}

- (void)mouseExited:(NSEvent *)theEvent
{
    EventRecord event;
cblu's avatar
cblu committed
234
        
darin's avatar
darin committed
235 236 237
    [self getCarbonEvent:&event withEvent:theEvent];
    event.what = adjustCursorEvent;

cblu's avatar
cblu committed
238 239
    BOOL acceptedEvent;
    acceptedEvent = [self sendEvent:&event]; 
darin's avatar
darin committed
240
    
241
    LOG(Plugins, "NPP_HandleEvent(mouseExited): %d", acceptedEvent);
cblu's avatar
cblu committed
242 243 244
    
    // Set cursor back to arrow cursor.
    [[NSCursor arrowCursor] set];
darin's avatar
darin committed
245 246
}

247 248 249 250 251
- (void)mouseDragged:(NSEvent *)theEvent
{
    // Do nothing so that other responders don't respond to the drag that initiated in this view.
}

darin's avatar
darin committed
252 253 254
- (void)keyUp:(NSEvent *)theEvent
{
    EventRecord event;
255

darin's avatar
darin committed
256 257
    [self getCarbonEvent:&event withEvent:theEvent];
    event.what = keyUp;
cblu's avatar
cblu committed
258

259
    if (event.message == 0) {
cblu's avatar
cblu committed
260 261
        event.message = [self keyMessageForEvent:theEvent];
    }
262
    
263
    BOOL acceptedEvent = [self sendEvent:&event];
cblu's avatar
cblu committed
264

265
    LOG(Plugins, "NPP_HandleEvent(keyUp): %d charCode:%c keyCode:%lu",
cblu's avatar
cblu committed
266
                     acceptedEvent, (char) (event.message & charCodeMask), (event.message & keyCodeMask));
cblu's avatar
WebKit:  
cblu committed
267
    
268 269
    // If the plug-in didn't accept this event,
    // pass it along so that keyboard scrolling, for example, will work.
cblu's avatar
cblu committed
270
    if (!acceptedEvent){
271
        [super keyUp:theEvent];
cblu's avatar
cblu committed
272
    }
darin's avatar
darin committed
273 274 275 276 277
}

- (void)keyDown:(NSEvent *)theEvent
{
    EventRecord event;
278 279 280 281 282 283

    // Some command keys are sent with both performKeyEquivalent and keyDown.
    // We should send only 1 keyDown to the plug-in, so we'll ignore this one.
    if([theEvent modifierFlags] & NSCommandKeyMask){
        return;
    }
darin's avatar
darin committed
284 285 286
    
    [self getCarbonEvent:&event withEvent:theEvent];
    event.what = keyDown;
cblu's avatar
cblu committed
287

288
    if (event.message == 0) {
cblu's avatar
cblu committed
289 290
        event.message = [self keyMessageForEvent:theEvent];
    }
darin's avatar
darin committed
291
    
292
    BOOL acceptedEvent = [self sendEvent:&event];
cblu's avatar
cblu committed
293

294
    LOG(Plugins, "NPP_HandleEvent(keyDown): %d charCode:%c keyCode:%lu",
cblu's avatar
cblu committed
295
                     acceptedEvent, (char) (event.message & charCodeMask), (event.message & keyCodeMask));
cblu's avatar
WebKit:  
cblu committed
296
    
297 298
    // If the plug-in didn't accept this event,
    // pass it along so that keyboard scrolling, for example, will work.
cblu's avatar
cblu committed
299
    if (!acceptedEvent){
300
        [super keyDown:theEvent];
cblu's avatar
cblu committed
301 302 303
    }
}

cblu's avatar
WebKit:  
cblu committed
304 305 306 307 308 309 310 311 312 313 314 315 316
- (BOOL)isInResponderChain
{
    NSResponder *responder = [[self window] firstResponder];

    while(responder != nil){
        if(responder == self){
            return YES;
        }
        responder = [responder nextResponder];
    }
    return NO;
}

317 318 319
// Stop overriding performKeyEquivalent because the gain is not worth the frustation.
// Need to find a better way to pass command-modified keys to plug-ins. 3080103
#if 0
320
// Must subclass performKeyEquivalent: for command-modified keys to work.
321 322 323 324
- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
{
    EventRecord event;

cblu's avatar
WebKit:  
cblu committed
325 326 327 328
    if(![self isInResponderChain]){
        return NO;
    }
    
329 330 331
    [self getCarbonEvent:&event withEvent:theEvent];
    event.what = keyDown;

332
    if (event.message == 0) {
333 334 335
        event.message = [self keyMessageForEvent:theEvent];
    }

336
    BOOL acceptedEvent = [self sendEvent:&event];
337

338
    LOG(Plugins, "NPP_HandleEvent(performKeyEquivalent): %d charCode:%c keyCode:%lu",
339 340 341 342
                     acceptedEvent, (char) (event.message & charCodeMask), (event.message & keyCodeMask));
    
    return acceptedEvent;
}
343
#endif
344

345
#pragma mark WEB_NETSCAPE_PLUGIN
346

347 348
- (void)setUpWindowAndPort
{
349
    CGrafPtr port = GetWindowPort([[self window] windowRef]);
cblu's avatar
cblu committed
350
    NSRect contentViewFrame = [[[self window] contentView] frame];
351
    NSRect boundsInWindow = [self convertRect:[self bounds] toView:nil];
cblu's avatar
cblu committed
352
    NSRect visibleRectInWindow = [self convertRect:[self visibleRect] toView:nil];
353 354
    
    // flip Y coordinates
cblu's avatar
cblu committed
355 356
    boundsInWindow.origin.y = contentViewFrame.size.height - boundsInWindow.origin.y - boundsInWindow.size.height; 
    visibleRectInWindow.origin.y = contentViewFrame.size.height - visibleRectInWindow.origin.y - visibleRectInWindow.size.height;
357
    
cblu's avatar
WebKit:  
cblu committed
358
    nPort.port = port;
359
    
cblu's avatar
WebKit:  
cblu committed
360
    // FIXME: Are these values correct? Without them, Flash freaks.
361 362
    nPort.portx = (int32)-boundsInWindow.origin.x;
    nPort.porty = (int32)-boundsInWindow.origin.y;
363
    
364 365
    window.window = &nPort;
    
366 367
    window.x = (int32)boundsInWindow.origin.x; 
    window.y = (int32)boundsInWindow.origin.y;
368

369 370
    window.width = (uint32)boundsInWindow.size.width;
    window.height = (uint32)boundsInWindow.size.height;
371

372
    window.clipRect.top = (uint16)visibleRectInWindow.origin.y;
373 374 375
    window.clipRect.left = (uint16)visibleRectInWindow.origin.x;
    window.clipRect.bottom = (uint16)(visibleRectInWindow.origin.y + visibleRectInWindow.size.height);
    window.clipRect.right = (uint16)(visibleRectInWindow.origin.x + visibleRectInWindow.size.width);
376
    
377
    window.type = NPWindowTypeWindow;
378 379
}

380
- (void)setWindow
381 382 383
{
    [self setUpWindowAndPort];

cblu's avatar
cblu committed
384
    NPError npErr;
cblu's avatar
cblu committed
385
    npErr = NPP_SetWindow(instance, &window);
386
    LOG(Plugins, "NPP_SetWindow: %d, port=0x%08x, window.x:%d window.y:%d",
cblu's avatar
WebKit:  
cblu committed
387
                     npErr, (int)nPort.port, (int)window.x, (int)window.y);
cblu's avatar
WebKit:  
cblu committed
388 389

#if 0
390
    // Draw test    
cblu's avatar
WebKit:  
cblu committed
391
    Rect portRect;
392 393
    GetPortBounds(nPort.port, &portRect);
    SetPort(nPort.port);
cblu's avatar
WebKit:  
cblu committed
394 395 396
    MoveTo(0,0);
    LineTo(portRect.right, portRect.bottom);
#endif
397 398
}

399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
- (void)removeTrackingRect
{
    if (trackingTag) {
        [self removeTrackingRect:trackingTag];
        // Must release the window to balance the retain in resetTrackingRect.
        [[self window] release];
        trackingTag = 0;
    }
}

- (void)resetTrackingRect
{
    [self removeTrackingRect];
    if (isStarted) {
        // Must retain the window so that removeTrackingRect can work after the window is closed.
        [[self window] retain];
        trackingTag = [self addTrackingRect:[self bounds] owner:self userData:nil assumeInside:NO];
    }
}

cblu's avatar
cblu committed
419 420
-(void)start
{
421
    if (isStarted || !canRestart || NPP_New == 0){
cblu's avatar
cblu committed
422
        return;
423
    }
424
    
425 426
    isStarted = YES;
    
cblu's avatar
cblu committed
427 428
    NPError npErr;
    npErr = NPP_New((char *)[MIMEType cString], instance, mode, argsCount, cAttributes, cValues, NULL);
429
    LOG(Plugins, "NPP_New: %d", npErr);
430 431
    
    // Create a WindowRef is one doesn't already exist
432
    [[self window] windowRef];
cblu's avatar
cblu committed
433 434 435
        
    [self setWindow];
    
436 437
    NSWindow *theWindow = [self window];
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
438 439 440 441 442 443 444
    NSView *view;
    for (view = self; view; view = [view superview]) {
        [notificationCenter addObserver:self selector:@selector(viewHasMoved:) 
            name:NSViewFrameDidChangeNotification object:view];
        [notificationCenter addObserver:self selector:@selector(viewHasMoved:) 
            name:NSViewBoundsDidChangeNotification object:view];
    }
445
    [notificationCenter addObserver:self selector:@selector(windowWillClose:)
446
        name:NSWindowWillCloseNotification object:theWindow];
cblu's avatar
 
cblu committed
447
    [notificationCenter addObserver:self selector:@selector(windowBecameKey:) 
448
        name:NSWindowDidBecomeKeyNotification object:theWindow];
cblu's avatar
 
cblu committed
449
    [notificationCenter addObserver:self selector:@selector(windowResignedKey:) 
450
        name:NSWindowDidResignKeyNotification object:theWindow];
cblu's avatar
 
cblu committed
451
    [notificationCenter addObserver:self selector:@selector(defaultsHaveChanged:) 
452
        name:NSUserDefaultsDidChangeNotification object:nil];
453 454 455 456
    [notificationCenter addObserver:self selector:@selector(windowDidMiniaturize:)
        name:NSWindowDidMiniaturizeNotification object:theWindow];
    [notificationCenter addObserver:self selector:@selector(windowDidDeminiaturize:)
        name:NSWindowDidDeminiaturizeNotification object:theWindow];
sullivan's avatar
WebKit:  
sullivan committed
457

458
    if ([theWindow isKeyWindow]) {
459
        [self sendActivateEvent:YES];
cblu's avatar
WebKit:  
cblu committed
460 461
    }
    
462
    eventSender = [[WebNetscapePluginNullEventSender alloc] initWithPluginView:self];
463 464 465
    if (![theWindow isMiniaturized]) {
        [eventSender sendNullEvents];
    }
466
    [self resetTrackingRect];
cblu's avatar
cblu committed
467
}
468

cblu's avatar
cblu committed
469
- (void)stop
470
{
471
    [self removeTrackingRect];
472 473

    if (!isStarted){
cblu's avatar
cblu committed
474
        return;
475 476
    }
    
cblu's avatar
cblu committed
477
    isStarted = NO;
cblu's avatar
WebKit:  
cblu committed
478

cblu's avatar
cblu committed
479
    // Stop any active streams
cblu's avatar
WebKit:  
cblu committed
480
    [streams makeObjectsPerformSelector:@selector(stop)];
cblu's avatar
cblu committed
481 482
    
    // Stop the null events
cblu's avatar
cblu committed
483 484
    [eventSender stop];
    [eventSender release];
cblu's avatar
cblu committed
485 486 487 488 489 490 491

    // Set cursor back to arrow cursor
    [[NSCursor arrowCursor] set];
    
    // Stop notifications
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    
kocienda's avatar
kocienda committed
492 493
    NPError npErr;
    npErr = NPP_Destroy(instance, NULL);
494
    LOG(Plugins, "NPP_Destroy: %d", npErr);
495 496
}

497
- (WebDataSource *)dataSource
cblu's avatar
WebKit:  
cblu committed
498
{
499 500
    // Do nothing. Overridden by subclasses.
    return nil;
cblu's avatar
WebKit:  
cblu committed
501 502
}

503
- (WebFrame *)webFrame
cblu's avatar
WebKit:  
cblu committed
504
{
505
    return [[self dataSource] webFrame];
cblu's avatar
WebKit:  
cblu committed
506 507
}

508 509 510 511
- (WebController *)controller
{
    return [[self webFrame] controller];
}
cblu's avatar
cblu committed
512

513 514 515 516 517
- (NPP)pluginPointer
{
    return instance;
}

518
- (WebNetscapePluginPackage *)plugin
cblu's avatar
cblu committed
519
{
520
    return plugin;
cblu's avatar
cblu committed
521 522
}

523
- (void)setPlugin:(WebNetscapePluginPackage *)thePlugin;
cblu's avatar
cblu committed
524
{
525 526 527
    [plugin release];
    plugin = [thePlugin retain];

cblu's avatar
cblu committed
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
    NPP_New = 		[plugin NPP_New];
    NPP_Destroy = 	[plugin NPP_Destroy];
    NPP_SetWindow = 	[plugin NPP_SetWindow];
    NPP_NewStream = 	[plugin NPP_NewStream];
    NPP_WriteReady = 	[plugin NPP_WriteReady];
    NPP_Write = 	[plugin NPP_Write];
    NPP_StreamAsFile = 	[plugin NPP_StreamAsFile];
    NPP_DestroyStream = [plugin NPP_DestroyStream];
    NPP_HandleEvent = 	[plugin NPP_HandleEvent];
    NPP_URLNotify = 	[plugin NPP_URLNotify];
    NPP_GetValue = 	[plugin NPP_GetValue];
    NPP_SetValue = 	[plugin NPP_SetValue];
    NPP_Print = 	[plugin NPP_Print];
}

543
- (void)setMIMEType:(NSString *)theMIMEType
cblu's avatar
cblu committed
544
{
545 546
    [MIMEType release];
    MIMEType = [theMIMEType retain];
cblu's avatar
cblu committed
547
}
548 549

- (void)setBaseURL:(NSURL *)theBaseURL
550
{
551 552
    [baseURL release];
    baseURL = [theBaseURL retain];
553 554
}

cblu's avatar
cblu committed
555
- (void)setAttributes:(NSDictionary *)attributes
cblu's avatar
cblu committed
556
{
cblu's avatar
cblu committed
557
    LOG(Plugins, "%@", attributes);
558

559 560 561 562 563 564
    // Convert arguments dictionary to 2 string arrays.
    // These arrays are passed to NPP_New, but the strings need to be
    // modifiable and live the entire life of the plugin.

    // The Java plug-in requires the first argument to be the base URL
    if ([MIMEType isEqualToString:@"application/x-java-applet"]) {
cblu's avatar
cblu committed
565 566
        cAttributes = (char **)malloc(([attributes count] + 1) * sizeof(char *));
        cValues = (char **)malloc(([attributes count] + 1) * sizeof(char *));
567 568 569 570
        cAttributes[0] = strdup("DOCBASE");
        cValues[0] = strdup([[baseURL absoluteString] UTF8String]);
        argsCount++;
    } else {
cblu's avatar
cblu committed
571 572
        cAttributes = (char **)malloc([attributes count] * sizeof(char *));
        cValues = (char **)malloc([attributes count] * sizeof(char *));
573 574
    }

cblu's avatar
cblu committed
575
    NSEnumerator *e = [attributes keyEnumerator];
576 577 578
    NSString *key;
    while ((key = [e nextObject])) {
        cAttributes[argsCount] = strdup([key UTF8String]);
cblu's avatar
cblu committed
579
        cValues[argsCount] = strdup([[attributes objectForKey:key] UTF8String]);
580 581 582 583 584 585 586
        argsCount++;
    }
}

- (void)setMode:(int)theMode
{
    mode = theMode;
cblu's avatar
cblu committed
587 588
}

589 590
#pragma mark NSVIEW

591 592 593 594 595 596 597 598 599 600
- initWithFrame:(NSRect)frame
{
    [super initWithFrame:frame];

    instance = &instanceStruct;
    instance->ndata = self;

    canRestart = YES;

    streams = [[NSMutableArray alloc] init];
601
    streamNotifications = [[NSMutableDictionary alloc] init];
602 603 604 605 606

    return self;
}

-(void)dealloc
607
{
608 609 610 611 612 613 614
    unsigned i;

    [self stop];

    for (i = 0; i < argsCount; i++) {
        free(cAttributes[i]);
        free(cValues[i]);
615
    }
616 617 618 619
    [streams removeAllObjects];
    [streams release];
    [MIMEType release];
    [baseURL release];
620 621
    [streamNotifications removeAllObjects];
    [streamNotifications release];
622 623 624 625
    free(cAttributes);
    free(cValues);
    [super dealloc];
}
626

627 628
- (void)drawRect:(NSRect)rect
{
629 630 631 632 633
    if (!isStarted) {
        return;
    }
    
    if([NSGraphicsContext currentContextDrawingToScreen]){
634 635 636 637 638 639 640 641 642 643 644 645
        // AppKit tried to help us by doing a BeginUpdate.
        // But the invalid region at that level didn't include AppKit's notion of what was not valid.
        // We reset the port's visible region to counteract what BeginUpdate did.
        RgnHandle savedVisibleRegion = NewRgn();
        GetPortVisibleRegion(nPort.port, savedVisibleRegion);
        Rect portBounds;
        GetPortBounds(nPort.port, &portBounds);
        RgnHandle portBoundsAsRegion = NewRgn();
        RectRgn(portBoundsAsRegion, &portBounds);
        SetPortVisibleRegion(nPort.port, portBoundsAsRegion);
        DisposeRgn(portBoundsAsRegion);
        
646
        [self sendUpdateEvent];
647 648 649

        SetPortVisibleRegion(nPort.port, savedVisibleRegion);
        DisposeRgn(savedVisibleRegion);
650
    }else{
651
        // Printing 2862383
652
    }
653 654 655 656 657 658 659
}

- (BOOL)isFlipped
{
    return YES;
}

660 661 662 663 664 665 666 667
- (void)viewWillMoveToWindow:(NSWindow *)newWindow
{
    // We must remove the tracking rect before we move to the new window.
    // Once we move to the new window, it will be too late.
    [self removeTrackingRect];
    [super viewWillMoveToWindow:newWindow];
}

668
- (void)viewDidMoveToWindow
cblu's avatar
cblu committed
669
{
670
    if (![self window]) {
darin's avatar
darin committed
671
        [self stop];
cblu's avatar
WebKit:  
cblu committed
672 673
    }
    
674
    [self resetTrackingRect];
cblu's avatar
cblu committed
675 676
}

cblu's avatar
cblu committed
677 678
#pragma mark NOTIFICATIONS

679
-(void)viewHasMoved:(NSNotification *)notification
cblu's avatar
cblu committed
680
{
681
    [self setUpWindowAndPort];
682
    [self resetTrackingRect];
cblu's avatar
cblu committed
683 684
}

685
-(void)windowWillClose:(NSNotification *)notification
686 687 688 689
{
    [self stop];
}

690
-(void)windowBecameKey:(NSNotification *)notification
cblu's avatar
cblu committed
691
{
692
    [self sendActivateEvent:YES];
693
    [self sendUpdateEvent];
cblu's avatar
cblu committed
694 695
}

696
-(void)windowResignedKey:(NSNotification *)notification
cblu's avatar
cblu committed
697
{
698
    [self sendActivateEvent:NO];
699
    [self sendUpdateEvent];
cblu's avatar
cblu committed
700 701
}

702 703 704 705 706 707 708 709 710 711
-(void)windowDidMiniaturize:(NSNotification *)notification
{
    [eventSender stop];
}

-(void)windowDidDeminiaturize:(NSNotification *)notification
{
    [eventSender sendNullEvents];
}

712
- (void)defaultsHaveChanged:(NSNotification *)notification
cblu's avatar
cblu committed
713 714
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
715
    if ([defaults boolForKey:@"WebKitPluginsEnabled"]) {
cblu's avatar
cblu committed
716 717
        canRestart = YES;
        [self start];
718
    } else {
cblu's avatar
cblu committed
719 720 721 722 723 724
        canRestart = NO;
        [self stop];
        [self setNeedsDisplay:YES];
    }
}

725
- (void)frameStateChanged:(NSNotification *)notification
cblu's avatar
cblu committed
726
{
727 728 729
    WebFrame *frame = [notification object];
    NSURL *URL = [[[frame dataSource] request] URL];
    NSValue *notifyDataValue = [streamNotifications objectForKey:URL];
cblu's avatar
cblu committed
730
    
731
    if(!notifyDataValue){
cblu's avatar
cblu committed
732
        return;
733
    }
cblu's avatar
cblu committed
734
    
735 736
    void *notifyData = [notifyDataValue pointerValue];
    WebFrameState frameState = [[[notification userInfo] objectForKey:WebCurrentFrameState] intValue];
737
    if (frameState == WebFrameStateComplete) {
darin's avatar
darin committed
738
        NPP_URLNotify(instance, [[URL absoluteString] cString], NPRES_DONE, notifyData);
739
        [streamNotifications removeObjectForKey:URL];
cblu's avatar
cblu committed
740 741
    }
    //FIXME: Need to send other NPReasons
cblu's avatar
cblu committed
742 743
}

744 745
@end

746
@implementation WebBaseNetscapePluginView (WebNPPCallbacks)
747

kocienda's avatar
kocienda committed
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764
- (NSURL *)pluginURLFromCString:(const char *)URLCString
{
    NSString *URLString;
    NSURL *URL;

    URLString = [NSString stringWithCString:URLCString];

    if ([URLString _web_looksLikeAbsoluteURL]) {
        URL = [NSURL _web_URLWithString:URLString];
    }
    else {
        URL = [NSURL _web_URLWithString:URLString relativeToURL:baseURL];
    }
    
    return URL;
}

765
- (NPError)loadRequest:(WebResourceRequest *)request inTarget:(NSString *)target withNotifyData:(void *)notifyData
766
{
767
    NSURL *URL = [request URL];
768

mjs's avatar
WebKit:  
mjs committed
769
    if (!URL) {
770
        return NPERR_INVALID_URL;
771
    }
772
    
mjs's avatar
WebKit:  
mjs committed
773
    if (!target) {
774 775 776
        WebNetscapePluginStream *stream = [[WebNetscapePluginStream alloc] initWithRequest:request
                                                                             pluginPointer:instance
                                                                                notifyData:notifyData];
mjs's avatar
WebKit:  
mjs committed
777
        if (stream) {
cblu's avatar
WebKit:  
cblu committed
778
            [streams addObject:stream];
779
            [stream start];
cblu's avatar
WebKit:  
cblu committed
780
            [stream release];
mjs's avatar
WebKit:  
mjs committed
781
        } else {
cblu's avatar
cblu committed
782
            return NPERR_INVALID_URL;
cblu's avatar
WebKit:  
cblu committed
783
        }
mjs's avatar
WebKit:  
mjs committed
784
    } else {
785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
        if([[URL scheme] isEqualToString:@"javascript"]){
            NSString *JSString = [[URL absoluteString] substringFromIndex:11];
            [[self controller] stringByEvaluatingJavaScriptFromString:JSString];
            if(notifyData){
               NPP_URLNotify(instance, [[URL absoluteString] cString], NPRES_DONE, notifyData);
            }
        }else{
            WebFrame *frame = [[self webFrame] findOrCreateFramedNamed:target];
            [frame loadRequest:request];
    
            if (notifyData) {
                if (![target isEqualToString:@"_self"] && ![target isEqualToString:@"_current"] &&
                    ![target isEqualToString:@"_parent"] && ![target isEqualToString:@"_top"]) {
                    
                    [streamNotifications setObject:[NSValue valueWithPointer:notifyData] forKey:URL];
                    [[NSNotificationCenter defaultCenter] addObserver:self
                                                             selector:@selector(frameStateChanged:)
                                                                 name:WebFrameStateChangedNotification
                                                               object:frame];
                }
            }
        }
807
    }
cblu's avatar
cblu committed
808
    
809
    return NPERR_NO_ERROR;
810 811
}

darin's avatar
darin committed
812
-(NPError)getURLNotify:(const char *)URL target:(const char *)target notifyData:(void *)notifyData
cblu's avatar
cblu committed
813 814
{
    NSString *theTarget = nil;
kocienda's avatar
kocienda committed
815 816
    NSURL *pluginURL;
    WebResourceRequest *request;
cblu's avatar
cblu committed
817
        
818
    LOG(Plugins, "NPN_GetURLNotify: %s target: %s", URL, target);
cblu's avatar
cblu committed
819
        
darin's avatar
darin committed
820
    if(!URL)
cblu's avatar
cblu committed
821 822 823
        return NPERR_INVALID_URL;
        
    if(target)
824
        theTarget = [NSString stringWithCString:target];
kocienda's avatar
kocienda committed
825 826 827 828 829 830 831

    pluginURL = [self pluginURLFromCString:URL]; 

    if(!pluginURL)
        return NPERR_INVALID_URL;
        
    request = [[[WebResourceRequest alloc] initWithURL:pluginURL] autorelease];
cblu's avatar
cblu committed
832
    
kocienda's avatar
kocienda committed
833
    return [self loadRequest:request inTarget:theTarget withNotifyData:notifyData];
cblu's avatar
cblu committed
834 835
}

darin's avatar
darin committed
836
-(NPError)getURL:(const char *)URL target:(const char *)target
837
{
cblu's avatar
cblu committed
838
    NSString *theTarget = nil;
kocienda's avatar
kocienda committed
839 840
    NSURL *pluginURL;
    WebResourceRequest *request;
cblu's avatar
cblu committed
841
    
842
    LOG(Plugins, "NPN_GetURL: %s target: %s", URL, target);
cblu's avatar
cblu committed
843
    
darin's avatar
darin committed
844
    if(!URL)
cblu's avatar
cblu committed
845 846 847
        return NPERR_INVALID_URL;
        
    if(target)
848
        theTarget = [NSString stringWithCString:target];
kocienda's avatar
kocienda committed
849 850 851 852 853 854 855

    pluginURL = [self pluginURLFromCString:URL]; 

    if(!pluginURL)
        return NPERR_INVALID_URL;
        
    request = [[[WebResourceRequest alloc] initWithURL:pluginURL] autorelease];
cblu's avatar
cblu committed
856
    
kocienda's avatar
kocienda committed
857
    return [self loadRequest:request inTarget:theTarget withNotifyData:NULL];
858 859
}

darin's avatar
darin committed
860
-(NPError)postURLNotify:(const char *)URL target:(const char *)target len:(UInt32)len buf:(const char *)buf file:(NPBool)file notifyData:(void *)notifyData
861
{
cblu's avatar
WebKit:  
cblu committed
862
    NSData *postData;