1/* 2 * Copyright (C) 2005, 2008 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#import "WebPluginContainerCheck.h" 30 31#import "WebFrameInternal.h" 32#import "WebPluginContainerPrivate.h" 33#import "WebPluginController.h" 34#import "WebPolicyDelegatePrivate.h" 35#import "WebView.h" 36#import "WebViewInternal.h" 37#import <Foundation/NSDictionary.h> 38#import <Foundation/NSURL.h> 39#import <Foundation/NSURLRequest.h> 40#import <WebCore/Frame.h> 41#import <WebCore/FrameLoader.h> 42#import <WebCore/FrameLoaderTypes.h> 43#import <wtf/Assertions.h> 44#import <objc/objc-runtime.h> 45 46using namespace WebCore; 47 48@implementation WebPluginContainerCheck 49 50- (id)initWithRequest:(NSURLRequest *)request target:(NSString *)target resultObject:(id)obj selector:(SEL)selector controller:(id <WebPluginContainerCheckController>)controller contextInfo:(id)contextInfo /*optional*/ 51{ 52 if (!(self = [super init])) 53 return nil; 54 55 _request = [request copy]; 56 _target = [target copy]; 57 _resultObject = [obj retain]; 58 _resultSelector = selector; 59 _contextInfo = [contextInfo retain]; 60 61 // controller owns us so don't retain, to avoid cycle 62 _controller = controller; 63 64 return self; 65} 66 67+ (id)checkWithRequest:(NSURLRequest *)request target:(NSString *)target resultObject:(id)obj selector:(SEL)selector controller:(id <WebPluginContainerCheckController>)controller contextInfo:(id)contextInfo /*optional*/ 68{ 69 return [[[self alloc] initWithRequest:request target:target resultObject:obj selector:selector controller:controller contextInfo:contextInfo] autorelease]; 70} 71 72- (void)finalize 73{ 74 // mandatory to complete or cancel before releasing this object 75 ASSERT(_done); 76 [super finalize]; 77} 78 79- (void)dealloc 80{ 81 // mandatory to complete or cancel before releasing this object 82 ASSERT(_done); 83 [super dealloc]; 84} 85 86- (void)_continueWithPolicy:(PolicyAction)policy 87{ 88 if (_contextInfo) 89 ((void (*)(id, SEL, BOOL, id))objc_msgSend)(_resultObject, _resultSelector, (policy == PolicyUse), _contextInfo); 90 else 91 ((void (*)(id, SEL, BOOL))objc_msgSend)(_resultObject, _resultSelector, (policy == PolicyUse)); 92 93 // this will call indirectly call cancel 94 [_controller _webPluginContainerCancelCheckIfAllowedToLoadRequest:self]; 95} 96 97- (BOOL)_isForbiddenFileLoad 98{ 99 Frame* coreFrame = core([_controller webFrame]); 100 ASSERT(coreFrame); 101 if (!coreFrame->loader()->canLoad([_request URL], String(), coreFrame->document())) { 102 [self _continueWithPolicy:PolicyIgnore]; 103 return YES; 104 } 105 106 return NO; 107} 108 109- (NSDictionary *)_actionInformationWithURL:(NSURL *)URL 110{ 111 return [NSDictionary dictionaryWithObjectsAndKeys: 112 [NSNumber numberWithInt:WebNavigationTypePlugInRequest], WebActionNavigationTypeKey, 113 [NSNumber numberWithInt:0], WebActionModifierFlagsKey, 114 URL, WebActionOriginalURLKey, 115 nil]; 116} 117 118- (void)_askPolicyDelegate 119{ 120 WebView *webView = [_controller webView]; 121 122 WebFrame *targetFrame; 123 if ([_target length] > 0) { 124 targetFrame = [[_controller webFrame] findFrameNamed:_target]; 125 } else { 126 targetFrame = [_controller webFrame]; 127 } 128 129 NSDictionary *action = [self _actionInformationWithURL:[_request URL]]; 130 131 _listener = [[WebPolicyDecisionListener alloc] _initWithTarget:self action:@selector(_continueWithPolicy:)]; 132 133 if (targetFrame == nil) { 134 // would open new window 135 [[webView _policyDelegateForwarder] webView:webView 136 decidePolicyForNewWindowAction:action 137 request:_request 138 newFrameName:_target 139 decisionListener:_listener]; 140 } else { 141 // would target existing frame 142 [[webView _policyDelegateForwarder] webView:webView 143 decidePolicyForNavigationAction:action 144 request:_request 145 frame:targetFrame 146 decisionListener:_listener]; 147 } 148} 149 150- (void)start 151{ 152 ASSERT(!_listener); 153 ASSERT(!_done); 154 155 if ([self _isForbiddenFileLoad]) 156 return; 157 158 [self _askPolicyDelegate]; 159} 160 161- (void)cancel 162{ 163 if (_done) 164 return; 165 166 [_request release]; 167 _request = nil; 168 169 [_target release]; 170 _target = nil; 171 172 [_listener _invalidate]; 173 [_listener release]; 174 _listener = nil; 175 176 [_resultObject autorelease]; 177 _resultObject = nil; 178 179 _controller = nil; 180 181 [_contextInfo release]; 182 _contextInfo = nil; 183 184 _done = YES; 185} 186 187- (id)contextInfo 188{ 189 return _contextInfo; 190} 191 192@end 193