1/*
2 * Copyright (C) 2010, 2011 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 "InjectedBundleNavigationAction.h"
32#include "InjectedBundleUserMessageCoders.h"
33#include "PlatformCertificateInfo.h"
34#include "PluginView.h"
35#include "StringPairVector.h"
36#include "WebBackForwardListProxy.h"
37#include "WebContextMessages.h"
38#include "WebCoreArgumentCoders.h"
39#include "WebErrors.h"
40#include "WebEvent.h"
41#include "WebFrame.h"
42#include "WebFrameNetworkingContext.h"
43#include "WebNavigationDataStore.h"
44#include "WebPage.h"
45#include "WebPageProxyMessages.h"
46#include "WebProcess.h"
47#include "WebProcessProxyMessages.h"
48#include <JavaScriptCore/APICast.h>
49#include <JavaScriptCore/JSObject.h>
50#include <WebCore/Chrome.h>
51#include <WebCore/DOMWrapperWorld.h>
52#include <WebCore/DocumentLoader.h>
53#include <WebCore/FormState.h>
54#include <WebCore/Frame.h>
55#include <WebCore/FrameLoadRequest.h>
56#include <WebCore/FrameView.h>
57#include <WebCore/HTMLAppletElement.h>
58#include <WebCore/HTMLFormElement.h>
59#include <WebCore/HistoryItem.h>
60#include <WebCore/MIMETypeRegistry.h>
61#include <WebCore/MouseEvent.h>
62#include <WebCore/NotImplemented.h>
63#include <WebCore/Page.h>
64#include <WebCore/PluginData.h>
65#include <WebCore/ProgressTracker.h>
66#include <WebCore/ResourceError.h>
67#include <WebCore/UIEventWithKeyState.h>
68#include <WebCore/Widget.h>
69#include <WebCore/WindowFeatures.h>
70
71using namespace WebCore;
72
73namespace WebKit {
74
75WebFrameLoaderClient::WebFrameLoaderClient(WebFrame* frame)
76    : m_frame(frame)
77    , m_hasSentResponseToPluginView(false)
78    , m_frameHasCustomRepresentation(false)
79{
80}
81
82WebFrameLoaderClient::~WebFrameLoaderClient()
83{
84}
85
86void WebFrameLoaderClient::frameLoaderDestroyed()
87{
88    m_frame->invalidate();
89
90    // Balances explicit ref() in WebFrame::createMainFrame and WebFrame::createSubframe.
91    m_frame->deref();
92}
93
94bool WebFrameLoaderClient::hasHTMLView() const
95{
96    return !m_frameHasCustomRepresentation;
97}
98
99bool WebFrameLoaderClient::hasWebView() const
100{
101    return m_frame->page();
102}
103
104void WebFrameLoaderClient::makeRepresentation(DocumentLoader*)
105{
106    notImplemented();
107}
108
109void WebFrameLoaderClient::forceLayout()
110{
111    notImplemented();
112}
113
114void WebFrameLoaderClient::forceLayoutForNonHTML()
115{
116    notImplemented();
117}
118
119void WebFrameLoaderClient::setCopiesOnScroll()
120{
121    notImplemented();
122}
123
124void WebFrameLoaderClient::detachedFromParent2()
125{
126    WebPage* webPage = m_frame->page();
127    if (!webPage)
128        return;
129
130    RefPtr<APIObject> userData;
131
132    // Notify the bundle client.
133    webPage->injectedBundleLoaderClient().didRemoveFrameFromHierarchy(webPage, m_frame, userData);
134
135    // Notify the UIProcess.
136    webPage->send(Messages::WebPageProxy::DidRemoveFrameFromHierarchy(m_frame->frameID(), InjectedBundleUserMessageEncoder(userData.get())));
137
138}
139
140void WebFrameLoaderClient::detachedFromParent3()
141{
142    notImplemented();
143}
144
145void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
146{
147    WebPage* webPage = m_frame->page();
148    if (!webPage)
149        return;
150
151    bool pageIsProvisionallyLoading = false;
152    if (FrameLoader* frameLoader = loader->frameLoader())
153        pageIsProvisionallyLoading = frameLoader->provisionalDocumentLoader() == loader;
154
155    webPage->injectedBundleResourceLoadClient().didInitiateLoadForResource(webPage, m_frame, identifier, request, pageIsProvisionallyLoading);
156    webPage->send(Messages::WebPageProxy::DidInitiateLoadForResource(m_frame->frameID(), identifier, request, pageIsProvisionallyLoading));
157}
158
159void WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
160{
161    WebPage* webPage = m_frame->page();
162    if (!webPage)
163        return;
164
165    webPage->injectedBundleResourceLoadClient().willSendRequestForFrame(webPage, m_frame, identifier, request, redirectResponse);
166
167    if (request.isNull()) {
168        // FIXME: We should probably send a message saying we cancelled the request for the resource.
169        return;
170    }
171
172    webPage->send(Messages::WebPageProxy::DidSendRequestForResource(m_frame->frameID(), identifier, request, redirectResponse));
173}
174
175bool WebFrameLoaderClient::shouldUseCredentialStorage(DocumentLoader*, unsigned long identifier)
176{
177    return true;
178}
179
180void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long, const AuthenticationChallenge& challenge)
181{
182    // FIXME: Authentication is a per-resource concept, but we don't do per-resource handling in the UIProcess at the API level quite yet.
183    // Once we do, we might need to make sure authentication fits with our solution.
184
185    WebPage* webPage = m_frame->page();
186    if (!webPage)
187        return;
188
189    AuthenticationManager::shared().didReceiveAuthenticationChallenge(m_frame, challenge);
190}
191
192void WebFrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&)
193{
194    notImplemented();
195}
196
197#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
198bool WebFrameLoaderClient::canAuthenticateAgainstProtectionSpace(DocumentLoader*, unsigned long, const ProtectionSpace& protectionSpace)
199{
200    // FIXME: Authentication is a per-resource concept, but we don't do per-resource handling in the UIProcess at the API level quite yet.
201    // Once we do, we might need to make sure authentication fits with our solution.
202
203    WebPage* webPage = m_frame->page();
204    if (!webPage)
205        return false;
206
207    bool canAuthenticate;
208    if (!webPage->sendSync(Messages::WebPageProxy::CanAuthenticateAgainstProtectionSpaceInFrame(m_frame->frameID(), protectionSpace), Messages::WebPageProxy::CanAuthenticateAgainstProtectionSpaceInFrame::Reply(canAuthenticate)))
209        return false;
210
211    return canAuthenticate;
212}
213#endif
214
215void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse& response)
216{
217    WebPage* webPage = m_frame->page();
218    if (!webPage)
219        return;
220
221    webPage->injectedBundleResourceLoadClient().didReceiveResponseForResource(webPage, m_frame, identifier, response);
222    webPage->send(Messages::WebPageProxy::DidReceiveResponseForResource(m_frame->frameID(), identifier, response));
223}
224
225void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int dataLength)
226{
227    WebPage* webPage = m_frame->page();
228    if (!webPage)
229        return;
230
231    webPage->injectedBundleResourceLoadClient().didReceiveContentLengthForResource(webPage, m_frame, identifier, dataLength);
232    webPage->send(Messages::WebPageProxy::DidReceiveContentLengthForResource(m_frame->frameID(), identifier, dataLength));
233}
234
235void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier)
236{
237    WebPage* webPage = m_frame->page();
238    if (!webPage)
239        return;
240
241    webPage->injectedBundleResourceLoadClient().didFinishLoadForResource(webPage, m_frame, identifier);
242    webPage->send(Messages::WebPageProxy::DidFinishLoadForResource(m_frame->frameID(), identifier));
243}
244
245void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError& error)
246{
247    WebPage* webPage = m_frame->page();
248    if (!webPage)
249        return;
250
251    webPage->injectedBundleResourceLoadClient().didFailLoadForResource(webPage, m_frame, identifier, error);
252    webPage->send(Messages::WebPageProxy::DidFailLoadForResource(m_frame->frameID(), identifier, error));
253}
254
255bool WebFrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length)
256{
257    notImplemented();
258    return false;
259}
260
261void WebFrameLoaderClient::dispatchDidLoadResourceByXMLHttpRequest(unsigned long identifier, const String&)
262{
263    notImplemented();
264}
265
266void WebFrameLoaderClient::dispatchDidHandleOnloadEvents()
267{
268    WebPage* webPage = m_frame->page();
269    if (!webPage)
270        return;
271
272    // Notify the bundle client.
273    webPage->injectedBundleLoaderClient().didHandleOnloadEventsForFrame(webPage, m_frame);
274}
275
276void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
277{
278    WebPage* webPage = m_frame->page();
279    if (!webPage)
280        return;
281
282    DocumentLoader* provisionalLoader = m_frame->coreFrame()->loader()->provisionalDocumentLoader();
283    const String& url = provisionalLoader->url().string();
284    RefPtr<APIObject> userData;
285
286    // Notify the bundle client.
287    webPage->injectedBundleLoaderClient().didReceiveServerRedirectForProvisionalLoadForFrame(webPage, m_frame, userData);
288
289    // Notify the UIProcess.
290    webPage->send(Messages::WebPageProxy::DidReceiveServerRedirectForProvisionalLoadForFrame(m_frame->frameID(), url, InjectedBundleUserMessageEncoder(userData.get())));
291}
292
293void WebFrameLoaderClient::dispatchDidCancelClientRedirect()
294{
295    WebPage* webPage = m_frame->page();
296    if (!webPage)
297        return;
298
299    // Notify the bundle client.
300    webPage->injectedBundleLoaderClient().didCancelClientRedirectForFrame(webPage, m_frame);
301}
302
303void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const KURL& url, double interval, double fireDate)
304{
305    WebPage* webPage = m_frame->page();
306    if (!webPage)
307        return;
308
309    // Notify the bundle client.
310    webPage->injectedBundleLoaderClient().willPerformClientRedirectForFrame(webPage, m_frame, url.string(), interval, fireDate);
311}
312
313void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage()
314{
315    WebPage* webPage = m_frame->page();
316    if (!webPage)
317        return;
318
319    RefPtr<APIObject> userData;
320
321    // Notify the bundle client.
322    webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(webPage, m_frame, SameDocumentNavigationAnchorNavigation, userData);
323
324    // Notify the UIProcess.
325    webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), SameDocumentNavigationAnchorNavigation, m_frame->coreFrame()->document()->url().string(), InjectedBundleUserMessageEncoder(userData.get())));
326}
327
328void WebFrameLoaderClient::dispatchDidPushStateWithinPage()
329{
330    WebPage* webPage = m_frame->page();
331    if (!webPage)
332        return;
333
334    RefPtr<APIObject> userData;
335
336    // Notify the bundle client.
337    webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(webPage, m_frame, SameDocumentNavigationSessionStatePush, userData);
338
339    // Notify the UIProcess.
340    webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), SameDocumentNavigationSessionStatePush, m_frame->coreFrame()->document()->url().string(), InjectedBundleUserMessageEncoder(userData.get())));
341}
342
343void WebFrameLoaderClient::dispatchDidReplaceStateWithinPage()
344{
345    WebPage* webPage = m_frame->page();
346    if (!webPage)
347        return;
348
349    RefPtr<APIObject> userData;
350
351    // Notify the bundle client.
352    webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(webPage, m_frame, SameDocumentNavigationSessionStateReplace, userData);
353
354    // Notify the UIProcess.
355    webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), SameDocumentNavigationSessionStateReplace, m_frame->coreFrame()->document()->url().string(), InjectedBundleUserMessageEncoder(userData.get())));
356}
357
358void WebFrameLoaderClient::dispatchDidPopStateWithinPage()
359{
360    WebPage* webPage = m_frame->page();
361    if (!webPage)
362        return;
363
364    RefPtr<APIObject> userData;
365
366    // Notify the bundle client.
367    webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(webPage, m_frame, SameDocumentNavigationSessionStatePop, userData);
368
369    // Notify the UIProcess.
370    webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), SameDocumentNavigationSessionStatePop, m_frame->coreFrame()->document()->url().string(), InjectedBundleUserMessageEncoder(userData.get())));
371}
372
373void WebFrameLoaderClient::dispatchWillClose()
374{
375    notImplemented();
376}
377
378void WebFrameLoaderClient::dispatchDidReceiveIcon()
379{
380    notImplemented();
381}
382
383void WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
384{
385    WebPage* webPage = m_frame->page();
386    if (!webPage)
387        return;
388
389    webPage->findController().hideFindUI();
390    webPage->sandboxExtensionTracker().didStartProvisionalLoad(m_frame);
391
392    DocumentLoader* provisionalLoader = m_frame->coreFrame()->loader()->provisionalDocumentLoader();
393    const String& url = provisionalLoader->url().string();
394    RefPtr<APIObject> userData;
395
396    // Notify the bundle client.
397    webPage->injectedBundleLoaderClient().didStartProvisionalLoadForFrame(webPage, m_frame, userData);
398
399    String unreachableURL = provisionalLoader->unreachableURL().string();
400
401    // Notify the UIProcess.
402    webPage->send(Messages::WebPageProxy::DidStartProvisionalLoadForFrame(m_frame->frameID(), url, unreachableURL, InjectedBundleUserMessageEncoder(userData.get())));
403}
404
405void WebFrameLoaderClient::dispatchDidReceiveTitle(const StringWithDirection& title)
406{
407    WebPage* webPage = m_frame->page();
408    if (!webPage)
409        return;
410
411    RefPtr<APIObject> userData;
412
413    // Notify the bundle client.
414    // FIXME: use direction of title.
415    webPage->injectedBundleLoaderClient().didReceiveTitleForFrame(webPage, title.string(), m_frame, userData);
416
417    // Notify the UIProcess.
418    webPage->send(Messages::WebPageProxy::DidReceiveTitleForFrame(m_frame->frameID(), title.string(), InjectedBundleUserMessageEncoder(userData.get())));
419}
420
421void WebFrameLoaderClient::dispatchDidChangeIcons()
422{
423    notImplemented();
424}
425
426void WebFrameLoaderClient::dispatchDidCommitLoad()
427{
428    WebPage* webPage = m_frame->page();
429    if (!webPage)
430        return;
431
432    const ResourceResponse& response = m_frame->coreFrame()->loader()->documentLoader()->response();
433    RefPtr<APIObject> userData;
434
435    // Notify the bundle client.
436    webPage->injectedBundleLoaderClient().didCommitLoadForFrame(webPage, m_frame, userData);
437
438    webPage->sandboxExtensionTracker().didCommitProvisionalLoad(m_frame);
439
440    // Notify the UIProcess.
441
442    webPage->send(Messages::WebPageProxy::DidCommitLoadForFrame(m_frame->frameID(), response.mimeType(), m_frameHasCustomRepresentation, PlatformCertificateInfo(response), InjectedBundleUserMessageEncoder(userData.get())));
443
444    // Only restore the scale factor for standard frame loads (of the main frame).
445    if (m_frame->isMainFrame() && m_frame->coreFrame()->loader()->loadType() == FrameLoadTypeStandard) {
446        if (m_frame->coreFrame()->pageScaleFactor() != 1)
447            webPage->scaleWebView(1, IntPoint());
448    }
449}
450
451void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
452{
453    WebPage* webPage = m_frame->page();
454    if (!webPage)
455        return;
456
457    RefPtr<APIObject> userData;
458
459    // Notify the bundle client.
460    webPage->injectedBundleLoaderClient().didFailProvisionalLoadWithErrorForFrame(webPage, m_frame, error, userData);
461
462    webPage->sandboxExtensionTracker().didFailProvisionalLoad(m_frame);
463
464    // Notify the UIProcess.
465    webPage->send(Messages::WebPageProxy::DidFailProvisionalLoadForFrame(m_frame->frameID(), error, InjectedBundleUserMessageEncoder(userData.get())));
466
467    // If we have a load listener, notify it.
468    if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
469        loadListener->didFailLoad(m_frame, error.isCancellation());
470}
471
472void WebFrameLoaderClient::dispatchDidFailLoad(const ResourceError& error)
473{
474    WebPage* webPage = m_frame->page();
475    if (!webPage)
476        return;
477
478    RefPtr<APIObject> userData;
479
480    // Notify the bundle client.
481    webPage->injectedBundleLoaderClient().didFailLoadWithErrorForFrame(webPage, m_frame, error, userData);
482
483    // Notify the UIProcess.
484    webPage->send(Messages::WebPageProxy::DidFailLoadForFrame(m_frame->frameID(), error, InjectedBundleUserMessageEncoder(userData.get())));
485
486    // If we have a load listener, notify it.
487    if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
488        loadListener->didFailLoad(m_frame, error.isCancellation());
489}
490
491void WebFrameLoaderClient::dispatchDidFinishDocumentLoad()
492{
493    WebPage* webPage = m_frame->page();
494    if (!webPage)
495        return;
496
497    RefPtr<APIObject> userData;
498
499    // Notify the bundle client.
500    webPage->injectedBundleLoaderClient().didFinishDocumentLoadForFrame(webPage, m_frame, userData);
501
502    // Notify the UIProcess.
503    webPage->send(Messages::WebPageProxy::DidFinishDocumentLoadForFrame(m_frame->frameID(), InjectedBundleUserMessageEncoder(userData.get())));
504}
505
506void WebFrameLoaderClient::dispatchDidFinishLoad()
507{
508    WebPage* webPage = m_frame->page();
509    if (!webPage)
510        return;
511
512    RefPtr<APIObject> userData;
513
514    // Notify the bundle client.
515    webPage->injectedBundleLoaderClient().didFinishLoadForFrame(webPage, m_frame, userData);
516
517    // Notify the UIProcess.
518    webPage->send(Messages::WebPageProxy::DidFinishLoadForFrame(m_frame->frameID(), InjectedBundleUserMessageEncoder(userData.get())));
519
520    // If we have a load listener, notify it.
521    if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
522        loadListener->didFinishLoad(m_frame);
523}
524
525void WebFrameLoaderClient::dispatchDidFirstLayout()
526{
527    WebPage* webPage = m_frame->page();
528    if (!webPage)
529        return;
530
531    RefPtr<APIObject> userData;
532
533    // Notify the bundle client.
534    webPage->injectedBundleLoaderClient().didFirstLayoutForFrame(webPage, m_frame, userData);
535
536    // Notify the UIProcess.
537    webPage->send(Messages::WebPageProxy::DidFirstLayoutForFrame(m_frame->frameID(), InjectedBundleUserMessageEncoder(userData.get())));
538}
539
540void WebFrameLoaderClient::dispatchDidFirstVisuallyNonEmptyLayout()
541{
542    WebPage* webPage = m_frame->page();
543    if (!webPage)
544        return;
545
546    RefPtr<APIObject> userData;
547
548    // Notify the bundle client.
549    webPage->injectedBundleLoaderClient().didFirstVisuallyNonEmptyLayoutForFrame(webPage, m_frame, userData);
550
551    // Notify the UIProcess.
552    webPage->send(Messages::WebPageProxy::DidFirstVisuallyNonEmptyLayoutForFrame(m_frame->frameID(), InjectedBundleUserMessageEncoder(userData.get())));
553}
554
555Frame* WebFrameLoaderClient::dispatchCreatePage(const NavigationAction& navigationAction)
556{
557    WebPage* webPage = m_frame->page();
558    if (!webPage)
559        return 0;
560
561    // Just call through to the chrome client.
562    Page* newPage = webPage->corePage()->chrome()->createWindow(m_frame->coreFrame(), FrameLoadRequest(m_frame->coreFrame()->document()->securityOrigin()), WindowFeatures(), navigationAction);
563    if (!newPage)
564        return 0;
565
566    return newPage->mainFrame();
567}
568
569void WebFrameLoaderClient::dispatchShow()
570{
571    WebPage* webPage = m_frame->page();
572    if (!webPage)
573        return;
574
575    webPage->show();
576}
577
578void WebFrameLoaderClient::dispatchDecidePolicyForResponse(FramePolicyFunction function, const ResourceResponse& response, const ResourceRequest& request)
579{
580    WebPage* webPage = m_frame->page();
581    if (!webPage)
582        return;
583
584    if (!request.url().string())
585        return;
586
587    RefPtr<APIObject> userData;
588
589    // Notify the bundle client.
590    WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForResponse(webPage, m_frame, response, request, userData);
591    if (policy == WKBundlePagePolicyActionUse) {
592        (m_frame->coreFrame()->loader()->policyChecker()->*function)(PolicyUse);
593        return;
594    }
595
596    uint64_t listenerID = m_frame->setUpPolicyListener(function);
597    bool receivedPolicyAction;
598    uint64_t policyAction;
599    uint64_t downloadID;
600
601    // Notify the UIProcess.
602    if (!webPage->sendSync(Messages::WebPageProxy::DecidePolicyForResponse(m_frame->frameID(), response, request, listenerID, InjectedBundleUserMessageEncoder(userData.get())), Messages::WebPageProxy::DecidePolicyForResponse::Reply(receivedPolicyAction, policyAction, downloadID)))
603        return;
604
605    // We call this synchronously because CFNetwork can only convert a loading connection to a download from its didReceiveResponse callback.
606    if (receivedPolicyAction)
607        m_frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), downloadID);
608}
609
610void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function, const NavigationAction& navigationAction, const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName)
611{
612    WebPage* webPage = m_frame->page();
613    if (!webPage)
614        return;
615
616    RefPtr<APIObject> userData;
617
618    RefPtr<InjectedBundleNavigationAction> action = InjectedBundleNavigationAction::create(m_frame, navigationAction, formState);
619
620    // Notify the bundle client.
621    WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForNewWindowAction(webPage, m_frame, action.get(), request, frameName, userData);
622    if (policy == WKBundlePagePolicyActionUse) {
623        (m_frame->coreFrame()->loader()->policyChecker()->*function)(PolicyUse);
624        return;
625    }
626
627
628    uint64_t listenerID = m_frame->setUpPolicyListener(function);
629
630    // Notify the UIProcess.
631    webPage->send(Messages::WebPageProxy::DecidePolicyForNewWindowAction(m_frame->frameID(), action->navigationType(), action->modifiers(), action->mouseButton(), request, frameName, listenerID, InjectedBundleUserMessageEncoder(userData.get())));
632}
633
634void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, const NavigationAction& navigationAction, const ResourceRequest& request, PassRefPtr<FormState> formState)
635{
636    WebPage* webPage = m_frame->page();
637    if (!webPage)
638        return;
639
640    // Always ignore requests with empty URLs.
641    if (request.isEmpty()) {
642        (m_frame->coreFrame()->loader()->policyChecker()->*function)(PolicyIgnore);
643        return;
644    }
645
646    RefPtr<APIObject> userData;
647
648    RefPtr<InjectedBundleNavigationAction> action = InjectedBundleNavigationAction::create(m_frame, navigationAction, formState);
649
650    // Notify the bundle client.
651    WKBundlePagePolicyAction policy = webPage->injectedBundlePolicyClient().decidePolicyForNavigationAction(webPage, m_frame, action.get(), request, userData);
652    if (policy == WKBundlePagePolicyActionUse) {
653        (m_frame->coreFrame()->loader()->policyChecker()->*function)(PolicyUse);
654        return;
655    }
656
657    uint64_t listenerID = m_frame->setUpPolicyListener(function);
658    bool receivedPolicyAction;
659    uint64_t policyAction;
660    uint64_t downloadID;
661
662    // Notify the UIProcess.
663    if (!webPage->sendSync(Messages::WebPageProxy::DecidePolicyForNavigationAction(m_frame->frameID(), action->navigationType(), action->modifiers(), action->mouseButton(), request, listenerID, InjectedBundleUserMessageEncoder(userData.get())), Messages::WebPageProxy::DecidePolicyForNavigationAction::Reply(receivedPolicyAction, policyAction, downloadID)))
664        return;
665
666    // We call this synchronously because WebCore cannot gracefully handle a frame load without a synchronous navigation policy reply.
667    if (receivedPolicyAction)
668        m_frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), downloadID);
669}
670
671void WebFrameLoaderClient::cancelPolicyCheck()
672{
673    m_frame->invalidatePolicyListener();
674}
675
676void WebFrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError& error)
677{
678    WebPage* webPage = m_frame->page();
679    if (!webPage)
680        return;
681
682    RefPtr<APIObject> userData;
683
684    // Notify the bundle client.
685    webPage->injectedBundlePolicyClient().unableToImplementPolicy(webPage, m_frame, error, userData);
686
687    // Notify the UIProcess.
688    webPage->send(Messages::WebPageProxy::UnableToImplementPolicy(m_frame->frameID(), error, InjectedBundleUserMessageEncoder(userData.get())));
689}
690
691void WebFrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction function, PassRefPtr<FormState> prpFormState)
692{
693    WebPage* webPage = m_frame->page();
694    if (!webPage)
695        return;
696
697    // FIXME: Pass more of the form state.
698    RefPtr<FormState> formState = prpFormState;
699
700    HTMLFormElement* form = formState->form();
701    WebFrame* sourceFrame = static_cast<WebFrameLoaderClient*>(formState->sourceFrame()->loader()->client())->webFrame();
702    const Vector<std::pair<String, String> >& values = formState->textFieldValues();
703
704    RefPtr<APIObject> userData;
705    webPage->injectedBundleFormClient().willSubmitForm(webPage, form, m_frame, sourceFrame, values, userData);
706
707
708    uint64_t listenerID = m_frame->setUpPolicyListener(function);
709    StringPairVector valuesVector(values);
710
711    webPage->send(Messages::WebPageProxy::WillSubmitForm(m_frame->frameID(), sourceFrame->frameID(), valuesVector, listenerID, InjectedBundleUserMessageEncoder(userData.get())));
712}
713
714void WebFrameLoaderClient::dispatchDidLoadMainResource(DocumentLoader*)
715{
716    notImplemented();
717}
718
719void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader*)
720{
721    notImplemented();
722}
723
724void WebFrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError& error)
725{
726    if (!m_pluginView)
727        return;
728
729    m_pluginView->manualLoadDidFail(error);
730    m_pluginView = 0;
731    m_hasSentResponseToPluginView = false;
732}
733
734void WebFrameLoaderClient::willChangeEstimatedProgress()
735{
736    notImplemented();
737}
738
739void WebFrameLoaderClient::didChangeEstimatedProgress()
740{
741    notImplemented();
742}
743
744void WebFrameLoaderClient::postProgressStartedNotification()
745{
746    if (WebPage* webPage = m_frame->page())
747        webPage->send(Messages::WebPageProxy::DidStartProgress());
748}
749
750void WebFrameLoaderClient::postProgressEstimateChangedNotification()
751{
752    if (WebPage* webPage = m_frame->page()) {
753        double progress = webPage->corePage()->progress()->estimatedProgress();
754        webPage->send(Messages::WebPageProxy::DidChangeProgress(progress));
755
756    }
757}
758
759void WebFrameLoaderClient::postProgressFinishedNotification()
760{
761    if (WebPage* webPage = m_frame->page())
762        webPage->send(Messages::WebPageProxy::DidFinishProgress());
763}
764
765void WebFrameLoaderClient::setMainFrameDocumentReady(bool)
766{
767    notImplemented();
768}
769
770void WebFrameLoaderClient::startDownload(const ResourceRequest& request)
771{
772    m_frame->startDownload(request);
773}
774
775void WebFrameLoaderClient::willChangeTitle(DocumentLoader*)
776{
777    notImplemented();
778}
779
780void WebFrameLoaderClient::didChangeTitle(DocumentLoader*)
781{
782    notImplemented();
783}
784
785void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
786{
787    // If we're loading a custom representation, we don't want to hand off the data to WebCore.
788    if (m_frameHasCustomRepresentation)
789        return;
790
791    if (!m_pluginView)
792        loader->commitData(data, length);
793
794    // If the document is a stand-alone media document, now is the right time to cancel the WebKit load.
795    // FIXME: This code should be shared across all ports. <http://webkit.org/b/48762>.
796    if (m_frame->coreFrame()->document()->isMediaDocument())
797        loader->cancelMainResourceLoad(pluginWillHandleLoadError(loader->response()));
798
799    // Calling commitData did not create the plug-in view.
800    if (!m_pluginView)
801        return;
802
803    if (!m_hasSentResponseToPluginView) {
804        m_pluginView->manualLoadDidReceiveResponse(loader->response());
805        // manualLoadDidReceiveResponse sets up a new stream to the plug-in. on a full-page plug-in, a failure in
806        // setting up this stream can cause the main document load to be cancelled, setting m_pluginView
807        // to null
808        if (!m_pluginView)
809            return;
810        m_hasSentResponseToPluginView = true;
811    }
812    m_pluginView->manualLoadDidReceiveData(data, length);
813}
814
815void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
816{
817    if (!m_pluginView) {
818        committedLoad(loader, 0, 0);
819
820        if (m_frameHasCustomRepresentation) {
821            WebPage* webPage = m_frame->page();
822            if (!webPage)
823                return;
824
825            RefPtr<SharedBuffer> mainResourceData = loader->mainResourceData();
826            CoreIPC::DataReference dataReference(reinterpret_cast<const uint8_t*>(mainResourceData ? mainResourceData->data() : 0), mainResourceData ? mainResourceData->size() : 0);
827
828            webPage->send(Messages::WebPageProxy::DidFinishLoadingDataForCustomRepresentation(loader->response().suggestedFilename(), dataReference));
829        }
830
831        return;
832    }
833
834    m_pluginView->manualLoadDidFinishLoading();
835    m_pluginView = 0;
836    m_hasSentResponseToPluginView = false;
837}
838
839void WebFrameLoaderClient::updateGlobalHistory()
840{
841    WebPage* webPage = m_frame->page();
842    if (!webPage || !webPage->pageGroup()->isVisibleToHistoryClient())
843        return;
844
845    DocumentLoader* loader = m_frame->coreFrame()->loader()->documentLoader();
846
847    WebNavigationDataStore data;
848    data.url = loader->urlForHistory().string();
849    // FIXME: use direction of title.
850    data.title = loader->title().string();
851
852    WebProcess::shared().connection()->send(Messages::WebContext::DidNavigateWithNavigationData(webPage->pageID(), data, m_frame->frameID()), 0);
853}
854
855void WebFrameLoaderClient::updateGlobalHistoryRedirectLinks()
856{
857    WebPage* webPage = m_frame->page();
858    if (!webPage || !webPage->pageGroup()->isVisibleToHistoryClient())
859        return;
860
861    DocumentLoader* loader = m_frame->coreFrame()->loader()->documentLoader();
862    ASSERT(loader->unreachableURL().isEmpty());
863
864    // Client redirect
865    if (!loader->clientRedirectSourceForHistory().isNull()) {
866        WebProcess::shared().connection()->send(Messages::WebContext::DidPerformClientRedirect(webPage->pageID(),
867            loader->clientRedirectSourceForHistory(), loader->clientRedirectDestinationForHistory(), m_frame->frameID()), 0);
868    }
869
870    // Server redirect
871    if (!loader->serverRedirectSourceForHistory().isNull()) {
872        WebProcess::shared().connection()->send(Messages::WebContext::DidPerformServerRedirect(webPage->pageID(),
873            loader->serverRedirectSourceForHistory(), loader->serverRedirectDestinationForHistory(), m_frame->frameID()), 0);
874    }
875}
876
877bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
878{
879    WebPage* webPage = m_frame->page();
880    if (!webPage)
881        return false;
882
883    uint64_t itemID = WebBackForwardListProxy::idForItem(item);
884    if (!itemID) {
885        // We should never be considering navigating to an item that is not actually in the back/forward list.
886        ASSERT_NOT_REACHED();
887        return false;
888    }
889
890    bool shouldGoToBackForwardListItem;
891    if (!webPage->sendSync(Messages::WebPageProxy::ShouldGoToBackForwardListItem(itemID), Messages::WebPageProxy::ShouldGoToBackForwardListItem::Reply(shouldGoToBackForwardListItem)))
892        return false;
893
894    return shouldGoToBackForwardListItem;
895}
896
897bool WebFrameLoaderClient::shouldStopLoadingForHistoryItem(HistoryItem* item) const
898{
899    return true;
900}
901
902void WebFrameLoaderClient::dispatchDidAddBackForwardItem(HistoryItem*) const
903{
904    notImplemented();
905}
906
907void WebFrameLoaderClient::dispatchDidRemoveBackForwardItem(HistoryItem*) const
908{
909    notImplemented();
910}
911
912void WebFrameLoaderClient::dispatchDidChangeBackForwardIndex() const
913{
914    notImplemented();
915}
916
917void WebFrameLoaderClient::didDisplayInsecureContent()
918{
919    WebPage* webPage = m_frame->page();
920    if (!webPage)
921        return;
922
923    RefPtr<APIObject> userData;
924
925    webPage->injectedBundleLoaderClient().didDisplayInsecureContentForFrame(webPage, m_frame, userData);
926
927    webPage->send(Messages::WebPageProxy::DidDisplayInsecureContentForFrame(m_frame->frameID(), InjectedBundleUserMessageEncoder(userData.get())));
928}
929
930void WebFrameLoaderClient::didRunInsecureContent(SecurityOrigin*, const KURL&)
931{
932    WebPage* webPage = m_frame->page();
933    if (!webPage)
934        return;
935
936    RefPtr<APIObject> userData;
937
938    webPage->injectedBundleLoaderClient().didRunInsecureContentForFrame(webPage, m_frame, userData);
939
940    webPage->send(Messages::WebPageProxy::DidRunInsecureContentForFrame(m_frame->frameID(), InjectedBundleUserMessageEncoder(userData.get())));
941}
942
943ResourceError WebFrameLoaderClient::cancelledError(const ResourceRequest& request)
944{
945    return WebKit::cancelledError(request);
946}
947
948ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request)
949{
950    return WebKit::blockedError(request);
951}
952
953ResourceError WebFrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
954{
955    return WebKit::cannotShowURLError(request);
956}
957
958ResourceError WebFrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest& request)
959{
960    return WebKit::interruptForPolicyChangeError(request);
961}
962
963ResourceError WebFrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
964{
965    return WebKit::cannotShowMIMETypeError(response);
966}
967
968ResourceError WebFrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
969{
970    return WebKit::fileDoesNotExistError(response);
971}
972
973ResourceError WebFrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response)
974{
975    return WebKit::pluginWillHandleLoadError(response);
976}
977
978bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error)
979{
980    DEFINE_STATIC_LOCAL(const ResourceError, cancelledError, (this->cancelledError(ResourceRequest())));
981    DEFINE_STATIC_LOCAL(const ResourceError, pluginWillHandleLoadError, (this->pluginWillHandleLoadError(ResourceResponse())));
982
983    if (error.errorCode() == cancelledError.errorCode() && error.domain() == cancelledError.domain())
984        return false;
985
986    if (error.errorCode() == pluginWillHandleLoadError.errorCode() && error.domain() == pluginWillHandleLoadError.domain())
987        return false;
988
989    return true;
990}
991
992bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest&) const
993{
994    notImplemented();
995    return true;
996}
997
998bool WebFrameLoaderClient::canShowMIMEType(const String& MIMEType) const
999{
1000    notImplemented();
1001    return true;
1002}
1003
1004bool WebFrameLoaderClient::canShowMIMETypeAsHTML(const String& MIMEType) const
1005{
1006    return true;
1007}
1008
1009bool WebFrameLoaderClient::representationExistsForURLScheme(const String& URLScheme) const
1010{
1011    notImplemented();
1012    return false;
1013}
1014
1015String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& URLScheme) const
1016{
1017    notImplemented();
1018    return String();
1019}
1020
1021void WebFrameLoaderClient::frameLoadCompleted()
1022{
1023    notImplemented();
1024}
1025
1026void WebFrameLoaderClient::saveViewStateToItem(HistoryItem*)
1027{
1028    notImplemented();
1029}
1030
1031void WebFrameLoaderClient::restoreViewState()
1032{
1033    // Inform the UI process of the scale factor.
1034    double scaleFactor = m_frame->coreFrame()->loader()->history()->currentItem()->pageScaleFactor();
1035    m_frame->page()->send(Messages::WebPageProxy::ViewScaleFactorDidChange(scaleFactor));
1036
1037    // FIXME: This should not be necessary. WebCore should be correctly invalidating
1038    // the view on restores from the back/forward cache.
1039    if (m_frame == m_frame->page()->mainFrame())
1040        m_frame->page()->drawingArea()->setNeedsDisplay(m_frame->page()->bounds());
1041}
1042
1043void WebFrameLoaderClient::provisionalLoadStarted()
1044{
1045    notImplemented();
1046}
1047
1048void WebFrameLoaderClient::didFinishLoad()
1049{
1050    // If we have a load listener, notify it.
1051    if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
1052        loadListener->didFinishLoad(m_frame);
1053}
1054
1055void WebFrameLoaderClient::prepareForDataSourceReplacement()
1056{
1057    notImplemented();
1058}
1059
1060PassRefPtr<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& data)
1061{
1062    return DocumentLoader::create(request, data);
1063}
1064
1065void WebFrameLoaderClient::setTitle(const StringWithDirection& title, const KURL& url)
1066{
1067    WebPage* webPage = m_frame->page();
1068    if (!webPage || !webPage->pageGroup()->isVisibleToHistoryClient())
1069        return;
1070
1071    // FIXME: use direction of title.
1072    WebProcess::shared().connection()->send(Messages::WebContext::DidUpdateHistoryTitle(webPage->pageID(),
1073        title.string(), url.string(), m_frame->frameID()), 0);
1074}
1075
1076String WebFrameLoaderClient::userAgent(const KURL&)
1077{
1078    WebPage* webPage = m_frame->page();
1079    if (!webPage)
1080        return String();
1081
1082    return webPage->userAgent();
1083}
1084
1085void WebFrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame*)
1086{
1087}
1088
1089void WebFrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame*)
1090{
1091    WebPage* webPage = m_frame->page();
1092    bool isMainFrame = webPage->mainFrame() == m_frame;
1093
1094    const String& mimeType = m_frame->coreFrame()->loader()->documentLoader()->response().mimeType();
1095    m_frameHasCustomRepresentation = isMainFrame && WebProcess::shared().shouldUseCustomRepresentationForMIMEType(mimeType);
1096}
1097
1098void WebFrameLoaderClient::transitionToCommittedForNewPage()
1099{
1100    WebPage* webPage = m_frame->page();
1101    Color backgroundColor = webPage->drawsTransparentBackground() ? Color::transparent : Color::white;
1102
1103    bool isMainFrame = webPage->mainFrame() == m_frame;
1104
1105#if ENABLE(TILED_BACKING_STORE)
1106    IntSize currentVisibleContentSize = m_frame->coreFrame()->view() ? m_frame->coreFrame()->view()->actualVisibleContentRect().size() : IntSize();
1107    m_frame->coreFrame()->createView(webPage->size(), backgroundColor, false, webPage->resizesToContentsLayoutSize(), isMainFrame && webPage->resizesToContentsEnabled());
1108
1109    if (isMainFrame && webPage->resizesToContentsEnabled()) {
1110        m_frame->coreFrame()->view()->setDelegatesScrolling(true);
1111        m_frame->coreFrame()->view()->setPaintsEntireContents(true);
1112    }
1113
1114    // The HistoryController will update the scroll position later if needed.
1115    m_frame->coreFrame()->view()->setActualVisibleContentRect(IntRect(IntPoint::zero(), currentVisibleContentSize));
1116#else
1117    const String& mimeType = m_frame->coreFrame()->loader()->documentLoader()->response().mimeType();
1118    m_frameHasCustomRepresentation = isMainFrame && WebProcess::shared().shouldUseCustomRepresentationForMIMEType(mimeType);
1119
1120    m_frame->coreFrame()->createView(webPage->size(), backgroundColor, false, IntSize(), false);
1121#endif
1122
1123    m_frame->coreFrame()->view()->setTransparent(!webPage->drawsBackground());
1124}
1125
1126void WebFrameLoaderClient::didSaveToPageCache()
1127{
1128    WebPage* webPage = m_frame->page();
1129    if (!webPage)
1130        return;
1131
1132    if (m_frame->isMainFrame())
1133        return;
1134
1135    webPage->send(Messages::WebPageProxy::DidSaveFrameToPageCache(m_frame->frameID()));
1136}
1137
1138void WebFrameLoaderClient::didRestoreFromPageCache()
1139{
1140    WebPage* webPage = m_frame->page();
1141    if (!webPage)
1142        return;
1143
1144    if (m_frame->isMainFrame())
1145        return;
1146
1147    WebFrame* parentFrame = static_cast<WebFrameLoaderClient*>(m_frame->coreFrame()->tree()->parent()->loader()->client())->webFrame();
1148    webPage->send(Messages::WebPageProxy::DidRestoreFrameFromPageCache(m_frame->frameID(), parentFrame->frameID()));
1149}
1150
1151void WebFrameLoaderClient::dispatchDidBecomeFrameset(bool value)
1152{
1153    WebPage* webPage = m_frame->page();
1154    if (!webPage)
1155        return;
1156
1157    webPage->send(Messages::WebPageProxy::FrameDidBecomeFrameSet(m_frame->frameID(), value));
1158}
1159
1160bool WebFrameLoaderClient::canCachePage() const
1161{
1162    // We cannot cache frames that have custom representations because they are
1163    // rendered in the UIProcess.
1164    return !m_frameHasCustomRepresentation;
1165}
1166
1167void WebFrameLoaderClient::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest& initialRequest, const ResourceResponse& response)
1168{
1169    m_frame->convertHandleToDownload(handle, request, initialRequest, response);
1170}
1171
1172PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
1173                                                    const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
1174{
1175    WebPage* webPage = m_frame->page();
1176
1177    RefPtr<WebFrame> subframe = WebFrame::createSubframe(webPage, name, ownerElement);
1178
1179    Frame* coreSubframe = subframe->coreFrame();
1180
1181     // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
1182    m_frame->coreFrame()->loader()->loadURLIntoChildFrame(url, referrer, coreSubframe);
1183
1184    // The frame's onload handler may have removed it from the document.
1185    if (!coreSubframe->tree()->parent())
1186        return 0;
1187
1188    return coreSubframe;
1189}
1190
1191void WebFrameLoaderClient::didTransferChildFrameToNewDocument(Page*)
1192{
1193    notImplemented();
1194}
1195
1196void WebFrameLoaderClient::transferLoadingResourceFromPage(unsigned long, DocumentLoader*, const ResourceRequest&, Page*)
1197{
1198    notImplemented();
1199}
1200
1201PassRefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize&, HTMLPlugInElement* pluginElement, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
1202{
1203    ASSERT(paramNames.size() == paramValues.size());
1204
1205    WebPage* webPage = m_frame->page();
1206    ASSERT(webPage);
1207
1208    Plugin::Parameters parameters;
1209    parameters.url = url;
1210    parameters.names = paramNames;
1211    parameters.values = paramValues;
1212    parameters.mimeType = mimeType;
1213    parameters.loadManually = loadManually;
1214
1215    // <rdar://problem/8440903>: AppleConnect has a bug where it does not
1216    // understand the parameter names specified in the <object> element that
1217    // embeds its plug-in. This hack works around the issue by converting the
1218    // parameter names to lowercase before passing them to the plug-in.
1219    // FIXME: This workaround should be dependent on site-specific quirks being
1220    // enabled. This requires adding this setting to WebKit2's WebPreferences
1221    // implementation. See <https://bugs.webkit.org/show_bug.cgi?id=46076>.
1222    if (equalIgnoringCase(mimeType, "application/x-snkp")) {
1223        for (size_t i = 0; i < paramNames.size(); ++i)
1224            parameters.names[i] = paramNames[i].lower();
1225    }
1226
1227#if PLUGIN_ARCHITECTURE(X11)
1228    if (equalIgnoringCase(mimeType, "application/x-shockwave-flash")) {
1229        // Currently we don't support transparency and windowed mode.
1230        // Inject wmode=opaque to make Flash work in these conditions.
1231        size_t wmodeIndex = parameters.names.find("wmode");
1232        if (wmodeIndex == -1) {
1233            parameters.names.append("wmode");
1234            parameters.values.append("opaque");
1235        } else if (equalIgnoringCase(parameters.values[wmodeIndex], "window"))
1236            parameters.values[wmodeIndex] = "opaque";
1237    }
1238#endif
1239
1240    RefPtr<Plugin> plugin = webPage->createPlugin(parameters);
1241    if (!plugin)
1242        return 0;
1243
1244    return PluginView::create(pluginElement, plugin.release(), parameters);
1245}
1246
1247void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
1248{
1249    ASSERT(!m_pluginView);
1250    ASSERT(pluginWidget);
1251
1252    m_pluginView = static_cast<PluginView*>(pluginWidget);
1253}
1254
1255PassRefPtr<Widget> WebFrameLoaderClient::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement* appletElement, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues)
1256{
1257    return createPlugin(pluginSize, appletElement, KURL(), paramNames, paramValues, "application/x-java-applet", false);
1258}
1259
1260static bool pluginSupportsExtension(PluginData* pluginData, const String& extension)
1261{
1262    ASSERT(extension.lower() == extension);
1263
1264    for (size_t i = 0; i < pluginData->mimes().size(); ++i) {
1265        const MimeClassInfo& mimeClassInfo = pluginData->mimes()[i];
1266
1267        if (mimeClassInfo.extensions.contains(extension))
1268            return true;
1269    }
1270    return false;
1271}
1272
1273ObjectContentType WebFrameLoaderClient::objectContentType(const KURL& url, const String& mimeTypeIn, bool shouldPreferPlugInsForImages)
1274{
1275    // FIXME: This should be merged with WebCore::FrameLoader::defaultObjectContentType when the plugin code
1276    // is consolidated.
1277
1278    String mimeType = mimeTypeIn;
1279    if (mimeType.isEmpty()) {
1280        String extension = url.path().substring(url.path().reverseFind('.') + 1).lower();
1281
1282        // Try to guess the MIME type from the extension.
1283        mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
1284
1285        if (mimeType.isEmpty()) {
1286            // Check if there's a plug-in around that can handle the extension.
1287            if (WebPage* webPage = m_frame->page()) {
1288                if (PluginData* pluginData = webPage->corePage()->pluginData()) {
1289                    if (pluginSupportsExtension(pluginData, extension))
1290                        return ObjectContentNetscapePlugin;
1291                }
1292            }
1293        }
1294    }
1295
1296    if (mimeType.isEmpty())
1297        return ObjectContentFrame;
1298
1299    bool plugInSupportsMIMEType = false;
1300    if (WebPage* webPage = m_frame->page()) {
1301        if (PluginData* pluginData = webPage->corePage()->pluginData()) {
1302            if (pluginData->supportsMimeType(mimeType))
1303                plugInSupportsMIMEType = true;
1304        }
1305    }
1306
1307    if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
1308        return shouldPreferPlugInsForImages && plugInSupportsMIMEType ? ObjectContentNetscapePlugin : ObjectContentImage;
1309
1310    if (plugInSupportsMIMEType)
1311        return ObjectContentNetscapePlugin;
1312
1313    if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
1314        return ObjectContentFrame;
1315
1316    return ObjectContentNone;
1317}
1318
1319String WebFrameLoaderClient::overrideMediaType() const
1320{
1321    notImplemented();
1322    return String();
1323}
1324
1325void WebFrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world)
1326{
1327    WebPage* webPage = m_frame->page();
1328    if (!webPage)
1329        return;
1330
1331    webPage->injectedBundleLoaderClient().didClearWindowObjectForFrame(webPage, m_frame, world);
1332}
1333
1334void WebFrameLoaderClient::documentElementAvailable()
1335{
1336    notImplemented();
1337}
1338
1339void WebFrameLoaderClient::didPerformFirstNavigation() const
1340{
1341    notImplemented();
1342}
1343
1344void WebFrameLoaderClient::registerForIconNotification(bool listen)
1345{
1346    notImplemented();
1347}
1348
1349#if PLATFORM(MAC)
1350
1351RemoteAXObjectRef WebFrameLoaderClient::accessibilityRemoteObject()
1352{
1353    return m_frame->page()->accessibilityRemoteObject();
1354}
1355
1356#if ENABLE(MAC_JAVA_BRIDGE)
1357jobject WebFrameLoaderClient::javaApplet(NSView*) { return 0; }
1358#endif
1359NSCachedURLResponse* WebFrameLoaderClient::willCacheResponse(DocumentLoader*, unsigned long identifier, NSCachedURLResponse* response) const
1360{
1361    return response;
1362}
1363
1364#endif
1365#if USE(CFNETWORK)
1366bool WebFrameLoaderClient::shouldCacheResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&, const unsigned char* data, unsigned long long length)
1367{
1368    return true;
1369}
1370
1371#endif
1372
1373bool WebFrameLoaderClient::shouldUsePluginDocument(const String& /*mimeType*/) const
1374{
1375    notImplemented();
1376    return false;
1377}
1378
1379void WebFrameLoaderClient::didChangeScrollOffset()
1380{
1381    WebPage* webPage = m_frame->page();
1382    if (!webPage)
1383        return;
1384
1385    if (!m_frame->isMainFrame())
1386        return;
1387
1388    // If this is called when tearing down a FrameView, the WebCore::Frame's
1389    // current FrameView will be null.
1390    if (!m_frame->coreFrame()->view())
1391        return;
1392
1393    webPage->didChangeScrollOffsetForMainFrame();
1394}
1395
1396PassRefPtr<FrameNetworkingContext> WebFrameLoaderClient::createNetworkingContext()
1397{
1398    return WebFrameNetworkingContext::create(m_frame->coreFrame());
1399}
1400
1401} // namespace WebKit
1402