WebBaseNetscapePluginView.m 27.8 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
#import <WebKit/WebNetscapePluginStream.h>
14
15
#import <WebKit/WebNullPluginView.h>
#import <WebKit/WebNSViewExtras.h>
16
#import <WebKit/WebNetscapePluginPackage.h>
17
#import <WebKit/WebView.h>
18
#import <WebKit/WebWindowOperationsDelegate.h>
19

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

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

28
29
30
31
// FIXME: Why .01? Why not 0? Why not a larger number?
#define NullEventIntervalActive 	0.1
#define NullEventIntervalNotActive	0.25

32
@implementation WebBaseNetscapePluginView
33

darin's avatar
darin committed
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#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
52
- (EventModifiers)modifiersForEvent:(NSEvent *)event
darin's avatar
darin committed
53
54
55
{
    EventModifiers modifiers;
    unsigned int modifierFlags = [event modifierFlags];
cblu's avatar
cblu committed
56
    NSEventType eventType = [event type];
darin's avatar
darin committed
57
58
59
    
    modifiers = 0;
    
cblu's avatar
cblu committed
60
    if (eventType != NSLeftMouseDown && eventType != NSRightMouseDown)
darin's avatar
darin committed
61
62
63
64
65
66
67
68
69
70
71
72
73
74
        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
75
    if (modifierFlags & NSControlKeyMask || eventType == NSRightMouseDown)
darin's avatar
darin committed
76
        modifiers |= controlKey;
cblu's avatar
cblu committed
77
    
darin's avatar
darin committed
78
79
80
    return modifiers;
}

cblu's avatar
cblu committed
81
- (void)getCarbonEvent:(EventRecord *)carbonEvent withEvent:(NSEvent *)cocoaEvent
darin's avatar
darin committed
82
{
83
    if ([cocoaEvent _eventRef] && ConvertEventRefToEventRecord([cocoaEvent _eventRef], carbonEvent)) {
cblu's avatar
cblu committed
84
85
        return;
    }
86
87
88
89
90
91
92
93
94
    
    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
95
96
}

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

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

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

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

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

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

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

156
    LOG(Plugins, "NPP_HandleEvent(updateEvt): %d", acceptedEvent);
157

158
    return acceptedEvent;
darin's avatar
darin committed
159
160
}

161
162
163
164
165
166
-(void)sendNullEvent
{
    EventRecord event;

    [self getCarbonEvent:&event];

167
168
169
170
171
172
173
174
    // Plug-in should not react to cursor position when not active or when a menu is down.
    MenuTrackingData trackingData;
    OSStatus error = GetMenuTrackingData(NULL, &trackingData);
    
    if (![_window isKeyWindow] || (error == noErr && trackingData.menu)){
        // FIXME: How does passing a v and h of 0 prevent it from reacting to the cursor position?
        event.where.v = -1;
        event.where.h = -1;
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
    }

    [self sendEvent:&event];
}

- (void)stopNullEvents
{
    [nullEventTimer invalidate];
    [nullEventTimer release];
    nullEventTimer = nil;
}

- (void)restartNullEvents
{
    if(nullEventTimer){
        [self stopNullEvents];
    }

    NSTimeInterval interval;
    
195
    if ([_window isKeyWindow]){
196
197
198
199
200
201
202
203
204
205
206
207
        interval = NullEventIntervalActive;
    }else{
        interval = NullEventIntervalNotActive;
    }
    
    nullEventTimer = [[NSTimer scheduledTimerWithTimeInterval:interval
                                                       target:self
                                                     selector:@selector(sendNullEvent)
                                                     userInfo:nil
                                                      repeats:YES] retain];
}

208
- (BOOL)acceptsFirstResponder
darin's avatar
darin committed
209
210
211
212
213
214
215
216
217
218
219
{
    return YES;
}

