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