3aae96deac7cf958952240c78ef7bf84f616d039
[WebKit-https.git] / WebKit / mac / Plugins / WebBaseNetscapePluginView.mm
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #if ENABLE(NETSCAPE_PLUGIN_API)
30
31 #import "WebBaseNetscapePluginView.h"
32
33 #import "WebFrameInternal.h"
34 #import "WebKitLogging.h"
35 #import "WebKitNSStringExtras.h"
36 #import "WebKitSystemInterface.h"
37 #import "WebPluginContainerCheck.h"
38 #import "WebNetscapeContainerCheckContextInfo.h"
39 #import "WebNSURLExtras.h"
40 #import "WebNSURLRequestExtras.h"
41 #import "WebView.h"
42 #import "WebViewInternal.h"
43
44 #import <WebCore/WebCoreObjCExtras.h>
45 #import <WebCore/AuthenticationMac.h>
46 #import <WebCore/CString.h>
47 #import <WebCore/Document.h>
48 #import <WebCore/Element.h>
49 #import <WebCore/Frame.h>
50 #import <WebCore/FrameLoader.h>
51 #import <WebCore/HTMLPlugInElement.h>
52 #import <WebCore/Page.h>
53 #import <WebCore/RenderView.h>
54 #import <WebKit/DOMPrivate.h>
55 #import <runtime/InitializeThreading.h>
56 #import <wtf/Assertions.h>
57
58 #define LoginWindowDidSwitchFromUserNotification    @"WebLoginWindowDidSwitchFromUserNotification"
59 #define LoginWindowDidSwitchToUserNotification      @"WebLoginWindowDidSwitchToUserNotification"
60
61 using namespace WebCore;
62
63 @implementation WebBaseNetscapePluginView
64
65 + (void)initialize
66 {
67     JSC::initializeThreading();
68 #ifndef BUILDING_ON_TIGER
69     WebCoreObjCFinalizeOnMainThread(self);
70 #endif
71     WKSendUserChangeNotifications();
72 }
73
74 - (id)initWithFrame:(NSRect)frame
75       pluginPackage:(WebNetscapePluginPackage *)pluginPackage
76                 URL:(NSURL *)URL
77             baseURL:(NSURL *)baseURL
78            MIMEType:(NSString *)MIME
79       attributeKeys:(NSArray *)keys
80     attributeValues:(NSArray *)values
81        loadManually:(BOOL)loadManually
82             element:(PassRefPtr<WebCore::HTMLPlugInElement>)element
83 {
84     self = [super initWithFrame:frame];
85     if (!self)
86         return nil;
87     
88     _pluginPackage = pluginPackage;
89     _element = element;
90     _sourceURL.adoptNS([URL copy]);
91     _baseURL.adoptNS([baseURL copy]);
92     _MIMEType.adoptNS([MIME copy]);
93     
94 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
95     // Enable "kiosk mode" when instantiating the QT plug-in inside of Dashboard. See <rdar://problem/6878105>
96     if ([[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.dashboard.client"] &&
97         [[[_pluginPackage.get() bundle] bundleIdentifier] isEqualToString:@"com.apple.QuickTime Plugin.plugin"]) {
98         RetainPtr<NSMutableArray> mutableKeys(AdoptNS, [keys mutableCopy]);
99         RetainPtr<NSMutableArray> mutableValues(AdoptNS, [values mutableCopy]);
100
101         [mutableKeys.get() addObject:@"kioskmode"];
102         [mutableValues.get() addObject:@"true"];
103         [self setAttributeKeys:mutableKeys.get() andValues:mutableValues.get()];
104     } else
105 #endif
106          [self setAttributeKeys:keys andValues:values];
107
108     if (loadManually)
109         _mode = NP_FULL;
110     else
111         _mode = NP_EMBED;
112     
113     _loadManually = loadManually;
114
115     return self;
116 }
117
118 - (void)dealloc
119 {
120     ASSERT(!_isStarted);
121
122     [super dealloc];
123 }
124
125 - (void)finalize
126 {
127     ASSERT_MAIN_THREAD();
128     ASSERT(!_isStarted);
129
130     [super finalize];
131 }
132
133 - (WebNetscapePluginPackage *)pluginPackage
134 {
135     return _pluginPackage.get();
136 }
137     
138 - (BOOL)isFlipped
139 {
140     return YES;
141 }
142
143 - (NSURL *)URLWithCString:(const char *)URLCString
144 {
145     if (!URLCString)
146         return nil;
147     
148     CFStringRef string = CFStringCreateWithCString(kCFAllocatorDefault, URLCString, kCFStringEncodingISOLatin1);
149     ASSERT(string); // All strings should be representable in ISO Latin 1
150     
151     NSString *URLString = [(NSString *)string _web_stringByStrippingReturnCharacters];
152     NSURL *URL = [NSURL _web_URLWithDataAsString:URLString relativeToURL:_baseURL.get()];
153     CFRelease(string);
154     if (!URL)
155         return nil;
156     
157     return URL;
158 }
159
160 - (NSMutableURLRequest *)requestWithURLCString:(const char *)URLCString
161 {
162     NSURL *URL = [self URLWithCString:URLCString];
163     if (!URL)
164         return nil;
165     
166     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
167     Frame* frame = core([self webFrame]);
168     if (!frame)
169         return nil;
170     [request _web_setHTTPReferrer:frame->loader()->outgoingReferrer()];
171     return request;
172 }
173
174 // Methods that subclasses must override
175 - (void)setAttributeKeys:(NSArray *)keys andValues:(NSArray *)values
176 {
177     ASSERT_NOT_REACHED();
178 }
179
180 - (void)handleMouseMoved:(NSEvent *)event
181 {
182     ASSERT_NOT_REACHED();
183 }
184
185 - (void)focusChanged
186 {
187     ASSERT_NOT_REACHED();
188 }
189
190 - (void)windowFocusChanged:(BOOL)hasFocus
191 {
192     ASSERT_NOT_REACHED();
193 }
194
195 - (BOOL)createPlugin
196 {
197     ASSERT_NOT_REACHED();
198     return NO;
199 }
200
201 - (void)loadStream
202 {
203     ASSERT_NOT_REACHED();
204 }
205
206 - (BOOL)shouldStop
207 {
208     ASSERT_NOT_REACHED();
209     return YES;
210 }
211
212 - (void)destroyPlugin
213 {
214     ASSERT_NOT_REACHED();
215 }
216
217 - (void)updateAndSetWindow
218 {
219     ASSERT_NOT_REACHED();
220 }
221
222 - (void)sendModifierEventWithKeyCode:(int)keyCode character:(char)character
223 {
224     ASSERT_NOT_REACHED();
225 }
226
227 - (void)removeTrackingRect
228 {
229     if (_trackingTag) {
230         [self removeTrackingRect:_trackingTag];
231         _trackingTag = 0;
232         
233         // Do the following after setting trackingTag to 0 so we don't re-enter.
234         
235         // Balance the retain in resetTrackingRect. Use autorelease in case we hold 
236         // the last reference to the window during tear-down, to avoid crashing AppKit. 
237         [[self window] autorelease];
238     }
239 }
240
241 - (void)resetTrackingRect
242 {
243     [self removeTrackingRect];
244     if (_isStarted) {
245         // Retain the window so that removeTrackingRect can work after the window is closed.
246         [[self window] retain];
247         _trackingTag = [self addTrackingRect:[self bounds] owner:self userData:nil assumeInside:NO];
248     }
249 }
250
251 - (void)stopTimers
252 {
253     _shouldFireTimers = NO;
254 }
255
256 - (void)startTimers
257 {
258     _shouldFireTimers = YES;
259 }
260
261 - (void)restartTimers
262 {
263     ASSERT([self window]);
264     
265     [self stopTimers];
266     
267     if (!_isStarted || [[self window] isMiniaturized])
268         return;
269     
270     [self startTimers];
271 }
272
273 - (NSRect)_windowClipRect
274 {
275     RenderObject* renderer = _element->renderer();
276     
277     if (renderer && renderer->view()) {
278         if (FrameView* frameView = renderer->view()->frameView())
279             return frameView->windowClipRectForLayer(renderer->enclosingLayer(), true);
280     }
281     
282     return NSZeroRect;
283 }
284
285 - (NSRect)visibleRect
286 {
287     // WebCore may impose an additional clip (via CSS overflow or clip properties).  Fetch
288     // that clip now.    
289     return NSIntersectionRect([self convertRect:[self _windowClipRect] fromView:nil], [super visibleRect]);
290 }
291
292 - (BOOL)acceptsFirstResponder
293 {
294     return YES;
295 }
296
297 - (void)sendActivateEvent:(BOOL)activate
298 {
299     if (!_isStarted)
300         return;
301     
302     [self windowFocusChanged:activate];
303 }
304
305 - (void)setHasFocus:(BOOL)flag
306 {
307     if (!_isStarted)
308         return;
309     
310     if (_hasFocus == flag)
311         return;
312     
313     _hasFocus = flag;
314     
315     [self focusChanged];
316 }
317
318 - (void)addWindowObservers
319 {
320     ASSERT([self window]);
321     
322     NSWindow *theWindow = [self window];
323     
324     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
325     [notificationCenter addObserver:self selector:@selector(windowWillClose:) 
326                                name:NSWindowWillCloseNotification object:theWindow]; 
327     [notificationCenter addObserver:self selector:@selector(windowBecameKey:)
328                                name:NSWindowDidBecomeKeyNotification object:theWindow];
329     [notificationCenter addObserver:self selector:@selector(windowResignedKey:)
330                                name:NSWindowDidResignKeyNotification object:theWindow];
331     [notificationCenter addObserver:self selector:@selector(windowDidMiniaturize:)
332                                name:NSWindowDidMiniaturizeNotification object:theWindow];
333     [notificationCenter addObserver:self selector:@selector(windowDidDeminiaturize:)
334                                name:NSWindowDidDeminiaturizeNotification object:theWindow];
335     
336     [notificationCenter addObserver:self selector:@selector(loginWindowDidSwitchFromUser:)
337                                name:LoginWindowDidSwitchFromUserNotification object:nil];
338     [notificationCenter addObserver:self selector:@selector(loginWindowDidSwitchToUser:)
339                                name:LoginWindowDidSwitchToUserNotification object:nil];
340 }
341
342 - (void)removeWindowObservers
343 {
344     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
345     [notificationCenter removeObserver:self name:NSWindowWillCloseNotification        object:nil]; 
346     [notificationCenter removeObserver:self name:NSWindowDidBecomeKeyNotification     object:nil];
347     [notificationCenter removeObserver:self name:NSWindowDidResignKeyNotification     object:nil];
348     [notificationCenter removeObserver:self name:NSWindowDidMiniaturizeNotification   object:nil];
349     [notificationCenter removeObserver:self name:NSWindowDidDeminiaturizeNotification object:nil];
350     [notificationCenter removeObserver:self name:LoginWindowDidSwitchFromUserNotification   object:nil];
351     [notificationCenter removeObserver:self name:LoginWindowDidSwitchToUserNotification     object:nil];
352 }
353
354 - (void)start
355 {
356     ASSERT([self currentWindow]);
357     
358     if (_isStarted)
359         return;
360     
361     if (_triedAndFailedToCreatePlugin)
362         return;
363     
364     ASSERT([self webView]);
365     
366     if (![[[self webView] preferences] arePlugInsEnabled])
367         return;
368    
369     Frame* frame = core([self webFrame]);
370     if (!frame)
371         return;
372     Page* page = frame->page();
373     if (!page)
374         return;
375     
376     bool wasDeferring = page->defersLoading();
377     if (!wasDeferring)
378         page->setDefersLoading(true);
379
380     BOOL result = [self createPlugin];
381     
382     if (!wasDeferring)
383         page->setDefersLoading(false);
384
385     if (!result) {
386         _triedAndFailedToCreatePlugin = YES;
387         return;
388     }
389     
390     _isStarted = YES;
391     [[self webView] addPluginInstanceView:self];
392
393     if ([self currentWindow])
394         [self updateAndSetWindow];
395
396     if ([self window]) {
397         [self addWindowObservers];
398         if ([[self window] isKeyWindow]) {
399             [self sendActivateEvent:YES];
400         }
401         [self restartTimers];
402     }
403     
404     [self resetTrackingRect];
405     
406     [self loadStream];
407 }
408
409 - (void)stop
410 {
411     if (![self shouldStop])
412         return;
413     
414     [self removeTrackingRect];
415     
416     if (!_isStarted)
417         return;
418     
419     _isStarted = NO;
420     
421     [[self webView] removePluginInstanceView:self];
422     
423     // Stop the timers
424     [self stopTimers];
425     
426     // Stop notifications and callbacks.
427     [self removeWindowObservers];
428     
429     [self destroyPlugin];
430 }
431
432 - (void)viewWillMoveToWindow:(NSWindow *)newWindow
433 {
434     // We must remove the tracking rect before we move to the new window.
435     // Once we move to the new window, it will be too late.
436     [self removeTrackingRect];
437     [self removeWindowObservers];
438     
439     // Workaround for: <rdar://problem/3822871> resignFirstResponder is not sent to first responder view when it is removed from the window
440     [self setHasFocus:NO];
441     
442     if (!newWindow) {
443         if ([[self webView] hostWindow]) {
444             // View will be moved out of the actual window but it still has a host window.
445             [self stopTimers];
446         } else {
447             // View will have no associated windows.
448             [self stop];
449             
450             // Stop observing WebPreferencesChangedNotification -- we only need to observe this when installed in the view hierarchy.
451             // When not in the view hierarchy, -viewWillMoveToWindow: and -viewDidMoveToWindow will start/stop the plugin as needed.
452             [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:nil];
453         }
454     }
455 }
456
457 - (void)viewWillMoveToSuperview:(NSView *)newSuperview
458 {
459     if (!newSuperview) {
460         // Stop the plug-in when it is removed from its superview.  It is not sufficient to do this in -viewWillMoveToWindow:nil, because
461         // the WebView might still has a hostWindow at that point, which prevents the plug-in from being destroyed.
462         // There is no need to start the plug-in when moving into a superview.  -viewDidMoveToWindow takes care of that.
463         [self stop];
464         
465         // Stop observing WebPreferencesChangedNotification -- we only need to observe this when installed in the view hierarchy.
466         // When not in the view hierarchy, -viewWillMoveToWindow: and -viewDidMoveToWindow will start/stop the plugin as needed.
467         [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:nil];
468     }
469 }
470
471 - (void)viewDidMoveToWindow
472 {
473     [self resetTrackingRect];
474     
475     if ([self window]) {
476         // While in the view hierarchy, observe WebPreferencesChangedNotification so that we can start/stop depending
477         // on whether plugins are enabled.
478         [[NSNotificationCenter defaultCenter] addObserver:self
479                                                  selector:@selector(preferencesHaveChanged:)
480                                                      name:WebPreferencesChangedNotification
481                                                    object:nil];
482         
483         // View moved to an actual window. Start it if not already started.
484         [self start];
485     } else if ([[self webView] hostWindow]) {
486         // View moved out of an actual window, but still has a host window.
487         // Call setWindow to explicitly "clip out" the plug-in from sight.
488         // FIXME: It would be nice to do this where we call stopNullEvents in viewWillMoveToWindow.
489         [self updateAndSetWindow];
490     }
491 }
492
493 - (void)viewWillMoveToHostWindow:(NSWindow *)hostWindow
494 {
495     if (!hostWindow && ![self window]) {
496         // View will have no associated windows.
497         [self stop];
498         
499         // Remove WebPreferencesChangedNotification observer -- we will observe once again when we move back into the window
500         [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:nil];
501     }
502 }
503
504 - (void)viewDidMoveToHostWindow
505 {
506     if ([[self webView] hostWindow]) {
507         // View now has an associated window. Start it if not already started.
508         [self start];
509     }
510 }
511
512 #pragma mark NOTIFICATIONS
513
514 - (void)windowWillClose:(NSNotification *)notification 
515 {
516     [self stop]; 
517
518
519 - (void)windowBecameKey:(NSNotification *)notification
520 {
521     [self sendActivateEvent:YES];
522     [self invalidatePluginContentRect:[self bounds]];
523     [self restartTimers];
524 }
525
526 - (void)windowResignedKey:(NSNotification *)notification
527 {
528     [self sendActivateEvent:NO];
529     [self invalidatePluginContentRect:[self bounds]];
530     [self restartTimers];
531 }
532
533 - (void)windowDidMiniaturize:(NSNotification *)notification
534 {
535     [self stopTimers];
536 }
537
538 - (void)windowDidDeminiaturize:(NSNotification *)notification
539 {
540     [self restartTimers];
541 }
542
543 - (void)loginWindowDidSwitchFromUser:(NSNotification *)notification
544 {
545     [self stopTimers];
546 }
547
548 -(void)loginWindowDidSwitchToUser:(NSNotification *)notification
549 {
550     [self restartTimers];
551 }
552
553 - (void)preferencesHaveChanged:(NSNotification *)notification
554 {
555     WebPreferences *preferences = [[self webView] preferences];
556     BOOL arePlugInsEnabled = [preferences arePlugInsEnabled];
557     
558     if ([notification object] == preferences && _isStarted != arePlugInsEnabled) {
559         if (arePlugInsEnabled) {
560             if ([self currentWindow]) {
561                 [self start];
562             }
563         } else {
564             [self stop];
565             [self invalidatePluginContentRect:[self bounds]];
566         }
567     }
568 }
569
570 - (void)renewGState
571 {
572     [super renewGState];
573     
574     // -renewGState is called whenever the view's geometry changes.  It's a little hacky to override this method, but
575     // much safer than walking up the view hierarchy and observing frame/bounds changed notifications, since you don't
576     // have to track subsequent changes to the view hierarchy and add/remove notification observers.
577     // NSOpenGLView uses the exact same technique to reshape its OpenGL surface.
578     
579     // All of the work this method does may safely be skipped if the view is not in a window.  When the view
580     // is moved back into a window, everything should be set up correctly.
581     if (![self window])
582         return;
583     
584     [self updateAndSetWindow];
585     
586     [self resetTrackingRect];
587     
588     // Check to see if the plugin view is completely obscured (scrolled out of view, for example).
589     // For performance reasons, we send null events at a lower rate to plugins which are obscured.
590     BOOL oldIsObscured = _isCompletelyObscured;
591     _isCompletelyObscured = NSIsEmptyRect([self visibleRect]);
592     if (_isCompletelyObscured != oldIsObscured)
593         [self restartTimers];
594 }
595
596 - (BOOL)becomeFirstResponder
597 {
598     [self setHasFocus:YES];
599     return YES;
600 }
601
602 - (BOOL)resignFirstResponder
603 {
604     [self setHasFocus:NO];    
605     return YES;
606 }
607
608 - (WebDataSource *)dataSource
609 {
610     WebFrame *webFrame = kit(_element->document()->frame());
611     return [webFrame _dataSource];
612 }
613
614 - (WebFrame *)webFrame
615 {
616     return [[self dataSource] webFrame];
617 }
618
619 - (WebView *)webView
620 {
621     return [[self webFrame] webView];
622 }
623
624 - (NSWindow *)currentWindow
625 {
626     return [self window] ? [self window] : [[self webView] hostWindow];
627 }
628
629 - (WebCore::HTMLPlugInElement*)element
630 {
631     return _element.get();
632 }
633
634 - (void)cut:(id)sender
635 {
636     [self sendModifierEventWithKeyCode:7 character:'x'];
637 }
638
639 - (void)copy:(id)sender
640 {
641     [self sendModifierEventWithKeyCode:8 character:'c'];
642 }
643
644 - (void)paste:(id)sender
645 {
646     [self sendModifierEventWithKeyCode:9 character:'v'];
647 }
648
649 - (void)selectAll:(id)sender
650 {
651     [self sendModifierEventWithKeyCode:0 character:'a'];
652 }
653
654 // AppKit doesn't call mouseDown or mouseUp on right-click. Simulate control-click
655 // mouseDown and mouseUp so plug-ins get the right-click event as they do in Carbon (3125743).
656 - (void)rightMouseDown:(NSEvent *)theEvent
657 {
658     [self mouseDown:theEvent];
659 }
660
661 - (void)rightMouseUp:(NSEvent *)theEvent
662 {
663     [self mouseUp:theEvent];
664 }
665
666
667 - (BOOL)convertFromX:(double)sourceX andY:(double)sourceY space:(NPCoordinateSpace)sourceSpace
668                  toX:(double *)destX andY:(double *)destY space:(NPCoordinateSpace)destSpace
669 {
670     // Nothing to do
671     if (sourceSpace == destSpace)
672         return TRUE;
673     
674     NSPoint sourcePoint = NSMakePoint(sourceX, sourceY);
675     
676     NSPoint sourcePointInScreenSpace;
677     
678     // First convert to screen space
679     switch (sourceSpace) {
680         case NPCoordinateSpacePlugin:
681             sourcePointInScreenSpace = [self convertPoint:sourcePoint toView:nil];
682             sourcePointInScreenSpace = [[self currentWindow] convertBaseToScreen:sourcePointInScreenSpace];
683             break;
684             
685         case NPCoordinateSpaceWindow:
686             sourcePointInScreenSpace = [[self currentWindow] convertBaseToScreen:sourcePoint];
687             break;
688             
689         case NPCoordinateSpaceFlippedWindow:
690             sourcePoint.y = [[self currentWindow] frame].size.height - sourcePoint.y;
691             sourcePointInScreenSpace = [[self currentWindow] convertBaseToScreen:sourcePoint];
692             break;
693             
694         case NPCoordinateSpaceScreen:
695             sourcePointInScreenSpace = sourcePoint;
696             break;
697             
698         case NPCoordinateSpaceFlippedScreen:
699             sourcePoint.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - sourcePoint.y;
700             sourcePointInScreenSpace = sourcePoint;
701             break;
702         default:
703             return FALSE;
704     }
705     
706     NSPoint destPoint;
707     
708     // Then convert back to the destination space
709     switch (destSpace) {
710         case NPCoordinateSpacePlugin:
711             destPoint = [[self currentWindow] convertScreenToBase:sourcePointInScreenSpace];
712             destPoint = [self convertPoint:destPoint fromView:nil];
713             break;
714             
715         case NPCoordinateSpaceWindow:
716             destPoint = [[self currentWindow] convertScreenToBase:sourcePointInScreenSpace];
717             break;
718             
719         case NPCoordinateSpaceFlippedWindow:
720             destPoint = [[self currentWindow] convertScreenToBase:sourcePointInScreenSpace];
721             destPoint.y = [[self currentWindow] frame].size.height - destPoint.y;
722             break;
723             
724         case NPCoordinateSpaceScreen:
725             destPoint = sourcePointInScreenSpace;
726             break;
727             
728         case NPCoordinateSpaceFlippedScreen:
729             destPoint = sourcePointInScreenSpace;
730             destPoint.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - destPoint.y;
731             break;
732             
733         default:
734             return FALSE;
735     }
736     
737     if (destX)
738         *destX = destPoint.x;
739     if (destY)
740         *destY = destPoint.y;
741     
742     return TRUE;
743 }
744
745
746 - (CString)resolvedURLStringForURL:(const char*)url target:(const char*)target;
747 {
748     String relativeURLString = String::fromUTF8(url);
749     if (relativeURLString.isNull())
750         return CString();
751     
752     Frame* frame = core([self webFrame]);
753     if (!frame)
754         return CString();
755
756     Frame* targetFrame = frame->tree()->find(String::fromUTF8(target));
757     if (!targetFrame)
758         return CString();
759     
760     if (!frame->document()->securityOrigin()->canAccess(targetFrame->document()->securityOrigin()))
761         return CString();
762   
763     KURL absoluteURL = targetFrame->loader()->completeURL(relativeURLString);
764     return absoluteURL.string().utf8();
765 }
766
767 - (void)invalidatePluginContentRect:(NSRect)rect
768 {
769     if (RenderBoxModelObject *renderer = toRenderBoxModelObject(_element->renderer())) {
770         IntRect contentRect(rect);
771         contentRect.move(renderer->borderLeft() + renderer->paddingLeft(), renderer->borderTop() + renderer->paddingTop());
772         
773         renderer->repaintRectangle(contentRect);
774     }
775 }
776
777 @end
778
779 namespace WebKit {
780
781 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
782 CString proxiesForURL(NSURL *url)
783 {
784     RetainPtr<CFDictionaryRef> systemProxies(AdoptCF, CFNetworkCopySystemProxySettings());
785     if (!systemProxies)
786         return "DIRECT";
787     
788     RetainPtr<CFArrayRef> proxiesForURL(AdoptCF, CFNetworkCopyProxiesForURL((CFURLRef)url, systemProxies.get()));
789     CFIndex proxyCount = proxiesForURL ? CFArrayGetCount(proxiesForURL.get()) : 0;
790     if (!proxyCount)
791         return "DIRECT";
792  
793     // proxiesForURL is a CFArray of CFDictionaries. Each dictionary represents a proxy.
794     // The format of the result should be:
795     // "PROXY host[:port]" (for HTTP proxy) or
796     // "SOCKS host[:port]" (for SOCKS proxy) or
797     // A combination of the above, separated by semicolon, in the order that they should be tried.
798     String proxies;
799     for (CFIndex i = 0; i < proxyCount; ++i) {
800         CFDictionaryRef proxy = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(proxiesForURL.get(), i));
801         if (!proxy)
802             continue;
803
804         CFStringRef type = static_cast<CFStringRef>(CFDictionaryGetValue(proxy, kCFProxyTypeKey));
805         bool isHTTP = type == kCFProxyTypeHTTP || type == kCFProxyTypeHTTPS;
806         bool isSOCKS = type == kCFProxyTypeSOCKS;
807         
808         // We can only report HTTP and SOCKS proxies.
809         if (!isHTTP && !isSOCKS)
810             continue;
811         
812         CFStringRef host = static_cast<CFStringRef>(CFDictionaryGetValue(proxy, kCFProxyHostNameKey));
813         CFNumberRef port = static_cast<CFNumberRef>(CFDictionaryGetValue(proxy, kCFProxyPortNumberKey));
814         
815         // If we are inserting multiple entries, add a separator
816         if (!proxies.isEmpty())
817             proxies += ";";
818         
819         if (isHTTP)
820             proxies += "PROXY ";
821         else if (isSOCKS)
822             proxies += "SOCKS ";
823         
824         proxies += host;
825
826         if (port) {
827             SInt32 intPort;
828             CFNumberGetValue(port, kCFNumberSInt32Type, &intPort);
829             
830             proxies += ":" + String::number(intPort);
831         }
832     }
833     
834     if (proxies.isEmpty())
835         return "DIRECT";
836     
837     return proxies.utf8();
838 }
839 #endif
840
841 bool getAuthenticationInfo(const char* protocolStr, const char* hostStr, int32_t port, const char* schemeStr, const char* realmStr,
842                            CString& username, CString& password)
843 {
844     if (strcasecmp(protocolStr, "http") != 0 && 
845         strcasecmp(protocolStr, "https") != 0)
846         return false;
847
848     NSString *host = [NSString stringWithUTF8String:hostStr];
849     if (!hostStr)
850         return false;
851     
852     NSString *protocol = [NSString stringWithUTF8String:protocolStr];
853     if (!protocol)
854         return false;
855     
856     NSString *realm = [NSString stringWithUTF8String:realmStr];
857     if (!realm)
858         return NPERR_GENERIC_ERROR;
859     
860     NSString *authenticationMethod = NSURLAuthenticationMethodDefault;
861     if (!strcasecmp(protocolStr, "http")) {
862         if (!strcasecmp(schemeStr, "basic"))
863             authenticationMethod = NSURLAuthenticationMethodHTTPBasic;
864         else if (!strcasecmp(schemeStr, "digest"))
865             authenticationMethod = NSURLAuthenticationMethodHTTPDigest;
866     }
867     
868     RetainPtr<NSURLProtectionSpace> protectionSpace(AdoptNS, [[NSURLProtectionSpace alloc] initWithHost:host port:port protocol:protocol realm:realm authenticationMethod:authenticationMethod]);
869     
870     NSURLCredential *credential = WebCoreCredentialStorage::get(protectionSpace.get());
871     if (!credential)
872         credential = [[NSURLCredentialStorage sharedCredentialStorage] defaultCredentialForProtectionSpace:protectionSpace.get()];
873     if (!credential)
874         return false;
875   
876     if (![credential hasPassword])
877         return false;
878     
879     username = [[credential user] UTF8String];
880     password = [[credential password] UTF8String];
881     
882     return true;
883 }
884     
885 } // namespace WebKit
886
887 #endif //  ENABLE(NETSCAPE_PLUGIN_API)
888