- (BOOL)becomeFirstResponder
{
    EventRecord event;
    
    [self getCarbonEvent:&event];
    event.what = getFocusEvent;
    
cblu's avatar
cblu committed
220
221
    BOOL acceptedEvent;
    acceptedEvent = [self sendEvent:&event]; 
darin's avatar
darin committed
222
    
223
    LOG(Plugins, "NPP_HandleEvent(getFocusEvent): %d", acceptedEvent);
darin's avatar
darin committed
224
225
226
227
228
229
230
231
232
233
    return YES;
}

- (BOOL)resignFirstResponder
{
    EventRecord event;
    
    [self getCarbonEvent:&event];
    event.what = loseFocusEvent;
    
cblu's avatar
cblu committed
234
235
    BOOL acceptedEvent;
    acceptedEvent = [self sendEvent:&event]; 
darin's avatar
darin committed
236
    
237
    LOG(Plugins, "NPP_HandleEvent(loseFocusEvent): %d", acceptedEvent);
darin's avatar
darin committed
238
239
240
    return YES;
}

241
- (void)mouseDown:(NSEvent *)theEvent
darin's avatar
darin committed
242
243
{
    EventRecord event;
cblu's avatar
cblu committed
244

cblu's avatar
cblu committed
245
    [self getCarbonEvent:&event withEvent:theEvent];
darin's avatar
darin committed
246
    event.what = mouseDown;
cblu's avatar
cblu committed
247

cblu's avatar
cblu committed
248
249
    BOOL acceptedEvent;
    acceptedEvent = [self sendEvent:&event]; 
250
    
251
    LOG(Plugins, "NPP_HandleEvent(mouseDown): %d pt.v=%d, pt.h=%d", acceptedEvent, event.where.v, event.where.h);
darin's avatar
darin committed
252
253
}

254
- (void)mouseUp:(NSEvent *)theEvent
darin's avatar
darin committed
255
256
257
{
    EventRecord event;
    
cblu's avatar
cblu committed
258
    [self getCarbonEvent:&event withEvent:theEvent];
darin's avatar
darin committed
259
260
    event.what = mouseUp;

cblu's avatar
cblu committed
261
262
    BOOL acceptedEvent;
    acceptedEvent = [self sendEvent:&event]; 
darin's avatar
darin committed
263
    
264
    LOG(Plugins, "NPP_HandleEvent(mouseUp): %d pt.v=%d, pt.h=%d", acceptedEvent, event.where.v, event.where.h);
darin's avatar
darin committed
265
266
267
268
269
270
271
272
273
}

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

cblu's avatar
cblu committed
274
275
    BOOL acceptedEvent;
    acceptedEvent = [self sendEvent:&event]; 
darin's avatar
darin committed
276
    
277
    LOG(Plugins, "NPP_HandleEvent(mouseEntered): %d", acceptedEvent);
darin's avatar
darin committed
278
279
280
281
282
}

- (void)mouseExited:(NSEvent *)theEvent
{
    EventRecord event;
cblu's avatar
cblu committed
283
        
darin's avatar
darin committed
284
285
286
    [self getCarbonEvent:&event withEvent:theEvent];
    event.what = adjustCursorEvent;

cblu's avatar
cblu committed
287
288
    BOOL acceptedEvent;
    acceptedEvent = [self sendEvent:&event]; 
darin's avatar
darin committed
289
    
290
    LOG(Plugins, "NPP_HandleEvent(mouseExited): %d", acceptedEvent);
cblu's avatar
cblu committed
291
292
293
    
    // Set cursor back to arrow cursor.
    [[NSCursor arrowCursor] set];
darin's avatar
darin committed
294
295
}

