Home | History | Annotate | Download | only in Plugins
      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/BitmapImage.h>
     47 #import <WebCore/Credential.h>
     48 #import <WebCore/CredentialStorage.h>
     49 #import <WebCore/CString.h>
     50 #import <WebCore/Document.h>
     51 #import <WebCore/Element.h>
     52 #import <WebCore/Frame.h>
     53 #import <WebCore/FrameLoader.h>
     54 #import <WebCore/HTMLPlugInElement.h>
     55 #import <WebCore/HaltablePlugin.h>
     56 #import <WebCore/Page.h>
     57 #import <WebCore/ProtectionSpace.h>
     58 #import <WebCore/RenderView.h>
     59 #import <WebCore/RenderWidget.h>
     60 #import <WebKit/DOMPrivate.h>
     61 #import <runtime/InitializeThreading.h>
     62 #import <wtf/Assertions.h>
     63 
     64 #define LoginWindowDidSwitchFromUserNotification    @"WebLoginWindowDidSwitchFromUserNotification"
     65 #define LoginWindowDidSwitchToUserNotification      @"WebLoginWindowDidSwitchToUserNotification"
     66 
     67 static const NSTimeInterval ClearSubstituteImageDelay = 0.5;
     68 
     69 using namespace WebCore;
     70 
     71 class WebHaltablePlugin : public HaltablePlugin {
     72 public:
     73     WebHaltablePlugin(WebBaseNetscapePluginView* view)
     74         : m_view(view)
     75     {
     76     }
     77 
     78 private:
     79     virtual void halt();
     80     virtual void restart();
     81     virtual Node* node() const;
     82     virtual bool isWindowed() const;
     83     virtual String pluginName() const;
     84 
     85     WebBaseNetscapePluginView* m_view;
     86 };
     87 
     88 void WebHaltablePlugin::halt()
     89 {
     90     [m_view halt];
     91 }
     92 
     93 void WebHaltablePlugin::restart()
     94 {
     95     [m_view resumeFromHalt];
     96 }
     97 
     98 Node* WebHaltablePlugin::node() const
     99 {
    100     return [m_view element];
    101 }
    102 
    103 bool WebHaltablePlugin::isWindowed() const
    104 {
    105     return false;
    106 }
    107 
    108 String WebHaltablePlugin::pluginName() const
    109 {
    110     return [[m_view pluginPackage] name];
    111 }
    112 
    113 @implementation WebBaseNetscapePluginView
    114 
    115 + (void)initialize
    116 {
    117     JSC::initializeThreading();
    118 #ifndef BUILDING_ON_TIGER
    119     WebCoreObjCFinalizeOnMainThread(self);
    120 #endif
    121     WKSendUserChangeNotifications();
    122 }
    123 
    124 - (id)initWithFrame:(NSRect)frame
    125       pluginPackage:(WebNetscapePluginPackage *)pluginPackage
    126                 URL:(NSURL *)URL
    127             baseURL:(NSURL *)baseURL
    128            MIMEType:(NSString *)MIME
    129       attributeKeys:(NSArray *)keys
    130     attributeValues:(NSArray *)values
    131        loadManually:(BOOL)loadManually
    132             element:(PassRefPtr<WebCore::HTMLPlugInElement>)element
    133 {
    134     self = [super initWithFrame:frame];
    135     if (!self)
    136         return nil;
    137 
    138     _pluginPackage = pluginPackage;
    139     _element = element;
    140     _sourceURL.adoptNS([URL copy]);
    141     _baseURL.adoptNS([baseURL copy]);
    142     _MIMEType.adoptNS([MIME copy]);
    143 
    144 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
    145     // Enable "kiosk mode" when instantiating the QT plug-in inside of Dashboard. See <rdar://problem/6878105>
    146     if ([[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.apple.dashboard.client"] &&
    147         [[[_pluginPackage.get() bundle] bundleIdentifier] isEqualToString:@"com.apple.QuickTime Plugin.plugin"]) {
    148         RetainPtr<NSMutableArray> mutableKeys(AdoptNS, [keys mutableCopy]);
    149         RetainPtr<NSMutableArray> mutableValues(AdoptNS, [values mutableCopy]);
    150 
    151         [mutableKeys.get() addObject:@"kioskmode"];
    152         [mutableValues.get() addObject:@"true"];
    153         [self setAttributeKeys:mutableKeys.get() andValues:mutableValues.get()];
    154     } else
    155 #endif
    156          [self setAttributeKeys:keys andValues:values];
    157 
    158     if (loadManually)
    159         _mode = NP_FULL;
    160     else
    161         _mode = NP_EMBED;
    162 
    163     _loadManually = loadManually;
    164     _haltable = new WebHaltablePlugin(self);
    165     return self;
    166 }
    167 
    168 - (void)dealloc
    169 {
    170     ASSERT(!_isStarted);
    171 
    172     [super dealloc];
    173 }
    174 
    175 - (void)finalize
    176 {
    177     ASSERT_MAIN_THREAD();
    178     ASSERT(!_isStarted);
    179 
    180     [super finalize];
    181 }
    182 
    183 - (WebNetscapePluginPackage *)pluginPackage
    184 {
    185     return _pluginPackage.get();
    186 }
    187 
    188 - (BOOL)isFlipped
    189 {
    190     return YES;
    191 }
    192 
    193 - (NSURL *)URLWithCString:(const char *)URLCString
    194 {
    195     if (!URLCString)
    196         return nil;
    197 
    198     CFStringRef string = CFStringCreateWithCString(kCFAllocatorDefault, URLCString, kCFStringEncodingISOLatin1);
    199     ASSERT(string); // All strings should be representable in ISO Latin 1
    200 
    201     NSString *URLString = [(NSString *)string _web_stringByStrippingReturnCharacters];
    202     NSURL *URL = [NSURL _web_URLWithDataAsString:URLString relativeToURL:_baseURL.get()];
    203     CFRelease(string);
    204     if (!URL)
    205         return nil;
    206 
    207     return URL;
    208 }
    209 
    210 - (NSMutableURLRequest *)requestWithURLCString:(const char *)URLCString
    211 {
    212     NSURL *URL = [self URLWithCString:URLCString];
    213     if (!URL)
    214         return nil;
    215 
    216     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
    217     Frame* frame = core([self webFrame]);
    218     if (!frame)
    219         return nil;
    220     [request _web_setHTTPReferrer:frame->loader()->outgoingReferrer()];
    221     return request;
    222 }
    223 
    224 // Methods that subclasses must override
    225 - (void)setAttributeKeys:(NSArray *)keys andValues:(NSArray *)values
    226 {
    227     ASSERT_NOT_REACHED();
    228 }
    229 
    230 - (void)handleMouseMoved:(NSEvent *)event
    231 {
    232     ASSERT_NOT_REACHED();
    233 }
    234 
    235 - (void)focusChanged
    236 {
    237     ASSERT_NOT_REACHED();
    238 }
    239 
    240 - (void)windowFocusChanged:(BOOL)hasFocus
    241 {
    242     ASSERT_NOT_REACHED();
    243 }
    244 
    245 - (BOOL)createPlugin
    246 {
    247     ASSERT_NOT_REACHED();
    248     return NO;
    249 }
    250 
    251 - (void)loadStream
    252 {
    253     ASSERT_NOT_REACHED();
    254 }
    255 
    256 - (BOOL)shouldStop
    257 {
    258     ASSERT_NOT_REACHED();
    259     return YES;
    260 }
    261 
    262 - (void)destroyPlugin
    263 {
    264     ASSERT_NOT_REACHED();
    265 }
    266 
    267 - (void)updateAndSetWindow
    268 {
    269     ASSERT_NOT_REACHED();
    270 }
    271 
    272 - (void)sendModifierEventWithKeyCode:(int)keyCode character:(char)character
    273 {
    274     ASSERT_NOT_REACHED();
    275 }
    276 
    277 - (void)privateBrowsingModeDidChange
    278 {
    279 }
    280 
    281 - (void)removeTrackingRect
    282 {
    283     if (_trackingTag) {
    284         [self removeTrackingRect:_trackingTag];
    285         _trackingTag = 0;
    286 
    287         // Do the following after setting trackingTag to 0 so we don't re-enter.
    288 
    289         // Balance the retain in resetTrackingRect. Use autorelease in case we hold
    290         // the last reference to the window during tear-down, to avoid crashing AppKit.
    291         [[self window] autorelease];
    292     }
    293 }
    294 
    295 - (void)resetTrackingRect
    296 {
    297     [self removeTrackingRect];
    298     if (_isStarted) {
    299         // Retain the window so that removeTrackingRect can work after the window is closed.
    300         [[self window] retain];
    301         _trackingTag = [self addTrackingRect:[self bounds] owner:self userData:nil assumeInside:NO];
    302     }
    303 }
    304 
    305 - (void)stopTimers
    306 {
    307     _shouldFireTimers = NO;
    308 }
    309 
    310 - (void)startTimers
    311 {
    312     _shouldFireTimers = YES;
    313 }
    314 
    315 - (void)restartTimers
    316 {
    317     ASSERT([self window]);
    318 
    319     [self stopTimers];
    320 
    321     if (!_isStarted || [[self window] isMiniaturized])
    322         return;
    323 
    324     [self startTimers];
    325 }
    326 
    327 - (NSRect)_windowClipRect
    328 {
    329     RenderObject* renderer = _element->renderer();
    330 
    331     if (renderer && renderer->view()) {
    332         if (FrameView* frameView = renderer->view()->frameView())
    333             return frameView->windowClipRectForLayer(renderer->enclosingLayer(), true);
    334     }
    335 
    336     return NSZeroRect;
    337 }
    338 
    339 - (NSRect)visibleRect
    340 {
    341     // WebCore may impose an additional clip (via CSS overflow or clip properties).  Fetch
    342     // that clip now.
    343     return NSIntersectionRect([self convertRect:[self _windowClipRect] fromView:nil], [super visibleRect]);
    344 }
    345 
    346 - (BOOL)acceptsFirstResponder
    347 {
    348     return YES;
    349 }
    350 
    351 - (void)sendActivateEvent:(BOOL)activate
    352 {
    353     if (!_isStarted)
    354         return;
    355 
    356     [self windowFocusChanged:activate];
    357 }
    358 
    359 - (void)setHasFocus:(BOOL)flag
    360 {
    361     if (!_isStarted)
    362         return;
    363 
    364     if (_hasFocus == flag)
    365         return;
    366 
    367     _hasFocus = flag;
    368 
    369     [self focusChanged];
    370 }
    371 
    372 - (void)addWindowObservers
    373 {
    374     ASSERT([self window]);
    375 
    376     NSWindow *theWindow = [self window];
    377 
    378     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    379     [notificationCenter addObserver:self selector:@selector(windowWillClose:)
    380                                name:NSWindowWillCloseNotification object:theWindow];
    381     [notificationCenter addObserver:self selector:@selector(windowBecameKey:)
    382                                name:NSWindowDidBecomeKeyNotification object:theWindow];
    383     [notificationCenter addObserver:self selector:@selector(windowResignedKey:)
    384                                name:NSWindowDidResignKeyNotification object:theWindow];
    385     [notificationCenter addObserver:self selector:@selector(windowDidMiniaturize:)
    386                                name:NSWindowDidMiniaturizeNotification object:theWindow];
    387     [notificationCenter addObserver:self selector:@selector(windowDidDeminiaturize:)
    388                                name:NSWindowDidDeminiaturizeNotification object:theWindow];
    389 
    390     [notificationCenter addObserver:self selector:@selector(loginWindowDidSwitchFromUser:)
    391                                name:LoginWindowDidSwitchFromUserNotification object:nil];
    392     [notificationCenter addObserver:self selector:@selector(loginWindowDidSwitchToUser:)
    393                                name:LoginWindowDidSwitchToUserNotification object:nil];
    394 }
    395 
    396 - (void)removeWindowObservers
    397 {
    398     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    399     [notificationCenter removeObserver:self name:NSWindowWillCloseNotification        object:nil];
    400     [notificationCenter removeObserver:self name:NSWindowDidBecomeKeyNotification     object:nil];
    401     [notificationCenter removeObserver:self name:NSWindowDidResignKeyNotification     object:nil];
    402     [notificationCenter removeObserver:self name:NSWindowDidMiniaturizeNotification   object:nil];
    403     [notificationCenter removeObserver:self name:NSWindowDidDeminiaturizeNotification object:nil];
    404     [notificationCenter removeObserver:self name:LoginWindowDidSwitchFromUserNotification   object:nil];
    405     [notificationCenter removeObserver:self name:LoginWindowDidSwitchToUserNotification     object:nil];
    406 }
    407 
    408 - (void)start
    409 {
    410     ASSERT([self currentWindow]);
    411 
    412     if (_isStarted)
    413         return;
    414 
    415     if (_triedAndFailedToCreatePlugin)
    416         return;
    417 
    418     ASSERT([self webView]);
    419 
    420     if (![[[self webView] preferences] arePlugInsEnabled])
    421         return;
    422 
    423     Frame* frame = core([self webFrame]);
    424     if (!frame)
    425         return;
    426     Page* page = frame->page();
    427     if (!page)
    428         return;
    429 
    430     bool wasDeferring = page->defersLoading();
    431     if (!wasDeferring)
    432         page->setDefersLoading(true);
    433 
    434     BOOL result = [self createPlugin];
    435 
    436     if (!wasDeferring)
    437         page->setDefersLoading(false);
    438 
    439     if (!result) {
    440         _triedAndFailedToCreatePlugin = YES;
    441         return;
    442     }
    443 
    444     _isStarted = YES;
    445     page->didStartPlugin(_haltable.get());
    446 
    447     [[self webView] addPluginInstanceView:self];
    448 
    449     if ([self currentWindow])
    450         [self updateAndSetWindow];
    451 
    452     if ([self window]) {
    453         [self addWindowObservers];
    454         if ([[self window] isKeyWindow]) {
    455             [self sendActivateEvent:YES];
    456         }
    457         [self restartTimers];
    458     }
    459 
    460     [self resetTrackingRect];
    461 
    462     [self loadStream];
    463 }
    464 
    465 - (void)stop
    466 {
    467     if (![self shouldStop])
    468         return;
    469 
    470     [self removeTrackingRect];
    471 
    472     if (!_isStarted)
    473         return;
    474 
    475     if (Frame* frame = core([self webFrame])) {
    476         if (Page* page = frame->page())
    477             page->didStopPlugin(_haltable.get());
    478     }
    479 
    480     _isStarted = NO;
    481 
    482     [[self webView] removePluginInstanceView:self];
    483 
    484     // Stop the timers
    485     [self stopTimers];
    486 
    487     // Stop notifications and callbacks.
    488     [self removeWindowObservers];
    489 
    490     [self destroyPlugin];
    491 }
    492 
    493 - (void)halt
    494 {
    495     ASSERT(!_isHalted);
    496     ASSERT(_isStarted);
    497     Element *element = [self element];
    498 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
    499     CGImageRef cgImage = CGImageRetain([core([self webFrame])->nodeImage(element) CGImageForProposedRect:nil context:nil hints:nil]);
    500 #else
    501     RetainPtr<CGImageSourceRef> imageRef(AdoptCF, CGImageSourceCreateWithData((CFDataRef)[core([self webFrame])->nodeImage(element) TIFFRepresentation], 0));
    502     CGImageRef cgImage = CGImageSourceCreateImageAtIndex(imageRef.get(), 0, 0);
    503 #endif
    504     ASSERT(cgImage);
    505 
    506     // BitmapImage will release the passed in CGImage on destruction.
    507     RefPtr<Image> nodeImage = BitmapImage::create(cgImage);
    508     ASSERT(element->renderer());
    509     toRenderWidget(element->renderer())->showSubstituteImage(nodeImage);
    510     [self stop];
    511     _isHalted = YES;
    512     _hasBeenHalted = YES;
    513 }
    514 
    515 - (void)_clearSubstituteImage
    516 {
    517     Element* element = [self element];
    518     if (!element)
    519         return;
    520 
    521     RenderObject* renderer = element->renderer();
    522     if (!renderer)
    523         return;
    524 
    525     toRenderWidget(renderer)->showSubstituteImage(0);
    526 }
    527 
    528 - (void)resumeFromHalt
    529 {
    530     ASSERT(_isHalted);
    531     ASSERT(!_isStarted);
    532     [self start];
    533 
    534     if (_isStarted)
    535         _isHalted = NO;
    536 
    537     ASSERT([self element]->renderer());
    538     // FIXME 7417484: This is a workaround for plug-ins not drawing immediately. We'd like to detect when the
    539     // plug-in actually draws instead of just assuming it will do so within 0.5 seconds of being restarted.
    540     [self performSelector:@selector(_clearSubstituteImage) withObject:nil afterDelay:ClearSubstituteImageDelay];
    541 }
    542 
    543 - (BOOL)isHalted
    544 {
    545     return _isHalted;
    546 }
    547 
    548 - (BOOL)superviewsHaveSuperviews
    549 {
    550     NSView *contentView = [[self window] contentView];
    551     for (NSView *view = self; view; view = [view superview]) {
    552         if (view == contentView)
    553             return YES;
    554     }
    555     return NO;
    556 }
    557 
    558 - (BOOL)shouldClipOutPlugin
    559 {
    560     NSWindow *window = [self window];
    561     return !window || [window isMiniaturized] || [NSApp isHidden] || ![self superviewsHaveSuperviews] || [self isHiddenOrHasHiddenAncestor];
    562 }
    563 
    564 - (BOOL)hasBeenHalted
    565 {
    566     return _hasBeenHalted;
    567 }
    568 
    569 - (void)viewWillMoveToWindow:(NSWindow *)newWindow
    570 {
    571     // We must remove the tracking rect before we move to the new window.
    572     // Once we move to the new window, it will be too late.
    573     [self removeTrackingRect];
    574     [self removeWindowObservers];
    575 
    576     // Workaround for: <rdar://problem/3822871> resignFirstResponder is not sent to first responder view when it is removed from the window
    577     [self setHasFocus:NO];
    578 
    579     if (!newWindow) {
    580         if ([[self webView] hostWindow]) {
    581             // View will be moved out of the actual window but it still has a host window.
    582             [self stopTimers];
    583         } else {
    584             // View will have no associated windows.
    585             [self stop];
    586 
    587             // Stop observing WebPreferencesChangedNotification -- we only need to observe this when installed in the view hierarchy.
    588             // When not in the view hierarchy, -viewWillMoveToWindow: and -viewDidMoveToWindow will start/stop the plugin as needed.
    589             [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:nil];
    590         }
    591     }
    592 }
    593 
    594 - (void)viewWillMoveToSuperview:(NSView *)newSuperview
    595 {
    596     if (!newSuperview) {
    597         // Stop the plug-in when it is removed from its superview.  It is not sufficient to do this in -viewWillMoveToWindow:nil, because
    598         // the WebView might still has a hostWindow at that point, which prevents the plug-in from being destroyed.
    599         // There is no need to start the plug-in when moving into a superview.  -viewDidMoveToWindow takes care of that.
    600         [self stop];
    601 
    602         // Stop observing WebPreferencesChangedNotification -- we only need to observe this when installed in the view hierarchy.
    603         // When not in the view hierarchy, -viewWillMoveToWindow: and -viewDidMoveToWindow will start/stop the plugin as needed.
    604         [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:nil];
    605     }
    606 }
    607 
    608 - (void)viewDidMoveToWindow
    609 {
    610     [self resetTrackingRect];
    611 
    612     if ([self window]) {
    613         // While in the view hierarchy, observe WebPreferencesChangedNotification so that we can start/stop depending
    614         // on whether plugins are enabled.
    615         [[NSNotificationCenter defaultCenter] addObserver:self
    616                                                  selector:@selector(preferencesHaveChanged:)
    617                                                      name:WebPreferencesChangedNotification
    618                                                    object:nil];
    619 
    620         _isPrivateBrowsingEnabled = [[[self webView] preferences] privateBrowsingEnabled];
    621 
    622         // View moved to an actual window. Start it if not already started.
    623         [self start];
    624 
    625         // Starting the plug-in can result in it removing itself from the window so we need to ensure that we're still in
    626         // place before doing anything that requires a window.
    627         if ([self window]) {
    628             [self restartTimers];
    629             [self addWindowObservers];
    630         }
    631     } else if ([[self webView] hostWindow]) {
    632         // View moved out of an actual window, but still has a host window.
    633         // Call setWindow to explicitly "clip out" the plug-in from sight.
    634         // FIXME: It would be nice to do this where we call stopNullEvents in viewWillMoveToWindow.
    635         [self updateAndSetWindow];
    636     }
    637 }
    638 
    639 - (void)viewWillMoveToHostWindow:(NSWindow *)hostWindow
    640 {
    641     if (!hostWindow && ![self window]) {
    642         // View will have no associated windows.
    643         [self stop];
    644 
    645         // Remove WebPreferencesChangedNotification observer -- we will observe once again when we move back into the window
    646         [[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:nil];
    647     }
    648 }
    649 
    650 - (void)viewDidMoveToHostWindow
    651 {
    652     if ([[self webView] hostWindow]) {
    653         // View now has an associated window. Start it if not already started.
    654         [self start];
    655     }
    656 }
    657 
    658 #pragma mark NOTIFICATIONS
    659 
    660 - (void)windowWillClose:(NSNotification *)notification
    661 {
    662     [self stop];
    663 }
    664 
    665 - (void)windowBecameKey:(NSNotification *)notification
    666 {
    667     [self sendActivateEvent:YES];
    668     [self invalidatePluginContentRect:[self bounds]];
    669     [self restartTimers];
    670 }
    671 
    672 - (void)windowResignedKey:(NSNotification *)notification
    673 {
    674     [self sendActivateEvent:NO];
    675     [self invalidatePluginContentRect:[self bounds]];
    676     [self restartTimers];
    677 }
    678 
    679 - (void)windowDidMiniaturize:(NSNotification *)notification
    680 {
    681     [self stopTimers];
    682 }
    683 
    684 - (void)windowDidDeminiaturize:(NSNotification *)notification
    685 {
    686     [self restartTimers];
    687 }
    688 
    689 - (void)loginWindowDidSwitchFromUser:(NSNotification *)notification
    690 {
    691     [self stopTimers];
    692 }
    693 
    694 -(void)loginWindowDidSwitchToUser:(NSNotification *)notification
    695 {
    696     [self restartTimers];
    697 }
    698 
    699 - (void)preferencesHaveChanged:(NSNotification *)notification
    700 {
    701     WebPreferences *preferences = [[self webView] preferences];
    702 
    703     if ([notification object] != preferences)
    704         return;
    705 
    706     BOOL arePlugInsEnabled = [preferences arePlugInsEnabled];
    707     if (_isStarted != arePlugInsEnabled) {
    708         if (arePlugInsEnabled) {
    709             if ([self currentWindow]) {
    710                 [self start];
    711             }
    712         } else {
    713             [self stop];
    714             [self invalidatePluginContentRect:[self bounds]];
    715         }
    716     }
    717 
    718     BOOL isPrivateBrowsingEnabled = [preferences privateBrowsingEnabled];
    719     if (isPrivateBrowsingEnabled != _isPrivateBrowsingEnabled) {
    720         _isPrivateBrowsingEnabled = isPrivateBrowsingEnabled;
    721         [self privateBrowsingModeDidChange];
    722     }
    723 }
    724 
    725 - (void)renewGState
    726 {
    727     [super renewGState];
    728 
    729     // -renewGState is called whenever the view's geometry changes.  It's a little hacky to override this method, but
    730     // much safer than walking up the view hierarchy and observing frame/bounds changed notifications, since you don't
    731     // have to track subsequent changes to the view hierarchy and add/remove notification observers.
    732     // NSOpenGLView uses the exact same technique to reshape its OpenGL surface.
    733 
    734     // All of the work this method does may safely be skipped if the view is not in a window.  When the view
    735     // is moved back into a window, everything should be set up correctly.
    736     if (![self window])
    737         return;
    738 
    739     [self updateAndSetWindow];
    740 
    741     [self resetTrackingRect];
    742 
    743     // Check to see if the plugin view is completely obscured (scrolled out of view, for example).
    744     // For performance reasons, we send null events at a lower rate to plugins which are obscured.
    745     BOOL oldIsObscured = _isCompletelyObscured;
    746     _isCompletelyObscured = NSIsEmptyRect([self visibleRect]);
    747     if (_isCompletelyObscured != oldIsObscured)
    748         [self restartTimers];
    749 }
    750 
    751 - (BOOL)becomeFirstResponder
    752 {
    753     [self setHasFocus:YES];
    754     return YES;
    755 }
    756 
    757 - (BOOL)resignFirstResponder
    758 {
    759     [self setHasFocus:NO];
    760     return YES;
    761 }
    762 
    763 - (WebDataSource *)dataSource
    764 {
    765     return [[self webFrame] _dataSource];
    766 }
    767 
    768 - (WebFrame *)webFrame
    769 {
    770     return kit(_element->document()->frame());
    771 }
    772 
    773 - (WebView *)webView
    774 {
    775     return [[self webFrame] webView];
    776 }
    777 
    778 - (NSWindow *)currentWindow
    779 {
    780     return [self window] ? [self window] : [[self webView] hostWindow];
    781 }
    782 
    783 - (WebCore::HTMLPlugInElement*)element
    784 {
    785     return _element.get();
    786 }
    787 
    788 - (void)cut:(id)sender
    789 {
    790     [self sendModifierEventWithKeyCode:7 character:'x'];
    791 }
    792 
    793 - (void)copy:(id)sender
    794 {
    795     [self sendModifierEventWithKeyCode:8 character:'c'];
    796 }
    797 
    798 - (void)paste:(id)sender
    799 {
    800     [self sendModifierEventWithKeyCode:9 character:'v'];
    801 }
    802 
    803 - (void)selectAll:(id)sender
    804 {
    805     [self sendModifierEventWithKeyCode:0 character:'a'];
    806 }
    807 
    808 // AppKit doesn't call mouseDown or mouseUp on right-click. Simulate control-click
    809 // mouseDown and mouseUp so plug-ins get the right-click event as they do in Carbon (3125743).
    810 - (void)rightMouseDown:(NSEvent *)theEvent
    811 {
    812     [self mouseDown:theEvent];
    813 }
    814 
    815 - (void)rightMouseUp:(NSEvent *)theEvent
    816 {
    817     [self mouseUp:theEvent];
    818 }
    819 
    820 
    821 - (BOOL)convertFromX:(double)sourceX andY:(double)sourceY space:(NPCoordinateSpace)sourceSpace
    822                  toX:(double *)destX andY:(double *)destY space:(NPCoordinateSpace)destSpace
    823 {
    824     // Nothing to do
    825     if (sourceSpace == destSpace)
    826         return TRUE;
    827 
    828     NSPoint sourcePoint = NSMakePoint(sourceX, sourceY);
    829 
    830     NSPoint sourcePointInScreenSpace;
    831 
    832     // First convert to screen space
    833     switch (sourceSpace) {
    834         case NPCoordinateSpacePlugin:
    835             sourcePointInScreenSpace = [self convertPoint:sourcePoint toView:nil];
    836             sourcePointInScreenSpace = [[self currentWindow] convertBaseToScreen:sourcePointInScreenSpace];
    837             break;
    838 
    839         case NPCoordinateSpaceWindow:
    840             sourcePointInScreenSpace = [[self currentWindow] convertBaseToScreen:sourcePoint];
    841             break;
    842 
    843         case NPCoordinateSpaceFlippedWindow:
    844             sourcePoint.y = [[self currentWindow] frame].size.height - sourcePoint.y;
    845             sourcePointInScreenSpace = [[self currentWindow] convertBaseToScreen:sourcePoint];
    846             break;
    847 
    848         case NPCoordinateSpaceScreen:
    849             sourcePointInScreenSpace = sourcePoint;
    850             break;
    851 
    852         case NPCoordinateSpaceFlippedScreen:
    853             sourcePoint.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - sourcePoint.y;
    854             sourcePointInScreenSpace = sourcePoint;
    855             break;
    856         default:
    857             return FALSE;
    858     }
    859 
    860     NSPoint destPoint;
    861 
    862     // Then convert back to the destination space
    863     switch (destSpace) {
    864         case NPCoordinateSpacePlugin:
    865             destPoint = [[self currentWindow] convertScreenToBase:sourcePointInScreenSpace];
    866             destPoint = [self convertPoint:destPoint fromView:nil];
    867             break;
    868 
    869         case NPCoordinateSpaceWindow:
    870             destPoint = [[self currentWindow] convertScreenToBase:sourcePointInScreenSpace];
    871             break;
    872 
    873         case NPCoordinateSpaceFlippedWindow:
    874             destPoint = [[self currentWindow] convertScreenToBase:sourcePointInScreenSpace];
    875             destPoint.y = [[self currentWindow] frame].size.height - destPoint.y;
    876             break;
    877 
    878         case NPCoordinateSpaceScreen:
    879             destPoint = sourcePointInScreenSpace;
    880             break;
    881 
    882         case NPCoordinateSpaceFlippedScreen:
    883             destPoint = sourcePointInScreenSpace;
    884             destPoint.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - destPoint.y;
    885             break;
    886 
    887         default:
    888             return FALSE;
    889     }
    890 
    891     if (destX)
    892         *destX = destPoint.x;
    893     if (destY)
    894         *destY = destPoint.y;
    895 
    896     return TRUE;
    897 }
    898 
    899 
    900 - (CString)resolvedURLStringForURL:(const char*)url target:(const char*)target;
    901 {
    902     String relativeURLString = String::fromUTF8(url);
    903     if (relativeURLString.isNull())
    904         return CString();
    905 
    906     Frame* frame = core([self webFrame]);
    907     if (!frame)
    908         return CString();
    909 
    910     Frame* targetFrame = frame->tree()->find(String::fromUTF8(target));
    911     if (!targetFrame)
    912         return CString();
    913 
    914     if (!frame->document()->securityOrigin()->canAccess(targetFrame->document()->securityOrigin()))
    915         return CString();
    916 
    917     KURL absoluteURL = targetFrame->loader()->completeURL(relativeURLString);
    918     return absoluteURL.string().utf8();
    919 }
    920 
    921 - (void)invalidatePluginContentRect:(NSRect)rect
    922 {
    923     if (RenderBoxModelObject *renderer = toRenderBoxModelObject(_element->renderer())) {
    924         IntRect contentRect(rect);
    925         contentRect.move(renderer->borderLeft() + renderer->paddingLeft(), renderer->borderTop() + renderer->paddingTop());
    926 
    927         renderer->repaintRectangle(contentRect);
    928     }
    929 }
    930 
    931 @end
    932 
    933 namespace WebKit {
    934 
    935 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
    936 CString proxiesForURL(NSURL *url)
    937 {
    938     RetainPtr<CFDictionaryRef> systemProxies(AdoptCF, CFNetworkCopySystemProxySettings());
    939     if (!systemProxies)
    940         return "DIRECT";
    941 
    942     RetainPtr<CFArrayRef> proxiesForURL(AdoptCF, CFNetworkCopyProxiesForURL((CFURLRef)url, systemProxies.get()));
    943     CFIndex proxyCount = proxiesForURL ? CFArrayGetCount(proxiesForURL.get()) : 0;
    944     if (!proxyCount)
    945         return "DIRECT";
    946 
    947     // proxiesForURL is a CFArray of CFDictionaries. Each dictionary represents a proxy.
    948     // The format of the result should be:
    949     // "PROXY host[:port]" (for HTTP proxy) or
    950     // "SOCKS host[:port]" (for SOCKS proxy) or
    951     // A combination of the above, separated by semicolon, in the order that they should be tried.
    952     String proxies;
    953     for (CFIndex i = 0; i < proxyCount; ++i) {
    954         CFDictionaryRef proxy = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(proxiesForURL.get(), i));
    955         if (!proxy)
    956             continue;
    957 
    958         CFStringRef type = static_cast<CFStringRef>(CFDictionaryGetValue(proxy, kCFProxyTypeKey));
    959         bool isHTTP = type == kCFProxyTypeHTTP || type == kCFProxyTypeHTTPS;
    960         bool isSOCKS = type == kCFProxyTypeSOCKS;
    961 
    962         // We can only report HTTP and SOCKS proxies.
    963         if (!isHTTP && !isSOCKS)
    964             continue;
    965 
    966         CFStringRef host = static_cast<CFStringRef>(CFDictionaryGetValue(proxy, kCFProxyHostNameKey));
    967         CFNumberRef port = static_cast<CFNumberRef>(CFDictionaryGetValue(proxy, kCFProxyPortNumberKey));
    968 
    969         // If we are inserting multiple entries, add a separator
    970         if (!proxies.isEmpty())
    971             proxies += ";";
    972 
    973         if (isHTTP)
    974             proxies += "PROXY ";
    975         else if (isSOCKS)
    976             proxies += "SOCKS ";
    977 
    978         proxies += host;
    979 
    980         if (port) {
    981             SInt32 intPort;
    982             CFNumberGetValue(port, kCFNumberSInt32Type, &intPort);
    983 
    984             proxies += ":" + String::number(intPort);
    985         }
    986     }
    987 
    988     if (proxies.isEmpty())
    989         return "DIRECT";
    990 
    991     return proxies.utf8();
    992 }
    993 #endif
    994 
    995 bool getAuthenticationInfo(const char* protocolStr, const char* hostStr, int32_t port, const char* schemeStr, const char* realmStr,
    996                            CString& username, CString& password)
    997 {
    998     if (strcasecmp(protocolStr, "http") != 0 &&
    999         strcasecmp(protocolStr, "https") != 0)
   1000         return false;
   1001 
   1002     NSString *host = [NSString stringWithUTF8String:hostStr];
   1003     if (!hostStr)
   1004         return false;
   1005 
   1006     NSString *protocol = [NSString stringWithUTF8String:protocolStr];
   1007     if (!protocol)
   1008         return false;
   1009 
   1010     NSString *realm = [NSString stringWithUTF8String:realmStr];
   1011     if (!realm)
   1012         return NPERR_GENERIC_ERROR;
   1013 
   1014     NSString *authenticationMethod = NSURLAuthenticationMethodDefault;
   1015     if (!strcasecmp(protocolStr, "http")) {
   1016         if (!strcasecmp(schemeStr, "basic"))
   1017             authenticationMethod = NSURLAuthenticationMethodHTTPBasic;
   1018         else if (!strcasecmp(schemeStr, "digest"))
   1019             authenticationMethod = NSURLAuthenticationMethodHTTPDigest;
   1020     }
   1021 
   1022     RetainPtr<NSURLProtectionSpace> protectionSpace(AdoptNS, [[NSURLProtectionSpace alloc] initWithHost:host port:port protocol:protocol realm:realm authenticationMethod:authenticationMethod]);
   1023 
   1024     NSURLCredential *credential = mac(CredentialStorage::get(core(protectionSpace.get())));
   1025     if (!credential)
   1026         credential = [[NSURLCredentialStorage sharedCredentialStorage] defaultCredentialForProtectionSpace:protectionSpace.get()];
   1027     if (!credential)
   1028         return false;
   1029 
   1030     if (![credential hasPassword])
   1031         return false;
   1032 
   1033     username = [[credential user] UTF8String];
   1034     password = [[credential password] UTF8String];
   1035 
   1036     return true;
   1037 }
   1038 
   1039 } // namespace WebKit
   1040 
   1041 #endif //  ENABLE(NETSCAPE_PLUGIN_API)
   1042 
   1043