Home | History | Annotate | Download | only in Hosted
      1 /*
      2  * Copyright (C) 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  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 #if USE(PLUGIN_HOST_PROCESS)
     26 
     27 #import "WebHostedNetscapePluginView.h"
     28 
     29 #import "HostedNetscapePluginStream.h"
     30 #import "NetscapePluginInstanceProxy.h"
     31 #import "NetscapePluginHostManager.h"
     32 #import "NetscapePluginHostProxy.h"
     33 #import "WebTextInputWindowController.h"
     34 #import "WebFrameInternal.h"
     35 #import "WebView.h"
     36 #import "WebViewInternal.h"
     37 #import "WebUIDelegate.h"
     38 
     39 #import <CoreFoundation/CoreFoundation.h>
     40 #import <WebCore/Bridge.h>
     41 #import <WebCore/Frame.h>
     42 #import <WebCore/FrameLoaderTypes.h>
     43 #import <WebCore/HTMLPlugInElement.h>
     44 #import <WebCore/runtime_root.h>
     45 #import <WebCore/WebCoreObjCExtras.h>
     46 #import <runtime/InitializeThreading.h>
     47 #import <wtf/Assertions.h>
     48 
     49 using namespace WebCore;
     50 using namespace WebKit;
     51 
     52 extern "C" {
     53 #include "WebKitPluginClientServer.h"
     54 #include "WebKitPluginHost.h"
     55 }
     56 
     57 @implementation WebHostedNetscapePluginView
     58 
     59 + (void)initialize
     60 {
     61     JSC::initializeThreading();
     62 #ifndef BUILDING_ON_TIGER
     63     WebCoreObjCFinalizeOnMainThread(self);
     64 #endif
     65     WKSendUserChangeNotifications();
     66 }
     67 
     68 - (id)initWithFrame:(NSRect)frame
     69       pluginPackage:(WebNetscapePluginPackage *)pluginPackage
     70                 URL:(NSURL *)URL
     71             baseURL:(NSURL *)baseURL
     72            MIMEType:(NSString *)MIME
     73       attributeKeys:(NSArray *)keys
     74     attributeValues:(NSArray *)values
     75        loadManually:(BOOL)loadManually
     76             element:(PassRefPtr<WebCore::HTMLPlugInElement>)element
     77 {
     78     self = [super initWithFrame:frame pluginPackage:pluginPackage URL:URL baseURL:baseURL MIMEType:MIME attributeKeys:keys attributeValues:values loadManually:loadManually element:element];
     79     if (!self)
     80         return nil;
     81 
     82     return self;
     83 }
     84 
     85 - (void)handleMouseMoved:(NSEvent *)event
     86 {
     87     if (_isStarted && _proxy)
     88         _proxy->mouseEvent(self, event, NPCocoaEventMouseMoved);
     89 }
     90 
     91 - (void)setAttributeKeys:(NSArray *)keys andValues:(NSArray *)values
     92 {
     93     ASSERT(!_attributeKeys);
     94     ASSERT(!_attributeValues);
     95 
     96     _attributeKeys.adoptNS([keys copy]);
     97     _attributeValues.adoptNS([values copy]);
     98 }
     99 
    100 - (BOOL)createPlugin
    101 {
    102     ASSERT(!_proxy);
    103 
    104     NSString *userAgent = [[self webView] userAgentForURL:_baseURL.get()];
    105     BOOL accleratedCompositingEnabled = false;
    106 #if USE(ACCELERATED_COMPOSITING)
    107     accleratedCompositingEnabled = [[[self webView] preferences] acceleratedCompositingEnabled];
    108 #endif
    109 
    110     _proxy = NetscapePluginHostManager::shared().instantiatePlugin(_pluginPackage.get(), self, _MIMEType.get(), _attributeKeys.get(), _attributeValues.get(), userAgent, _sourceURL.get(),
    111                                                                    _mode == NP_FULL, _isPrivateBrowsingEnabled, accleratedCompositingEnabled);
    112     if (!_proxy)
    113         return NO;
    114 
    115     if (_proxy->useSoftwareRenderer())
    116         _softwareRenderer = WKSoftwareCARendererCreate(_proxy->renderContextID());
    117     else {
    118         _pluginLayer = WKMakeRenderLayer(_proxy->renderContextID());
    119 
    120         if (accleratedCompositingEnabled)
    121             [self element]->setNeedsStyleRecalc(SyntheticStyleChange);
    122         else
    123             self.wantsLayer = YES;
    124     }
    125 
    126     // Update the window frame.
    127     _proxy->windowFrameChanged([[self window] frame]);
    128 
    129     return YES;
    130 }
    131 
    132 // FIXME: This method is an ideal candidate to move up to the base class
    133 - (CALayer *)pluginLayer
    134 {
    135     return _pluginLayer.get();
    136 }
    137 
    138 - (void)setLayer:(CALayer *)newLayer
    139 {
    140     // FIXME: This should use the same implementation as WebNetscapePluginView (and move to the base class).
    141     [super setLayer:newLayer];
    142 
    143     if (_pluginLayer)
    144         [newLayer addSublayer:_pluginLayer.get()];
    145 }
    146 
    147 - (void)privateBrowsingModeDidChange
    148 {
    149     if (_proxy)
    150         _proxy->privateBrowsingModeDidChange(_isPrivateBrowsingEnabled);
    151 }
    152 
    153 - (void)loadStream
    154 {
    155 }
    156 
    157 - (void)updateAndSetWindow
    158 {
    159     if (!_proxy)
    160         return;
    161 
    162     // Use AppKit to convert view coordinates to NSWindow coordinates.
    163     NSRect boundsInWindow = [self convertRect:[self bounds] toView:nil];
    164     NSRect visibleRectInWindow;
    165 
    166     // Core Animation plug-ins need to be updated (with a 0,0,0,0 clipRect) when
    167     // moved to a background tab. We don't do this for Core Graphics plug-ins as
    168     // older versions of Flash have historical WebKit-specific code that isn't
    169     // compatible with this behavior.
    170     BOOL shouldClipOutPlugin = _pluginLayer && [self shouldClipOutPlugin];
    171     if (!shouldClipOutPlugin)
    172         visibleRectInWindow = [self convertRect:[self visibleRect] toView:nil];
    173     else
    174         visibleRectInWindow = NSZeroRect;
    175 
    176     // Flip Y to convert NSWindow coordinates to top-left-based window coordinates.
    177     float borderViewHeight = [[self currentWindow] frame].size.height;
    178     boundsInWindow.origin.y = borderViewHeight - NSMaxY(boundsInWindow);
    179 
    180     if (!shouldClipOutPlugin)
    181         visibleRectInWindow.origin.y = borderViewHeight - NSMaxY(visibleRectInWindow);
    182 
    183     BOOL sizeChanged = !NSEqualSizes(_previousSize, boundsInWindow.size);
    184     _previousSize = boundsInWindow.size;
    185 
    186     _proxy->resize(boundsInWindow, visibleRectInWindow, sizeChanged);
    187 }
    188 
    189 - (void)windowFocusChanged:(BOOL)hasFocus
    190 {
    191     if (_proxy)
    192         _proxy->windowFocusChanged(hasFocus);
    193 }
    194 
    195 - (BOOL)shouldStop
    196 {
    197     if (!_proxy)
    198         return YES;
    199 
    200     return _proxy->shouldStop();
    201 }
    202 
    203 - (void)destroyPlugin
    204 {
    205     if (_proxy) {
    206         if (_softwareRenderer) {
    207             WKSoftwareCARendererDestroy(_softwareRenderer);
    208             _softwareRenderer = 0;
    209         }
    210 
    211         _proxy->destroy();
    212         _proxy = 0;
    213     }
    214 
    215     _pluginLayer = 0;
    216 }
    217 
    218 - (void)startTimers
    219 {
    220     if (_proxy)
    221         _proxy->startTimers(_isCompletelyObscured);
    222 }
    223 
    224 - (void)stopTimers
    225 {
    226     if (_proxy)
    227         _proxy->stopTimers();
    228 }
    229 
    230 - (void)focusChanged
    231 {
    232     if (_proxy)
    233         _proxy->focusChanged(_hasFocus);
    234 }
    235 
    236 - (void)windowFrameDidChange:(NSNotification *)notification
    237 {
    238     if (_proxy && [self window])
    239         _proxy->windowFrameChanged([[self window] frame]);
    240 }
    241 
    242 - (void)addWindowObservers
    243 {
    244     [super addWindowObservers];
    245 
    246     ASSERT([self window]);
    247 
    248     NSWindow *window = [self window];
    249 
    250     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    251     [notificationCenter addObserver:self selector:@selector(windowFrameDidChange:)
    252                                name:NSWindowDidMoveNotification object:window];
    253     [notificationCenter addObserver:self selector:@selector(windowFrameDidChange:)
    254                                name:NSWindowDidResizeNotification object:window];
    255 
    256     if (_proxy)
    257         _proxy->windowFrameChanged([window frame]);
    258     [self updateAndSetWindow];
    259 }
    260 
    261 - (void)removeWindowObservers
    262 {
    263     [super removeWindowObservers];
    264 
    265     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    266     [notificationCenter removeObserver:self name:NSWindowDidMoveNotification object:nil];
    267     [notificationCenter removeObserver:self name:NSWindowDidResizeNotification object:nil];
    268 }
    269 
    270 - (void)mouseDown:(NSEvent *)event
    271 {
    272     if (_isStarted && _proxy)
    273         _proxy->mouseEvent(self, event, NPCocoaEventMouseDown);
    274 }
    275 
    276 - (void)mouseUp:(NSEvent *)event
    277 {
    278     if (_isStarted && _proxy)
    279         _proxy->mouseEvent(self, event, NPCocoaEventMouseUp);
    280 }
    281 
    282 - (void)mouseDragged:(NSEvent *)event
    283 {
    284     if (_isStarted && _proxy)
    285         _proxy->mouseEvent(self, event, NPCocoaEventMouseDragged);
    286 }
    287 
    288 - (void)mouseEntered:(NSEvent *)event
    289 {
    290     if (_isStarted && _proxy)
    291         _proxy->mouseEvent(self, event, NPCocoaEventMouseEntered);
    292 }
    293 
    294 - (void)mouseExited:(NSEvent *)event
    295 {
    296     if (_isStarted && _proxy)
    297         _proxy->mouseEvent(self, event, NPCocoaEventMouseExited);
    298 }
    299 
    300 - (void)scrollWheel:(NSEvent *)event
    301 {
    302     bool processedEvent = false;
    303 
    304     if (_isStarted && _proxy)
    305         processedEvent = _proxy->wheelEvent(self, event);
    306 
    307     if (!processedEvent)
    308         [super scrollWheel:event];
    309 }
    310 
    311 - (NSTextInputContext *)inputContext
    312 {
    313     return [[WebTextInputWindowController sharedTextInputWindowController] inputContext];
    314 }
    315 
    316 - (void)keyDown:(NSEvent *)event
    317 {
    318     if (!_isStarted || !_proxy)
    319         return;
    320 
    321     NSString *string = nil;
    322     if ([[WebTextInputWindowController sharedTextInputWindowController] interpretKeyEvent:event string:&string]) {
    323         if (string)
    324             _proxy->insertText(string);
    325         return;
    326     }
    327 
    328     _proxy->keyEvent(self, event, NPCocoaEventKeyDown);
    329 }
    330 
    331 - (void)keyUp:(NSEvent *)event
    332 {
    333     if (_isStarted && _proxy)
    334         _proxy->keyEvent(self, event, NPCocoaEventKeyUp);
    335 }
    336 
    337 - (void)flagsChanged:(NSEvent *)event
    338 {
    339     if (_isStarted && _proxy)
    340         _proxy->flagsChanged(event);
    341 }
    342 
    343 - (void)sendModifierEventWithKeyCode:(int)keyCode character:(char)character
    344 {
    345     if (_isStarted && _proxy)
    346         _proxy->syntheticKeyDownWithCommandModifier(keyCode, character);
    347 }
    348 
    349 - (void)pluginHostDied
    350 {
    351     _pluginHostDied = YES;
    352 
    353     _pluginLayer = nil;
    354     _proxy = 0;
    355 
    356     // No need for us to be layer backed anymore
    357     self.wantsLayer = NO;
    358 
    359     [self invalidatePluginContentRect:[self bounds]];
    360 }
    361 
    362 
    363 - (void)drawRect:(NSRect)rect
    364 {
    365     if (_proxy) {
    366         if (_softwareRenderer) {
    367             if ([NSGraphicsContext currentContextDrawingToScreen]) {
    368                 WKSoftwareCARendererRender(_softwareRenderer, (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort], NSRectToCGRect(rect));
    369                 _proxy->didDraw();
    370             } else
    371                 _proxy->print(reinterpret_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]), [self bounds].size.width, [self bounds].size.height);
    372         }
    373 
    374         return;
    375     }
    376 
    377     if (_pluginHostDied) {
    378         static NSImage *nullPlugInImage;
    379         if (!nullPlugInImage) {
    380             NSBundle *bundle = [NSBundle bundleForClass:[WebHostedNetscapePluginView class]];
    381             nullPlugInImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"nullplugin" ofType:@"tiff"]];
    382             [nullPlugInImage setFlipped:YES];
    383         }
    384 
    385         if (!nullPlugInImage)
    386             return;
    387 
    388         NSSize imageSize = [nullPlugInImage size];
    389         NSSize viewSize = [self bounds].size;
    390 
    391         NSPoint point = NSMakePoint((viewSize.width - imageSize.width) / 2.0, (viewSize.height - imageSize.height) / 2.0);
    392         [nullPlugInImage drawAtPoint:point fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
    393     }
    394 }
    395 
    396 - (PassRefPtr<JSC::Bindings::Instance>)createPluginBindingsInstance:(PassRefPtr<JSC::Bindings::RootObject>)rootObject
    397 {
    398     if (!_proxy)
    399         return 0;
    400 
    401     return _proxy->createBindingsInstance(rootObject);
    402 }
    403 
    404 - (void)pluginView:(NSView *)pluginView receivedResponse:(NSURLResponse *)response
    405 {
    406     ASSERT(_loadManually);
    407     if (!_proxy)
    408         return;
    409 
    410     ASSERT(!_proxy->manualStream());
    411 
    412     _proxy->setManualStream(HostedNetscapePluginStream::create(_proxy.get(), core([self webFrame])->loader()));
    413     _proxy->manualStream()->startStreamWithResponse(response);
    414 }
    415 
    416 - (void)pluginView:(NSView *)pluginView receivedData:(NSData *)data
    417 {
    418     ASSERT(_loadManually);
    419     if (!_proxy)
    420         return;
    421 
    422     if (HostedNetscapePluginStream* manualStream = _proxy->manualStream())
    423         manualStream->didReceiveData(0, static_cast<const char*>([data bytes]), [data length]);
    424 }
    425 
    426 - (void)pluginView:(NSView *)pluginView receivedError:(NSError *)error
    427 {
    428     ASSERT(_loadManually);
    429     if (!_proxy)
    430         return;
    431 
    432     if (HostedNetscapePluginStream* manualStream = _proxy->manualStream())
    433         manualStream->didFail(0, error);
    434 }
    435 
    436 - (void)pluginViewFinishedLoading:(NSView *)pluginView
    437 {
    438     ASSERT(_loadManually);
    439     if (!_proxy)
    440         return;
    441 
    442     if (HostedNetscapePluginStream* manualStream = _proxy->manualStream())
    443         manualStream->didFinishLoading(0);
    444 }
    445 
    446 - (void)_webPluginContainerCancelCheckIfAllowedToLoadRequest:(id)webPluginContainerCheck
    447 {
    448     ASSERT([webPluginContainerCheck isKindOfClass:[WebPluginContainerCheck class]]);
    449 
    450     id contextInfo = [webPluginContainerCheck contextInfo];
    451     ASSERT([contextInfo isKindOfClass:[NSNumber class]]);
    452 
    453     if (!_proxy)
    454         return;
    455 
    456     uint32_t checkID = [(NSNumber *)contextInfo unsignedIntValue];
    457     _proxy->cancelCheckIfAllowedToLoadURL(checkID);
    458 }
    459 
    460 - (void)_containerCheckResult:(PolicyAction)policy contextInfo:(id)contextInfo
    461 {
    462     ASSERT([contextInfo isKindOfClass:[NSNumber class]]);
    463     if (!_proxy)
    464         return;
    465 
    466     uint32_t checkID = [(NSNumber *)contextInfo unsignedIntValue];
    467     _proxy->checkIfAllowedToLoadURLResult(checkID, (policy == PolicyUse));
    468 }
    469 
    470 - (void)webFrame:(WebFrame *)webFrame didFinishLoadWithReason:(NPReason)reason
    471 {
    472     if (_isStarted && _proxy)
    473         _proxy->webFrameDidFinishLoadWithReason(webFrame, reason);
    474 }
    475 
    476 - (void)webFrame:(WebFrame *)webFrame didFinishLoadWithError:(NSError *)error
    477 {
    478     NPReason reason = NPRES_DONE;
    479     if (error)
    480         reason = HostedNetscapePluginStream::reasonForError(error);
    481     [self webFrame:webFrame didFinishLoadWithReason:reason];
    482 }
    483 
    484 @end
    485 
    486 #endif
    487