296
297
298
299
300
- (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
301
302
303
- (void)keyUp:(NSEvent *)theEvent
{
    EventRecord event;
304

darin's avatar
darin committed
305
306
    [self getCarbonEvent:&event withEvent:theEvent];
    event.what = keyUp;
cblu's avatar
cblu committed
307

308
    if (event.message == 0) {
cblu's avatar
cblu committed
309
310
        event.message = [self keyMessageForEvent:theEvent];
    }
311
    
312
    BOOL acceptedEvent = [self sendEvent:&event];
cblu's avatar
cblu committed
313

314
    LOG(Plugins, "NPP_HandleEvent(keyUp): %d charCode:%c keyCode:%lu",
cblu's avatar
cblu committed
315
                     acceptedEvent, (char) (event.message & charCodeMask), (event.message & keyCodeMask));
cblu's avatar
WebKit:    
cblu committed
316
    
317
318
    // 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
319
    if (!acceptedEvent){
320
        [super keyUp:theEvent];
cblu's avatar
cblu committed
321
    }
darin's avatar
darin committed
322
323
324
325
326
}

- (void)keyDown:(NSEvent *)theEvent
{
    EventRecord event;
327
328
329
330
331
332

    // 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
333
334
335
    
    [self getCarbonEvent:&event withEvent:theEvent];
    event.what = keyDown;
cblu's avatar
cblu committed
336

337
    if (event.message == 0) {
cblu's avatar
cblu committed
338
339
        event.message = [self keyMessageForEvent:theEvent];
    }
darin's avatar
darin committed
340
    
341
    BOOL acceptedEvent = [self sendEvent:&event];
cblu's avatar
cblu committed
342

343
    LOG(Plugins, "NPP_HandleEvent(keyDown): %d charCode:%c keyCode:%lu",
cblu's avatar
cblu committed
344
                     acceptedEvent, (char) (event.message & charCodeMask), (event.message & keyCodeMask));
cblu's avatar
WebKit:    
cblu committed
345
    
346
347
    // 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
348
    if (!acceptedEvent){
349
        [super keyDown:theEvent];
cblu's avatar
cblu committed
350
351
352
    }
}

cblu's avatar
WebKit:    
cblu committed
353
354
355
356
357
358
359
360
361
362
363
364
365
- (BOOL)isInResponderChain
{
    NSResponder *responder = [[self window] firstResponder];

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

366
367
368
// 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
369
// Must subclass performKeyEquivalent: for command-modified keys to work.
370
371
372
373
- (BOOL)performKeyEquivalent:(NSEvent *)theEvent
{
    EventRecord event;

cblu's avatar
WebKit:    
cblu committed
374
375
376
377
    if(![self isInResponderChain]){
        return NO;
    }
    
378
379
380
    [self getCarbonEvent:&event withEvent:theEvent];
    event.what = keyDown;

381
    if (event.message == 0) {
382
383
384
        event.message = [self keyMessageForEvent:theEvent];
    }

385
    BOOL acceptedEvent = [self sendEvent:&event];
386

387
    LOG(Plugins, "NPP_HandleEvent(performKeyEquivalent): %d charCode:%c keyCode:%lu",
388
389
390
391
                     acceptedEvent, (char) (event.message & charCodeMask), (event.message & keyCodeMask));
    
    return acceptedEvent;
}
392
#endif
393

394
#pragma mark WEB_NETSCAPE_PLUGIN
395

396
397
- (void)setUpWindowAndPort
{
398
    CGrafPtr port = GetWindowPort([[self window] windowRef]);
cblu's avatar
cblu committed
399
    NSRect contentViewFrame = [[[self window] contentView] frame];
400
    NSRect boundsInWindow = [self convertRect:[self bounds] toView:nil];
cblu's avatar
cblu committed
401
    NSRect visibleRectInWindow = [self convertRect:[self visibleRect] toView:nil];
402
403
    
    // flip Y coordinates
cblu's avatar
cblu committed
404
405
    boundsInWindow.origin.y = contentViewFrame.size.height - boundsInWindow.origin.y - boundsInWindow.size.height; 
    visibleRectInWindow.origin.y = contentViewFrame.size.height - visibleRectInWindow.origin.y - visibleRectInWindow.size.height;
406
    
cblu's avatar
WebKit:    
cblu committed
407
    nPort.port = port;
408
    
cblu's avatar
WebKit:    
cblu committed
409
    // FIXME: Are these values correct? Without them, Flash freaks.
410
411
    nPort.portx = (int32)-boundsInWindow.origin.x;
    nPort.porty = (int32)-boundsInWindow.origin.y;
412
    
413
414
    window.window = &nPort;
    
415
416
    window.x = (int32)boundsInWindow.origin.x; 
    window.y = (int32)boundsInWindow.origin.y;
417

418
419
    window.width = (uint32)boundsInWindow.size.width;
    window.height = (uint32)boundsInWindow.size.height;
420

421
    window.clipRect.top = (uint16)visibleRectInWindow.origin.y;
422
423
424
    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);
425
    
426
    window.type = NPWindowTypeWindow;
427
428
}

429
- (void)setWindow
430
431
432
{
    [self setUpWindowAndPort];

cblu's avatar
cblu committed
433
    NPError npErr;
cblu's avatar
cblu committed
434
    npErr = NPP_SetWindow(instance, &window);
435
    LOG(Plugins, "NPP_SetWindow: %d, port=0x%08x, window.x:%d window.y:%d",
cblu's avatar
WebKit:    
cblu committed
436
                     npErr, (int)nPort.port, (int)window.x, (int)window.y);
cblu's avatar
WebKit:    
cblu committed
437
438

#if 0
439
    // Draw test    
cblu's avatar
WebKit:    
cblu committed
440
    Rect portRect;
441
442
    GetPortBounds(nPort.port, &portRect);
    SetPort(nPort.port);
cblu's avatar
WebKit:    
cblu committed
443
444
445
    MoveTo(0,0);
    LineTo(portRect.right, portRect.bottom);
#endif
446
447
}

448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
- (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
468
469
-(void)start
{
470
    if (isStarted || !canRestart || NPP_New == 0){
cblu's avatar
cblu committed
471
        return;
472
    }
473
    
474
475
    isStarted = YES;
    
cblu's avatar
cblu committed
476
477
    NPError npErr;
    npErr = NPP_New((char *)[MIMEType cString], instance, mode, argsCount, cAttributes, cValues, NULL);
478
    LOG(Plugins, "NPP_New: %d", npErr);
479
480
    
    // Create a WindowRef is one doesn't already exist
481
    [_window windowRef];
cblu's avatar
cblu committed
482
483
484
        
    [self setWindow];
    
485
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
486
487
488
489
490
491
492
    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];
    }
493
    [notificationCenter addObserver:self selector:@selector(windowWillClose:)
494
        name:NSWindowWillCloseNotification object:_window];
cblu's avatar
   
cblu committed
495
    [notificationCenter addObserver:self selector:@selector(windowBecameKey:) 
496
        name:NSWindowDidBecomeKeyNotification object:_window];
cblu's avatar
   
cblu committed
497
    [notificationCenter addObserver:self selector:@selector(windowResignedKey:) 
498
        name:NSWindowDidResignKeyNotification object:_window];
cblu's avatar
   
cblu committed
499
    [notificationCenter addObserver:self selector:@selector(defaultsHaveChanged:) 
500
        name:NSUserDefaultsDidChangeNotification object:nil];
501
    [notificationCenter addObserver:self selector:@selector(windowDidMiniaturize:)
502
        name:NSWindowDidMiniaturizeNotification object:_window];
503
    [notificationCenter addObserver:self selector:@selector(windowDidDeminiaturize:)
504
        name:NSWindowDidDeminiaturizeNotification object:_window];
sullivan's avatar
WebKit:    
sullivan committed
505

506
    if ([_window isKeyWindow]) {
507
        [self sendActivateEvent:YES];
cblu's avatar
WebKit:    
cblu committed
508
509
    }
    
510
511
    if (![_window isMiniaturized]) {
        [self restartNullEvents];
512
    }
513
    
514
    [self resetTrackingRect];
cblu's avatar
cblu committed
515
}
516

