• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
61using 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    [self updateAndSetWindow];
394
395    if ([self window]) {
396        [self addWindowObservers];
397        if ([[self window] isKeyWindow]) {
398            [self sendActivateEvent:YES];
399        }
400        [self restartTimers];
401    }
402
403    [self resetTrackingRect];
404
405    [self loadStream];
406}
407
408- (void)stop
409{
410    if (![self shouldStop])
411        return;
412
413    [self removeTrackingRect];
414
415    if (!_isStarted)
416        return;
417
418    _isStarted = NO;
419
420    [[self webView] removePluginInstanceView:self];
421
422    // Stop the timers
423    [self stopTimers];
424
425    // Stop notifications and callbacks.
426    [self removeWindowObservers];
427
428    [self destroyPlugin];
429}
430
431- (void)viewWillMoveToWindow:(NSWindow *)newWindow
432{
433    // We must remove the tracking rect before we move to the new window.
434    // Once we move to the new window, it will be too late.
435    [self removeTrackingRect];
436    [self removeWindowObservers];
437
438    // Workaround for: <rdar://problem/3822871> resignFirstResponder is not sent to first responder view when it is removed from the window
439    [self setHasFocus:NO];
440
441    if (!newWindow) {
442        if ([[self webView] hostWindow]) {
443            // View will be moved out of the actual window but it still has a host window.
444            [self stopTimers];
445        } else {
446            // View will have no associated windows.
447            [self stop];
448
449            // Stop observing WebPreferencesChangedNotification -- we only need to observe this when installed in the view hierarchy.
450            // When not in the view hierarchy, -viewWillMoveToWindow: and -viewDidMoveToWindow will start/stop the plugin as needed.
451            [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:nil];
452        }
453    }
454}
455
456- (void)viewWillMoveToSuperview:(NSView *)newSuperview
457{
458    if (!newSuperview) {
459        // Stop the plug-in when it is removed from its superview.  It is not sufficient to do this in -viewWillMoveToWindow:nil, because
460        // the WebView might still has a hostWindow at that point, which prevents the plug-in from being destroyed.
461        // There is no need to start the plug-in when moving into a superview.  -viewDidMoveToWindow takes care of that.
462        [self stop];
463
464        // Stop observing WebPreferencesChangedNotification -- we only need to observe this when installed in the view hierarchy.
465        // When not in the view hierarchy, -viewWillMoveToWindow: and -viewDidMoveToWindow will start/stop the plugin as needed.
466        [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:nil];
467    }
468}
469
470- (void)viewDidMoveToWindow
471{
472    [self resetTrackingRect];
473
474    if ([self window]) {
475        // While in the view hierarchy, observe WebPreferencesChangedNotification so that we can start/stop depending
476        // on whether plugins are enabled.
477        [[NSNotificationCenter defaultCenter] addObserver:self
478                                                 selector:@selector(preferencesHaveChanged:)
479                                                     name:WebPreferencesChangedNotification
480                                                   object:nil];
481
482        // View moved to an actual window. Start it if not already started.
483        [self start];
484        [self restartTimers];
485        [self addWindowObservers];
486    } else if ([[self webView] hostWindow]) {
487        // View moved out of an actual window, but still has a host window.
488        // Call setWindow to explicitly "clip out" the plug-in from sight.
489        // FIXME: It would be nice to do this where we call stopNullEvents in viewWillMoveToWindow.
490        [self updateAndSetWindow];
491    }
492}
493
494- (void)viewWillMoveToHostWindow:(NSWindow *)hostWindow
495{
496    if (!hostWindow && ![self window]) {
497        // View will have no associated windows.
498        [self stop];
499
500        // Remove WebPreferencesChangedNotification observer -- we will observe once again when we move back into the window
501        [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:nil];
502    }
503}
504
505- (void)viewDidMoveToHostWindow
506{
507    if ([[self webView] hostWindow]) {
508        // View now has an associated window. Start it if not already started.
509        [self start];
510    }
511}
512
513#pragma mark NOTIFICATIONS
514
515- (void)windowWillClose:(NSNotification *)notification
516{
517    [self stop];
518}
519
520- (void)windowBecameKey:(NSNotification *)notification
521{
522    [self sendActivateEvent:YES];
523    [self invalidatePluginContentRect:[self bounds]];
524    [self restartTimers];
525}
526
527- (void)windowResignedKey:(NSNotification *)notification
528{
529    [self sendActivateEvent:NO];
530    [self invalidatePluginContentRect:[self bounds]];
531    [self restartTimers];
532}
533
534- (void)windowDidMiniaturize:(NSNotification *)notification
535{
536    [self stopTimers];
537}
538
539- (void)windowDidDeminiaturize:(NSNotification *)notification
540{
541    [self restartTimers];
542}
543
544- (void)loginWindowDidSwitchFromUser:(NSNotification *)notification
545{
546    [self stopTimers];
547}
548
549-(void)loginWindowDidSwitchToUser:(NSNotification *)notification
550{
551    [self restartTimers];
552}
553
554- (void)preferencesHaveChanged:(NSNotification *)notification
555{
556    WebPreferences *preferences = [[self webView] preferences];
557    BOOL arePlugInsEnabled = [preferences arePlugInsEnabled];
558
559    if ([notification object] == preferences && _isStarted != arePlugInsEnabled) {
560        if (arePlugInsEnabled) {
561            if ([self currentWindow]) {
562                [self start];
563            }
564        } else {
565            [self stop];
566            [self invalidatePluginContentRect:[self bounds]];
567        }
568    }
569}
570
571- (void)renewGState
572{
573    [super renewGState];
574
575    // -renewGState is called whenever the view's geometry changes.  It's a little hacky to override this method, but
576    // much safer than walking up the view hierarchy and observing frame/bounds changed notifications, since you don't
577    // have to track subsequent changes to the view hierarchy and add/remove notification observers.
578    // NSOpenGLView uses the exact same technique to reshape its OpenGL surface.
579
580    // All of the work this method does may safely be skipped if the view is not in a window.  When the view
581    // is moved back into a window, everything should be set up correctly.
582    if (![self window])
583        return;
584
585    [self updateAndSetWindow];
586
587    [self resetTrackingRect];
588
589    // Check to see if the plugin view is completely obscured (scrolled out of view, for example).
590    // For performance reasons, we send null events at a lower rate to plugins which are obscured.
591    BOOL oldIsObscured = _isCompletelyObscured;
592    _isCompletelyObscured = NSIsEmptyRect([self visibleRect]);
593    if (_isCompletelyObscured != oldIsObscured)
594        [self restartTimers];
595}
596
597- (BOOL)becomeFirstResponder
598{
599    [self setHasFocus:YES];
600    return YES;
601}
602
603- (BOOL)resignFirstResponder
604{
605    [self setHasFocus:NO];
606    return YES;
607}
608
609- (WebDataSource *)dataSource
610{
611    WebFrame *webFrame = kit(_element->document()->frame());
612    return [webFrame _dataSource];
613}
614
615- (WebFrame *)webFrame
616{
617    return [[self dataSource] webFrame];
618}
619
620- (WebView *)webView
621{
622    return [[self webFrame] webView];
623}
624
625- (NSWindow *)currentWindow
626{
627    return [self window] ? [self window] : [[self webView] hostWindow];
628}
629
630- (WebCore::HTMLPlugInElement*)element
631{
632    return _element.get();
633}
634
635- (void)cut:(id)sender
636{
637    [self sendModifierEventWithKeyCode:7 character:'x'];
638}
639
640- (void)copy:(id)sender
641{
642    [self sendModifierEventWithKeyCode:8 character:'c'];
643}
644
645- (void)paste:(id)sender
646{
647    [self sendModifierEventWithKeyCode:9 character:'v'];
648}
649
650- (void)selectAll:(id)sender
651{
652    [self sendModifierEventWithKeyCode:0 character:'a'];
653}
654
655// AppKit doesn't call mouseDown or mouseUp on right-click. Simulate control-click
656// mouseDown and mouseUp so plug-ins get the right-click event as they do in Carbon (3125743).
657- (void)rightMouseDown:(NSEvent *)theEvent
658{
659    [self mouseDown:theEvent];
660}
661
662- (void)rightMouseUp:(NSEvent *)theEvent
663{
664    [self mouseUp:theEvent];
665}
666
667
668- (BOOL)convertFromX:(double)sourceX andY:(double)sourceY space:(NPCoordinateSpace)sourceSpace
669                 toX:(double *)destX andY:(double *)destY space:(NPCoordinateSpace)destSpace
670{
671    // Nothing to do
672    if (sourceSpace == destSpace)
673        return TRUE;
674
675    NSPoint sourcePoint = NSMakePoint(sourceX, sourceY);
676
677    NSPoint sourcePointInScreenSpace;
678
679    // First convert to screen space
680    switch (sourceSpace) {
681        case NPCoordinateSpacePlugin:
682            sourcePointInScreenSpace = [self convertPoint:sourcePoint toView:nil];
683            sourcePointInScreenSpace = [[self currentWindow] convertBaseToScreen:sourcePointInScreenSpace];
684            break;
685
686        case NPCoordinateSpaceWindow:
687            sourcePointInScreenSpace = [[self currentWindow] convertBaseToScreen:sourcePoint];
688            break;
689
690        case NPCoordinateSpaceFlippedWindow:
691            sourcePoint.y = [[self currentWindow] frame].size.height - sourcePoint.y;
692            sourcePointInScreenSpace = [[self currentWindow] convertBaseToScreen:sourcePoint];
693            break;
694
695        case NPCoordinateSpaceScreen:
696            sourcePointInScreenSpace = sourcePoint;
697            break;
698
699        case NPCoordinateSpaceFlippedScreen:
700            sourcePoint.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - sourcePoint.y;
701            sourcePointInScreenSpace = sourcePoint;
702            break;
703        default:
704            return FALSE;
705    }
706
707    NSPoint destPoint;
708
709    // Then convert back to the destination space
710    switch (destSpace) {
711        case NPCoordinateSpacePlugin:
712            destPoint = [[self currentWindow] convertScreenToBase:sourcePointInScreenSpace];
713            destPoint = [self convertPoint:destPoint fromView:nil];
714            break;
715
716        case NPCoordinateSpaceWindow:
717            destPoint = [[self currentWindow] convertScreenToBase:sourcePointInScreenSpace];
718            break;
719
720        case NPCoordinateSpaceFlippedWindow:
721            destPoint = [[self currentWindow] convertScreenToBase:sourcePointInScreenSpace];
722            destPoint.y = [[self currentWindow] frame].size.height - destPoint.y;
723            break;
724
725        case NPCoordinateSpaceScreen:
726            destPoint = sourcePointInScreenSpace;
727            break;
728
729        case NPCoordinateSpaceFlippedScreen:
730            destPoint = sourcePointInScreenSpace;
731            destPoint.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - destPoint.y;
732            break;
733
734        default:
735            return FALSE;
736    }
737
738    if (destX)
739        *destX = destPoint.x;
740    if (destY)
741        *destY = destPoint.y;
742
743    return TRUE;
744}
745
746
747- (CString)resolvedURLStringForURL:(const char*)url target:(const char*)target;
748{
749    String relativeURLString = String::fromUTF8(url);
750    if (relativeURLString.isNull())
751        return CString();
752
753    Frame* frame = core([self webFrame]);
754    if (!frame)
755        return CString();
756
757    Frame* targetFrame = frame->tree()->find(String::fromUTF8(target));
758    if (!targetFrame)
759        return CString();
760
761    if (!frame->document()->securityOrigin()->canAccess(targetFrame->document()->securityOrigin()))
762        return CString();
763
764    KURL absoluteURL = targetFrame->loader()->completeURL(relativeURLString);
765    return absoluteURL.string().utf8();
766}
767
768- (void)invalidatePluginContentRect:(NSRect)rect
769{
770    if (RenderBoxModelObject *renderer = toRenderBoxModelObject(_element->renderer())) {
771        IntRect contentRect(rect);
772        contentRect.move(renderer->borderLeft() + renderer->paddingLeft(), renderer->borderTop() + renderer->paddingTop());
773
774        renderer->repaintRectangle(contentRect);
775    }
776}
777
778@end
779
780namespace WebKit {
781
782#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
783CString proxiesForURL(NSURL *url)
784{
785    RetainPtr<CFDictionaryRef> systemProxies(AdoptCF, CFNetworkCopySystemProxySettings());
786    if (!systemProxies)
787        return "DIRECT";
788
789    RetainPtr<CFArrayRef> proxiesForURL(AdoptCF, CFNetworkCopyProxiesForURL((CFURLRef)url, systemProxies.get()));
790    CFIndex proxyCount = proxiesForURL ? CFArrayGetCount(proxiesForURL.get()) : 0;
791    if (!proxyCount)
792        return "DIRECT";
793
794    // proxiesForURL is a CFArray of CFDictionaries. Each dictionary represents a proxy.
795    // The format of the result should be:
796    // "PROXY host[:port]" (for HTTP proxy) or
797    // "SOCKS host[:port]" (for SOCKS proxy) or
798    // A combination of the above, separated by semicolon, in the order that they should be tried.
799    String proxies;
800    for (CFIndex i = 0; i < proxyCount; ++i) {
801        CFDictionaryRef proxy = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(proxiesForURL.get(), i));
802        if (!proxy)
803            continue;
804
805        CFStringRef type = static_cast<CFStringRef>(CFDictionaryGetValue(proxy, kCFProxyTypeKey));
806        bool isHTTP = type == kCFProxyTypeHTTP || type == kCFProxyTypeHTTPS;
807        bool isSOCKS = type == kCFProxyTypeSOCKS;
808
809        // We can only report HTTP and SOCKS proxies.
810        if (!isHTTP && !isSOCKS)
811            continue;
812
813        CFStringRef host = static_cast<CFStringRef>(CFDictionaryGetValue(proxy, kCFProxyHostNameKey));
814        CFNumberRef port = static_cast<CFNumberRef>(CFDictionaryGetValue(proxy, kCFProxyPortNumberKey));
815
816        // If we are inserting multiple entries, add a separator
817        if (!proxies.isEmpty())
818            proxies += ";";
819
820        if (isHTTP)
821            proxies += "PROXY ";
822        else if (isSOCKS)
823            proxies += "SOCKS ";
824
825        proxies += host;
826
827        if (port) {
828            SInt32 intPort;
829            CFNumberGetValue(port, kCFNumberSInt32Type, &intPort);
830
831            proxies += ":" + String::number(intPort);
832        }
833    }
834
835    if (proxies.isEmpty())
836        return "DIRECT";
837
838    return proxies.utf8();
839}
840#endif
841
842bool getAuthenticationInfo(const char* protocolStr, const char* hostStr, int32_t port, const char* schemeStr, const char* realmStr,
843                           CString& username, CString& password)
844{
845    if (strcasecmp(protocolStr, "http") != 0 &&
846        strcasecmp(protocolStr, "https") != 0)
847        return false;
848
849    NSString *host = [NSString stringWithUTF8String:hostStr];
850    if (!hostStr)
851        return false;
852
853    NSString *protocol = [NSString stringWithUTF8String:protocolStr];
854    if (!protocol)
855        return false;
856
857    NSString *realm = [NSString stringWithUTF8String:realmStr];
858    if (!realm)
859        return NPERR_GENERIC_ERROR;
860
861    NSString *authenticationMethod = NSURLAuthenticationMethodDefault;
862    if (!strcasecmp(protocolStr, "http")) {
863        if (!strcasecmp(schemeStr, "basic"))
864            authenticationMethod = NSURLAuthenticationMethodHTTPBasic;
865        else if (!strcasecmp(schemeStr, "digest"))
866            authenticationMethod = NSURLAuthenticationMethodHTTPDigest;
867    }
868
869    RetainPtr<NSURLProtectionSpace> protectionSpace(AdoptNS, [[NSURLProtectionSpace alloc] initWithHost:host port:port protocol:protocol realm:realm authenticationMethod:authenticationMethod]);
870
871    NSURLCredential *credential = WebCoreCredentialStorage::get(protectionSpace.get());
872    if (!credential)
873        credential = [[NSURLCredentialStorage sharedCredentialStorage] defaultCredentialForProtectionSpace:protectionSpace.get()];
874    if (!credential)
875        return false;
876
877    if (![credential hasPassword])
878        return false;
879
880    username = [[credential user] UTF8String];
881    password = [[credential password] UTF8String];
882
883    return true;
884}
885
886} // namespace WebKit
887
888#endif //  ENABLE(NETSCAPE_PLUGIN_API)
889
890