Reviewed by Chris.
authorkdecker <kdecker@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 19 Feb 2005 21:40:02 +0000 (21:40 +0000)
committerkdecker <kdecker@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 19 Feb 2005 21:40:02 +0000 (21:40 +0000)
Fixed <rdar://problem/4010765> Flash player can be used to arbitrarily open popup windows without user permission

Our window.open() policy is to refuse the <script>window.open(...)</script> case and allow the inline the <a href="javascript:window.open('foo')> case.  Clever advertisers at some point realized that by executing their Javascript through the Flash plugin, Safari would always treat their code as the inline case, and thus, they were able to work around our popup blocker.

        * Plugins.subproj/WebBaseNetscapePluginView.h: Addded currentEventIsUserGesture boolean ivar.
        * Plugins.subproj/WebBaseNetscapePluginView.m:
        (-[WebBaseNetscapePluginView sendEvent:]): If at any point the user clicks or presses a key from within a plugin, set the currentEventIsUserGesture flag to true. This is important to differentiate legitimate window.open() calls originating from plugins;  we still want to allow those.
        (-[WebBaseNetscapePluginView initWithFrame:]): In our asynchronous load, pass along currentEventIsUserGesture to the PluginRequest.
        (-[WebBaseNetscapePluginView evaluateJavaScriptPluginRequest:]): Inform WebCore if this was a user originated gesture when calling executeScript().
        (-[WebBaseNetscapePluginView loadRequest:inTarget:withNotifyData:sendNotification:]):
        (-[WebPluginRequest initWithRequest:frameName:notifyData:sendNotification:didStartFromUserGesture:]):
        (-[WebPluginRequest isCurrentEventUserGesture]): Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@8639 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebKit/ChangeLog
WebKit/Plugins.subproj/WebBaseNetscapePluginView.h
WebKit/Plugins.subproj/WebBaseNetscapePluginView.m

index 53fdf16be13279685468ab645d1994539080bfaf..b1869f0daf0e9854ce2cce4003d575835593d4d5 100644 (file)
@@ -1,3 +1,20 @@
+2005-02-19  Kevin Decker  <kdecker@apple.com>
+
+        Reviewed by Chris.
+
+       Fixed <rdar://problem/4010765> Flash player can be used to arbitrarily open popup windows without user permission
+       
+       Our window.open() policy is to refuse the <script>window.open(...)</script> case and allow the inline the <a href="javascript:window.open('foo')> case.  Clever advertisers at some point realized that by executing their Javascript through the Flash plugin, Safari would always treat their code as the inline case, and thus, they were able to work around our popup blocker. 
+
+        * Plugins.subproj/WebBaseNetscapePluginView.h: Addded currentEventIsUserGesture boolean ivar. 
+        * Plugins.subproj/WebBaseNetscapePluginView.m:
+        (-[WebBaseNetscapePluginView sendEvent:]): If at any point the user clicks or presses a key from within a plugin, set the currentEventIsUserGesture flag to true. This is important to differentiate legitimate window.open() calls originating from plugins;  we still want to allow those. 
+        (-[WebBaseNetscapePluginView initWithFrame:]): In our asynchronous load, pass along currentEventIsUserGesture to the PluginRequest. 
+        (-[WebBaseNetscapePluginView evaluateJavaScriptPluginRequest:]): Inform WebCore if this was a user originated gesture when calling executeScript(). 
+        (-[WebBaseNetscapePluginView loadRequest:inTarget:withNotifyData:sendNotification:]):
+        (-[WebPluginRequest initWithRequest:frameName:notifyData:sendNotification:didStartFromUserGesture:]):
+        (-[WebPluginRequest isCurrentEventUserGesture]): Added. 
+
 2005-02-18  Chris Blumenberg  <cblu@apple.com>
 
        Fixed: <rdar://problem/3945271> REGRESSION (Mail): pasted plain text should pick up typing style instead of being unstyled
index c4cc59e7be6ef1bd702419e733267a92191e41df..735dea90fc2b2df12bc38f6e8af35f8bc8e9b7cd 100644 (file)
@@ -35,6 +35,7 @@
     BOOL inSetWindow;
     BOOL suspendKeyUpEvents;
     BOOL hasFocus;