cblu's avatar
cblu committed
517
- (void)stop
518
{
519
    [self removeTrackingRect];
520
521

    if (!isStarted){
cblu's avatar
cblu committed
522
        return;
523
524
    }
    
cblu's avatar
cblu committed
525
    isStarted = NO;
cblu's avatar
WebKit:    
cblu committed
526

cblu's avatar
cblu committed
527
    // Stop any active streams
cblu's avatar
WebKit:    
cblu committed
528
    [streams makeObjectsPerformSelector:@selector(stop)];
cblu's avatar
cblu committed
529
530
    
    // Stop the null events
531
    [self stopNullEvents];
cblu's avatar
cblu committed
532
533
534
535
536
537
538

    // Set cursor back to arrow cursor
    [[NSCursor arrowCursor] set];
    
    // Stop notifications
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    
kocienda's avatar
kocienda committed
539
540
    NPError npErr;
    npErr = NPP_Destroy(instance, NULL);
541
    LOG(Plugins, "NPP_Destroy: %d", npErr);
542
543
}

544
- (WebDataSource *)dataSource
cblu's avatar
WebKit:    
cblu committed
545
{
546
547
    // Do nothing. Overridden by subclasses.
    return nil;
cblu's avatar
WebKit:    
cblu committed
548
549
}

