REGRESSION (iOS 8): PDFs embedded in <object>/<embed> tag don't load at all
[WebKit-https.git] / Source / WebKit2 / WebProcess / WebCoreSupport / WebFrameLoaderClient.cpp
1 /*
2  * Copyright (C) 2010, 2011, 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 #include "config.h"
27 #include "WebFrameLoaderClient.h"
28
29 #include "AuthenticationManager.h"
30 #include "DataReference.h"
31 #include "DrawingArea.h"
32 #include "InjectedBundle.h"
33 #include "InjectedBundleBackForwardListItem.h"
34 #include "InjectedBundleDOMWindowExtension.h"
35 #include "InjectedBundleNavigationAction.h"
36 #include "NavigationActionData.h"
37 #include "PluginView.h"
38 #include "UserData.h"
39 #include "WKBundleAPICast.h"
40 #include "WebBackForwardListProxy.h"
41 #include "WebCoreArgumentCoders.h"
42 #include "WebDocumentLoader.h"
43 #include "WebErrors.h"
44 #include "WebEvent.h"
45 #include "WebFrame.h"
46 #include "WebFrameNetworkingContext.h"
47 #include "WebFullScreenManager.h"
48 #include "WebIconDatabaseMessages.h"
49 #include "WebNavigationDataStore.h"
50 #include "WebPage.h"
51 #include "WebPageGroupProxy.h"
52 #include "WebPageProxyMessages.h"
53 #include "WebProcess.h"
54 #include "WebProcessPoolMessages.h"
55 #include <JavaScriptCore/APICast.h>
56 #include <JavaScriptCore/JSObject.h>
57 #include <WebCore/CertificateInfo.h>
58 #include <WebCore/Chrome.h>
59 #include <WebCore/DOMWrapperWorld.h>
60 #include <WebCore/DocumentLoader.h>
61 #include <WebCore/FormState.h>
62 #include <WebCore/FrameLoadRequest.h>
63 #include <WebCore/FrameLoader.h>
64 #include <WebCore/FrameView.h>
65 #include <WebCore/HTMLAppletElement.h>
66 #include <WebCore/HTMLFormElement.h>
67 #include <WebCore/HistoryController.h>
68 #include <WebCore/HistoryItem.h>
69 #include <WebCore/MIMETypeRegistry.h>
70 #include <WebCore/MainFrame.h>
71 #include <WebCore/MouseEvent.h>
72 #include <WebCore/NotImplemented.h>
73 #include <WebCore/Page.h>
74 #include <WebCore/PluginData.h>
75 #include <WebCore/PluginDocument.h>
76 #include <WebCore/ProgressTracker.h>
77 #include <WebCore/ResourceError.h>
78 #include <WebCore/ScriptController.h>
79 #include <WebCore/Settings.h>
80 #include <WebCore/SubframeLoader.h>
81 #include <WebCore/UIEventWithKeyState.h>
82 #include <WebCore/Widget.h>
83 #include <WebCore/WindowFeatures.h>
84 #include <wtf/NeverDestroyed.h>
85
86 using namespace WebCore;
87
88 namespace WebKit {
89
90 WebFrameLoaderClient::WebFrameLoaderClient()
91     : m_frame(0)
92     , m_hasSentResponseToPluginView(false)
93     , m_didCompletePageTransition(false)
94     , m_frameHasCustomContentProvider(false)
95     , m_frameCameFromPageCache(false)
96 {
97 }
98
99 WebFrameLoaderClient::~WebFrameLoaderClient()
100 {
101 }
102     
103 void WebFrameLoaderClient::frameLoaderDestroyed()
104 {
105     if (WebPage* webPage = m_frame->page())
106         webPage->injectedBundleLoaderClient().willDestroyFrame(webPage, m_frame);
107
108     m_frame->invalidate();
109
110     // Balances explicit ref() in WebFrame::create().
111     m_frame->deref();
112 }
113
114 bool WebFrameLoaderClient::hasHTMLView() const
115 {
116     return !m_frameHasCustomContentProvider;
117 }
118
119 bool WebFrameLoaderClient::hasWebView() const
120 {
121     return m_frame->page();
122 }
123
124 void WebFrameLoaderClient::makeRepresentation(DocumentLoader*)
125 {
126     notImplemented();
127 }
128
129 void WebFrameLoaderClient::forceLayoutForNonHTML()
130 {
131     notImplemented();
132 }
133
134 void WebFrameLoaderClient::setCopiesOnScroll()
135 {
136     notImplemented();
137 }
138
139 void WebFrameLoaderClient::detachedFromParent2()
140 {
141     WebPage* webPage = m_frame->page();
142     if (!webPage)
143         return;
144
145 #if PLATFORM(IOS)
146     webPage->resetAssistedNodeForFrame(m_frame);
147 #endif
148     RefPtr<API::Object> userData;
149
150     // Notify the bundle client.
151     webPage->injectedBundleLoaderClient().didRemoveFrameFromHierarchy(webPage, m_frame, userData);
152
153     // Notify the UIProcess.
154     webPage->send(Messages::WebPageProxy::DidRemoveFrameFromHierarchy(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
155 }
156
157 void WebFrameLoaderClient::detachedFromParent3()
158 {
159     notImplemented();
160 }
161
162 void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
163 {
164     WebPage* webPage = m_frame->page();
165     if (!webPage)
166         return;
167
168     bool pageIsProvisionallyLoading = false;
169     if (FrameLoader* frameLoader = loader->frameLoader())
170         pageIsProvisionallyLoading = frameLoader->provisionalDocumentLoader() == loader;
171
172     webPage->injectedBundleResourceLoadClient().didInitiateLoadForResource(webPage, m_frame, identifier, request, pageIsProvisionallyLoading);
173     webPage->addResourceRequest(identifier, request);
174 }
175
176 void WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
177 {
178     WebPage* webPage = m_frame->page();
179     if (!webPage)
180         return;
181
182     webPage->injectedBundleResourceLoadClient().willSendRequestForFrame(webPage, m_frame, identifier, request, redirectResponse);
183 }
184
185 bool WebFrameLoaderClient::shouldUseCredentialStorage(DocumentLoader*, unsigned long identifier)
186 {
187     WebPage* webPage = m_frame->page();
188     if (!webPage)
189         return true;
190
191     return webPage->injectedBundleResourceLoadClient().shouldUseCredentialStorage(webPage, m_frame, identifier);
192 }
193
194 void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long, const AuthenticationChallenge& challenge)
195 {
196     // FIXME: Authentication is a per-resource concept, but we don't do per-resource handling in the UIProcess at the API level quite yet.
197     // Once we do, we might need to make sure authentication fits with our solution.
198
199     WebPage* webPage = m_frame->page();
200     if (!webPage)
201         return;
202
203     WebProcess::singleton().supplement<AuthenticationManager>()->didReceiveAuthenticationChallenge(m_frame, challenge);
204 }
205
206 void WebFrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long /*identifier*/, const AuthenticationChallenge&)    
207 {
208     notImplemented();
209 }
210
211 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
212 bool WebFrameLoaderClient::canAuthenticateAgainstProtectionSpace(DocumentLoader*, unsigned long, const ProtectionSpace& protectionSpace)
213 {
214     // FIXME: Authentication is a per-resource concept, but we don't do per-resource handling in the UIProcess at the API level quite yet.
215     // Once we do, we might need to make sure authentication fits with our solution.
216     
217     WebPage* webPage = m_frame->page();
218     if (!webPage)
219         return false;
220         
221     bool canAuthenticate;
222     if (!webPage->sendSync(Messages::WebPageProxy::CanAuthenticateAgainstProtectionSpaceInFrame(m_frame->frameID(), protectionSpace), Messages::WebPageProxy::CanAuthenticateAgainstProtectionSpaceInFrame::Reply(canAuthenticate)))
223         return false;
224     
225     return canAuthenticate;
226 }
227 #endif
228
229 void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse& response)
230 {
231     WebPage* webPage = m_frame->page();
232     if (!webPage)
233         return;
234
235     webPage->injectedBundleResourceLoadClient().didReceiveResponseForResource(webPage, m_frame, identifier, response);
236 }
237
238 void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int dataLength)
239 {
240     WebPage* webPage = m_frame->page();
241     if (!webPage)
242         return;
243
244     webPage->injectedBundleResourceLoadClient().didReceiveContentLengthForResource(webPage, m_frame, identifier, dataLength);
245 }
246
247 void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier)
248 {
249     WebPage* webPage = m_frame->page();
250     if (!webPage)
251         return;
252
253     webPage->injectedBundleResourceLoadClient().didFinishLoadForResource(webPage, m_frame, identifier);
254     webPage->removeResourceRequest(identifier);
255 }
256
257 void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError& error)
258 {
259     WebPage* webPage = m_frame->page();
260     if (!webPage)
261         return;
262
263     webPage->injectedBundleResourceLoadClient().didFailLoadForResource(webPage, m_frame, identifier, error);
264     webPage->removeResourceRequest(identifier);
265 }
266
267 bool WebFrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int /*length*/)
268 {
269     notImplemented();
270     return false;
271 }
272
273 void WebFrameLoaderClient::dispatchDidHandleOnloadEvents()
274 {
275     WebPage* webPage = m_frame->page();
276     if (!webPage)
277         return;
278
279     // Notify the bundle client.
280     webPage->injectedBundleLoaderClient().didHandleOnloadEventsForFrame(webPage, m_frame);
281 }
282
283 void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
284 {
285     WebPage* webPage = m_frame->page();
286     if (!webPage)
287         return;
288
289     WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().provisionalDocumentLoader());
290     const String& url = documentLoader.url().string();
291     RefPtr<API::Object> userData;
292
293     // Notify the bundle client.
294     webPage->injectedBundleLoaderClient().didReceiveServerRedirectForProvisionalLoadForFrame(webPage, m_frame, userData);
295
296     // Notify the UIProcess.
297     webPage->send(Messages::WebPageProxy::DidReceiveServerRedirectForProvisionalLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), url, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
298 }
299
300 void WebFrameLoaderClient::dispatchDidCancelClientRedirect()
301 {
302     WebPage* webPage = m_frame->page();
303     if (!webPage)
304         return;
305
306     // Notify the bundle client.
307     webPage->injectedBundleLoaderClient().didCancelClientRedirectForFrame(webPage, m_frame);
308 }
309
310 void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const URL& url, double interval, double fireDate)
311 {
312     WebPage* webPage = m_frame->page();
313     if (!webPage)
314         return;
315
316     // Notify the bundle client.
317     webPage->injectedBundleLoaderClient().willPerformClientRedirectForFrame(webPage, m_frame, url.string(), interval, fireDate);
318 }
319
320 void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage()
321 {
322     WebPage* webPage = m_frame->page();
323     if (!webPage)
324         return;
325
326     RefPtr<API::Object> userData;
327
328     // Notify the bundle client.
329     webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(webPage, m_frame, SameDocumentNavigationAnchorNavigation, userData);
330
331     // Notify the UIProcess.
332     WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
333     webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), documentLoader.navigationID(), SameDocumentNavigationAnchorNavigation, m_frame->coreFrame()->document()->url().string(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
334 }
335
336 void WebFrameLoaderClient::dispatchDidPushStateWithinPage()
337 {
338     WebPage* webPage = m_frame->page();
339     if (!webPage)
340         return;
341
342     RefPtr<API::Object> userData;
343
344     // Notify the bundle client.
345     webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(webPage, m_frame, SameDocumentNavigationSessionStatePush, userData);
346
347     // Notify the UIProcess.
348     WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
349     webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), documentLoader.navigationID(), SameDocumentNavigationSessionStatePush, m_frame->coreFrame()->document()->url().string(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
350 }
351
352 void WebFrameLoaderClient::dispatchDidReplaceStateWithinPage()
353 {
354     WebPage* webPage = m_frame->page();
355     if (!webPage)
356         return;
357
358     RefPtr<API::Object> userData;
359
360     // Notify the bundle client.
361     webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(webPage, m_frame, SameDocumentNavigationSessionStateReplace, userData);
362
363     // Notify the UIProcess.
364     WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
365     webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), documentLoader.navigationID(), SameDocumentNavigationSessionStateReplace, m_frame->coreFrame()->document()->url().string(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
366 }
367
368 void WebFrameLoaderClient::dispatchDidPopStateWithinPage()
369 {
370     WebPage* webPage = m_frame->page();
371     if (!webPage)
372         return;
373
374     RefPtr<API::Object> userData;
375
376     // Notify the bundle client.
377     webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(webPage, m_frame, SameDocumentNavigationSessionStatePop, userData);
378
379     // Notify the UIProcess.
380     WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
381     webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), documentLoader.navigationID(), SameDocumentNavigationSessionStatePop, m_frame->coreFrame()->document()->url().string(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
382 }
383
384 void WebFrameLoaderClient::dispatchWillClose()
385 {
386     notImplemented();
387 }
388
389 void WebFrameLoaderClient::dispatchDidReceiveIcon()
390 {
391     WebProcess::singleton().parentProcessConnection()->send(Messages::WebIconDatabase::DidReceiveIconForPageURL(m_frame->url()), 0);
392 }
393
394 void WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
395 {
396     WebPage* webPage = m_frame->page();
397     if (!webPage)
398         return;
399
400 #if ENABLE(FULLSCREEN_API)
401     Element* documentElement = m_frame->coreFrame()->document()->documentElement();
402     if (documentElement && documentElement->containsFullScreenElement())
403         webPage->fullScreenManager()->exitFullScreenForElement(webPage->fullScreenManager()->element());
404 #endif
405
406     webPage->findController().hideFindUI();
407     webPage->sandboxExtensionTracker().didStartProvisionalLoad(m_frame);
408
409     WebDocumentLoader& provisionalLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().provisionalDocumentLoader());
410     const String& url = provisionalLoader.url().string();
411     RefPtr<API::Object> userData;
412
413     // Notify the bundle client.
414     webPage->injectedBundleLoaderClient().didStartProvisionalLoadForFrame(webPage, m_frame, userData);
415
416     String unreachableURL = provisionalLoader.unreachableURL().string();
417
418     // Notify the UIProcess.
419     webPage->send(Messages::WebPageProxy::DidStartProvisionalLoadForFrame(m_frame->frameID(), provisionalLoader.navigationID(), url, unreachableURL, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
420 }
421
422 void WebFrameLoaderClient::dispatchDidReceiveTitle(const StringWithDirection& title)
423 {
424     WebPage* webPage = m_frame->page();
425     if (!webPage)
426         return;
427
428     RefPtr<API::Object> userData;
429
430     // Notify the bundle client.
431     // FIXME: use direction of title.
432     webPage->injectedBundleLoaderClient().didReceiveTitleForFrame(webPage, title.string(), m_frame, userData);
433
434     // Notify the UIProcess.
435     webPage->send(Messages::WebPageProxy::DidReceiveTitleForFrame(m_frame->frameID(), title.string(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
436 }
437
438 void WebFrameLoaderClient::dispatchDidChangeIcons(WebCore::IconType)
439 {
440     notImplemented();
441 }
442
443 void WebFrameLoaderClient::dispatchDidCommitLoad()
444 {
445     WebPage* webPage = m_frame->page();
446     if (!webPage)
447         return;
448
449     WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
450     RefPtr<API::Object> userData;
451
452     // Notify the bundle client.
453     webPage->injectedBundleLoaderClient().didCommitLoadForFrame(webPage, m_frame, userData);
454
455     webPage->sandboxExtensionTracker().didCommitProvisionalLoad(m_frame);
456
457     // Notify the UIProcess.
458
459     webPage->send(Messages::WebPageProxy::DidCommitLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), documentLoader.response().mimeType(), m_frameHasCustomContentProvider, static_cast<uint32_t>(m_frame->coreFrame()->loader().loadType()), documentLoader.response().certificateInfo(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
460     webPage->didCommitLoad(m_frame);
461 }
462
463 void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
464 {
465     WebPage* webPage = m_frame->page();
466     if (!webPage)
467         return;
468
469     RefPtr<API::Object> userData;
470
471     // Notify the bundle client.
472     webPage->injectedBundleLoaderClient().didFailProvisionalLoadWithErrorForFrame(webPage, m_frame, error, userData);
473
474     webPage->sandboxExtensionTracker().didFailProvisionalLoad(m_frame);
475
476     // FIXME: This is gross. This is necessary because if the client calls WKBundlePageStopLoading() from within the didFailProvisionalLoadWithErrorForFrame
477     // injected bundle client call, that will cause the provisional DocumentLoader to be disconnected from the Frame, and didDistroyNavigation message
478     // to be sent to the UIProcess (and the destruction of the DocumentLoader). If that happens, and we had captured the navigationID before injected bundle 
479     // client call, the DidFailProvisionalLoadForFrame would send a navigationID of a destroyed Navigation, and the UIProcess would not be able to find it
480     // in its table.
481     //
482     // A better solution to this problem would be find a clean way to postpone the disconnection of the DocumentLoader from the Frame until
483     // the entire FrameLoaderClient function was complete.
484     uint64_t navigationID = 0;
485     if (auto documentLoader = m_frame->coreFrame()->loader().provisionalDocumentLoader())
486         navigationID = static_cast<WebDocumentLoader*>(documentLoader)->navigationID();
487
488     // Notify the UIProcess.
489     webPage->send(Messages::WebPageProxy::DidFailProvisionalLoadForFrame(m_frame->frameID(), navigationID, error, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
490
491     // If we have a load listener, notify it.
492     if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
493         loadListener->didFailLoad(m_frame, error.isCancellation());
494 }
495
496 void WebFrameLoaderClient::dispatchDidFailLoad(const ResourceError& error)
497 {
498     WebPage* webPage = m_frame->page();
499     if (!webPage)
500         return;
501
502     RefPtr<API::Object> userData;
503
504     // Notify the bundle client.
505     webPage->injectedBundleLoaderClient().didFailLoadWithErrorForFrame(webPage, m_frame, error, userData);
506
507     // Notify the UIProcess.
508     WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
509     webPage->send(Messages::WebPageProxy::DidFailLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), error, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
510
511     // If we have a load listener, notify it.
512     if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
513         loadListener->didFailLoad(m_frame, error.isCancellation());
514 }
515
516 void WebFrameLoaderClient::dispatchDidFinishDocumentLoad()
517 {
518     WebPage* webPage = m_frame->page();
519     if (!webPage)
520         return;
521
522     RefPtr<API::Object> userData;
523
524     // Notify the bundle client.
525     webPage->injectedBundleLoaderClient().didFinishDocumentLoadForFrame(webPage, m_frame, userData);
526
527     WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
528
529     // Notify the UIProcess.
530     webPage->send(Messages::WebPageProxy::DidFinishDocumentLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
531 }
532
533 void WebFrameLoaderClient::dispatchDidFinishLoad()
534 {
535     WebPage* webPage = m_frame->page();
536     if (!webPage)
537         return;
538
539     RefPtr<API::Object> userData;
540
541     // Notify the bundle client.
542     webPage->injectedBundleLoaderClient().didFinishLoadForFrame(webPage, m_frame, userData);
543
544     WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
545
546     // Notify the UIProcess.
547     webPage->send(Messages::WebPageProxy::DidFinishLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
548
549     // If we have a load listener, notify it.
550     if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
551         loadListener->didFinishLoad(m_frame);
552
553     webPage->didFinishLoad(m_frame);
554 }
555
556 void WebFrameLoaderClient::forcePageTransitionIfNeeded()
557 {
558     if (m_didCompletePageTransition)
559         return;
560
561     WebPage* webPage = m_frame->page();
562     if (!webPage)
563         return;
564
565     webPage->didCompletePageTransition();
566     m_didCompletePageTransition = true;
567 }
568
569 void WebFrameLoaderClient::dispatchDidLayout(LayoutMilestones milestones)
570 {
571     WebPage* webPage = m_frame->page();
572     if (!webPage)
573         return;
574
575     RefPtr<API::Object> userData;
576
577     if (milestones & DidFirstLayout) {
578         // FIXME: We should consider removing the old didFirstLayout API since this is doing double duty with the
579         // new didLayout API.
580         webPage->injectedBundleLoaderClient().didFirstLayoutForFrame(webPage, m_frame, userData);
581         webPage->send(Messages::WebPageProxy::DidFirstLayoutForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
582
583 #if PLATFORM(MAC)
584         // FIXME: Do this on DidFirstVisuallyNonEmptyLayout when Mac Safari is able to handle it (<rdar://problem/17580021>)
585         if (m_frame->isMainFrame() && !m_didCompletePageTransition && !webPage->corePage()->settings().suppressesIncrementalRendering()) {
586             webPage->didCompletePageTransition();
587             m_didCompletePageTransition = true;
588         }
589 #endif
590
591 #if USE(TILED_BACKING_STORE)
592         // Make sure viewport properties are dispatched on the main frame by the time the first layout happens.
593         ASSERT(!webPage->useFixedLayout() || m_frame != m_frame->page()->mainWebFrame() || m_frame->coreFrame()->document()->didDispatchViewportPropertiesChanged());
594 #endif
595     }
596
597     // Send this after DidFirstLayout-specific calls since some clients expect to get those messages first.
598     webPage->injectedBundleLoaderClient().didLayout(webPage, milestones, userData);
599     webPage->send(Messages::WebPageProxy::DidLayout(milestones, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
600
601     if (milestones & DidFirstVisuallyNonEmptyLayout) {
602         if (m_frame->isMainFrame() && !m_didCompletePageTransition && !webPage->corePage()->settings().suppressesIncrementalRendering()) {
603             webPage->didCompletePageTransition();
604             m_didCompletePageTransition = true;
605         }
606
607         // FIXME: We should consider removing the old didFirstVisuallyNonEmptyLayoutForFrame API since this is doing
608         // double duty with the new didLayout API.
609         webPage->injectedBundleLoaderClient().didFirstVisuallyNonEmptyLayoutForFrame(webPage, m_frame, userData);
610         webPage->send(Messages::WebPageProxy::DidFirstVisuallyNonEmptyLayoutForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
611     }
612 }
613
614 void WebFrameLoaderClient::dispatchDidLayout()
615 {
616     WebPage* webPage = m_frame->page();
617     if (!webPage)
618         return;
619
620     // Notify the bundle client.
621     webPage->injectedBundleLoaderClient().didLayoutForFrame(webPage, m_frame);
622
623     webPage->recomputeShortCircuitHorizontalWheelEventsState();
624
625 #if PLATFORM(IOS)
626     webPage->updateSelectionAppearance();
627 #endif
628
629     // NOTE: Unlike the other layout notifications, this does not notify the
630     // the UIProcess for every call.
631
632     if (m_frame == m_frame->page()->mainWebFrame()) {
633         // FIXME: Remove at the soonest possible time.
634         webPage->send(Messages::WebPageProxy::SetRenderTreeSize(webPage->renderTreeSize()));
635         webPage->mainFrameDidLayout();
636     }
637 }
638
639 Frame* WebFrameLoaderClient::dispatchCreatePage(const NavigationAction& navigationAction)
640 {
641     WebPage* webPage = m_frame->page();
642     if (!webPage)
643         return 0;
644
645     // Just call through to the chrome client.
646     Page* newPage = webPage->corePage()->chrome().createWindow(m_frame->coreFrame(), FrameLoadRequest(m_frame->coreFrame()->document()->securityOrigin(), navigationAction.resourceRequest()), WindowFeatures(), navigationAction);
647     if (!newPage)
648         return 0;
649     
650     return &newPage->mainFrame();
651 }
652
653 void WebFrameLoaderClient::dispatchShow()
654 {
655     WebPage* webPage = m_frame->page();
656     if (!webPage)
657         return;
658
659     webPage->show();
660 }
661
662 void WebFrameLoaderClient::dispatchDecidePolicyForResponse(const ResourceResponse& response, const ResourceRequest& request, FramePolicyFunction function)
663 {
664     WebPage* webPage = m_frame->page();
665     if (!webPage)
666         return;
667
668     if (!request.url().string()) {
669         function(PolicyUse);
670         return;
671     }
672
673     RefPtr<API::Object> userData;
674
675     // Notify the bundle client.
676     WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForResponse(webPage, m_frame, response, request, userData);
677     if (policy == WKBundlePagePolicyActionUse) {
678         function(PolicyUse);
679         return;
680     }
681
682     bool canShowMIMEType = webPage->canShowMIMEType(response.mimeType());
683
684     uint64_t listenerID = m_frame->setUpPolicyListener(WTF::move(function));
685     bool receivedPolicyAction;
686     uint64_t policyAction;
687     uint64_t downloadID;
688
689     unsigned syncSendFlags = IPC::InformPlatformProcessWillSuspend;
690     if (WebPage::synchronousMessagesShouldSpinRunLoop())
691         syncSendFlags |= IPC::SpinRunLoopWhileWaitingForReply;
692     if (!webPage->sendSync(Messages::WebPageProxy::DecidePolicyForResponseSync(m_frame->frameID(), response, request, canShowMIMEType, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())), Messages::WebPageProxy::DecidePolicyForResponseSync::Reply(receivedPolicyAction, policyAction, downloadID), std::chrono::milliseconds::max(), syncSendFlags))
693         return;
694
695     // We call this synchronously because CFNetwork can only convert a loading connection to a download from its didReceiveResponse callback.
696     if (receivedPolicyAction)
697         m_frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), 0, downloadID);
698 }
699
700 void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(const NavigationAction& navigationAction, const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, FramePolicyFunction function)
701 {
702     WebPage* webPage = m_frame->page();
703     if (!webPage)
704         return;
705
706     RefPtr<API::Object> userData;
707
708     RefPtr<InjectedBundleNavigationAction> action = InjectedBundleNavigationAction::create(m_frame, navigationAction, formState);
709
710     // Notify the bundle client.
711     WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForNewWindowAction(webPage, m_frame, action.get(), request, frameName, userData);
712     if (policy == WKBundlePagePolicyActionUse) {
713         function(PolicyUse);
714         return;
715     }
716
717
718     uint64_t listenerID = m_frame->setUpPolicyListener(WTF::move(function));
719
720     NavigationActionData navigationActionData;
721     navigationActionData.navigationType = action->navigationType();
722     navigationActionData.modifiers = action->modifiers();
723     navigationActionData.mouseButton = action->mouseButton();
724     navigationActionData.isProcessingUserGesture = navigationAction.processingUserGesture();
725     navigationActionData.canHandleRequest = webPage->canHandleRequest(request);
726
727     webPage->send(Messages::WebPageProxy::DecidePolicyForNewWindowAction(m_frame->frameID(), navigationActionData, request, frameName, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
728 }
729
730 void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(const NavigationAction& navigationAction, const ResourceRequest& request, PassRefPtr<FormState> prpFormState, FramePolicyFunction function)
731 {
732     WebPage* webPage = m_frame->page();
733     if (!webPage)
734         return;
735
736     // Always ignore requests with empty URLs. 
737     if (request.isEmpty()) {
738         function(PolicyIgnore);
739         return;
740     }
741
742     RefPtr<API::Object> userData;
743     RefPtr<FormState> formState = prpFormState;
744
745     RefPtr<InjectedBundleNavigationAction> action = InjectedBundleNavigationAction::create(m_frame, navigationAction, formState);
746
747     // Notify the bundle client.
748     WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForNavigationAction(webPage, m_frame, action.get(), request, userData);
749     if (policy == WKBundlePagePolicyActionUse) {
750         function(PolicyUse);
751         return;
752     }
753     
754     uint64_t listenerID = m_frame->setUpPolicyListener(WTF::move(function));
755     bool receivedPolicyAction;
756     uint64_t newNavigationID;
757     uint64_t policyAction;
758     uint64_t downloadID;
759
760     RefPtr<WebFrame> originatingFrame;
761     switch (action->navigationType()) {
762     case NavigationTypeLinkClicked:
763         if (EventTarget* target = navigationAction.event()->target()) {
764             if (Node* node = target->toNode()) {
765                 if (Frame* frame = node->document().frame())
766                     originatingFrame = WebFrame::fromCoreFrame(*frame);
767             }
768         }
769         break;
770     case NavigationTypeFormSubmitted:
771     case NavigationTypeFormResubmitted:
772         if (formState)
773             originatingFrame = WebFrame::fromCoreFrame(*formState->sourceDocument()->frame());
774         break;
775     case NavigationTypeBackForward:
776     case NavigationTypeReload:
777     case NavigationTypeOther:
778         break;
779     }
780
781     NavigationActionData navigationActionData;
782     navigationActionData.navigationType = action->navigationType();
783     navigationActionData.modifiers = action->modifiers();
784     navigationActionData.mouseButton = action->mouseButton();
785     navigationActionData.isProcessingUserGesture = navigationAction.processingUserGesture();
786     navigationActionData.canHandleRequest = webPage->canHandleRequest(request);
787
788     WebCore::Frame* coreFrame = m_frame->coreFrame();
789     WebDocumentLoader* documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().policyDocumentLoader());
790     if (!documentLoader)
791         documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().documentLoader());
792
793     // Notify the UIProcess.
794     if (!webPage->sendSync(Messages::WebPageProxy::DecidePolicyForNavigationAction(m_frame->frameID(), documentLoader->navigationID(), navigationActionData, originatingFrame ? originatingFrame->frameID() : 0, navigationAction.resourceRequest(), request, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())), Messages::WebPageProxy::DecidePolicyForNavigationAction::Reply(receivedPolicyAction, newNavigationID, policyAction, downloadID)))
795         return;
796
797     // We call this synchronously because WebCore cannot gracefully handle a frame load without a synchronous navigation policy reply.
798     if (receivedPolicyAction)
799         m_frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), newNavigationID, downloadID);
800 }
801
802 void WebFrameLoaderClient::cancelPolicyCheck()
803 {
804     m_frame->invalidatePolicyListener();
805 }
806
807 void WebFrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError& error)
808 {
809     WebPage* webPage = m_frame->page();
810     if (!webPage)
811         return;
812
813     RefPtr<API::Object> userData;
814
815     // Notify the bundle client.
816     webPage->injectedBundlePolicyClient().unableToImplementPolicy(webPage, m_frame, error, userData);
817
818     // Notify the UIProcess.
819     webPage->send(Messages::WebPageProxy::UnableToImplementPolicy(m_frame->frameID(), error, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
820 }
821
822 void WebFrameLoaderClient::dispatchWillSendSubmitEvent(PassRefPtr<FormState> prpFormState)
823 {
824     WebPage* webPage = m_frame->page();
825     if (!webPage)
826         return;
827
828     RefPtr<FormState> formState = prpFormState;
829     HTMLFormElement* form = formState->form();
830
831     WebFrame* sourceFrame = WebFrame::fromCoreFrame(*formState->sourceDocument()->frame());
832     ASSERT(sourceFrame);
833
834     webPage->injectedBundleFormClient().willSendSubmitEvent(webPage, form, m_frame, sourceFrame, formState->textFieldValues());
835 }
836
837 void WebFrameLoaderClient::dispatchWillSubmitForm(PassRefPtr<FormState> prpFormState, FramePolicyFunction function)
838 {
839     WebPage* webPage = m_frame->page();
840     if (!webPage)
841         return;
842
843     // FIXME: Pass more of the form state.
844     RefPtr<FormState> formState = prpFormState;
845     
846     HTMLFormElement* form = formState->form();
847
848     WebFrame* sourceFrame = WebFrame::fromCoreFrame(*formState->sourceDocument()->frame());
849     ASSERT(sourceFrame);
850
851     const Vector<std::pair<String, String>>& values = formState->textFieldValues();
852
853     RefPtr<API::Object> userData;
854     webPage->injectedBundleFormClient().willSubmitForm(webPage, form, m_frame, sourceFrame, values, userData);
855
856
857     uint64_t listenerID = m_frame->setUpPolicyListener(WTF::move(function));
858
859     webPage->send(Messages::WebPageProxy::WillSubmitForm(m_frame->frameID(), sourceFrame->frameID(), values, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
860 }
861
862 void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader*)
863 {
864     notImplemented();
865 }
866
867 void WebFrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError& error)
868 {
869     if (!m_pluginView)
870         return;
871     
872     m_pluginView->manualLoadDidFail(error);
873     m_pluginView = nullptr;
874     m_hasSentResponseToPluginView = false;
875 }
876
877 void WebFrameLoaderClient::setMainFrameDocumentReady(bool)
878 {
879     notImplemented();
880 }
881
882 void WebFrameLoaderClient::startDownload(const ResourceRequest& request, const String& /* suggestedName */)
883 {
884     m_frame->startDownload(request);
885 }
886
887 void WebFrameLoaderClient::willChangeTitle(DocumentLoader*)
888 {
889     notImplemented();
890 }
891
892 void WebFrameLoaderClient::didChangeTitle(DocumentLoader*)
893 {
894     notImplemented();
895 }
896
897 void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
898 {
899     if (!m_pluginView)
900         loader->commitData(data, length);
901
902     // If the document is a stand-alone media document, now is the right time to cancel the WebKit load.
903     // FIXME: This code should be shared across all ports. <http://webkit.org/b/48762>.
904     if (m_frame->coreFrame()->document()->isMediaDocument())
905         loader->cancelMainResourceLoad(pluginWillHandleLoadError(loader->response()));
906
907     // Calling commitData did not create the plug-in view.
908     if (!m_pluginView)
909         return;
910
911     if (!m_hasSentResponseToPluginView) {
912         m_pluginView->manualLoadDidReceiveResponse(loader->response());
913         // manualLoadDidReceiveResponse sets up a new stream to the plug-in. on a full-page plug-in, a failure in
914         // setting up this stream can cause the main document load to be cancelled, setting m_pluginView
915         // to null
916         if (!m_pluginView)
917             return;
918         m_hasSentResponseToPluginView = true;
919     }
920     m_pluginView->manualLoadDidReceiveData(data, length);
921 }
922
923 void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
924 {
925     if (!m_pluginView) {
926         if (m_frameHasCustomContentProvider) {
927             WebPage* webPage = m_frame->page();
928             if (!webPage)
929                 return;
930
931             RefPtr<SharedBuffer> mainResourceData = loader->mainResourceData();
932             IPC::DataReference dataReference(reinterpret_cast<const uint8_t*>(mainResourceData ? mainResourceData->data() : 0), mainResourceData ? mainResourceData->size() : 0);
933             webPage->send(Messages::WebPageProxy::DidFinishLoadingDataForCustomContentProvider(loader->response().suggestedFilename(), dataReference));
934         }
935
936         return;
937     }
938
939     // If we just received an empty response without any data, we won't have sent a response to the plug-in view.
940     // Make sure to do this before calling manualLoadDidFinishLoading.
941     if (!m_hasSentResponseToPluginView) {
942         m_pluginView->manualLoadDidReceiveResponse(loader->response());
943
944         // Protect against the above call nulling out the plug-in (by trying to cancel the load for example).
945         if (!m_pluginView)
946             return;
947     }
948
949     m_pluginView->manualLoadDidFinishLoading();
950     m_pluginView = nullptr;
951     m_hasSentResponseToPluginView = false;
952 }
953
954 void WebFrameLoaderClient::updateGlobalHistory()
955 {
956     WebPage* webPage = m_frame->page();
957     if (!webPage || !webPage->pageGroup()->isVisibleToHistoryClient())
958         return;
959
960     DocumentLoader* loader = m_frame->coreFrame()->loader().documentLoader();
961
962     WebNavigationDataStore data;
963     data.url = loader->url().string();
964     // FIXME: use direction of title.
965     data.title = loader->title().string();
966     data.originalRequest = loader->originalRequestCopy();
967     data.response = loader->response();
968
969     webPage->send(Messages::WebPageProxy::DidNavigateWithNavigationData(data, m_frame->frameID()));
970 }
971
972 void WebFrameLoaderClient::updateGlobalHistoryRedirectLinks()
973 {
974     WebPage* webPage = m_frame->page();
975     if (!webPage || !webPage->pageGroup()->isVisibleToHistoryClient())
976         return;
977
978     DocumentLoader* loader = m_frame->coreFrame()->loader().documentLoader();
979     ASSERT(loader->unreachableURL().isEmpty());
980
981     // Client redirect
982     if (!loader->clientRedirectSourceForHistory().isNull()) {
983         webPage->send(Messages::WebPageProxy::DidPerformClientRedirect(
984             loader->clientRedirectSourceForHistory(), loader->clientRedirectDestinationForHistory(), m_frame->frameID()));
985     }
986
987     // Server redirect
988     if (!loader->serverRedirectSourceForHistory().isNull()) {
989         webPage->send(Messages::WebPageProxy::DidPerformServerRedirect(
990             loader->serverRedirectSourceForHistory(), loader->serverRedirectDestinationForHistory(), m_frame->frameID()));
991     }
992 }
993
994 bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
995 {
996     WebPage* webPage = m_frame->page();
997     if (!webPage)
998         return false;
999     
1000     uint64_t itemID = WebBackForwardListProxy::idForItem(item);
1001     if (!itemID) {
1002         // We should never be considering navigating to an item that is not actually in the back/forward list.
1003         ASSERT_NOT_REACHED();
1004         return false;
1005     }
1006
1007     RefPtr<InjectedBundleBackForwardListItem> bundleItem = InjectedBundleBackForwardListItem::create(item);
1008     RefPtr<API::Object> userData;
1009
1010     // Ask the bundle client first
1011     bool shouldGoToBackForwardListItem = webPage->injectedBundleLoaderClient().shouldGoToBackForwardListItem(webPage, bundleItem.get(), userData);
1012     if (!shouldGoToBackForwardListItem)
1013         return false;
1014
1015     webPage->send(Messages::WebPageProxy::WillGoToBackForwardListItem(itemID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1016     return true;
1017 }
1018
1019 void WebFrameLoaderClient::didDisplayInsecureContent()
1020 {
1021     WebPage* webPage = m_frame->page();
1022     if (!webPage)
1023         return;
1024
1025     RefPtr<API::Object> userData;
1026
1027     webPage->injectedBundleLoaderClient().didDisplayInsecureContentForFrame(webPage, m_frame, userData);
1028
1029     webPage->send(Messages::WebPageProxy::DidDisplayInsecureContentForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1030 }
1031
1032 void WebFrameLoaderClient::didRunInsecureContent(SecurityOrigin*, const URL&)
1033 {
1034     WebPage* webPage = m_frame->page();
1035     if (!webPage)
1036         return;
1037
1038     RefPtr<API::Object> userData;
1039
1040     webPage->injectedBundleLoaderClient().didRunInsecureContentForFrame(webPage, m_frame, userData);
1041
1042     webPage->send(Messages::WebPageProxy::DidRunInsecureContentForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1043 }
1044
1045 void WebFrameLoaderClient::didDetectXSS(const URL&, bool)
1046 {
1047     WebPage* webPage = m_frame->page();
1048     if (!webPage)
1049         return;
1050
1051     RefPtr<API::Object> userData;
1052
1053     webPage->injectedBundleLoaderClient().didDetectXSSForFrame(webPage, m_frame, userData);
1054
1055     webPage->send(Messages::WebPageProxy::DidDetectXSSForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
1056 }
1057
1058 ResourceError WebFrameLoaderClient::cancelledError(const ResourceRequest& request)
1059 {
1060     return WebKit::cancelledError(request);
1061 }
1062
1063 ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request)
1064 {
1065     return WebKit::blockedError(request);
1066 }
1067
1068 ResourceError WebFrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
1069 {
1070     return WebKit::cannotShowURLError(request);
1071 }
1072
1073 ResourceError WebFrameLoaderClient::interruptedForPolicyChangeError(const ResourceRequest& request)
1074 {
1075     return WebKit::interruptedForPolicyChangeError(request);
1076 }
1077
1078 ResourceError WebFrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
1079 {
1080     return WebKit::cannotShowMIMETypeError(response);
1081 }
1082
1083 ResourceError WebFrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
1084 {
1085     return WebKit::fileDoesNotExistError(response);
1086 }
1087
1088 ResourceError WebFrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response)
1089 {
1090     return WebKit::pluginWillHandleLoadError(response);
1091 }
1092
1093 bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error)
1094 {
1095     static NeverDestroyed<const ResourceError> cancelledError(this->cancelledError(ResourceRequest()));
1096     static NeverDestroyed<const ResourceError> pluginWillHandleLoadError(this->pluginWillHandleLoadError(ResourceResponse()));
1097
1098     if (error.errorCode() == cancelledError.get().errorCode() && error.domain() == cancelledError.get().domain())
1099         return false;
1100
1101     if (error.errorCode() == pluginWillHandleLoadError.get().errorCode() && error.domain() == pluginWillHandleLoadError.get().domain())
1102         return false;
1103
1104     return true;
1105 }
1106
1107 bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest&) const
1108 {
1109     notImplemented();
1110     return true;
1111 }
1112
1113 bool WebFrameLoaderClient::canShowMIMEType(const String& /*MIMEType*/) const
1114 {
1115     notImplemented();
1116     return true;
1117 }
1118
1119 bool WebFrameLoaderClient::canShowMIMETypeAsHTML(const String& /*MIMEType*/) const
1120 {
1121     return true;
1122 }
1123
1124 bool WebFrameLoaderClient::representationExistsForURLScheme(const String& /*URLScheme*/) const
1125 {
1126     notImplemented();
1127     return false;
1128 }
1129
1130 String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& /*URLScheme*/) const
1131 {
1132     notImplemented();
1133     return String();
1134 }
1135
1136 void WebFrameLoaderClient::frameLoadCompleted()
1137 {
1138     // Note: Can be called multiple times.
1139     WebPage* webPage = m_frame->page();
1140     if (!webPage)
1141         return;
1142
1143     if (m_frame->isMainFrame() && !m_didCompletePageTransition) {
1144         webPage->didCompletePageTransition();
1145         m_didCompletePageTransition = true;
1146     }
1147 }
1148
1149 void WebFrameLoaderClient::saveViewStateToItem(HistoryItem* historyItem)
1150 {
1151 #if PLATFORM(IOS) || PLATFORM(EFL)
1152     if (m_frame->isMainFrame())
1153         m_frame->page()->savePageState(*historyItem);
1154 #else
1155     UNUSED_PARAM(historyItem);
1156 #endif
1157 }
1158
1159 void WebFrameLoaderClient::restoreViewState()
1160 {
1161 #if PLATFORM(IOS) || PLATFORM(EFL)
1162     Frame& frame = *m_frame->coreFrame();
1163     HistoryItem* currentItem = frame.loader().history().currentItem();
1164     if (FrameView* view = frame.view()) {
1165         if (m_frame->isMainFrame())
1166             m_frame->page()->restorePageState(*currentItem);
1167         else if (!view->wasScrolledByUser())
1168             view->setScrollPosition(currentItem->scrollPoint());
1169     }
1170 #else
1171     // Inform the UI process of the scale factor.
1172     double scaleFactor = m_frame->coreFrame()->loader().history().currentItem()->pageScaleFactor();
1173
1174     // A scale factor of 0 means the history item has the default scale factor, thus we do not need to update it.
1175     if (scaleFactor)
1176         m_frame->page()->send(Messages::WebPageProxy::PageScaleFactorDidChange(scaleFactor));
1177
1178     // FIXME: This should not be necessary. WebCore should be correctly invalidating
1179     // the view on restores from the back/forward cache.
1180     if (m_frame == m_frame->page()->mainWebFrame())
1181         m_frame->page()->drawingArea()->setNeedsDisplay();
1182 #endif
1183 }
1184
1185 void WebFrameLoaderClient::provisionalLoadStarted()
1186 {
1187     WebPage* webPage = m_frame->page();
1188     if (!webPage)
1189         return;
1190
1191     if (m_frame->isMainFrame()) {
1192         webPage->didStartPageTransition();
1193         m_didCompletePageTransition = false;
1194     }
1195 }
1196
1197 void WebFrameLoaderClient::didFinishLoad()
1198 {
1199     // If we have a load listener, notify it.
1200     if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
1201         loadListener->didFinishLoad(m_frame);
1202 }
1203
1204 void WebFrameLoaderClient::prepareForDataSourceReplacement()
1205 {
1206     notImplemented();
1207 }
1208
1209 PassRefPtr<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
1210 {
1211     return m_frame->page()->createDocumentLoader(*m_frame->coreFrame(), request, substituteData);
1212 }
1213
1214 void WebFrameLoaderClient::setTitle(const StringWithDirection& title, const URL& url)
1215 {
1216     WebPage* webPage = m_frame->page();
1217     if (!webPage || !webPage->pageGroup()->isVisibleToHistoryClient())
1218         return;
1219
1220     // FIXME: use direction of title.
1221     webPage->send(Messages::WebPageProxy::DidUpdateHistoryTitle(title.string(), url.string(), m_frame->frameID()));
1222 }
1223
1224 String WebFrameLoaderClient::userAgent(const URL& url)
1225 {
1226     WebPage* webPage = m_frame->page();
1227     if (!webPage)
1228         return String();
1229
1230     return webPage->userAgent(m_frame, url);
1231 }
1232
1233 void WebFrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame*)
1234 {
1235 }
1236
1237 void WebFrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame*)
1238 {
1239     const ResourceResponse& response = m_frame->coreFrame()->loader().documentLoader()->response();
1240     m_frameHasCustomContentProvider = m_frame->isMainFrame() && m_frame->page()->shouldUseCustomContentProviderForResponse(response);
1241     m_frameCameFromPageCache = true;
1242 }
1243
1244 void WebFrameLoaderClient::transitionToCommittedForNewPage()
1245 {
1246     WebPage* webPage = m_frame->page();
1247
1248     Color backgroundColor = webPage->drawsTransparentBackground() ? Color::transparent : Color::white;
1249     bool isMainFrame = m_frame->isMainFrame();
1250     bool isTransparent = !webPage->drawsBackground();
1251     bool shouldUseFixedLayout = isMainFrame && webPage->useFixedLayout();
1252     bool shouldDisableScrolling = isMainFrame && !webPage->mainFrameIsScrollable();
1253     bool shouldHideScrollbars = shouldUseFixedLayout || shouldDisableScrolling;
1254     IntRect fixedVisibleContentRect;
1255
1256 #if USE(TILED_BACKING_STORE)
1257     if (m_frame->coreFrame()->view())
1258         fixedVisibleContentRect = m_frame->coreFrame()->view()->fixedVisibleContentRect();
1259 #endif
1260
1261     const ResourceResponse& response = m_frame->coreFrame()->loader().documentLoader()->response();
1262     m_frameHasCustomContentProvider = isMainFrame && webPage->shouldUseCustomContentProviderForResponse(response);
1263     m_frameCameFromPageCache = false;
1264
1265     ScrollbarMode defaultScrollbarMode = shouldHideScrollbars ? ScrollbarAlwaysOff : ScrollbarAuto;
1266
1267     m_frame->coreFrame()->createView(webPage->size(), backgroundColor, isTransparent,
1268         IntSize(), fixedVisibleContentRect, shouldUseFixedLayout,
1269         defaultScrollbarMode, /* lock */ shouldHideScrollbars, defaultScrollbarMode, /* lock */ shouldHideScrollbars);
1270
1271     if (int minimumLayoutWidth = webPage->minimumLayoutSize().width()) {
1272         int minimumLayoutHeight = std::max(webPage->minimumLayoutSize().height(), 1);
1273         int maximumSize = std::numeric_limits<int>::max();
1274         m_frame->coreFrame()->view()->enableAutoSizeMode(true, IntSize(minimumLayoutWidth, minimumLayoutHeight), IntSize(maximumSize, maximumSize));
1275         m_frame->coreFrame()->view()->setAutoSizeFixedMinimumHeight(webPage->size().height());
1276     }
1277
1278     m_frame->coreFrame()->view()->setProhibitsScrolling(shouldDisableScrolling);
1279     m_frame->coreFrame()->view()->setVisualUpdatesAllowedByClient(!webPage->shouldExtendIncrementalRenderingSuppression());
1280 #if PLATFORM(COCOA)
1281     m_frame->coreFrame()->view()->setExposedRect(webPage->drawingArea()->exposedRect());
1282 #endif
1283 #if PLATFORM(IOS)
1284     m_frame->coreFrame()->view()->setDelegatesScrolling(true);
1285 #endif
1286
1287     if (webPage->scrollPinningBehavior() != DoNotPin)
1288         m_frame->coreFrame()->view()->setScrollPinningBehavior(webPage->scrollPinningBehavior());
1289
1290 #if USE(TILED_BACKING_STORE)
1291     if (shouldUseFixedLayout) {
1292         m_frame->coreFrame()->view()->setDelegatesScrolling(shouldUseFixedLayout);
1293         m_frame->coreFrame()->view()->setPaintsEntireContents(shouldUseFixedLayout);
1294         return;
1295     }
1296 #endif
1297 }
1298
1299 void WebFrameLoaderClient::didSaveToPageCache()
1300 {
1301     WebPage* webPage = m_frame->page();
1302     if (!webPage)
1303         return;
1304
1305     webPage->send(Messages::WebPageProxy::DidSaveToPageCache());
1306 }
1307
1308 void WebFrameLoaderClient::didRestoreFromPageCache()
1309 {
1310     m_frameCameFromPageCache = true;
1311 }
1312
1313 void WebFrameLoaderClient::dispatchDidBecomeFrameset(bool value)
1314 {
1315     WebPage* webPage = m_frame->page();
1316     if (!webPage)
1317         return;
1318
1319     webPage->send(Messages::WebPageProxy::FrameDidBecomeFrameSet(m_frame->frameID(), value));
1320 }
1321
1322 bool WebFrameLoaderClient::canCachePage() const
1323 {
1324     // We cannot cache frames that have custom representations because they are
1325     // rendered in the UIProcess.
1326     return !m_frameHasCustomContentProvider;
1327 }
1328
1329 void WebFrameLoaderClient::convertMainResourceLoadToDownload(DocumentLoader *documentLoader, const ResourceRequest& request, const ResourceResponse& response)
1330 {
1331     m_frame->convertMainResourceLoadToDownload(documentLoader, request, response);
1332 }
1333
1334 PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const URL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
1335                                                     const String& referrer, bool /*allowsScrolling*/, int /*marginWidth*/, int /*marginHeight*/)
1336 {
1337     WebPage* webPage = m_frame->page();
1338
1339     RefPtr<WebFrame> subframe = WebFrame::createSubframe(webPage, name, ownerElement);
1340
1341     Frame* coreSubframe = subframe->coreFrame();
1342     if (!coreSubframe)
1343         return 0;
1344
1345     // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
1346     if (!coreSubframe->page())
1347         return 0;
1348
1349     m_frame->coreFrame()->loader().loadURLIntoChildFrame(url, referrer, coreSubframe);
1350
1351     // The frame's onload handler may have removed it from the document.
1352     if (!subframe->coreFrame())
1353         return 0;
1354     ASSERT(subframe->coreFrame() == coreSubframe);
1355     if (!coreSubframe->tree().parent())
1356         return 0;
1357
1358     return coreSubframe;
1359 }
1360
1361 PassRefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize&, HTMLPlugInElement* pluginElement, const URL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
1362 {
1363     ASSERT(paramNames.size() == paramValues.size());
1364     ASSERT(m_frame->page());
1365
1366     Plugin::Parameters parameters;
1367     parameters.url = url;
1368     parameters.names = paramNames;
1369     parameters.values = paramValues;
1370     parameters.mimeType = mimeType;
1371     parameters.isFullFramePlugin = loadManually;
1372     parameters.shouldUseManualLoader = parameters.isFullFramePlugin && !m_frameCameFromPageCache;
1373 #if PLATFORM(COCOA)
1374     parameters.layerHostingMode = m_frame->page()->layerHostingMode();
1375 #endif
1376
1377 #if ENABLE(NETSCAPE_PLUGIN_API)
1378     RefPtr<Plugin> plugin = m_frame->page()->createPlugin(m_frame, pluginElement, parameters, parameters.mimeType);
1379     if (!plugin)
1380         return 0;
1381
1382     return PluginView::create(pluginElement, plugin.release(), parameters);
1383 #else
1384     UNUSED_PARAM(pluginElement);
1385     return 0;
1386 #endif
1387 }
1388
1389 void WebFrameLoaderClient::recreatePlugin(Widget* widget)
1390 {
1391 #if ENABLE(NETSCAPE_PLUGIN_API)
1392     ASSERT(widget && widget->isPluginViewBase());
1393     ASSERT(m_frame->page());
1394
1395     PluginView* pluginView = static_cast<PluginView*>(widget);
1396     String newMIMEType;
1397     RefPtr<Plugin> plugin = m_frame->page()->createPlugin(m_frame, pluginView->pluginElement(), pluginView->initialParameters(), newMIMEType);
1398     pluginView->recreateAndInitialize(plugin.release());
1399 #else
1400     UNUSED_PARAM(widget);
1401 #endif
1402 }
1403
1404 void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
1405 {
1406     if (pluginWidget)
1407         m_pluginView = static_cast<PluginView*>(pluginWidget);
1408 }
1409
1410 #if ENABLE(WEBGL)
1411 WebCore::WebGLLoadPolicy WebFrameLoaderClient::webGLPolicyForURL(const String& url) const
1412 {
1413     if (WebPage* webPage = m_frame->page())
1414         return webPage->webGLPolicyForURL(m_frame, url);
1415
1416     return WebGLAllowCreation;
1417 }
1418
1419 WebCore::WebGLLoadPolicy WebFrameLoaderClient::resolveWebGLPolicyForURL(const String& url) const
1420 {
1421     if (WebPage* webPage = m_frame->page())
1422         return webPage->resolveWebGLPolicyForURL(m_frame, url);
1423
1424     return WebGLAllowCreation;
1425 }
1426 #endif // ENABLE(WEBGL)
1427
1428 PassRefPtr<Widget> WebFrameLoaderClient::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement* appletElement, const URL&, const Vector<String>& paramNames, const Vector<String>& paramValues)
1429 {
1430 #if ENABLE(NETSCAPE_PLUGIN_API)
1431     RefPtr<Widget> plugin = createPlugin(pluginSize, appletElement, URL(), paramNames, paramValues, appletElement->serviceType(), false);
1432     if (!plugin) {
1433         if (WebPage* webPage = m_frame->page()) {
1434             String frameURLString = m_frame->coreFrame()->loader().documentLoader()->responseURL().string();
1435             String pageURLString = webPage->corePage()->mainFrame().loader().documentLoader()->responseURL().string();
1436             webPage->send(Messages::WebPageProxy::DidFailToInitializePlugin(appletElement->serviceType(), frameURLString, pageURLString));
1437         }
1438     }
1439     return plugin.release();
1440 #else
1441     UNUSED_PARAM(pluginSize);
1442     UNUSED_PARAM(appletElement);
1443     UNUSED_PARAM(paramNames);
1444     UNUSED_PARAM(paramValues);
1445     return 0;
1446 #endif
1447 }
1448
1449 static bool pluginSupportsExtension(const PluginData& pluginData, const String& extension)
1450 {
1451     ASSERT(extension.lower() == extension);
1452
1453     for (size_t i = 0; i < pluginData.mimes().size(); ++i) {
1454         const MimeClassInfo& mimeClassInfo = pluginData.mimes()[i];
1455
1456         if (mimeClassInfo.extensions.contains(extension))
1457             return true;
1458     }
1459     return false;
1460 }
1461
1462 ObjectContentType WebFrameLoaderClient::objectContentType(const URL& url, const String& mimeTypeIn, bool shouldPreferPlugInsForImages)
1463 {
1464     // FIXME: This should be merged with WebCore::FrameLoader::defaultObjectContentType when the plugin code
1465     // is consolidated.
1466
1467     String mimeType = mimeTypeIn;
1468     if (mimeType.isEmpty()) {
1469         String extension = url.path().substring(url.path().reverseFind('.') + 1).lower();
1470
1471         // Try to guess the MIME type from the extension.
1472         mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
1473
1474         if (mimeType.isEmpty()) {
1475             // Check if there's a plug-in around that can handle the extension.
1476             if (WebPage* webPage = m_frame->page()) {
1477                 if (pluginSupportsExtension(webPage->corePage()->pluginData(), extension))
1478                     return ObjectContentNetscapePlugin;
1479             }
1480         }
1481     }
1482
1483     if (mimeType.isEmpty())
1484         return ObjectContentFrame;
1485
1486     bool plugInSupportsMIMEType = false;
1487     if (WebPage* webPage = m_frame->page()) {
1488         const PluginData& pluginData = webPage->corePage()->pluginData();
1489         if (pluginData.supportsMimeType(mimeType, PluginData::AllPlugins) && webFrame()->coreFrame()->loader().subframeLoader().allowPlugins(NotAboutToInstantiatePlugin))
1490             plugInSupportsMIMEType = true;
1491         else if (pluginData.supportsMimeType(mimeType, PluginData::OnlyApplicationPlugins))
1492             plugInSupportsMIMEType = true;
1493     }
1494     
1495     if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
1496         return shouldPreferPlugInsForImages && plugInSupportsMIMEType ? ObjectContentNetscapePlugin : ObjectContentImage;
1497
1498     if (plugInSupportsMIMEType)
1499         return ObjectContentNetscapePlugin;
1500
1501     if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
1502         return ObjectContentFrame;
1503
1504 #if PLATFORM(IOS)
1505     // iOS can render PDF in <object>/<embed> via PDFDocumentImage.
1506     if (MIMETypeRegistry::isPDFOrPostScriptMIMEType(mimeType))
1507         return ObjectContentImage;
1508 #endif
1509
1510     return ObjectContentNone;
1511 }
1512
1513 String WebFrameLoaderClient::overrideMediaType() const
1514 {
1515     notImplemented();
1516     return String();
1517 }
1518
1519 void WebFrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
1520 {
1521     WebPage* webPage = m_frame->page();
1522     if (!webPage)
1523         return;
1524
1525     webPage->injectedBundleLoaderClient().didClearWindowObjectForFrame(webPage, m_frame, world);
1526
1527 #if HAVE(ACCESSIBILITY) && (PLATFORM(GTK) || PLATFORM(EFL))
1528     // Ensure the accessibility hierarchy is updated.
1529     webPage->updateAccessibilityTree();
1530 #endif
1531 }
1532
1533
1534 void WebFrameLoaderClient::dispatchGlobalObjectAvailable(DOMWrapperWorld& world)
1535 {
1536     WebPage* webPage = m_frame->page();
1537     if (!webPage)
1538         return;
1539     
1540     webPage->injectedBundleLoaderClient().globalObjectIsAvailableForFrame(webPage, m_frame, world);
1541 }
1542
1543 void WebFrameLoaderClient::dispatchWillDisconnectDOMWindowExtensionFromGlobalObject(WebCore::DOMWindowExtension* extension)
1544 {
1545     WebPage* webPage = m_frame->page();
1546     if (!webPage)
1547         return;
1548         
1549     webPage->injectedBundleLoaderClient().willDisconnectDOMWindowExtensionFromGlobalObject(webPage, extension);
1550 }
1551
1552 void WebFrameLoaderClient::dispatchDidReconnectDOMWindowExtensionToGlobalObject(WebCore::DOMWindowExtension* extension)
1553 {
1554     WebPage* webPage = m_frame->page();
1555     if (!webPage)
1556         return;
1557         
1558     webPage->injectedBundleLoaderClient().didReconnectDOMWindowExtensionToGlobalObject(webPage, extension);
1559 }
1560
1561 void WebFrameLoaderClient::dispatchWillDestroyGlobalObjectForDOMWindowExtension(WebCore::DOMWindowExtension* extension)
1562 {
1563     WebPage* webPage = m_frame->page();
1564     if (!webPage)
1565         return;
1566         
1567     webPage->injectedBundleLoaderClient().willDestroyGlobalObjectForDOMWindowExtension(webPage, extension);
1568 }
1569
1570 void WebFrameLoaderClient::registerForIconNotification(bool /*listen*/)
1571 {
1572     notImplemented();
1573 }
1574
1575 #if PLATFORM(COCOA)
1576     
1577 RemoteAXObjectRef WebFrameLoaderClient::accessibilityRemoteObject() 
1578 {
1579     WebPage* webPage = m_frame->page();
1580     if (!webPage)
1581         return 0;
1582     
1583     return webPage->accessibilityRemoteObject();
1584 }
1585     
1586 NSCachedURLResponse* WebFrameLoaderClient::willCacheResponse(DocumentLoader*, unsigned long identifier, NSCachedURLResponse* response) const
1587 {
1588     WebPage* webPage = m_frame->page();
1589     if (!webPage)
1590         return response;
1591
1592     return webPage->injectedBundleResourceLoadClient().shouldCacheResponse(webPage, m_frame, identifier) ? response : nil;
1593 }
1594
1595 #endif // PLATFORM(COCOA)
1596
1597 bool WebFrameLoaderClient::shouldAlwaysUsePluginDocument(const String& /*mimeType*/) const
1598 {
1599     notImplemented();
1600     return false;
1601 }
1602
1603 void WebFrameLoaderClient::didChangeScrollOffset()
1604 {
1605     WebPage* webPage = m_frame->page();
1606     if (!webPage)
1607         return;
1608
1609     webPage->didChangeScrollOffsetForFrame(m_frame->coreFrame());
1610 }
1611
1612 bool WebFrameLoaderClient::allowScript(bool enabledPerSettings)
1613 {
1614     if (!enabledPerSettings)
1615         return false;
1616
1617     Frame* coreFrame = m_frame->coreFrame();
1618
1619     if (coreFrame->document()->isPluginDocument()) {
1620         PluginDocument* pluginDocument = static_cast<PluginDocument*>(coreFrame->document());
1621
1622         if (pluginDocument->pluginWidget() && pluginDocument->pluginWidget()->isPluginView()) {
1623             PluginView* pluginView = static_cast<PluginView*>(pluginDocument->pluginWidget());
1624
1625             if (!pluginView->shouldAllowScripting())
1626                 return false;
1627         }
1628     }
1629
1630     return true;
1631 }
1632
1633 bool WebFrameLoaderClient::shouldForceUniversalAccessFromLocalURL(const WebCore::URL& url)
1634 {
1635     WebPage* webPage = m_frame->page();
1636     if (!webPage)
1637         return false;
1638
1639     return webPage->injectedBundleLoaderClient().shouldForceUniversalAccessFromLocalURL(webPage, url.string());
1640 }
1641
1642 PassRefPtr<FrameNetworkingContext> WebFrameLoaderClient::createNetworkingContext()
1643 {
1644     RefPtr<WebFrameNetworkingContext> context = WebFrameNetworkingContext::create(m_frame);
1645     return context.release();
1646 }
1647
1648 #if ENABLE(CONTENT_FILTERING)
1649 void WebFrameLoaderClient::contentFilterDidBlockLoad(std::unique_ptr<WebCore::ContentFilter> contentFilter)
1650 {
1651     if (WebPage* webPage = m_frame->page())
1652         webPage->send(Messages::WebPageProxy::ContentFilterDidBlockLoadForFrame(*contentFilter, m_frame->frameID()));
1653 }
1654 #endif
1655
1656 #if ENABLE(REQUEST_AUTOCOMPLETE)
1657 void WebFrameLoaderClient::didRequestAutocomplete(PassRefPtr<WebCore::FormState>)
1658 {
1659 }
1660 #endif
1661
1662 } // namespace WebKit