1/*
2 * Copyright (C) 2006, 2007, 2008, 2009 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 *
8 * 1.  Redistributions of source code must retain the above copyright
9 *     notice, this list of conditions and the following disclaimer.
10 * 2.  Redistributions in binary form must reproduce the above copyright
11 *     notice, this list of conditions and the following disclaimer in the
12 *     documentation and/or other materials provided with the distribution.
13 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 *     its contributors may be used to endorse or promote products derived
15 *     from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "config.h"
30#include "WebFrameLoaderClient.h"
31
32#include "CFDictionaryPropertyBag.h"
33#include "COMPropertyBag.h"
34#include "DOMHTMLClasses.h"
35#include "EmbeddedWidget.h"
36#include "MarshallingHelpers.h"
37#include "NotImplemented.h"
38#include "WebCachedFramePlatformData.h"
39#include "WebChromeClient.h"
40#include "WebDocumentLoader.h"
41#include "WebError.h"
42#include "WebFrame.h"
43#include "WebHistory.h"
44#include "WebHistoryItem.h"
45#include "WebMutableURLRequest.h"
46#include "WebNavigationData.h"
47#include "WebNotificationCenter.h"
48#include "WebSecurityOrigin.h"
49#include "WebURLAuthenticationChallenge.h"
50#include "WebURLResponse.h"
51#include "WebView.h"
52#pragma warning(push, 0)
53#include <WebCore/CachedFrame.h>
54#include <WebCore/DocumentLoader.h>
55#include <WebCore/FrameLoader.h>
56#include <WebCore/FrameTree.h>
57#include <WebCore/FrameView.h>
58#include <WebCore/HTMLAppletElement.h>
59#include <WebCore/HTMLFrameElement.h>
60#include <WebCore/HTMLFrameOwnerElement.h>
61#include <WebCore/HTMLNames.h>
62#include <WebCore/HTMLPlugInElement.h>
63#include <WebCore/HistoryItem.h>
64#include <WebCore/Page.h>
65#include <WebCore/PluginPackage.h>
66#include <WebCore/PluginView.h>
67#include <WebCore/RenderPart.h>
68#include <WebCore/ResourceHandle.h>
69#include <WebCore/ScriptString.h>
70#pragma warning(pop)
71
72using namespace WebCore;
73using namespace HTMLNames;
74
75static WebDataSource* getWebDataSource(DocumentLoader* loader)
76{
77    return loader ? static_cast<WebDocumentLoader*>(loader)->dataSource() : 0;
78}
79
80WebFrameLoaderClient::WebFrameLoaderClient(WebFrame* webFrame)
81    : m_webFrame(webFrame)
82    , m_manualLoader(0)
83    , m_hasSentResponseToPlugin(false)
84{
85    ASSERT_ARG(webFrame, webFrame);
86}
87
88WebFrameLoaderClient::~WebFrameLoaderClient()
89{
90}
91
92bool WebFrameLoaderClient::hasWebView() const
93{
94    return m_webFrame->webView();
95}
96
97void WebFrameLoaderClient::forceLayout()
98{
99    Frame* frame = core(m_webFrame);
100    if (!frame)
101        return;
102
103    if (frame->document() && frame->document()->inPageCache())
104        return;
105
106    FrameView* view = frame->view();
107    if (!view)
108        return;
109
110    view->setNeedsLayout();
111    view->forceLayout(true);
112}
113
114void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
115{
116    WebView* webView = m_webFrame->webView();
117    COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
118    if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
119        return;
120
121    COMPtr<WebMutableURLRequest> webURLRequest(AdoptCOM, WebMutableURLRequest::createInstance(request));
122    resourceLoadDelegate->identifierForInitialRequest(webView, webURLRequest.get(), getWebDataSource(loader), identifier);
123}
124
125bool WebFrameLoaderClient::shouldUseCredentialStorage(DocumentLoader* loader, unsigned long identifier)
126{
127    WebView* webView = m_webFrame->webView();
128    COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
129    if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
130        return true;
131
132    COMPtr<IWebResourceLoadDelegatePrivate> resourceLoadDelegatePrivate;
133    if (FAILED(resourceLoadDelegate->QueryInterface(IID_IWebResourceLoadDelegatePrivate, reinterpret_cast<void**>(&resourceLoadDelegatePrivate))))
134        return true;
135
136    BOOL shouldUse;
137    if (SUCCEEDED(resourceLoadDelegatePrivate->shouldUseCredentialStorage(webView, identifier, getWebDataSource(loader), &shouldUse)))
138        return shouldUse;
139
140    return true;
141}
142
143void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge)
144{
145#if USE(CFNETWORK)
146    ASSERT(challenge.authenticationClient());
147
148    WebView* webView = m_webFrame->webView();
149    COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
150    if (SUCCEEDED(webView->resourceLoadDelegate(&resourceLoadDelegate))) {
151        COMPtr<WebURLAuthenticationChallenge> webChallenge(AdoptCOM, WebURLAuthenticationChallenge::createInstance(challenge));
152        if (SUCCEEDED(resourceLoadDelegate->didReceiveAuthenticationChallenge(webView, identifier, webChallenge.get(), getWebDataSource(loader))))
153            return;
154    }
155
156    // If the ResourceLoadDelegate doesn't exist or fails to handle the call, we tell the ResourceHandle
157    // to continue without credential - this is the best approximation of Mac behavior
158    challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge);
159#else
160   notImplemented();
161#endif
162}
163
164void WebFrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge)
165{
166    WebView* webView = m_webFrame->webView();
167    COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
168    if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
169        return;
170
171    COMPtr<WebURLAuthenticationChallenge> webChallenge(AdoptCOM, WebURLAuthenticationChallenge::createInstance(challenge));
172    resourceLoadDelegate->didCancelAuthenticationChallenge(webView, identifier, webChallenge.get(), getWebDataSource(loader));
173}
174
175void WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
176{
177    WebView* webView = m_webFrame->webView();
178    COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
179    if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
180        return;
181
182    COMPtr<WebMutableURLRequest> webURLRequest(AdoptCOM, WebMutableURLRequest::createInstance(request));
183    COMPtr<WebURLResponse> webURLRedirectResponse(AdoptCOM, WebURLResponse::createInstance(redirectResponse));
184
185    COMPtr<IWebURLRequest> newWebURLRequest;
186    if (FAILED(resourceLoadDelegate->willSendRequest(webView, identifier, webURLRequest.get(), webURLRedirectResponse.get(), getWebDataSource(loader), &newWebURLRequest)))
187        return;
188
189    if (webURLRequest == newWebURLRequest)
190        return;
191
192    if (!newWebURLRequest) {
193        request = ResourceRequest();
194        return;
195    }
196
197    COMPtr<WebMutableURLRequest> newWebURLRequestImpl(Query, newWebURLRequest);
198    if (!newWebURLRequestImpl)
199        return;
200
201    request = newWebURLRequestImpl->resourceRequest();
202}
203
204void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response)
205{
206    WebView* webView = m_webFrame->webView();
207    COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
208    if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
209        return;
210
211    COMPtr<WebURLResponse> webURLResponse(AdoptCOM, WebURLResponse::createInstance(response));
212    resourceLoadDelegate->didReceiveResponse(webView, identifier, webURLResponse.get(), getWebDataSource(loader));
213}
214
215void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int length)
216{
217    WebView* webView = m_webFrame->webView();
218    COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
219    if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
220        return;
221
222    resourceLoadDelegate->didReceiveContentLength(webView, identifier, length, getWebDataSource(loader));
223}
224
225void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier)
226{
227    WebView* webView = m_webFrame->webView();
228    COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
229    if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
230        return;
231
232    resourceLoadDelegate->didFinishLoadingFromDataSource(webView, identifier, getWebDataSource(loader));
233}
234
235void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
236{
237    WebView* webView = m_webFrame->webView();
238    COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
239    if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
240        return;
241
242    COMPtr<WebError> webError(AdoptCOM, WebError::createInstance(error));
243    resourceLoadDelegate->didFailLoadingWithError(webView, identifier, webError.get(), getWebDataSource(loader));
244}
245
246void WebFrameLoaderClient::dispatchDidLoadResourceByXMLHttpRequest(unsigned long, const ScriptString&)
247{
248}
249
250bool WebFrameLoaderClient::shouldCacheResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response, const unsigned char* data, const unsigned long long length)
251{
252    WebView* webView = m_webFrame->webView();
253    COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
254    if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
255        return true;
256
257    COMPtr<IWebResourceLoadDelegatePrivate> resourceLoadDelegatePrivate(Query, resourceLoadDelegate);
258    if (!resourceLoadDelegatePrivate)
259        return true;
260
261    COMPtr<IWebURLResponse> urlResponse(AdoptCOM, WebURLResponse::createInstance(response));
262    BOOL shouldCache;
263    if (SUCCEEDED(resourceLoadDelegatePrivate->shouldCacheResponse(webView, identifier, urlResponse.get(), data, length, getWebDataSource(loader), &shouldCache)))
264        return shouldCache;
265
266    return true;
267}
268
269void WebFrameLoaderClient::dispatchDidHandleOnloadEvents()
270{
271    WebView* webView = m_webFrame->webView();
272    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
273    if (SUCCEEDED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv)
274        frameLoadDelegatePriv->didHandleOnloadEventsForFrame(webView, m_webFrame);
275}
276
277void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
278{
279    WebView* webView = m_webFrame->webView();
280    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
281    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
282        frameLoadDelegate->didReceiveServerRedirectForProvisionalLoadForFrame(webView, m_webFrame);
283}
284
285void WebFrameLoaderClient::dispatchDidCancelClientRedirect()
286{
287    WebView* webView = m_webFrame->webView();
288    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
289    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
290        frameLoadDelegate->didCancelClientRedirectForFrame(webView, m_webFrame);
291}
292
293void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const KURL& url, double delay, double fireDate)
294{
295    WebView* webView = m_webFrame->webView();
296    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
297    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
298        frameLoadDelegate->willPerformClientRedirectToURL(webView, BString(url.string()), delay, MarshallingHelpers::CFAbsoluteTimeToDATE(fireDate), m_webFrame);
299}
300
301void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage()
302{
303    WebView* webView = m_webFrame->webView();
304    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
305    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
306        frameLoadDelegate->didChangeLocationWithinPageForFrame(webView, m_webFrame);
307}
308
309void WebFrameLoaderClient::dispatchDidPushStateWithinPage()
310{
311    WebView* webView = m_webFrame->webView();
312    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
313    if (FAILED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) || !frameLoadDelegatePriv)
314        return;
315
316    COMPtr<IWebFrameLoadDelegatePrivate2> frameLoadDelegatePriv2(Query, frameLoadDelegatePriv);
317    if (!frameLoadDelegatePriv2)
318        return;
319
320    frameLoadDelegatePriv2->didPushStateWithinPageForFrame(webView, m_webFrame);
321}
322
323void WebFrameLoaderClient::dispatchDidReplaceStateWithinPage()
324{
325    WebView* webView = m_webFrame->webView();
326    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
327    if (FAILED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) || !frameLoadDelegatePriv)
328        return;
329
330    COMPtr<IWebFrameLoadDelegatePrivate2> frameLoadDelegatePriv2(Query, frameLoadDelegatePriv);
331    if (!frameLoadDelegatePriv2)
332        return;
333
334    frameLoadDelegatePriv2->didReplaceStateWithinPageForFrame(webView, m_webFrame);
335}
336
337void WebFrameLoaderClient::dispatchDidPopStateWithinPage()
338{
339    WebView* webView = m_webFrame->webView();
340    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
341    if (FAILED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) || !frameLoadDelegatePriv)
342        return;
343
344    COMPtr<IWebFrameLoadDelegatePrivate2> frameLoadDelegatePriv2(Query, frameLoadDelegatePriv);
345    if (!frameLoadDelegatePriv2)
346        return;
347
348    frameLoadDelegatePriv2->didPopStateWithinPageForFrame(webView, m_webFrame);
349}
350void WebFrameLoaderClient::dispatchWillClose()
351{
352    WebView* webView = m_webFrame->webView();
353    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
354    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
355        frameLoadDelegate->willCloseFrame(webView, m_webFrame);
356}
357
358void WebFrameLoaderClient::dispatchDidReceiveIcon()
359{
360    m_webFrame->webView()->dispatchDidReceiveIconFromWebFrame(m_webFrame);
361}
362
363void WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
364{
365    WebView* webView = m_webFrame->webView();
366    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
367    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
368        frameLoadDelegate->didStartProvisionalLoadForFrame(webView, m_webFrame);
369}
370
371void WebFrameLoaderClient::dispatchDidReceiveTitle(const String& title)
372{
373    WebView* webView = m_webFrame->webView();
374    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
375    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
376        frameLoadDelegate->didReceiveTitle(webView, BString(title), m_webFrame);
377}
378
379void WebFrameLoaderClient::dispatchDidCommitLoad()
380{
381    WebView* webView = m_webFrame->webView();
382    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
383    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
384        frameLoadDelegate->didCommitLoadForFrame(webView, m_webFrame);
385}
386
387void WebFrameLoaderClient::dispatchDidFinishDocumentLoad()
388{
389    WebView* webView = m_webFrame->webView();
390    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
391    if (SUCCEEDED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv)
392        frameLoadDelegatePriv->didFinishDocumentLoadForFrame(webView, m_webFrame);
393}
394
395void WebFrameLoaderClient::dispatchDidFinishLoad()
396{
397    WebView* webView = m_webFrame->webView();
398    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
399    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
400        frameLoadDelegate->didFinishLoadForFrame(webView, m_webFrame);
401}
402
403void WebFrameLoaderClient::dispatchDidFirstLayout()
404{
405    WebView* webView = m_webFrame->webView();
406    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
407    if (SUCCEEDED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv)
408        frameLoadDelegatePriv->didFirstLayoutInFrame(webView, m_webFrame);
409}
410
411void WebFrameLoaderClient::dispatchDidFirstVisuallyNonEmptyLayout()
412{
413    WebView* webView = m_webFrame->webView();
414    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePrivate;
415    if (SUCCEEDED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePrivate)) && frameLoadDelegatePrivate)
416        frameLoadDelegatePrivate->didFirstVisuallyNonEmptyLayoutInFrame(webView, m_webFrame);
417}
418
419Frame* WebFrameLoaderClient::dispatchCreatePage()
420{
421    WebView* webView = m_webFrame->webView();
422
423    COMPtr<IWebUIDelegate> ui;
424    if (FAILED(webView->uiDelegate(&ui)))
425        return 0;
426
427    COMPtr<IWebView> newWebView;
428    if (FAILED(ui->createWebViewWithRequest(webView, 0, &newWebView)))
429        return 0;
430
431    COMPtr<IWebFrame> mainFrame;
432    if (FAILED(newWebView->mainFrame(&mainFrame)))
433        return 0;
434
435    COMPtr<WebFrame> mainFrameImpl(Query, mainFrame);
436    return core(mainFrameImpl.get());
437}
438
439void WebFrameLoaderClient::dispatchShow()
440{
441    WebView* webView = m_webFrame->webView();
442    COMPtr<IWebUIDelegate> ui;
443    if (SUCCEEDED(webView->uiDelegate(&ui)))
444        ui->webViewShow(webView);
445}
446
447void WebFrameLoaderClient::dispatchDidLoadMainResource(DocumentLoader*)
448{
449}
450
451void WebFrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError& error)
452{
453    if (!m_manualLoader)
454        return;
455
456    m_manualLoader->didFail(error);
457    m_manualLoader = 0;
458    m_hasSentResponseToPlugin = false;
459}
460
461void WebFrameLoaderClient::postProgressStartedNotification()
462{
463    static BSTR progressStartedName = SysAllocString(WebViewProgressStartedNotification);
464    IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
465    notifyCenter->postNotificationName(progressStartedName, static_cast<IWebView*>(m_webFrame->webView()), 0);
466}
467
468void WebFrameLoaderClient::postProgressEstimateChangedNotification()
469{
470    static BSTR progressEstimateChangedName = SysAllocString(WebViewProgressEstimateChangedNotification);
471    IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
472    notifyCenter->postNotificationName(progressEstimateChangedName, static_cast<IWebView*>(m_webFrame->webView()), 0);
473}
474
475void WebFrameLoaderClient::postProgressFinishedNotification()
476{
477    static BSTR progressFinishedName = SysAllocString(WebViewProgressFinishedNotification);
478    IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
479    notifyCenter->postNotificationName(progressFinishedName, static_cast<IWebView*>(m_webFrame->webView()), 0);
480}
481
482void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
483{
484    // FIXME: This should probably go through the data source.
485    const String& textEncoding = loader->response().textEncodingName();
486
487    if (!m_manualLoader)
488        receivedData(data, length, textEncoding);
489
490    if (!m_manualLoader)
491        return;
492
493    if (!m_hasSentResponseToPlugin) {
494        m_manualLoader->didReceiveResponse(core(m_webFrame)->loader()->documentLoader()->response());
495        // didReceiveResponse sets up a new stream to the plug-in. on a full-page plug-in, a failure in
496        // setting up this stream can cause the main document load to be cancelled, setting m_manualLoader
497        // to null
498        if (!m_manualLoader)
499            return;
500        m_hasSentResponseToPlugin = true;
501    }
502    m_manualLoader->didReceiveData(data, length);
503}
504
505void WebFrameLoaderClient::receivedData(const char* data, int length, const String& textEncoding)
506{
507    Frame* coreFrame = core(m_webFrame);
508    if (!coreFrame)
509        return;
510
511    // Set the encoding. This only needs to be done once, but it's harmless to do it again later.
512    String encoding = coreFrame->loader()->documentLoader()->overrideEncoding();
513    bool userChosen = !encoding.isNull();
514    if (encoding.isNull())
515        encoding = textEncoding;
516    coreFrame->loader()->setEncoding(encoding, userChosen);
517
518    coreFrame->loader()->addData(data, length);
519}
520
521void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
522{
523    // Telling the frame we received some data and passing 0 as the data is our
524    // way to get work done that is normally done when the first bit of data is
525    // received, even for the case of a document with no data (like about:blank)
526    if (!m_manualLoader) {
527        committedLoad(loader, 0, 0);
528        return;
529    }
530
531    m_manualLoader->didFinishLoading();
532    m_manualLoader = 0;
533    m_hasSentResponseToPlugin = false;
534}
535
536void WebFrameLoaderClient::updateGlobalHistory()
537{
538    DocumentLoader* loader = core(m_webFrame)->loader()->documentLoader();
539    WebView* webView = m_webFrame->webView();
540    COMPtr<IWebHistoryDelegate> historyDelegate;
541    webView->historyDelegate(&historyDelegate);
542
543    if (historyDelegate) {
544        COMPtr<IWebURLResponse> urlResponse(AdoptCOM, WebURLResponse::createInstance(loader->response()));
545        COMPtr<IWebURLRequest> urlRequest(AdoptCOM, WebMutableURLRequest::createInstance(loader->originalRequestCopy()));
546
547        COMPtr<IWebNavigationData> navigationData(AdoptCOM, WebNavigationData::createInstance(
548            loader->urlForHistory(), loader->title(), urlRequest.get(), urlResponse.get(), loader->substituteData().isValid(), loader->clientRedirectSourceForHistory()));
549
550        historyDelegate->didNavigateWithNavigationData(webView, navigationData.get(), m_webFrame);
551        return;
552    }
553
554    WebHistory* history = WebHistory::sharedHistory();
555    if (!history)
556        return;
557
558    history->visitedURL(loader->urlForHistory(), loader->title(), loader->originalRequestCopy().httpMethod(), loader->urlForHistoryReflectsFailure(), !loader->clientRedirectSourceForHistory());
559}
560
561void WebFrameLoaderClient::updateGlobalHistoryRedirectLinks()
562{
563    WebView* webView = m_webFrame->webView();
564    COMPtr<IWebHistoryDelegate> historyDelegate;
565    webView->historyDelegate(&historyDelegate);
566
567    WebHistory* history = WebHistory::sharedHistory();
568
569    DocumentLoader* loader = core(m_webFrame)->loader()->documentLoader();
570    ASSERT(loader->unreachableURL().isEmpty());
571
572    if (!loader->clientRedirectSourceForHistory().isNull()) {
573        if (historyDelegate) {
574            BString sourceURL(loader->clientRedirectSourceForHistory());
575            BString destURL(loader->clientRedirectDestinationForHistory());
576            historyDelegate->didPerformClientRedirectFromURL(webView, sourceURL, destURL, m_webFrame);
577        } else {
578            if (history) {
579                if (COMPtr<IWebHistoryItem> iWebHistoryItem = history->itemForURLString(loader->clientRedirectSourceForHistory())) {
580                    COMPtr<WebHistoryItem> webHistoryItem(Query, iWebHistoryItem);
581                    webHistoryItem->historyItem()->addRedirectURL(loader->clientRedirectDestinationForHistory());
582                }
583            }
584        }
585    }
586
587    if (!loader->serverRedirectSourceForHistory().isNull()) {
588        if (historyDelegate) {
589            BString sourceURL(loader->serverRedirectSourceForHistory());
590            BString destURL(loader->serverRedirectDestinationForHistory());
591            historyDelegate->didPerformServerRedirectFromURL(webView, sourceURL, destURL, m_webFrame);
592        } else {
593            if (history) {
594                if (COMPtr<IWebHistoryItem> iWebHistoryItem = history->itemForURLString(loader->serverRedirectSourceForHistory())) {
595                    COMPtr<WebHistoryItem> webHistoryItem(Query, iWebHistoryItem);
596                    webHistoryItem->historyItem()->addRedirectURL(loader->serverRedirectDestinationForHistory());
597                }
598            }
599        }
600    }
601}
602
603bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem*) const
604{
605    return true;
606}
607
608void WebFrameLoaderClient::dispatchDidAddBackForwardItem(HistoryItem*) const
609{
610}
611
612void WebFrameLoaderClient::dispatchDidRemoveBackForwardItem(HistoryItem*) const
613{
614}
615
616void WebFrameLoaderClient::dispatchDidChangeBackForwardIndex() const
617{
618}
619
620void WebFrameLoaderClient::didDisplayInsecureContent()
621{
622    WebView* webView = m_webFrame->webView();
623    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
624    if (FAILED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) || !frameLoadDelegatePriv)
625        return;
626
627    COMPtr<IWebFrameLoadDelegatePrivate2> frameLoadDelegatePriv2(Query, frameLoadDelegatePriv);
628    if (!frameLoadDelegatePriv2)
629        return;
630
631    frameLoadDelegatePriv2->didDisplayInsecureContent(webView);
632}
633
634void WebFrameLoaderClient::didRunInsecureContent(SecurityOrigin* origin)
635{
636    COMPtr<IWebSecurityOrigin> webSecurityOrigin = WebSecurityOrigin::createInstance(origin);
637
638    WebView* webView = m_webFrame->webView();
639    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
640    if (FAILED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) || !frameLoadDelegatePriv)
641        return;
642
643    COMPtr<IWebFrameLoadDelegatePrivate2> frameLoadDelegatePriv2(Query, frameLoadDelegatePriv);
644    if (!frameLoadDelegatePriv2)
645        return;
646
647    frameLoadDelegatePriv2->didRunInsecureContent(webView, webSecurityOrigin.get());
648}
649
650PassRefPtr<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
651{
652    RefPtr<WebDocumentLoader> loader = WebDocumentLoader::create(request, substituteData);
653
654    COMPtr<WebDataSource> dataSource(AdoptCOM, WebDataSource::createInstance(loader.get()));
655
656    loader->setDataSource(dataSource.get());
657    return loader.release();
658}
659
660void WebFrameLoaderClient::setTitle(const String& title, const KURL& url)
661{
662    WebView* webView = m_webFrame->webView();
663    COMPtr<IWebHistoryDelegate> historyDelegate;
664    webView->historyDelegate(&historyDelegate);
665    if (historyDelegate) {
666        BString titleBSTR(title);
667        BString urlBSTR(url.string());
668        historyDelegate->updateHistoryTitle(webView, titleBSTR, urlBSTR);
669        return;
670    }
671
672    BOOL privateBrowsingEnabled = FALSE;
673    COMPtr<IWebPreferences> preferences;
674    if (SUCCEEDED(m_webFrame->webView()->preferences(&preferences)))
675        preferences->privateBrowsingEnabled(&privateBrowsingEnabled);
676    if (privateBrowsingEnabled)
677        return;
678
679    // update title in global history
680    COMPtr<WebHistory> history = webHistory();
681    if (!history)
682        return;
683
684    COMPtr<IWebHistoryItem> item;
685    if (FAILED(history->itemForURL(BString(url.string()), &item)))
686        return;
687
688    COMPtr<IWebHistoryItemPrivate> itemPrivate(Query, item);
689    if (!itemPrivate)
690        return;
691
692    itemPrivate->setTitle(BString(title));
693}
694
695void WebFrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame)
696{
697#if USE(CFNETWORK)
698    Frame* coreFrame = core(m_webFrame);
699    if (!coreFrame)
700        return;
701
702    ASSERT(coreFrame->loader()->documentLoader() == cachedFrame->documentLoader());
703
704    WebCachedFramePlatformData* webPlatformData = new WebCachedFramePlatformData(static_cast<IWebDataSource*>(getWebDataSource(coreFrame->loader()->documentLoader())));
705    cachedFrame->setCachedFramePlatformData(webPlatformData);
706#else
707    notImplemented();
708#endif
709}
710
711void WebFrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame*)
712{
713}
714
715void WebFrameLoaderClient::transitionToCommittedForNewPage()
716{
717    WebView* view = m_webFrame->webView();
718
719    RECT rect;
720    view->frameRect(&rect);
721    bool transparent = view->transparent();
722    Color backgroundColor = transparent ? Color::transparent : Color::white;
723    core(m_webFrame)->createView(IntRect(rect).size(), backgroundColor, transparent, IntSize(), false);
724}
725
726bool WebFrameLoaderClient::canCachePage() const
727{
728    return true;
729}
730
731PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
732                            const String& referrer, bool /*allowsScrolling*/, int /*marginWidth*/, int /*marginHeight*/)
733{
734    RefPtr<Frame> result = createFrame(url, name, ownerElement, referrer);
735    if (!result)
736        return 0;
737    return result.release();
738}
739
740PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& URL, const String& name, HTMLFrameOwnerElement* ownerElement, const String& referrer)
741{
742    Frame* coreFrame = core(m_webFrame);
743    ASSERT(coreFrame);
744
745    COMPtr<WebFrame> webFrame(AdoptCOM, WebFrame::createInstance());
746
747    RefPtr<Frame> childFrame = webFrame->init(m_webFrame->webView(), coreFrame->page(), ownerElement);
748
749    coreFrame->tree()->appendChild(childFrame);
750    childFrame->tree()->setName(name);
751    childFrame->init();
752
753    coreFrame->loader()->loadURLIntoChildFrame(URL, referrer, childFrame.get());
754
755    // The frame's onload handler may have removed it from the document.
756    if (!childFrame->tree()->parent())
757        return 0;
758
759    return childFrame.release();
760}
761
762void WebFrameLoaderClient::dispatchDidFailToStartPlugin(const PluginView* pluginView) const
763{
764    WebView* webView = m_webFrame->webView();
765
766    COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
767    if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
768        return;
769
770    RetainPtr<CFMutableDictionaryRef> userInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
771
772    Frame* frame = core(m_webFrame);
773    ASSERT(frame == pluginView->parentFrame());
774
775    if (!pluginView->pluginsPage().isNull()) {
776        KURL pluginPageURL = frame->document()->completeURL(deprecatedParseURL(pluginView->pluginsPage()));
777        if (pluginPageURL.protocolInHTTPFamily()) {
778            static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorPlugInPageURLStringKey);
779            RetainPtr<CFStringRef> str(AdoptCF, pluginPageURL.string().createCFString());
780            CFDictionarySetValue(userInfo.get(), key, str.get());
781        }
782    }
783
784    if (!pluginView->mimeType().isNull()) {
785        static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorMIMETypeKey);
786
787        RetainPtr<CFStringRef> str(AdoptCF, pluginView->mimeType().createCFString());
788        CFDictionarySetValue(userInfo.get(), key, str.get());
789    }
790
791    if (pluginView->plugin()) {
792        String pluginName = pluginView->plugin()->name();
793        if (!pluginName.isNull()) {
794            static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorPlugInNameKey);
795            RetainPtr<CFStringRef> str(AdoptCF, pluginName.createCFString());
796            CFDictionarySetValue(userInfo.get(), key, str.get());
797        }
798    }
799
800    COMPtr<CFDictionaryPropertyBag> userInfoBag = CFDictionaryPropertyBag::createInstance();
801    userInfoBag->setDictionary(userInfo.get());
802
803    int errorCode = 0;
804    switch (pluginView->status()) {
805        case PluginStatusCanNotFindPlugin:
806            errorCode = WebKitErrorCannotFindPlugIn;
807            break;
808        case PluginStatusCanNotLoadPlugin:
809            errorCode = WebKitErrorCannotLoadPlugIn;
810            break;
811        default:
812            ASSERT_NOT_REACHED();
813    }
814
815    ResourceError resourceError(String(WebKitErrorDomain), errorCode, pluginView->url().string(), String());
816    COMPtr<IWebError> error(AdoptCOM, WebError::createInstance(resourceError, userInfoBag.get()));
817
818    resourceLoadDelegate->plugInFailedWithError(webView, error.get(), getWebDataSource(frame->loader()->documentLoader()));
819}
820
821PassRefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize& pluginSize, HTMLPlugInElement* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
822{
823    WebView* webView = m_webFrame->webView();
824
825    COMPtr<IWebUIDelegate> ui;
826    if (SUCCEEDED(webView->uiDelegate(&ui)) && ui) {
827        COMPtr<IWebUIDelegatePrivate> uiPrivate(Query, ui);
828
829        if (uiPrivate) {
830            // Assemble the view arguments in a property bag.
831            HashMap<String, String> viewArguments;
832            for (unsigned i = 0; i < paramNames.size(); i++)
833                viewArguments.set(paramNames[i], paramValues[i]);
834            COMPtr<IPropertyBag> viewArgumentsBag(AdoptCOM, COMPropertyBag<String>::adopt(viewArguments));
835            COMPtr<IDOMElement> containingElement(AdoptCOM, DOMElement::createInstance(element));
836
837            HashMap<String, COMVariant> arguments;
838
839            arguments.set(WebEmbeddedViewAttributesKey, viewArgumentsBag);
840            arguments.set(WebEmbeddedViewBaseURLKey, url.string());
841            arguments.set(WebEmbeddedViewContainingElementKey, containingElement);
842            arguments.set(WebEmbeddedViewMIMETypeKey, mimeType);
843
844            COMPtr<IPropertyBag> argumentsBag(AdoptCOM, COMPropertyBag<COMVariant>::adopt(arguments));
845
846            COMPtr<IWebEmbeddedView> view;
847            HRESULT result = uiPrivate->embeddedViewWithArguments(webView, m_webFrame, argumentsBag.get(), &view);
848            if (SUCCEEDED(result)) {
849                HWND parentWindow;
850                HRESULT hr = webView->viewWindow((OLE_HANDLE*)&parentWindow);
851                ASSERT(SUCCEEDED(hr));
852
853                return EmbeddedWidget::create(view.get(), element, parentWindow, pluginSize);
854            }
855        }
856    }
857
858    Frame* frame = core(m_webFrame);
859    RefPtr<PluginView> pluginView = PluginView::create(frame, pluginSize, element, url, paramNames, paramValues, mimeType, loadManually);
860
861    if (pluginView->status() == PluginStatusLoadedSuccessfully)
862        return pluginView;
863
864    dispatchDidFailToStartPlugin(pluginView.get());
865
866    return pluginView;
867}
868
869void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
870{
871    // Ideally, this function shouldn't be necessary, see <rdar://problem/4852889>
872
873    if (pluginWidget->isPluginView())
874        m_manualLoader = static_cast<PluginView*>(pluginWidget);
875    else
876        m_manualLoader = static_cast<EmbeddedWidget*>(pluginWidget);
877}
878
879WebHistory* WebFrameLoaderClient::webHistory() const
880{
881    if (m_webFrame != m_webFrame->webView()->topLevelFrame())
882        return 0;
883
884    return WebHistory::sharedHistory();
885}
886
887bool WebFrameLoaderClient::shouldUsePluginDocument(const String& mimeType) const
888{
889    WebView* webView = m_webFrame->webView();
890    if (!webView)
891        return false;
892
893    return webView->shouldUseEmbeddedView(mimeType);
894}
895