550
- (WebFrame *)webFrame
cblu's avatar
WebKit:    
cblu committed
551
{
552
    return [[self dataSource] webFrame];
cblu's avatar
WebKit:    
cblu committed
553
554
}

555
556
557
558
- (WebController *)controller
{
    return [[self webFrame] controller];
}
cblu's avatar
cblu committed
559

560
561
562
563
564
- (NPP)pluginPointer
{
    return instance;
}

565
- (WebNetscapePluginPackage *)plugin
cblu's avatar
cblu committed
566
{
567
    return plugin;
cblu's avatar
cblu committed
568
569
}

570
- (void)setPlugin:(WebNetscapePluginPackage *)thePlugin;
cblu's avatar
cblu committed
571
{
572
573
574
    [plugin release];
    plugin = [thePlugin retain];

cblu's avatar
cblu committed
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
    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];
}

590
- (void)setMIMEType:(NSString *)theMIMEType
cblu's avatar
cblu committed
591
{
592
593
    [MIMEType release];
    MIMEType = [theMIMEType retain];
cblu's avatar
cblu committed
594
}
595
596

- (void)setBaseURL:(NSURL *)theBaseURL
597
{
598
599
    [baseURL release];
    baseURL = [theBaseURL retain];
600
601
}

cblu's avatar
cblu committed
602
- (void)setAttributes:(NSDictionary *)attributes
cblu's avatar
cblu committed
603
{
cblu's avatar
cblu committed
604
    LOG(Plugins, "%@", attributes);
605

606
607
608
609
610
611
    // 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
612
613
        cAttributes = (char **)malloc(([attributes count] + 1) * sizeof(char *));
        cValues = (char **)malloc(([attributes count] + 1) * sizeof(char *));
614
615
616
617
        cAttributes[0] = strdup("DOCBASE");
        cValues[0] = strdup([[baseURL absoluteString] UTF8String]);
        argsCount++;
    } else {
cblu's avatar
cblu committed
618
619
        cAttributes = (char **)malloc([attributes count] * sizeof(char *));
        cValues = (char **)malloc([attributes count] * sizeof(char *));
620
621
    }

cblu's avatar
cblu committed
622
    NSEnumerator *e = [attributes keyEnumerator];
623
624
625
    NSString *key;
    while ((key = [e nextObject])) {
        cAttributes[argsCount] = strdup([key UTF8String]);
cblu's avatar
cblu committed
626
        cValues[argsCount] = strdup([[attributes objectForKey:key] UTF8String]);
627
628
629
630
631
632
633
        argsCount++;
    }
}

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

636
637
#pragma mark NSVIEW

638
639
640
641
642
643
644
645
646
647
- initWithFrame:(NSRect)frame
{
    [super initWithFrame:frame];

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

    canRestart = YES;

    streams = [[NSMutableArray alloc] init];
648
    streamNotifications = [[NSMutableDictionary alloc] init];
649
650
651
652
653

    return self;
}

-(void)dealloc
654
{
655
656
657
658
659
660
661
    unsigned i;

    [self stop];

    for (i = 0; i < argsCount; i++) {
        free(cAttributes[i]);
        free(cValues[i]);
662
    }
663
664
665
666
    [streams removeAllObjects];
    [streams release];
    [MIMEType release];
    [baseURL release];
667
668
    [streamNotifications removeAllObjects];
    [streamNotifications release];
669
670
671
672
    free(cAttributes);
    free(cValues);
    [super dealloc];
}
673

