44c98dbd35b2c7e0a64b8b9fbb8d943083a97274
[WebKit-https.git] / Source / WebKit2 / WebProcess / InjectedBundle / API / mac / WKWebProcessPlugInBrowserContextController.mm
1 /*
2  * Copyright (C) 2012 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "WKWebProcessPlugInBrowserContextControllerInternal.h"
28
29 #if WK_API_ENABLED
30
31 #import "RemoteObjectRegistry.h"
32 #import "RemoteObjectRegistryMessages.h"
33 #import "WKBrowsingContextHandleInternal.h"
34 #import "WKBundleAPICast.h"
35 #import "WKBundlePage.h"
36 #import "WKBundlePagePrivate.h"
37 #import "WKDOMInternals.h"
38 #import "WKNSError.h"
39 #import "WKRemoteObjectRegistryInternal.h"
40 #import "WKRenderingProgressEventsInternal.h"
41 #import "WKRetainPtr.h"
42 #import "WKURLRequestNS.h"
43 #import "WKWebProcessPluginFrameInternal.h"
44 #import "WKWebProcessPlugInInternal.h"
45 #import "WKWebProcessPlugInFormDelegatePrivate.h"
46 #import "WKWebProcessPlugInLoadDelegate.h"
47 #import "WKWebProcessPlugInNodeHandleInternal.h"
48 #import "WKWebProcessPlugInPageGroupInternal.h"
49 #import "WKWebProcessPlugInScriptWorldInternal.h"
50 #import "WeakObjCPtr.h"
51 #import "WebPage.h"
52 #import "WebProcess.h"
53 #import <WebCore/Document.h>
54 #import <WebCore/Frame.h>
55
56 using namespace WebCore;
57 using namespace WebKit;
58
59 @implementation WKWebProcessPlugInBrowserContextController {
60     API::ObjectStorage<WebPage> _page;
61     WeakObjCPtr<id <WKWebProcessPlugInLoadDelegate>> _loadDelegate;
62     WeakObjCPtr<id <WKWebProcessPlugInFormDelegatePrivate>> _formDelegate;
63     
64     RetainPtr<WKRemoteObjectRegistry> _remoteObjectRegistry;
65 }
66
67 static void didStartProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef* userDataRef, const void *clientInfo)
68 {
69     WKWebProcessPlugInBrowserContextController *pluginContextController = (WKWebProcessPlugInBrowserContextController *)clientInfo;
70     auto loadDelegate = pluginContextController->_loadDelegate.get();
71
72     if ([loadDelegate respondsToSelector:@selector(webProcessPlugInBrowserContextController:didStartProvisionalLoadForFrame:)])
73         [loadDelegate webProcessPlugInBrowserContextController:pluginContextController didStartProvisionalLoadForFrame:wrapper(*toImpl(frame))];
74 }
75
76 static void didFinishLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef* userData, const void *clientInfo)
77 {
78     WKWebProcessPlugInBrowserContextController *pluginContextController = (WKWebProcessPlugInBrowserContextController *)clientInfo;
79     auto loadDelegate = pluginContextController->_loadDelegate.get();
80
81     if ([loadDelegate respondsToSelector:@selector(webProcessPlugInBrowserContextController:didFinishLoadForFrame:)])
82         [loadDelegate webProcessPlugInBrowserContextController:pluginContextController didFinishLoadForFrame:wrapper(*toImpl(frame))];
83 }
84
85 static void globalObjectIsAvailableForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleScriptWorldRef scriptWorld, const void* clientInfo)
86 {
87     WKWebProcessPlugInBrowserContextController *pluginContextController = (WKWebProcessPlugInBrowserContextController *)clientInfo;
88     auto loadDelegate = pluginContextController->_loadDelegate.get();
89
90     if ([loadDelegate respondsToSelector:@selector(webProcessPlugInBrowserContextController:globalObjectIsAvailableForFrame:inScriptWorld:)])
91         [loadDelegate webProcessPlugInBrowserContextController:pluginContextController globalObjectIsAvailableForFrame:wrapper(*toImpl(frame)) inScriptWorld:wrapper(*toImpl(scriptWorld))];
92 }
93
94 static void didRemoveFrameFromHierarchy(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef* userData, const void* clientInfo)
95 {
96     WKWebProcessPlugInBrowserContextController *pluginContextController = (WKWebProcessPlugInBrowserContextController *)clientInfo;
97     auto loadDelegate = pluginContextController->_loadDelegate.get();
98
99     if ([loadDelegate respondsToSelector:@selector(webProcessPlugInBrowserContextController:didRemoveFrameFromHierarchy:)])
100         [loadDelegate webProcessPlugInBrowserContextController:pluginContextController didRemoveFrameFromHierarchy:wrapper(*toImpl(frame))];
101 }
102
103 static void didCommitLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef* userData, const void *clientInfo)
104 {
105     WKWebProcessPlugInBrowserContextController *pluginContextController = (WKWebProcessPlugInBrowserContextController *)clientInfo;
106     auto loadDelegate = pluginContextController->_loadDelegate.get();
107
108     if ([loadDelegate respondsToSelector:@selector(webProcessPlugInBrowserContextController:didCommitLoadForFrame:)])
109         [loadDelegate webProcessPlugInBrowserContextController:pluginContextController didCommitLoadForFrame:wrapper(*toImpl(frame))];
110 }
111
112 static void didFinishDocumentLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef* userData, const void *clientInfo)
113 {
114     WKWebProcessPlugInBrowserContextController *pluginContextController = (WKWebProcessPlugInBrowserContextController *)clientInfo;
115     auto loadDelegate = pluginContextController->_loadDelegate.get();
116
117     if ([loadDelegate respondsToSelector:@selector(webProcessPlugInBrowserContextController:didFinishDocumentLoadForFrame:)])
118         [loadDelegate webProcessPlugInBrowserContextController:pluginContextController didFinishDocumentLoadForFrame:wrapper(*toImpl(frame))];
119 }
120
121 static void didFailLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef wkError, WKTypeRef* userData, const void *clientInfo)
122 {
123     WKWebProcessPlugInBrowserContextController *pluginContextController = (WKWebProcessPlugInBrowserContextController *)clientInfo;
124     auto loadDelegate = pluginContextController->_loadDelegate.get();
125
126     if ([loadDelegate respondsToSelector:@selector(webProcessPlugInBrowserContextController:didFailLoadWithErrorForFrame:error:)])
127         [loadDelegate webProcessPlugInBrowserContextController:pluginContextController didFailLoadWithErrorForFrame:wrapper(*toImpl(frame)) error:wrapper(*toImpl(wkError))];
128 }
129
130 static void didSameDocumentNavigationForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef* userData, const void *clientInfo)
131 {
132     WKWebProcessPlugInBrowserContextController *pluginContextController = (WKWebProcessPlugInBrowserContextController *)clientInfo;
133     auto loadDelegate = pluginContextController->_loadDelegate.get();
134
135     if ([loadDelegate respondsToSelector:@selector(webProcessPlugInBrowserContextController:didSameDocumentNavigationForFrame:)])
136         [loadDelegate webProcessPlugInBrowserContextController:pluginContextController didSameDocumentNavigationForFrame:wrapper(*toImpl(frame))];
137 }
138
139 static void didLayoutForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void* clientInfo)
140 {
141     WKWebProcessPlugInBrowserContextController *pluginContextController = (WKWebProcessPlugInBrowserContextController *)clientInfo;
142     auto loadDelegate = pluginContextController->_loadDelegate.get();
143
144     if ([loadDelegate respondsToSelector:@selector(webProcessPlugInBrowserContextController:didLayoutForFrame:)])
145         [loadDelegate webProcessPlugInBrowserContextController:pluginContextController didLayoutForFrame:wrapper(*toImpl(frame))];
146 }
147
148 static void didLayout(WKBundlePageRef page, WKLayoutMilestones milestones, WKTypeRef* userData, const void *clientInfo)
149 {
150     WKWebProcessPlugInBrowserContextController *pluginContextController = (WKWebProcessPlugInBrowserContextController *)clientInfo;
151     auto loadDelegate = pluginContextController->_loadDelegate.get();
152
153     if ([loadDelegate respondsToSelector:@selector(webProcessPlugInBrowserContextController:renderingProgressDidChange:)])
154         [loadDelegate webProcessPlugInBrowserContextController:pluginContextController renderingProgressDidChange:renderingProgressEvents(milestones)];
155 }
156
157 static void didFirstVisuallyNonEmptyLayoutForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKTypeRef* userData, const void *clientInfo)
158 {
159     WKWebProcessPlugInBrowserContextController *pluginContextController = (WKWebProcessPlugInBrowserContextController *)clientInfo;
160     auto loadDelegate = pluginContextController->_loadDelegate.get();
161
162     if ([loadDelegate respondsToSelector:@selector(webProcessPlugInBrowserContextController:didFirstVisuallyNonEmptyLayoutForFrame:)])
163         [loadDelegate webProcessPlugInBrowserContextController:pluginContextController didFirstVisuallyNonEmptyLayoutForFrame:wrapper(*toImpl(frame))];
164 }
165
166 static void didHandleOnloadEventsForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void* clientInfo)
167 {
168     WKWebProcessPlugInBrowserContextController *pluginContextController = (WKWebProcessPlugInBrowserContextController *)clientInfo;
169     auto loadDelegate = pluginContextController->_loadDelegate.get();
170
171     if ([loadDelegate respondsToSelector:@selector(webProcessPlugInBrowserContextController:didHandleOnloadEventsForFrame:)])
172         [loadDelegate webProcessPlugInBrowserContextController:pluginContextController didHandleOnloadEventsForFrame:wrapper(*toImpl(frame))];
173 }
174 static void setUpPageLoaderClient(WKWebProcessPlugInBrowserContextController *contextController, WebPage& page)
175 {
176     WKBundlePageLoaderClientV7 client;
177     memset(&client, 0, sizeof(client));
178
179     client.base.version = 7;
180     client.base.clientInfo = contextController;
181     client.didStartProvisionalLoadForFrame = didStartProvisionalLoadForFrame;
182     client.didCommitLoadForFrame = didCommitLoadForFrame;
183     client.didFinishDocumentLoadForFrame = didFinishDocumentLoadForFrame;
184     client.didFailLoadWithErrorForFrame = didFailLoadWithErrorForFrame;
185     client.didSameDocumentNavigationForFrame = didSameDocumentNavigationForFrame;
186     client.didFinishLoadForFrame = didFinishLoadForFrame;
187     client.globalObjectIsAvailableForFrame = globalObjectIsAvailableForFrame;
188     client.didRemoveFrameFromHierarchy = didRemoveFrameFromHierarchy;
189     client.didHandleOnloadEventsForFrame = didHandleOnloadEventsForFrame;
190     client.didFirstVisuallyNonEmptyLayoutForFrame = didFirstVisuallyNonEmptyLayoutForFrame;
191
192     client.didLayoutForFrame = didLayoutForFrame;
193     client.didLayout = didLayout;
194
195     page.initializeInjectedBundleLoaderClient(&client.base);
196 }
197
198 static WKURLRequestRef willSendRequestForFrame(WKBundlePageRef, WKBundleFrameRef frame, uint64_t, WKURLRequestRef request, WKURLResponseRef redirectResponse, const void* clientInfo)
199 {
200     WKWebProcessPlugInBrowserContextController *pluginContextController = (WKWebProcessPlugInBrowserContextController *)clientInfo;
201     auto loadDelegate = pluginContextController->_loadDelegate.get();
202
203     if ([loadDelegate respondsToSelector:@selector(webProcessPlugInBrowserContextController:frame:willSendRequest:redirectResponse:)]) {
204         NSURLRequest *originalRequest = toImpl(request)->resourceRequest().nsURLRequest(DoNotUpdateHTTPBody);
205         RetainPtr<NSURLRequest> substituteRequest = [loadDelegate webProcessPlugInBrowserContextController:pluginContextController frame:wrapper(*toImpl(frame)) willSendRequest:originalRequest
206             redirectResponse:toImpl(redirectResponse)->resourceResponse().nsURLResponse()];
207
208         if (substituteRequest != originalRequest)
209             return substituteRequest ? WKURLRequestCreateWithNSURLRequest(substituteRequest.get()) : nullptr;
210     }
211
212     WKRetain(request);
213     return request;
214 }
215
216 static void didInitiateLoadForResource(WKBundlePageRef, WKBundleFrameRef frame, uint64_t resourceIdentifier, WKURLRequestRef request, bool, const void* clientInfo)
217 {
218     WKWebProcessPlugInBrowserContextController *pluginContextController = (WKWebProcessPlugInBrowserContextController *)clientInfo;
219     auto loadDelegate = pluginContextController->_loadDelegate.get();
220
221     if ([loadDelegate respondsToSelector:@selector(webProcessPlugInBrowserContextController:frame:didInitiateLoadForResource:request:)]) {
222         [loadDelegate webProcessPlugInBrowserContextController:pluginContextController
223                                                          frame:wrapper(*toImpl(frame))
224                                     didInitiateLoadForResource:resourceIdentifier
225                                                        request:toImpl(request)->resourceRequest().nsURLRequest(DoNotUpdateHTTPBody)];
226     }
227 }
228
229 static void didFinishLoadForResource(WKBundlePageRef, WKBundleFrameRef frame, uint64_t resourceIdentifier, const void* clientInfo)
230 {
231     WKWebProcessPlugInBrowserContextController *pluginContextController = (WKWebProcessPlugInBrowserContextController *)clientInfo;
232     auto loadDelegate = pluginContextController->_loadDelegate.get();
233
234     if ([loadDelegate respondsToSelector:@selector(webProcessPlugInBrowserContextController:frame:didFinishLoadForResource:)]) {
235         [loadDelegate webProcessPlugInBrowserContextController:pluginContextController
236                                                          frame:wrapper(*toImpl(frame))
237                                       didFinishLoadForResource:resourceIdentifier];
238     }
239 }
240
241 static void didFailLoadForResource(WKBundlePageRef, WKBundleFrameRef frame, uint64_t resourceIdentifier, WKErrorRef error, const void* clientInfo)
242 {
243     WKWebProcessPlugInBrowserContextController *pluginContextController = (WKWebProcessPlugInBrowserContextController *)clientInfo;
244     auto loadDelegate = pluginContextController->_loadDelegate.get();
245
246     if ([loadDelegate respondsToSelector:@selector(webProcessPlugInBrowserContextController:frame:didFailLoadForResource:error:)]) {
247         [loadDelegate webProcessPlugInBrowserContextController:pluginContextController
248                                                          frame:wrapper(*toImpl(frame))
249                                         didFailLoadForResource:resourceIdentifier
250                                                          error:wrapper(*toImpl(error))];
251     }
252 }
253
254 static void setUpResourceLoadClient(WKWebProcessPlugInBrowserContextController *contextController, WebPage& page)
255 {
256     WKBundlePageResourceLoadClientV1 client;
257     memset(&client, 0, sizeof(client));
258
259     client.base.version = 1;
260     client.base.clientInfo = contextController;
261     client.willSendRequestForFrame = willSendRequestForFrame;
262     client.didInitiateLoadForResource = didInitiateLoadForResource;
263     client.didFinishLoadForResource = didFinishLoadForResource;
264     client.didFailLoadForResource = didFailLoadForResource;
265
266     page.initializeInjectedBundleResourceLoadClient(&client.base);
267 }
268
269 static void didFocusTextField(WKBundlePageRef page, WKBundleNodeHandleRef htmlInputElementHandleRef, WKBundleFrameRef frameRef, const void* clientInfo)
270 {
271     WKWebProcessPlugInBrowserContextController *controller = (WKWebProcessPlugInBrowserContextController *)clientInfo;
272     auto formDelegate = controller->_formDelegate.get();
273
274     if ([formDelegate respondsToSelector:@selector(_webProcessPlugInBrowserContextController:didFocusTextField:inFrame:)])
275         [formDelegate _webProcessPlugInBrowserContextController:controller didFocusTextField:wrapper(*toImpl(htmlInputElementHandleRef)) inFrame:wrapper(*toImpl(frameRef))];
276 }
277
278 static void setUpFormClient(WKWebProcessPlugInBrowserContextController *contextController, WebPage& page)
279 {
280     WKBundlePageFormClientV2 client;
281     memset(&client, 0, sizeof(client));
282
283     client.base.version = 2;
284     client.base.clientInfo = contextController;
285     client.didFocusTextField = didFocusTextField;
286
287     page.initializeInjectedBundleFormClient(&client.base);
288 }
289
290 - (id <WKWebProcessPlugInLoadDelegate>)loadDelegate
291 {
292     return _loadDelegate.getAutoreleased();
293 }
294
295 - (void)setLoadDelegate:(id <WKWebProcessPlugInLoadDelegate>)loadDelegate
296 {
297     _loadDelegate = loadDelegate;
298
299     if (loadDelegate) {
300         setUpPageLoaderClient(self, *_page);
301         setUpResourceLoadClient(self, *_page);
302     } else {
303         _page->initializeInjectedBundleLoaderClient(nullptr);
304         _page->initializeInjectedBundleResourceLoadClient(nullptr);
305     }
306 }
307
308 - (void)dealloc
309 {
310     _page->~WebPage();
311
312     [super dealloc];
313 }
314
315 - (WKDOMDocument *)mainFrameDocument
316 {
317     Frame* webCoreMainFrame = _page->mainFrame();
318     if (!webCoreMainFrame)
319         return nil;
320
321     return toWKDOMDocument(webCoreMainFrame->document());
322 }
323
324 - (WKDOMRange *)selectedRange
325 {
326     RefPtr<Range> range = _page->currentSelectionAsRange();
327     if (!range)
328         return nil;
329
330     return toWKDOMRange(range.get());
331 }
332
333 - (WKWebProcessPlugInFrame *)mainFrame
334 {
335     WebFrame *webKitMainFrame = _page->mainWebFrame();
336     if (!webKitMainFrame)
337         return nil;
338
339     return wrapper(*webKitMainFrame);
340 }
341
342 - (WKWebProcessPlugInPageGroup *)pageGroup
343 {
344     return wrapper(*_page->pageGroup());
345 }
346
347 #pragma mark WKObject protocol implementation
348
349 - (API::Object&)_apiObject
350 {
351     return *_page;
352 }
353
354 @end
355
356 @implementation WKWebProcessPlugInBrowserContextController (Private)
357
358 - (WKBundlePageRef)_bundlePageRef
359 {
360     return toAPI(_page.get());
361 }
362
363 - (WKBrowsingContextHandle *)handle
364 {
365     return [[[WKBrowsingContextHandle alloc] _initWithPageID:_page->pageID()] autorelease];
366 }
367
368 + (instancetype)lookUpBrowsingContextFromHandle:(WKBrowsingContextHandle *)handle
369 {
370     WebPage* webPage = WebProcess::shared().webPage(handle.pageID);
371     if (!webPage)
372         return nil;
373
374     return wrapper(*webPage);
375 }
376
377 - (WKRemoteObjectRegistry *)remoteObjectRegistry
378 {
379     if (!_remoteObjectRegistry) {
380         _remoteObjectRegistry = [[WKRemoteObjectRegistry alloc] _initWithMessageSender:*_page];
381         WebProcess::shared().addMessageReceiver(Messages::RemoteObjectRegistry::messageReceiverName(), _page->pageID(), [_remoteObjectRegistry remoteObjectRegistry]);
382     }
383
384     return _remoteObjectRegistry.get();
385 }
386
387 - (id <WKWebProcessPlugInFormDelegatePrivate>)_formDelegate
388 {
389     return _formDelegate.getAutoreleased();
390 }
391
392 - (void)_setFormDelegate:(id <WKWebProcessPlugInFormDelegatePrivate>)formDelegate
393 {
394     _formDelegate = formDelegate;
395
396     if (formDelegate)
397         setUpFormClient(self, *_page);
398     else
399         _page->initializeInjectedBundleFormClient(nullptr);
400 }
401
402 @end
403
404 #endif // WK_API_ENABLED