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