WebKit:
[WebKit-https.git] / WebKit / Plugins.subproj / WebPluginController.m
1 //
2 //  WebPluginController.m
3 //  WebKit
4 //
5 //  Created by Chris Blumenberg on Wed Oct 23 2002.
6 //  Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
7 //
8
9 #import <WebKit/WebPluginController.h>
10
11 #import <WebKit/WebBridge.h>
12 #import <WebKit/WebFramePrivate.h>
13 #import <WebKit/WebFrameView.h>
14 #import <WebKit/WebHTMLViewPrivate.h>
15 #import <WebKit/WebKitLogging.h>
16 #import <WebKit/WebNSViewExtras.h>
17 #import <WebKit/WebPlugin.h>
18 #import <WebKit/WebPluginContainer.h>
19 #import <WebKit/WebPluginContainerCheck.h>
20 #import <WebKit/WebPluginPackage.h>
21 #import <WebKit/WebPluginViewFactory.h>
22 #import <WebKit/WebViewPrivate.h>
23 #import <WebKit/WebUIDelegate.h>
24
25 #import <WebCore/WebCoreBridge.h>
26
27 #import <Foundation/NSURL_NSURLExtras.h>
28 #import <Foundation/NSURLRequest.h>
29
30 @interface NSView (PluginSecrets)
31 - (void)setContainingWindow:(NSWindow *)w;
32 @end
33
34 // For compatibility only.
35 @interface NSObject (OldPluginAPI)
36 + (NSView *)pluginViewWithArguments:(NSDictionary *)arguments;
37 @end
38
39 @interface NSView (OldPluginAPI)
40 - (void)pluginInitialize;
41 - (void)pluginStart;
42 - (void)pluginStop;
43 - (void)pluginDestroy;
44 @end
45
46 static NSMutableSet *pluginViews = nil;
47
48 @implementation WebPluginController
49
50 + (NSView *)plugInViewWithArguments:(NSDictionary *)arguments fromPluginPackage:(WebPluginPackage *)pluginPackage
51 {
52     [pluginPackage load];
53     Class viewFactory = [pluginPackage viewFactory];
54     
55     NSView *view = nil;
56     if ([viewFactory respondsToSelector:@selector(plugInViewWithArguments:)]) {
57         view = [viewFactory plugInViewWithArguments:arguments];
58     } else if ([viewFactory respondsToSelector:@selector(pluginViewWithArguments:)]) {
59         view = [viewFactory pluginViewWithArguments:arguments];
60     }
61     
62     if (view == nil) {
63         return nil;
64     }
65     
66     if (pluginViews == nil) {
67         pluginViews = [[NSMutableSet alloc] init];
68     }
69     [pluginViews addObject:view];
70     
71     return view;
72 }
73
74 + (BOOL)isPlugInView:(NSView *)view
75 {
76     return [pluginViews containsObject:view];
77 }
78
79 - (id)initWithDocumentView:(NSView *)view
80 {
81     [super init];
82     _documentView = view;
83     _views = [[NSMutableArray alloc] init];
84     _checksInProgress = (NSMutableSet *)CFSetCreateMutable(NULL, 0, NULL);
85
86     return self;
87 }
88
89 - (void)startAllPlugins
90 {
91     if (_started) {
92         return;
93     }
94     
95     if ([_views count] > 0) {
96         LOG(Plugins, "starting WebKit plugins : %@", [_views description]);
97     }
98     
99     int i, count = [_views count];
100     for (i = 0; i < count; i++) {
101         id aView = [_views objectAtIndex:i];
102         if ([aView respondsToSelector:@selector(webPlugInStart)])
103             [aView webPlugInStart];
104         else if ([aView respondsToSelector:@selector(pluginStart)])
105             [aView pluginStart];
106     }
107     _started = YES;
108 }
109
110 - (void)stopAllPlugins
111 {
112     if (!_started) {
113         return;
114     }
115
116     if ([_views count] > 0) {
117         LOG(Plugins, "stopping WebKit plugins: %@", [_views description]);
118     }
119     
120     int i, count = [_views count];
121     for (i = 0; i < count; i++) {
122         id aView = [_views objectAtIndex:i];
123         if ([aView respondsToSelector:@selector(webPlugInStop)])
124             [aView webPlugInStop];
125         else if ([aView respondsToSelector:@selector(pluginStop)])
126             [aView pluginStop];
127     }
128     _started = NO;
129 }
130
131 - (void)addPlugin:(NSView *)view
132 {
133     if (!_documentView) {
134         ERROR("can't add a plug-in to a defunct WebPluginController");
135         return;
136     }
137     
138     if (![_views containsObject:view]) {
139         [_views addObject:view];
140         
141         LOG(Plugins, "initializing plug-in %@", view);
142         if ([view respondsToSelector:@selector(webPlugInInitialize)])
143             [view webPlugInInitialize];
144         else if ([view respondsToSelector:@selector(pluginInitialize)])
145             [view pluginInitialize];
146
147         if (_started) {
148             LOG(Plugins, "starting plug-in %@", view);
149             if ([view respondsToSelector:@selector(webPlugInStart)])
150                 [view webPlugInStart];
151             else if ([view respondsToSelector:@selector(pluginStart)])
152                 [view pluginStart];
153             
154             if ([view respondsToSelector:@selector(setContainingWindow:)])
155                 [view setContainingWindow:[_documentView window]];
156         }
157     }
158 }
159
160 - (void)_webPluginContainerCancelCheckIfAllowedToLoadRequest:(id)checkIdentifier
161 {
162     [checkIdentifier cancel];
163     [_checksInProgress removeObject:checkIdentifier];
164 }
165
166 - (void)_cancelOutstandingChecks
167 {
168     NSEnumerator *e = [_checksInProgress objectEnumerator];
169     id check;
170     while ((check = [e nextObject])) {
171         [check cancel];
172     }
173     [_checksInProgress release];
174     _checksInProgress = nil;
175 }
176
177 - (void)destroyAllPlugins
178 {    
179     [self stopAllPlugins];
180
181     if ([_views count] > 0) {
182         LOG(Plugins, "destroying WebKit plugins: %@", [_views description]);
183     }
184
185     [self _cancelOutstandingChecks];
186     
187     int i, count = [_views count];
188     for (i = 0; i < count; i++) {
189         id aView = [_views objectAtIndex:i];
190         if ([aView respondsToSelector:@selector(webPlugInDestroy)]) {
191             [aView webPlugInDestroy];
192         } else if ([aView respondsToSelector:@selector(pluginDestroy)]) {
193             [aView pluginDestroy];
194         }
195         [pluginViews removeObject:aView];
196     }
197     [_views makeObjectsPerformSelector:@selector(removeFromSuperviewWithoutNeedingDisplay)];
198     [_views release];
199     _views = nil;
200
201     _documentView = nil;
202 }
203
204 - (id)_webPluginContainerCheckIfAllowedToLoadRequest:(NSURLRequest *)request inFrame:(NSString *)target resultObject:(id)obj selector:(SEL)selector
205 {
206     WebPluginContainerCheck *check = [WebPluginContainerCheck checkWithRequest:request target:target resultObject:obj selector:selector controller:self];
207     [_checksInProgress addObject:check];
208     [check start];
209
210     return check;
211 }
212
213 - (void)webPlugInContainerLoadRequest:(NSURLRequest *)request inFrame:(NSString *)target
214 {
215     if (!request) {
216         ERROR("nil URL passed");
217         return;
218     }
219     if (!_documentView) {
220         ERROR("could not load URL %@ because plug-in has already been destroyed", request);
221         return;
222     }
223     WebFrame *frame = [_documentView _frame];
224     if (!frame) {
225         ERROR("could not load URL %@ because plug-in has already been stopped", request);
226         return;
227     }
228     if (!target) {
229         target = @"_top";
230     }
231     NSString *JSString = [[request URL] _web_scriptIfJavaScriptURL];
232     if (JSString) {
233         if ([frame findFrameNamed:target] != frame) {
234             ERROR("JavaScript requests can only be made on the frame that contains the plug-in");
235             return;
236         }
237         [[frame _bridge] stringByEvaluatingJavaScriptFromString:JSString];
238     } else {
239         if (!request) {
240             ERROR("could not load URL %@", [request URL]);
241             return;
242         }
243         [frame _loadRequest:request inFrameNamed:target];
244     }
245 }
246
247 // For compatibility only.
248 - (void)showURL:(NSURL *)URL inFrame:(NSString *)target
249 {
250     [self webPlugInContainerLoadRequest:[NSURLRequest requestWithURL:URL] inFrame:target];
251 }
252
253 - (void)webPlugInContainerShowStatus:(NSString *)message
254 {
255     if (!message) {
256         message = @"";
257     }
258     if (!_documentView) {
259         ERROR("could not show status message (%@) because plug-in has already been destroyed", message);
260         return;
261     }
262     WebView *v = [_documentView _webView];
263     [[v _UIDelegateForwarder] webView:v setStatusText:message];
264 }
265
266 // For compatibility only.
267 - (void)showStatus:(NSString *)message
268 {
269     [self webPlugInContainerShowStatus:message];
270 }
271
272 - (NSColor *)webPlugInContainerSelectionColor
273 {
274     return [[_documentView _bridge] selectionColor];
275 }
276
277 // For compatibility only.
278 - (NSColor *)selectionColor
279 {
280     return [self webPlugInContainerSelectionColor];
281 }
282
283 - (WebFrame *)webFrame
284 {
285     return [_documentView _frame];
286 }
287
288 - (WebBridge *)bridge
289 {
290     return [[self webFrame] _bridge];
291 }
292
293 - (WebView *)webView
294 {
295     return [[self webFrame] webView];
296 }
297
298 @end