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/Frame.h> 41#import <WebCore/FrameLoaderTypes.h> 42#import <WebCore/HTMLPlugInElement.h> 43#import <WebCore/runtime.h> 44#import <WebCore/runtime_root.h> 45#import <WebCore/WebCoreObjCExtras.h> 46#import <runtime/InitializeThreading.h> 47#import <wtf/Assertions.h> 48 49using namespace WebCore; 50using namespace WebKit; 51 52extern "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 && !_attributeValues); 94 95 _attributeKeys.adoptNS([keys copy]); 96 _attributeValues.adoptNS([values copy]); 97} 98 99- (BOOL)createPlugin 100{ 101 ASSERT(!_proxy); 102 103 NSString *userAgent = [[self webView] userAgentForURL:_baseURL.get()]; 104 105 _proxy = NetscapePluginHostManager::shared().instantiatePlugin(_pluginPackage.get(), self, _MIMEType.get(), _attributeKeys.get(), _attributeValues.get(), userAgent, _sourceURL.get(), _mode == NP_FULL); 106 if (!_proxy) 107 return NO; 108 109 if (_proxy->useSoftwareRenderer()) 110 _softwareRenderer = WKSoftwareCARendererCreate(_proxy->renderContextID()); 111 else { 112 _pluginLayer = WKMakeRenderLayer(_proxy->renderContextID()); 113 self.wantsLayer = YES; 114 } 115 116 // Update the window frame. 117 _proxy->windowFrameChanged([[self window] frame]); 118 119 return YES; 120} 121 122- (void)setLayer:(CALayer *)newLayer 123{ 124 // FIXME: This should use the same implementation as WebNetscapePluginView (and move to the base class). 125 [super setLayer:newLayer]; 126 127 if (_pluginLayer) 128 [newLayer addSublayer:_pluginLayer.get()]; 129} 130 131- (void)loadStream 132{ 133} 134 135- (void)updateAndSetWindow 136{ 137 if (!_proxy) 138 return; 139 140 // Use AppKit to convert view coordinates to NSWindow coordinates. 141 NSRect boundsInWindow = [self convertRect:[self bounds] toView:nil]; 142 NSRect visibleRectInWindow = [self convertRect:[self visibleRect] toView:nil]; 143 144 // Flip Y to convert NSWindow coordinates to top-left-based window coordinates. 145 float borderViewHeight = [[self currentWindow] frame].size.height; 146 boundsInWindow.origin.y = borderViewHeight - NSMaxY(boundsInWindow); 147 visibleRectInWindow.origin.y = borderViewHeight - NSMaxY(visibleRectInWindow); 148 149 BOOL sizeChanged = !NSEqualSizes(_previousSize, boundsInWindow.size); 150 _previousSize = boundsInWindow.size; 151 152 _proxy->resize(boundsInWindow, visibleRectInWindow, sizeChanged); 153} 154 155- (void)windowFocusChanged:(BOOL)hasFocus 156{ 157 if (_proxy) 158 _proxy->windowFocusChanged(hasFocus); 159} 160 161- (BOOL)shouldStop 162{ 163 if (!_proxy) 164 return YES; 165 166 return _proxy->shouldStop(); 167} 168 169- (void)destroyPlugin 170{ 171 if (_proxy) { 172 if (_softwareRenderer) { 173 WKSoftwareCARendererDestroy(_softwareRenderer); 174 _softwareRenderer = 0; 175 } 176 177 _proxy->destroy(); 178 _proxy = 0; 179 } 180 181 _pluginLayer = 0; 182} 183 184- (void)startTimers 185{ 186 if (_proxy) 187 _proxy->startTimers(_isCompletelyObscured); 188} 189 190- (void)stopTimers 191{ 192 if (_proxy) 193 _proxy->stopTimers(); 194} 195 196- (void)focusChanged 197{ 198 if (_proxy) 199 _proxy->focusChanged(_hasFocus); 200} 201 202- (void)windowFrameDidChange:(NSNotification *)notification 203{ 204 if (_proxy && [self window]) 205 _proxy->windowFrameChanged([[self window] frame]); 206} 207 208- (void)addWindowObservers 209{ 210 [super addWindowObservers]; 211 212 ASSERT([self window]); 213 214 NSWindow *window = [self window]; 215 216 NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 217 [notificationCenter addObserver:self selector:@selector(windowFrameDidChange:) 218 name:NSWindowDidMoveNotification object:window]; 219 [notificationCenter addObserver:self selector:@selector(windowFrameDidChange:) 220 name:NSWindowDidResizeNotification object:window]; 221 222 if (_proxy) 223 _proxy->windowFrameChanged([window frame]); 224 [self updateAndSetWindow]; 225} 226 227- (void)removeWindowObservers 228{ 229 [super removeWindowObservers]; 230 231 NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 232 [notificationCenter removeObserver:self name:NSWindowDidMoveNotification object:nil]; 233 [notificationCenter removeObserver:self name:NSWindowDidResizeNotification object:nil]; 234} 235 236- (void)mouseDown:(NSEvent *)event 237{ 238 if (_isStarted && _proxy) 239 _proxy->mouseEvent(self, event, NPCocoaEventMouseDown); 240} 241 242- (void)mouseUp:(NSEvent *)event 243{ 244 if (_isStarted && _proxy) 245 _proxy->mouseEvent(self, event, NPCocoaEventMouseUp); 246} 247 248- (void)mouseDragged:(NSEvent *)event 249{ 250 if (_isStarted && _proxy) 251 _proxy->mouseEvent(self, event, NPCocoaEventMouseDragged); 252} 253 254- (void)mouseEntered:(NSEvent *)event 255{ 256 if (_isStarted && _proxy) 257 _proxy->mouseEvent(self, event, NPCocoaEventMouseEntered); 258} 259 260- (void)mouseExited:(NSEvent *)event 261{ 262 if (_isStarted && _proxy) 263 _proxy->mouseEvent(self, event, NPCocoaEventMouseExited); 264} 265 266- (void)scrollWheel:(NSEvent *)event 267{ 268 bool processedEvent = false; 269 270 if (_isStarted && _proxy) 271 processedEvent = _proxy->wheelEvent(self, event); 272 273 if (!processedEvent) 274 [super scrollWheel:event]; 275} 276 277- (NSTextInputContext *)inputContext 278{ 279 return [[WebTextInputWindowController sharedTextInputWindowController] inputContext]; 280} 281 282- (void)keyDown:(NSEvent *)event 283{ 284 if (!_isStarted || !_proxy) 285 return; 286 287 NSString *string = nil; 288 if ([[WebTextInputWindowController sharedTextInputWindowController] interpretKeyEvent:event string:&string]) { 289 if (string) 290 _proxy->insertText(string); 291 return; 292 } 293 294 _proxy->keyEvent(self, event, NPCocoaEventKeyDown); 295} 296 297- (void)keyUp:(NSEvent *)event 298{ 299 if (_isStarted && _proxy) 300 _proxy->keyEvent(self, event, NPCocoaEventKeyUp); 301} 302 303- (void)flagsChanged:(NSEvent *)event 304{ 305 if (_isStarted && _proxy) 306 _proxy->flagsChanged(event); 307} 308 309- (void)sendModifierEventWithKeyCode:(int)keyCode character:(char)character 310{ 311 if (_isStarted && _proxy) 312 _proxy->syntheticKeyDownWithCommandModifier(keyCode, character); 313} 314 315- (void)pluginHostDied 316{ 317 _pluginHostDied = YES; 318 319 _pluginLayer = nil; 320 _proxy = 0; 321 322 // No need for us to be layer backed anymore 323 self.wantsLayer = NO; 324 325 [self invalidatePluginContentRect:[self bounds]]; 326} 327 328 329- (void)drawRect:(NSRect)rect 330{ 331 if (_proxy) { 332 if (_softwareRenderer) { 333 if ([NSGraphicsContext currentContextDrawingToScreen]) 334 WKSoftwareCARendererRender(_softwareRenderer, (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort], NSRectToCGRect(rect)); 335 else 336 _proxy->print(reinterpret_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]), [self bounds].size.width, [self bounds].size.height); 337 } 338 339 return; 340 } 341 342 if (_pluginHostDied) { 343 static NSImage *nullPlugInImage; 344 if (!nullPlugInImage) { 345 NSBundle *bundle = [NSBundle bundleForClass:[WebHostedNetscapePluginView class]]; 346 nullPlugInImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"nullplugin" ofType:@"tiff"]]; 347 [nullPlugInImage setFlipped:YES]; 348 } 349 350 if (!nullPlugInImage) 351 return; 352 353 NSSize imageSize = [nullPlugInImage size]; 354 NSSize viewSize = [self bounds].size; 355 356 NSPoint point = NSMakePoint((viewSize.width - imageSize.width) / 2.0, (viewSize.height - imageSize.height) / 2.0); 357 [nullPlugInImage drawAtPoint:point fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; 358 } 359} 360 361- (PassRefPtr<JSC::Bindings::Instance>)createPluginBindingsInstance:(PassRefPtr<JSC::Bindings::RootObject>)rootObject 362{ 363 if (!_proxy) 364 return 0; 365 366 return _proxy->createBindingsInstance(rootObject); 367} 368 369- (void)pluginView:(NSView *)pluginView receivedResponse:(NSURLResponse *)response 370{ 371 ASSERT(_loadManually); 372 if (!_proxy) 373 return; 374 375 ASSERT(!_proxy->manualStream()); 376 377 _proxy->setManualStream(HostedNetscapePluginStream::create(_proxy.get(), core([self webFrame])->loader())); 378 _proxy->manualStream()->startStreamWithResponse(response); 379} 380 381- (void)pluginView:(NSView *)pluginView receivedData:(NSData *)data 382{ 383 ASSERT(_loadManually); 384 if (!_proxy) 385 return; 386 387 if (HostedNetscapePluginStream* manualStream = _proxy->manualStream()) 388 manualStream->didReceiveData(0, static_cast<const char*>([data bytes]), [data length]); 389} 390 391- (void)pluginView:(NSView *)pluginView receivedError:(NSError *)error 392{ 393 ASSERT(_loadManually); 394 if (!_proxy) 395 return; 396 397 if (HostedNetscapePluginStream* manualStream = _proxy->manualStream()) 398 manualStream->didFail(0, error); 399} 400 401- (void)pluginViewFinishedLoading:(NSView *)pluginView 402{ 403 ASSERT(_loadManually); 404 if (!_proxy) 405 return; 406 407 if (HostedNetscapePluginStream* manualStream = _proxy->manualStream()) 408 manualStream->didFinishLoading(0); 409} 410 411- (void)_webPluginContainerCancelCheckIfAllowedToLoadRequest:(id)webPluginContainerCheck 412{ 413 ASSERT([webPluginContainerCheck isKindOfClass:[WebPluginContainerCheck class]]); 414 415 id contextInfo = [webPluginContainerCheck contextInfo]; 416 ASSERT(contextInfo && [contextInfo isKindOfClass:[NSNumber class]]); 417 418 if (!_proxy) 419 return; 420 421 uint32_t checkID = [(NSNumber *)contextInfo unsignedIntValue]; 422 _proxy->cancelCheckIfAllowedToLoadURL(checkID); 423} 424 425- (void)_containerCheckResult:(PolicyAction)policy contextInfo:(id)contextInfo 426{ 427 ASSERT([contextInfo isKindOfClass:[NSNumber class]]); 428 if (!_proxy) 429 return; 430 431 uint32_t checkID = [(NSNumber *)contextInfo unsignedIntValue]; 432 _proxy->checkIfAllowedToLoadURLResult(checkID, (policy == PolicyUse)); 433} 434 435@end 436 437#endif 438