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
+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
--- /dev/null
+//
+// 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
--- /dev/null
+//
+// 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
@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;
- (void)stopAllPlugins;
- (void)destroyAllPlugins;
+- (WebBridge *)bridge;
+- (WebView *)webView;
+
@end
#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>
[super init];
_documentView = view;
_views = [[NSMutableArray alloc] init];
+ _checksInProgress = (NSMutableSet *)CFSetCreateMutable(NULL, 0, NULL);
+
return self;
}
}
}
+- (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];
if ([_views count] > 0) {
LOG(Plugins, "destroying WebKit plugins: %@", [_views description]);
}
+
+ [self _cancelOutstandingChecks];
int i, count = [_views count];
for (i = 0; i < count; i++) {
_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
return [_documentView _frame];
}
+- (WebBridge *)bridge
+{
+ return [[self webFrame] _bridge];
+}
+
+- (WebView *)webView
+{
+ return [[self webFrame] webView];
+}
+
@end
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,
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.
@class WebHistoryItem;
+typedef enum {
+ WebNavigationTypePlugInRequest = WebNavigationTypeOther + 1
+} WebExtraNavigationType;
+
typedef enum {
WebPolicyUse,
WebPolicyDownload,