WebKit:
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 23 Mar 2005 22:09:34 +0000 (22:09 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 23 Mar 2005 22:09:34 +0000 (22:09 +0000)
        Reviewed by Darin.

<rdar://problem/4051145> The QuickTime Cocoa plug-in needs an SPI that it can call to check for URL policy

        * Plugins.subproj/WebPluginContainerCheck.h: Added.
        * Plugins.subproj/WebPluginContainerCheck.m: Added this new helper class to encapsulate
an async plugin navigation check.
        (+[WebPluginContainerCheck checkWithRequest:target:resultObject:selector:controller:]): Convenience allocator that gives autoreleased value.
        (-[WebPluginContainerCheck initWithRequest:target:resultObject:selector:controller:]): Initializer.
        (-[WebPluginContainerCheck finalize]): Just assert that we're done, it would
be bad to deallocate this object while request is still outstanding.
        (-[WebPluginContainerCheck dealloc]): Ditto.
        (-[WebPluginContainerCheck _continueWithPolicy:]): Method to continue after async
policy check.
        (-[WebPluginContainerCheck _isDisallowedFileLoad]): Do "file: URL from remote content"
check.
        (-[WebPluginContainerCheck _actionInformationWithURL:]): Helper to make action
dictionary.
        (-[WebPluginContainerCheck _askPolicyDelegate]): Call policy delegate to let
the app decide if this load is allowed.
        (-[WebPluginContainerCheck start]): Start the check.
        (-[WebPluginContainerCheck cancel]): Cancel a check in progress.
        * Plugins.subproj/WebPluginController.h:
        * Plugins.subproj/WebPluginController.m:
        (-[WebPluginController initWithDocumentView:]): Initialize new _checksInProgress field.
        (-[WebPluginController _webPluginContainerCancelCheckIfAllowedToLoadRequest:]): Implement
this new SPI method.
        (-[WebPluginController _cancelOutstandingChecks]): New helper to make sure to cancel
all outstanding requests when destroying all plugins.
        (-[WebPluginController destroyAllPlugins]): Call above helper.
        (-[WebPluginController _webPluginContainerCheckIfAllowedToLoadRequest:inFrame:resultObject:selector:]): Implement this new plug-in SPI method.
        (-[WebPluginController bridge]): New helper method.
        (-[WebPluginController webView]): New helper method.
        * WebView.subproj/WebPolicyDelegatePrivate.h: Add new navigation
type WebNavigationTypePlugInRequest.
        * WebKit.pbproj/project.pbxproj: Add new files.
        * WebView.subproj/WebDefaultPolicyDelegate.m:
        (-[WebDefaultPolicyDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:]): Don't open externally on a plug-in request.

WebBrowser:

        Reviewed by Darin.

<rdar://problem/4051145> The QuickTime Cocoa plug-in needs an SPI that it can call to check for URL policy

* BrowserWebController.m:
        (-[BrowserWebView decidePolicyForAction:request:frame:newFrameName:decisionListener:]): In
case this is a plugin load request, accept it early to avoid throwing up UI or
causing external loads.

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

WebKit/ChangeLog
WebKit/Plugins.subproj/WebPluginContainerCheck.h [new file with mode: 0644]
WebKit/Plugins.subproj/WebPluginContainerCheck.m [new file with mode: 0644]
WebKit/Plugins.subproj/WebPluginController.h
WebKit/Plugins.subproj/WebPluginController.m
WebKit/WebKit.pbproj/project.pbxproj
WebKit/WebView.subproj/WebDefaultPolicyDelegate.m
WebKit/WebView.subproj/WebPolicyDelegatePrivate.h

index 5b77ef681255f8886f9d8781a689e6e26674bb67..f7445949f45917deef52413256561c618ab1d6d3 100644 (file)
@@ -1,3 +1,44 @@
+2005-03-21  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Darin.
+
+       <rdar://problem/4051145> The QuickTime Cocoa plug-in needs an SPI that it can call to check for URL policy
+
+        * Plugins.subproj/WebPluginContainerCheck.h: Added.
+        * Plugins.subproj/WebPluginContainerCheck.m: Added this new helper class to encapsulate
+       an async plugin navigation check.
+        (+[WebPluginContainerCheck checkWithRequest:target:resultObject:selector:controller:]): Convenience allocator that gives autoreleased value.
+        (-[WebPluginContainerCheck initWithRequest:target:resultObject:selector:controller:]): Initializer.
+        (-[WebPluginContainerCheck finalize]): Just assert that we're done, it would
+       be bad to deallocate this object while request is still outstanding.
+        (-[WebPluginContainerCheck dealloc]): Ditto.
+        (-[WebPluginContainerCheck _continueWithPolicy:]): Method to continue after async
+       policy check.
+        (-[WebPluginContainerCheck _isDisallowedFileLoad]): Do "file: URL from remote content"
+       check.
+        (-[WebPluginContainerCheck _actionInformationWithURL:]): Helper to make action
+       dictionary.
+        (-[WebPluginContainerCheck _askPolicyDelegate]): Call policy delegate to let
+       the app decide if this load is allowed.
+        (-[WebPluginContainerCheck start]): Start the check.
+        (-[WebPluginContainerCheck cancel]): Cancel a check in progress.
+        * Plugins.subproj/WebPluginController.h:
+        * Plugins.subproj/WebPluginController.m:
+        (-[WebPluginController initWithDocumentView:]): Initialize new _checksInProgress field.
+        (-[WebPluginController _webPluginContainerCancelCheckIfAllowedToLoadRequest:]): Implement
+       this new SPI method.
+        (-[WebPluginController _cancelOutstandingChecks]): New helper to make sure to cancel
+       all outstanding requests when destroying all plugins.
+        (-[WebPluginController destroyAllPlugins]): Call above helper.
+        (-[WebPluginController _webPluginContainerCheckIfAllowedToLoadRequest:inFrame:resultObject:selector:]): Implement this new plug-in SPI method.
+        (-[WebPluginController bridge]): New helper method.
+        (-[WebPluginController webView]): New helper method.
+        * WebView.subproj/WebPolicyDelegatePrivate.h: Add new navigation
+       type WebNavigationTypePlugInRequest.
+        * WebKit.pbproj/project.pbxproj: Add new files.
+        * WebView.subproj/WebDefaultPolicyDelegate.m:
+        (-[WebDefaultPolicyDelegate webView:decidePolicyForNavigationAction:request:frame:decisionListener:]): Don't open externally on a plug-in request.
+
 2005-03-23  Richard Williamson   <rjw@apple.com>
 
        Fixed <rdar://problem/4053515> REGRESSION (Mail): Kotoeri input method reconversion does not work in WebViews
diff --git a/WebKit/Plugins.subproj/WebPluginContainerCheck.h b/WebKit/Plugins.subproj/WebPluginContainerCheck.h
new file mode 100644 (file)
index 0000000..8f85db7
--- /dev/null
@@ -0,0 +1,34 @@
+//
+//  WebPluginContainerCheck.h
+//  WebKit
+//
+//  Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@class NSURLRequest;
+@class NSString;
+@class WebPluginController;
+@class WebPolicyDecisionListener;
+
+@interface WebPluginContainerCheck : NSObject
+{
+    NSURLRequest *_request;
+    NSString *_target;
+    WebPluginController *_controller;
+    id _resultObject;
+    SEL _resultSelector;
+    BOOL _done;
+    WebPolicyDecisionListener *_listener;
+}
+
++ (id)checkWithRequest:(NSURLRequest *)request target:(NSString *)target resultObject:(id)obj selector:(SEL)selector controller:(WebPluginController *)controller;
+
+- (id)initWithRequest:(NSURLRequest *)request target:(NSString *)target resultObject:(id)obj selector:(SEL)selector controller:(WebPluginController *)controller;
+
+- (void)start;
+
+- (void)cancel;
+
+@end
diff --git a/WebKit/Plugins.subproj/WebPluginContainerCheck.m b/WebKit/Plugins.subproj/WebPluginContainerCheck.m
new file mode 100644 (file)
index 0000000..0b000ce
--- /dev/null
@@ -0,0 +1,157 @@
+//
+//  WebPluginContainerCheck.m
+//  WebKit
+//
+//  Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+//
+
+#import <WebKit/WebPluginContainerCheck.h>
+
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSURL.h>
+#import <Foundation/NSURLRequest.h>
+#import <WebKit/WebAssertions.h>
+#import <WebKit/WebBridge.h>
+#import <WebKit/WebFrame.h>
+#import <WebKit/WebPluginContainer.h>
+#import <WebKit/WebPluginContainerPrivate.h>
+#import <WebKit/WebPluginController.h>
+#import <WebKit/WebPolicyDelegate.h>
+#import <WebKit/WebPolicyDelegatePrivate.h>
+#import <WebKit/WebView.h>
+#import <WebKit/WebViewPrivate.h>
+#import <objc/objc-runtime.h>
+
+@implementation WebPluginContainerCheck
+
++ (id)checkWithRequest:(NSURLRequest *)request target:(NSString *)target resultObject:(id)obj selector:(SEL)selector controller:(WebPluginController *)controller
+{
+    return [[[self alloc] initWithRequest:request target:target resultObject:obj selector:selector controller:controller] autorelease];
+}
+
+- (id)initWithRequest:(NSURLRequest *)request target:(NSString *)target resultObject:(id)obj selector:(SEL)selector controller:(WebPluginController *)controller
+{
+    if (!(self = [super init]))
+        return nil;
+
+    _request = [request copy];
+    _target = [target copy];
+    _resultObject = [obj retain];
+    _resultSelector = selector;
+
+    // controller owns us so don't retain, to avoid cycle
+    _controller = controller;
+
+    return self;
+}
+
+- (void)finalize
+{
+    // mandatory to complete or cancel before releasing this object
+    ASSERT(_done);
+}
+
+- (void)dealloc
+{
+    // mandatory to complete or cancel before releasing this object
+    ASSERT(_done);
+    [super dealloc];
+}
+
+- (void)_continueWithPolicy:(WebPolicyAction)policy
+{
+    void (*callBack)(id, SEL, BOOL) = (void (*)(id, SEL, BOOL))objc_msgSend;
+    (*callBack) (_resultObject, _resultSelector, (policy == WebPolicyUse));
+
+    // this will call indirectly call cancel
+    [_controller _webPluginContainerCancelCheckIfAllowedToLoadRequest:self];
+}
+
+- (BOOL)_isForbiddenFileLoad
+{
+   BOOL ignore;
+   WebBridge *bridge = [_controller bridge];
+   if (![bridge canLoadURL:[_request URL] fromReferrer:[bridge referrer] hideReferrer:&ignore]) {
+       [self _continueWithPolicy:WebPolicyIgnore];
+       return YES;
+   }
+
+   return NO;
+}
+
+- (NSDictionary *)_actionInformationWithURL:(NSURL *)URL
+{
+    return [NSDictionary dictionaryWithObjectsAndKeys:
+               [NSNumber numberWithInt:WebNavigationTypePlugInRequest], WebActionNavigationTypeKey,
+               [NSNumber numberWithInt:0], WebActionModifierFlagsKey,
+               URL, WebActionOriginalURLKey,
+               nil];
+}
+
+- (void)_askPolicyDelegate
+{
+    WebView *webView = [_controller webView];
+
+    WebFrame *targetFrame;
+    if ([_target length] > 0) {
+        targetFrame = [[_controller webFrame] findFrameNamed:_target];
+    } else {
+        targetFrame = [_controller webFrame];
+    }
+
+    NSDictionary *action = [self _actionInformationWithURL:[_request URL]];
+
+    _listener = [[WebPolicyDecisionListener alloc] _initWithTarget:self action:@selector(_continueWithPolicy:)];
+
+    if (targetFrame == nil) {
+        // would open new window
+        [[webView _policyDelegateForwarder] webView:webView
+                     decidePolicyForNewWindowAction:action
+                                            request:_request
+                                       newFrameName:_target
+                                   decisionListener:_listener];
+    } else {
+        // would target existing frame
+        [[webView _policyDelegateForwarder] webView:webView
+                    decidePolicyForNavigationAction:action
+                                            request:_request
+                                              frame:targetFrame
+                                   decisionListener:_listener];        
+    }
+}
+
+- (void)start
+{
+    ASSERT(!_listener);
+    ASSERT(!_done);
+
+    if ([self _isForbiddenFileLoad])
+        return;
+
+    [self _askPolicyDelegate];
+}
+
+- (void)cancel
+{
+    if (_done)
+        return;
+
+    [_request release];
+    _request = nil;
+    
+    [_target release];
+    _target = nil;
+
+    [_listener _invalidate];
+    [_listener release];
+    _listener = nil;
+
+    [_resultObject autorelease];
+    _resultObject = nil;
+
+    _controller = nil;
+
+    _done = YES;
+}
+
+@end
index 774f029c100d3ed7dcb12ad181a3987d84bce0fc..05513377648c379cf333f1df56a798fdeaa2dd6c 100644 (file)
 
 @class WebHTMLView;
 @class WebPluginPackage;
+@class WebBridge;
+@class WebView;
 
 @interface WebPluginController : NSObject
 {
     NSView *_documentView;
     NSMutableArray *_views;
     BOOL _started;
+    NSMutableSet *_checksInProgress;
 }
 
 + (NSView *)plugInViewWithArguments:(NSDictionary *)arguments fromPluginPackage:(WebPluginPackage *)plugin;
@@ -29,4 +32,7 @@
 - (void)stopAllPlugins;
 - (void)destroyAllPlugins;
 
+- (WebBridge *)bridge;
+- (WebView *)webView;
+
 @end
index 3b6d2560a64b424ed1fb3ba7a8ad3c0d92b759f4..9f21ca5d80f66780a3ac890b63f78881478d91da 100644 (file)
@@ -16,6 +16,7 @@
 #import <WebKit/WebNSViewExtras.h>
 #import <WebKit/WebPlugin.h>
 #import <WebKit/WebPluginContainer.h>
+#import <WebKit/WebPluginContainerCheck.h>
 #import <WebKit/WebPluginPackage.h>
 #import <WebKit/WebPluginViewFactory.h>
 #import <WebKit/WebViewPrivate.h>
@@ -80,6 +81,8 @@ static NSMutableSet *pluginViews = nil;
     [super init];
     _documentView = view;
     _views = [[NSMutableArray alloc] init];
+    _checksInProgress = (NSMutableSet *)CFSetCreateMutable(NULL, 0, NULL);
+
     return self;
 }
 
