• 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/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
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);
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