674
675
- (void)drawRect:(NSRect)rect
{
676
677
678
679
680
    if (!isStarted) {
        return;
    }
    
    if([NSGraphicsContext currentContextDrawingToScreen]){
681
682
683
684
685
686
687
688
689
690
691
692
        // 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);
        
693
        [self sendUpdateEvent];
694
695
696

        SetPortVisibleRegion(nPort.port, savedVisibleRegion);
        DisposeRgn(savedVisibleRegion);
697
    }else{
698
        // Printing 2862383
699
    }
700
701
702
703
704
705
706
}

- (BOOL)isFlipped
{
    return YES;
}

707
708
709
710
711
712
713
714
- (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];
}

715
- (void)viewDidMoveToWindow
cblu's avatar
cblu committed
716
{
717
    if (![self window]) {
darin's avatar
darin committed
718
        [self stop];
cblu's avatar
WebKit:    
cblu committed
719
720
    }
    
721
    [self resetTrackingRect];
cblu's avatar
cblu committed
722
723
}

cblu's avatar
cblu committed
724
725
#pragma mark NOTIFICATIONS

726
-(void)viewHasMoved:(NSNotification *)notification
cblu's avatar
cblu committed
727
{
728
    [self setUpWindowAndPort];
729
    [self resetTrackingRect];
cblu's avatar
cblu committed
730
731
}

732
-(void)windowWillClose:(NSNotification *)notification
733
734
735
736
{
    [self stop];
}

737
-(void)windowBecameKey:(NSNotification *)notification
cblu's avatar
cblu committed
738
{
739
    [self sendActivateEvent:YES];
740
    [self sendUpdateEvent];
741
    [self restartNullEvents];
cblu's avatar
cblu committed
742
743
}

744
-(void)windowResignedKey:(NSNotification *)notification
cblu's avatar
cblu committed
745
{
746
    [self sendActivateEvent:NO];
747
    [self sendUpdateEvent];
748
    [self restartNullEvents];
cblu's avatar
cblu committed
749
750
}

751
752
-(void)windowDidMiniaturize:(NSNotification *)notification
{
753
    [self stopNullEvents];
754
755
756
757
}

-(void)windowDidDeminiaturize:(NSNotification *)notification
{
758
    [self restartNullEvents];
759
760
}

761
- (void)defaultsHaveChanged:(NSNotification *)notification
cblu's avatar
cblu committed
762
763
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
764
    if ([defaults boolForKey:@"WebKitPluginsEnabled"]) {
cblu's avatar
cblu committed
765
766
        canRestart = YES;
        [self start];
767
    } else {
cblu's avatar
cblu committed
768
769
770
771
772
773
        canRestart = NO;
        [self stop];
        [self setNeedsDisplay:YES];
    }
}

774
- (void)frameStateChanged:(NSNotification *)notification
cblu's avatar
cblu committed
775
{
776
777
778
    WebFrame *frame = [notification object];
    NSURL *URL = [[[frame dataSource] request] URL];
    NSValue *notifyDataValue = [streamNotifications objectForKey:URL];
cblu's avatar
cblu committed
779
    
780
    if(!notifyDataValue){
cblu's avatar
cblu committed
781
        return;
782
    }
cblu's avatar
cblu committed
783
    
784
785
    void *notifyData = [notifyDataValue pointerValue];
    WebFrameState frameState = [[[notification userInfo] objectForKey:WebCurrentFrameState] intValue];
786
    if (frameState == WebFrameStateComplete) {
darin's avatar
darin committed
787
        NPP_URLNotify(instance, [[URL absoluteString] cString], NPRES_DONE, notifyData);
788
        [streamNotifications removeObjectForKey:URL];
cblu's avatar
cblu committed
789
790
    }
    //FIXME: Need to send other NPReasons
cblu's avatar
cblu committed
791
792
}

793
794
@end