@@ -154,6 +157,23 @@ static NSMutableSet *pluginViews = nil;
     }
 }
 
+- (void)_webPluginContainerCancelCheckIfAllowedToLoadRequest:(id)checkIdentifier
+{
+    [checkIdentifier cancel];
+    [_checksInProgress removeObject:checkIdentifier];
+}
+
+- (void)_cancelOutstandingChecks
+{
+    NSEnumerator *e = [_checksInProgress objectEnumerator];
+    id check;
+    while ((check = [e nextObject])) {
+        [check cancel];
+    }
+    [_checksInProgress release];
+    _checksInProgress = nil;
+}
+
 - (void)destroyAllPlugins
 {    
     [self stopAllPlugins];
@@ -161,6 +181,8 @@ static NSMutableSet *pluginViews = nil;
     if ([_views count] > 0) {
         LOG(Plugins, "destroying WebKit plugins: %@", [_views description]);
     }
+
+    [self _cancelOutstandingChecks];
     
     int i, count = [_views count];
     for (i = 0; i < count; i++) {
@@ -179,16 +201,13 @@ static NSMutableSet *pluginViews = nil;
     _documentView = nil;
 }
 
-- (id)_webPluginContainerCheckIfAllowedToLoadRequest:(NSURLRequest *)Request inFrame:(NSString *)target resultObject:(id)obj selector:(SEL)selector
+- (id)_webPluginContainerCheckIfAllowedToLoadRequest:(NSURLRequest *)request inFrame:(NSString *)target resultObject:(id)obj selector:(SEL)selector
 {
-    // FIXME: really implement this
-    [obj performSelector:selector withObject:(id)YES];
-    return nil;
-}
+    WebPluginContainerCheck *check = [WebPluginContainerCheck checkWithRequest:request target:target resultObject:obj selector:selector controller:self];
+    [_checksInProgress addObject:check];
+    [check start];
 
-- (void)_webPluginContainerCancelCheckIfAllowedToLoadRequest:(id)checkIdentifier
-{
-    // FIXME: really implement this
+    return check;
 }
 
 - (void)webPlugInContainerLoadRequest:(NSURLRequest *)request inFrame:(NSString *)target
@@ -266,4 +285,14 @@ static NSMutableSet *pluginViews = nil;
     return [_documentView _frame];
 }
 
