• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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