795
@implementation WebBaseNetscapePluginView (WebNPPCallbacks)
796

kocienda's avatar
kocienda committed
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
- (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;
}

814
- (NPError)loadRequest:(WebResourceRequest *)request inTarget:(NSString *)target withNotifyData:(void *)notifyData
815
{
816
    NSURL *URL = [request URL];
817

mjs's avatar
WebKit:    
mjs committed
818
    if (!URL) {
819
        return NPERR_INVALID_URL;
820
    }
821
    
mjs's avatar
WebKit:    
mjs committed
822
    if (!target) {
823
824
825
        WebNetscapePluginStream *stream = [[WebNetscapePluginStream alloc] initWithRequest:request
                                                                             pluginPointer:instance
                                                                                notifyData:notifyData];
mjs's avatar
WebKit:    
mjs committed
826
        if (stream) {
cblu's avatar
WebKit:    
cblu committed
827
            [streams addObject:stream];
828
            [stream start];
cblu's avatar
WebKit:    
cblu committed
829
            [stream release];
mjs's avatar
WebKit:    
mjs committed
830
        } else {
cblu's avatar
cblu committed
831
            return NPERR_INVALID_URL;
cblu's avatar
WebKit:    
cblu committed
832
        }
mjs's avatar
WebKit:    
mjs committed
833
    } else {
darin's avatar
darin committed
834
835
        NSString *JSString = [URL _web_scriptIfJavaScriptURL];
        if(JSString){
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
            [[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];
                }
            }
        }
856
    }
cblu's avatar
cblu committed
857
    
858
    return NPERR_NO_ERROR;
859
860
}

darin's avatar
darin committed
861
-(NPError)getURLNotify:(const char *)URL target:(const char *)target notifyData:(void *)notifyData
cblu's avatar
cblu committed
862
863
{
    NSString *theTarget = nil;
kocienda's avatar
kocienda committed
864
865
    NSURL *pluginURL;
    WebResourceRequest *request;
cblu's avatar
cblu committed
866
        
867
    LOG(Plugins, "NPN_GetURLNotify: %s target: %s", URL, target);
cblu's avatar
cblu committed
868
        
darin's avatar
darin committed
869
    if(!URL)
cblu's avatar
cblu committed
870
871
872
        return NPERR_INVALID_URL;
        
    if(target)
873
        theTarget = [NSString stringWithCString:target];
kocienda's avatar
kocienda committed
874
875
876
877
878
879
880

    pluginURL = [self pluginURLFromCString:URL]; 

    if(!pluginURL)
        return NPERR_INVALID_URL;
        
    request = [[[WebResourceRequest alloc] initWithURL:pluginURL] autorelease];
cblu's avatar
cblu committed
881
    
kocienda's avatar
kocienda committed
882
    return [self loadRequest:request inTarget:theTarget withNotifyData:notifyData];
cblu's avatar
cblu committed
883
884
}

darin's avatar
darin committed
885
-(NPError)getURL:(const char *)URL target:(const char *)target
886
{
cblu's avatar
cblu committed
887
    NSString *theTarget = nil;
kocienda's avatar
kocienda committed
888
889
    NSURL *pluginURL;
    WebResourceRequest *request;
cblu's avatar
cblu committed
890
    
891
    LOG(Plugins, "NPN_GetURL: %s target: %s", URL, target);
cblu's avatar
cblu committed
892
    
darin's avatar
darin committed
893
    if(!URL)
cblu's avatar
cblu committed
894
895
896
        return NPERR_INVALID_URL;
        
    if(target)
897
        theTarget = [NSString stringWithCString:target];
kocienda's avatar
kocienda committed
898
899
900
901
902
903
904

    pluginURL = [self pluginURLFromCString:URL]; 

    if(!pluginURL)
        return NPERR_INVALID_URL;
        
    request = [[[WebResourceRequest alloc] initWithURL:pluginURL] autorelease];
cblu's avatar
cblu committed
905
    
kocienda's avatar
kocienda committed
906
    return [self loadRequest:request inTarget:theTarget withNotifyData:NULL];
907
908
}

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