+- (WebBridge *)bridge
+{
+    return [[self webFrame] _bridge];
+}
+
+- (WebView *)webView
+{
+    return [[self webFrame] webView];
+}
+
 @end
index 1e8abc57c0687a59bb57ef05b06ee9283042f766..578c3a5441a7f63b8127abeaeddf46b57e123316 100644 (file)
                                514C4C30075E7DE500B89CAD,
                                93C6F14607920B93002449CD,
                                65836F5F07EE425900682F95,
+                               65E1150507EFFEBF009B8BF7,
                        );
                        isa = PBXHeadersBuildPhase;
                        runOnlyForDeploymentPostprocessing = 0;
                                832D7E060709D8FB00F49B61,
                                514C4C2F075E7DE500B89CAD,
                                514C4C31075E7DE500B89CAD,
+                               65E1150607EFFEBF009B8BF7,
                        );
                        isa = PBXSourcesBuildPhase;
                        runOnlyForDeploymentPostprocessing = 0;
                        settings = {
                        };
                };
+               65E1150307EFFEBF009B8BF7 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = WebPluginContainerCheck.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               65E1150407EFFEBF009B8BF7 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.objc;
+                       path = WebPluginContainerCheck.m;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               65E1150507EFFEBF009B8BF7 = {
+                       fileRef = 65E1150307EFFEBF009B8BF7;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               65E1150607EFFEBF009B8BF7 = {
+                       fileRef = 65E1150407EFFEBF009B8BF7;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
 //650
 //651
 //652
                };
                848DFF430365F71500CA2ACA = {
                        children = (
-                               65836F5E07EE425900682F95,
                                848DFF840365FE6A00CA2ACA,
                                848DFF850365FE6A00CA2ACA,
+                               65836F5E07EE425900682F95,
+                               65E1150307EFFEBF009B8BF7,
+                               65E1150407EFFEBF009B8BF7,
                                8467275C0367158500CA2ACA,
                                8467275D0367158500CA2ACA,
                                832D7E030709D8FB00F49B61,
index 99426fc3d8c74831388e44c4ed46b5e34fe1ec29..87a29e567bfcc0ffbb2888d0e76b61416b8fd58a 100644 (file)
@@ -63,8 +63,12 @@ static WebDefaultPolicyDelegate *sharedDelegate = nil;
                                                          frame:(WebFrame *)frame
                                               decisionListener:(WebPolicyDecisionListener *)listener
 {
+    WebNavigationType navType = [[actionInformation objectForKey:WebActionNavigationTypeKey] intValue];
+
     if ([WebView _canHandleRequest:request]) {
        [listener use];
+    } else if (navType == WebNavigationTypePlugInRequest) {
+       [listener use];
     } else {
        // A file URL shouldn't fall through to here, but if it did,
        // it would be a security risk to open it.
index 50f91736bcb25b6f85592d1c3e157b8a1a047792..eae93e82c8f1f5cd1d4a5d5d275628a709df5371 100644 (file)
@@ -9,6 +9,10 @@
 
 @class WebHistoryItem;
 
+typedef enum {
+    WebNavigationTypePlugInRequest =  WebNavigationTypeOther + 1
+} WebExtraNavigationType;
+
 typedef enum {
     WebPolicyUse,
     WebPolicyDownload,