+    BOOL currentEventIsUserGesture;
 
     int32 specifiedHeight;
     int32 specifiedWidth;
index e7abb93d2269eaa49449044b136833ee149b4204..8dc64d374480dc51dd4613ee15939dba52bb50ea 100644 (file)
@@ -62,14 +62,16 @@ typedef struct {
     NSURLRequest *_request;
     NSString *_frameName;
     void *_notifyData;
+    BOOL _didStartFromUserGesture;
     BOOL _sendNotification;
 }
 
-- (id)initWithRequest:(NSURLRequest *)request frameName:(NSString *)frameName notifyData:(void *)notifyData sendNotification:(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
@@ -323,7 +325,15 @@ void ConsoleConnectionChangeNotifyProc(CGSNotificationType type, CGSNotification
 - (BOOL)sendEvent:(EventRecord *)event
 {
     ASSERT([self window]);
-
+    ASSERT(event);
+   
+    // If at any point the user clicks or presses a key from within a plugin, set the 
+    // currentEventIsUserGesture flag to true. This is important to differentiate legitimate 
+    // window.open() calls;  we still want to allow those.  See rdar://problem/4010765
+    if(event->what == mouseDown || event->what == keyDown || event->what == mouseUp || event->what == autoKey) {
+        currentEventIsUserGesture = YES;
+    }
+    
     suspendKeyUpEvents = NO;
     
     if (!isStarted) {
@@ -366,6 +376,8 @@ void ConsoleConnectionChangeNotifyProc(CGSNotificationType type, CGSNotification
 
     BOOL acceptedEvent = NPP_HandleEvent(instance, event);
 
+    currentEventIsUserGesture = NO;
+    
     if ([self currentWindow]) {
         [self restorePortState:portState];
     }
@@ -1105,7 +1117,6 @@ static OSStatus TSMEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEve
 
     instance = &instanceStruct;
     instance->ndata = self;
-
     streams = [[NSMutableArray alloc] init];
     pendingFrameLoads = [[NSMutableDictionary alloc] init];
 
@@ -1359,7 +1370,7 @@ static OSStatus TSMEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEve
     NSString *JSString = [URL _web_scriptIfJavaScriptURL];
     ASSERT(JSString);
     
-    NSString *result = [[[self webFrame] _bridge] stringByEvaluatingJavaScriptFromString:JSString];
+    NSString *result = [[[self webFrame] _bridge] stringByEvaluatingJavaScriptFromString:JSString forceUserGesture:[JSPluginRequest isCurrentEventUserGesture]];
     
     // Don't continue if stringByEvaluatingJavaScriptFromString caused the plug-in to stop.
     if (!isStarted) {
@@ -1499,7 +1510,7 @@ static OSStatus TSMEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEve
             return NPERR_INVALID_PARAM;
         }
         
-        WebPluginRequest *pluginRequest = [[WebPluginRequest alloc] initWithRequest:request frameName:target notifyData:notifyData sendNotification:sendNotification];
+        WebPluginRequest *pluginRequest = [[WebPluginRequest alloc] initWithRequest:request frameName:target notifyData:notifyData sendNotification:sendNotification didStartFromUserGesture:currentEventIsUserGesture];
         [self performSelector:@selector(loadPluginRequest:) withObject:pluginRequest afterDelay:0];
         [pluginRequest release];
         if (target) {
@@ -1723,9 +1734,10 @@ static OSStatus TSMEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEve
 
 @implementation WebPluginRequest
 
-- (id)initWithRequest:(NSURLRequest *)request frameName:(NSString *)frameName notifyData:(void *)notifyData sendNotification:(BOOL)sendNotification
+- (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;
@@ -1750,6 +1762,11 @@ static OSStatus TSMEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEve
     return _frameName;
 }
 
+- (BOOL)isCurrentEventUserGesture
+{
+    return _didStartFromUserGesture;
+}
+
 - (BOOL)sendNotification
 {
     return _sendNotification;