1 | /* |
2 | * Copyright (C) 2010-2018 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 | #include "config.h" |
27 | #include "WebFrameLoaderClient.h" |
28 | |
29 | #include "AuthenticationManager.h" |
30 | #include "DataReference.h" |
31 | #include "DrawingArea.h" |
32 | #include "FindController.h" |
33 | #include "FormDataReference.h" |
34 | #include "FrameInfoData.h" |
35 | #include "InjectedBundle.h" |
36 | #include "InjectedBundleDOMWindowExtension.h" |
37 | #include "InjectedBundleNavigationAction.h" |
38 | #include "Logging.h" |
39 | #include "NavigationActionData.h" |
40 | #include "NetworkConnectionToWebProcessMessages.h" |
41 | #include "NetworkProcessConnection.h" |
42 | #include "PluginView.h" |
43 | #include "UserData.h" |
44 | #include "WKBundleAPICast.h" |
45 | #include "WebAutomationSessionProxy.h" |
46 | #include "WebBackForwardListProxy.h" |
47 | #include "WebCoreArgumentCoders.h" |
48 | #include "WebDocumentLoader.h" |
49 | #include "WebErrors.h" |
50 | #include "WebEvent.h" |
51 | #include "WebFrame.h" |
52 | #include "WebFrameNetworkingContext.h" |
53 | #include "WebFullScreenManager.h" |
54 | #include "WebNavigationDataStore.h" |
55 | #include "WebPage.h" |
56 | #include "WebPageGroupProxy.h" |
57 | #include "WebPageProxyMessages.h" |
58 | #include "WebProcess.h" |
59 | #include "WebProcessPoolMessages.h" |
60 | #include "WebsitePoliciesData.h" |
61 | #include <JavaScriptCore/APICast.h> |
62 | #include <JavaScriptCore/JSObject.h> |
63 | #include <WebCore/CachedFrame.h> |
64 | #include <WebCore/CertificateInfo.h> |
65 | #include <WebCore/Chrome.h> |
66 | #include <WebCore/DOMWrapperWorld.h> |
67 | #include <WebCore/DocumentLoader.h> |
68 | #include <WebCore/FormState.h> |
69 | #include <WebCore/Frame.h> |
70 | #include <WebCore/FrameLoadRequest.h> |
71 | #include <WebCore/FrameLoader.h> |
72 | #include <WebCore/FrameLoaderTypes.h> |
73 | #include <WebCore/FrameView.h> |
74 | #include <WebCore/HTMLAppletElement.h> |
75 | #include <WebCore/HTMLFormElement.h> |
76 | #include <WebCore/HistoryController.h> |
77 | #include <WebCore/HistoryItem.h> |
78 | #include <WebCore/MIMETypeRegistry.h> |
79 | #include <WebCore/MouseEvent.h> |
80 | #include <WebCore/NotImplemented.h> |
81 | #include <WebCore/Page.h> |
82 | #include <WebCore/PluginData.h> |
83 | #include <WebCore/PluginDocument.h> |
84 | #include <WebCore/PolicyChecker.h> |
85 | #include <WebCore/ProgressTracker.h> |
86 | #include <WebCore/ResourceError.h> |
87 | #include <WebCore/ResourceRequest.h> |
88 | #include <WebCore/ScriptController.h> |
89 | #include <WebCore/SecurityOriginData.h> |
90 | #include <WebCore/Settings.h> |
91 | #include <WebCore/SubframeLoader.h> |
92 | #include <WebCore/UIEventWithKeyState.h> |
93 | #include <WebCore/Widget.h> |
94 | #include <WebCore/WindowFeatures.h> |
95 | #include <wtf/NeverDestroyed.h> |
96 | #include <wtf/ProcessID.h> |
97 | #include <wtf/ProcessPrivilege.h> |
98 | |
99 | namespace WebKit { |
100 | using namespace WebCore; |
101 | |
102 | WebFrameLoaderClient::WebFrameLoaderClient() |
103 | : m_frame(0) |
104 | , m_hasSentResponseToPluginView(false) |
105 | , m_didCompletePageTransition(false) |
106 | , m_frameHasCustomContentProvider(false) |
107 | , m_frameCameFromPageCache(false) |
108 | { |
109 | } |
110 | |
111 | WebFrameLoaderClient::~WebFrameLoaderClient() |
112 | { |
113 | } |
114 | |
115 | Optional<PageIdentifier> WebFrameLoaderClient::pageID() const |
116 | { |
117 | if (m_frame && m_frame->page()) |
118 | return m_frame->page()->pageID(); |
119 | |
120 | return WTF::nullopt; |
121 | } |
122 | |
123 | Optional<uint64_t> WebFrameLoaderClient::frameID() const |
124 | { |
125 | if (m_frame) |
126 | return m_frame->frameID(); |
127 | |
128 | return WTF::nullopt; |
129 | } |
130 | |
131 | PAL::SessionID WebFrameLoaderClient::sessionID() const |
132 | { |
133 | return m_frame && m_frame->page() ? m_frame->page()->sessionID() : PAL::SessionID::defaultSessionID(); |
134 | } |
135 | |
136 | void WebFrameLoaderClient::frameLoaderDestroyed() |
137 | { |
138 | m_frame->invalidate(); |
139 | |
140 | // Balances explicit ref() in WebFrame::create(). |
141 | m_frame->deref(); |
142 | } |
143 | |
144 | bool WebFrameLoaderClient::hasHTMLView() const |
145 | { |
146 | return !m_frameHasCustomContentProvider; |
147 | } |
148 | |
149 | bool WebFrameLoaderClient::hasWebView() const |
150 | { |
151 | return m_frame->page(); |
152 | } |
153 | |
154 | void WebFrameLoaderClient::makeRepresentation(DocumentLoader*) |
155 | { |
156 | notImplemented(); |
157 | } |
158 | |
159 | void WebFrameLoaderClient::forceLayoutForNonHTML() |
160 | { |
161 | notImplemented(); |
162 | } |
163 | |
164 | void WebFrameLoaderClient::setCopiesOnScroll() |
165 | { |
166 | notImplemented(); |
167 | } |
168 | |
169 | void WebFrameLoaderClient::detachedFromParent2() |
170 | { |
171 | WebPage* webPage = m_frame->page(); |
172 | if (!webPage) |
173 | return; |
174 | |
175 | #if ENABLE(RESOURCE_LOAD_STATISTICS) |
176 | if (m_hasFrameSpecificStorageAccess) { |
177 | WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::RemoveStorageAccessForFrame(sessionID(), frameID().value(), pageID().value()), 0); |
178 | m_hasFrameSpecificStorageAccess = false; |
179 | } |
180 | #endif |
181 | |
182 | RefPtr<API::Object> userData; |
183 | |
184 | // Notify the bundle client. |
185 | webPage->injectedBundleLoaderClient().didRemoveFrameFromHierarchy(*webPage, *m_frame, userData); |
186 | } |
187 | |
188 | void WebFrameLoaderClient::detachedFromParent3() |
189 | { |
190 | notImplemented(); |
191 | } |
192 | |
193 | void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request) |
194 | { |
195 | WebPage* webPage = m_frame->page(); |
196 | if (!webPage) |
197 | return; |
198 | |
199 | bool pageIsProvisionallyLoading = false; |
200 | if (FrameLoader* frameLoader = loader->frameLoader()) |
201 | pageIsProvisionallyLoading = frameLoader->provisionalDocumentLoader() == loader; |
202 | |
203 | webPage->injectedBundleResourceLoadClient().didInitiateLoadForResource(*webPage, *m_frame, identifier, request, pageIsProvisionallyLoading); |
204 | webPage->addResourceRequest(identifier, request); |
205 | } |
206 | |
207 | void WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse) |
208 | { |
209 | WebPage* webPage = m_frame->page(); |
210 | if (!webPage) |
211 | return; |
212 | |
213 | // The API can return a completely new request. We should ensure that at least the requester |
214 | // is kept, so that if this is a main resource load it's still considered as such. |
215 | auto requester = request.requester(); |
216 | webPage->injectedBundleResourceLoadClient().willSendRequestForFrame(*webPage, *m_frame, identifier, request, redirectResponse); |
217 | if (!request.isNull()) |
218 | request.setRequester(requester); |
219 | } |
220 | |
221 | bool WebFrameLoaderClient::shouldUseCredentialStorage(DocumentLoader*, unsigned long identifier) |
222 | { |
223 | WebPage* webPage = m_frame->page(); |
224 | if (!webPage) |
225 | return true; |
226 | |
227 | return webPage->injectedBundleResourceLoadClient().shouldUseCredentialStorage(*webPage, *m_frame, identifier); |
228 | } |
229 | |
230 | void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long, const AuthenticationChallenge&) |
231 | { |
232 | ASSERT_NOT_REACHED(); |
233 | } |
234 | |
235 | #if USE(PROTECTION_SPACE_AUTH_CALLBACK) |
236 | bool WebFrameLoaderClient::canAuthenticateAgainstProtectionSpace(DocumentLoader*, unsigned long, const ProtectionSpace& protectionSpace) |
237 | { |
238 | // The WebKit 2 Networking process asks the UIProcess directly, so the WebContent process should never receive this callback. |
239 | ASSERT_NOT_REACHED(); |
240 | return false; |
241 | } |
242 | #endif |
243 | |
244 | void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse& response) |
245 | { |
246 | WebPage* webPage = m_frame->page(); |
247 | if (!webPage) |
248 | return; |
249 | |
250 | webPage->injectedBundleResourceLoadClient().didReceiveResponseForResource(*webPage, *m_frame, identifier, response); |
251 | } |
252 | |
253 | void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int dataLength) |
254 | { |
255 | WebPage* webPage = m_frame->page(); |
256 | if (!webPage) |
257 | return; |
258 | |
259 | webPage->injectedBundleResourceLoadClient().didReceiveContentLengthForResource(*webPage, *m_frame, identifier, dataLength); |
260 | } |
261 | |
262 | #if ENABLE(DATA_DETECTION) |
263 | void WebFrameLoaderClient::dispatchDidFinishDataDetection(NSArray *detectionResults) |
264 | { |
265 | WebPage* webPage = m_frame->page(); |
266 | if (!webPage) |
267 | return; |
268 | webPage->setDataDetectionResults(detectionResults); |
269 | } |
270 | #endif |
271 | |
272 | void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier) |
273 | { |
274 | WebPage* webPage = m_frame->page(); |
275 | if (!webPage) |
276 | return; |
277 | |
278 | webPage->injectedBundleResourceLoadClient().didFinishLoadForResource(*webPage, *m_frame, identifier); |
279 | webPage->removeResourceRequest(identifier); |
280 | } |
281 | |
282 | void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError& error) |
283 | { |
284 | WebPage* webPage = m_frame->page(); |
285 | if (!webPage) |
286 | return; |
287 | |
288 | webPage->injectedBundleResourceLoadClient().didFailLoadForResource(*webPage, *m_frame, identifier, error); |
289 | webPage->removeResourceRequest(identifier); |
290 | } |
291 | |
292 | bool WebFrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int /*length*/) |
293 | { |
294 | notImplemented(); |
295 | return false; |
296 | } |
297 | |
298 | void WebFrameLoaderClient::dispatchDidDispatchOnloadEvents() |
299 | { |
300 | WebPage* webPage = m_frame->page(); |
301 | if (!webPage) |
302 | return; |
303 | |
304 | // Notify the bundle client. |
305 | webPage->injectedBundleLoaderClient().didHandleOnloadEventsForFrame(*webPage, *m_frame); |
306 | } |
307 | |
308 | void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad() |
309 | { |
310 | WebPage* webPage = m_frame->page(); |
311 | if (!webPage) |
312 | return; |
313 | |
314 | WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().provisionalDocumentLoader()); |
315 | RefPtr<API::Object> userData; |
316 | |
317 | LOG(Loading, "WebProcess %i - dispatchDidReceiveServerRedirectForProvisionalLoad to request url %s" , getCurrentProcessID(), documentLoader.request().url().string().utf8().data()); |
318 | |
319 | // Notify the bundle client. |
320 | webPage->injectedBundleLoaderClient().didReceiveServerRedirectForProvisionalLoadForFrame(*webPage, *m_frame, userData); |
321 | |
322 | // Notify the UIProcess. |
323 | webPage->send(Messages::WebPageProxy::DidReceiveServerRedirectForProvisionalLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), documentLoader.request(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
324 | } |
325 | |
326 | void WebFrameLoaderClient::dispatchDidChangeProvisionalURL() |
327 | { |
328 | WebPage* webPage = m_frame->page(); |
329 | if (!webPage) |
330 | return; |
331 | |
332 | WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().provisionalDocumentLoader()); |
333 | webPage->send(Messages::WebPageProxy::DidChangeProvisionalURLForFrame(m_frame->frameID(), documentLoader.navigationID(), documentLoader.url())); |
334 | } |
335 | |
336 | void WebFrameLoaderClient::dispatchDidCancelClientRedirect() |
337 | { |
338 | WebPage* webPage = m_frame->page(); |
339 | if (!webPage) |
340 | return; |
341 | |
342 | // Notify the bundle client. |
343 | webPage->injectedBundleLoaderClient().didCancelClientRedirectForFrame(*webPage, *m_frame); |
344 | |
345 | // Notify the UIProcess. |
346 | webPage->send(Messages::WebPageProxy::DidCancelClientRedirectForFrame(m_frame->frameID())); |
347 | } |
348 | |
349 | void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const URL& url, double interval, WallTime fireDate, LockBackForwardList lockBackForwardList) |
350 | { |
351 | WebPage* webPage = m_frame->page(); |
352 | if (!webPage) |
353 | return; |
354 | |
355 | // Notify the bundle client. |
356 | webPage->injectedBundleLoaderClient().willPerformClientRedirectForFrame(*webPage, *m_frame, url, interval, fireDate); |
357 | |
358 | // Notify the UIProcess. |
359 | webPage->send(Messages::WebPageProxy::WillPerformClientRedirectForFrame(m_frame->frameID(), url.string(), interval, lockBackForwardList)); |
360 | } |
361 | |
362 | void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage() |
363 | { |
364 | WebPage* webPage = m_frame->page(); |
365 | if (!webPage) |
366 | return; |
367 | |
368 | RefPtr<API::Object> userData; |
369 | |
370 | auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID(); |
371 | |
372 | // Notify the bundle client. |
373 | webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(*webPage, *m_frame, SameDocumentNavigationAnchorNavigation, userData); |
374 | |
375 | // Notify the UIProcess. |
376 | webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationAnchorNavigation, m_frame->coreFrame()->document()->url(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
377 | } |
378 | |
379 | void WebFrameLoaderClient::dispatchDidChangeMainDocument() |
380 | { |
381 | WebPage* webPage = m_frame->page(); |
382 | if (!webPage) |
383 | return; |
384 | |
385 | webPage->send(Messages::WebPageProxy::DidChangeMainDocument(m_frame->frameID())); |
386 | } |
387 | |
388 | void WebFrameLoaderClient::dispatchWillChangeDocument(const URL& currentUrl, const URL& newUrl) |
389 | { |
390 | #if ENABLE(RESOURCE_LOAD_STATISTICS) |
391 | if (m_frame->isMainFrame()) |
392 | return; |
393 | |
394 | WebPage* webPage = m_frame->page(); |
395 | if (!webPage) |
396 | return; |
397 | |
398 | if (m_hasFrameSpecificStorageAccess && !WebCore::areRegistrableDomainsEqual(currentUrl, newUrl)) { |
399 | WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::RemoveStorageAccessForFrame(sessionID(), frameID().value(), pageID().value()), 0); |
400 | m_hasFrameSpecificStorageAccess = false; |
401 | } |
402 | #endif |
403 | } |
404 | |
405 | void WebFrameLoaderClient::dispatchDidPushStateWithinPage() |
406 | { |
407 | WebPage* webPage = m_frame->page(); |
408 | if (!webPage) |
409 | return; |
410 | |
411 | RefPtr<API::Object> userData; |
412 | |
413 | auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID(); |
414 | |
415 | // Notify the bundle client. |
416 | webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(*webPage, *m_frame, SameDocumentNavigationSessionStatePush, userData); |
417 | |
418 | // Notify the UIProcess. |
419 | webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationSessionStatePush, m_frame->coreFrame()->document()->url(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
420 | } |
421 | |
422 | void WebFrameLoaderClient::dispatchDidReplaceStateWithinPage() |
423 | { |
424 | WebPage* webPage = m_frame->page(); |
425 | if (!webPage) |
426 | return; |
427 | |
428 | RefPtr<API::Object> userData; |
429 | |
430 | auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID(); |
431 | |
432 | // Notify the bundle client. |
433 | webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(*webPage, *m_frame, SameDocumentNavigationSessionStateReplace, userData); |
434 | |
435 | // Notify the UIProcess. |
436 | webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationSessionStateReplace, m_frame->coreFrame()->document()->url(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
437 | } |
438 | |
439 | void WebFrameLoaderClient::dispatchDidPopStateWithinPage() |
440 | { |
441 | WebPage* webPage = m_frame->page(); |
442 | if (!webPage) |
443 | return; |
444 | |
445 | RefPtr<API::Object> userData; |
446 | |
447 | auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID(); |
448 | |
449 | // Notify the bundle client. |
450 | webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(*webPage, *m_frame, SameDocumentNavigationSessionStatePop, userData); |
451 | |
452 | // Notify the UIProcess. |
453 | webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationSessionStatePop, m_frame->coreFrame()->document()->url(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
454 | } |
455 | |
456 | void WebFrameLoaderClient::dispatchWillClose() |
457 | { |
458 | notImplemented(); |
459 | } |
460 | |
461 | void WebFrameLoaderClient::dispatchDidExplicitOpen(const URL& url) |
462 | { |
463 | auto* webPage = m_frame->page(); |
464 | if (!webPage) |
465 | return; |
466 | |
467 | // Notify the UIProcess. |
468 | webPage->send(Messages::WebPageProxy::DidExplicitOpenForFrame(m_frame->frameID(), url)); |
469 | } |
470 | |
471 | void WebFrameLoaderClient::dispatchDidStartProvisionalLoad() |
472 | { |
473 | WebPage* webPage = m_frame->page(); |
474 | if (!webPage) |
475 | return; |
476 | |
477 | #if ENABLE(FULLSCREEN_API) |
478 | Element* documentElement = m_frame->coreFrame()->document()->documentElement(); |
479 | if (documentElement && documentElement->containsFullScreenElement()) |
480 | webPage->fullScreenManager()->exitFullScreenForElement(webPage->fullScreenManager()->element()); |
481 | #endif |
482 | |
483 | webPage->findController().hideFindUI(); |
484 | webPage->sandboxExtensionTracker().didStartProvisionalLoad(m_frame); |
485 | |
486 | WebDocumentLoader& provisionalLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().provisionalDocumentLoader()); |
487 | auto& url = provisionalLoader.url(); |
488 | RefPtr<API::Object> userData; |
489 | |
490 | // Notify the bundle client. |
491 | webPage->injectedBundleLoaderClient().didStartProvisionalLoadForFrame(*webPage, *m_frame, userData); |
492 | |
493 | auto& unreachableURL = provisionalLoader.unreachableURL(); |
494 | |
495 | // Notify the UIProcess. |
496 | webPage->send(Messages::WebPageProxy::DidStartProvisionalLoadForFrame(m_frame->frameID(), provisionalLoader.navigationID(), url, unreachableURL, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
497 | } |
498 | |
499 | static constexpr unsigned maxTitleLength = 1000; // Closest power of 10 above the W3C recommendation for Title length. |
500 | |
501 | void WebFrameLoaderClient::dispatchDidReceiveTitle(const StringWithDirection& title) |
502 | { |
503 | WebPage* webPage = m_frame->page(); |
504 | if (!webPage) |
505 | return; |
506 | |
507 | auto truncatedTitle = truncateFromEnd(title, maxTitleLength); |
508 | |
509 | RefPtr<API::Object> userData; |
510 | |
511 | // Notify the bundle client. |
512 | // FIXME: Use direction of title. |
513 | webPage->injectedBundleLoaderClient().didReceiveTitleForFrame(*webPage, truncatedTitle.string, *m_frame, userData); |
514 | |
515 | // Notify the UIProcess. |
516 | webPage->send(Messages::WebPageProxy::DidReceiveTitleForFrame(m_frame->frameID(), truncatedTitle.string, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
517 | } |
518 | |
519 | void WebFrameLoaderClient::dispatchDidCommitLoad(Optional<HasInsecureContent> hasInsecureContent) |
520 | { |
521 | WebPage* webPage = m_frame->page(); |
522 | if (!webPage) |
523 | return; |
524 | |
525 | WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()); |
526 | RefPtr<API::Object> userData; |
527 | |
528 | // Notify the bundle client. |
529 | webPage->injectedBundleLoaderClient().didCommitLoadForFrame(*webPage, *m_frame, userData); |
530 | |
531 | webPage->sandboxExtensionTracker().didCommitProvisionalLoad(m_frame); |
532 | |
533 | // Notify the UIProcess. |
534 | webPage->send(Messages::WebPageProxy::DidCommitLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), documentLoader.response().mimeType(), m_frameHasCustomContentProvider, static_cast<uint32_t>(m_frame->coreFrame()->loader().loadType()), valueOrCompute(documentLoader.response().certificateInfo(), [] { return CertificateInfo(); }), m_frame->coreFrame()->document()->isPluginDocument(), hasInsecureContent, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
535 | webPage->didCommitLoad(m_frame); |
536 | } |
537 | |
538 | void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error, WillContinueLoading willContinueLoading) |
539 | { |
540 | WebPage* webPage = m_frame->page(); |
541 | if (!webPage) |
542 | return; |
543 | |
544 | RELEASE_LOG(Network, "%p - WebFrameLoaderClient::dispatchDidFailProvisionalLoad: (pageID = %" PRIu64 ", frameID = %" PRIu64 ")" , this, webPage->pageID().toUInt64(), m_frame->frameID()); |
545 | |
546 | RefPtr<API::Object> userData; |
547 | |
548 | // Notify the bundle client. |
549 | webPage->injectedBundleLoaderClient().didFailProvisionalLoadWithErrorForFrame(*webPage, *m_frame, error, userData); |
550 | |
551 | webPage->sandboxExtensionTracker().didFailProvisionalLoad(m_frame); |
552 | |
553 | // FIXME: This is gross. This is necessary because if the client calls WKBundlePageStopLoading() from within the didFailProvisionalLoadWithErrorForFrame |
554 | // injected bundle client call, that will cause the provisional DocumentLoader to be disconnected from the Frame, and didDistroyNavigation message |
555 | // to be sent to the UIProcess (and the destruction of the DocumentLoader). If that happens, and we had captured the navigationID before injected bundle |
556 | // client call, the DidFailProvisionalLoadForFrame would send a navigationID of a destroyed Navigation, and the UIProcess would not be able to find it |
557 | // in its table. |
558 | // |
559 | // A better solution to this problem would be find a clean way to postpone the disconnection of the DocumentLoader from the Frame until |
560 | // the entire FrameLoaderClient function was complete. |
561 | uint64_t navigationID = 0; |
562 | if (auto documentLoader = m_frame->coreFrame()->loader().provisionalDocumentLoader()) |
563 | navigationID = static_cast<WebDocumentLoader*>(documentLoader)->navigationID(); |
564 | |
565 | // Notify the UIProcess. |
566 | WebCore::Frame* coreFrame = m_frame ? m_frame->coreFrame() : nullptr; |
567 | webPage->send(Messages::WebPageProxy::DidFailProvisionalLoadForFrame(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), navigationID, m_frame->coreFrame()->loader().provisionalLoadErrorBeingHandledURL(), error, willContinueLoading, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
568 | |
569 | // If we have a load listener, notify it. |
570 | if (WebFrame::LoadListener* loadListener = m_frame->loadListener()) |
571 | loadListener->didFailLoad(m_frame, error.isCancellation()); |
572 | } |
573 | |
574 | void WebFrameLoaderClient::dispatchDidFailLoad(const ResourceError& error) |
575 | { |
576 | WebPage* webPage = m_frame->page(); |
577 | if (!webPage) |
578 | return; |
579 | |
580 | RELEASE_LOG(Network, "%p - WebFrameLoaderClient::dispatchDidFailLoad: (pageID = %" PRIu64 ", frameID = %" PRIu64 ")" , this, webPage->pageID().toUInt64(), m_frame->frameID()); |
581 | |
582 | RefPtr<API::Object> userData; |
583 | |
584 | auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID(); |
585 | |
586 | // Notify the bundle client. |
587 | webPage->injectedBundleLoaderClient().didFailLoadWithErrorForFrame(*webPage, *m_frame, error, userData); |
588 | |
589 | // Notify the UIProcess. |
590 | webPage->send(Messages::WebPageProxy::DidFailLoadForFrame(m_frame->frameID(), navigationID, error, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
591 | |
592 | // If we have a load listener, notify it. |
593 | if (WebFrame::LoadListener* loadListener = m_frame->loadListener()) |
594 | loadListener->didFailLoad(m_frame, error.isCancellation()); |
595 | } |
596 | |
597 | void WebFrameLoaderClient::dispatchDidFinishDocumentLoad() |
598 | { |
599 | WebPage* webPage = m_frame->page(); |
600 | if (!webPage) |
601 | return; |
602 | |
603 | RefPtr<API::Object> userData; |
604 | |
605 | auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID(); |
606 | |
607 | // Notify the bundle client. |
608 | webPage->injectedBundleLoaderClient().didFinishDocumentLoadForFrame(*webPage, *m_frame, userData); |
609 | |
610 | // Notify the UIProcess. |
611 | webPage->send(Messages::WebPageProxy::DidFinishDocumentLoadForFrame(m_frame->frameID(), navigationID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
612 | |
613 | webPage->didFinishDocumentLoad(*m_frame); |
614 | } |
615 | |
616 | void WebFrameLoaderClient::dispatchDidFinishLoad() |
617 | { |
618 | WebPage* webPage = m_frame->page(); |
619 | if (!webPage) |
620 | return; |
621 | |
622 | RefPtr<API::Object> userData; |
623 | |
624 | auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID(); |
625 | |
626 | // Notify the bundle client. |
627 | webPage->injectedBundleLoaderClient().didFinishLoadForFrame(*webPage, *m_frame, userData); |
628 | |
629 | // Notify the UIProcess. |
630 | webPage->send(Messages::WebPageProxy::DidFinishLoadForFrame(m_frame->frameID(), navigationID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
631 | |
632 | // If we have a load listener, notify it. |
633 | if (WebFrame::LoadListener* loadListener = m_frame->loadListener()) |
634 | loadListener->didFinishLoad(m_frame); |
635 | |
636 | webPage->didFinishLoad(*m_frame); |
637 | } |
638 | |
639 | void WebFrameLoaderClient::forcePageTransitionIfNeeded() |
640 | { |
641 | if (m_didCompletePageTransition) |
642 | return; |
643 | |
644 | WebPage* webPage = m_frame->page(); |
645 | if (!webPage) |
646 | return; |
647 | |
648 | webPage->didCompletePageTransition(); |
649 | m_didCompletePageTransition = true; |
650 | } |
651 | |
652 | void WebFrameLoaderClient::dispatchDidReachLayoutMilestone(OptionSet<WebCore::LayoutMilestone> milestones) |
653 | { |
654 | WebPage* webPage = m_frame->page(); |
655 | if (!webPage) |
656 | return; |
657 | |
658 | RefPtr<API::Object> userData; |
659 | |
660 | if (milestones & DidFirstLayout) { |
661 | RELEASE_LOG(Layout, "%p - WebFrameLoaderClient::dispatchDidReachLayoutMilestone: dispatching DidFirstLayoutForFrame, page = %p" , this, webPage); |
662 | |
663 | // FIXME: We should consider removing the old didFirstLayout API since this is doing double duty with the |
664 | // new didLayout API. |
665 | webPage->injectedBundleLoaderClient().didFirstLayoutForFrame(*webPage, *m_frame, userData); |
666 | webPage->send(Messages::WebPageProxy::DidFirstLayoutForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
667 | |
668 | #if PLATFORM(MAC) |
669 | // FIXME: Do this on DidFirstVisuallyNonEmptyLayout when Mac Safari is able to handle it (<rdar://problem/17580021>) |
670 | if (m_frame->isMainFrame() && !m_didCompletePageTransition && !webPage->corePage()->settings().suppressesIncrementalRendering()) { |
671 | RELEASE_LOG(Layout, "%p - WebFrameLoaderClient::dispatchDidReachLayoutMilestone: dispatching didCompletePageTransition, page = %p" , this, webPage); |
672 | webPage->didCompletePageTransition(); |
673 | m_didCompletePageTransition = true; |
674 | } |
675 | #endif |
676 | |
677 | #if USE(COORDINATED_GRAPHICS) |
678 | // Make sure viewport properties are dispatched on the main frame by the time the first layout happens. |
679 | ASSERT(!webPage->useFixedLayout() || m_frame != m_frame->page()->mainWebFrame() || m_frame->coreFrame()->document()->didDispatchViewportPropertiesChanged()); |
680 | #endif |
681 | } |
682 | |
683 | #if !RELEASE_LOG_DISABLED |
684 | StringBuilder builder; |
685 | auto addIfSet = [&milestones, &builder] (WebCore::LayoutMilestone milestone, const String& toAdd) { |
686 | if (milestones.contains(milestone)) { |
687 | if (!builder.isEmpty()) |
688 | builder.append(", " ); |
689 | builder.append(toAdd); |
690 | } |
691 | }; |
692 | |
693 | addIfSet(DidFirstLayout, "DidFirstLayout"_s ); |
694 | addIfSet(DidFirstVisuallyNonEmptyLayout, "DidFirstVisuallyNonEmptyLayout"_s ); |
695 | addIfSet(DidHitRelevantRepaintedObjectsAreaThreshold, "DidHitRelevantRepaintedObjectsAreaThreshold"_s ); |
696 | addIfSet(DidFirstFlushForHeaderLayer, "DidFirstFlushForHeaderLayer"_s ); |
697 | addIfSet(DidFirstLayoutAfterSuppressedIncrementalRendering, "DidFirstLayoutAfterSuppressedIncrementalRendering"_s ); |
698 | addIfSet(DidFirstPaintAfterSuppressedIncrementalRendering, "DidFirstPaintAfterSuppressedIncrementalRendering"_s ); |
699 | addIfSet(ReachedSessionRestorationRenderTreeSizeThreshold, "ReachedSessionRestorationRenderTreeSizeThreshold"_s ); |
700 | addIfSet(DidRenderSignificantAmountOfText, "DidRenderSignificantAmountOfText"_s ); |
701 | addIfSet(DidFirstMeaningfulPaint, "DidFirstMeaningfulPaint"_s ); |
702 | |
703 | RELEASE_LOG(Layout, "%p - WebFrameLoaderClient::dispatchDidReachLayoutMilestone: dispatching DidReachLayoutMilestone, page = %p, milestones = %{public}s" , this, webPage, builder.toString().utf8().data()); |
704 | #endif |
705 | |
706 | // Send this after DidFirstLayout-specific calls since some clients expect to get those messages first. |
707 | webPage->dispatchDidReachLayoutMilestone(milestones); |
708 | |
709 | if (milestones & DidFirstVisuallyNonEmptyLayout) { |
710 | if (m_frame->isMainFrame() && !m_didCompletePageTransition && !webPage->corePage()->settings().suppressesIncrementalRendering()) { |
711 | RELEASE_LOG(Layout, "%p - WebFrameLoaderClient::dispatchDidReachLayoutMilestone: dispatching didCompletePageTransition, page = %p" , this, webPage); |
712 | webPage->didCompletePageTransition(); |
713 | m_didCompletePageTransition = true; |
714 | } |
715 | |
716 | // FIXME: We should consider removing the old didFirstVisuallyNonEmptyLayoutForFrame API since this is doing |
717 | // double duty with the new didLayout API. |
718 | RELEASE_LOG(Layout, "%p - WebFrameLoaderClient::dispatchDidReachLayoutMilestone: dispatching DidFirstVisuallyNonEmptyLayoutForFrame, page = %p" , this, webPage); |
719 | webPage->injectedBundleLoaderClient().didFirstVisuallyNonEmptyLayoutForFrame(*webPage, *m_frame, userData); |
720 | webPage->send(Messages::WebPageProxy::DidFirstVisuallyNonEmptyLayoutForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
721 | } |
722 | } |
723 | |
724 | void WebFrameLoaderClient::dispatchDidLayout() |
725 | { |
726 | WebPage* webPage = m_frame->page(); |
727 | if (!webPage) |
728 | return; |
729 | |
730 | // Notify the bundle client. |
731 | webPage->injectedBundleLoaderClient().didLayoutForFrame(*webPage, *m_frame); |
732 | |
733 | webPage->recomputeShortCircuitHorizontalWheelEventsState(); |
734 | |
735 | #if PLATFORM(IOS_FAMILY) |
736 | webPage->updateSelectionAppearance(); |
737 | #endif |
738 | |
739 | // NOTE: Unlike the other layout notifications, this does not notify the |
740 | // the UIProcess for every call. |
741 | |
742 | if (m_frame == m_frame->page()->mainWebFrame()) { |
743 | // FIXME: Remove at the soonest possible time. |
744 | webPage->send(Messages::WebPageProxy::SetRenderTreeSize(webPage->renderTreeSize())); |
745 | webPage->mainFrameDidLayout(); |
746 | } |
747 | } |
748 | |
749 | Frame* WebFrameLoaderClient::dispatchCreatePage(const NavigationAction& navigationAction) |
750 | { |
751 | WebPage* webPage = m_frame->page(); |
752 | if (!webPage) |
753 | return nullptr; |
754 | |
755 | // Just call through to the chrome client. |
756 | FrameLoadRequest frameLoadRequest { *m_frame->coreFrame()->document(), m_frame->coreFrame()->document()->securityOrigin(), navigationAction.resourceRequest(), { }, LockHistory::No, LockBackForwardList::No, MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, navigationAction.shouldOpenExternalURLsPolicy(), InitiatedByMainFrame::Unknown }; |
757 | Page* newPage = webPage->corePage()->chrome().createWindow(*m_frame->coreFrame(), frameLoadRequest, { }, navigationAction); |
758 | if (!newPage) |
759 | return nullptr; |
760 | |
761 | return &newPage->mainFrame(); |
762 | } |
763 | |
764 | void WebFrameLoaderClient::dispatchShow() |
765 | { |
766 | WebPage* webPage = m_frame->page(); |
767 | if (!webPage) |
768 | return; |
769 | |
770 | webPage->show(); |
771 | } |
772 | |
773 | void WebFrameLoaderClient::dispatchDecidePolicyForResponse(const ResourceResponse& response, const ResourceRequest& request, WebCore::PolicyCheckIdentifier identifier, const String& downloadAttribute, FramePolicyFunction&& function) |
774 | { |
775 | WebPage* webPage = m_frame ? m_frame->page() : nullptr; |
776 | if (!webPage) { |
777 | function(PolicyAction::Ignore, identifier); |
778 | return; |
779 | } |
780 | |
781 | if (!request.url().string()) { |
782 | function(PolicyAction::Use, identifier); |
783 | return; |
784 | } |
785 | |
786 | RefPtr<API::Object> userData; |
787 | |
788 | // Notify the bundle client. |
789 | WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForResponse(webPage, m_frame, response, request, userData); |
790 | if (policy == WKBundlePagePolicyActionUse) { |
791 | function(PolicyAction::Use, identifier); |
792 | return; |
793 | } |
794 | |
795 | bool canShowResponse = webPage->canShowResponse(response); |
796 | |
797 | WebCore::Frame* coreFrame = m_frame->coreFrame(); |
798 | auto* policyDocumentLoader = coreFrame ? coreFrame->loader().provisionalDocumentLoader() : nullptr; |
799 | auto navigationID = policyDocumentLoader ? static_cast<WebDocumentLoader&>(*policyDocumentLoader).navigationID() : 0; |
800 | |
801 | Ref<WebFrame> protector(*m_frame); |
802 | uint64_t listenerID = m_frame->setUpPolicyListener(identifier, WTFMove(function), WebFrame::ForNavigationAction::No); |
803 | if (!webPage->send(Messages::WebPageProxy::DecidePolicyForResponse(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), identifier, navigationID, response, request, |
804 | canShowResponse, downloadAttribute, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())))) |
805 | m_frame->didReceivePolicyDecision(listenerID, identifier, PolicyAction::Ignore, 0, { }, { }); |
806 | } |
807 | |
808 | void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(const NavigationAction& navigationAction, const ResourceRequest& request, |
809 | FormState* formState, const String& frameName, WebCore::PolicyCheckIdentifier identifier, FramePolicyFunction&& function) |
810 | { |
811 | WebPage* webPage = m_frame ? m_frame->page() : nullptr; |
812 | if (!webPage) { |
813 | function(PolicyAction::Ignore, identifier); |
814 | return; |
815 | } |
816 | |
817 | RefPtr<API::Object> userData; |
818 | |
819 | auto action = InjectedBundleNavigationAction::create(m_frame, navigationAction, formState); |
820 | |
821 | // Notify the bundle client. |
822 | WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForNewWindowAction(webPage, m_frame, action.ptr(), request, frameName, userData); |
823 | if (policy == WKBundlePagePolicyActionUse) { |
824 | function(PolicyAction::Use, identifier); |
825 | return; |
826 | } |
827 | |
828 | uint64_t listenerID = m_frame->setUpPolicyListener(identifier, WTFMove(function), WebFrame::ForNavigationAction::No); |
829 | |
830 | NavigationActionData navigationActionData; |
831 | navigationActionData.navigationType = action->navigationType(); |
832 | navigationActionData.modifiers = action->modifiers(); |
833 | navigationActionData.mouseButton = action->mouseButton(); |
834 | navigationActionData.syntheticClickType = action->syntheticClickType(); |
835 | navigationActionData.clickLocationInRootViewCoordinates = action->clickLocationInRootViewCoordinates(); |
836 | navigationActionData.userGestureTokenIdentifier = WebProcess::singleton().userGestureTokenIdentifier(navigationAction.userGestureToken()); |
837 | navigationActionData.canHandleRequest = webPage->canHandleRequest(request); |
838 | navigationActionData.shouldOpenExternalURLsPolicy = navigationAction.shouldOpenExternalURLsPolicy(); |
839 | navigationActionData.downloadAttribute = navigationAction.downloadAttribute(); |
840 | |
841 | WebCore::Frame* coreFrame = m_frame ? m_frame->coreFrame() : nullptr; |
842 | webPage->send(Messages::WebPageProxy::DecidePolicyForNewWindowAction(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), identifier, navigationActionData, request, |
843 | frameName, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
844 | } |
845 | |
846 | void WebFrameLoaderClient::applyToDocumentLoader(WebsitePoliciesData&& websitePolicies) |
847 | { |
848 | if (!m_frame) |
849 | return; |
850 | auto* coreFrame = m_frame->coreFrame(); |
851 | if (!coreFrame) |
852 | return; |
853 | WebDocumentLoader* documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().policyDocumentLoader()); |
854 | if (!documentLoader) |
855 | documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().provisionalDocumentLoader()); |
856 | if (!documentLoader) |
857 | documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().documentLoader()); |
858 | if (!documentLoader) |
859 | return; |
860 | |
861 | WebsitePoliciesData::applyToDocumentLoader(WTFMove(websitePolicies), *documentLoader); |
862 | } |
863 | |
864 | void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(const NavigationAction& navigationAction, const ResourceRequest& request, const ResourceResponse& redirectResponse, |
865 | FormState* formState, PolicyDecisionMode policyDecisionMode, WebCore::PolicyCheckIdentifier requestIdentifier, FramePolicyFunction&& function) |
866 | { |
867 | WebPage* webPage = m_frame ? m_frame->page() : nullptr; |
868 | if (!webPage) { |
869 | function(PolicyAction::Ignore, requestIdentifier); |
870 | return; |
871 | } |
872 | |
873 | LOG(Loading, "WebProcess %i - dispatchDecidePolicyForNavigationAction to request url %s" , getCurrentProcessID(), request.url().string().utf8().data()); |
874 | |
875 | // Always ignore requests with empty URLs. |
876 | if (request.isEmpty()) { |
877 | function(PolicyAction::Ignore, requestIdentifier); |
878 | return; |
879 | } |
880 | |
881 | RefPtr<API::Object> userData; |
882 | |
883 | Ref<InjectedBundleNavigationAction> action = InjectedBundleNavigationAction::create(m_frame, navigationAction, formState); |
884 | |
885 | // Notify the bundle client. |
886 | WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForNavigationAction(webPage, m_frame, action.ptr(), request, userData); |
887 | if (policy == WKBundlePagePolicyActionUse) { |
888 | function(PolicyAction::Use, requestIdentifier); |
889 | return; |
890 | } |
891 | |
892 | uint64_t listenerID = m_frame->setUpPolicyListener(requestIdentifier, WTFMove(function), WebFrame::ForNavigationAction::Yes); |
893 | |
894 | ASSERT(navigationAction.requester()); |
895 | auto requester = navigationAction.requester().value(); |
896 | |
897 | FrameInfoData originatingFrameInfoData; |
898 | originatingFrameInfoData.isMainFrame = navigationAction.initiatedByMainFrame() == InitiatedByMainFrame::Yes; |
899 | originatingFrameInfoData.request = ResourceRequest { requester.url() }; |
900 | originatingFrameInfoData.securityOrigin = requester.securityOrigin().data(); |
901 | if (requester.frameID() && WebProcess::singleton().webFrame(requester.frameID())) |
902 | originatingFrameInfoData.frameID = requester.frameID(); |
903 | |
904 | Optional<PageIdentifier> originatingPageID; |
905 | if (requester.pageID() && WebProcess::singleton().webPage(requester.pageID())) |
906 | originatingPageID = requester.pageID(); |
907 | |
908 | NavigationActionData navigationActionData; |
909 | navigationActionData.navigationType = action->navigationType(); |
910 | navigationActionData.modifiers = action->modifiers(); |
911 | navigationActionData.mouseButton = action->mouseButton(); |
912 | navigationActionData.syntheticClickType = action->syntheticClickType(); |
913 | navigationActionData.clickLocationInRootViewCoordinates = action->clickLocationInRootViewCoordinates(); |
914 | navigationActionData.userGestureTokenIdentifier = WebProcess::singleton().userGestureTokenIdentifier(navigationAction.userGestureToken()); |
915 | navigationActionData.canHandleRequest = webPage->canHandleRequest(request); |
916 | navigationActionData.shouldOpenExternalURLsPolicy = navigationAction.shouldOpenExternalURLsPolicy(); |
917 | navigationActionData.downloadAttribute = navigationAction.downloadAttribute(); |
918 | navigationActionData.isRedirect = !redirectResponse.isNull(); |
919 | navigationActionData.treatAsSameOriginNavigation = navigationAction.treatAsSameOriginNavigation(); |
920 | navigationActionData.hasOpenedFrames = navigationAction.hasOpenedFrames(); |
921 | navigationActionData.openedByDOMWithOpener = navigationAction.openedByDOMWithOpener(); |
922 | if (auto& requester = navigationAction.requester()) |
923 | navigationActionData.requesterOrigin = requester->securityOrigin().data(); |
924 | navigationActionData.targetBackForwardItemIdentifier = navigationAction.targetBackForwardItemIdentifier(); |
925 | navigationActionData.sourceBackForwardItemIdentifier = navigationAction.sourceBackForwardItemIdentifier(); |
926 | navigationActionData.lockHistory = navigationAction.lockHistory(); |
927 | navigationActionData.lockBackForwardList = navigationAction.lockBackForwardList(); |
928 | navigationActionData.adClickAttribution = navigationAction.adClickAttribution(); |
929 | |
930 | WebCore::Frame* coreFrame = m_frame->coreFrame(); |
931 | if (!coreFrame) |
932 | return function(PolicyAction::Ignore, requestIdentifier); |
933 | WebDocumentLoader* documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().policyDocumentLoader()); |
934 | if (!documentLoader) { |
935 | // FIXME: When we receive a redirect after the navigation policy has been decided for the initial request, |
936 | // the provisional load's DocumentLoader needs to receive navigation policy decisions. We need a better model for this state. |
937 | documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().provisionalDocumentLoader()); |
938 | } |
939 | if (!documentLoader) |
940 | documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().documentLoader()); |
941 | |
942 | navigationActionData.clientRedirectSourceForHistory = documentLoader->clientRedirectSourceForHistory(); |
943 | |
944 | // Notify the UIProcess. |
945 | Ref<WebFrame> protect(*m_frame); |
946 | |
947 | if (policyDecisionMode == PolicyDecisionMode::Synchronous) { |
948 | uint64_t newNavigationID; |
949 | WebCore::PolicyCheckIdentifier responseIdentifier; |
950 | PolicyAction policyAction; |
951 | DownloadID downloadID; |
952 | Optional<WebsitePoliciesData> websitePolicies; |
953 | |
954 | if (!webPage->sendSync(Messages::WebPageProxy::DecidePolicyForNavigationActionSync(m_frame->frameID(), m_frame->isMainFrame(), SecurityOriginData::fromFrame(coreFrame), |
955 | requestIdentifier, documentLoader->navigationID(), navigationActionData, originatingFrameInfoData, originatingPageID, navigationAction.resourceRequest(), request, |
956 | IPC::FormDataReference { request.httpBody() }, redirectResponse, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())), |
957 | Messages::WebPageProxy::DecidePolicyForNavigationActionSync::Reply(responseIdentifier, policyAction, newNavigationID, downloadID, websitePolicies))) { |
958 | m_frame->didReceivePolicyDecision(listenerID, requestIdentifier, PolicyAction::Ignore, 0, { }, { }); |
959 | return; |
960 | } |
961 | |
962 | m_frame->didReceivePolicyDecision(listenerID, responseIdentifier, policyAction, 0, downloadID, { }); |
963 | return; |
964 | } |
965 | |
966 | ASSERT(policyDecisionMode == PolicyDecisionMode::Asynchronous); |
967 | if (!webPage->send(Messages::WebPageProxy::DecidePolicyForNavigationActionAsync(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), |
968 | requestIdentifier, documentLoader->navigationID(), navigationActionData, originatingFrameInfoData, originatingPageID, navigationAction.resourceRequest(), request, |
969 | IPC::FormDataReference { request.httpBody() }, redirectResponse, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()), listenerID))) |
970 | m_frame->didReceivePolicyDecision(listenerID, requestIdentifier, PolicyAction::Ignore, 0, { }, { }); |
971 | } |
972 | |
973 | void WebFrameLoaderClient::cancelPolicyCheck() |
974 | { |
975 | m_frame->invalidatePolicyListener(); |
976 | } |
977 | |
978 | void WebFrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError& error) |
979 | { |
980 | WebPage* webPage = m_frame->page(); |
981 | if (!webPage) |
982 | return; |
983 | |
984 | RefPtr<API::Object> userData; |
985 | |
986 | // Notify the bundle client. |
987 | webPage->injectedBundlePolicyClient().unableToImplementPolicy(webPage, m_frame, error, userData); |
988 | |
989 | // Notify the UIProcess. |
990 | webPage->send(Messages::WebPageProxy::UnableToImplementPolicy(m_frame->frameID(), error, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
991 | } |
992 | |
993 | void WebFrameLoaderClient::dispatchWillSendSubmitEvent(Ref<FormState>&& formState) |
994 | { |
995 | auto* webPage = m_frame->page(); |
996 | if (!webPage) |
997 | return; |
998 | |
999 | auto& form = formState->form(); |
1000 | |
1001 | ASSERT(formState->sourceDocument().frame()); |
1002 | auto* sourceFrame = WebFrame::fromCoreFrame(*formState->sourceDocument().frame()); |
1003 | ASSERT(sourceFrame); |
1004 | |
1005 | webPage->injectedBundleFormClient().willSendSubmitEvent(webPage, &form, m_frame, sourceFrame, formState->textFieldValues()); |
1006 | } |
1007 | |
1008 | void WebFrameLoaderClient::dispatchWillSubmitForm(FormState& formState, CompletionHandler<void()>&& completionHandler) |
1009 | { |
1010 | WebPage* webPage = m_frame->page(); |
1011 | if (!webPage) { |
1012 | completionHandler(); |
1013 | return; |
1014 | } |
1015 | |
1016 | auto& form = formState.form(); |
1017 | |
1018 | auto* sourceCoreFrame = formState.sourceDocument().frame(); |
1019 | if (!sourceCoreFrame) |
1020 | return completionHandler(); |
1021 | auto* sourceFrame = WebFrame::fromCoreFrame(*sourceCoreFrame); |
1022 | if (!sourceFrame) |
1023 | return completionHandler(); |
1024 | |
1025 | auto& values = formState.textFieldValues(); |
1026 | |
1027 | RefPtr<API::Object> userData; |
1028 | webPage->injectedBundleFormClient().willSubmitForm(webPage, &form, m_frame, sourceFrame, values, userData); |
1029 | |
1030 | uint64_t listenerID = m_frame->setUpWillSubmitFormListener(WTFMove(completionHandler)); |
1031 | |
1032 | webPage->send(Messages::WebPageProxy::WillSubmitForm(m_frame->frameID(), sourceFrame->frameID(), values, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
1033 | } |
1034 | |
1035 | void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader*) |
1036 | { |
1037 | notImplemented(); |
1038 | } |
1039 | |
1040 | void WebFrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError& error) |
1041 | { |
1042 | if (!m_pluginView) |
1043 | return; |
1044 | |
1045 | m_pluginView->manualLoadDidFail(error); |
1046 | m_pluginView = nullptr; |
1047 | m_hasSentResponseToPluginView = false; |
1048 | } |
1049 | |
1050 | void WebFrameLoaderClient::setMainFrameDocumentReady(bool) |
1051 | { |
1052 | notImplemented(); |
1053 | } |
1054 | |
1055 | void WebFrameLoaderClient::startDownload(const ResourceRequest& request, const String& suggestedName) |
1056 | { |
1057 | m_frame->startDownload(request, suggestedName); |
1058 | } |
1059 | |
1060 | void WebFrameLoaderClient::willChangeTitle(DocumentLoader*) |
1061 | { |
1062 | notImplemented(); |
1063 | } |
1064 | |
1065 | void WebFrameLoaderClient::didChangeTitle(DocumentLoader*) |
1066 | { |
1067 | notImplemented(); |
1068 | } |
1069 | |
1070 | void WebFrameLoaderClient::willReplaceMultipartContent() |
1071 | { |
1072 | WebPage* webPage = m_frame->page(); |
1073 | if (!webPage) |
1074 | return; |
1075 | webPage->willReplaceMultipartContent(*m_frame); |
1076 | } |
1077 | |
1078 | void WebFrameLoaderClient::didReplaceMultipartContent() |
1079 | { |
1080 | WebPage* webPage = m_frame->page(); |
1081 | if (!webPage) |
1082 | return; |
1083 | webPage->didReplaceMultipartContent(*m_frame); |
1084 | } |
1085 | |
1086 | void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length) |
1087 | { |
1088 | if (!m_pluginView) |
1089 | loader->commitData(data, length); |
1090 | |
1091 | // If the document is a stand-alone media document, now is the right time to cancel the WebKit load. |
1092 | // FIXME: This code should be shared across all ports. <http://webkit.org/b/48762>. |
1093 | if (m_frame->coreFrame()->document()->isMediaDocument()) |
1094 | loader->cancelMainResourceLoad(pluginWillHandleLoadError(loader->response())); |
1095 | |
1096 | // Calling commitData did not create the plug-in view. |
1097 | if (!m_pluginView) |
1098 | return; |
1099 | |
1100 | if (!m_hasSentResponseToPluginView) { |
1101 | m_pluginView->manualLoadDidReceiveResponse(loader->response()); |
1102 | // manualLoadDidReceiveResponse sets up a new stream to the plug-in. on a full-page plug-in, a failure in |
1103 | // setting up this stream can cause the main document load to be cancelled, setting m_pluginView |
1104 | // to null |
1105 | if (!m_pluginView) |
1106 | return; |
1107 | m_hasSentResponseToPluginView = true; |
1108 | } |
1109 | m_pluginView->manualLoadDidReceiveData(data, length); |
1110 | } |
1111 | |
1112 | void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader) |
1113 | { |
1114 | if (!m_pluginView) { |
1115 | if (m_frameHasCustomContentProvider) { |
1116 | WebPage* webPage = m_frame->page(); |
1117 | if (!webPage) |
1118 | return; |
1119 | |
1120 | RefPtr<SharedBuffer> mainResourceData = loader->mainResourceData(); |
1121 | IPC::DataReference dataReference(reinterpret_cast<const uint8_t*>(mainResourceData ? mainResourceData->data() : 0), mainResourceData ? mainResourceData->size() : 0); |
1122 | webPage->send(Messages::WebPageProxy::DidFinishLoadingDataForCustomContentProvider(loader->response().suggestedFilename(), dataReference)); |
1123 | } |
1124 | |
1125 | return; |
1126 | } |
1127 | |
1128 | // If we just received an empty response without any data, we won't have sent a response to the plug-in view. |
1129 | // Make sure to do this before calling manualLoadDidFinishLoading. |
1130 | if (!m_hasSentResponseToPluginView) { |
1131 | m_pluginView->manualLoadDidReceiveResponse(loader->response()); |
1132 | |
1133 | // Protect against the above call nulling out the plug-in (by trying to cancel the load for example). |
1134 | if (!m_pluginView) |
1135 | return; |
1136 | } |
1137 | |
1138 | m_pluginView->manualLoadDidFinishLoading(); |
1139 | m_pluginView = nullptr; |
1140 | m_hasSentResponseToPluginView = false; |
1141 | } |
1142 | |
1143 | void WebFrameLoaderClient::updateGlobalHistory() |
1144 | { |
1145 | WebPage* webPage = m_frame->page(); |
1146 | if (!webPage) |
1147 | return; |
1148 | |
1149 | DocumentLoader* loader = m_frame->coreFrame()->loader().documentLoader(); |
1150 | |
1151 | WebNavigationDataStore data; |
1152 | data.url = loader->url().string(); |
1153 | // FIXME: Use direction of title. |
1154 | data.title = loader->title().string; |
1155 | data.originalRequest = loader->originalRequestCopy(); |
1156 | data.response = loader->response(); |
1157 | |
1158 | webPage->send(Messages::WebPageProxy::DidNavigateWithNavigationData(data, m_frame->frameID())); |
1159 | } |
1160 | |
1161 | void WebFrameLoaderClient::updateGlobalHistoryRedirectLinks() |
1162 | { |
1163 | WebPage* webPage = m_frame->page(); |
1164 | if (!webPage) |
1165 | return; |
1166 | |
1167 | DocumentLoader* loader = m_frame->coreFrame()->loader().documentLoader(); |
1168 | ASSERT(loader->unreachableURL().isEmpty()); |
1169 | |
1170 | // Client redirect |
1171 | if (!loader->clientRedirectSourceForHistory().isNull()) { |
1172 | webPage->send(Messages::WebPageProxy::DidPerformClientRedirect( |
1173 | loader->clientRedirectSourceForHistory(), loader->clientRedirectDestinationForHistory(), m_frame->frameID())); |
1174 | } |
1175 | |
1176 | // Server redirect |
1177 | if (!loader->serverRedirectSourceForHistory().isNull()) { |
1178 | webPage->send(Messages::WebPageProxy::DidPerformServerRedirect( |
1179 | loader->serverRedirectSourceForHistory(), loader->serverRedirectDestinationForHistory(), m_frame->frameID())); |
1180 | } |
1181 | } |
1182 | |
1183 | bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem& item) const |
1184 | { |
1185 | WebPage* webPage = m_frame->page(); |
1186 | if (!webPage) |
1187 | return false; |
1188 | webPage->send(Messages::WebPageProxy::WillGoToBackForwardListItem(item.identifier(), item.isInPageCache())); |
1189 | return true; |
1190 | } |
1191 | |
1192 | void WebFrameLoaderClient::didDisplayInsecureContent() |
1193 | { |
1194 | WebPage* webPage = m_frame->page(); |
1195 | if (!webPage) |
1196 | return; |
1197 | |
1198 | RefPtr<API::Object> userData; |
1199 | |
1200 | webPage->injectedBundleLoaderClient().didDisplayInsecureContentForFrame(*webPage, *m_frame, userData); |
1201 | |
1202 | webPage->send(Messages::WebPageProxy::DidDisplayInsecureContentForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
1203 | } |
1204 | |
1205 | void WebFrameLoaderClient::didRunInsecureContent(SecurityOrigin&, const URL&) |
1206 | { |
1207 | WebPage* webPage = m_frame->page(); |
1208 | if (!webPage) |
1209 | return; |
1210 | |
1211 | RefPtr<API::Object> userData; |
1212 | |
1213 | webPage->injectedBundleLoaderClient().didRunInsecureContentForFrame(*webPage, *m_frame, userData); |
1214 | |
1215 | webPage->send(Messages::WebPageProxy::DidRunInsecureContentForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
1216 | } |
1217 | |
1218 | void WebFrameLoaderClient::didDetectXSS(const URL&, bool) |
1219 | { |
1220 | WebPage* webPage = m_frame->page(); |
1221 | if (!webPage) |
1222 | return; |
1223 | |
1224 | RefPtr<API::Object> userData; |
1225 | |
1226 | webPage->injectedBundleLoaderClient().didDetectXSSForFrame(*webPage, *m_frame, userData); |
1227 | |
1228 | webPage->send(Messages::WebPageProxy::DidDetectXSSForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get()))); |
1229 | } |
1230 | |
1231 | ResourceError WebFrameLoaderClient::cancelledError(const ResourceRequest& request) |
1232 | { |
1233 | return WebKit::cancelledError(request); |
1234 | } |
1235 | |
1236 | ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request) |
1237 | { |
1238 | return WebKit::blockedError(request); |
1239 | } |
1240 | |
1241 | ResourceError WebFrameLoaderClient::blockedByContentBlockerError(const ResourceRequest& request) |
1242 | { |
1243 | return WebKit::blockedByContentBlockerError(request); |
1244 | } |
1245 | |
1246 | ResourceError WebFrameLoaderClient::cannotShowURLError(const ResourceRequest& request) |
1247 | { |
1248 | return WebKit::cannotShowURLError(request); |
1249 | } |
1250 | |
1251 | ResourceError WebFrameLoaderClient::interruptedForPolicyChangeError(const ResourceRequest& request) |
1252 | { |
1253 | return WebKit::interruptedForPolicyChangeError(request); |
1254 | } |
1255 | |
1256 | #if ENABLE(CONTENT_FILTERING) |
1257 | ResourceError WebFrameLoaderClient::blockedByContentFilterError(const ResourceRequest& request) |
1258 | { |
1259 | return WebKit::blockedByContentFilterError(request); |
1260 | } |
1261 | #endif |
1262 | |
1263 | ResourceError WebFrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response) |
1264 | { |
1265 | return WebKit::cannotShowMIMETypeError(response); |
1266 | } |
1267 | |
1268 | ResourceError WebFrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response) |
1269 | { |
1270 | return WebKit::fileDoesNotExistError(response); |
1271 | } |
1272 | |
1273 | ResourceError WebFrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response) |
1274 | { |
1275 | return WebKit::pluginWillHandleLoadError(response); |
1276 | } |
1277 | |
1278 | bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error) |
1279 | { |
1280 | static NeverDestroyed<const ResourceError> cancelledError(this->cancelledError(ResourceRequest())); |
1281 | static NeverDestroyed<const ResourceError> pluginWillHandleLoadError(this->pluginWillHandleLoadError(ResourceResponse())); |
1282 | |
1283 | if (error.errorCode() == cancelledError.get().errorCode() && error.domain() == cancelledError.get().domain()) |
1284 | return false; |
1285 | |
1286 | if (error.errorCode() == pluginWillHandleLoadError.get().errorCode() && error.domain() == pluginWillHandleLoadError.get().domain()) |
1287 | return false; |
1288 | |
1289 | return true; |
1290 | } |
1291 | |
1292 | bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest&) const |
1293 | { |
1294 | notImplemented(); |
1295 | return true; |
1296 | } |
1297 | |
1298 | bool WebFrameLoaderClient::canShowMIMEType(const String& /*MIMEType*/) const |
1299 | { |
1300 | notImplemented(); |
1301 | return true; |
1302 | } |
1303 | |
1304 | bool WebFrameLoaderClient::canShowMIMETypeAsHTML(const String& /*MIMEType*/) const |
1305 | { |
1306 | return true; |
1307 | } |
1308 | |
1309 | bool WebFrameLoaderClient::representationExistsForURLScheme(const String& /*URLScheme*/) const |
1310 | { |
1311 | notImplemented(); |
1312 | return false; |
1313 | } |
1314 | |
1315 | String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& /*URLScheme*/) const |
1316 | { |
1317 | notImplemented(); |
1318 | return String(); |
1319 | } |
1320 | |
1321 | void WebFrameLoaderClient::frameLoadCompleted() |
1322 | { |
1323 | // Note: Can be called multiple times. |
1324 | WebPage* webPage = m_frame->page(); |
1325 | if (!webPage) |
1326 | return; |
1327 | |
1328 | if (m_frame->isMainFrame() && !m_didCompletePageTransition) { |
1329 | webPage->didCompletePageTransition(); |
1330 | m_didCompletePageTransition = true; |
1331 | } |
1332 | } |
1333 | |
1334 | void WebFrameLoaderClient::saveViewStateToItem(HistoryItem& historyItem) |
1335 | { |
1336 | #if PLATFORM(IOS_FAMILY) |
1337 | if (m_frame->isMainFrame()) |
1338 | m_frame->page()->savePageState(historyItem); |
1339 | #else |
1340 | UNUSED_PARAM(historyItem); |
1341 | #endif |
1342 | } |
1343 | |
1344 | void WebFrameLoaderClient::restoreViewState() |
1345 | { |
1346 | #if PLATFORM(IOS_FAMILY) |
1347 | Frame& frame = *m_frame->coreFrame(); |
1348 | HistoryItem* currentItem = frame.loader().history().currentItem(); |
1349 | if (FrameView* view = frame.view()) { |
1350 | if (m_frame->isMainFrame()) |
1351 | m_frame->page()->restorePageState(*currentItem); |
1352 | else if (!view->wasScrolledByUser()) |
1353 | view->setScrollPosition(currentItem->scrollPosition()); |
1354 | } |
1355 | #else |
1356 | // Inform the UI process of the scale factor. |
1357 | double scaleFactor = m_frame->coreFrame()->loader().history().currentItem()->pageScaleFactor(); |
1358 | |
1359 | // A scale factor of 0 means the history item has the default scale factor, thus we do not need to update it. |
1360 | if (scaleFactor) |
1361 | m_frame->page()->send(Messages::WebPageProxy::PageScaleFactorDidChange(scaleFactor)); |
1362 | |
1363 | // FIXME: This should not be necessary. WebCore should be correctly invalidating |
1364 | // the view on restores from the back/forward cache. |
1365 | if (m_frame->page() && m_frame == m_frame->page()->mainWebFrame()) |
1366 | m_frame->page()->drawingArea()->setNeedsDisplay(); |
1367 | #endif |
1368 | } |
1369 | |
1370 | void WebFrameLoaderClient::provisionalLoadStarted() |
1371 | { |
1372 | WebPage* webPage = m_frame->page(); |
1373 | if (!webPage) |
1374 | return; |
1375 | |
1376 | if (m_frame->isMainFrame()) { |
1377 | webPage->didStartPageTransition(); |
1378 | m_didCompletePageTransition = false; |
1379 | } |
1380 | } |
1381 | |
1382 | void WebFrameLoaderClient::didFinishLoad() |
1383 | { |
1384 | // If we have a load listener, notify it. |
1385 | if (WebFrame::LoadListener* loadListener = m_frame->loadListener()) |
1386 | loadListener->didFinishLoad(m_frame); |
1387 | } |
1388 | |
1389 | void WebFrameLoaderClient::prepareForDataSourceReplacement() |
1390 | { |
1391 | notImplemented(); |
1392 | } |
1393 | |
1394 | Ref<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData) |
1395 | { |
1396 | return m_frame->page()->createDocumentLoader(*m_frame->coreFrame(), request, substituteData); |
1397 | } |
1398 | |
1399 | void WebFrameLoaderClient::updateCachedDocumentLoader(WebCore::DocumentLoader& loader) |
1400 | { |
1401 | m_frame->page()->updateCachedDocumentLoader(static_cast<WebDocumentLoader&>(loader), *m_frame->coreFrame()); |
1402 | } |
1403 | |
1404 | void WebFrameLoaderClient::setTitle(const StringWithDirection& title, const URL& url) |
1405 | { |
1406 | WebPage* webPage = m_frame->page(); |
1407 | if (!webPage) |
1408 | return; |
1409 | |
1410 | // FIXME: Use direction of title. |
1411 | webPage->send(Messages::WebPageProxy::DidUpdateHistoryTitle(title.string, url.string(), m_frame->frameID())); |
1412 | } |
1413 | |
1414 | String WebFrameLoaderClient::userAgent(const URL& url) |
1415 | { |
1416 | auto* webPage = m_frame->page(); |
1417 | if (!webPage) |
1418 | return String(); |
1419 | |
1420 | return webPage->userAgent(url); |
1421 | } |
1422 | |
1423 | String WebFrameLoaderClient::overrideContentSecurityPolicy() const |
1424 | { |
1425 | WebPage* webPage = m_frame->page(); |
1426 | if (!webPage) |
1427 | return String(); |
1428 | |
1429 | return webPage->overrideContentSecurityPolicy(); |
1430 | } |
1431 | |
1432 | void WebFrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame) |
1433 | { |
1434 | WebPage* webPage = m_frame->page(); |
1435 | if (!webPage) |
1436 | return; |
1437 | |
1438 | HasInsecureContent hasInsecureContent; |
1439 | if (webPage->sendSync(Messages::WebPageProxy::HasInsecureContent(), Messages::WebPageProxy::HasInsecureContent::Reply(hasInsecureContent))) |
1440 | cachedFrame->setHasInsecureContent(hasInsecureContent); |
1441 | } |
1442 | |
1443 | void WebFrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame*) |
1444 | { |
1445 | const ResourceResponse& response = m_frame->coreFrame()->loader().documentLoader()->response(); |
1446 | m_frameHasCustomContentProvider = m_frame->isMainFrame() && m_frame->page()->shouldUseCustomContentProviderForResponse(response); |
1447 | m_frameCameFromPageCache = true; |
1448 | } |
1449 | |
1450 | void WebFrameLoaderClient::transitionToCommittedForNewPage() |
1451 | { |
1452 | WebPage* webPage = m_frame->page(); |
1453 | |
1454 | bool isMainFrame = m_frame->isMainFrame(); |
1455 | bool shouldUseFixedLayout = isMainFrame && webPage->useFixedLayout(); |
1456 | bool shouldDisableScrolling = isMainFrame && !webPage->mainFrameIsScrollable(); |
1457 | bool shouldHideScrollbars = shouldDisableScrolling; |
1458 | IntRect fixedVisibleContentRect; |
1459 | |
1460 | #if USE(COORDINATED_GRAPHICS) |
1461 | if (m_frame->coreFrame()->view()) |
1462 | fixedVisibleContentRect = m_frame->coreFrame()->view()->fixedVisibleContentRect(); |
1463 | if (shouldUseFixedLayout) |
1464 | shouldHideScrollbars = true; |
1465 | #endif |
1466 | |
1467 | const ResourceResponse& response = m_frame->coreFrame()->loader().documentLoader()->response(); |
1468 | m_frameHasCustomContentProvider = isMainFrame && webPage->shouldUseCustomContentProviderForResponse(response); |
1469 | m_frameCameFromPageCache = false; |
1470 | |
1471 | ScrollbarMode defaultScrollbarMode = shouldHideScrollbars ? ScrollbarAlwaysOff : ScrollbarAuto; |
1472 | |
1473 | ScrollbarMode horizontalScrollbarMode = webPage->alwaysShowsHorizontalScroller() ? ScrollbarAlwaysOn : defaultScrollbarMode; |
1474 | ScrollbarMode verticalScrollbarMode = webPage->alwaysShowsVerticalScroller() ? ScrollbarAlwaysOn : defaultScrollbarMode; |
1475 | |
1476 | bool horizontalLock = shouldHideScrollbars || webPage->alwaysShowsHorizontalScroller(); |
1477 | bool verticalLock = shouldHideScrollbars || webPage->alwaysShowsVerticalScroller(); |
1478 | |
1479 | m_frame->coreFrame()->createView(webPage->size(), webPage->backgroundColor(), |
1480 | webPage->fixedLayoutSize(), fixedVisibleContentRect, shouldUseFixedLayout, |
1481 | horizontalScrollbarMode, horizontalLock, verticalScrollbarMode, verticalLock); |
1482 | |
1483 | if (int viewLayoutWidth = webPage->viewLayoutSize().width()) { |
1484 | int viewLayoutHeight = std::max(webPage->viewLayoutSize().height(), 1); |
1485 | m_frame->coreFrame()->view()->enableAutoSizeMode(true, { viewLayoutWidth, viewLayoutHeight }); |
1486 | |
1487 | if (webPage->autoSizingShouldExpandToViewHeight()) |
1488 | m_frame->coreFrame()->view()->setAutoSizeFixedMinimumHeight(webPage->size().height()); |
1489 | } |
1490 | |
1491 | if (auto viewportSizeForViewportUnits = webPage->viewportSizeForCSSViewportUnits()) |
1492 | m_frame->coreFrame()->view()->setViewportSizeForCSSViewportUnits(*viewportSizeForViewportUnits); |
1493 | m_frame->coreFrame()->view()->setProhibitsScrolling(shouldDisableScrolling); |
1494 | m_frame->coreFrame()->view()->setVisualUpdatesAllowedByClient(!webPage->shouldExtendIncrementalRenderingSuppression()); |
1495 | #if PLATFORM(COCOA) |
1496 | m_frame->coreFrame()->view()->setViewExposedRect(webPage->drawingArea()->viewExposedRect()); |
1497 | #endif |
1498 | #if PLATFORM(IOS_FAMILY) |
1499 | if (isMainFrame) |
1500 | m_frame->coreFrame()->view()->setDelegatesScrolling(true); |
1501 | #endif |
1502 | |
1503 | if (webPage->scrollPinningBehavior() != DoNotPin) |
1504 | m_frame->coreFrame()->view()->setScrollPinningBehavior(webPage->scrollPinningBehavior()); |
1505 | |
1506 | #if USE(COORDINATED_GRAPHICS) |
1507 | if (shouldUseFixedLayout) { |
1508 | m_frame->coreFrame()->view()->setDelegatesScrolling(shouldUseFixedLayout); |
1509 | m_frame->coreFrame()->view()->setPaintsEntireContents(shouldUseFixedLayout); |
1510 | return; |
1511 | } |
1512 | #endif |
1513 | } |
1514 | |
1515 | void WebFrameLoaderClient::didSaveToPageCache() |
1516 | { |
1517 | WebPage* webPage = m_frame->page(); |
1518 | if (!webPage) |
1519 | return; |
1520 | |
1521 | if (m_frame->isMainFrame()) |
1522 | webPage->send(Messages::WebPageProxy::DidSaveToPageCache()); |
1523 | } |
1524 | |
1525 | void WebFrameLoaderClient::didRestoreFromPageCache() |
1526 | { |
1527 | m_frameCameFromPageCache = true; |
1528 | } |
1529 | |
1530 | void WebFrameLoaderClient::dispatchDidBecomeFrameset(bool value) |
1531 | { |
1532 | WebPage* webPage = m_frame->page(); |
1533 | if (!webPage) |
1534 | return; |
1535 | |
1536 | webPage->send(Messages::WebPageProxy::FrameDidBecomeFrameSet(m_frame->frameID(), value)); |
1537 | } |
1538 | |
1539 | bool WebFrameLoaderClient::canCachePage() const |
1540 | { |
1541 | // We cannot cache frames that have custom representations because they are |
1542 | // rendered in the UIProcess. |
1543 | return !m_frameHasCustomContentProvider; |
1544 | } |
1545 | |
1546 | void WebFrameLoaderClient::convertMainResourceLoadToDownload(DocumentLoader *documentLoader, PAL::SessionID sessionID, const ResourceRequest& request, const ResourceResponse& response) |
1547 | { |
1548 | m_frame->convertMainResourceLoadToDownload(documentLoader, sessionID, request, response); |
1549 | } |
1550 | |
1551 | RefPtr<Frame> WebFrameLoaderClient::createFrame(const URL& url, const String& name, HTMLFrameOwnerElement& ownerElement, |
1552 | const String& referrer) |
1553 | { |
1554 | auto* webPage = m_frame->page(); |
1555 | |
1556 | auto subframe = WebFrame::createSubframe(webPage, name, &ownerElement); |
1557 | auto* coreSubframe = subframe->coreFrame(); |
1558 | if (!coreSubframe) |
1559 | return nullptr; |
1560 | |
1561 | // The creation of the frame may have run arbitrary JavaScript that removed it from the page already. |
1562 | if (!coreSubframe->page()) |
1563 | return nullptr; |
1564 | |
1565 | m_frame->coreFrame()->loader().loadURLIntoChildFrame(url, referrer, coreSubframe); |
1566 | |
1567 | // The frame's onload handler may have removed it from the document. |
1568 | if (!subframe->coreFrame()) |
1569 | return nullptr; |
1570 | ASSERT(subframe->coreFrame() == coreSubframe); |
1571 | if (!coreSubframe->tree().parent()) |
1572 | return nullptr; |
1573 | |
1574 | return coreSubframe; |
1575 | } |
1576 | |
1577 | RefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize&, HTMLPlugInElement& pluginElement, const URL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually) |
1578 | { |
1579 | ASSERT(paramNames.size() == paramValues.size()); |
1580 | ASSERT(m_frame->page()); |
1581 | |
1582 | Plugin::Parameters parameters; |
1583 | parameters.url = url; |
1584 | parameters.names = paramNames; |
1585 | parameters.values = paramValues; |
1586 | parameters.mimeType = mimeType; |
1587 | parameters.isFullFramePlugin = loadManually; |
1588 | parameters.shouldUseManualLoader = parameters.isFullFramePlugin && !m_frameCameFromPageCache; |
1589 | #if PLATFORM(COCOA) |
1590 | parameters.layerHostingMode = m_frame->page()->layerHostingMode(); |
1591 | #endif |
1592 | |
1593 | #if ENABLE(NETSCAPE_PLUGIN_API) |
1594 | auto plugin = m_frame->page()->createPlugin(m_frame, &pluginElement, parameters, parameters.mimeType); |
1595 | if (!plugin) |
1596 | return nullptr; |
1597 | |
1598 | return PluginView::create(pluginElement, plugin.releaseNonNull(), parameters); |
1599 | #else |
1600 | UNUSED_PARAM(pluginElement); |
1601 | return nullptr; |
1602 | #endif |
1603 | } |
1604 | |
1605 | void WebFrameLoaderClient::redirectDataToPlugin(Widget& pluginWidget) |
1606 | { |
1607 | m_pluginView = static_cast<PluginView*>(&pluginWidget); |
1608 | } |
1609 | |
1610 | #if ENABLE(WEBGL) |
1611 | |
1612 | WebCore::WebGLLoadPolicy WebFrameLoaderClient::webGLPolicyForURL(const URL& url) const |
1613 | { |
1614 | if (auto* webPage = m_frame->page()) |
1615 | return webPage->webGLPolicyForURL(m_frame, url); |
1616 | |
1617 | return WebGLAllowCreation; |
1618 | } |
1619 | |
1620 | WebCore::WebGLLoadPolicy WebFrameLoaderClient::resolveWebGLPolicyForURL(const URL& url) const |
1621 | { |
1622 | if (auto* webPage = m_frame->page()) |
1623 | return webPage->resolveWebGLPolicyForURL(m_frame, url); |
1624 | |
1625 | return WebGLAllowCreation; |
1626 | } |
1627 | |
1628 | #endif |
1629 | |
1630 | RefPtr<Widget> WebFrameLoaderClient::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement& appletElement, const URL&, const Vector<String>& paramNames, const Vector<String>& paramValues) |
1631 | { |
1632 | #if ENABLE(NETSCAPE_PLUGIN_API) |
1633 | auto plugin = createPlugin(pluginSize, appletElement, URL(), paramNames, paramValues, appletElement.serviceType(), false); |
1634 | if (!plugin) { |
1635 | if (auto* webPage = m_frame->page()) { |
1636 | auto frameURLString = m_frame->coreFrame()->loader().documentLoader()->responseURL().string(); |
1637 | auto pageURLString = webPage->corePage()->mainFrame().loader().documentLoader()->responseURL().string(); |
1638 | webPage->send(Messages::WebPageProxy::DidFailToInitializePlugin(appletElement.serviceType(), frameURLString, pageURLString)); |
1639 | } |
1640 | } |
1641 | return plugin; |
1642 | #else |
1643 | UNUSED_PARAM(pluginSize); |
1644 | UNUSED_PARAM(appletElement); |
1645 | UNUSED_PARAM(paramNames); |
1646 | UNUSED_PARAM(paramValues); |
1647 | return nullptr; |
1648 | #endif |
1649 | } |
1650 | |
1651 | static bool pluginSupportsExtension(const PluginData& pluginData, const String& extension) |
1652 | { |
1653 | ASSERT(extension.convertToASCIILowercase() == extension); |
1654 | Vector<MimeClassInfo> mimes; |
1655 | Vector<size_t> mimePluginIndices; |
1656 | pluginData.getWebVisibleMimesAndPluginIndices(mimes, mimePluginIndices); |
1657 | for (auto& mimeClassInfo : mimes) { |
1658 | if (mimeClassInfo.extensions.contains(extension)) |
1659 | return true; |
1660 | } |
1661 | return false; |
1662 | } |
1663 | |
1664 | ObjectContentType WebFrameLoaderClient::objectContentType(const URL& url, const String& mimeTypeIn) |
1665 | { |
1666 | // FIXME: This should eventually be merged with WebCore::FrameLoader::defaultObjectContentType. |
1667 | |
1668 | String mimeType = mimeTypeIn; |
1669 | if (mimeType.isEmpty()) { |
1670 | String path = url.path(); |
1671 | auto dotPosition = path.reverseFind('.'); |
1672 | if (dotPosition == notFound) |
1673 | return ObjectContentType::Frame; |
1674 | String extension = path.substring(dotPosition + 1).convertToASCIILowercase(); |
1675 | |
1676 | // Try to guess the MIME type from the extension. |
1677 | mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension); |
1678 | if (mimeType.isEmpty()) { |
1679 | // Check if there's a plug-in around that can handle the extension. |
1680 | if (WebPage* webPage = m_frame->page()) { |
1681 | if (pluginSupportsExtension(webPage->corePage()->pluginData(), extension)) |
1682 | return ObjectContentType::PlugIn; |
1683 | } |
1684 | return ObjectContentType::Frame; |
1685 | } |
1686 | } |
1687 | |
1688 | if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType)) |
1689 | return ObjectContentType::Image; |
1690 | |
1691 | if (WebPage* webPage = m_frame->page()) { |
1692 | auto allowedPluginTypes = webFrame()->coreFrame()->loader().subframeLoader().allowPlugins() |
1693 | ? PluginData::AllPlugins : PluginData::OnlyApplicationPlugins; |
1694 | if (webPage->corePage()->pluginData().supportsMimeType(mimeType, allowedPluginTypes)) |
1695 | return ObjectContentType::PlugIn; |
1696 | } |
1697 | |
1698 | if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType)) |
1699 | return ObjectContentType::Frame; |
1700 | |
1701 | #if PLATFORM(IOS_FAMILY) |
1702 | // iOS can render PDF in <object>/<embed> via PDFDocumentImage. |
1703 | if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType)) |
1704 | return ObjectContentType::Image; |
1705 | #endif |
1706 | |
1707 | return ObjectContentType::None; |
1708 | } |
1709 | |
1710 | String WebFrameLoaderClient::overrideMediaType() const |
1711 | { |
1712 | notImplemented(); |
1713 | return String(); |
1714 | } |
1715 | |
1716 | void WebFrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world) |
1717 | { |
1718 | WebPage* webPage = m_frame->page(); |
1719 | if (!webPage) |
1720 | return; |
1721 | |
1722 | webPage->injectedBundleLoaderClient().didClearWindowObjectForFrame(*webPage, *m_frame, world); |
1723 | |
1724 | WebAutomationSessionProxy* automationSessionProxy = WebProcess::singleton().automationSessionProxy(); |
1725 | if (automationSessionProxy && world.isNormal()) |
1726 | automationSessionProxy->didClearWindowObjectForFrame(*m_frame); |
1727 | } |
1728 | |
1729 | void WebFrameLoaderClient::dispatchGlobalObjectAvailable(DOMWrapperWorld& world) |
1730 | { |
1731 | WebPage* webPage = m_frame->page(); |
1732 | if (!webPage) |
1733 | return; |
1734 | |
1735 | webPage->injectedBundleLoaderClient().globalObjectIsAvailableForFrame(*webPage, *m_frame, world); |
1736 | } |
1737 | |
1738 | void WebFrameLoaderClient::willInjectUserScript(DOMWrapperWorld& world) |
1739 | { |
1740 | WebPage* webPage = m_frame->page(); |
1741 | if (!webPage) |
1742 | return; |
1743 | |
1744 | webPage->injectedBundleLoaderClient().willInjectUserScriptForFrame(*webPage, *m_frame, world); |
1745 | } |
1746 | |
1747 | void WebFrameLoaderClient::dispatchWillDisconnectDOMWindowExtensionFromGlobalObject(WebCore::DOMWindowExtension* extension) |
1748 | { |
1749 | WebPage* webPage = m_frame->page(); |
1750 | if (!webPage) |
1751 | return; |
1752 | |
1753 | webPage->injectedBundleLoaderClient().willDisconnectDOMWindowExtensionFromGlobalObject(*webPage, extension); |
1754 | } |
1755 | |
1756 | void WebFrameLoaderClient::dispatchDidReconnectDOMWindowExtensionToGlobalObject(WebCore::DOMWindowExtension* extension) |
1757 | { |
1758 | WebPage* webPage = m_frame->page(); |
1759 | if (!webPage) |
1760 | return; |
1761 | |
1762 | webPage->injectedBundleLoaderClient().didReconnectDOMWindowExtensionToGlobalObject(*webPage, extension); |
1763 | } |
1764 | |
1765 | void WebFrameLoaderClient::dispatchWillDestroyGlobalObjectForDOMWindowExtension(WebCore::DOMWindowExtension* extension) |
1766 | { |
1767 | WebPage* webPage = m_frame->page(); |
1768 | if (!webPage) |
1769 | return; |
1770 | |
1771 | webPage->injectedBundleLoaderClient().willDestroyGlobalObjectForDOMWindowExtension(*webPage, extension); |
1772 | } |
1773 | |
1774 | #if PLATFORM(COCOA) |
1775 | |
1776 | RemoteAXObjectRef WebFrameLoaderClient::accessibilityRemoteObject() |
1777 | { |
1778 | WebPage* webPage = m_frame->page(); |
1779 | if (!webPage) |
1780 | return 0; |
1781 | |
1782 | return webPage->accessibilityRemoteObject(); |
1783 | } |
1784 | |
1785 | void WebFrameLoaderClient::willCacheResponse(DocumentLoader*, unsigned long identifier, NSCachedURLResponse* response, CompletionHandler<void(NSCachedURLResponse *)>&& completionHandler) const |
1786 | { |
1787 | WebPage* webPage = m_frame->page(); |
1788 | if (!webPage) |
1789 | return completionHandler(response); |
1790 | |
1791 | return completionHandler(webPage->injectedBundleResourceLoadClient().shouldCacheResponse(*webPage, *m_frame, identifier) ? response : nil); |
1792 | } |
1793 | |
1794 | NSDictionary *WebFrameLoaderClient::dataDetectionContext() |
1795 | { |
1796 | WebPage* webPage = m_frame->page(); |
1797 | if (!webPage) |
1798 | return nil; |
1799 | |
1800 | return webPage->dataDetectionContext(); |
1801 | } |
1802 | |
1803 | #endif // PLATFORM(COCOA) |
1804 | |
1805 | void WebFrameLoaderClient::didChangeScrollOffset() |
1806 | { |
1807 | WebPage* webPage = m_frame->page(); |
1808 | if (!webPage) |
1809 | return; |
1810 | |
1811 | webPage->didChangeScrollOffsetForFrame(m_frame->coreFrame()); |
1812 | } |
1813 | |
1814 | bool WebFrameLoaderClient::allowScript(bool enabledPerSettings) |
1815 | { |
1816 | if (!enabledPerSettings) |
1817 | return false; |
1818 | |
1819 | auto* pluginView = WebPage::pluginViewForFrame(m_frame->coreFrame()); |
1820 | return !pluginView || !pluginView->shouldAllowScripting(); |
1821 | } |
1822 | |
1823 | bool WebFrameLoaderClient::shouldForceUniversalAccessFromLocalURL(const URL& url) |
1824 | { |
1825 | WebPage* webPage = m_frame->page(); |
1826 | if (!webPage) |
1827 | return false; |
1828 | |
1829 | return webPage->injectedBundleLoaderClient().shouldForceUniversalAccessFromLocalURL(*webPage, url); |
1830 | } |
1831 | |
1832 | Ref<FrameNetworkingContext> WebFrameLoaderClient::createNetworkingContext() |
1833 | { |
1834 | ASSERT(!hasProcessPrivilege(ProcessPrivilege::CanAccessRawCookies)); |
1835 | return WebFrameNetworkingContext::create(m_frame); |
1836 | } |
1837 | |
1838 | #if ENABLE(CONTENT_FILTERING) |
1839 | |
1840 | void WebFrameLoaderClient::contentFilterDidBlockLoad(WebCore::ContentFilterUnblockHandler unblockHandler) |
1841 | { |
1842 | if (!unblockHandler.needsUIProcess()) { |
1843 | m_frame->coreFrame()->loader().policyChecker().setContentFilterUnblockHandler(WTFMove(unblockHandler)); |
1844 | return; |
1845 | } |
1846 | |
1847 | if (WebPage* webPage { m_frame->page() }) |
1848 | webPage->send(Messages::WebPageProxy::ContentFilterDidBlockLoadForFrame(unblockHandler, m_frame->frameID())); |
1849 | } |
1850 | |
1851 | #endif |
1852 | |
1853 | void WebFrameLoaderClient::prefetchDNS(const String& hostname) |
1854 | { |
1855 | WebProcess::singleton().prefetchDNS(hostname); |
1856 | } |
1857 | |
1858 | void WebFrameLoaderClient::didRestoreScrollPosition() |
1859 | { |
1860 | WebPage* webPage = m_frame->page(); |
1861 | if (!webPage) |
1862 | return; |
1863 | |
1864 | webPage->didRestoreScrollPosition(); |
1865 | } |
1866 | |
1867 | void WebFrameLoaderClient::getLoadDecisionForIcons(const Vector<std::pair<WebCore::LinkIcon&, uint64_t>>& icons) |
1868 | { |
1869 | auto* webPage = m_frame->page(); |
1870 | if (!webPage) |
1871 | return; |
1872 | |
1873 | for (auto& icon : icons) |
1874 | webPage->send(Messages::WebPageProxy::GetLoadDecisionForIcon(icon.first, CallbackID::fromInteger(icon.second))); |
1875 | } |
1876 | |
1877 | void WebFrameLoaderClient::finishedLoadingIcon(uint64_t callbackIdentifier, SharedBuffer* data) |
1878 | { |
1879 | auto callbackID = CallbackID::fromInteger(callbackIdentifier); |
1880 | if (WebPage* webPage { m_frame->page() }) { |
1881 | if (data) |
1882 | webPage->send(Messages::WebPageProxy::FinishedLoadingIcon(callbackID, { reinterpret_cast<const uint8_t*>(data->data()), data->size() })); |
1883 | else |
1884 | webPage->send(Messages::WebPageProxy::FinishedLoadingIcon(callbackID, { nullptr, 0 })); |
1885 | } |
1886 | } |
1887 | |
1888 | void WebFrameLoaderClient::didCreateWindow(DOMWindow& window) |
1889 | { |
1890 | auto* webPage = m_frame->page(); |
1891 | if (!webPage) |
1892 | return; |
1893 | |
1894 | webPage->send(Messages::WebPageProxy::DidCreateWindow(m_frame->frameID(), window.identifier())); |
1895 | } |
1896 | |
1897 | #if ENABLE(APPLICATION_MANIFEST) |
1898 | void WebFrameLoaderClient::finishedLoadingApplicationManifest(uint64_t callbackIdentifier, const Optional<WebCore::ApplicationManifest>& manifest) |
1899 | { |
1900 | WebPage* webPage = m_frame->page(); |
1901 | if (!webPage) |
1902 | return; |
1903 | |
1904 | webPage->didFinishLoadingApplicationManifest(callbackIdentifier, manifest); |
1905 | } |
1906 | #endif // ENABLE(APPLICATION_MANIFEST) |
1907 | |
1908 | } // namespace WebKit |
1909 | |