summaryrefslogtreecommitdiffstats
path: root/WebKit/mac/Plugins
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/mac/Plugins')
-rw-r--r--WebKit/mac/Plugins/WebBaseNetscapePluginStream.h7
-rw-r--r--WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm20
-rw-r--r--WebKit/mac/Plugins/WebBaseNetscapePluginView.h186
-rw-r--r--WebKit/mac/Plugins/WebBaseNetscapePluginView.mm2751
-rw-r--r--WebKit/mac/Plugins/WebBasePluginPackage.mm (renamed from WebKit/mac/Plugins/WebBasePluginPackage.m)6
-rw-r--r--WebKit/mac/Plugins/WebNetscapePluginEventHandler.h10
-rw-r--r--WebKit/mac/Plugins/WebNetscapePluginEventHandler.mm4
-rw-r--r--WebKit/mac/Plugins/WebNetscapePluginEventHandlerCarbon.h2
-rw-r--r--WebKit/mac/Plugins/WebNetscapePluginEventHandlerCarbon.mm9
-rw-r--r--WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.h2
-rw-r--r--WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.mm4
-rw-r--r--WebKit/mac/Plugins/WebNetscapePluginPackage.h40
-rw-r--r--WebKit/mac/Plugins/WebNetscapePluginPackage.m150
-rw-r--r--WebKit/mac/Plugins/WebNetscapePluginView.h174
-rw-r--r--WebKit/mac/Plugins/WebNetscapePluginView.mm2338
-rw-r--r--WebKit/mac/Plugins/WebPluginController.mm2
-rw-r--r--WebKit/mac/Plugins/WebPluginDatabase.mm6
-rw-r--r--WebKit/mac/Plugins/WebPluginRequest.h (renamed from WebKit/mac/Plugins/WebPlugInStreamLoaderDelegate.h)34
-rw-r--r--WebKit/mac/Plugins/WebPluginRequest.m80
-rw-r--r--WebKit/mac/Plugins/npapi.mm16
20 files changed, 2955 insertions, 2886 deletions
diff --git a/WebKit/mac/Plugins/WebBaseNetscapePluginStream.h b/WebKit/mac/Plugins/WebBaseNetscapePluginStream.h
index c2e8a21..a28793a 100644
--- a/WebKit/mac/Plugins/WebBaseNetscapePluginStream.h
+++ b/WebKit/mac/Plugins/WebBaseNetscapePluginStream.h
@@ -32,20 +32,19 @@
#import <WebCore/Timer.h>
#import <WebCore/NetscapePlugInStreamLoader.h>
#import <WebKit/npfunctions.h>
-#import <WebKit/WebPlugInStreamLoaderDelegate.h>
#import <wtf/PassRefPtr.h>
#import <wtf/RefCounted.h>
#import <wtf/RefPtr.h>
#import <wtf/RetainPtr.h>
-#import "WebBaseNetscapePluginView.h"
+#import "WebNetscapePluginView.h"
namespace WebCore {
class FrameLoader;
class NetscapePlugInStreamLoader;
}
-@class WebBaseNetscapePluginView;
+@class WebNetscapePluginView;
@class NSURLResponse;
class WebNetscapePluginStream : public RefCounted<WebNetscapePluginStream>
@@ -113,7 +112,7 @@ private:
BOOL m_sendNotification;
void *m_notifyData;
char *m_headers;
- RetainPtr<WebBaseNetscapePluginView> m_pluginView;
+ RetainPtr<WebNetscapePluginView> m_pluginView;
NPReason m_reason;
bool m_isTerminated;
bool m_newStreamSuccessful;
diff --git a/WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm b/WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm
index 246a3ca..a29be2d 100644
--- a/WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm
+++ b/WebKit/mac/Plugins/WebBaseNetscapePluginStream.mm
@@ -29,7 +29,7 @@
#if ENABLE(NETSCAPE_PLUGIN_API)
#import "WebBaseNetscapePluginStream.h"
-#import "WebBaseNetscapePluginView.h"
+#import "WebNetscapePluginView.h"
#import "WebFrameInternal.h"
#import "WebKitErrorsPrivate.h"
#import "WebKitLogging.h"
@@ -45,6 +45,7 @@
#import <WebCore/WebCoreObjCExtras.h>
#import <WebKitSystemInterface.h>
#import <wtf/HashMap.h>
+#import <wtf/StdLibExtras.h>
using namespace WebCore;
@@ -55,7 +56,7 @@ static NSString *CarbonPathFromPOSIXPath(NSString *posixPath);
typedef HashMap<NPStream*, NPP> StreamMap;
static StreamMap& streams()
{
- static StreamMap staticStreams;
+ DEFINE_STATIC_LOCAL(StreamMap, staticStreams, ());
return staticStreams;
}
@@ -134,7 +135,7 @@ WebNetscapePluginStream::WebNetscapePluginStream(NSURLRequest *request, NPP plug
{
memset(&m_stream, 0, sizeof(NPStream));
- WebBaseNetscapePluginView *view = (WebBaseNetscapePluginView *)plugin->ndata;
+ WebNetscapePluginView *view = (WebNetscapePluginView *)plugin->ndata;
// This check has already been done by the plug-in view.
ASSERT(FrameLoader::canLoad([request URL], String(), core([view webFrame])->document()));
@@ -148,9 +149,6 @@ WebNetscapePluginStream::WebNetscapePluginStream(NSURLRequest *request, NPP plug
if (core([view webFrame])->loader()->shouldHideReferrer([request URL], core([view webFrame])->loader()->outgoingReferrer()))
[m_request.get() _web_setHTTPReferrer:nil];
-
- m_loader = NetscapePlugInStreamLoader::create(core([view webFrame]), this);
- m_loader->setShouldBufferData(false);
}
WebNetscapePluginStream::~WebNetscapePluginStream()
@@ -173,13 +171,13 @@ void WebNetscapePluginStream::setPlugin(NPP plugin)
{
if (plugin) {
m_plugin = plugin;
- m_pluginView = static_cast<WebBaseNetscapePluginView *>(m_plugin->ndata);
+ m_pluginView = static_cast<WebNetscapePluginView *>(m_plugin->ndata);
WebNetscapePluginPackage *pluginPackage = [m_pluginView.get() pluginPackage];
m_pluginFuncs = [pluginPackage pluginFuncs];
} else {
- WebBaseNetscapePluginView *view = m_pluginView.get();
+ WebNetscapePluginView *view = m_pluginView.get();
m_plugin = 0;
m_pluginFuncs = 0;
@@ -256,6 +254,10 @@ void WebNetscapePluginStream::start()
{
ASSERT(m_request);
ASSERT(!m_frameLoader);
+ ASSERT(!m_loader);
+
+ m_loader = NetscapePlugInStreamLoader::create(core([m_pluginView.get() webFrame]), this);
+ m_loader->setShouldBufferData(false);
m_loader->documentLoader()->addPlugInStreamLoader(m_loader.get());
m_loader->load(m_request.get());
@@ -434,6 +436,8 @@ void WebNetscapePluginStream::destroyStreamWithReason(NPReason reason)
// There is more data to be streamed, don't destroy the stream now.
return;
}
+
+ RefPtr<WebNetscapePluginStream> protect(this);
destroyStream();
ASSERT(!m_stream.ndata);
}
diff --git a/WebKit/mac/Plugins/WebBaseNetscapePluginView.h b/WebKit/mac/Plugins/WebBaseNetscapePluginView.h
index 909196b..b2ea2b1 100644
--- a/WebKit/mac/Plugins/WebBaseNetscapePluginView.h
+++ b/WebKit/mac/Plugins/WebBaseNetscapePluginView.h
@@ -29,118 +29,37 @@
#if ENABLE(NETSCAPE_PLUGIN_API)
#import <Cocoa/Cocoa.h>
-#import <WebKit/npfunctions.h>
-#import <WebKit/npapi.h>
-#import <WebKit/WebBasePluginPackage.h>
-#import <wtf/HashMap.h>
-#import <wtf/HashSet.h>
+#import "WebNetscapePluginPackage.h"
+
+#import <wtf/RetainPtr.h>
@class DOMElement;
@class WebDataSource;
@class WebFrame;
-@class WebNetscapePluginPackage;
@class WebView;
-class PluginTimer;
-class WebNetscapePluginStream;
-class WebNetscapePluginEventHandler;
-
-typedef union PluginPort {
-#ifndef NP_NO_QUICKDRAW
- NP_Port qdPort;
-#endif
- NP_CGContext cgPort;
-} PluginPort;
-
-typedef struct _NPPluginTextInputFuncs NPPluginTextInputFuncs;
-
-// Because the Adobe 7.x Acrobat plug-in has a hard coded check for a view named
-// "WebNetscapePluginDocumentView", this class must retain the old name in order
-// for the plug-in to function correctly. (rdar://problem/4699455)
-#define WebBaseNetscapePluginView WebNetscapePluginDocumentView
-
-@interface WebBaseNetscapePluginView : NSView <WebPluginManualLoader, NSTextInput>
+@interface WebBaseNetscapePluginView : NSView
{
- WebNetscapePluginPackage *pluginPackage;
+ RetainPtr<WebNetscapePluginPackage> _pluginPackage;
- NSURL *sourceURL;
WebFrame *_webFrame;
- BOOL _loadManually;
- RefPtr<WebNetscapePluginStream> _manualStream;
-#ifndef BUILDING_ON_TIGER
- CALayer *_layer;
-#endif
- unsigned _dataLengthReceived;
- NSError *_error;
-
- int mode;
-
- unsigned argsCount;
- char **cAttributes;
- char **cValues;
-
- NPP plugin;
- NPWindow window;
- NPWindow lastSetWindow;
- PluginPort nPort;
- PluginPort lastSetPort;
- NPDrawingModel drawingModel;
- NPEventModel eventModel;
+ int _mode;
-
-#ifndef NP_NO_QUICKDRAW
- // This is only valid when drawingModel is NPDrawingModelQuickDraw
- GWorldPtr offscreenGWorld;
-#endif
-
- WebNetscapePluginEventHandler *eventHandler;
-
- BOOL isStarted;
- BOOL inSetWindow;
- BOOL hasFocus;
- BOOL isTransparent;
- BOOL isCompletelyObscured;
- BOOL shouldStopSoon;
-
- BOOL shouldFireTimers;
- uint32 currentTimerID;
- HashMap<uint32, PluginTimer*>* timers;
-
- unsigned pluginFunctionCallDepth;
-
- DOMElement *element;
-
- int32 specifiedHeight;
- int32 specifiedWidth;
-
- NSString *MIMEType;
- NSURL *baseURL;
- NSTrackingRectTag trackingTag;
-
- HashSet<RefPtr<WebNetscapePluginStream> > streams;
- NSMutableDictionary *pendingFrameLoads;
+ BOOL _loadManually;
+ BOOL _shouldFireTimers;
+ BOOL _isStarted;
+ BOOL _hasFocus;
+ BOOL _isCompletelyObscured;
- NPPluginTextInputFuncs *textInputFuncs;
+ RetainPtr<DOMElement> _element;
+ RetainPtr<NSString> _MIMEType;
+ RetainPtr<NSURL> _baseURL;
+ RetainPtr<NSURL> _sourceURL;
- NPP_NewProcPtr NPP_New;
- NPP_DestroyProcPtr NPP_Destroy;
- NPP_SetWindowProcPtr NPP_SetWindow;
- NPP_NewStreamProcPtr NPP_NewStream;
- NPP_DestroyStreamProcPtr NPP_DestroyStream;
- NPP_StreamAsFileProcPtr NPP_StreamAsFile;
- NPP_WriteReadyProcPtr NPP_WriteReady;
- NPP_WriteProcPtr NPP_Write;
- NPP_PrintProcPtr NPP_Print;
- NPP_HandleEventProcPtr NPP_HandleEvent;
- NPP_URLNotifyProcPtr NPP_URLNotify;
- NPP_GetValueProcPtr NPP_GetValue;
- NPP_SetValueProcPtr NPP_SetValue;
+ NSTrackingRectTag _trackingTag;
}
-+ (WebBaseNetscapePluginView *)currentPluginView;
-
-
- (id)initWithFrame:(NSRect)r
pluginPackage:(WebNetscapePluginPackage *)thePluginPackage
URL:(NSURL *)URL
@@ -151,74 +70,31 @@ typedef struct _NPPluginTextInputFuncs NPPluginTextInputFuncs;
loadManually:(BOOL)loadManually
DOMElement:(DOMElement *)anElement;
+- (WebNetscapePluginPackage *)pluginPackage;
-- (BOOL)start;
-- (BOOL)isStarted;
-- (void)stop;
-- (void)stopTimers;
-- (void)restartTimers;
+- (NSMutableURLRequest *)requestWithURLCString:(const char *)URLCString;
+
+// Subclasses must override these.
+- (void)handleMouseMoved:(NSEvent *)event;
+- (void)setAttributeKeys:(NSArray *)keys andValues:(NSArray *)values;
+- (void)focusChanged;
- (WebFrame *)webFrame;
- (WebDataSource *)dataSource;
- (WebView *)webView;
- (NSWindow *)currentWindow;
-- (NPP)plugin;
+- (void)removeTrackingRect;
+- (void)resetTrackingRect;
-- (WebNetscapePluginPackage *)pluginPackage;
-- (void)setPluginPackage:(WebNetscapePluginPackage *)thePluginPackage;
-- (void)setMIMEType:(NSString *)theMIMEType;
-- (void)setBaseURL:(NSURL *)theBaseURL;
-- (void)setAttributeKeys:(NSArray *)keys andValues:(NSArray *)values;
-- (void)setMode:(int)theMode;
-- (void)viewWillMoveToHostWindow:(NSWindow *)hostWindow;
-- (void)viewDidMoveToHostWindow;
-- (void)disconnectStream:(WebNetscapePluginStream*)stream;
-
-// Returns the NPObject that represents the plugin interface.
-// The return value is expected to be retained.
-- (NPObject *)createPluginScriptableObject;
-
-// -willCallPlugInFunction must be called before calling any of the NPP_* functions for this view's plugin.
-// This is necessary to ensure that plug-ins are not destroyed while WebKit calls into them. Some plug-ins (Flash
-// at least) are written with the assumption that nothing they do in their plug-in functions can cause NPP_Destroy()
-// to be called. Unfortunately, this is not true, especially if the plug-in uses NPN_Invoke() to execute a
-// document.write(), which clears the document and destroys the plug-in.
-// See <rdar://problem/4480737>.
-- (void)willCallPlugInFunction;
-
-// -didCallPlugInFunction should be called after returning from a plug-in function. It should be called exactly
-// once for every call to -willCallPlugInFunction.
-// See <rdar://problem/4480737>.
-- (void)didCallPlugInFunction;
-
-- (void)handleMouseMoved:(NSEvent *)event;
-
-@end
+- (void)stopTimers;
+- (void)startTimers;
+- (void)restartTimers;
-@interface WebBaseNetscapePluginView (WebInternal)
-- (BOOL)sendEvent:(void*)event isDrawRect:(BOOL)eventIsDrawRect;
-- (NPEventModel)eventModel;
-
-- (NPError)loadRequest:(NSURLRequest *)request inTarget:(NSString *)target withNotifyData:(void *)notifyData sendNotification:(BOOL)sendNotification;
-- (NPError)getURLNotify:(const char *)URL target:(const char *)target notifyData:(void *)notifyData;
-- (NPError)getURL:(const char *)URL target:(const char *)target;
-- (NPError)postURLNotify:(const char *)URL target:(const char *)target len:(UInt32)len buf:(const char *)buf file:(NPBool)file notifyData:(void *)notifyData;
-- (NPError)postURL:(const char *)URL target:(const char *)target len:(UInt32)len buf:(const char *)buf file:(NPBool)file;
-- (NPError)newStream:(NPMIMEType)type target:(const char *)target stream:(NPStream**)stream;
-- (NPError)write:(NPStream*)stream len:(SInt32)len buffer:(void *)buffer;
-- (NPError)destroyStream:(NPStream*)stream reason:(NPReason)reason;
-- (void)status:(const char *)message;
-- (const char *)userAgent;
-- (void)invalidateRect:(NPRect *)invalidRect;
-- (void)invalidateRegion:(NPRegion)invalidateRegion;
-- (void)forceRedraw;
-- (NPError)getVariable:(NPNVariable)variable value:(void *)value;
-- (NPError)setVariable:(NPPVariable)variable value:(void *)value;
-- (uint32)scheduleTimerWithInterval:(uint32)interval repeat:(NPBool)repeat timerFunc:(void (*)(NPP npp, uint32 timerID))timerFunc;
-- (void)unscheduleTimer:(uint32)timerID;
-- (NPError)popUpContextMenu:(NPMenu *)menu;
+- (void)stop;
+- (void)addWindowObservers;
+- (void)removeWindowObservers;
@end
#endif
diff --git a/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm b/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm
index 2097673..a2a8b50 100644
--- a/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm
+++ b/WebKit/mac/Plugins/WebBaseNetscapePluginView.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,1100 +30,250 @@
#import "WebBaseNetscapePluginView.h"
-#import "WebDataSourceInternal.h"
-#import "WebDefaultUIDelegate.h"
-#import "WebFrameInternal.h"
-#import "WebFrameView.h"
-#import "WebGraphicsExtras.h"
+#import "WebFrameInternal.h"
#import "WebKitLogging.h"
#import "WebKitNSStringExtras.h"
#import "WebKitSystemInterface.h"
-#import "WebNSDataExtras.h"
-#import "WebNSDictionaryExtras.h"
-#import "WebNSObjectExtras.h"
#import "WebNSURLExtras.h"
#import "WebNSURLRequestExtras.h"
-#import "WebNSViewExtras.h"
-#import "WebNetscapePluginPackage.h"
-#import "WebBaseNetscapePluginStream.h"
-#import "WebNetscapePluginEventHandler.h"
-#import "WebNullPluginView.h"
-#import "WebPreferences.h"
+#import "WebView.h"
#import "WebViewInternal.h"
-#import "WebUIDelegatePrivate.h"
-#import <Carbon/Carbon.h>
-#import <runtime/JSLock.h>
-#import <WebCore/npruntime_impl.h>
+
+#import <WebCore/WebCoreObjCExtras.h>
#import <WebCore/Document.h>
-#import <WebCore/DocumentLoader.h>
#import <WebCore/Element.h>
-#import <WebCore/Frame.h>
-#import <WebCore/FrameLoader.h>
-#import <WebCore/FrameTree.h>
-#import <WebCore/Page.h>
-#import <WebCore/PluginMainThreadScheduler.h>
-#import <WebCore/ScriptController.h>
-#import <WebCore/SoftLinking.h>
-#import <WebCore/WebCoreObjCExtras.h>
-#import <WebKit/nptextinput.h>
+#import <WebCore/Frame.h>
+#import <WebCore/FrameLoader.h>
+#import <WebCore/Page.h>
#import <WebKit/DOMPrivate.h>
-#import <WebKit/WebUIDelegate.h>
+#import <runtime/InitializeThreading.h>
#import <wtf/Assertions.h>
-#import <objc/objc-runtime.h>
-
-using namespace WebCore;
#define LoginWindowDidSwitchFromUserNotification @"WebLoginWindowDidSwitchFromUserNotification"
#define LoginWindowDidSwitchToUserNotification @"WebLoginWindowDidSwitchToUserNotification"
-static inline bool isDrawingModelQuickDraw(NPDrawingModel drawingModel)
-{
-#ifndef NP_NO_QUICKDRAW
- return drawingModel == NPDrawingModelQuickDraw;
-#else
- return false;
-#endif
-};
-
-@interface WebBaseNetscapePluginView (Internal)
-- (void)_viewHasMoved;
-- (NPError)_createPlugin;
-- (void)_destroyPlugin;
-- (NSBitmapImageRep *)_printedPluginBitmap;
-- (void)_redeliverStream;
-@end
-
-static WebBaseNetscapePluginView *currentPluginView = nil;
-
-typedef struct OpaquePortState* PortState;
-
-static const double ThrottledTimerInterval = 0.25;
-
-class PluginTimer : public TimerBase {
-public:
- typedef void (*TimerFunc)(NPP npp, uint32 timerID);
-
- PluginTimer(NPP npp, uint32 timerID, uint32 interval, NPBool repeat, TimerFunc timerFunc)
- : m_npp(npp)
- , m_timerID(timerID)
- , m_interval(interval)
- , m_repeat(repeat)
- , m_timerFunc(timerFunc)
- {
- }
-
- void start(bool throttle)
- {
- ASSERT(!isActive());
-
- double timeInterval = throttle ? ThrottledTimerInterval : m_interval / 1000.0;
- if (m_repeat)
- startRepeating(timeInterval);
- else
- startOneShot(timeInterval);
- }
-
-private:
- virtual void fired()
- {
- m_timerFunc(m_npp, m_timerID);
- if (!m_repeat)
- delete this;
- }
-
- NPP m_npp;
- uint32 m_timerID;
- uint32 m_interval;
- NPBool m_repeat;
- TimerFunc m_timerFunc;
-};
-
-#ifndef NP_NO_QUICKDRAW
-
-// QuickDraw is not available in 64-bit
-
-typedef struct {
- GrafPtr oldPort;
- GDHandle oldDevice;
- Point oldOrigin;
- RgnHandle oldClipRegion;
- RgnHandle oldVisibleRegion;
- RgnHandle clipRegion;
- BOOL forUpdate;
-} PortState_QD;
-
-#endif /* NP_NO_QUICKDRAW */
-
-typedef struct {
- CGContextRef context;
-} PortState_CG;
-
-@class NSTextInputContext;
-@interface NSResponder (AppKitDetails)
-- (NSTextInputContext *)inputContext;
-@end
-
-@interface WebPluginRequest : NSObject
-{
- NSURLRequest *_request;
- NSString *_frameName;
- void *_notifyData;
- BOOL _didStartFromUserGesture;
- BOOL _sendNotification;
-}
-
-- (id)initWithRequest:(NSURLRequest *)request frameName:(NSString *)frameName notifyData:(void *)notifyData sendNotification:(BOOL)sendNotification didStartFromUserGesture:(BOOL)currentEventIsUserGesture;
-
-- (NSURLRequest *)request;
-- (NSString *)frameName;
-- (void *)notifyData;
-- (BOOL)isCurrentEventUserGesture;
-- (BOOL)sendNotification;
-
-@end
-
-@interface NSData (WebPluginDataExtras)
-- (BOOL)_web_startsWithBlankLine;
-- (NSInteger)_web_locationAfterFirstBlankLine;
-@end
-
-@interface WebBaseNetscapePluginView (ForwardDeclarations)
-- (void)setWindowIfNecessary;
-- (NPError)loadRequest:(NSMutableURLRequest *)request inTarget:(const char *)cTarget withNotifyData:(void *)notifyData sendNotification:(BOOL)sendNotification;
-@end
+using namespace WebCore;
@implementation WebBaseNetscapePluginView
+ (void)initialize
{
+ JSC::initializeThreading();
#ifndef BUILDING_ON_TIGER
WebCoreObjCFinalizeOnMainThread(self);
#endif
WKSendUserChangeNotifications();
}
-#pragma mark EVENTS
-
-- (BOOL)superviewsHaveSuperviews
-{
- NSView *contentView = [[self window] contentView];
- NSView *view;
- for (view = self; view != nil; view = [view superview]) {
- if (view == contentView) {
- return YES;
- }
- }
- return NO;
-}
-
-
-// The WindowRef created by -[NSWindow windowRef] has a QuickDraw GrafPort that covers
-// the entire window frame (or structure region to use the Carbon term) rather then just the window content.
-// We can remove this when <rdar://problem/4201099> is fixed.
-- (void)fixWindowPort
+- (id)initWithFrame:(NSRect)frame
+ pluginPackage:(WebNetscapePluginPackage *)pluginPackage
+ URL:(NSURL *)URL
+ baseURL:(NSURL *)baseURL
+ MIMEType:(NSString *)MIME
+ attributeKeys:(NSArray *)keys
+ attributeValues:(NSArray *)values
+ loadManually:(BOOL)loadManually
+ DOMElement:(DOMElement *)anElement
{
-#ifndef NP_NO_QUICKDRAW
- ASSERT(isDrawingModelQuickDraw(drawingModel));
-
- NSWindow *currentWindow = [self currentWindow];
- if ([currentWindow isKindOfClass:objc_getClass("NSCarbonWindow")])
- return;
+ self = [super initWithFrame:frame];
+ if (!self)
+ return nil;
- float windowHeight = [currentWindow frame].size.height;
- NSView *contentView = [currentWindow contentView];
- NSRect contentRect = [contentView convertRect:[contentView frame] toView:nil]; // convert to window-relative coordinates
+ _pluginPackage = pluginPackage;
+ _element = anElement;
+ _sourceURL.adoptNS([URL copy]);
+ _baseURL.adoptNS([baseURL copy]);
+ _MIMEType.adoptNS([MIME copy]);
- CGrafPtr oldPort;
- GetPort(&oldPort);
- SetPort(GetWindowPort((WindowRef)[currentWindow windowRef]));
+ [self setAttributeKeys:keys andValues:values];
+ if (loadManually)
+ _mode = NP_FULL;
+ else
+ _mode = NP_EMBED;
- MovePortTo(static_cast<short>(contentRect.origin.x), /* Flip Y */ static_cast<short>(windowHeight - NSMaxY(contentRect)));
- PortSize(static_cast<short>(contentRect.size.width), static_cast<short>(contentRect.size.height));
+ _loadManually = loadManually;
- SetPort(oldPort);
-#endif
+ return self;
}
-#ifndef NP_NO_QUICKDRAW
-static UInt32 getQDPixelFormatForBitmapContext(CGContextRef context)
+- (void)dealloc
{
- UInt32 byteOrder = CGBitmapContextGetBitmapInfo(context) & kCGBitmapByteOrderMask;
- if (byteOrder == kCGBitmapByteOrderDefault)
- switch (CGBitmapContextGetBitsPerPixel(context)) {
- case 16:
- byteOrder = kCGBitmapByteOrder16Host;
- break;
- case 32:
- byteOrder = kCGBitmapByteOrder32Host;
- break;
- }
- switch (byteOrder) {
- case kCGBitmapByteOrder16Little:
- return k16LE555PixelFormat;
- case kCGBitmapByteOrder32Little:
- return k32BGRAPixelFormat;
- case kCGBitmapByteOrder16Big:
- return k16BE555PixelFormat;
- case kCGBitmapByteOrder32Big:
- return k32ARGBPixelFormat;
- }
- ASSERT_NOT_REACHED();
- return 0;
-}
+ ASSERT(!_isStarted);
-static inline void getNPRect(const CGRect& cgr, NPRect& npr)
-{
- npr.top = static_cast<uint16>(cgr.origin.y);
- npr.left = static_cast<uint16>(cgr.origin.x);
- npr.bottom = static_cast<uint16>(CGRectGetMaxY(cgr));
- npr.right = static_cast<uint16>(CGRectGetMaxX(cgr));
+ [super dealloc];
}
-#endif
-
-static inline void getNPRect(const NSRect& nr, NPRect& npr)
+- (void)finalize
{
- npr.top = static_cast<uint16>(nr.origin.y);
- npr.left = static_cast<uint16>(nr.origin.x);
- npr.bottom = static_cast<uint16>(NSMaxY(nr));
- npr.right = static_cast<uint16>(NSMaxX(nr));
-}
+ ASSERT_MAIN_THREAD();
+ ASSERT(!_isStarted);
-- (NSRect)visibleRect
-{
- // WebCore may impose an additional clip (via CSS overflow or clip properties). Fetch
- // that clip now.
- return NSIntersectionRect([self convertRect:[element _windowClipRect] fromView:nil], [super visibleRect]);
+ [super finalize];
}
-- (PortState)saveAndSetNewPortStateForUpdate:(BOOL)forUpdate
+- (WebNetscapePluginPackage *)pluginPackage
{
- ASSERT(drawingModel != NPDrawingModelCoreAnimation);
- ASSERT([self currentWindow] != nil);
-
- // If drawing with QuickDraw, fix the window port so that it has the same bounds as the NSWindow's
- // content view. This makes it easier to convert between AppKit view and QuickDraw port coordinates.
- if (isDrawingModelQuickDraw(drawingModel))
- [self fixWindowPort];
-
- // Use AppKit to convert view coordinates to NSWindow coordinates.
- NSRect boundsInWindow = [self convertRect:[self bounds] toView:nil];
- NSRect visibleRectInWindow = [self convertRect:[self visibleRect] toView:nil];
-
- // Flip Y to convert NSWindow coordinates to top-left-based window coordinates.
- float borderViewHeight = [[self currentWindow] frame].size.height;
- boundsInWindow.origin.y = borderViewHeight - NSMaxY(boundsInWindow);
- visibleRectInWindow.origin.y = borderViewHeight - NSMaxY(visibleRectInWindow);
-
-#ifndef NP_NO_QUICKDRAW
- WindowRef windowRef = (WindowRef)[[self currentWindow] windowRef];
- ASSERT(windowRef);
-
- // Look at the Carbon port to convert top-left-based window coordinates into top-left-based content coordinates.
- if (isDrawingModelQuickDraw(drawingModel)) {
- ::Rect portBounds;
- CGrafPtr port = GetWindowPort(windowRef);
- GetPortBounds(port, &portBounds);
-
- PixMap *pix = *GetPortPixMap(port);
- boundsInWindow.origin.x += pix->bounds.left - portBounds.left;
- boundsInWindow.origin.y += pix->bounds.top - portBounds.top;
- visibleRectInWindow.origin.x += pix->bounds.left - portBounds.left;
- visibleRectInWindow.origin.y += pix->bounds.top - portBounds.top;
- }
-#endif
-
- window.x = (int32)boundsInWindow.origin.x;
- window.y = (int32)boundsInWindow.origin.y;
- window.width = static_cast<uint32>(NSWidth(boundsInWindow));
- window.height = static_cast<uint32>(NSHeight(boundsInWindow));
-
- // "Clip-out" the plug-in when:
- // 1) it's not really in a window or off-screen or has no height or width.
- // 2) window.x is a "big negative number" which is how WebCore expresses off-screen widgets.
- // 3) the window is miniaturized or the app is hidden
- // 4) we're inside of viewWillMoveToWindow: with a nil window. In this case, superviews may already have nil
- // superviews and nil windows and results from convertRect:toView: are incorrect.
- NSWindow *realWindow = [self window];
- if (window.width <= 0 || window.height <= 0 || window.x < -100000
- || realWindow == nil || [realWindow isMiniaturized]
- || [NSApp isHidden]
- || ![self superviewsHaveSuperviews]
- || [self isHiddenOrHasHiddenAncestor]) {
-
- // The following code tries to give plug-ins the same size they will eventually have.
- // The specifiedWidth and specifiedHeight variables are used to predict the size that
- // WebCore will eventually resize us to.
-
- // The QuickTime plug-in has problems if you give it a width or height of 0.
- // Since other plug-ins also might have the same sort of trouble, we make sure
- // to always give plug-ins a size other than 0,0.
-
- if (window.width <= 0)
- window.width = specifiedWidth > 0 ? specifiedWidth : 100;
- if (window.height <= 0)
- window.height = specifiedHeight > 0 ? specifiedHeight : 100;
-
- window.clipRect.bottom = window.clipRect.top;
- window.clipRect.left = window.clipRect.right;
- } else {
- getNPRect(visibleRectInWindow, window.clipRect);
- }
-
- // Save the port state, set up the port for entry into the plugin
- PortState portState;
- switch (drawingModel) {
-#ifndef NP_NO_QUICKDRAW
- case NPDrawingModelQuickDraw: {
- // Set up NS_Port.
- ::Rect portBounds;
- CGrafPtr port = GetWindowPort(windowRef);
- GetPortBounds(port, &portBounds);
- nPort.qdPort.port = port;
- nPort.qdPort.portx = (int32)-boundsInWindow.origin.x;
- nPort.qdPort.porty = (int32)-boundsInWindow.origin.y;
- window.window = &nPort;
-
- PortState_QD *qdPortState = (PortState_QD*)malloc(sizeof(PortState_QD));
- portState = (PortState)qdPortState;
-
- GetGWorld(&qdPortState->oldPort, &qdPortState->oldDevice);
-
- qdPortState->oldOrigin.h = portBounds.left;
- qdPortState->oldOrigin.v = portBounds.top;
-
- qdPortState->oldClipRegion = NewRgn();
- GetPortClipRegion(port, qdPortState->oldClipRegion);
-
- qdPortState->oldVisibleRegion = NewRgn();
- GetPortVisibleRegion(port, qdPortState->oldVisibleRegion);
-
- RgnHandle clipRegion = NewRgn();
- qdPortState->clipRegion = clipRegion;
-
- CGContextRef currentContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
- if (currentContext && WKCGContextIsBitmapContext(currentContext)) {
- // We use WKCGContextIsBitmapContext here, because if we just called CGBitmapContextGetData
- // on any context, we'd log to the console every time. But even if WKCGContextIsBitmapContext
- // returns true, it still might not be a context we need to create a GWorld for; for example
- // transparency layers will return true, but return 0 for CGBitmapContextGetData.
- void* offscreenData = CGBitmapContextGetData(currentContext);
- if (offscreenData) {
- // If the current context is an offscreen bitmap, then create a GWorld for it.
- ::Rect offscreenBounds;
- offscreenBounds.top = 0;
- offscreenBounds.left = 0;
- offscreenBounds.right = CGBitmapContextGetWidth(currentContext);
- offscreenBounds.bottom = CGBitmapContextGetHeight(currentContext);
- GWorldPtr newOffscreenGWorld;
- QDErr err = NewGWorldFromPtr(&newOffscreenGWorld,
- getQDPixelFormatForBitmapContext(currentContext), &offscreenBounds, 0, 0, 0,
- static_cast<char*>(offscreenData), CGBitmapContextGetBytesPerRow(currentContext));
- ASSERT(newOffscreenGWorld && !err);
- if (!err) {
- if (offscreenGWorld)
- DisposeGWorld(offscreenGWorld);
- offscreenGWorld = newOffscreenGWorld;
-
- SetGWorld(offscreenGWorld, NULL);
-
- port = offscreenGWorld;
-
- nPort.qdPort.port = port;
- boundsInWindow = [self bounds];
-
- // Generate a QD origin based on the current affine transform for currentContext.
- CGAffineTransform offscreenMatrix = CGContextGetCTM(currentContext);
- CGPoint origin = {0,0};
- CGPoint axisFlip = {1,1};
- origin = CGPointApplyAffineTransform(origin, offscreenMatrix);
- axisFlip = CGPointApplyAffineTransform(axisFlip, offscreenMatrix);
-
- // Quartz bitmaps have origins at the bottom left, but the axes may be inverted, so handle that.
- origin.x = offscreenBounds.left - origin.x * (axisFlip.x - origin.x);
- origin.y = offscreenBounds.bottom + origin.y * (axisFlip.y - origin.y);
-
- nPort.qdPort.portx = static_cast<int32>(-boundsInWindow.origin.x + origin.x);
- nPort.qdPort.porty = static_cast<int32>(-boundsInWindow.origin.y - origin.y);
- window.x = 0;
- window.y = 0;
- window.window = &nPort;
-
- // Use the clip bounds from the context instead of the bounds we created
- // from the window above.
- getNPRect(CGRectOffset(CGContextGetClipBoundingBox(currentContext), -origin.x, origin.y), window.clipRect);
- }
- }
- }
-
- MacSetRectRgn(clipRegion,
- window.clipRect.left + nPort.qdPort.portx, window.clipRect.top + nPort.qdPort.porty,
- window.clipRect.right + nPort.qdPort.portx, window.clipRect.bottom + nPort.qdPort.porty);
-
- // Clip to the dirty region if drawing to a window. When drawing to another bitmap context, do not clip.
- if ([NSGraphicsContext currentContext] == [[self currentWindow] graphicsContext]) {
- // Clip to dirty region so plug-in does not draw over already-drawn regions of the window that are
- // not going to be redrawn this update. This forces plug-ins to play nice with z-index ordering.
- if (forUpdate) {
- RgnHandle viewClipRegion = NewRgn();
-
- // Get list of dirty rects from the opaque ancestor -- WebKit does some tricks with invalidation and
- // display to enable z-ordering for NSViews; a side-effect of this is that only the WebHTMLView
- // knows about the true set of dirty rects.
- NSView *opaqueAncestor = [self opaqueAncestor];
- const NSRect *dirtyRects;
- NSInteger dirtyRectCount, dirtyRectIndex;
- [opaqueAncestor getRectsBeingDrawn:&dirtyRects count:&dirtyRectCount];
-
- for (dirtyRectIndex = 0; dirtyRectIndex < dirtyRectCount; dirtyRectIndex++) {
- NSRect dirtyRect = [self convertRect:dirtyRects[dirtyRectIndex] fromView:opaqueAncestor];
- if (!NSEqualSizes(dirtyRect.size, NSZeroSize)) {
- // Create a region for this dirty rect
- RgnHandle dirtyRectRegion = NewRgn();
- SetRectRgn(dirtyRectRegion, static_cast<short>(NSMinX(dirtyRect)), static_cast<short>(NSMinY(dirtyRect)), static_cast<short>(NSMaxX(dirtyRect)), static_cast<short>(NSMaxY(dirtyRect)));
-
- // Union this dirty rect with the rest of the dirty rects
- UnionRgn(viewClipRegion, dirtyRectRegion, viewClipRegion);
- DisposeRgn(dirtyRectRegion);
- }
- }
-
- // Intersect the dirty region with the clip region, so that we only draw over dirty parts
- SectRgn(clipRegion, viewClipRegion, clipRegion);
- DisposeRgn(viewClipRegion);
- }
- }
-
- // Switch to the port and set it up.
- SetPort(port);
- PenNormal();
- ForeColor(blackColor);
- BackColor(whiteColor);
- SetOrigin(nPort.qdPort.portx, nPort.qdPort.porty);
- SetPortClipRegion(nPort.qdPort.port, clipRegion);
-
- if (forUpdate) {
- // AppKit may have tried to help us by doing a BeginUpdate.
- // But the invalid region at that level didn't include AppKit's notion of what was not valid.
- // We reset the port's visible region to counteract what BeginUpdate did.
- SetPortVisibleRegion(nPort.qdPort.port, clipRegion);
- InvalWindowRgn(windowRef, clipRegion);
- }
-
- qdPortState->forUpdate = forUpdate;
- break;
- }
-#endif /* NP_NO_QUICKDRAW */
-
- case NPDrawingModelCoreGraphics: {
- ASSERT([NSView focusView] == self);
-
- CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]);
-
- PortState_CG *cgPortState = (PortState_CG *)malloc(sizeof(PortState_CG));
- portState = (PortState)cgPortState;
- cgPortState->context = context;
-
- // Update the plugin's window/context
-#ifdef NP_NO_CARBON
- nPort.cgPort.window = (NPNSWindow *)[self currentWindow];
-#else
- nPort.cgPort.window = eventHandler->platformWindow([self currentWindow]);
-#endif /* NP_NO_CARBON */
- nPort.cgPort.context = context;
- window.window = &nPort.cgPort;
-
- // Save current graphics context's state; will be restored by -restorePortState:
- CGContextSaveGState(context);
-
- // Clip to the dirty region if drawing to a window. When drawing to another bitmap context, do not clip.
- if ([NSGraphicsContext currentContext] == [[self currentWindow] graphicsContext]) {
- // Get list of dirty rects from the opaque ancestor -- WebKit does some tricks with invalidation and
- // display to enable z-ordering for NSViews; a side-effect of this is that only the WebHTMLView
- // knows about the true set of dirty rects.
- NSView *opaqueAncestor = [self opaqueAncestor];
- const NSRect *dirtyRects;
- NSInteger count;
- [opaqueAncestor getRectsBeingDrawn:&dirtyRects count:&count];
- Vector<CGRect, 16> convertedDirtyRects;
- convertedDirtyRects.resize(count);
- for (int i = 0; i < count; ++i)
- reinterpret_cast<NSRect&>(convertedDirtyRects[i]) = [self convertRect:dirtyRects[i] fromView:opaqueAncestor];
- CGContextClipToRects(context, convertedDirtyRects.data(), count);
- }
-
- break;
- }
-
- default:
- ASSERT_NOT_REACHED();
- portState = NULL;
- break;
- }
-
- return portState;
+ return _pluginPackage.get();
}
-
-- (PortState)saveAndSetNewPortState
+
+- (BOOL)isFlipped
{
- return [self saveAndSetNewPortStateForUpdate:NO];
+ return YES;
}
-- (void)restorePortState:(PortState)portState
+- (NSMutableURLRequest *)requestWithURLCString:(const char *)URLCString
{
- if (drawingModel == NPDrawingModelCoreAnimation)
- return;
-
- ASSERT([self currentWindow]);
- ASSERT(portState);
+ if (!URLCString)
+ return nil;
- switch (drawingModel) {
-#ifndef NP_NO_QUICKDRAW
- case NPDrawingModelQuickDraw: {
- PortState_QD *qdPortState = (PortState_QD *)portState;
- WindowRef windowRef = (WindowRef)[[self currentWindow] windowRef];
- CGrafPtr port = GetWindowPort(windowRef);
-
- SetPort(port);
-
- if (qdPortState->forUpdate)
- ValidWindowRgn(windowRef, qdPortState->clipRegion);
-
- SetOrigin(qdPortState->oldOrigin.h, qdPortState->oldOrigin.v);
-
- SetPortClipRegion(port, qdPortState->oldClipRegion);
- if (qdPortState->forUpdate)
- SetPortVisibleRegion(port, qdPortState->oldVisibleRegion);
-
- DisposeRgn(qdPortState->oldClipRegion);
- DisposeRgn(qdPortState->oldVisibleRegion);
- DisposeRgn(qdPortState->clipRegion);
-
- SetGWorld(qdPortState->oldPort, qdPortState->oldDevice);
- break;
- }
-#endif /* NP_NO_QUICKDRAW */
-
- case NPDrawingModelCoreGraphics:
- ASSERT([NSView focusView] == self);
- ASSERT(((PortState_CG *)portState)->context == nPort.cgPort.context);
- CGContextRestoreGState(nPort.cgPort.context);
- break;
-
- default:
- ASSERT_NOT_REACHED();
- break;
- }
-}
-
-- (BOOL)sendEvent:(void*)event isDrawRect:(BOOL)eventIsDrawRect
-{
- if (![self window])
- return NO;
- ASSERT(event);
-
- if (!isStarted)
- return NO;
-
- ASSERT(NPP_HandleEvent);
+ CFStringRef string = CFStringCreateWithCString(kCFAllocatorDefault, URLCString, kCFStringEncodingISOLatin1);
+ ASSERT(string); // All strings should be representable in ISO Latin 1
- // Make sure we don't call NPP_HandleEvent while we're inside NPP_SetWindow.
- // We probably don't want more general reentrancy protection; we are really
- // protecting only against this one case, which actually comes up when
- // you first install the SVG viewer plug-in.
- if (inSetWindow)
- return NO;
-
+ NSString *URLString = [(NSString *)string _web_stringByStrippingReturnCharacters];
+ NSURL *URL = [NSURL _web_URLWithDataAsString:URLString relativeToURL:_baseURL.get()];
+ CFRelease(string);
+ if (!URL)
+ return nil;
+
+ NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
Frame* frame = core([self webFrame]);
if (!frame)
- return NO;
- Page* page = frame->page();
- if (!page)
- return NO;
-
- bool wasDeferring = page->defersLoading();
- if (!wasDeferring)
- page->setDefersLoading(true);
-
- // Can only send drawRect (updateEvt) to CoreGraphics plugins when actually drawing
- ASSERT((drawingModel != NPDrawingModelCoreGraphics) || !eventIsDrawRect || [NSView focusView] == self);
-
- PortState portState = NULL;
-
- if (isDrawingModelQuickDraw(drawingModel) || (drawingModel != NPDrawingModelCoreAnimation && eventIsDrawRect)) {
- // In CoreGraphics mode, the port state only needs to be saved/set when redrawing the plug-in view.
- // The plug-in is not allowed to draw at any other time.
- portState = [self saveAndSetNewPortStateForUpdate:eventIsDrawRect];
- // We may have changed the window, so inform the plug-in.
- [self setWindowIfNecessary];
- }
-
-#if !defined(NDEBUG) && !defined(NP_NO_QUICKDRAW)
- // Draw green to help debug.
- // If we see any green we know something's wrong.
- // Note that PaintRect() only works for QuickDraw plugins; otherwise the current QD port is undefined.
- if (isDrawingModelQuickDraw(drawingModel) && !isTransparent && eventIsDrawRect) {
- ForeColor(greenColor);
- const ::Rect bigRect = { -10000, -10000, 10000, 10000 };
- PaintRect(&bigRect);
- ForeColor(blackColor);
- }
-#endif
-
- // Temporarily retain self in case the plug-in view is released while sending an event.
- [[self retain] autorelease];
-
- BOOL acceptedEvent;
- [self willCallPlugInFunction];
- {
- JSC::JSLock::DropAllLocks dropAllLocks(false);
- acceptedEvent = NPP_HandleEvent(plugin, event);
- }
- [self didCallPlugInFunction];
-
- if (portState) {
- if ([self currentWindow])
- [self restorePortState:portState];
- free(portState);
- }
-
- if (!wasDeferring)
- page->setDefersLoading(false);
-
- return acceptedEvent;
+ return nil;
+ [request _web_setHTTPReferrer:frame->loader()->outgoingReferrer()];
+ return request;
}
-- (void)sendActivateEvent:(BOOL)activate
+// Methods that subclasses must override
+- (void)setAttributeKeys:(NSArray *)keys andValues:(NSArray *)values
{
- if (!isStarted)
- return;
-
- eventHandler->windowFocusChanged(activate);
+ ASSERT_NOT_REACHED();
}
-- (void)sendDrawRectEvent:(NSRect)rect
+- (void)handleMouseMoved:(NSEvent *)event
{
- ASSERT(eventHandler);
-
- eventHandler->drawRect(rect);
+ ASSERT_NOT_REACHED();
}
-- (void)stopTimers
+- (void)focusChanged
{
- if (eventHandler)
- eventHandler->stopTimers();
-
- shouldFireTimers = NO;
-
- if (!timers)
- return;
-
- HashMap<uint32, PluginTimer*>::const_iterator end = timers->end();
- for (HashMap<uint32, PluginTimer*>::const_iterator it = timers->begin(); it != end; ++it) {
- PluginTimer* timer = it->second;
- timer->stop();
- }
+ ASSERT_NOT_REACHED();
}
-- (void)restartTimers
+- (void)windowFocusChanged:(BOOL)hasFocus
{
- ASSERT([self window]);
-
- if (shouldFireTimers)
- [self stopTimers];
-
- if (!isStarted || [[self window] isMiniaturized])
- return;
-
- shouldFireTimers = YES;
-
- // If the plugin is completely obscured (scrolled out of view, for example), then we will
- // send null events at a reduced rate.
- eventHandler->startTimers(isCompletelyObscured);
-
- if (!timers)
- return;
-
- HashMap<uint32, PluginTimer*>::const_iterator end = timers->end();
- for (HashMap<uint32, PluginTimer*>::const_iterator it = timers->begin(); it != end; ++it) {
- PluginTimer* timer = it->second;
- ASSERT(!timer->isActive());
- timer->start(isCompletelyObscured);
- }
+ ASSERT_NOT_REACHED();
}
-- (BOOL)acceptsFirstResponder
+- (BOOL)createPlugin
{
- return YES;
+ ASSERT_NOT_REACHED();
+ return NO;
}
-- (void)setHasFocus:(BOOL)flag
+- (void)loadStream
{
- if (!isStarted)
- return;
-
- if (hasFocus == flag)
- return;
-
- hasFocus = flag;
-
- // We need to null check the event handler here because
- // the plug-in view can resign focus after it's been stopped
- // and the event handler has been deleted.
- if (eventHandler)
- eventHandler->focusChanged(hasFocus);
+ ASSERT_NOT_REACHED();
}
-- (BOOL)becomeFirstResponder
+- (BOOL)shouldStop
{
- [self setHasFocus:YES];
+ ASSERT_NOT_REACHED();
return YES;
}
-- (BOOL)resignFirstResponder
+- (void)destroyPlugin
{
- [self setHasFocus:NO];
- return YES;
+ ASSERT_NOT_REACHED();
}
-// AppKit doesn't call mouseDown or mouseUp on right-click. Simulate control-click
-// mouseDown and mouseUp so plug-ins get the right-click event as they do in Carbon (3125743).
-- (void)rightMouseDown:(NSEvent *)theEvent
+- (void)updateAndSetWindow
{
- [self mouseDown:theEvent];
+ ASSERT_NOT_REACHED();
}
-- (void)rightMouseUp:(NSEvent *)theEvent
+- (void)removeTrackingRect
{
- [self mouseUp:theEvent];
+ if (_trackingTag) {
+ [self removeTrackingRect:_trackingTag];
+ _trackingTag = 0;
+
+ // Do the following after setting trackingTag to 0 so we don't re-enter.
+
+ // Balance the retain in resetTrackingRect. Use autorelease in case we hold
+ // the last reference to the window during tear-down, to avoid crashing AppKit.
+ [[self window] autorelease];
+ }
}
-- (void)mouseDown:(NSEvent *)theEvent
+- (void)resetTrackingRect
{
- if (!isStarted)
- return;
-
- eventHandler->mouseDown(theEvent);
+ [self removeTrackingRect];
+ if (_isStarted) {
+ // Retain the window so that removeTrackingRect can work after the window is closed.
+ [[self window] retain];
+ _trackingTag = [self addTrackingRect:[self bounds] owner:self userData:nil assumeInside:NO];
+ }
}
-- (void)mouseUp:(NSEvent *)theEvent
+- (void)stopTimers
{
- if (!isStarted)
- return;
-
- eventHandler->mouseUp(theEvent);
+ _shouldFireTimers = NO;
}
-- (void)mouseEntered:(NSEvent *)theEvent
+- (void)startTimers
{
- if (!isStarted)
- return;
-
- eventHandler->mouseEntered(theEvent);
+ _shouldFireTimers = YES;
}
-- (void)mouseExited:(NSEvent *)theEvent
+- (void)restartTimers
{
- if (!isStarted)
- return;
-
- eventHandler->mouseExited(theEvent);
+ ASSERT([self window]);
- // Set cursor back to arrow cursor. Because NSCursor doesn't know about changes that the plugin made, we could get confused about what we think the
- // current cursor is otherwise. Therefore we have no choice but to unconditionally reset the cursor when the mouse exits the plugin.
- [[NSCursor arrowCursor] set];
-}
-
-// We can't name this method mouseMoved because we don't want to override
-// the NSView mouseMoved implementation.
-- (void)handleMouseMoved:(NSEvent *)theEvent
-{
- if (!isStarted)
- return;
-
- eventHandler->mouseMoved(theEvent);
-}
+ [self stopTimers];
-- (void)mouseDragged:(NSEvent *)theEvent
-{
- if (!isStarted)
+ if (!_isStarted || [[self window] isMiniaturized])
return;
-
- eventHandler->mouseDragged(theEvent);
-}
-
-- (void)scrollWheel:(NSEvent *)theEvent
-{
- if (!isStarted) {
- [super scrollWheel:theEvent];
- return;
- }
-
- if (!eventHandler->scrollWheel(theEvent))
- [super scrollWheel:theEvent];
-}
-
-- (void)keyUp:(NSEvent *)theEvent
-{
- if (!isStarted)
- return;
-
- eventHandler->keyUp(theEvent);
-}
-
-- (void)keyDown:(NSEvent *)theEvent
-{
- if (!isStarted)
- return;
-
- eventHandler->keyDown(theEvent);
-}
-
-- (void)flagsChanged:(NSEvent *)theEvent
-{
- if (!isStarted)
- return;
-
- eventHandler->flagsChanged(theEvent);
-}
-
-- (void)cut:(id)sender
-{
- if (!isStarted)
- return;
-
- eventHandler->keyDown([NSApp currentEvent]);
-}
-
-- (void)copy:(id)sender
-{
- if (!isStarted)
- return;
-
- eventHandler->keyDown([NSApp currentEvent]);
-}
-
-- (void)paste:(id)sender
-{
- if (!isStarted)
- return;
-
- eventHandler->keyDown([NSApp currentEvent]);
+
+ [self startTimers];
}
-- (void)selectAll:(id)sender
+- (NSRect)visibleRect
{
- if (!isStarted)
- return;
-
- eventHandler->keyDown([NSApp currentEvent]);
+ // WebCore may impose an additional clip (via CSS overflow or clip properties). Fetch
+ // that clip now.
+ return NSIntersectionRect([self convertRect:[_element.get() _windowClipRect] fromView:nil], [super visibleRect]);
}
-#pragma mark WEB_NETSCAPE_PLUGIN
-
-- (BOOL)isNewWindowEqualToOldWindow
+- (BOOL)acceptsFirstResponder
{
- ASSERT(drawingModel != NPDrawingModelCoreAnimation);
-
- if (window.x != lastSetWindow.x)
- return NO;
- if (window.y != lastSetWindow.y)
- return NO;
- if (window.width != lastSetWindow.width)
- return NO;
- if (window.height != lastSetWindow.height)
- return NO;
- if (window.clipRect.top != lastSetWindow.clipRect.top)
- return NO;
- if (window.clipRect.left != lastSetWindow.clipRect.left)
- return NO;
- if (window.clipRect.bottom != lastSetWindow.clipRect.bottom)
- return NO;
- if (window.clipRect.right != lastSetWindow.clipRect.right)
- return NO;
- if (window.type != lastSetWindow.type)
- return NO;
-
- switch (drawingModel) {
-#ifndef NP_NO_QUICKDRAW
- case NPDrawingModelQuickDraw:
- if (nPort.qdPort.portx != lastSetPort.qdPort.portx)
- return NO;
- if (nPort.qdPort.porty != lastSetPort.qdPort.porty)
- return NO;
- if (nPort.qdPort.port != lastSetPort.qdPort.port)
- return NO;
- break;
-#endif /* NP_NO_QUICKDRAW */
-
- case NPDrawingModelCoreGraphics:
- if (nPort.cgPort.window != lastSetPort.cgPort.window)
- return NO;
- if (nPort.cgPort.context != lastSetPort.cgPort.context)
- return NO;
- break;
-
- default:
- ASSERT_NOT_REACHED();
- break;
- }
-
return YES;
}
-- (void)updateAndSetWindow
+- (void)sendActivateEvent:(BOOL)activate
{
- ASSERT(drawingModel != NPDrawingModelCoreAnimation);
-
- // A plug-in can only update if it's (1) already been started (2) isn't stopped
- // and (3) is able to draw on-screen. To meet condition (3) the plug-in must not
- // be hidden and be attached to a window. QuickDraw plug-ins are an important
- // excpetion to rule (3) because they manually must be told when to stop writing
- // bits to the window backing store, thus to do so requires a new call to
- // NPP_SetWindow() with an empty NPWindow struct.
- if (!isStarted)
- return;
-#ifdef NP_NO_QUICKDRAW
- if (![self canDraw])
- return;
-#else
- if (drawingModel != NPDrawingModelQuickDraw && ![self canDraw])
+ if (!_isStarted)
return;
-#endif // NP_NO_QUICKDRAW
- BOOL didLockFocus = [NSView focusView] != self && [self lockFocusIfCanDraw];
-
- if (drawingModel == NPDrawingModelCoreGraphics || isDrawingModelQuickDraw(drawingModel)) {
- [self setWindowIfNecessary];
- if (didLockFocus)
- [self unlockFocus];
-
- return;
- }
-
- PortState portState = [self saveAndSetNewPortState];
- if (portState) {
- [self setWindowIfNecessary];
- [self restorePortState:portState];
- free(portState);
- }
- if (didLockFocus)
- [self unlockFocus];
+ [self windowFocusChanged:activate];
}
-- (void)setWindowIfNecessary
+- (void)setHasFocus:(BOOL)flag
{
- ASSERT(drawingModel != NPDrawingModelCoreAnimation);
-
- if (!isStarted) {
+ if (!_isStarted)
return;
- }
- if (![self isNewWindowEqualToOldWindow]) {
- // Make sure we don't call NPP_HandleEvent while we're inside NPP_SetWindow.
- // We probably don't want more general reentrancy protection; we are really
- // protecting only against this one case, which actually comes up when
- // you first install the SVG viewer plug-in.
- NPError npErr;
- ASSERT(!inSetWindow);
-
- inSetWindow = YES;
-
- // A CoreGraphics plugin's window may only be set while the plugin is being updated
- ASSERT((drawingModel != NPDrawingModelCoreGraphics) || [NSView focusView] == self);
-
- [self willCallPlugInFunction];
- {
- JSC::JSLock::DropAllLocks dropAllLocks(false);
- npErr = NPP_SetWindow(plugin, &window);
- }
- [self didCallPlugInFunction];
- inSetWindow = NO;
-
-#ifndef NDEBUG
- switch (drawingModel) {
-#ifndef NP_NO_QUICKDRAW
- case NPDrawingModelQuickDraw:
- LOG(Plugins, "NPP_SetWindow (QuickDraw): %d, port=0x%08x, window.x:%d window.y:%d window.width:%d window.height:%d",
- npErr, (int)nPort.qdPort.port, (int)window.x, (int)window.y, (int)window.width, (int)window.height);
- break;
-#endif /* NP_NO_QUICKDRAW */
-
- case NPDrawingModelCoreGraphics:
- LOG(Plugins, "NPP_SetWindow (CoreGraphics): %d, window=%p, context=%p, window.x:%d window.y:%d window.width:%d window.height:%d",
- npErr, nPort.cgPort.window, nPort.cgPort.context, (int)window.x, (int)window.y, (int)window.width, (int)window.height);
- break;
-
- default:
- ASSERT_NOT_REACHED();
- break;
- }
-#endif /* !defined(NDEBUG) */
-
- lastSetWindow = window;
- lastSetPort = nPort;
- }
-}
-
-- (void)removeTrackingRect
-{
- if (trackingTag) {
- [self removeTrackingRect:trackingTag];
- trackingTag = 0;
-
- // Do the following after setting trackingTag to 0 so we don't re-enter.
-
- // Balance the retain in resetTrackingRect. Use autorelease in case we hold
- // the last reference to the window during tear-down, to avoid crashing AppKit.
- [[self window] autorelease];
- }
-}
-
-- (void)resetTrackingRect
-{
- [self removeTrackingRect];
- if (isStarted) {
- // Retain the window so that removeTrackingRect can work after the window is closed.
- [[self window] retain];
- trackingTag = [self addTrackingRect:[self bounds] owner:self userData:nil assumeInside:NO];
- }
-}
-
-+ (void)setCurrentPluginView:(WebBaseNetscapePluginView *)view
-{
- currentPluginView = view;
-}
-
-+ (WebBaseNetscapePluginView *)currentPluginView
-{
- return currentPluginView;
-}
-
-- (BOOL)canStart
-{
- return YES;
-}
-
-- (void)didStart
-{
- if (_loadManually) {
- [self _redeliverStream];
+ if (_hasFocus == flag)
return;
- }
- // If the OBJECT/EMBED tag has no SRC, the URL is passed to us as "".
- // Check for this and don't start a load in this case.
- if (sourceURL != nil && ![sourceURL _web_isEmpty]) {
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:sourceURL];
- [request _web_setHTTPReferrer:core([self webFrame])->loader()->outgoingReferrer()];
- [self loadRequest:request inTarget:nil withNotifyData:nil sendNotification:NO];
- }
+ _hasFocus = flag;
+
+ [self focusChanged];
}
- (void)addWindowObservers
{
ASSERT([self window]);
-
+
NSWindow *theWindow = [self window];
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
@@ -1156,106 +306,42 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
[notificationCenter removeObserver:self name:LoginWindowDidSwitchToUserNotification object:nil];
}
-- (BOOL)start
+- (void)start
{
ASSERT([self currentWindow]);
- if (isStarted)
- return YES;
-
- if (![self canStart])
- return NO;
+ if (_isStarted)
+ return;
ASSERT([self webView]);
if (![[[self webView] preferences] arePlugInsEnabled])
- return NO;
-
- // Open the plug-in package so it remains loaded while our plugin uses it
- [pluginPackage open];
-
- // Initialize drawingModel to an invalid value so that we can detect when the plugin does not specify a drawingModel
- drawingModel = (NPDrawingModel)-1;
-
- // Initialize eventModel to an invalid value so that we can detect when the plugin does not specify an event model.
- eventModel = (NPEventModel)-1;
-
- // Plug-ins are "windowed" by default. On MacOS, windowed plug-ins share the same window and graphics port as the main
- // browser window. Windowless plug-ins are rendered off-screen, then copied into the main browser window.
- window.type = NPWindowTypeWindow;
-
- NPError npErr = [self _createPlugin];
- if (npErr != NPERR_NO_ERROR) {
- LOG_ERROR("NPP_New failed with error: %d", npErr);
- [self _destroyPlugin];
- [pluginPackage close];
- return NO;
- }
+ return;
+
+ Frame* frame = core([self webFrame]);
+ if (!frame)
+ return;
+ Page* page = frame->page();
+ if (!page)
+ return;
- if (drawingModel == (NPDrawingModel)-1) {
-#ifndef NP_NO_QUICKDRAW
- // Default to QuickDraw if the plugin did not specify a drawing model.
- drawingModel = NPDrawingModelQuickDraw;
-#else
- // QuickDraw is not available, so we can't default to it. Instead, default to CoreGraphics.
- drawingModel = NPDrawingModelCoreGraphics;
-#endif
- }
-
- if (eventModel == (NPEventModel)-1) {
- // If the plug-in did not specify a drawing model we default to Carbon when it is available.
-#ifndef NP_NO_CARBON
- eventModel = NPEventModelCarbon;
-#else
- eventModel = NPEventModelCocoa;
-#endif // NP_NO_CARBON
- }
+ bool wasDeferring = page->defersLoading();
+ if (!wasDeferring)
+ page->setDefersLoading(true);
-#ifndef NP_NO_CARBON
- if (eventModel == NPEventModelCocoa && isDrawingModelQuickDraw(drawingModel)) {
- LOG(Plugins, "Plugin can't use use Cocoa event model with QuickDraw drawing model: %@", pluginPackage);
- [self _destroyPlugin];
- [pluginPackage close];
-
- return NO;
- }
-#endif // NP_NO_CARBON
+ BOOL result = [self createPlugin];
-#ifndef BUILDING_ON_TIGER
- if (drawingModel == NPDrawingModelCoreAnimation) {
- void *value = 0;
- if (NPP_GetValue(plugin, NPPVpluginCoreAnimationLayer, &value) == NPERR_NO_ERROR && value) {
- _layer = (CALayer *)value;
- [self setWantsLayer:YES];
- [self setLayer:_layer];
- LOG(Plugins, "%@ is using Core Animation drawing model with layer %@", pluginPackage, _layer);
- }
+ if (!wasDeferring)
+ page->setDefersLoading(false);
- ASSERT(_layer);
- }
-#endif
+ if (!result)
+ return;
- // Create the event handler
- eventHandler = WebNetscapePluginEventHandler::create(self);
+ _isStarted = YES;
+ [[self webView] addPluginInstanceView:self];
- // Get the text input vtable
- if (eventModel == NPEventModelCocoa) {
- [self willCallPlugInFunction];
- {
- JSC::JSLock::DropAllLocks dropAllLocks(false);
- NPPluginTextInputFuncs *value;
- if (NPP_GetValue(plugin, NPPVpluginTextInputFuncs, &value) == NPERR_NO_ERROR && value)
- textInputFuncs = value;
- }
- [self didCallPlugInFunction];
- }
+ [self updateAndSetWindow];
- isStarted = YES;
- [[self webView] addPluginInstanceView:self];
-
- if (drawingModel == NPDrawingModelCoreGraphics || isDrawingModelQuickDraw(drawingModel))
- [self updateAndSetWindow];
-
if ([self window]) {
[self addWindowObservers];
if ([[self window] isKeyWindow]) {
@@ -1263,353 +349,37 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
}
[self restartTimers];
}
-
- [self resetTrackingRect];
- [self didStart];
+ [self resetTrackingRect];
- return YES;
+ [self loadStream];
}
- (void)stop
{
- // If we're already calling a plug-in function, do not call NPP_Destroy(). The plug-in function we are calling
- // may assume that its instance->pdata, or other memory freed by NPP_Destroy(), is valid and unchanged until said
- // plugin-function returns.
- // See <rdar://problem/4480737>.
- if (pluginFunctionCallDepth > 0) {
- shouldStopSoon = YES;
+ if (![self shouldStop])
return;
- }
[self removeTrackingRect];
-
- if (!isStarted)
+
+ if (!_isStarted)
return;
- isStarted = NO;
+ _isStarted = NO;
[[self webView] removePluginInstanceView:self];
-
- // To stop active streams it's necessary to invoke stop() on a copy
- // of streams. This is because calling WebNetscapePluginStream::stop() also has the side effect
- // of removing a stream from this hash set.
- Vector<RefPtr<WebNetscapePluginStream> > streamsCopy;
- copyToVector(streams, streamsCopy);
- for (size_t i = 0; i < streamsCopy.size(); i++)
- streamsCopy[i]->stop();
-
// Stop the timers
[self stopTimers];
// Stop notifications and callbacks.
[self removeWindowObservers];
- [[pendingFrameLoads allKeys] makeObjectsPerformSelector:@selector(_setInternalLoadDelegate:) withObject:nil];
- [NSObject cancelPreviousPerformRequestsWithTarget:self];
-
- // Setting the window type to 0 ensures that NPP_SetWindow will be called if the plug-in is restarted.
- lastSetWindow.type = (NPWindowType)0;
-
- [self _destroyPlugin];
- [pluginPackage close];
-
- delete eventHandler;
- eventHandler = 0;
-
- textInputFuncs = 0;
-}
-
-- (BOOL)isStarted
-{
- return isStarted;
-}
-
-- (NPEventModel)eventModel
-{
- return eventModel;
-}
-
-- (WebDataSource *)dataSource
-{
- WebFrame *webFrame = kit(core(element)->document()->frame());
- return [webFrame _dataSource];
-}
-
-- (WebFrame *)webFrame
-{
- return [[self dataSource] webFrame];
-}
-
-- (WebView *)webView
-{
- return [[self webFrame] webView];
-}
-
-- (NSWindow *)currentWindow
-{
- return [self window] ? [self window] : [[self webView] hostWindow];
-}
-
-- (NPP)plugin
-{
- return plugin;
-}
-
-- (WebNetscapePluginPackage *)pluginPackage
-{
- return pluginPackage;
-}
-
-- (void)setPluginPackage:(WebNetscapePluginPackage *)thePluginPackage;
-{
- [thePluginPackage retain];
- [pluginPackage release];
- pluginPackage = thePluginPackage;
-
- NPP_New = [pluginPackage NPP_New];
- NPP_Destroy = [pluginPackage NPP_Destroy];
- NPP_SetWindow = [pluginPackage NPP_SetWindow];
- NPP_NewStream = [pluginPackage NPP_NewStream];
- NPP_WriteReady = [pluginPackage NPP_WriteReady];
- NPP_Write = [pluginPackage NPP_Write];
- NPP_StreamAsFile = [pluginPackage NPP_StreamAsFile];
- NPP_DestroyStream = [pluginPackage NPP_DestroyStream];
- NPP_HandleEvent = [pluginPackage NPP_HandleEvent];
- NPP_URLNotify = [pluginPackage NPP_URLNotify];
- NPP_GetValue = [pluginPackage NPP_GetValue];
- NPP_SetValue = [pluginPackage NPP_SetValue];
- NPP_Print = [pluginPackage NPP_Print];
-}
-
-- (void)setMIMEType:(NSString *)theMIMEType
-{
- NSString *type = [theMIMEType copy];
- [MIMEType release];
- MIMEType = type;
-}
-
-- (void)setBaseURL:(NSURL *)theBaseURL
-{
- [theBaseURL retain];
- [baseURL release];
- baseURL = theBaseURL;
-}
-
-- (void)setAttributeKeys:(NSArray *)keys andValues:(NSArray *)values;
-{
- ASSERT([keys count] == [values count]);
-
- // Convert the attributes to 2 C string arrays.
- // These arrays are passed to NPP_New, but the strings need to be
- // modifiable and live the entire life of the plugin.
-
- // The Java plug-in requires the first argument to be the base URL
- if ([MIMEType isEqualToString:@"application/x-java-applet"]) {
- cAttributes = (char **)malloc(([keys count] + 1) * sizeof(char *));
- cValues = (char **)malloc(([values count] + 1) * sizeof(char *));
- cAttributes[0] = strdup("DOCBASE");
- cValues[0] = strdup([baseURL _web_URLCString]);
- argsCount++;
- } else {
- cAttributes = (char **)malloc([keys count] * sizeof(char *));
- cValues = (char **)malloc([values count] * sizeof(char *));
- }
-
- BOOL isWMP = [[[pluginPackage bundle] bundleIdentifier] isEqualToString:@"com.microsoft.WMP.defaultplugin"];
-
- unsigned i;
- unsigned count = [keys count];
- for (i = 0; i < count; i++) {
- NSString *key = [keys objectAtIndex:i];
- NSString *value = [values objectAtIndex:i];
- if ([key _webkit_isCaseInsensitiveEqualToString:@"height"]) {
- specifiedHeight = [value intValue];
- } else if ([key _webkit_isCaseInsensitiveEqualToString:@"width"]) {
- specifiedWidth = [value intValue];
- }
- // Avoid Window Media Player crash when these attributes are present.
- if (isWMP && ([key _webkit_isCaseInsensitiveEqualToString:@"SAMIStyle"] || [key _webkit_isCaseInsensitiveEqualToString:@"SAMILang"])) {
- continue;
- }
- cAttributes[argsCount] = strdup([key UTF8String]);
- cValues[argsCount] = strdup([value UTF8String]);
- LOG(Plugins, "%@ = %@", key, value);
- argsCount++;
- }
-}
-
-- (void)setMode:(int)theMode
-{
- mode = theMode;
-}
-
-#pragma mark NSVIEW
-
-- (id)initWithFrame:(NSRect)frame
- pluginPackage:(WebNetscapePluginPackage *)thePluginPackage
- URL:(NSURL *)theURL
- baseURL:(NSURL *)theBaseURL
- MIMEType:(NSString *)MIME
- attributeKeys:(NSArray *)keys
- attributeValues:(NSArray *)values
- loadManually:(BOOL)loadManually
- DOMElement:(DOMElement *)anElement
-{
- [super initWithFrame:frame];
-
- pendingFrameLoads = [[NSMutableDictionary alloc] init];
-
- // load the plug-in if it is not already loaded
- if (![thePluginPackage load]) {
- [self release];
- return nil;
- }
- [self setPluginPackage:thePluginPackage];
-
- element = [anElement retain];
- sourceURL = [theURL retain];
-
- [self setMIMEType:MIME];
- [self setBaseURL:theBaseURL];
- [self setAttributeKeys:keys andValues:values];
- if (loadManually)
- [self setMode:NP_FULL];
- else
- [self setMode:NP_EMBED];
-
- _loadManually = loadManually;
- return self;
-}
-
-- (id)initWithFrame:(NSRect)frame
-{
- ASSERT_NOT_REACHED();
- return nil;
-}
-
-- (void)fini
-{
-#ifndef NP_NO_QUICKDRAW
- if (offscreenGWorld)
- DisposeGWorld(offscreenGWorld);
-#endif
-
- unsigned i;
- for (i = 0; i < argsCount; i++) {
- free(cAttributes[i]);
- free(cValues[i]);
- }
- free(cAttributes);
- free(cValues);
-
- ASSERT(!eventHandler);
-
- if (timers) {
- deleteAllValues(*timers);
- delete timers;
- }
-}
-
-- (void)disconnectStream:(WebNetscapePluginStream*)stream
-{
- streams.remove(stream);
-}
-
-- (void)dealloc
-{
- ASSERT(!isStarted);
-
- [sourceURL release];
- [_error release];
- [pluginPackage release];
- [MIMEType release];
- [baseURL release];
- [pendingFrameLoads release];
- [element release];
-
- ASSERT(!plugin);
-
- [self fini];
-
- [super dealloc];
-}
-
-- (void)finalize
-{
- ASSERT_MAIN_THREAD();
- ASSERT(!isStarted);
-
- [self fini];
-
- [super finalize];
-}
-
-- (void)drawRect:(NSRect)rect
-{
- if (drawingModel == NPDrawingModelCoreAnimation)
- return;
-
- if (!isStarted)
- return;
-
- if ([NSGraphicsContext currentContextDrawingToScreen])
- [self sendDrawRectEvent:rect];
- else {
- NSBitmapImageRep *printedPluginBitmap = [self _printedPluginBitmap];
- if (printedPluginBitmap) {
- // Flip the bitmap before drawing because the QuickDraw port is flipped relative
- // to this view.
- CGContextRef cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
- CGContextSaveGState(cgContext);
- NSRect bounds = [self bounds];
- CGContextTranslateCTM(cgContext, 0.0f, NSHeight(bounds));
- CGContextScaleCTM(cgContext, 1.0f, -1.0f);
- [printedPluginBitmap drawInRect:bounds];
- CGContextRestoreGState(cgContext);
- }
- }
-}
-
-- (BOOL)isFlipped
-{
- return YES;
-}
-
-- (void)renewGState
-{
- [super renewGState];
-
- // -renewGState is called whenever the view's geometry changes. It's a little hacky to override this method, but
- // much safer than walking up the view hierarchy and observing frame/bounds changed notifications, since you don't
- // have to track subsequent changes to the view hierarchy and add/remove notification observers.
- // NSOpenGLView uses the exact same technique to reshape its OpenGL surface.
- [self _viewHasMoved];
-}
-
--(void)tellQuickTimeToChill
-{
-#ifndef NP_NO_QUICKDRAW
- ASSERT(isDrawingModelQuickDraw(drawingModel));
-
- // Make a call to the secret QuickDraw API that makes QuickTime calm down.
- WindowRef windowRef = (WindowRef)[[self window] windowRef];
- if (!windowRef) {
- return;
- }
- CGrafPtr port = GetWindowPort(windowRef);
- ::Rect bounds;
- GetPortBounds(port, &bounds);
- WKCallDrawingNotification(port, &bounds);
-#endif /* NP_NO_QUICKDRAW */
+ [self destroyPlugin];
}
- (void)viewWillMoveToWindow:(NSWindow *)newWindow
{
- if (isDrawingModelQuickDraw(drawingModel))
- [self tellQuickTimeToChill];
-
// We must remove the tracking rect before we move to the new window.
// Once we move to the new window, it will be too late.
[self removeTrackingRect];
@@ -1617,7 +387,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
// Workaround for: <rdar://problem/3822871> resignFirstResponder is not sent to first responder view when it is removed from the window
[self setHasFocus:NO];
-
+
if (!newWindow) {
if ([[self webView] hostWindow]) {
// View will be moved out of the actual window but it still has a host window.
@@ -1625,7 +395,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
} else {
// View will have no associated windows.
[self stop];
-
+
// Stop observing WebPreferencesChangedNotification -- we only need to observe this when installed in the view hierarchy.
// When not in the view hierarchy, -viewWillMoveToWindow: and -viewDidMoveToWindow will start/stop the plugin as needed.
[[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:nil];
@@ -1655,10 +425,10 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
// While in the view hierarchy, observe WebPreferencesChangedNotification so that we can start/stop depending
// on whether plugins are enabled.
[[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(preferencesHaveChanged:)
- name:WebPreferencesChangedNotification
- object:nil];
-
+ selector:@selector(preferencesHaveChanged:)
+ name:WebPreferencesChangedNotification
+ object:nil];
+
// View moved to an actual window. Start it if not already started.
[self start];
[self restartTimers];
@@ -1676,7 +446,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
if (!hostWindow && ![self window]) {
// View will have no associated windows.
[self stop];
-
+
// Remove WebPreferencesChangedNotification observer -- we will observe once again when we move back into the window
[[NSNotificationCenter defaultCenter] removeObserver:self name:WebPreferencesChangedNotification object:nil];
}
@@ -1702,9 +472,6 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
[self sendActivateEvent:YES];
[self setNeedsDisplay:YES];
[self restartTimers];
-#ifndef NP_NO_CARBON
- SetUserFocusWindow((WindowRef)[[self window] windowRef]);
-#endif // NP_NO_CARBON
}
- (void)windowResignedKey:(NSNotification *)notification
@@ -1721,7 +488,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
- (void)windowDidDeminiaturize:(NSNotification *)notification
{
- [self stopTimers];
+ [self restartTimers];
}
- (void)loginWindowDidSwitchFromUser:(NSNotification *)notification
@@ -1739,7 +506,7 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
WebPreferences *preferences = [[self webView] preferences];
BOOL arePlugInsEnabled = [preferences arePlugInsEnabled];
- if ([notification object] == preferences && isStarted != arePlugInsEnabled) {
+ if ([notification object] == preferences && _isStarted != arePlugInsEnabled) {
if (arePlugInsEnabled) {
if ([self currentWindow]) {
[self start];
@@ -1751,1198 +518,100 @@ static inline void getNPRect(const NSRect& nr, NPRect& npr)
}
}
-- (NPObject *)createPluginScriptableObject
-{
- if (!NPP_GetValue || ![self isStarted])
- return NULL;
-
- NPObject *value = NULL;
- NPError error;
- [self willCallPlugInFunction];
- {
- JSC::JSLock::DropAllLocks dropAllLocks(false);
- error = NPP_GetValue(plugin, NPPVpluginScriptableNPObject, &value);
- }
- [self didCallPlugInFunction];
- if (error != NPERR_NO_ERROR)
- return NULL;
-
- return value;
-}
-
-- (void)willCallPlugInFunction
-{
- ASSERT(plugin);
-
- // Could try to prevent infinite recursion here, but it's probably not worth the effort.
- pluginFunctionCallDepth++;
-}
-
-- (void)didCallPlugInFunction
-{
- ASSERT(pluginFunctionCallDepth > 0);
- pluginFunctionCallDepth--;
-
- // If -stop was called while we were calling into a plug-in function, and we're no longer
- // inside a plug-in function, stop now.
- if (pluginFunctionCallDepth == 0 && shouldStopSoon) {
- shouldStopSoon = NO;
- [self stop];
- }
-}
-
--(void)pluginView:(NSView *)pluginView receivedResponse:(NSURLResponse *)response
-{
- ASSERT(_loadManually);
- ASSERT(!_manualStream);
-
- _manualStream = WebNetscapePluginStream::create(core([self webFrame])->loader());
-}
-
-- (void)pluginView:(NSView *)pluginView receivedData:(NSData *)data
-{
- ASSERT(_loadManually);
- ASSERT(_manualStream);
-
- _dataLengthReceived += [data length];
-
- if (![self isStarted])
- return;
-
- if (!_manualStream->plugin()) {
-
- _manualStream->setRequestURL([[[self dataSource] request] URL]);
- _manualStream->setPlugin([self plugin]);
- ASSERT(_manualStream->plugin());
-
- _manualStream->startStreamWithResponse([[self dataSource] response]);
- }
-
- if (_manualStream->plugin())
- _manualStream->didReceiveData(0, static_cast<const char *>([data bytes]), [data length]);
-}
-
-- (void)pluginView:(NSView *)pluginView receivedError:(NSError *)error
-{
- ASSERT(_loadManually);
-
- [error retain];
- [_error release];
- _error = error;
-
- if (![self isStarted]) {
- return;
- }
-
- _manualStream->destroyStreamWithError(error);
-}
-
-- (void)pluginViewFinishedLoading:(NSView *)pluginView
-{
- ASSERT(_loadManually);
- ASSERT(_manualStream);
-
- if ([self isStarted])
- _manualStream->didFinishLoading(0);
-}
-
-#pragma mark NSTextInput implementation
-
-- (NSTextInputContext *)inputContext
-{
-#ifndef NP_NO_CARBON
- if (![self isStarted] || eventModel == NPEventModelCarbon)
- return nil;
-#endif
-
- return [super inputContext];
-}
-
-- (BOOL)hasMarkedText
-{
- ASSERT(eventModel == NPEventModelCocoa);
- ASSERT([self isStarted]);
-
- if (textInputFuncs && textInputFuncs->hasMarkedText)
- return textInputFuncs->hasMarkedText(plugin);
-
- return NO;
-}
-
-- (void)insertText:(id)aString
-{
- ASSERT(eventModel == NPEventModelCocoa);
- ASSERT([self isStarted]);
-
- if (textInputFuncs && textInputFuncs->insertText)
- textInputFuncs->insertText(plugin, aString);
-}
-
-- (NSRange)markedRange
-{
- ASSERT(eventModel == NPEventModelCocoa);
- ASSERT([self isStarted]);
-
- if (textInputFuncs && textInputFuncs->markedRange)
- return textInputFuncs->markedRange(plugin);
-
- return NSMakeRange(NSNotFound, 0);
-}
-
-- (NSRange)selectedRange
-{
- ASSERT(eventModel == NPEventModelCocoa);
- ASSERT([self isStarted]);
-
- if (textInputFuncs && textInputFuncs->selectedRange)
- return textInputFuncs->selectedRange(plugin);
-
- return NSMakeRange(NSNotFound, 0);
-}
-
-- (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange
-{
- ASSERT(eventModel == NPEventModelCocoa);
- ASSERT([self isStarted]);
-
- if (textInputFuncs && textInputFuncs->setMarkedText)
- textInputFuncs->setMarkedText(plugin, aString, selRange);
-}
-
-- (void)unmarkText
-{
- ASSERT(eventModel == NPEventModelCocoa);
- ASSERT([self isStarted]);
-
- if (textInputFuncs && textInputFuncs->unmarkText)
- textInputFuncs->unmarkText(plugin);
-}
-
-- (NSArray *)validAttributesForMarkedText
-{
- ASSERT(eventModel == NPEventModelCocoa);
- ASSERT([self isStarted]);
-
- if (textInputFuncs && textInputFuncs->validAttributesForMarkedText)
- return textInputFuncs->validAttributesForMarkedText(plugin);
-
- return [NSArray array];
-}
-
-- (NSAttributedString *)attributedSubstringFromRange:(NSRange)theRange
-{
- ASSERT(eventModel == NPEventModelCocoa);
- ASSERT([self isStarted]);
-
- if (textInputFuncs && textInputFuncs->attributedSubstringFromRange)
- return textInputFuncs->attributedSubstringFromRange(plugin, theRange);
-
- return nil;
-}
-
-- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint
-{
- ASSERT(eventModel == NPEventModelCocoa);
- ASSERT([self isStarted]);
-
- if (textInputFuncs && textInputFuncs->characterIndexForPoint) {
- // Convert the point to window coordinates
- NSPoint point = [[self window] convertScreenToBase:thePoint];
-
- // And view coordinates
- point = [self convertPoint:point fromView:nil];
-
- return textInputFuncs->characterIndexForPoint(plugin, point);
- }
-
- return NSNotFound;
-}
-
-- (void)doCommandBySelector:(SEL)aSelector
-{
- ASSERT(eventModel == NPEventModelCocoa);
- ASSERT([self isStarted]);
-
- if (textInputFuncs && textInputFuncs->doCommandBySelector)
- textInputFuncs->doCommandBySelector(plugin, aSelector);
-}
-
-- (NSRect)firstRectForCharacterRange:(NSRange)theRange
-{
- ASSERT(eventModel == NPEventModelCocoa);
- ASSERT([self isStarted]);
-
- if (textInputFuncs && textInputFuncs->firstRectForCharacterRange) {
- NSRect rect = textInputFuncs->firstRectForCharacterRange(plugin, theRange);
-
- // Convert the rect to window coordinates
- rect = [self convertRect:rect toView:nil];
-
- // Convert the rect location to screen coordinates
- rect.origin = [[self window] convertBaseToScreen:rect.origin];
-
- return rect;
- }
-
- return NSZeroRect;
-}
-
-// test for 10.4 because of <rdar://problem/4243463>
-#ifdef BUILDING_ON_TIGER
-- (long)conversationIdentifier
-{
- return (long)self;
-}
-#else
-- (NSInteger)conversationIdentifier
-{
- return (NSInteger)self;
-}
-#endif
-
-@end
-
-@implementation WebBaseNetscapePluginView (WebNPPCallbacks)
-
-- (NSMutableURLRequest *)requestWithURLCString:(const char *)URLCString
-{
- if (!URLCString)
- return nil;
-
- CFStringRef string = CFStringCreateWithCString(kCFAllocatorDefault, URLCString, kCFStringEncodingISOLatin1);
- ASSERT(string); // All strings should be representable in ISO Latin 1
-
- NSString *URLString = [(NSString *)string _web_stringByStrippingReturnCharacters];
- NSURL *URL = [NSURL _web_URLWithDataAsString:URLString relativeToURL:baseURL];
- CFRelease(string);
- if (!URL)
- return nil;
-
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
- Frame* frame = core([self webFrame]);
- if (!frame)
- return nil;
- [request _web_setHTTPReferrer:frame->loader()->outgoingReferrer()];
- return request;
-}
-
-- (void)evaluateJavaScriptPluginRequest:(WebPluginRequest *)JSPluginRequest
+- (void)renewGState
{
- // FIXME: Is this isStarted check needed here? evaluateJavaScriptPluginRequest should not be called
- // if we are stopped since this method is called after a delay and we call
- // cancelPreviousPerformRequestsWithTarget inside of stop.
- if (!isStarted) {
- return;
- }
-
- NSURL *URL = [[JSPluginRequest request] URL];
- NSString *JSString = [URL _webkit_scriptIfJavaScriptURL];
- ASSERT(JSString);
+ [super renewGState];
- NSString *result = [[self webFrame] _stringByEvaluatingJavaScriptFromString:JSString forceUserGesture:[JSPluginRequest isCurrentEventUserGesture]];
+ // -renewGState is called whenever the view's geometry changes. It's a little hacky to override this method, but
+ // much safer than walking up the view hierarchy and observing frame/bounds changed notifications, since you don't
+ // have to track subsequent changes to the view hierarchy and add/remove notification observers.
+ // NSOpenGLView uses the exact same technique to reshape its OpenGL surface.
- // Don't continue if stringByEvaluatingJavaScriptFromString caused the plug-in to stop.
- if (!isStarted) {
+ // All of the work this method does may safely be skipped if the view is not in a window. When the view
+ // is moved back into a window, everything should be set up correctly.
+ if (![self window])
return;
- }
-
- if ([JSPluginRequest frameName] != nil) {
- // FIXME: If the result is a string, we probably want to put that string into the frame.
- if ([JSPluginRequest sendNotification]) {
- [self willCallPlugInFunction];
- {
- JSC::JSLock::DropAllLocks dropAllLocks(false);
- NPP_URLNotify(plugin, [URL _web_URLCString], NPRES_DONE, [JSPluginRequest notifyData]);
- }
- [self didCallPlugInFunction];
- }
- } else if ([result length] > 0) {
- // Don't call NPP_NewStream and other stream methods if there is no JS result to deliver. This is what Mozilla does.
- NSData *JSData = [result dataUsingEncoding:NSUTF8StringEncoding];
-
- RefPtr<WebNetscapePluginStream> stream = WebNetscapePluginStream::create([NSURLRequest requestWithURL:URL], plugin, [JSPluginRequest sendNotification], [JSPluginRequest notifyData]);
-
- RetainPtr<NSURLResponse> response(AdoptNS, [[NSURLResponse alloc] initWithURL:URL
- MIMEType:@"text/plain"
- expectedContentLength:[JSData length]
- textEncodingName:nil]);
-
- stream->startStreamWithResponse(response.get());
- stream->didReceiveData(0, static_cast<const char*>([JSData bytes]), [JSData length]);
- stream->didFinishLoading(0);
- }
-}
-
-- (void)webFrame:(WebFrame *)webFrame didFinishLoadWithReason:(NPReason)reason
-{
- ASSERT(isStarted);
- WebPluginRequest *pluginRequest = [pendingFrameLoads objectForKey:webFrame];
- ASSERT(pluginRequest != nil);
- ASSERT([pluginRequest sendNotification]);
-
- [self willCallPlugInFunction];
- {
- JSC::JSLock::DropAllLocks dropAllLocks(false);
- NPP_URLNotify(plugin, [[[pluginRequest request] URL] _web_URLCString], reason, [pluginRequest notifyData]);
- }
- [self didCallPlugInFunction];
+ [self updateAndSetWindow];
- [pendingFrameLoads removeObjectForKey:webFrame];
- [webFrame _setInternalLoadDelegate:nil];
-}
-
-- (void)webFrame:(WebFrame *)webFrame didFinishLoadWithError:(NSError *)error
-{
- NPReason reason = NPRES_DONE;
- if (error != nil)
- reason = WebNetscapePluginStream::reasonForError(error);
- [self webFrame:webFrame didFinishLoadWithReason:reason];
-}
-
-- (void)loadPluginRequest:(WebPluginRequest *)pluginRequest
-{
- NSURLRequest *request = [pluginRequest request];
- NSString *frameName = [pluginRequest frameName];
- WebFrame *frame = nil;
-
- NSURL *URL = [request URL];
- NSString *JSString = [URL _webkit_scriptIfJavaScriptURL];
-
- ASSERT(frameName || JSString);
-
- if (frameName) {
- // FIXME - need to get rid of this window creation which
- // bypasses normal targeted link handling
- frame = kit(core([self webFrame])->loader()->findFrameForNavigation(frameName));
- if (frame == nil) {
- WebView *currentWebView = [self webView];
- NSDictionary *features = [[NSDictionary alloc] init];
- WebView *newWebView = [[currentWebView _UIDelegateForwarder] webView:currentWebView
- createWebViewWithRequest:nil
- windowFeatures:features];
- [features release];
-
- if (!newWebView) {
- if ([pluginRequest sendNotification]) {
- [self willCallPlugInFunction];
- {
- JSC::JSLock::DropAllLocks dropAllLocks(false);
- NPP_URLNotify(plugin, [[[pluginRequest request] URL] _web_URLCString], NPERR_GENERIC_ERROR, [pluginRequest notifyData]);
- }
- [self didCallPlugInFunction];
- }
- return;
- }
-
- frame = [newWebView mainFrame];
- core(frame)->tree()->setName(frameName);
- [[newWebView _UIDelegateForwarder] webViewShow:newWebView];
- }
- }
-
- if (JSString) {
- ASSERT(frame == nil || [self webFrame] == frame);
- [self evaluateJavaScriptPluginRequest:pluginRequest];
- } else {
- [frame loadRequest:request];
- if ([pluginRequest sendNotification]) {
- // Check if another plug-in view or even this view is waiting for the frame to load.
- // If it is, tell it that the load was cancelled because it will be anyway.
- WebBaseNetscapePluginView *view = [frame _internalLoadDelegate];
- if (view != nil) {
- ASSERT([view isKindOfClass:[WebBaseNetscapePluginView class]]);
- [view webFrame:frame didFinishLoadWithReason:NPRES_USER_BREAK];
- }
- [pendingFrameLoads _webkit_setObject:pluginRequest forUncopiedKey:frame];
- [frame _setInternalLoadDelegate:self];
- }
- }
-}
-
-- (NPError)loadRequest:(NSMutableURLRequest *)request inTarget:(const char *)cTarget withNotifyData:(void *)notifyData sendNotification:(BOOL)sendNotification
-{
- NSURL *URL = [request URL];
-
- if (!URL)
- return NPERR_INVALID_URL;
-
- // Don't allow requests to be loaded when the document loader is stopping all loaders.
- if ([[self dataSource] _documentLoader]->isStopping())
- return NPERR_GENERIC_ERROR;
-
- NSString *target = nil;
- if (cTarget) {
- // Find the frame given the target string.
- target = [NSString stringWithCString:cTarget encoding:NSISOLatin1StringEncoding];
- }
- WebFrame *frame = [self webFrame];
-
- // don't let a plugin start any loads if it is no longer part of a document that is being
- // displayed unless the loads are in the same frame as the plugin.
- if ([[self dataSource] _documentLoader] != core([self webFrame])->loader()->activeDocumentLoader() &&
- (!cTarget || [frame findFrameNamed:target] != frame)) {
- return NPERR_GENERIC_ERROR;
- }
-
- NSString *JSString = [URL _webkit_scriptIfJavaScriptURL];
- if (JSString != nil) {
- if (![[[self webView] preferences] isJavaScriptEnabled]) {
- // Return NPERR_GENERIC_ERROR if JS is disabled. This is what Mozilla does.
- return NPERR_GENERIC_ERROR;
- } else if (cTarget == NULL && mode == NP_FULL) {
- // Don't allow a JavaScript request from a standalone plug-in that is self-targetted
- // because this can cause the user to be redirected to a blank page (3424039).
- return NPERR_INVALID_PARAM;
- }
- } else {
- if (!FrameLoader::canLoad(URL, String(), core([self webFrame])->document()))
- return NPERR_GENERIC_ERROR;
- }
-
- if (cTarget || JSString) {
- // Make when targetting a frame or evaluating a JS string, perform the request after a delay because we don't
- // want to potentially kill the plug-in inside of its URL request.
-
- if (JSString && target && [frame findFrameNamed:target] != frame) {
- // For security reasons, only allow JS requests to be made on the frame that contains the plug-in.
- return NPERR_INVALID_PARAM;
- }
-
- bool currentEventIsUserGesture = false;
- if (eventHandler)
- currentEventIsUserGesture = eventHandler->currentEventIsUserGesture();
-
- WebPluginRequest *pluginRequest = [[WebPluginRequest alloc] initWithRequest:request
- frameName:target
- notifyData:notifyData
- sendNotification:sendNotification
- didStartFromUserGesture:currentEventIsUserGesture];
- [self performSelector:@selector(loadPluginRequest:) withObject:pluginRequest afterDelay:0];
- [pluginRequest release];
- } else {
- RefPtr<WebNetscapePluginStream> stream = WebNetscapePluginStream::create(request, plugin, sendNotification, notifyData);
-
- streams.add(stream.get());
- stream->start();
- }
-
- return NPERR_NO_ERROR;
-}
-
--(NPError)getURLNotify:(const char *)URLCString target:(const char *)cTarget notifyData:(void *)notifyData
-{
- LOG(Plugins, "NPN_GetURLNotify: %s target: %s", URLCString, cTarget);
-
- NSMutableURLRequest *request = [self requestWithURLCString:URLCString];
- return [self loadRequest:request inTarget:cTarget withNotifyData:notifyData sendNotification:YES];
-}
-
--(NPError)getURL:(const char *)URLCString target:(const char *)cTarget
-{
- LOG(Plugins, "NPN_GetURL: %s target: %s", URLCString, cTarget);
-
- NSMutableURLRequest *request = [self requestWithURLCString:URLCString];
- return [self loadRequest:request inTarget:cTarget withNotifyData:NULL sendNotification:NO];
-}
-
-- (NPError)_postURL:(const char *)URLCString
- target:(const char *)target
- len:(UInt32)len
- buf:(const char *)buf
- file:(NPBool)file
- notifyData:(void *)notifyData
- sendNotification:(BOOL)sendNotification
- allowHeaders:(BOOL)allowHeaders
-{
- if (!URLCString || !len || !buf) {
- return NPERR_INVALID_PARAM;
- }
-
- NSData *postData = nil;
-
- if (file) {
- // If we're posting a file, buf is either a file URL or a path to the file.
- NSString *bufString = (NSString *)CFStringCreateWithCString(kCFAllocatorDefault, buf, kCFStringEncodingWindowsLatin1);
- if (!bufString) {
- return NPERR_INVALID_PARAM;
- }
- NSURL *fileURL = [NSURL _web_URLWithDataAsString:bufString];
- NSString *path;
- if ([fileURL isFileURL]) {
- path = [fileURL path];
- } else {
- path = bufString;
- }
- postData = [NSData dataWithContentsOfFile:[path _webkit_fixedCarbonPOSIXPath]];
- CFRelease(bufString);
- if (!postData) {
- return NPERR_FILE_NOT_FOUND;
- }
- } else {
- postData = [NSData dataWithBytes:buf length:len];
- }
-
- if ([postData length] == 0) {
- return NPERR_INVALID_PARAM;
- }
-
- NSMutableURLRequest *request = [self requestWithURLCString:URLCString];
- [request setHTTPMethod:@"POST"];
-
- if (allowHeaders) {
- if ([postData _web_startsWithBlankLine]) {
- postData = [postData subdataWithRange:NSMakeRange(1, [postData length] - 1)];
- } else {
- NSInteger location = [postData _web_locationAfterFirstBlankLine];
- if (location != NSNotFound) {
- // If the blank line is somewhere in the middle of postData, everything before is the header.
- NSData *headerData = [postData subdataWithRange:NSMakeRange(0, location)];
- NSMutableDictionary *header = [headerData _webkit_parseRFC822HeaderFields];
- unsigned dataLength = [postData length] - location;
-
- // Sometimes plugins like to set Content-Length themselves when they post,
- // but WebFoundation does not like that. So we will remove the header
- // and instead truncate the data to the requested length.
- NSString *contentLength = [header objectForKey:@"Content-Length"];
-
- if (contentLength != nil)
- dataLength = MIN((unsigned)[contentLength intValue], dataLength);
- [header removeObjectForKey:@"Content-Length"];
-
- if ([header count] > 0) {
- [request setAllHTTPHeaderFields:header];
- }
- // Everything after the blank line is the actual content of the POST.
- postData = [postData subdataWithRange:NSMakeRange(location, dataLength)];
-
- }
- }
- if ([postData length] == 0) {
- return NPERR_INVALID_PARAM;
- }
- }
-
- // Plug-ins expect to receive uncached data when doing a POST (3347134).
- [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
- [request setHTTPBody:postData];
-
- return [self loadRequest:request inTarget:target withNotifyData:notifyData sendNotification:sendNotification];
-}
-
-- (NPError)postURLNotify:(const char *)URLCString
- target:(const char *)target
- len:(UInt32)len
- buf:(const char *)buf
- file:(NPBool)file
- notifyData:(void *)notifyData
-{
- LOG(Plugins, "NPN_PostURLNotify: %s", URLCString);
- return [self _postURL:URLCString target:target len:len buf:buf file:file notifyData:notifyData sendNotification:YES allowHeaders:YES];
-}
-
--(NPError)postURL:(const char *)URLCString
- target:(const char *)target
- len:(UInt32)len
- buf:(const char *)buf
- file:(NPBool)file
-{
- LOG(Plugins, "NPN_PostURL: %s", URLCString);
- // As documented, only allow headers to be specified via NPP_PostURL when using a file.
- return [self _postURL:URLCString target:target len:len buf:buf file:file notifyData:NULL sendNotification:NO allowHeaders:file];
-}
-
--(NPError)newStream:(NPMIMEType)type target:(const char *)target stream:(NPStream**)stream
-{
- LOG(Plugins, "NPN_NewStream");
- return NPERR_GENERIC_ERROR;
-}
-
--(NPError)write:(NPStream*)stream len:(SInt32)len buffer:(void *)buffer
-{
- LOG(Plugins, "NPN_Write");
- return NPERR_GENERIC_ERROR;
-}
-
--(NPError)destroyStream:(NPStream*)stream reason:(NPReason)reason
-{
- LOG(Plugins, "NPN_DestroyStream");
- // This function does a sanity check to ensure that the NPStream provided actually
- // belongs to the plug-in that provided it, which fixes a crash in the DivX
- // plug-in: <rdar://problem/5093862> | http://bugs.webkit.org/show_bug.cgi?id=13203
- if (!stream || WebNetscapePluginStream::ownerForStream(stream) != plugin) {
- LOG(Plugins, "Invalid NPStream passed to NPN_DestroyStream: %p", stream);
- return NPERR_INVALID_INSTANCE_ERROR;
- }
-
- WebNetscapePluginStream* browserStream = static_cast<WebNetscapePluginStream*>(stream->ndata);
- browserStream->cancelLoadAndDestroyStreamWithError(browserStream->errorForReason(reason));
-
- return NPERR_NO_ERROR;
-}
-
-- (const char *)userAgent
-{
- return [[[self webView] userAgentForURL:baseURL] UTF8String];
-}
-
--(void)status:(const char *)message
-{
- if (!message) {
- LOG_ERROR("NPN_Status passed a NULL status message");
- return;
- }
-
- CFStringRef status = CFStringCreateWithCString(NULL, message, kCFStringEncodingUTF8);
- if (!status) {
- LOG_ERROR("NPN_Status: the message was not valid UTF-8");
- return;
- }
+ [self resetTrackingRect];
- LOG(Plugins, "NPN_Status: %@", status);
- WebView *wv = [self webView];
- [[wv _UIDelegateForwarder] webView:wv setStatusText:(NSString *)status];
- CFRelease(status);
-}
-
--(void)invalidateRect:(NPRect *)invalidRect
-{
- LOG(Plugins, "NPN_InvalidateRect");
- [self setNeedsDisplayInRect:NSMakeRect(invalidRect->left, invalidRect->top,
- (float)invalidRect->right - invalidRect->left, (float)invalidRect->bottom - invalidRect->top)];
+ // Check to see if the plugin view is completely obscured (scrolled out of view, for example).
+ // For performance reasons, we send null events at a lower rate to plugins which are obscured.
+ BOOL oldIsObscured = _isCompletelyObscured;
+ _isCompletelyObscured = NSIsEmptyRect([self visibleRect]);
+ if (_isCompletelyObscured != oldIsObscured)
+ [self restartTimers];
}
--(BOOL)isOpaque
+- (BOOL)becomeFirstResponder
{
+ [self setHasFocus:YES];
return YES;
}
-- (void)invalidateRegion:(NPRegion)invalidRegion
-{
- LOG(Plugins, "NPN_InvalidateRegion");
- NSRect invalidRect = NSZeroRect;
- switch (drawingModel) {
-#ifndef NP_NO_QUICKDRAW
- case NPDrawingModelQuickDraw:
- {
- ::Rect qdRect;
- GetRegionBounds((NPQDRegion)invalidRegion, &qdRect);
- invalidRect = NSMakeRect(qdRect.left, qdRect.top, qdRect.right - qdRect.left, qdRect.bottom - qdRect.top);
- }
- break;
-#endif /* NP_NO_QUICKDRAW */
-
- case NPDrawingModelCoreGraphics:
- {
- CGRect cgRect = CGPathGetBoundingBox((NPCGRegion)invalidRegion);
- invalidRect = *(NSRect*)&cgRect;
- break;
- }
- default:
- ASSERT_NOT_REACHED();
- break;
- }
-
- [self setNeedsDisplayInRect:invalidRect];
-}
-
--(void)forceRedraw
-{
- LOG(Plugins, "forceRedraw");
- [self setNeedsDisplay:YES];
- [[self window] displayIfNeeded];
-}
-
-static NPBrowserTextInputFuncs *browserTextInputFuncs()
-{
- static NPBrowserTextInputFuncs inputFuncs = {
- 0,
- sizeof(NPBrowserTextInputFuncs),
- NPN_MarkedTextAbandoned,
- NPN_MarkedTextSelectionChanged
- };
-
- return &inputFuncs;
-}
-
-- (NPError)getVariable:(NPNVariable)variable value:(void *)value
-{
- switch (variable) {
- case NPNVWindowNPObject:
- {
- Frame* frame = core([self webFrame]);
- NPObject* windowScriptObject = frame ? frame->script()->windowScriptNPObject() : 0;
-
- // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess>
- if (windowScriptObject)
- _NPN_RetainObject(windowScriptObject);
-
- void **v = (void **)value;
- *v = windowScriptObject;
-
- return NPERR_NO_ERROR;
- }
-
- case NPNVPluginElementNPObject:
- {
- if (!element)
- return NPERR_GENERIC_ERROR;
-
- NPObject *plugInScriptObject = (NPObject *)[element _NPObject];
-
- // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess>
- if (plugInScriptObject)
- _NPN_RetainObject(plugInScriptObject);
-
- void **v = (void **)value;
- *v = plugInScriptObject;
-
- return NPERR_NO_ERROR;
- }
-
- case NPNVpluginDrawingModel:
- {
- *(NPDrawingModel *)value = drawingModel;
- return NPERR_NO_ERROR;
- }
-
-#ifndef NP_NO_QUICKDRAW
- case NPNVsupportsQuickDrawBool:
- {
- *(NPBool *)value = TRUE;
- return NPERR_NO_ERROR;
- }
-#endif /* NP_NO_QUICKDRAW */
-
- case NPNVsupportsCoreGraphicsBool:
- {
- *(NPBool *)value = TRUE;
- return NPERR_NO_ERROR;
- }
-
- case NPNVsupportsOpenGLBool:
- {
- *(NPBool *)value = FALSE;
- return NPERR_NO_ERROR;
- }
-
- case NPNVsupportsCoreAnimationBool:
- {
-#ifdef BUILDING_ON_TIGER
- *(NPBool *)value = FALSE;
-#else
- *(NPBool *)value = TRUE;
-#endif
- return NPERR_NO_ERROR;
- }
-
-#ifndef NP_NO_CARBON
- case NPNVsupportsCarbonBool:
- {
- *(NPBool *)value = TRUE;
- return NPERR_NO_ERROR;
- }
-#endif /* NP_NO_CARBON */
-
- case NPNVsupportsCocoaBool:
- {
- *(NPBool *)value = TRUE;
- return NPERR_NO_ERROR;
- }
-
- case NPNVbrowserTextInputFuncs:
- {
- if (eventModel == NPEventModelCocoa) {
- *(NPBrowserTextInputFuncs **)value = browserTextInputFuncs();
- return NPERR_NO_ERROR;
- }
- }
- default:
- break;
- }
-
- return NPERR_GENERIC_ERROR;
-}
-
-- (NPError)setVariable:(NPPVariable)variable value:(void *)value
-{
- switch (variable) {
- case NPPVpluginWindowBool:
- {
- NPWindowType newWindowType = (value ? NPWindowTypeWindow : NPWindowTypeDrawable);
-
- // Redisplay if window type is changing (some drawing models can only have their windows set while updating).
- if (newWindowType != window.type)
- [self setNeedsDisplay:YES];
-
- window.type = newWindowType;
- }
-
- case NPPVpluginTransparentBool:
- {
- BOOL newTransparent = (value != 0);
-
- // Redisplay if transparency is changing
- if (isTransparent != newTransparent)
- [self setNeedsDisplay:YES];
-
- isTransparent = newTransparent;
-
- return NPERR_NO_ERROR;
- }
-
- case NPPVpluginDrawingModel:
- {
- // Can only set drawing model inside NPP_New()
- if (self != [[self class] currentPluginView])
- return NPERR_GENERIC_ERROR;
-
- // Check for valid, supported drawing model
- NPDrawingModel newDrawingModel = (NPDrawingModel)(uintptr_t)value;
- switch (newDrawingModel) {
- // Supported drawing models:
-#ifndef NP_NO_QUICKDRAW
- case NPDrawingModelQuickDraw:
-#endif
- case NPDrawingModelCoreGraphics:
- drawingModel = newDrawingModel;
- return NPERR_NO_ERROR;
-
- case NPDrawingModelCoreAnimation:
- drawingModel = newDrawingModel;
- return NPERR_NO_ERROR;
-
-
- // Unsupported (or unknown) drawing models:
- default:
- LOG(Plugins, "Plugin %@ uses unsupported drawing model: %d", pluginPackage, drawingModel);
- return NPERR_GENERIC_ERROR;
- }
- }
-
- case NPPVpluginEventModel:
- {
- // Can only set event model inside NPP_New()
- if (self != [[self class] currentPluginView])
- return NPERR_GENERIC_ERROR;
-
- // Check for valid, supported event model
- NPEventModel newEventModel = (NPEventModel)(uintptr_t)value;
- switch (newEventModel) {
- // Supported event models:
-#ifndef NP_NO_CARBON
- case NPEventModelCarbon:
-#endif
- case NPEventModelCocoa:
- eventModel = newEventModel;
- return NPERR_NO_ERROR;
-
- // Unsupported (or unknown) event models:
- default:
- LOG(Plugins, "Plugin %@ uses unsupported event model: %d", pluginPackage, eventModel);
- return NPERR_GENERIC_ERROR;
- }
- }
-
- default:
- return NPERR_GENERIC_ERROR;
- }
-}
-
-- (uint32)scheduleTimerWithInterval:(uint32)interval repeat:(NPBool)repeat timerFunc:(void (*)(NPP npp, uint32 timerID))timerFunc
-{
- if (!timerFunc)
- return 0;
-
- if (!timers)
- timers = new HashMap<uint32, PluginTimer*>;
-
- uint32 timerID = ++currentTimerID;
-
- PluginTimer* timer = new PluginTimer(plugin, timerID, interval, repeat, timerFunc);
- timers->set(timerID, timer);
-
- if (shouldFireTimers)
- timer->start(isCompletelyObscured);
-
- return 0;
-}
-
-- (void)unscheduleTimer:(uint32)timerID
-{
- if (!timers)
- return;
-
- if (PluginTimer* timer = timers->take(timerID))
- delete timer;
-}
-
-- (NPError)popUpContextMenu:(NPMenu *)menu
+- (BOOL)resignFirstResponder
{
- NSEvent *currentEvent = [NSApp currentEvent];
-
- // NPN_PopUpContextMenu must be called from within the plug-in's NPP_HandleEvent.
- if (!currentEvent)
- return NPERR_GENERIC_ERROR;
-
- [NSMenu popUpContextMenu:(NSMenu *)menu withEvent:currentEvent forView:self];
- return NPERR_NO_ERROR;
+ [self setHasFocus:NO];
+ return YES;
}
-@end
-
-@implementation WebPluginRequest
-
-- (id)initWithRequest:(NSURLRequest *)request frameName:(NSString *)frameName notifyData:(void *)notifyData sendNotification:(BOOL)sendNotification didStartFromUserGesture:(BOOL)currentEventIsUserGesture
+- (WebDataSource *)dataSource
{
- [super init];
- _didStartFromUserGesture = currentEventIsUserGesture;
- _request = [request retain];
- _frameName = [frameName retain];
- _notifyData = notifyData;
- _sendNotification = sendNotification;
- return self;
+ WebFrame *webFrame = kit(core(_element.get())->document()->frame());
+ return [webFrame _dataSource];
}
-- (void)dealloc
+- (WebFrame *)webFrame
{
- [_request release];
- [_frameName release];
- [super dealloc];
+ return [[self dataSource] webFrame];
}
-- (NSURLRequest *)request
+- (WebView *)webView
{
- return _request;
+ return [[self webFrame] webView];
}
-- (NSString *)frameName
+- (NSWindow *)currentWindow
{
- return _frameName;
+ return [self window] ? [self window] : [[self webView] hostWindow];
}
-- (BOOL)isCurrentEventUserGesture
-{
- return _didStartFromUserGesture;
-}
+// We want to treat these as regular keyboard events.
-- (BOOL)sendNotification
+- (void)cut:(id)sender
{
- return _sendNotification;
+ [self keyDown:[NSApp currentEvent]];
}
-- (void *)notifyData
+- (void)copy:(id)sender
{
- return _notifyData;
+ [self keyDown:[NSApp currentEvent]];
}
-@end
-
-@implementation WebBaseNetscapePluginView (Internal)
-
-- (NPError)_createPlugin
-{
- plugin = (NPP)calloc(1, sizeof(NPP_t));
- plugin->ndata = self;
-
- ASSERT(NPP_New);
-
- // NPN_New(), which creates the plug-in instance, should never be called while calling a plug-in function for that instance.
- ASSERT(pluginFunctionCallDepth == 0);
-
- Frame* frame = core([self webFrame]);
- if (!frame)
- return NPERR_GENERIC_ERROR;
- Page* page = frame->page();
- if (!page)
- return NPERR_GENERIC_ERROR;
-
- bool wasDeferring = page->defersLoading();
- if (!wasDeferring)
- page->setDefersLoading(true);
-
- PluginMainThreadScheduler::scheduler().registerPlugin(plugin);
-
- [[self class] setCurrentPluginView:self];
- NPError npErr = NPP_New((char *)[MIMEType cString], plugin, mode, argsCount, cAttributes, cValues, NULL);
- [[self class] setCurrentPluginView:nil];
-
- if (!wasDeferring)
- page->setDefersLoading(false);
-
- LOG(Plugins, "NPP_New: %d", npErr);
- return npErr;
-}
-
-- (void)_destroyPlugin
+- (void)paste:(id)sender
{
- PluginMainThreadScheduler::scheduler().unregisterPlugin(plugin);
-
- NPError npErr;
- npErr = NPP_Destroy(plugin, NULL);
- LOG(Plugins, "NPP_Destroy: %d", npErr);
-
- if (Frame* frame = core([self webFrame]))
- frame->script()->cleanupScriptObjectsForPlugin(self);
-
- free(plugin);
- plugin = NULL;
+ [self keyDown:[NSApp currentEvent]];
}
-- (void)_viewHasMoved
+- (void)selectAll:(id)sender
{
- // All of the work this method does may safely be skipped if the view is not in a window. When the view
- // is moved back into a window, everything should be set up correctly.
- if (![self window])
- return;
-
- if (isDrawingModelQuickDraw(drawingModel))
- [self tellQuickTimeToChill];
-
- if (drawingModel == NPDrawingModelCoreGraphics || isDrawingModelQuickDraw(drawingModel))
- [self updateAndSetWindow];
-
- [self resetTrackingRect];
-
- // Check to see if the plugin view is completely obscured (scrolled out of view, for example).
- // For performance reasons, we send null events at a lower rate to plugins which are obscured.
- BOOL oldIsObscured = isCompletelyObscured;
- isCompletelyObscured = NSIsEmptyRect([self visibleRect]);
- if (isCompletelyObscured != oldIsObscured)
- [self restartTimers];
+ [self keyDown:[NSApp currentEvent]];
}
-- (NSBitmapImageRep *)_printedPluginBitmap
+// AppKit doesn't call mouseDown or mouseUp on right-click. Simulate control-click
+// mouseDown and mouseUp so plug-ins get the right-click event as they do in Carbon (3125743).
+- (void)rightMouseDown:(NSEvent *)theEvent
{
-#ifdef NP_NO_QUICKDRAW
- return nil;
-#else
- // Cannot print plugins that do not implement NPP_Print
- if (!NPP_Print)
- return nil;
-
- // This NSBitmapImageRep will share its bitmap buffer with a GWorld that the plugin will draw into.
- // The bitmap is created in 32-bits-per-pixel ARGB format, which is the default GWorld pixel format.
- NSBitmapImageRep *bitmap = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
- pixelsWide:window.width
- pixelsHigh:window.height
- bitsPerSample:8
- samplesPerPixel:4
- hasAlpha:YES
- isPlanar:NO
- colorSpaceName:NSDeviceRGBColorSpace
- bitmapFormat:NSAlphaFirstBitmapFormat
- bytesPerRow:0
- bitsPerPixel:0] autorelease];
- ASSERT(bitmap);
-
- // Create a GWorld with the same underlying buffer into which the plugin can draw
- ::Rect printGWorldBounds;
- SetRect(&printGWorldBounds, 0, 0, window.width, window.height);
- GWorldPtr printGWorld;
- if (NewGWorldFromPtr(&printGWorld,
- k32ARGBPixelFormat,
- &printGWorldBounds,
- NULL,
- NULL,
- 0,
- (Ptr)[bitmap bitmapData],
- [bitmap bytesPerRow]) != noErr) {
- LOG_ERROR("Could not create GWorld for printing");
- return nil;
- }
-
- /// Create NPWindow for the GWorld
- NPWindow printNPWindow;
- printNPWindow.window = &printGWorld; // Normally this is an NP_Port, but when printing it is the actual CGrafPtr
- printNPWindow.x = 0;
- printNPWindow.y = 0;
- printNPWindow.width = window.width;
- printNPWindow.height = window.height;
- printNPWindow.clipRect.top = 0;
- printNPWindow.clipRect.left = 0;
- printNPWindow.clipRect.right = window.width;
- printNPWindow.clipRect.bottom = window.height;
- printNPWindow.type = NPWindowTypeDrawable; // Offscreen graphics port as opposed to a proper window
-
- // Create embed-mode NPPrint
- NPPrint npPrint;
- npPrint.mode = NP_EMBED;
- npPrint.print.embedPrint.window = printNPWindow;
- npPrint.print.embedPrint.platformPrint = printGWorld;
-
- // Tell the plugin to print into the GWorld
- [self willCallPlugInFunction];
- {
- JSC::JSLock::DropAllLocks dropAllLocks(false);
- NPP_Print(plugin, &npPrint);
- }
- [self didCallPlugInFunction];
-
- // Don't need the GWorld anymore
- DisposeGWorld(printGWorld);
-
- return bitmap;
-#endif
+ [self mouseDown:theEvent];
}
-- (void)_redeliverStream
+- (void)rightMouseUp:(NSEvent *)theEvent
{
- if ([self dataSource] && [self isStarted]) {
- // Deliver what has not been passed to the plug-in up to this point.
- if (_dataLengthReceived > 0) {
- NSData *data = [[[self dataSource] data] subdataWithRange:NSMakeRange(0, _dataLengthReceived)];
- _dataLengthReceived = 0;
- [self pluginView:self receivedData:data];
- if (![[self dataSource] isLoading]) {
- if (_error)
- [self pluginView:self receivedError:_error];
- else
- [self pluginViewFinishedLoading:self];
- }
- }
- }
+ [self mouseUp:theEvent];
}
@end
-@implementation NSData (PluginExtras)
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
-- (BOOL)_web_startsWithBlankLine
-{
- return [self length] > 0 && ((const char *)[self bytes])[0] == '\n';
-}
-
-
-- (NSInteger)_web_locationAfterFirstBlankLine
-{
- const char *bytes = (const char *)[self bytes];
- unsigned length = [self length];
-
- unsigned i;
- for (i = 0; i < length - 4; i++) {
-
- // Support for Acrobat. It sends "\n\n".
- if (bytes[i] == '\n' && bytes[i+1] == '\n') {
- return i+2;
- }
-
- // Returns the position after 2 CRLF's or 1 CRLF if it is the first line.
- if (bytes[i] == '\r' && bytes[i+1] == '\n') {
- i += 2;
- if (i == 2) {
- return i;
- } else if (bytes[i] == '\n') {
- // Support for Director. It sends "\r\n\n" (3880387).
- return i+1;
- } else if (bytes[i] == '\r' && bytes[i+1] == '\n') {
- // Support for Flash. It sends "\r\n\r\n" (3758113).
- return i+2;
- }
- }
- }
- return NSNotFound;
-}
-
-@end
-#endif
diff --git a/WebKit/mac/Plugins/WebBasePluginPackage.m b/WebKit/mac/Plugins/WebBasePluginPackage.mm
index 03d438b..7b5ef8e 100644
--- a/WebKit/mac/Plugins/WebBasePluginPackage.m
+++ b/WebKit/mac/Plugins/WebBasePluginPackage.mm
@@ -33,6 +33,7 @@
#import <WebKit/WebNSObjectExtras.h>
#import <WebKit/WebPluginPackage.h>
#import <WebCore/WebCoreObjCExtras.h>
+#import <runtime/InitializeThreading.h>
#import <wtf/Assertions.h>
#import <wtf/Vector.h>
@@ -59,12 +60,13 @@
@implementation WebBasePluginPackage
-#ifndef BUILDING_ON_TIGER
+ (void)initialize
{
+ JSC::initializeThreading();
+#ifndef BUILDING_ON_TIGER
WebCoreObjCFinalizeOnMainThread(self);
-}
#endif
+}
+ (WebBasePluginPackage *)pluginWithPath:(NSString *)pluginPath
{
diff --git a/WebKit/mac/Plugins/WebNetscapePluginEventHandler.h b/WebKit/mac/Plugins/WebNetscapePluginEventHandler.h
index 54402bb..d00796f 100644
--- a/WebKit/mac/Plugins/WebNetscapePluginEventHandler.h
+++ b/WebKit/mac/Plugins/WebNetscapePluginEventHandler.h
@@ -26,18 +26,18 @@
#ifndef WebNetscapePluginEventHandler_h
#define WebNetscapePluginEventHandler_h
-#import "WebBaseNetscapePluginView.h"
+#import "WebNetscapePluginView.h"
#if ENABLE(NETSCAPE_PLUGIN_API)
@class NSEvent;
-@class WebBaseNetscapePluginView;
+@class WebNetscapePluginView;
struct CGRect;
class WebNetscapePluginEventHandler {
public:
- static WebNetscapePluginEventHandler* create(WebBaseNetscapePluginView*);
+ static WebNetscapePluginEventHandler* create(WebNetscapePluginView*);
virtual ~WebNetscapePluginEventHandler() { }
virtual void drawRect(const NSRect&) = 0;
@@ -65,13 +65,13 @@ public:
bool currentEventIsUserGesture() const { return m_currentEventIsUserGesture; }
protected:
- WebNetscapePluginEventHandler(WebBaseNetscapePluginView* pluginView)
+ WebNetscapePluginEventHandler(WebNetscapePluginView* pluginView)
: m_pluginView(pluginView)
, m_currentEventIsUserGesture(false)
{
}
- WebBaseNetscapePluginView* m_pluginView;
+ WebNetscapePluginView* m_pluginView;
bool m_currentEventIsUserGesture;
};
diff --git a/WebKit/mac/Plugins/WebNetscapePluginEventHandler.mm b/WebKit/mac/Plugins/WebNetscapePluginEventHandler.mm
index e8e6d8a..c886d7b 100644
--- a/WebKit/mac/Plugins/WebNetscapePluginEventHandler.mm
+++ b/WebKit/mac/Plugins/WebNetscapePluginEventHandler.mm
@@ -28,11 +28,11 @@
#import "WebNetscapePluginEventHandler.h"
#import <wtf/Assertions.h>
-#import "WebBaseNetscapePluginView.h"
+#import "WebNetscapePluginView.h"
#import "WebNetscapePluginEventHandlerCarbon.h"
#import "WebNetscapePluginEventHandlerCocoa.h"
-WebNetscapePluginEventHandler* WebNetscapePluginEventHandler::create(WebBaseNetscapePluginView* pluginView)
+WebNetscapePluginEventHandler* WebNetscapePluginEventHandler::create(WebNetscapePluginView* pluginView)
{
switch ([pluginView eventModel]) {
#ifndef NP_NO_CARBON
diff --git a/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCarbon.h b/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCarbon.h
index cf26276..b01922a 100644
--- a/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCarbon.h
+++ b/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCarbon.h
@@ -35,7 +35,7 @@
class WebNetscapePluginEventHandlerCarbon : public WebNetscapePluginEventHandler {
public:
- WebNetscapePluginEventHandlerCarbon(WebBaseNetscapePluginView*);
+ WebNetscapePluginEventHandlerCarbon(WebNetscapePluginView*);
virtual void drawRect(const NSRect&);
diff --git a/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCarbon.mm b/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCarbon.mm
index bfdd91c..7612322 100644
--- a/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCarbon.mm
+++ b/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCarbon.mm
@@ -27,7 +27,7 @@
#import "WebNetscapePluginEventHandlerCarbon.h"
-#import "WebBaseNetscapePluginView.h"
+#import "WebNetscapePluginView.h"
#import "WebKitLogging.h"
#import "WebKitSystemInterface.h"
@@ -35,7 +35,7 @@
#define NullEventIntervalActive 0.02
#define NullEventIntervalNotActive 0.25
-WebNetscapePluginEventHandlerCarbon::WebNetscapePluginEventHandlerCarbon(WebBaseNetscapePluginView* pluginView)
+WebNetscapePluginEventHandlerCarbon::WebNetscapePluginEventHandlerCarbon(WebNetscapePluginView* pluginView)
: WebNetscapePluginEventHandler(pluginView)
, m_keyEventHandler(0)
, m_suspendKeyUpEvents(false)
@@ -265,11 +265,14 @@ void WebNetscapePluginEventHandlerCarbon::focusChanged(bool hasFocus)
void WebNetscapePluginEventHandlerCarbon::windowFocusChanged(bool hasFocus)
{
+ WindowRef windowRef = (WindowRef)[[m_pluginView window] windowRef];
+
+ SetUserFocusWindow(windowRef);
+
EventRecord event;
getCarbonEvent(&event);
event.what = activateEvt;
- WindowRef windowRef = (WindowRef)[[m_pluginView window] windowRef];
event.message = (unsigned long)windowRef;
if (hasFocus)
event.modifiers |= activeFlag;
diff --git a/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.h b/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.h
index e22ff3d..8b6f6e7 100644
--- a/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.h
+++ b/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.h
@@ -33,7 +33,7 @@
class WebNetscapePluginEventHandlerCocoa : public WebNetscapePluginEventHandler {
public:
- WebNetscapePluginEventHandlerCocoa(WebBaseNetscapePluginView*);
+ WebNetscapePluginEventHandlerCocoa(WebNetscapePluginView*);
virtual void drawRect(const NSRect&);
diff --git a/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.mm b/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.mm
index fb13a12..288a356 100644
--- a/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.mm
+++ b/WebKit/mac/Plugins/WebNetscapePluginEventHandlerCocoa.mm
@@ -27,9 +27,9 @@
#import "WebNetscapePluginEventHandlerCocoa.h"
-#import "WebBaseNetscapePluginView.h"
+#import "WebNetscapePluginView.h"
-WebNetscapePluginEventHandlerCocoa::WebNetscapePluginEventHandlerCocoa(WebBaseNetscapePluginView* pluginView)
+WebNetscapePluginEventHandlerCocoa::WebNetscapePluginEventHandlerCocoa(WebNetscapePluginView* pluginView)
: WebNetscapePluginEventHandler(pluginView)
{
}
diff --git a/WebKit/mac/Plugins/WebNetscapePluginPackage.h b/WebKit/mac/Plugins/WebNetscapePluginPackage.h
index 6ccbfdb..010956d 100644
--- a/WebKit/mac/Plugins/WebNetscapePluginPackage.h
+++ b/WebKit/mac/Plugins/WebNetscapePluginPackage.h
@@ -52,26 +52,16 @@ typedef enum {
ResFileRefNum resourceRef;
- NPP_NewProcPtr NPP_New;
- NPP_DestroyProcPtr NPP_Destroy;
- NPP_SetWindowProcPtr NPP_SetWindow;
- NPP_NewStreamProcPtr NPP_NewStream;
- NPP_DestroyStreamProcPtr NPP_DestroyStream;
- NPP_StreamAsFileProcPtr NPP_StreamAsFile;
- NPP_WriteReadyProcPtr NPP_WriteReady;
- NPP_WriteProcPtr NPP_Write;
- NPP_PrintProcPtr NPP_Print;
- NPP_HandleEventProcPtr NPP_HandleEvent;
- NPP_URLNotifyProcPtr NPP_URLNotify;
- NPP_GetValueProcPtr NPP_GetValue;
- NPP_SetValueProcPtr NPP_SetValue;
- NPP_ShutdownProcPtr NPP_Shutdown;
- NPP_GetJavaClassProcPtr NPP_GetJavaClass;
+ NPP_ShutdownProcPtr NP_Shutdown;
BOOL isLoaded;
BOOL needsUnload;
unsigned int instanceCount;
-
+
+#if USE(PLUGIN_HOST_PROCESS)
+ cpu_type_t pluginHostArchitecture;
+#endif
+
#ifdef SUPPORT_CFM
BOOL isBundle;
BOOL isCFM;
@@ -85,21 +75,11 @@ typedef enum {
- (void)close;
- (WebExecutableType)executableType;
-
-- (NPP_NewProcPtr)NPP_New;
-- (NPP_DestroyProcPtr)NPP_Destroy;
-- (NPP_SetWindowProcPtr)NPP_SetWindow;
-- (NPP_NewStreamProcPtr)NPP_NewStream;
-- (NPP_WriteReadyProcPtr)NPP_WriteReady;
-- (NPP_WriteProcPtr)NPP_Write;
-- (NPP_StreamAsFileProcPtr)NPP_StreamAsFile;
-- (NPP_DestroyStreamProcPtr)NPP_DestroyStream;
-- (NPP_HandleEventProcPtr)NPP_HandleEvent;
-- (NPP_URLNotifyProcPtr)NPP_URLNotify;
-- (NPP_GetValueProcPtr)NPP_GetValue;
-- (NPP_SetValueProcPtr)NPP_SetValue;
-- (NPP_PrintProcPtr)NPP_Print;
- (NPPluginFuncs *)pluginFuncs;
+#if USE(PLUGIN_HOST_PROCESS)
+- (cpu_type_t)pluginHostArchitecture;
+#endif
+
@end
#endif
diff --git a/WebKit/mac/Plugins/WebNetscapePluginPackage.m b/WebKit/mac/Plugins/WebNetscapePluginPackage.m
index 0767c1d..b3ad0bd 100644
--- a/WebKit/mac/Plugins/WebNetscapePluginPackage.m
+++ b/WebKit/mac/Plugins/WebNetscapePluginPackage.m
@@ -236,9 +236,20 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer);
if (hasCFMHeader)
return NO;
#endif
+
+#if USE(PLUGIN_HOST_PROCESS)
+ NSArray *archs = [bundle executableArchitectures];
+ if ([archs containsObject:[NSNumber numberWithInteger:NSBundleExecutableArchitectureX86_64]])
+ pluginHostArchitecture = CPU_TYPE_X86_64;
+ else if ([archs containsObject:[NSNumber numberWithInteger:NSBundleExecutableArchitectureI386]])
+ pluginHostArchitecture = CPU_TYPE_X86;
+ else
+ return NO;
+#else
if (![self isNativeLibraryData:data])
return NO;
+#endif
}
if (![self getPluginInfoFromPLists] && ![self getPluginInfoFromResources])
@@ -272,6 +283,13 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer);
return WebMachOExecutableType;
}
+#if USE(PLUGIN_HOST_PROCESS)
+- (cpu_type_t)pluginHostArchitecture
+{
+ return pluginHostArchitecture;
+}
+#endif
+
- (void)launchRealPlayer
{
CFURLRef appURL = NULL;
@@ -346,8 +364,8 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer);
#endif
NP_Initialize = (NP_InitializeFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_Initialize"));
NP_GetEntryPoints = (NP_GetEntryPointsFuncPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_GetEntryPoints"));
- NPP_Shutdown = (NPP_ShutdownProcPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_Shutdown"));
- if (!NP_Initialize || !NP_GetEntryPoints || !NPP_Shutdown)
+ NP_Shutdown = (NPP_ShutdownProcPtr)CFBundleGetFunctionPointerForName(cfBundle, CFSTR("NP_Shutdown"));
+ if (!NP_Initialize || !NP_GetEntryPoints || !NP_Shutdown)
goto abort;
#ifdef SUPPORT_CFM
}
@@ -439,9 +457,11 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer);
browserFuncs.createobject = (NPN_CreateObjectProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_CreateObject);
browserFuncs.retainobject = (NPN_RetainObjectProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_RetainObject);
browserFuncs.releaseobject = (NPN_ReleaseObjectProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_ReleaseObject);
+ browserFuncs.hasmethod = (NPN_HasMethodProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_HasProperty);
browserFuncs.invoke = (NPN_InvokeProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_Invoke);
browserFuncs.invokeDefault = (NPN_InvokeDefaultProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_InvokeDefault);
browserFuncs.evaluate = (NPN_EvaluateProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_Evaluate);
+ browserFuncs.hasproperty = (NPN_HasPropertyProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_HasProperty);
browserFuncs.getproperty = (NPN_GetPropertyProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_GetProperty);
browserFuncs.setproperty = (NPN_SetPropertyProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_SetProperty);
browserFuncs.removeproperty = (NPN_RemovePropertyProcPtr)tVectorForFunctionPointer((FunctionPointer)_NPN_RemoveProperty);
@@ -457,7 +477,7 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer);
LOG(Plugins, "%f main timing started", mainStart);
NPP_ShutdownProcPtr shutdownFunction;
npErr = pluginMainFunc(&browserFuncs, &pluginFuncs, &shutdownFunction);
- NPP_Shutdown = (NPP_ShutdownProcPtr)functionPointerForTVector((TransitionVector)shutdownFunction);
+ NP_Shutdown = (NPP_ShutdownProcPtr)functionPointerForTVector((TransitionVector)shutdownFunction);
if (!isBundle)
// Don't free pluginMainFunc if we got it from a bundle because it is owned by CFBundle in that case.
free(pluginMainFunc);
@@ -479,24 +499,24 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer);
pluginVersion = pluginFuncs.version;
LOG(Plugins, "pluginMainFunc: %d, size=%d, version=%d", npErr, pluginSize, pluginVersion);
- NPP_New = (NPP_NewProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.newp);
- NPP_Destroy = (NPP_DestroyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.destroy);
- NPP_SetWindow = (NPP_SetWindowProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.setwindow);
- NPP_NewStream = (NPP_NewStreamProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.newstream);
- NPP_DestroyStream = (NPP_DestroyStreamProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.destroystream);
- NPP_StreamAsFile = (NPP_StreamAsFileProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.asfile);
- NPP_WriteReady = (NPP_WriteReadyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.writeready);
- NPP_Write = (NPP_WriteProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.write);
- NPP_Print = (NPP_PrintProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.print);
- NPP_HandleEvent = (NPP_HandleEventProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.event);
- NPP_URLNotify = (NPP_URLNotifyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.urlnotify);
- NPP_GetValue = (NPP_GetValueProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.getvalue);
- NPP_SetValue = (NPP_SetValueProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.setvalue);
+ pluginFuncs.newp = (NPP_NewProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.newp);
+ pluginFuncs.destroy = (NPP_DestroyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.destroy);
+ pluginFuncs.setwindow = (NPP_SetWindowProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.setwindow);
+ pluginFuncs.newstream = (NPP_NewStreamProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.newstream);
+ pluginFuncs.destroystream = (NPP_DestroyStreamProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.destroystream);
+ pluginFuncs.asfile = (NPP_StreamAsFileProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.asfile);
+ pluginFuncs.writeready = (NPP_WriteReadyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.writeready);
+ pluginFuncs.write = (NPP_WriteProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.write);
+ pluginFuncs.print = (NPP_PrintProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.print);
+ pluginFuncs.event = (NPP_HandleEventProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.event);
+ pluginFuncs.urlnotify = (NPP_URLNotifyProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.urlnotify);
+ pluginFuncs.getvalue = (NPP_GetValueProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.getvalue);
+ pluginFuncs.setvalue = (NPP_SetValueProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.setvalue);
// LiveConnect support
- NPP_GetJavaClass = (NPP_GetJavaClassProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.javaClass);
- if (NPP_GetJavaClass) {
- LOG(LiveConnect, "%@: CFM entry point for NPP_GetJavaClass = %p", [self name], NPP_GetJavaClass);
+ pluginFuncs.javaClass = (NPP_GetJavaClassProcPtr)functionPointerForTVector((TransitionVector)pluginFuncs.javaClass);
+ if (pluginFuncs.javaClass) {
+ LOG(LiveConnect, "%@: CFM entry point for NPP_GetJavaClass = %p", [self name], pluginFuncs.javaClass);
} else {
LOG(LiveConnect, "%@: no entry point for NPP_GetJavaClass", [self name]);
}
@@ -546,9 +566,11 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer);
browserFuncs.createobject = _NPN_CreateObject;
browserFuncs.retainobject = _NPN_RetainObject;
browserFuncs.releaseobject = _NPN_ReleaseObject;
+ browserFuncs.hasmethod = _NPN_HasMethod;
browserFuncs.invoke = _NPN_Invoke;
browserFuncs.invokeDefault = _NPN_InvokeDefault;
browserFuncs.evaluate = _NPN_Evaluate;
+ browserFuncs.hasproperty = _NPN_HasProperty;
browserFuncs.getproperty = _NPN_GetProperty;
browserFuncs.setproperty = _NPN_SetProperty;
browserFuncs.removeproperty = _NPN_RemoveProperty;
@@ -580,27 +602,10 @@ static TransitionVector tVectorForFunctionPointer(FunctionPointer);
pluginSize = pluginFuncs.size;
pluginVersion = pluginFuncs.version;
- NPP_New = pluginFuncs.newp;
- NPP_Destroy = pluginFuncs.destroy;
- NPP_SetWindow = pluginFuncs.setwindow;
- NPP_NewStream = pluginFuncs.newstream;
- NPP_DestroyStream = pluginFuncs.destroystream;
- NPP_StreamAsFile = pluginFuncs.asfile;
- NPP_WriteReady = pluginFuncs.writeready;
- NPP_Write = pluginFuncs.write;
- NPP_Print = pluginFuncs.print;
- NPP_HandleEvent = pluginFuncs.event;
- NPP_URLNotify = pluginFuncs.urlnotify;
- NPP_GetValue = pluginFuncs.getvalue;
- NPP_SetValue = pluginFuncs.setvalue;
-
- // LiveConnect support
- NPP_GetJavaClass = pluginFuncs.javaClass;
- if (NPP_GetJavaClass){
- LOG(LiveConnect, "%@: mach-o entry point for NPP_GetJavaClass = %p", [self name], NPP_GetJavaClass);
- } else {
+ if (pluginFuncs.javaClass)
+ LOG(LiveConnect, "%@: mach-o entry point for NPP_GetJavaClass = %p", [self name], pluginFuncs.javaClass);
+ else
LOG(LiveConnect, "%@: no entry point for NPP_GetJavaClass", [self name]);
- }
#ifdef SUPPORT_CFM
}
@@ -619,69 +624,6 @@ abort:
return NO;
}
-- (NPP_SetWindowProcPtr)NPP_SetWindow
-{
- return NPP_SetWindow;
-}
-
-- (NPP_NewProcPtr)NPP_New
-{
- return NPP_New;
-}
-
-- (NPP_DestroyProcPtr)NPP_Destroy
-{
- return NPP_Destroy;
-}
-
-- (NPP_NewStreamProcPtr)NPP_NewStream
-{
- return NPP_NewStream;
-}
-
-- (NPP_StreamAsFileProcPtr)NPP_StreamAsFile
-{
- return NPP_StreamAsFile;
-}
-- (NPP_DestroyStreamProcPtr)NPP_DestroyStream
-{
- return NPP_DestroyStream;
-}
-
-- (NPP_WriteReadyProcPtr)NPP_WriteReady
-{
- return NPP_WriteReady;
-}
-- (NPP_WriteProcPtr)NPP_Write
-{
- return NPP_Write;
-}
-
-- (NPP_HandleEventProcPtr)NPP_HandleEvent
-{
- return NPP_HandleEvent;
-}
-
--(NPP_URLNotifyProcPtr)NPP_URLNotify
-{
- return NPP_URLNotify;
-}
-
--(NPP_GetValueProcPtr)NPP_GetValue
-{
- return NPP_GetValue;
-}
-
--(NPP_SetValueProcPtr)NPP_SetValue
-{
- return NPP_SetValue;
-}
-
--(NPP_PrintProcPtr)NPP_Print
-{
- return NPP_Print;
-}
-
- (NPPluginFuncs *)pluginFuncs
{
return &pluginFuncs;
@@ -775,8 +717,8 @@ TransitionVector tVectorForFunctionPointer(FunctionPointer fp)
return;
}
- if (shutdown && NPP_Shutdown)
- NPP_Shutdown();
+ if (shutdown && NP_Shutdown)
+ NP_Shutdown();
if (resourceRef != -1)
[self closeResourceFile:resourceRef];
diff --git a/WebKit/mac/Plugins/WebNetscapePluginView.h b/WebKit/mac/Plugins/WebNetscapePluginView.h
new file mode 100644
index 0000000..9d2555b
--- /dev/null
+++ b/WebKit/mac/Plugins/WebNetscapePluginView.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2005, 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if ENABLE(NETSCAPE_PLUGIN_API)
+
+#import "WebBaseNetscapePluginView.h"
+
+#import <WebKit/npfunctions.h>
+#import <WebKit/npapi.h>
+#import <wtf/HashMap.h>
+#import <wtf/HashSet.h>
+#import <wtf/OwnPtr.h>
+
+@class WebDataSource;
+@class WebFrame;
+@class WebNetscapePluginPackage;
+@class WebView;
+
+class PluginTimer;
+class WebNetscapePluginStream;
+class WebNetscapePluginEventHandler;
+
+typedef union PluginPort {
+#ifndef NP_NO_QUICKDRAW
+ NP_Port qdPort;
+#endif
+ NP_CGContext cgPort;
+} PluginPort;
+
+typedef struct _NPPluginTextInputFuncs NPPluginTextInputFuncs;
+
+// Because the Adobe 7.x Acrobat plug-in has a hard coded check for a view named
+// "WebNetscapePluginDocumentView", this class must retain the old name in order
+// for the plug-in to function correctly. (rdar://problem/4699455)
+#define WebNetscapePluginView WebNetscapePluginDocumentView
+
+@interface WebNetscapePluginView : WebBaseNetscapePluginView<WebPluginManualLoader, NSTextInput>
+{
+ RefPtr<WebNetscapePluginStream> _manualStream;
+#ifndef BUILDING_ON_TIGER
+ RetainPtr<CALayer> _pluginLayer;
+#endif
+ unsigned _dataLengthReceived;
+ RetainPtr<NSError> _error;
+
+ unsigned argsCount;
+ char **cAttributes;
+ char **cValues;
+
+ NPP plugin;
+ NPWindow window;
+ NPWindow lastSetWindow;
+ PluginPort nPort;
+ PluginPort lastSetPort;
+ NPDrawingModel drawingModel;
+ NPEventModel eventModel;
+
+#ifndef NP_NO_QUICKDRAW
+ // This is only valid when drawingModel is NPDrawingModelQuickDraw
+ GWorldPtr offscreenGWorld;
+#endif
+
+ OwnPtr<WebNetscapePluginEventHandler> _eventHandler;
+
+ BOOL inSetWindow;
+ BOOL shouldStopSoon;
+
+ uint32 currentTimerID;
+ HashMap<uint32, PluginTimer*>* timers;
+
+ unsigned pluginFunctionCallDepth;
+
+ int32 specifiedHeight;
+ int32 specifiedWidth;
+
+ HashSet<RefPtr<WebNetscapePluginStream> > streams;
+ RetainPtr<NSMutableDictionary> _pendingFrameLoads;
+
+ BOOL _isSilverlight;
+
+ NPPluginTextInputFuncs *textInputFuncs;
+}
+
++ (WebNetscapePluginView *)currentPluginView;
+
+
+- (id)initWithFrame:(NSRect)r
+ pluginPackage:(WebNetscapePluginPackage *)thePluginPackage
+ URL:(NSURL *)URL
+ baseURL:(NSURL *)baseURL
+ MIMEType:(NSString *)MIME
+ attributeKeys:(NSArray *)keys
+ attributeValues:(NSArray *)values
+ loadManually:(BOOL)loadManually
+ DOMElement:(DOMElement *)anElement;
+
+
+- (NPP)plugin;
+
+- (void)disconnectStream:(WebNetscapePluginStream*)stream;
+
+// Returns the NPObject that represents the plugin interface.
+// The return value is expected to be retained.
+- (NPObject *)createPluginScriptableObject;
+
+// -willCallPlugInFunction must be called before calling any of the NPP_* functions for this view's plugin.
+// This is necessary to ensure that plug-ins are not destroyed while WebKit calls into them. Some plug-ins (Flash
+// at least) are written with the assumption that nothing they do in their plug-in functions can cause NPP_Destroy()
+// to be called. Unfortunately, this is not true, especially if the plug-in uses NPN_Invoke() to execute a
+// document.write(), which clears the document and destroys the plug-in.
+// See <rdar://problem/4480737>.
+- (void)willCallPlugInFunction;
+
+// -didCallPlugInFunction should be called after returning from a plug-in function. It should be called exactly
+// once for every call to -willCallPlugInFunction.
+// See <rdar://problem/4480737>.
+- (void)didCallPlugInFunction;
+
+- (void)handleMouseMoved:(NSEvent *)event;
+
+@end
+
+@interface WebNetscapePluginView (WebInternal)
+- (BOOL)sendEvent:(void*)event isDrawRect:(BOOL)eventIsDrawRect;
+- (NPEventModel)eventModel;
+
+- (NPError)loadRequest:(NSURLRequest *)request inTarget:(NSString *)target withNotifyData:(void *)notifyData sendNotification:(BOOL)sendNotification;
+- (NPError)getURLNotify:(const char *)URL target:(const char *)target notifyData:(void *)notifyData;
+- (NPError)getURL:(const char *)URL target:(const char *)target;
+- (NPError)postURLNotify:(const char *)URL target:(const char *)target len:(UInt32)len buf:(const char *)buf file:(NPBool)file notifyData:(void *)notifyData;
+- (NPError)postURL:(const char *)URL target:(const char *)target len:(UInt32)len buf:(const char *)buf file:(NPBool)file;
+- (NPError)newStream:(NPMIMEType)type target:(const char *)target stream:(NPStream**)stream;
+- (NPError)write:(NPStream*)stream len:(SInt32)len buffer:(void *)buffer;
+- (NPError)destroyStream:(NPStream*)stream reason:(NPReason)reason;
+- (void)status:(const char *)message;
+- (const char *)userAgent;
+- (void)invalidateRect:(NPRect *)invalidRect;
+- (void)invalidateRegion:(NPRegion)invalidateRegion;
+- (void)forceRedraw;
+- (NPError)getVariable:(NPNVariable)variable value:(void *)value;
+- (NPError)setVariable:(NPPVariable)variable value:(void *)value;
+- (uint32)scheduleTimerWithInterval:(uint32)interval repeat:(NPBool)repeat timerFunc:(void (*)(NPP npp, uint32 timerID))timerFunc;
+- (void)unscheduleTimer:(uint32)timerID;
+- (NPError)popUpContextMenu:(NPMenu *)menu;
+
+@end
+
+#endif
+
diff --git a/WebKit/mac/Plugins/WebNetscapePluginView.mm b/WebKit/mac/Plugins/WebNetscapePluginView.mm
new file mode 100644
index 0000000..a792e21
--- /dev/null
+++ b/WebKit/mac/Plugins/WebNetscapePluginView.mm
@@ -0,0 +1,2338 @@
+/*
+ * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if ENABLE(NETSCAPE_PLUGIN_API)
+
+#import "WebNetscapePluginView.h"
+
+#import "WebDataSourceInternal.h"
+#import "WebDefaultUIDelegate.h"
+#import "WebFrameInternal.h"
+#import "WebFrameView.h"
+#import "WebGraphicsExtras.h"
+#import "WebKitLogging.h"
+#import "WebKitNSStringExtras.h"
+#import "WebKitSystemInterface.h"
+#import "WebNSDataExtras.h"
+#import "WebNSDictionaryExtras.h"
+#import "WebNSObjectExtras.h"
+#import "WebNSURLExtras.h"
+#import "WebNSURLRequestExtras.h"
+#import "WebNSViewExtras.h"
+#import "WebNetscapePluginPackage.h"
+#import "WebBaseNetscapePluginStream.h"
+#import "WebNetscapePluginEventHandler.h"
+#import "WebNullPluginView.h"
+#import "WebPreferences.h"
+#import "WebPluginRequest.h"
+#import "WebViewInternal.h"
+#import "WebUIDelegatePrivate.h"
+#import <Carbon/Carbon.h>
+#import <runtime/JSLock.h>
+#import <WebCore/npruntime_impl.h>
+#import <WebCore/DocumentLoader.h>
+#import <WebCore/Element.h>
+#import <WebCore/Frame.h>
+#import <WebCore/FrameLoader.h>
+#import <WebCore/FrameTree.h>
+#import <WebCore/Page.h>
+#import <WebCore/PluginMainThreadScheduler.h>
+#import <WebCore/ScriptController.h>
+#import <WebCore/SoftLinking.h>
+#import <WebCore/WebCoreObjCExtras.h>
+#import <WebKit/nptextinput.h>
+#import <WebKit/DOMPrivate.h>
+#import <WebKit/WebUIDelegate.h>
+#import <runtime/InitializeThreading.h>
+#import <wtf/Assertions.h>
+#import <objc/objc-runtime.h>
+
+#define LoginWindowDidSwitchFromUserNotification @"WebLoginWindowDidSwitchFromUserNotification"
+#define LoginWindowDidSwitchToUserNotification @"WebLoginWindowDidSwitchToUserNotification"
+
+using namespace WebCore;
+
+static inline bool isDrawingModelQuickDraw(NPDrawingModel drawingModel)
+{
+#ifndef NP_NO_QUICKDRAW
+ return drawingModel == NPDrawingModelQuickDraw;
+#else
+ return false;
+#endif
+};
+
+@interface WebNetscapePluginView (Internal)
+- (NPError)_createPlugin;
+- (void)_destroyPlugin;
+- (NSBitmapImageRep *)_printedPluginBitmap;
+- (void)_redeliverStream;
+@end
+
+static WebNetscapePluginView *currentPluginView = nil;
+
+typedef struct OpaquePortState* PortState;
+
+static const double ThrottledTimerInterval = 0.25;
+
+class PluginTimer : public TimerBase {
+public:
+ typedef void (*TimerFunc)(NPP npp, uint32 timerID);
+
+ PluginTimer(NPP npp, uint32 timerID, uint32 interval, NPBool repeat, TimerFunc timerFunc)
+ : m_npp(npp)
+ , m_timerID(timerID)
+ , m_interval(interval)
+ , m_repeat(repeat)
+ , m_timerFunc(timerFunc)
+ {
+ }
+
+ void start(bool throttle)
+ {
+ ASSERT(!isActive());
+
+ double timeInterval = m_interval / 1000.0;
+
+ if (throttle)
+ timeInterval = max(timeInterval, ThrottledTimerInterval);
+
+ if (m_repeat)
+ startRepeating(timeInterval);
+ else
+ startOneShot(timeInterval);
+ }
+
+private:
+ virtual void fired()
+ {
+ m_timerFunc(m_npp, m_timerID);
+ if (!m_repeat)
+ delete this;
+ }
+
+ NPP m_npp;
+ uint32 m_timerID;
+ uint32 m_interval;
+ NPBool m_repeat;
+ TimerFunc m_timerFunc;
+};
+
+#ifndef NP_NO_QUICKDRAW
+
+// QuickDraw is not available in 64-bit
+
+typedef struct {
+ GrafPtr oldPort;
+ GDHandle oldDevice;
+ Point oldOrigin;
+ RgnHandle oldClipRegion;
+ RgnHandle oldVisibleRegion;
+ RgnHandle clipRegion;
+ BOOL forUpdate;
+} PortState_QD;
+
+#endif /* NP_NO_QUICKDRAW */
+
+typedef struct {
+ CGContextRef context;
+} PortState_CG;
+
+@class NSTextInputContext;
+@interface NSResponder (AppKitDetails)
+- (NSTextInputContext *)inputContext;
+@end
+
+@interface WebNetscapePluginView (ForwardDeclarations)
+- (void)setWindowIfNecessary;
+- (NPError)loadRequest:(NSMutableURLRequest *)request inTarget:(const char *)cTarget withNotifyData:(void *)notifyData sendNotification:(BOOL)sendNotification;
+@end
+
+@implementation WebNetscapePluginView
+
++ (void)initialize
+{
+ JSC::initializeThreading();
+#ifndef BUILDING_ON_TIGER
+ WebCoreObjCFinalizeOnMainThread(self);
+#endif
+ WKSendUserChangeNotifications();
+}
+
+#pragma mark EVENTS
+
+- (BOOL)superviewsHaveSuperviews
+{
+ NSView *contentView = [[self window] contentView];
+ NSView *view;
+ for (view = self; view != nil; view = [view superview]) {
+ if (view == contentView) {
+ return YES;
+ }
+ }
+ return NO;
+}
+
+
+// The WindowRef created by -[NSWindow windowRef] has a QuickDraw GrafPort that covers
+// the entire window frame (or structure region to use the Carbon term) rather then just the window content.
+// We can remove this when <rdar://problem/4201099> is fixed.
+- (void)fixWindowPort
+{
+#ifndef NP_NO_QUICKDRAW
+ ASSERT(isDrawingModelQuickDraw(drawingModel));
+
+ NSWindow *currentWindow = [self currentWindow];
+ if ([currentWindow isKindOfClass:objc_getClass("NSCarbonWindow")])
+ return;
+
+ float windowHeight = [currentWindow frame].size.height;
+ NSView *contentView = [currentWindow contentView];
+ NSRect contentRect = [contentView convertRect:[contentView frame] toView:nil]; // convert to window-relative coordinates
+
+ CGrafPtr oldPort;
+ GetPort(&oldPort);
+ SetPort(GetWindowPort((WindowRef)[currentWindow windowRef]));
+
+ MovePortTo(static_cast<short>(contentRect.origin.x), /* Flip Y */ static_cast<short>(windowHeight - NSMaxY(contentRect)));
+ PortSize(static_cast<short>(contentRect.size.width), static_cast<short>(contentRect.size.height));
+
+ SetPort(oldPort);
+#endif
+}
+
+#ifndef NP_NO_QUICKDRAW
+static UInt32 getQDPixelFormatForBitmapContext(CGContextRef context)
+{
+ UInt32 byteOrder = CGBitmapContextGetBitmapInfo(context) & kCGBitmapByteOrderMask;
+ if (byteOrder == kCGBitmapByteOrderDefault)
+ switch (CGBitmapContextGetBitsPerPixel(context)) {
+ case 16:
+ byteOrder = kCGBitmapByteOrder16Host;
+ break;
+ case 32:
+ byteOrder = kCGBitmapByteOrder32Host;
+ break;
+ }
+ switch (byteOrder) {
+ case kCGBitmapByteOrder16Little:
+ return k16LE555PixelFormat;
+ case kCGBitmapByteOrder32Little:
+ return k32BGRAPixelFormat;
+ case kCGBitmapByteOrder16Big:
+ return k16BE555PixelFormat;
+ case kCGBitmapByteOrder32Big:
+ return k32ARGBPixelFormat;
+ }
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+static inline void getNPRect(const CGRect& cgr, NPRect& npr)
+{
+ npr.top = static_cast<uint16>(cgr.origin.y);
+ npr.left = static_cast<uint16>(cgr.origin.x);
+ npr.bottom = static_cast<uint16>(CGRectGetMaxY(cgr));
+ npr.right = static_cast<uint16>(CGRectGetMaxX(cgr));
+}
+
+#endif
+
+static inline void getNPRect(const NSRect& nr, NPRect& npr)
+{
+ npr.top = static_cast<uint16>(nr.origin.y);
+ npr.left = static_cast<uint16>(nr.origin.x);
+ npr.bottom = static_cast<uint16>(NSMaxY(nr));
+ npr.right = static_cast<uint16>(NSMaxX(nr));
+}
+
+- (PortState)saveAndSetNewPortStateForUpdate:(BOOL)forUpdate
+{
+ ASSERT([self currentWindow] != nil);
+
+ // Use AppKit to convert view coordinates to NSWindow coordinates.
+ NSRect boundsInWindow = [self convertRect:[self bounds] toView:nil];
+ NSRect visibleRectInWindow = [self convertRect:[self visibleRect] toView:nil];
+
+ // Flip Y to convert NSWindow coordinates to top-left-based window coordinates.
+ float borderViewHeight = [[self currentWindow] frame].size.height;
+ boundsInWindow.origin.y = borderViewHeight - NSMaxY(boundsInWindow);
+ visibleRectInWindow.origin.y = borderViewHeight - NSMaxY(visibleRectInWindow);
+
+#ifndef NP_NO_QUICKDRAW
+ WindowRef windowRef = (WindowRef)[[self currentWindow] windowRef];
+ ASSERT(windowRef);
+
+ // Look at the Carbon port to convert top-left-based window coordinates into top-left-based content coordinates.
+ if (isDrawingModelQuickDraw(drawingModel)) {
+ // If drawing with QuickDraw, fix the window port so that it has the same bounds as the NSWindow's
+ // content view. This makes it easier to convert between AppKit view and QuickDraw port coordinates.
+ [self fixWindowPort];
+
+ ::Rect portBounds;
+ CGrafPtr port = GetWindowPort(windowRef);
+ GetPortBounds(port, &portBounds);
+
+ PixMap *pix = *GetPortPixMap(port);
+ boundsInWindow.origin.x += pix->bounds.left - portBounds.left;
+ boundsInWindow.origin.y += pix->bounds.top - portBounds.top;
+ visibleRectInWindow.origin.x += pix->bounds.left - portBounds.left;
+ visibleRectInWindow.origin.y += pix->bounds.top - portBounds.top;
+ }
+#endif
+
+ window.type = NPWindowTypeWindow;
+ window.x = (int32)boundsInWindow.origin.x;
+ window.y = (int32)boundsInWindow.origin.y;
+ window.width = static_cast<uint32>(NSWidth(boundsInWindow));
+ window.height = static_cast<uint32>(NSHeight(boundsInWindow));
+
+ // "Clip-out" the plug-in when:
+ // 1) it's not really in a window or off-screen or has no height or width.
+ // 2) window.x is a "big negative number" which is how WebCore expresses off-screen widgets.
+ // 3) the window is miniaturized or the app is hidden
+ // 4) we're inside of viewWillMoveToWindow: with a nil window. In this case, superviews may already have nil
+ // superviews and nil windows and results from convertRect:toView: are incorrect.
+ NSWindow *realWindow = [self window];
+ if (window.width <= 0 || window.height <= 0 || window.x < -100000
+ || realWindow == nil || [realWindow isMiniaturized]
+ || [NSApp isHidden]
+ || ![self superviewsHaveSuperviews]
+ || [self isHiddenOrHasHiddenAncestor]) {
+
+ // The following code tries to give plug-ins the same size they will eventually have.
+ // The specifiedWidth and specifiedHeight variables are used to predict the size that
+ // WebCore will eventually resize us to.
+
+ // The QuickTime plug-in has problems if you give it a width or height of 0.
+ // Since other plug-ins also might have the same sort of trouble, we make sure
+ // to always give plug-ins a size other than 0,0.
+
+ if (window.width <= 0)
+ window.width = specifiedWidth > 0 ? specifiedWidth : 100;
+ if (window.height <= 0)
+ window.height = specifiedHeight > 0 ? specifiedHeight : 100;
+
+ window.clipRect.bottom = window.clipRect.top;
+ window.clipRect.left = window.clipRect.right;
+ } else {
+ getNPRect(visibleRectInWindow, window.clipRect);
+ }
+
+ // Save the port state, set up the port for entry into the plugin
+ PortState portState;
+ switch (drawingModel) {
+#ifndef NP_NO_QUICKDRAW
+ case NPDrawingModelQuickDraw: {
+ // Set up NS_Port.
+ ::Rect portBounds;
+ CGrafPtr port = GetWindowPort(windowRef);
+ GetPortBounds(port, &portBounds);
+ nPort.qdPort.port = port;
+ nPort.qdPort.portx = (int32)-boundsInWindow.origin.x;
+ nPort.qdPort.porty = (int32)-boundsInWindow.origin.y;
+ window.window = &nPort;
+
+ PortState_QD *qdPortState = (PortState_QD*)malloc(sizeof(PortState_QD));
+ portState = (PortState)qdPortState;
+
+ GetGWorld(&qdPortState->oldPort, &qdPortState->oldDevice);
+
+ qdPortState->oldOrigin.h = portBounds.left;
+ qdPortState->oldOrigin.v = portBounds.top;
+
+ qdPortState->oldClipRegion = NewRgn();
+ GetPortClipRegion(port, qdPortState->oldClipRegion);
+
+ qdPortState->oldVisibleRegion = NewRgn();
+ GetPortVisibleRegion(port, qdPortState->oldVisibleRegion);
+
+ RgnHandle clipRegion = NewRgn();
+ qdPortState->clipRegion = clipRegion;
+
+ CGContextRef currentContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
+ if (currentContext && WKCGContextIsBitmapContext(currentContext)) {
+ // We use WKCGContextIsBitmapContext here, because if we just called CGBitmapContextGetData
+ // on any context, we'd log to the console every time. But even if WKCGContextIsBitmapContext
+ // returns true, it still might not be a context we need to create a GWorld for; for example
+ // transparency layers will return true, but return 0 for CGBitmapContextGetData.
+ void* offscreenData = CGBitmapContextGetData(currentContext);
+ if (offscreenData) {
+ // If the current context is an offscreen bitmap, then create a GWorld for it.
+ ::Rect offscreenBounds;
+ offscreenBounds.top = 0;
+ offscreenBounds.left = 0;
+ offscreenBounds.right = CGBitmapContextGetWidth(currentContext);
+ offscreenBounds.bottom = CGBitmapContextGetHeight(currentContext);
+ GWorldPtr newOffscreenGWorld;
+ QDErr err = NewGWorldFromPtr(&newOffscreenGWorld,
+ getQDPixelFormatForBitmapContext(currentContext), &offscreenBounds, 0, 0, 0,
+ static_cast<char*>(offscreenData), CGBitmapContextGetBytesPerRow(currentContext));
+ ASSERT(newOffscreenGWorld && !err);
+ if (!err) {
+ if (offscreenGWorld)
+ DisposeGWorld(offscreenGWorld);
+ offscreenGWorld = newOffscreenGWorld;
+
+ SetGWorld(offscreenGWorld, NULL);
+
+ port = offscreenGWorld;
+
+ nPort.qdPort.port = port;
+ boundsInWindow = [self bounds];
+
+ // Generate a QD origin based on the current affine transform for currentContext.
+ CGAffineTransform offscreenMatrix = CGContextGetCTM(currentContext);
+ CGPoint origin = {0,0};
+ CGPoint axisFlip = {1,1};
+ origin = CGPointApplyAffineTransform(origin, offscreenMatrix);
+ axisFlip = CGPointApplyAffineTransform(axisFlip, offscreenMatrix);
+
+ // Quartz bitmaps have origins at the bottom left, but the axes may be inverted, so handle that.
+ origin.x = offscreenBounds.left - origin.x * (axisFlip.x - origin.x);
+ origin.y = offscreenBounds.bottom + origin.y * (axisFlip.y - origin.y);
+
+ nPort.qdPort.portx = static_cast<int32>(-boundsInWindow.origin.x + origin.x);
+ nPort.qdPort.porty = static_cast<int32>(-boundsInWindow.origin.y - origin.y);
+ window.x = 0;
+ window.y = 0;
+ window.window = &nPort;
+
+ // Use the clip bounds from the context instead of the bounds we created
+ // from the window above.
+ getNPRect(CGRectOffset(CGContextGetClipBoundingBox(currentContext), -origin.x, origin.y), window.clipRect);
+ }
+ }
+ }
+
+ MacSetRectRgn(clipRegion,
+ window.clipRect.left + nPort.qdPort.portx, window.clipRect.top + nPort.qdPort.porty,
+ window.clipRect.right + nPort.qdPort.portx, window.clipRect.bottom + nPort.qdPort.porty);
+
+ // Clip to the dirty region if drawing to a window. When drawing to another bitmap context, do not clip.
+ if ([NSGraphicsContext currentContext] == [[self currentWindow] graphicsContext]) {
+ // Clip to dirty region so plug-in does not draw over already-drawn regions of the window that are
+ // not going to be redrawn this update. This forces plug-ins to play nice with z-index ordering.
+ if (forUpdate) {
+ RgnHandle viewClipRegion = NewRgn();
+
+ // Get list of dirty rects from the opaque ancestor -- WebKit does some tricks with invalidation and
+ // display to enable z-ordering for NSViews; a side-effect of this is that only the WebHTMLView
+ // knows about the true set of dirty rects.
+ NSView *opaqueAncestor = [self opaqueAncestor];
+ const NSRect *dirtyRects;
+ NSInteger dirtyRectCount, dirtyRectIndex;
+ [opaqueAncestor getRectsBeingDrawn:&dirtyRects count:&dirtyRectCount];
+
+ for (dirtyRectIndex = 0; dirtyRectIndex < dirtyRectCount; dirtyRectIndex++) {
+ NSRect dirtyRect = [self convertRect:dirtyRects[dirtyRectIndex] fromView:opaqueAncestor];
+ if (!NSEqualSizes(dirtyRect.size, NSZeroSize)) {
+ // Create a region for this dirty rect
+ RgnHandle dirtyRectRegion = NewRgn();
+ SetRectRgn(dirtyRectRegion, static_cast<short>(NSMinX(dirtyRect)), static_cast<short>(NSMinY(dirtyRect)), static_cast<short>(NSMaxX(dirtyRect)), static_cast<short>(NSMaxY(dirtyRect)));
+
+ // Union this dirty rect with the rest of the dirty rects
+ UnionRgn(viewClipRegion, dirtyRectRegion, viewClipRegion);
+ DisposeRgn(dirtyRectRegion);
+ }
+ }
+
+ // Intersect the dirty region with the clip region, so that we only draw over dirty parts
+ SectRgn(clipRegion, viewClipRegion, clipRegion);
+ DisposeRgn(viewClipRegion);
+ }
+ }
+
+ // Switch to the port and set it up.
+ SetPort(port);
+ PenNormal();
+ ForeColor(blackColor);
+ BackColor(whiteColor);
+ SetOrigin(nPort.qdPort.portx, nPort.qdPort.porty);
+ SetPortClipRegion(nPort.qdPort.port, clipRegion);
+
+ if (forUpdate) {
+ // AppKit may have tried to help us by doing a BeginUpdate.
+ // But the invalid region at that level didn't include AppKit's notion of what was not valid.
+ // We reset the port's visible region to counteract what BeginUpdate did.
+ SetPortVisibleRegion(nPort.qdPort.port, clipRegion);
+ InvalWindowRgn(windowRef, clipRegion);
+ }
+
+ qdPortState->forUpdate = forUpdate;
+ break;
+ }
+#endif /* NP_NO_QUICKDRAW */
+
+ case NPDrawingModelCoreGraphics: {
+ ASSERT([NSView focusView] == self);
+
+ CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]);
+
+ PortState_CG *cgPortState = (PortState_CG *)malloc(sizeof(PortState_CG));
+ portState = (PortState)cgPortState;
+ cgPortState->context = context;
+
+ // Update the plugin's window/context
+#ifdef NP_NO_CARBON
+ nPort.cgPort.window = (NPNSWindow *)[self currentWindow];
+#else
+ nPort.cgPort.window = _eventHandler->platformWindow([self currentWindow]);
+#endif /* NP_NO_CARBON */
+ nPort.cgPort.context = context;
+ window.window = &nPort.cgPort;
+
+ // Save current graphics context's state; will be restored by -restorePortState:
+ CGContextSaveGState(context);
+
+ // Clip to the dirty region if drawing to a window. When drawing to another bitmap context, do not clip.
+ if ([NSGraphicsContext currentContext] == [[self currentWindow] graphicsContext]) {
+ // Get list of dirty rects from the opaque ancestor -- WebKit does some tricks with invalidation and
+ // display to enable z-ordering for NSViews; a side-effect of this is that only the WebHTMLView
+ // knows about the true set of dirty rects.
+ NSView *opaqueAncestor = [self opaqueAncestor];
+ const NSRect *dirtyRects;
+ NSInteger count;
+ [opaqueAncestor getRectsBeingDrawn:&dirtyRects count:&count];
+ Vector<CGRect, 16> convertedDirtyRects;
+ convertedDirtyRects.resize(count);
+ for (int i = 0; i < count; ++i)
+ reinterpret_cast<NSRect&>(convertedDirtyRects[i]) = [self convertRect:dirtyRects[i] fromView:opaqueAncestor];
+ CGContextClipToRects(context, convertedDirtyRects.data(), count);
+ }
+
+ break;
+ }
+
+ case NPDrawingModelCoreAnimation:
+ window.window = [self currentWindow];
+ // Just set the port state to a dummy value.
+ portState = (PortState)1;
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ portState = NULL;
+ break;
+ }
+
+ return portState;
+}
+
+- (PortState)saveAndSetNewPortState
+{
+ return [self saveAndSetNewPortStateForUpdate:NO];
+}
+
+- (void)restorePortState:(PortState)portState
+{
+ ASSERT([self currentWindow]);
+ ASSERT(portState);
+
+ switch (drawingModel) {
+#ifndef NP_NO_QUICKDRAW
+ case NPDrawingModelQuickDraw: {
+ PortState_QD *qdPortState = (PortState_QD *)portState;
+ WindowRef windowRef = (WindowRef)[[self currentWindow] windowRef];
+ CGrafPtr port = GetWindowPort(windowRef);
+
+ SetPort(port);
+
+ if (qdPortState->forUpdate)
+ ValidWindowRgn(windowRef, qdPortState->clipRegion);
+
+ SetOrigin(qdPortState->oldOrigin.h, qdPortState->oldOrigin.v);
+
+ SetPortClipRegion(port, qdPortState->oldClipRegion);
+ if (qdPortState->forUpdate)
+ SetPortVisibleRegion(port, qdPortState->oldVisibleRegion);
+
+ DisposeRgn(qdPortState->oldClipRegion);
+ DisposeRgn(qdPortState->oldVisibleRegion);
+ DisposeRgn(qdPortState->clipRegion);
+
+ SetGWorld(qdPortState->oldPort, qdPortState->oldDevice);
+ break;
+ }
+#endif /* NP_NO_QUICKDRAW */
+
+ case NPDrawingModelCoreGraphics:
+ ASSERT([NSView focusView] == self);
+ ASSERT(((PortState_CG *)portState)->context == nPort.cgPort.context);
+ CGContextRestoreGState(nPort.cgPort.context);
+ break;
+
+ case NPDrawingModelCoreAnimation:
+ ASSERT(portState == (PortState)1);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+}
+
+- (BOOL)sendEvent:(void*)event isDrawRect:(BOOL)eventIsDrawRect
+{
+ if (![self window])
+ return NO;
+ ASSERT(event);
+
+ if (!_isStarted)
+ return NO;
+
+ ASSERT([_pluginPackage.get() pluginFuncs]->event);
+
+ // Make sure we don't call NPP_HandleEvent while we're inside NPP_SetWindow.
+ // We probably don't want more general reentrancy protection; we are really
+ // protecting only against this one case, which actually comes up when
+ // you first install the SVG viewer plug-in.
+ if (inSetWindow)
+ return NO;
+
+ Frame* frame = core([self webFrame]);
+ if (!frame)
+ return NO;
+ Page* page = frame->page();
+ if (!page)
+ return NO;
+
+ bool wasDeferring = page->defersLoading();
+ if (!wasDeferring)
+ page->setDefersLoading(true);
+
+ // Can only send drawRect (updateEvt) to CoreGraphics plugins when actually drawing
+ ASSERT((drawingModel != NPDrawingModelCoreGraphics) || !eventIsDrawRect || [NSView focusView] == self);
+
+ PortState portState = NULL;
+
+ if (isDrawingModelQuickDraw(drawingModel) || (drawingModel != NPDrawingModelCoreAnimation && eventIsDrawRect)) {
+ // In CoreGraphics mode, the port state only needs to be saved/set when redrawing the plug-in view.
+ // The plug-in is not allowed to draw at any other time.
+ portState = [self saveAndSetNewPortStateForUpdate:eventIsDrawRect];
+ // We may have changed the window, so inform the plug-in.
+ [self setWindowIfNecessary];
+ }
+
+#if !defined(NDEBUG) && !defined(NP_NO_QUICKDRAW)
+ // Draw green to help debug.
+ // If we see any green we know something's wrong.
+ // Note that PaintRect() only works for QuickDraw plugins; otherwise the current QD port is undefined.
+ if (isDrawingModelQuickDraw(drawingModel) && eventIsDrawRect) {
+ ForeColor(greenColor);
+ const ::Rect bigRect = { -10000, -10000, 10000, 10000 };
+ PaintRect(&bigRect);
+ ForeColor(blackColor);
+ }
+#endif
+
+ // Temporarily retain self in case the plug-in view is released while sending an event.
+ [[self retain] autorelease];
+
+ BOOL acceptedEvent;
+ [self willCallPlugInFunction];
+ {
+ JSC::JSLock::DropAllLocks dropAllLocks(false);
+ acceptedEvent = ![_pluginPackage.get() pluginFuncs]->event(plugin, event);
+ }
+ [self didCallPlugInFunction];
+
+ if (portState) {
+ if ([self currentWindow])
+ [self restorePortState:portState];
+ if (portState != (PortState)1)
+ free(portState);
+ }
+
+ if (!wasDeferring)
+ page->setDefersLoading(false);
+
+ return acceptedEvent;
+}
+
+- (void)windowFocusChanged:(BOOL)hasFocus
+{
+ _eventHandler->windowFocusChanged(hasFocus);
+}
+
+- (void)sendDrawRectEvent:(NSRect)rect
+{
+ ASSERT(_eventHandler);
+
+ _eventHandler->drawRect(rect);
+}
+
+- (void)stopTimers
+{
+ [super stopTimers];
+
+ if (_eventHandler)
+ _eventHandler->stopTimers();
+
+ if (!timers)
+ return;
+
+ HashMap<uint32, PluginTimer*>::const_iterator end = timers->end();
+ for (HashMap<uint32, PluginTimer*>::const_iterator it = timers->begin(); it != end; ++it) {
+ PluginTimer* timer = it->second;
+ timer->stop();
+ }
+}
+
+- (void)startTimers
+{
+ [super startTimers];
+
+ // If the plugin is completely obscured (scrolled out of view, for example), then we will
+ // send null events at a reduced rate.
+ _eventHandler->startTimers(_isCompletelyObscured);
+
+ if (!timers)
+ return;
+
+ HashMap<uint32, PluginTimer*>::const_iterator end = timers->end();
+ for (HashMap<uint32, PluginTimer*>::const_iterator it = timers->begin(); it != end; ++it) {
+ PluginTimer* timer = it->second;
+ ASSERT(!timer->isActive());
+ timer->start(_isCompletelyObscured);
+ }
+}
+
+- (void)focusChanged
+{
+ // We need to null check the event handler here because
+ // the plug-in view can resign focus after it's been stopped
+ // and the event handler has been deleted.
+ if (_eventHandler)
+ _eventHandler->focusChanged(_hasFocus);
+}
+
+- (void)mouseDown:(NSEvent *)theEvent
+{
+ if (!_isStarted)
+ return;
+
+ _eventHandler->mouseDown(theEvent);
+}
+
+- (void)mouseUp:(NSEvent *)theEvent
+{
+ if (!_isStarted)
+ return;
+
+ _eventHandler->mouseUp(theEvent);
+}
+
+- (void)mouseEntered:(NSEvent *)theEvent
+{
+ if (!_isStarted)
+ return;
+
+ _eventHandler->mouseEntered(theEvent);
+}
+
+- (void)mouseExited:(NSEvent *)theEvent
+{
+ if (!_isStarted)
+ return;
+
+ _eventHandler->mouseExited(theEvent);
+
+ // Set cursor back to arrow cursor. Because NSCursor doesn't know about changes that the plugin made, we could get confused about what we think the
+ // current cursor is otherwise. Therefore we have no choice but to unconditionally reset the cursor when the mouse exits the plugin.
+ [[NSCursor arrowCursor] set];
+}
+
+// We can't name this method mouseMoved because we don't want to override
+// the NSView mouseMoved implementation.
+- (void)handleMouseMoved:(NSEvent *)theEvent
+{
+ if (!_isStarted)
+ return;
+
+ _eventHandler->mouseMoved(theEvent);
+}
+
+- (void)mouseDragged:(NSEvent *)theEvent
+{
+ if (!_isStarted)
+ return;
+
+ _eventHandler->mouseDragged(theEvent);
+}
+
+- (void)scrollWheel:(NSEvent *)theEvent
+{
+ if (!_isStarted) {
+ [super scrollWheel:theEvent];
+ return;
+ }
+
+ if (!_eventHandler->scrollWheel(theEvent))
+ [super scrollWheel:theEvent];
+}
+
+- (void)keyUp:(NSEvent *)theEvent
+{
+ if (!_isStarted)
+ return;
+
+ _eventHandler->keyUp(theEvent);
+}
+
+- (void)keyDown:(NSEvent *)theEvent
+{
+ if (!_isStarted)
+ return;
+
+ _eventHandler->keyDown(theEvent);
+}
+
+- (void)flagsChanged:(NSEvent *)theEvent
+{
+ if (!_isStarted)
+ return;
+
+ _eventHandler->flagsChanged(theEvent);
+}
+
+#pragma mark WEB_NETSCAPE_PLUGIN
+
+- (BOOL)isNewWindowEqualToOldWindow
+{
+ if (window.x != lastSetWindow.x)
+ return NO;
+ if (window.y != lastSetWindow.y)
+ return NO;
+ if (window.width != lastSetWindow.width)
+ return NO;
+ if (window.height != lastSetWindow.height)
+ return NO;
+ if (window.clipRect.top != lastSetWindow.clipRect.top)
+ return NO;
+ if (window.clipRect.left != lastSetWindow.clipRect.left)
+ return NO;
+ if (window.clipRect.bottom != lastSetWindow.clipRect.bottom)
+ return NO;
+ if (window.clipRect.right != lastSetWindow.clipRect.right)
+ return NO;
+ if (window.type != lastSetWindow.type)
+ return NO;
+
+ switch (drawingModel) {
+#ifndef NP_NO_QUICKDRAW
+ case NPDrawingModelQuickDraw:
+ if (nPort.qdPort.portx != lastSetPort.qdPort.portx)
+ return NO;
+ if (nPort.qdPort.porty != lastSetPort.qdPort.porty)
+ return NO;
+ if (nPort.qdPort.port != lastSetPort.qdPort.port)
+ return NO;
+ break;
+#endif /* NP_NO_QUICKDRAW */
+
+ case NPDrawingModelCoreGraphics:
+ if (nPort.cgPort.window != lastSetPort.cgPort.window)
+ return NO;
+ if (nPort.cgPort.context != lastSetPort.cgPort.context)
+ return NO;
+ break;
+
+ case NPDrawingModelCoreAnimation:
+ if (window.window != lastSetWindow.window)
+ return NO;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+ return YES;
+}
+
+-(void)tellQuickTimeToChill
+{
+#ifndef NP_NO_QUICKDRAW
+ ASSERT(isDrawingModelQuickDraw(drawingModel));
+
+ // Make a call to the secret QuickDraw API that makes QuickTime calm down.
+ WindowRef windowRef = (WindowRef)[[self window] windowRef];
+ if (!windowRef) {
+ return;
+ }
+ CGrafPtr port = GetWindowPort(windowRef);
+ ::Rect bounds;
+ GetPortBounds(port, &bounds);
+ WKCallDrawingNotification(port, &bounds);
+#endif /* NP_NO_QUICKDRAW */
+}
+
+- (void)updateAndSetWindow
+{
+ // A plug-in can only update if it's (1) already been started (2) isn't stopped
+ // and (3) is able to draw on-screen. To meet condition (3) the plug-in must not
+ // be hidden and be attached to a window. QuickDraw plug-ins are an important
+ // excpetion to rule (3) because they manually must be told when to stop writing
+ // bits to the window backing store, thus to do so requires a new call to
+ // NPP_SetWindow() with an empty NPWindow struct.
+ if (!_isStarted)
+ return;
+
+#ifdef NP_NO_QUICKDRAW
+ if (![self canDraw])
+ return;
+#else
+ if (drawingModel == NPDrawingModelQuickDraw)
+ [self tellQuickTimeToChill];
+ else if (drawingModel == NPDrawingModelCoreGraphics && ![self canDraw])
+ return;
+
+#endif // NP_NO_QUICKDRAW
+
+ BOOL didLockFocus = [NSView focusView] != self && [self lockFocusIfCanDraw];
+
+ PortState portState = [self saveAndSetNewPortState];
+ if (portState) {
+ [self setWindowIfNecessary];
+ [self restorePortState:portState];
+ if (portState != (PortState)1)
+ free(portState);
+ }
+ if (didLockFocus)
+ [self unlockFocus];
+}
+
+- (void)setWindowIfNecessary
+{
+ if (!_isStarted)
+ return;
+
+ if (![self isNewWindowEqualToOldWindow]) {
+ // Make sure we don't call NPP_HandleEvent while we're inside NPP_SetWindow.
+ // We probably don't want more general reentrancy protection; we are really
+ // protecting only against this one case, which actually comes up when
+ // you first install the SVG viewer plug-in.
+ NPError npErr;
+ ASSERT(!inSetWindow);
+
+ inSetWindow = YES;
+
+ // A CoreGraphics plugin's window may only be set while the plugin is being updated
+ ASSERT((drawingModel != NPDrawingModelCoreGraphics) || [NSView focusView] == self);
+
+ [self willCallPlugInFunction];
+ {
+ JSC::JSLock::DropAllLocks dropAllLocks(false);
+ npErr = [_pluginPackage.get() pluginFuncs]->setwindow(plugin, &window);
+ }
+ [self didCallPlugInFunction];
+ inSetWindow = NO;
+
+#ifndef NDEBUG
+ switch (drawingModel) {
+#ifndef NP_NO_QUICKDRAW
+ case NPDrawingModelQuickDraw:
+ LOG(Plugins, "NPP_SetWindow (QuickDraw): %d, port=0x%08x, window.x:%d window.y:%d window.width:%d window.height:%d",
+ npErr, (int)nPort.qdPort.port, (int)window.x, (int)window.y, (int)window.width, (int)window.height);
+ break;
+#endif /* NP_NO_QUICKDRAW */
+
+ case NPDrawingModelCoreGraphics:
+ LOG(Plugins, "NPP_SetWindow (CoreGraphics): %d, window=%p, context=%p, window.x:%d window.y:%d window.width:%d window.height:%d",
+ npErr, nPort.cgPort.window, nPort.cgPort.context, (int)window.x, (int)window.y, (int)window.width, (int)window.height);
+ break;
+
+ case NPDrawingModelCoreAnimation:
+ LOG(Plugins, "NPP_SetWindow (CoreAnimation): %d, window=%p window.x:%d window.y:%d window.width:%d window.height:%d",
+ npErr, window.window, nPort.cgPort.context, (int)window.x, (int)window.y, (int)window.width, (int)window.height);
+ break;
+
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+#endif /* !defined(NDEBUG) */
+
+ lastSetWindow = window;
+ lastSetPort = nPort;
+ }
+}
+
++ (void)setCurrentPluginView:(WebNetscapePluginView *)view
+{
+ currentPluginView = view;
+}
+
++ (WebNetscapePluginView *)currentPluginView
+{
+ return currentPluginView;
+}
+
+- (BOOL)createPlugin
+{
+ // Open the plug-in package so it remains loaded while our plugin uses it
+ [_pluginPackage.get() open];
+
+ // Initialize drawingModel to an invalid value so that we can detect when the plugin does not specify a drawingModel
+ drawingModel = (NPDrawingModel)-1;
+
+ // Initialize eventModel to an invalid value so that we can detect when the plugin does not specify an event model.
+ eventModel = (NPEventModel)-1;
+
+ NPError npErr = [self _createPlugin];
+ if (npErr != NPERR_NO_ERROR) {
+ LOG_ERROR("NPP_New failed with error: %d", npErr);
+ [self _destroyPlugin];
+ [_pluginPackage.get() close];
+ return NO;
+ }
+
+ if (drawingModel == (NPDrawingModel)-1) {
+#ifndef NP_NO_QUICKDRAW
+ // Default to QuickDraw if the plugin did not specify a drawing model.
+ drawingModel = NPDrawingModelQuickDraw;
+#else
+ // QuickDraw is not available, so we can't default to it. Instead, default to CoreGraphics.
+ drawingModel = NPDrawingModelCoreGraphics;
+#endif
+ }
+
+ if (eventModel == (NPEventModel)-1) {
+ // If the plug-in did not specify a drawing model we default to Carbon when it is available.
+#ifndef NP_NO_CARBON
+ eventModel = NPEventModelCarbon;
+#else
+ eventModel = NPEventModelCocoa;
+#endif // NP_NO_CARBON
+ }
+
+#ifndef NP_NO_CARBON
+ if (eventModel == NPEventModelCocoa && isDrawingModelQuickDraw(drawingModel)) {
+ LOG(Plugins, "Plugin can't use use Cocoa event model with QuickDraw drawing model: %@", _pluginPackage.get());
+ [self _destroyPlugin];
+ [_pluginPackage.get() close];
+
+ return NO;
+ }
+#endif // NP_NO_CARBON
+
+#ifndef BUILDING_ON_TIGER
+ if (drawingModel == NPDrawingModelCoreAnimation) {
+ void *value = 0;
+ if ([_pluginPackage.get() pluginFuncs]->getvalue(plugin, NPPVpluginCoreAnimationLayer, &value) == NPERR_NO_ERROR && value) {
+
+ // The plug-in gives us a retained layer.
+ _pluginLayer.adoptNS((CALayer *)value);
+ [self setWantsLayer:YES];
+ LOG(Plugins, "%@ is using Core Animation drawing model with layer %@", _pluginPackage.get(), _pluginLayer.get());
+ }
+
+ ASSERT(_pluginLayer);
+ }
+#endif
+
+ // Create the event handler
+ _eventHandler.set(WebNetscapePluginEventHandler::create(self));
+
+ // Get the text input vtable
+ if (eventModel == NPEventModelCocoa) {
+ [self willCallPlugInFunction];
+ {
+ JSC::JSLock::DropAllLocks dropAllLocks(false);
+ NPPluginTextInputFuncs *value = 0;
+ if (![_pluginPackage.get() pluginFuncs]->getvalue(plugin, NPPVpluginTextInputFuncs, &value) == NPERR_NO_ERROR && value)
+ textInputFuncs = value;
+ }
+ [self didCallPlugInFunction];
+ }
+
+ return YES;
+}
+
+#ifndef BUILDING_ON_TIGER
+- (void)setLayer:(CALayer *)newLayer
+{
+ [super setLayer:newLayer];
+
+ if (_pluginLayer)
+ [newLayer addSublayer:_pluginLayer.get()];
+}
+#endif
+
+- (void)loadStream
+{
+ if (_loadManually) {
+ [self _redeliverStream];
+ return;
+ }
+
+ // If the OBJECT/EMBED tag has no SRC, the URL is passed to us as "".
+ // Check for this and don't start a load in this case.
+ if (_sourceURL && ![_sourceURL.get() _web_isEmpty]) {
+ NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:_sourceURL.get()];
+ [request _web_setHTTPReferrer:core([self webFrame])->loader()->outgoingReferrer()];
+ [self loadRequest:request inTarget:nil withNotifyData:nil sendNotification:NO];
+ }
+}
+
+- (BOOL)shouldStop
+{
+ // If we're already calling a plug-in function, do not call NPP_Destroy(). The plug-in function we are calling
+ // may assume that its instance->pdata, or other memory freed by NPP_Destroy(), is valid and unchanged until said
+ // plugin-function returns.
+ // See <rdar://problem/4480737>.
+ if (pluginFunctionCallDepth > 0) {
+ shouldStopSoon = YES;
+ return NO;
+ }
+
+ return YES;
+}
+
+- (void)destroyPlugin
+{
+ // To stop active streams it's necessary to invoke stop() on a copy
+ // of streams. This is because calling WebNetscapePluginStream::stop() also has the side effect
+ // of removing a stream from this hash set.
+ Vector<RefPtr<WebNetscapePluginStream> > streamsCopy;
+ copyToVector(streams, streamsCopy);
+ for (size_t i = 0; i < streamsCopy.size(); i++)
+ streamsCopy[i]->stop();
+
+ [[_pendingFrameLoads.get() allKeys] makeObjectsPerformSelector:@selector(_setInternalLoadDelegate:) withObject:nil];
+ [NSObject cancelPreviousPerformRequestsWithTarget:self];
+
+ // Setting the window type to 0 ensures that NPP_SetWindow will be called if the plug-in is restarted.
+ lastSetWindow.type = (NPWindowType)0;
+
+#ifndef BUILDING_ON_TIGER
+ _pluginLayer = 0;
+#endif
+
+ [self _destroyPlugin];
+ [_pluginPackage.get() close];
+
+ _eventHandler.clear();
+
+ textInputFuncs = 0;
+}
+
+- (NPEventModel)eventModel
+{
+ return eventModel;
+}
+
+- (NPP)plugin
+{
+ return plugin;
+}
+
+- (void)setAttributeKeys:(NSArray *)keys andValues:(NSArray *)values;
+{
+ ASSERT([keys count] == [values count]);
+
+ // Convert the attributes to 2 C string arrays.
+ // These arrays are passed to NPP_New, but the strings need to be
+ // modifiable and live the entire life of the plugin.
+
+ // The Java plug-in requires the first argument to be the base URL
+ if ([_MIMEType.get() isEqualToString:@"application/x-java-applet"]) {
+ cAttributes = (char **)malloc(([keys count] + 1) * sizeof(char *));
+ cValues = (char **)malloc(([values count] + 1) * sizeof(char *));
+ cAttributes[0] = strdup("DOCBASE");
+ cValues[0] = strdup([_baseURL.get() _web_URLCString]);
+ argsCount++;
+ } else {
+ cAttributes = (char **)malloc([keys count] * sizeof(char *));
+ cValues = (char **)malloc([values count] * sizeof(char *));
+ }
+
+ BOOL isWMP = [[[_pluginPackage.get() bundle] bundleIdentifier] isEqualToString:@"com.microsoft.WMP.defaultplugin"];
+
+ unsigned i;
+ unsigned count = [keys count];
+ for (i = 0; i < count; i++) {
+ NSString *key = [keys objectAtIndex:i];
+ NSString *value = [values objectAtIndex:i];
+ if ([key _webkit_isCaseInsensitiveEqualToString:@"height"]) {
+ specifiedHeight = [value intValue];
+ } else if ([key _webkit_isCaseInsensitiveEqualToString:@"width"]) {
+ specifiedWidth = [value intValue];
+ }
+ // Avoid Window Media Player crash when these attributes are present.
+ if (isWMP && ([key _webkit_isCaseInsensitiveEqualToString:@"SAMIStyle"] || [key _webkit_isCaseInsensitiveEqualToString:@"SAMILang"])) {
+ continue;
+ }
+ cAttributes[argsCount] = strdup([key UTF8String]);
+ cValues[argsCount] = strdup([value UTF8String]);
+ LOG(Plugins, "%@ = %@", key, value);
+ argsCount++;
+ }
+}
+
+#pragma mark NSVIEW
+
+- (id)initWithFrame:(NSRect)frame
+ pluginPackage:(WebNetscapePluginPackage *)pluginPackage
+ URL:(NSURL *)URL
+ baseURL:(NSURL *)baseURL
+ MIMEType:(NSString *)MIME
+ attributeKeys:(NSArray *)keys
+ attributeValues:(NSArray *)values
+ loadManually:(BOOL)loadManually
+ DOMElement:(DOMElement *)element
+{
+ self = [super initWithFrame:frame pluginPackage:pluginPackage URL:URL baseURL:baseURL MIMEType:MIME attributeKeys:keys attributeValues:values loadManually:loadManually DOMElement:element];
+ if (!self)
+ return nil;
+
+ _pendingFrameLoads.adoptNS([[NSMutableDictionary alloc] init]);
+
+ // load the plug-in if it is not already loaded
+ if (![pluginPackage load]) {
+ [self release];
+ return nil;
+ }
+
+ return self;
+}
+
+- (id)initWithFrame:(NSRect)frame
+{
+ ASSERT_NOT_REACHED();
+ return nil;
+}
+
+- (void)fini
+{
+#ifndef NP_NO_QUICKDRAW
+ if (offscreenGWorld)
+ DisposeGWorld(offscreenGWorld);
+#endif
+
+ for (unsigned i = 0; i < argsCount; i++) {
+ free(cAttributes[i]);
+ free(cValues[i]);
+ }
+ free(cAttributes);
+ free(cValues);
+
+ ASSERT(!_eventHandler);
+
+ if (timers) {
+ deleteAllValues(*timers);
+ delete timers;
+ }
+}
+
+- (void)disconnectStream:(WebNetscapePluginStream*)stream
+{
+ streams.remove(stream);
+}
+
+- (void)dealloc
+{
+ ASSERT(!_isStarted);
+ ASSERT(!plugin);
+
+ [self fini];
+
+ [super dealloc];
+}
+
+- (void)finalize
+{
+ ASSERT_MAIN_THREAD();
+ ASSERT(!_isStarted);
+
+ [self fini];
+
+ [super finalize];
+}
+
+- (void)drawRect:(NSRect)rect
+{
+ if (drawingModel == NPDrawingModelCoreAnimation)
+ return;
+
+ if (!_isStarted)
+ return;
+
+ if ([NSGraphicsContext currentContextDrawingToScreen])
+ [self sendDrawRectEvent:rect];
+ else {
+ NSBitmapImageRep *printedPluginBitmap = [self _printedPluginBitmap];
+ if (printedPluginBitmap) {
+ // Flip the bitmap before drawing because the QuickDraw port is flipped relative
+ // to this view.
+ CGContextRef cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
+ CGContextSaveGState(cgContext);
+ NSRect bounds = [self bounds];
+ CGContextTranslateCTM(cgContext, 0.0f, NSHeight(bounds));
+ CGContextScaleCTM(cgContext, 1.0f, -1.0f);
+ [printedPluginBitmap drawInRect:bounds];
+ CGContextRestoreGState(cgContext);
+ }
+ }
+}
+
+- (NPObject *)createPluginScriptableObject
+{
+ if (![_pluginPackage.get() pluginFuncs]->getvalue || !_isStarted)
+ return NULL;
+
+ NPObject *value = NULL;
+ NPError error;
+ [self willCallPlugInFunction];
+ {
+ JSC::JSLock::DropAllLocks dropAllLocks(false);
+ error = [_pluginPackage.get() pluginFuncs]->getvalue(plugin, NPPVpluginScriptableNPObject, &value);
+ }
+ [self didCallPlugInFunction];
+ if (error != NPERR_NO_ERROR)
+ return NULL;
+
+ return value;
+}
+
+- (void)willCallPlugInFunction
+{
+ ASSERT(plugin);
+
+ // Could try to prevent infinite recursion here, but it's probably not worth the effort.
+ pluginFunctionCallDepth++;
+}
+
+- (void)didCallPlugInFunction
+{
+ ASSERT(pluginFunctionCallDepth > 0);
+ pluginFunctionCallDepth--;
+
+ // If -stop was called while we were calling into a plug-in function, and we're no longer
+ // inside a plug-in function, stop now.
+ if (pluginFunctionCallDepth == 0 && shouldStopSoon) {
+ shouldStopSoon = NO;
+ [self stop];
+ }
+}
+
+-(void)pluginView:(NSView *)pluginView receivedResponse:(NSURLResponse *)response
+{
+ ASSERT(_loadManually);
+ ASSERT(!_manualStream);
+
+ _manualStream = WebNetscapePluginStream::create(core([self webFrame])->loader());
+}
+
+- (void)pluginView:(NSView *)pluginView receivedData:(NSData *)data
+{
+ ASSERT(_loadManually);
+ ASSERT(_manualStream);
+
+ _dataLengthReceived += [data length];
+
+ if (!_isStarted)
+ return;
+
+ if (!_manualStream->plugin()) {
+
+ _manualStream->setRequestURL([[[self dataSource] request] URL]);
+ _manualStream->setPlugin([self plugin]);
+ ASSERT(_manualStream->plugin());
+
+ _manualStream->startStreamWithResponse([[self dataSource] response]);
+ }
+
+ if (_manualStream->plugin())
+ _manualStream->didReceiveData(0, static_cast<const char *>([data bytes]), [data length]);
+}
+
+- (void)pluginView:(NSView *)pluginView receivedError:(NSError *)error
+{
+ ASSERT(_loadManually);
+
+ _error = error;
+
+ if (!_isStarted) {
+ return;
+ }
+
+ _manualStream->destroyStreamWithError(error);
+}
+
+- (void)pluginViewFinishedLoading:(NSView *)pluginView
+{
+ ASSERT(_loadManually);
+ ASSERT(_manualStream);
+
+ if (_isStarted)
+ _manualStream->didFinishLoading(0);
+}
+
+#pragma mark NSTextInput implementation
+
+- (NSTextInputContext *)inputContext
+{
+#ifndef NP_NO_CARBON
+ if (!_isStarted || eventModel == NPEventModelCarbon)
+ return nil;
+#endif
+
+ return [super inputContext];
+}
+
+- (BOOL)hasMarkedText
+{
+ ASSERT(eventModel == NPEventModelCocoa);
+ ASSERT(_isStarted);
+
+ if (textInputFuncs && textInputFuncs->hasMarkedText)
+ return textInputFuncs->hasMarkedText(plugin);
+
+ return NO;
+}
+
+- (void)insertText:(id)aString
+{
+ ASSERT(eventModel == NPEventModelCocoa);
+ ASSERT(_isStarted);
+
+ if (textInputFuncs && textInputFuncs->insertText)
+ textInputFuncs->insertText(plugin, aString);
+}
+
+- (NSRange)markedRange
+{
+ ASSERT(eventModel == NPEventModelCocoa);
+ ASSERT(_isStarted);
+
+ if (textInputFuncs && textInputFuncs->markedRange)
+ return textInputFuncs->markedRange(plugin);
+
+ return NSMakeRange(NSNotFound, 0);
+}
+
+- (NSRange)selectedRange
+{
+ ASSERT(eventModel == NPEventModelCocoa);
+ ASSERT(_isStarted);
+
+ if (textInputFuncs && textInputFuncs->selectedRange)
+ return textInputFuncs->selectedRange(plugin);
+
+ return NSMakeRange(NSNotFound, 0);
+}
+
+- (void)setMarkedText:(id)aString selectedRange:(NSRange)selRange
+{
+ ASSERT(eventModel == NPEventModelCocoa);
+ ASSERT(_isStarted);
+
+ if (textInputFuncs && textInputFuncs->setMarkedText)
+ textInputFuncs->setMarkedText(plugin, aString, selRange);
+}
+
+- (void)unmarkText
+{
+ ASSERT(eventModel == NPEventModelCocoa);
+ ASSERT(_isStarted);
+
+ if (textInputFuncs && textInputFuncs->unmarkText)
+ textInputFuncs->unmarkText(plugin);
+}
+
+- (NSArray *)validAttributesForMarkedText
+{
+ ASSERT(eventModel == NPEventModelCocoa);
+ ASSERT(_isStarted);
+
+ if (textInputFuncs && textInputFuncs->validAttributesForMarkedText)
+ return textInputFuncs->validAttributesForMarkedText(plugin);
+
+ return [NSArray array];
+}
+
+- (NSAttributedString *)attributedSubstringFromRange:(NSRange)theRange
+{
+ ASSERT(eventModel == NPEventModelCocoa);
+ ASSERT(_isStarted);
+
+ if (textInputFuncs && textInputFuncs->attributedSubstringFromRange)
+ return textInputFuncs->attributedSubstringFromRange(plugin, theRange);
+
+ return nil;
+}
+
+- (NSUInteger)characterIndexForPoint:(NSPoint)thePoint
+{
+ ASSERT(eventModel == NPEventModelCocoa);
+ ASSERT(_isStarted);
+
+ if (textInputFuncs && textInputFuncs->characterIndexForPoint) {
+ // Convert the point to window coordinates
+ NSPoint point = [[self window] convertScreenToBase:thePoint];
+
+ // And view coordinates
+ point = [self convertPoint:point fromView:nil];
+
+ return textInputFuncs->characterIndexForPoint(plugin, point);
+ }
+
+ return NSNotFound;
+}
+
+- (void)doCommandBySelector:(SEL)aSelector
+{
+ ASSERT(eventModel == NPEventModelCocoa);
+ ASSERT(_isStarted);
+
+ if (textInputFuncs && textInputFuncs->doCommandBySelector)
+ textInputFuncs->doCommandBySelector(plugin, aSelector);
+}
+
+- (NSRect)firstRectForCharacterRange:(NSRange)theRange
+{
+ ASSERT(eventModel == NPEventModelCocoa);
+ ASSERT(_isStarted);
+
+ if (textInputFuncs && textInputFuncs->firstRectForCharacterRange) {
+ NSRect rect = textInputFuncs->firstRectForCharacterRange(plugin, theRange);
+
+ // Convert the rect to window coordinates
+ rect = [self convertRect:rect toView:nil];
+
+ // Convert the rect location to screen coordinates
+ rect.origin = [[self window] convertBaseToScreen:rect.origin];
+
+ return rect;
+ }
+
+ return NSZeroRect;
+}
+
+// test for 10.4 because of <rdar://problem/4243463>
+#ifdef BUILDING_ON_TIGER
+- (long)conversationIdentifier
+{
+ return (long)self;
+}
+#else
+- (NSInteger)conversationIdentifier
+{
+ return (NSInteger)self;
+}
+#endif
+
+@end
+
+@implementation WebNetscapePluginView (WebNPPCallbacks)
+
+- (void)evaluateJavaScriptPluginRequest:(WebPluginRequest *)JSPluginRequest
+{
+ // FIXME: Is this isStarted check needed here? evaluateJavaScriptPluginRequest should not be called
+ // if we are stopped since this method is called after a delay and we call
+ // cancelPreviousPerformRequestsWithTarget inside of stop.
+ if (!_isStarted) {
+ return;
+ }
+
+ NSURL *URL = [[JSPluginRequest request] URL];
+ NSString *JSString = [URL _webkit_scriptIfJavaScriptURL];
+ ASSERT(JSString);
+
+ NSString *result = [[self webFrame] _stringByEvaluatingJavaScriptFromString:JSString forceUserGesture:[JSPluginRequest isCurrentEventUserGesture]];
+
+ // Don't continue if stringByEvaluatingJavaScriptFromString caused the plug-in to stop.
+ if (!_isStarted) {
+ return;
+ }
+
+ if ([JSPluginRequest frameName] != nil) {
+ // FIXME: If the result is a string, we probably want to put that string into the frame.
+ if ([JSPluginRequest sendNotification]) {
+ [self willCallPlugInFunction];
+ {
+ JSC::JSLock::DropAllLocks dropAllLocks(false);
+ [_pluginPackage.get() pluginFuncs]->urlnotify(plugin, [URL _web_URLCString], NPRES_DONE, [JSPluginRequest notifyData]);
+ }
+ [self didCallPlugInFunction];
+ }
+ } else if ([result length] > 0) {
+ // Don't call NPP_NewStream and other stream methods if there is no JS result to deliver. This is what Mozilla does.
+ NSData *JSData = [result dataUsingEncoding:NSUTF8StringEncoding];
+
+ RefPtr<WebNetscapePluginStream> stream = WebNetscapePluginStream::create([NSURLRequest requestWithURL:URL], plugin, [JSPluginRequest sendNotification], [JSPluginRequest notifyData]);
+
+ RetainPtr<NSURLResponse> response(AdoptNS, [[NSURLResponse alloc] initWithURL:URL
+ MIMEType:@"text/plain"
+ expectedContentLength:[JSData length]
+ textEncodingName:nil]);
+
+ stream->startStreamWithResponse(response.get());
+ stream->didReceiveData(0, static_cast<const char*>([JSData bytes]), [JSData length]);
+ stream->didFinishLoading(0);
+ }
+}
+
+- (void)webFrame:(WebFrame *)webFrame didFinishLoadWithReason:(NPReason)reason
+{
+ ASSERT(_isStarted);
+
+ WebPluginRequest *pluginRequest = [_pendingFrameLoads.get() objectForKey:webFrame];
+ ASSERT(pluginRequest != nil);
+ ASSERT([pluginRequest sendNotification]);
+
+ [self willCallPlugInFunction];
+ {
+ JSC::JSLock::DropAllLocks dropAllLocks(false);
+ [_pluginPackage.get() pluginFuncs]->urlnotify(plugin, [[[pluginRequest request] URL] _web_URLCString], reason, [pluginRequest notifyData]);
+ }
+ [self didCallPlugInFunction];
+
+ [_pendingFrameLoads.get() removeObjectForKey:webFrame];
+ [webFrame _setInternalLoadDelegate:nil];
+}
+
+- (void)webFrame:(WebFrame *)webFrame didFinishLoadWithError:(NSError *)error
+{
+ NPReason reason = NPRES_DONE;
+ if (error != nil)
+ reason = WebNetscapePluginStream::reasonForError(error);
+ [self webFrame:webFrame didFinishLoadWithReason:reason];
+}
+
+- (void)loadPluginRequest:(WebPluginRequest *)pluginRequest
+{
+ NSURLRequest *request = [pluginRequest request];
+ NSString *frameName = [pluginRequest frameName];
+ WebFrame *frame = nil;
+
+ NSURL *URL = [request URL];
+ NSString *JSString = [URL _webkit_scriptIfJavaScriptURL];
+
+ ASSERT(frameName || JSString);
+
+ if (frameName) {
+ // FIXME - need to get rid of this window creation which
+ // bypasses normal targeted link handling
+ frame = kit(core([self webFrame])->loader()->findFrameForNavigation(frameName));
+ if (frame == nil) {
+ WebView *currentWebView = [self webView];
+ NSDictionary *features = [[NSDictionary alloc] init];
+ WebView *newWebView = [[currentWebView _UIDelegateForwarder] webView:currentWebView
+ createWebViewWithRequest:nil
+ windowFeatures:features];
+ [features release];
+
+ if (!newWebView) {
+ if ([pluginRequest sendNotification]) {
+ [self willCallPlugInFunction];
+ {
+ JSC::JSLock::DropAllLocks dropAllLocks(false);
+ [_pluginPackage.get() pluginFuncs]->urlnotify(plugin, [[[pluginRequest request] URL] _web_URLCString], NPERR_GENERIC_ERROR, [pluginRequest notifyData]);
+ }
+ [self didCallPlugInFunction];
+ }
+ return;
+ }
+
+ frame = [newWebView mainFrame];
+ core(frame)->tree()->setName(frameName);
+ [[newWebView _UIDelegateForwarder] webViewShow:newWebView];
+ }
+ }
+
+ if (JSString) {
+ ASSERT(frame == nil || [self webFrame] == frame);
+ [self evaluateJavaScriptPluginRequest:pluginRequest];
+ } else {
+ [frame loadRequest:request];
+ if ([pluginRequest sendNotification]) {
+ // Check if another plug-in view or even this view is waiting for the frame to load.
+ // If it is, tell it that the load was cancelled because it will be anyway.
+ WebNetscapePluginView *view = [frame _internalLoadDelegate];
+ if (view != nil) {
+ ASSERT([view isKindOfClass:[WebNetscapePluginView class]]);
+ [view webFrame:frame didFinishLoadWithReason:NPRES_USER_BREAK];
+ }
+ [_pendingFrameLoads.get() _webkit_setObject:pluginRequest forUncopiedKey:frame];
+ [frame _setInternalLoadDelegate:self];
+ }
+ }
+}
+
+- (NPError)loadRequest:(NSMutableURLRequest *)request inTarget:(const char *)cTarget withNotifyData:(void *)notifyData sendNotification:(BOOL)sendNotification
+{
+ NSURL *URL = [request URL];
+
+ if (!URL)
+ return NPERR_INVALID_URL;
+
+ // Don't allow requests to be loaded when the document loader is stopping all loaders.
+ if ([[self dataSource] _documentLoader]->isStopping())
+ return NPERR_GENERIC_ERROR;
+
+ NSString *target = nil;
+ if (cTarget) {
+ // Find the frame given the target string.
+ target = [NSString stringWithCString:cTarget encoding:NSISOLatin1StringEncoding];
+ }
+ WebFrame *frame = [self webFrame];
+
+ // don't let a plugin start any loads if it is no longer part of a document that is being
+ // displayed unless the loads are in the same frame as the plugin.
+ if ([[self dataSource] _documentLoader] != core([self webFrame])->loader()->activeDocumentLoader() &&
+ (!cTarget || [frame findFrameNamed:target] != frame)) {
+ return NPERR_GENERIC_ERROR;
+ }
+
+ NSString *JSString = [URL _webkit_scriptIfJavaScriptURL];
+ if (JSString != nil) {
+ if (![[[self webView] preferences] isJavaScriptEnabled]) {
+ // Return NPERR_GENERIC_ERROR if JS is disabled. This is what Mozilla does.
+ return NPERR_GENERIC_ERROR;
+ } else if (cTarget == NULL && _mode == NP_FULL) {
+ // Don't allow a JavaScript request from a standalone plug-in that is self-targetted
+ // because this can cause the user to be redirected to a blank page (3424039).
+ return NPERR_INVALID_PARAM;
+ }
+ } else {
+ if (!FrameLoader::canLoad(URL, String(), core([self webFrame])->document()))
+ return NPERR_GENERIC_ERROR;
+ }
+
+ if (cTarget || JSString) {
+ // Make when targetting a frame or evaluating a JS string, perform the request after a delay because we don't
+ // want to potentially kill the plug-in inside of its URL request.
+
+ if (JSString && target && [frame findFrameNamed:target] != frame) {
+ // For security reasons, only allow JS requests to be made on the frame that contains the plug-in.
+ return NPERR_INVALID_PARAM;
+ }
+
+ bool currentEventIsUserGesture = false;
+ if (_eventHandler)
+ currentEventIsUserGesture = _eventHandler->currentEventIsUserGesture();
+
+ WebPluginRequest *pluginRequest = [[WebPluginRequest alloc] initWithRequest:request
+ frameName:target
+ notifyData:notifyData
+ sendNotification:sendNotification
+ didStartFromUserGesture:currentEventIsUserGesture];
+ [self performSelector:@selector(loadPluginRequest:) withObject:pluginRequest afterDelay:0];
+ [pluginRequest release];
+ } else {
+ RefPtr<WebNetscapePluginStream> stream = WebNetscapePluginStream::create(request, plugin, sendNotification, notifyData);
+
+ streams.add(stream.get());
+ stream->start();
+ }
+
+ return NPERR_NO_ERROR;
+}
+
+-(NPError)getURLNotify:(const char *)URLCString target:(const char *)cTarget notifyData:(void *)notifyData
+{
+ LOG(Plugins, "NPN_GetURLNotify: %s target: %s", URLCString, cTarget);
+
+ NSMutableURLRequest *request = [self requestWithURLCString:URLCString];
+ return [self loadRequest:request inTarget:cTarget withNotifyData:notifyData sendNotification:YES];
+}
+
+-(NPError)getURL:(const char *)URLCString target:(const char *)cTarget
+{
+ LOG(Plugins, "NPN_GetURL: %s target: %s", URLCString, cTarget);
+
+ NSMutableURLRequest *request = [self requestWithURLCString:URLCString];
+ return [self loadRequest:request inTarget:cTarget withNotifyData:NULL sendNotification:NO];
+}
+
+- (NPError)_postURL:(const char *)URLCString
+ target:(const char *)target
+ len:(UInt32)len
+ buf:(const char *)buf
+ file:(NPBool)file
+ notifyData:(void *)notifyData
+ sendNotification:(BOOL)sendNotification
+ allowHeaders:(BOOL)allowHeaders
+{
+ if (!URLCString || !len || !buf) {
+ return NPERR_INVALID_PARAM;
+ }
+
+ NSData *postData = nil;
+
+ if (file) {
+ // If we're posting a file, buf is either a file URL or a path to the file.
+ NSString *bufString = (NSString *)CFStringCreateWithCString(kCFAllocatorDefault, buf, kCFStringEncodingWindowsLatin1);
+ if (!bufString) {
+ return NPERR_INVALID_PARAM;
+ }
+ NSURL *fileURL = [NSURL _web_URLWithDataAsString:bufString];
+ NSString *path;
+ if ([fileURL isFileURL]) {
+ path = [fileURL path];
+ } else {
+ path = bufString;
+ }
+ postData = [NSData dataWithContentsOfFile:[path _webkit_fixedCarbonPOSIXPath]];
+ CFRelease(bufString);
+ if (!postData) {
+ return NPERR_FILE_NOT_FOUND;
+ }
+ } else {
+ postData = [NSData dataWithBytes:buf length:len];
+ }
+
+ if ([postData length] == 0) {
+ return NPERR_INVALID_PARAM;
+ }
+
+ NSMutableURLRequest *request = [self requestWithURLCString:URLCString];
+ [request setHTTPMethod:@"POST"];
+
+ if (allowHeaders) {
+ if ([postData _web_startsWithBlankLine]) {
+ postData = [postData subdataWithRange:NSMakeRange(1, [postData length] - 1)];
+ } else {
+ NSInteger location = [postData _web_locationAfterFirstBlankLine];
+ if (location != NSNotFound) {
+ // If the blank line is somewhere in the middle of postData, everything before is the header.
+ NSData *headerData = [postData subdataWithRange:NSMakeRange(0, location)];
+ NSMutableDictionary *header = [headerData _webkit_parseRFC822HeaderFields];
+ unsigned dataLength = [postData length] - location;
+
+ // Sometimes plugins like to set Content-Length themselves when they post,
+ // but WebFoundation does not like that. So we will remove the header
+ // and instead truncate the data to the requested length.
+ NSString *contentLength = [header objectForKey:@"Content-Length"];
+
+ if (contentLength != nil)
+ dataLength = MIN((unsigned)[contentLength intValue], dataLength);
+ [header removeObjectForKey:@"Content-Length"];
+
+ if ([header count] > 0) {
+ [request setAllHTTPHeaderFields:header];
+ }
+ // Everything after the blank line is the actual content of the POST.
+ postData = [postData subdataWithRange:NSMakeRange(location, dataLength)];
+
+ }
+ }
+ if ([postData length] == 0) {
+ return NPERR_INVALID_PARAM;
+ }
+ }
+
+ // Plug-ins expect to receive uncached data when doing a POST (3347134).
+ [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
+ [request setHTTPBody:postData];
+
+ return [self loadRequest:request inTarget:target withNotifyData:notifyData sendNotification:sendNotification];
+}
+
+- (NPError)postURLNotify:(const char *)URLCString
+ target:(const char *)target
+ len:(UInt32)len
+ buf:(const char *)buf
+ file:(NPBool)file
+ notifyData:(void *)notifyData
+{
+ LOG(Plugins, "NPN_PostURLNotify: %s", URLCString);
+ return [self _postURL:URLCString target:target len:len buf:buf file:file notifyData:notifyData sendNotification:YES allowHeaders:YES];
+}
+
+-(NPError)postURL:(const char *)URLCString
+ target:(const char *)target
+ len:(UInt32)len
+ buf:(const char *)buf
+ file:(NPBool)file
+{
+ LOG(Plugins, "NPN_PostURL: %s", URLCString);
+ // As documented, only allow headers to be specified via NPP_PostURL when using a file.
+ return [self _postURL:URLCString target:target len:len buf:buf file:file notifyData:NULL sendNotification:NO allowHeaders:file];
+}
+
+-(NPError)newStream:(NPMIMEType)type target:(const char *)target stream:(NPStream**)stream
+{
+ LOG(Plugins, "NPN_NewStream");
+ return NPERR_GENERIC_ERROR;
+}
+
+-(NPError)write:(NPStream*)stream len:(SInt32)len buffer:(void *)buffer
+{
+ LOG(Plugins, "NPN_Write");
+ return NPERR_GENERIC_ERROR;
+}
+
+-(NPError)destroyStream:(NPStream*)stream reason:(NPReason)reason
+{
+ LOG(Plugins, "NPN_DestroyStream");
+ // This function does a sanity check to ensure that the NPStream provided actually
+ // belongs to the plug-in that provided it, which fixes a crash in the DivX
+ // plug-in: <rdar://problem/5093862> | http://bugs.webkit.org/show_bug.cgi?id=13203
+ if (!stream || WebNetscapePluginStream::ownerForStream(stream) != plugin) {
+ LOG(Plugins, "Invalid NPStream passed to NPN_DestroyStream: %p", stream);
+ return NPERR_INVALID_INSTANCE_ERROR;
+ }
+
+ WebNetscapePluginStream* browserStream = static_cast<WebNetscapePluginStream*>(stream->ndata);
+ browserStream->cancelLoadAndDestroyStreamWithError(browserStream->errorForReason(reason));
+
+ return NPERR_NO_ERROR;
+}
+
+- (const char *)userAgent
+{
+ NSString *userAgent = [[self webView] userAgentForURL:_baseURL.get()];
+
+ if (_isSilverlight) {
+ // Silverlight has a workaround for a leak in Safari 2. This workaround is
+ // applied when the user agent does not contain "Version/3" so we append it
+ // at the end of the user agent.
+ userAgent = [userAgent stringByAppendingString:@" Version/3.2.1"];
+ }
+
+ return [userAgent UTF8String];
+}
+
+-(void)status:(const char *)message
+{
+ if (!message) {
+ LOG_ERROR("NPN_Status passed a NULL status message");
+ return;
+ }
+
+ CFStringRef status = CFStringCreateWithCString(NULL, message, kCFStringEncodingUTF8);
+ if (!status) {
+ LOG_ERROR("NPN_Status: the message was not valid UTF-8");
+ return;
+ }
+
+ LOG(Plugins, "NPN_Status: %@", status);
+ WebView *wv = [self webView];
+ [[wv _UIDelegateForwarder] webView:wv setStatusText:(NSString *)status];
+ CFRelease(status);
+}
+
+-(void)invalidateRect:(NPRect *)invalidRect
+{
+ LOG(Plugins, "NPN_InvalidateRect");
+ [self setNeedsDisplayInRect:NSMakeRect(invalidRect->left, invalidRect->top,
+ (float)invalidRect->right - invalidRect->left, (float)invalidRect->bottom - invalidRect->top)];
+}
+
+-(BOOL)isOpaque
+{
+ return YES;
+}
+
+- (void)invalidateRegion:(NPRegion)invalidRegion
+{
+ LOG(Plugins, "NPN_InvalidateRegion");
+ NSRect invalidRect = NSZeroRect;
+ switch (drawingModel) {
+#ifndef NP_NO_QUICKDRAW
+ case NPDrawingModelQuickDraw:
+ {
+ ::Rect qdRect;
+ GetRegionBounds((NPQDRegion)invalidRegion, &qdRect);
+ invalidRect = NSMakeRect(qdRect.left, qdRect.top, qdRect.right - qdRect.left, qdRect.bottom - qdRect.top);
+ }
+ break;
+#endif /* NP_NO_QUICKDRAW */
+
+ case NPDrawingModelCoreGraphics:
+ {
+ CGRect cgRect = CGPathGetBoundingBox((NPCGRegion)invalidRegion);
+ invalidRect = *(NSRect*)&cgRect;
+ break;
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+ [self setNeedsDisplayInRect:invalidRect];
+}
+
+-(void)forceRedraw
+{
+ LOG(Plugins, "forceRedraw");
+ [self setNeedsDisplay:YES];
+ [[self window] displayIfNeeded];
+}
+
+static NPBrowserTextInputFuncs *browserTextInputFuncs()
+{
+ static NPBrowserTextInputFuncs inputFuncs = {
+ 0,
+ sizeof(NPBrowserTextInputFuncs),
+ NPN_MarkedTextAbandoned,
+ NPN_MarkedTextSelectionChanged
+ };
+
+ return &inputFuncs;
+}
+
+- (NPError)getVariable:(NPNVariable)variable value:(void *)value
+{
+ switch (variable) {
+ case NPNVWindowNPObject:
+ {
+ Frame* frame = core([self webFrame]);
+ NPObject* windowScriptObject = frame ? frame->script()->windowScriptNPObject() : 0;
+
+ // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess>
+ if (windowScriptObject)
+ _NPN_RetainObject(windowScriptObject);
+
+ void **v = (void **)value;
+ *v = windowScriptObject;
+
+ return NPERR_NO_ERROR;
+ }
+
+ case NPNVPluginElementNPObject:
+ {
+ if (!_element)
+ return NPERR_GENERIC_ERROR;
+
+ NPObject *plugInScriptObject = (NPObject *)[_element.get() _NPObject];
+
+ // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess>
+ if (plugInScriptObject)
+ _NPN_RetainObject(plugInScriptObject);
+
+ void **v = (void **)value;
+ *v = plugInScriptObject;
+
+ return NPERR_NO_ERROR;
+ }
+
+ case NPNVpluginDrawingModel:
+ {
+ *(NPDrawingModel *)value = drawingModel;
+ return NPERR_NO_ERROR;
+ }
+
+#ifndef NP_NO_QUICKDRAW
+ case NPNVsupportsQuickDrawBool:
+ {
+ *(NPBool *)value = TRUE;
+ return NPERR_NO_ERROR;
+ }
+#endif /* NP_NO_QUICKDRAW */
+
+ case NPNVsupportsCoreGraphicsBool:
+ {
+ *(NPBool *)value = TRUE;
+ return NPERR_NO_ERROR;
+ }
+
+ case NPNVsupportsOpenGLBool:
+ {
+ *(NPBool *)value = FALSE;
+ return NPERR_NO_ERROR;
+ }
+
+ case NPNVsupportsCoreAnimationBool:
+ {
+#ifdef BUILDING_ON_TIGER
+ *(NPBool *)value = FALSE;
+#else
+ *(NPBool *)value = TRUE;
+#endif
+ return NPERR_NO_ERROR;
+ }
+
+#ifndef NP_NO_CARBON
+ case NPNVsupportsCarbonBool:
+ {
+ *(NPBool *)value = TRUE;
+ return NPERR_NO_ERROR;
+ }
+#endif /* NP_NO_CARBON */
+
+ case NPNVsupportsCocoaBool:
+ {
+ *(NPBool *)value = TRUE;
+ return NPERR_NO_ERROR;
+ }
+
+ case NPNVbrowserTextInputFuncs:
+ {
+ if (eventModel == NPEventModelCocoa) {
+ *(NPBrowserTextInputFuncs **)value = browserTextInputFuncs();
+ return NPERR_NO_ERROR;
+ }
+ }
+ default:
+ break;
+ }
+
+ return NPERR_GENERIC_ERROR;
+}
+
+- (NPError)setVariable:(NPPVariable)variable value:(void *)value
+{
+ switch (variable) {
+ case NPPVpluginDrawingModel:
+ {
+ // Can only set drawing model inside NPP_New()
+ if (self != [[self class] currentPluginView])
+ return NPERR_GENERIC_ERROR;
+
+ // Check for valid, supported drawing model
+ NPDrawingModel newDrawingModel = (NPDrawingModel)(uintptr_t)value;
+ switch (newDrawingModel) {
+ // Supported drawing models:
+#ifndef NP_NO_QUICKDRAW
+ case NPDrawingModelQuickDraw:
+#endif
+ case NPDrawingModelCoreGraphics:
+#ifndef BUILDING_ON_TIGER
+ case NPDrawingModelCoreAnimation:
+#endif
+ drawingModel = newDrawingModel;
+ return NPERR_NO_ERROR;
+
+
+ // Unsupported (or unknown) drawing models:
+ default:
+ LOG(Plugins, "Plugin %@ uses unsupported drawing model: %d", _eventHandler.get(), drawingModel);
+ return NPERR_GENERIC_ERROR;
+ }
+ }
+
+ case NPPVpluginEventModel:
+ {
+ // Can only set event model inside NPP_New()
+ if (self != [[self class] currentPluginView])
+ return NPERR_GENERIC_ERROR;
+
+ // Check for valid, supported event model
+ NPEventModel newEventModel = (NPEventModel)(uintptr_t)value;
+ switch (newEventModel) {
+ // Supported event models:
+#ifndef NP_NO_CARBON
+ case NPEventModelCarbon:
+#endif
+ case NPEventModelCocoa:
+ eventModel = newEventModel;
+ return NPERR_NO_ERROR;
+
+ // Unsupported (or unknown) event models:
+ default:
+ LOG(Plugins, "Plugin %@ uses unsupported event model: %d", _eventHandler.get(), eventModel);
+ return NPERR_GENERIC_ERROR;
+ }
+ }
+
+ default:
+ return NPERR_GENERIC_ERROR;
+ }
+}
+
+- (uint32)scheduleTimerWithInterval:(uint32)interval repeat:(NPBool)repeat timerFunc:(void (*)(NPP npp, uint32 timerID))timerFunc
+{
+ if (!timerFunc)
+ return 0;
+
+ if (!timers)
+ timers = new HashMap<uint32, PluginTimer*>;
+
+ uint32 timerID;
+
+ do {
+ timerID = ++currentTimerID;
+ } while (timers->contains(timerID) || timerID == 0);
+
+ PluginTimer* timer = new PluginTimer(plugin, timerID, interval, repeat, timerFunc);
+ timers->set(timerID, timer);
+
+ if (_shouldFireTimers)
+ timer->start(_isCompletelyObscured);
+
+ return timerID;
+}
+
+- (void)unscheduleTimer:(uint32)timerID
+{
+ if (!timers)
+ return;
+
+ if (PluginTimer* timer = timers->take(timerID))
+ delete timer;
+}
+
+- (NPError)popUpContextMenu:(NPMenu *)menu
+{
+ NSEvent *currentEvent = [NSApp currentEvent];
+
+ // NPN_PopUpContextMenu must be called from within the plug-in's NPP_HandleEvent.
+ if (!currentEvent)
+ return NPERR_GENERIC_ERROR;
+
+ [NSMenu popUpContextMenu:(NSMenu *)menu withEvent:currentEvent forView:self];
+ return NPERR_NO_ERROR;
+}
+
+@end
+
+@implementation WebNetscapePluginView (Internal)
+
+- (NPError)_createPlugin
+{
+ plugin = (NPP)calloc(1, sizeof(NPP_t));
+ plugin->ndata = self;
+
+ ASSERT([_pluginPackage.get() pluginFuncs]->newp);
+
+ // NPN_New(), which creates the plug-in instance, should never be called while calling a plug-in function for that instance.
+ ASSERT(pluginFunctionCallDepth == 0);
+
+ PluginMainThreadScheduler::scheduler().registerPlugin(plugin);
+
+ _isSilverlight = [[[_pluginPackage.get() bundle] bundleIdentifier] isEqualToString:@"com.microsoft.SilverlightPlugin"];
+
+ [[self class] setCurrentPluginView:self];
+ NPError npErr = [_pluginPackage.get() pluginFuncs]->newp((char *)[_MIMEType.get() cString], plugin, _mode, argsCount, cAttributes, cValues, NULL);
+ [[self class] setCurrentPluginView:nil];
+ LOG(Plugins, "NPP_New: %d", npErr);
+ return npErr;
+}
+
+- (void)_destroyPlugin
+{
+ PluginMainThreadScheduler::scheduler().unregisterPlugin(plugin);
+
+ NPError npErr;
+ npErr = ![_pluginPackage.get() pluginFuncs]->destroy(plugin, NULL);
+ LOG(Plugins, "NPP_Destroy: %d", npErr);
+
+ if (Frame* frame = core([self webFrame]))
+ frame->script()->cleanupScriptObjectsForPlugin(self);
+
+ free(plugin);
+ plugin = NULL;
+}
+
+- (NSBitmapImageRep *)_printedPluginBitmap
+{
+#ifdef NP_NO_QUICKDRAW
+ return nil;
+#else
+ // Cannot print plugins that do not implement NPP_Print
+ if (![_pluginPackage.get() pluginFuncs]->print)
+ return nil;
+
+ // This NSBitmapImageRep will share its bitmap buffer with a GWorld that the plugin will draw into.
+ // The bitmap is created in 32-bits-per-pixel ARGB format, which is the default GWorld pixel format.
+ NSBitmapImageRep *bitmap = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
+ pixelsWide:window.width
+ pixelsHigh:window.height
+ bitsPerSample:8
+ samplesPerPixel:4
+ hasAlpha:YES
+ isPlanar:NO
+ colorSpaceName:NSDeviceRGBColorSpace
+ bitmapFormat:NSAlphaFirstBitmapFormat
+ bytesPerRow:0
+ bitsPerPixel:0] autorelease];
+ ASSERT(bitmap);
+
+ // Create a GWorld with the same underlying buffer into which the plugin can draw
+ ::Rect printGWorldBounds;
+ SetRect(&printGWorldBounds, 0, 0, window.width, window.height);
+ GWorldPtr printGWorld;
+ if (NewGWorldFromPtr(&printGWorld,
+ k32ARGBPixelFormat,
+ &printGWorldBounds,
+ NULL,
+ NULL,
+ 0,
+ (Ptr)[bitmap bitmapData],
+ [bitmap bytesPerRow]) != noErr) {
+ LOG_ERROR("Could not create GWorld for printing");
+ return nil;
+ }
+
+ /// Create NPWindow for the GWorld
+ NPWindow printNPWindow;
+ printNPWindow.window = &printGWorld; // Normally this is an NP_Port, but when printing it is the actual CGrafPtr
+ printNPWindow.x = 0;
+ printNPWindow.y = 0;
+ printNPWindow.width = window.width;
+ printNPWindow.height = window.height;
+ printNPWindow.clipRect.top = 0;
+ printNPWindow.clipRect.left = 0;
+ printNPWindow.clipRect.right = window.width;
+ printNPWindow.clipRect.bottom = window.height;
+ printNPWindow.type = NPWindowTypeDrawable; // Offscreen graphics port as opposed to a proper window
+
+ // Create embed-mode NPPrint
+ NPPrint npPrint;
+ npPrint.mode = NP_EMBED;
+ npPrint.print.embedPrint.window = printNPWindow;
+ npPrint.print.embedPrint.platformPrint = printGWorld;
+
+ // Tell the plugin to print into the GWorld
+ [self willCallPlugInFunction];
+ {
+ JSC::JSLock::DropAllLocks dropAllLocks(false);
+ [_pluginPackage.get() pluginFuncs]->print(plugin, &npPrint);
+ }
+ [self didCallPlugInFunction];
+
+ // Don't need the GWorld anymore
+ DisposeGWorld(printGWorld);
+
+ return bitmap;
+#endif
+}
+
+- (void)_redeliverStream
+{
+ if ([self dataSource] && _isStarted) {
+ // Deliver what has not been passed to the plug-in up to this point.
+ if (_dataLengthReceived > 0) {
+ NSData *data = [[[self dataSource] data] subdataWithRange:NSMakeRange(0, _dataLengthReceived)];
+ _dataLengthReceived = 0;
+ [self pluginView:self receivedData:data];
+ if (![[self dataSource] isLoading]) {
+ if (_error)
+ [self pluginView:self receivedError:_error.get()];
+ else
+ [self pluginViewFinishedLoading:self];
+ }
+ }
+ }
+}
+
+@end
+
+#endif
diff --git a/WebKit/mac/Plugins/WebPluginController.mm b/WebKit/mac/Plugins/WebPluginController.mm
index d892d4a..b618bd6 100644
--- a/WebKit/mac/Plugins/WebPluginController.mm
+++ b/WebKit/mac/Plugins/WebPluginController.mm
@@ -335,7 +335,7 @@ static void cancelOutstandingCheck(const void *item, void *context)
LOG_ERROR("could not load URL %@", [request URL]);
return;
}
- core(frame)->loader()->load(request, target);
+ core(frame)->loader()->load(request, target, false);
}
}
diff --git a/WebKit/mac/Plugins/WebPluginDatabase.mm b/WebKit/mac/Plugins/WebPluginDatabase.mm
index 531214e..4f2bdd8 100644
--- a/WebKit/mac/Plugins/WebPluginDatabase.mm
+++ b/WebKit/mac/Plugins/WebPluginDatabase.mm
@@ -28,20 +28,20 @@
#import "WebPluginDatabase.h"
+#import "WebBaseNetscapePluginView.h"
#import "WebBasePluginPackage.h"
#import "WebDataSourcePrivate.h"
#import "WebFrame.h"
#import "WebFrameViewInternal.h"
#import "WebHTMLRepresentation.h"
#import "WebHTMLView.h"
+#import "WebHTMLView.h"
#import "WebKitLogging.h"
-#import "WebNetscapePluginPackage.h"
#import "WebNSFileManagerExtras.h"
+#import "WebNetscapePluginPackage.h"
#import "WebPluginController.h"
-#import "WebBaseNetscapePluginView.h"
#import "WebPluginPackage.h"
#import "WebViewPrivate.h"
-#import "WebHTMLView.h"
#import <WebKitSystemInterface.h>
#import <wtf/Assertions.h>
diff --git a/WebKit/mac/Plugins/WebPlugInStreamLoaderDelegate.h b/WebKit/mac/Plugins/WebPluginRequest.h
index c21fe4c..5336dcb 100644
--- a/WebKit/mac/Plugins/WebPlugInStreamLoaderDelegate.h
+++ b/WebKit/mac/Plugins/WebPluginRequest.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2005, 2007 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,23 +26,25 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-@class NSURLResponse;
-@class NSError;
-@class NSData;
+#if ENABLE(NETSCAPE_PLUGIN_API)
-@protocol WebPlugInStreamLoaderDelegate
+@interface WebPluginRequest : NSObject
+{
+ NSURLRequest *_request;
+ NSString *_frameName;
+ void *_notifyData;
+ BOOL _didStartFromUserGesture;
+ BOOL _sendNotification;
+}
-- (void)startStreamWithResponse:(NSURLResponse *)r;
+- (id)initWithRequest:(NSURLRequest *)request frameName:(NSString *)frameName notifyData:(void *)notifyData sendNotification:(BOOL)sendNotification didStartFromUserGesture:(BOOL)currentEventIsUserGesture;
-// destroyStreamWithError tells the plug-in that the load is completed (error == nil) or ended in error.
-- (void)destroyStreamWithError:(NSError *)error;
-
-// cancelLoadAndDestoryStreamWithError calls cancelLoadWithError: then destroyStreamWithError:.
-- (void)cancelLoadAndDestroyStreamWithError:(NSError *)error;
-
-- (void)receivedData:(NSData *)data;
-- (void)finishedLoading;
-
-- (BOOL)wantsAllStreams;
+- (NSURLRequest *)request;
+- (NSString *)frameName;
+- (void *)notifyData;
+- (BOOL)isCurrentEventUserGesture;
+- (BOOL)sendNotification;
@end
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/WebKit/mac/Plugins/WebPluginRequest.m b/WebKit/mac/Plugins/WebPluginRequest.m
new file mode 100644
index 0000000..df36d40
--- /dev/null
+++ b/WebKit/mac/Plugins/WebPluginRequest.m
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2005, 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if ENABLE(NETSCAPE_PLUGIN_API)
+
+#import "WebPluginRequest.h"
+
+@implementation WebPluginRequest
+
+- (id)initWithRequest:(NSURLRequest *)request frameName:(NSString *)frameName notifyData:(void *)notifyData sendNotification:(BOOL)sendNotification didStartFromUserGesture:(BOOL)currentEventIsUserGesture
+{
+ [super init];
+ _didStartFromUserGesture = currentEventIsUserGesture;
+ _request = [request retain];
+ _frameName = [frameName retain];
+ _notifyData = notifyData;
+ _sendNotification = sendNotification;
+ return self;
+}
+
+- (void)dealloc
+{
+ [_request release];
+ [_frameName release];
+ [super dealloc];
+}
+
+- (NSURLRequest *)request
+{
+ return _request;
+}
+
+- (NSString *)frameName
+{
+ return _frameName;
+}
+
+- (BOOL)isCurrentEventUserGesture
+{
+ return _didStartFromUserGesture;
+}
+
+- (BOOL)sendNotification
+{
+ return _sendNotification;
+}
+
+- (void *)notifyData
+{
+ return _notifyData;
+}
+
+@end
+
+#endif // ENABLE(NETSCAPE_PLUGIN_API)
diff --git a/WebKit/mac/Plugins/npapi.mm b/WebKit/mac/Plugins/npapi.mm
index f85ec9f..eb32c2b 100644
--- a/WebKit/mac/Plugins/npapi.mm
+++ b/WebKit/mac/Plugins/npapi.mm
@@ -30,13 +30,13 @@
#import <WebKit/npapi.h>
#import <WebKit/nptextinput.h>
-#import "WebBaseNetscapePluginView.h"
+#import "WebNetscapePluginView.h"
#import "WebKitLogging.h"
#import <WebCore/PluginMainThreadScheduler.h>
using namespace WebCore;
-WebBaseNetscapePluginView *pluginViewForInstance(NPP instance);
+WebNetscapePluginView *pluginViewForInstance(NPP instance);
// general plug-in to browser functions
@@ -70,14 +70,14 @@ NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList)
// instance-specific functions
// The plugin view is always the ndata of the instance. Sometimes, plug-ins will call an instance-specific function
// with a NULL instance. To workaround this, call the last plug-in view that made a call to a plug-in.
-// Currently, the current plug-in view is only set before NPP_New in [WebBaseNetscapePluginView start].
+// Currently, the current plug-in view is only set before NPP_New in [WebNetscapePluginView start].
// This specifically works around Flash and Shockwave. When we call NPP_New, they call NPN_UserAgent with a NULL instance.
-WebBaseNetscapePluginView *pluginViewForInstance(NPP instance)
+WebNetscapePluginView *pluginViewForInstance(NPP instance)
{
if (instance && instance->ndata)
- return (WebBaseNetscapePluginView *)instance->ndata;
+ return (WebNetscapePluginView *)instance->ndata;
else
- return [WebBaseNetscapePluginView currentPluginView];
+ return [WebNetscapePluginView currentPluginView];
}
NPError NPN_GetURLNotify(NPP instance, const char* URL, const char* target, void* notifyData)
@@ -194,14 +194,14 @@ NPError NPN_PopUpContextMenu(NPP instance, NPMenu *menu)
void NPN_MarkedTextAbandoned(NPP instance)
{
- WebBaseNetscapePluginView *pluginView = pluginViewForInstance(instance);
+ WebNetscapePluginView *pluginView = pluginViewForInstance(instance);
[[NSInputManager currentInputManager] markedTextAbandoned:pluginView];
}
void NPN_MarkedTextSelectionChanged(NPP instance, NSRange newSel)
{
- WebBaseNetscapePluginView *pluginView = pluginViewForInstance(instance);
+ WebNetscapePluginView *pluginView = pluginViewForInstance(instance);
[[NSInputManager currentInputManager] markedTextSelectionChanged:newSel client:pluginView];
}