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#include <WebCore/BackForwardController.h>
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/HTMLParserIdioms.h>
63#include <WebCore/HTMLPlugInElement.h>
64#include <WebCore/HistoryItem.h>
65#include <WebCore/Page.h>
66#include <WebCore/PluginPackage.h>
67#include <WebCore/PluginView.h>
68#include <WebCore/RenderPart.h>
69#include <WebCore/ResourceHandle.h>
70#include <WebCore/Settings.h>
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
246bool WebFrameLoaderClient::shouldCacheResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response, const unsigned char* data, const unsigned long long length)
247{
248    WebView* webView = m_webFrame->webView();
249    COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
250    if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
251        return true;
252
253    COMPtr<IWebResourceLoadDelegatePrivate> resourceLoadDelegatePrivate(Query, resourceLoadDelegate);
254    if (!resourceLoadDelegatePrivate)
255        return true;
256
257    COMPtr<IWebURLResponse> urlResponse(AdoptCOM, WebURLResponse::createInstance(response));
258    BOOL shouldCache;
259    if (SUCCEEDED(resourceLoadDelegatePrivate->shouldCacheResponse(webView, identifier, urlResponse.get(), data, length, getWebDataSource(loader), &shouldCache)))
260        return shouldCache;
261
262    return true;
263}
264
265void WebFrameLoaderClient::dispatchDidHandleOnloadEvents()
266{
267    WebView* webView = m_webFrame->webView();
268    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
269    if (SUCCEEDED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv)
270        frameLoadDelegatePriv->didHandleOnloadEventsForFrame(webView, m_webFrame);
271}
272
273void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
274{
275    WebView* webView = m_webFrame->webView();
276    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
277    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
278        frameLoadDelegate->didReceiveServerRedirectForProvisionalLoadForFrame(webView, m_webFrame);
279}
280
281void WebFrameLoaderClient::dispatchDidCancelClientRedirect()
282{
283    WebView* webView = m_webFrame->webView();
284    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
285    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
286        frameLoadDelegate->didCancelClientRedirectForFrame(webView, m_webFrame);
287}
288
289void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const KURL& url, double delay, double fireDate)
290{
291    WebView* webView = m_webFrame->webView();
292    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
293    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
294        frameLoadDelegate->willPerformClientRedirectToURL(webView, BString(url.string()), delay, MarshallingHelpers::CFAbsoluteTimeToDATE(fireDate), m_webFrame);
295}
296
297void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage()
298{
299    WebView* webView = m_webFrame->webView();
300    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
301    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
302        frameLoadDelegate->didChangeLocationWithinPageForFrame(webView, m_webFrame);
303}
304
305void WebFrameLoaderClient::dispatchDidPushStateWithinPage()
306{
307    WebView* webView = m_webFrame->webView();
308    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
309    if (FAILED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) || !frameLoadDelegatePriv)
310        return;
311
312    COMPtr<IWebFrameLoadDelegatePrivate2> frameLoadDelegatePriv2(Query, frameLoadDelegatePriv);
313    if (!frameLoadDelegatePriv2)
314        return;
315
316    frameLoadDelegatePriv2->didPushStateWithinPageForFrame(webView, m_webFrame);
317}
318
319void WebFrameLoaderClient::dispatchDidReplaceStateWithinPage()
320{
321    WebView* webView = m_webFrame->webView();
322    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
323    if (FAILED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) || !frameLoadDelegatePriv)
324        return;
325
326    COMPtr<IWebFrameLoadDelegatePrivate2> frameLoadDelegatePriv2(Query, frameLoadDelegatePriv);
327    if (!frameLoadDelegatePriv2)
328        return;
329
330    frameLoadDelegatePriv2->didReplaceStateWithinPageForFrame(webView, m_webFrame);
331}
332
333void WebFrameLoaderClient::dispatchDidPopStateWithinPage()
334{
335    WebView* webView = m_webFrame->webView();
336    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
337    if (FAILED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) || !frameLoadDelegatePriv)
338        return;
339
340    COMPtr<IWebFrameLoadDelegatePrivate2> frameLoadDelegatePriv2(Query, frameLoadDelegatePriv);
341    if (!frameLoadDelegatePriv2)
342        return;
343
344    frameLoadDelegatePriv2->didPopStateWithinPageForFrame(webView, m_webFrame);
345}
346void WebFrameLoaderClient::dispatchWillClose()
347{
348    WebView* webView = m_webFrame->webView();
349    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
350    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
351        frameLoadDelegate->willCloseFrame(webView, m_webFrame);
352}
353
354void WebFrameLoaderClient::dispatchDidReceiveIcon()
355{
356    m_webFrame->webView()->dispatchDidReceiveIconFromWebFrame(m_webFrame);
357}
358
359void WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
360{
361    WebView* webView = m_webFrame->webView();
362    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
363    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
364        frameLoadDelegate->didStartProvisionalLoadForFrame(webView, m_webFrame);
365}
366
367void WebFrameLoaderClient::dispatchDidReceiveTitle(const StringWithDirection& title)
368{
369    WebView* webView = m_webFrame->webView();
370    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
371    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
372        // FIXME: use direction of title.
373        frameLoadDelegate->didReceiveTitle(webView, BString(title.string()), m_webFrame);
374}
375
376void WebFrameLoaderClient::dispatchDidChangeIcons()
377{
378    WebView* webView = m_webFrame->webView();
379    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
380    if (FAILED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) || !frameLoadDelegatePriv)
381        return;
382
383    COMPtr<IWebFrameLoadDelegatePrivate2> frameLoadDelegatePriv2(Query, frameLoadDelegatePriv);
384    if (!frameLoadDelegatePriv2)
385        return;
386
387    frameLoadDelegatePriv2->didChangeIcons(webView, m_webFrame);
388}
389
390void WebFrameLoaderClient::dispatchDidCommitLoad()
391{
392    WebView* webView = m_webFrame->webView();
393    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
394    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
395        frameLoadDelegate->didCommitLoadForFrame(webView, m_webFrame);
396}
397
398void WebFrameLoaderClient::dispatchDidFinishDocumentLoad()
399{
400    WebView* webView = m_webFrame->webView();
401    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
402    if (SUCCEEDED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv)
403        frameLoadDelegatePriv->didFinishDocumentLoadForFrame(webView, m_webFrame);
404}
405
406void WebFrameLoaderClient::dispatchDidFinishLoad()
407{
408    WebView* webView = m_webFrame->webView();
409    COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
410    if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
411        frameLoadDelegate->didFinishLoadForFrame(webView, m_webFrame);
412}
413
414void WebFrameLoaderClient::dispatchDidFirstLayout()
415{
416    WebView* webView = m_webFrame->webView();
417    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
418    if (SUCCEEDED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv)
419        frameLoadDelegatePriv->didFirstLayoutInFrame(webView, m_webFrame);
420}
421
422void WebFrameLoaderClient::dispatchDidFirstVisuallyNonEmptyLayout()
423{
424    WebView* webView = m_webFrame->webView();
425    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePrivate;
426    if (SUCCEEDED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePrivate)) && frameLoadDelegatePrivate)
427        frameLoadDelegatePrivate->didFirstVisuallyNonEmptyLayoutInFrame(webView, m_webFrame);
428}
429
430Frame* WebFrameLoaderClient::dispatchCreatePage(const NavigationAction&)
431{
432    WebView* webView = m_webFrame->webView();
433
434    COMPtr<IWebUIDelegate> ui;
435    if (FAILED(webView->uiDelegate(&ui)))
436        return 0;
437
438    COMPtr<IWebView> newWebView;
439    if (FAILED(ui->createWebViewWithRequest(webView, 0, &newWebView)))
440        return 0;
441
442    COMPtr<IWebFrame> mainFrame;
443    if (FAILED(newWebView->mainFrame(&mainFrame)))
444        return 0;
445
446    COMPtr<WebFrame> mainFrameImpl(Query, mainFrame);
447    return core(mainFrameImpl.get());
448}
449
450void WebFrameLoaderClient::dispatchShow()
451{
452    WebView* webView = m_webFrame->webView();
453    COMPtr<IWebUIDelegate> ui;
454    if (SUCCEEDED(webView->uiDelegate(&ui)))
455        ui->webViewShow(webView);
456}
457
458void WebFrameLoaderClient::dispatchDidLoadMainResource(DocumentLoader*)
459{
460}
461
462void WebFrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError& error)
463{
464    if (!m_manualLoader)
465        return;
466
467    m_manualLoader->didFail(error);
468    m_manualLoader = 0;
469    m_hasSentResponseToPlugin = false;
470}
471
472void WebFrameLoaderClient::postProgressStartedNotification()
473{
474    static BSTR progressStartedName = SysAllocString(WebViewProgressStartedNotification);
475    IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
476    notifyCenter->postNotificationName(progressStartedName, static_cast<IWebView*>(m_webFrame->webView()), 0);
477}
478
479void WebFrameLoaderClient::postProgressEstimateChangedNotification()
480{
481    static BSTR progressEstimateChangedName = SysAllocString(WebViewProgressEstimateChangedNotification);
482    IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
483    notifyCenter->postNotificationName(progressEstimateChangedName, static_cast<IWebView*>(m_webFrame->webView()), 0);
484}
485
486void WebFrameLoaderClient::postProgressFinishedNotification()
487{
488    static BSTR progressFinishedName = SysAllocString(WebViewProgressFinishedNotification);
489    IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
490    notifyCenter->postNotificationName(progressFinishedName, static_cast<IWebView*>(m_webFrame->webView()), 0);
491}
492
493void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
494{
495    if (!m_manualLoader)
496        loader->commitData(data, length);
497
498    // If the document is a stand-alone media document, now is the right time to cancel the WebKit load.
499    // FIXME: This code should be shared across all ports. <http://webkit.org/b/48762>.
500    Frame* coreFrame = core(m_webFrame);
501    if (coreFrame->document()->isMediaDocument())
502        loader->cancelMainResourceLoad(pluginWillHandleLoadError(loader->response()));
503
504    if (!m_manualLoader)
505        return;
506
507    if (!m_hasSentResponseToPlugin) {
508        m_manualLoader->didReceiveResponse(loader->response());
509        // didReceiveResponse sets up a new stream to the plug-in. on a full-page plug-in, a failure in
510        // setting up this stream can cause the main document load to be cancelled, setting m_manualLoader
511        // to null
512        if (!m_manualLoader)
513            return;
514        m_hasSentResponseToPlugin = true;
515    }
516    m_manualLoader->didReceiveData(data, length);
517}
518
519void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
520{
521    // Telling the frame we received some data and passing 0 as the data is our
522    // way to get work done that is normally done when the first bit of data is
523    // received, even for the case of a document with no data (like about:blank)
524    committedLoad(loader, 0, 0);
525
526    if (!m_manualLoader)
527        return;
528
529    m_manualLoader->didFinishLoading();
530    m_manualLoader = 0;
531    m_hasSentResponseToPlugin = false;
532}
533
534void WebFrameLoaderClient::updateGlobalHistory()
535{
536    DocumentLoader* loader = core(m_webFrame)->loader()->documentLoader();
537    WebView* webView = m_webFrame->webView();
538    COMPtr<IWebHistoryDelegate> historyDelegate;
539    webView->historyDelegate(&historyDelegate);
540
541    if (historyDelegate) {
542        COMPtr<IWebURLResponse> urlResponse(AdoptCOM, WebURLResponse::createInstance(loader->response()));
543        COMPtr<IWebURLRequest> urlRequest(AdoptCOM, WebMutableURLRequest::createInstance(loader->originalRequestCopy()));
544
545        COMPtr<IWebNavigationData> navigationData(AdoptCOM, WebNavigationData::createInstance(
546            loader->urlForHistory(), loader->title().string(), urlRequest.get(), urlResponse.get(), loader->substituteData().isValid(), loader->clientRedirectSourceForHistory()));
547
548        historyDelegate->didNavigateWithNavigationData(webView, navigationData.get(), m_webFrame);
549        return;
550    }
551
552    WebHistory* history = WebHistory::sharedHistory();
553    if (!history)
554        return;
555
556    history->visitedURL(loader->urlForHistory(), loader->title().string(), loader->originalRequestCopy().httpMethod(), loader->urlForHistoryReflectsFailure(), !loader->clientRedirectSourceForHistory());
557}
558
559void WebFrameLoaderClient::updateGlobalHistoryRedirectLinks()
560{
561    WebView* webView = m_webFrame->webView();
562    COMPtr<IWebHistoryDelegate> historyDelegate;
563    webView->historyDelegate(&historyDelegate);
564
565    WebHistory* history = WebHistory::sharedHistory();
566
567    DocumentLoader* loader = core(m_webFrame)->loader()->documentLoader();
568    ASSERT(loader->unreachableURL().isEmpty());
569
570    if (!loader->clientRedirectSourceForHistory().isNull()) {
571        if (historyDelegate) {
572            BString sourceURL(loader->clientRedirectSourceForHistory());
573            BString destURL(loader->clientRedirectDestinationForHistory());
574            historyDelegate->didPerformClientRedirectFromURL(webView, sourceURL, destURL, m_webFrame);
575        } else {
576            if (history) {
577                if (COMPtr<IWebHistoryItem> iWebHistoryItem = history->itemForURLString(loader->clientRedirectSourceForHistory())) {
578                    COMPtr<WebHistoryItem> webHistoryItem(Query, iWebHistoryItem);
579                    webHistoryItem->historyItem()->addRedirectURL(loader->clientRedirectDestinationForHistory());
580                }
581            }
582        }
583    }
584
585    if (!loader->serverRedirectSourceForHistory().isNull()) {
586        if (historyDelegate) {
587            BString sourceURL(loader->serverRedirectSourceForHistory());
588            BString destURL(loader->serverRedirectDestinationForHistory());
589            historyDelegate->didPerformServerRedirectFromURL(webView, sourceURL, destURL, m_webFrame);
590        } else {
591            if (history) {
592                if (COMPtr<IWebHistoryItem> iWebHistoryItem = history->itemForURLString(loader->serverRedirectSourceForHistory())) {
593                    COMPtr<WebHistoryItem> webHistoryItem(Query, iWebHistoryItem);
594                    webHistoryItem->historyItem()->addRedirectURL(loader->serverRedirectDestinationForHistory());
595                }
596            }
597        }
598    }
599}
600
601bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem*) const
602{
603    return true;
604}
605
606bool WebFrameLoaderClient::shouldStopLoadingForHistoryItem(HistoryItem*) const
607{
608    return true;
609}
610
611void WebFrameLoaderClient::dispatchDidAddBackForwardItem(HistoryItem*) const
612{
613}
614
615void WebFrameLoaderClient::dispatchDidRemoveBackForwardItem(HistoryItem*) const
616{
617}
618
619void WebFrameLoaderClient::dispatchDidChangeBackForwardIndex() const
620{
621}
622
623void WebFrameLoaderClient::updateGlobalHistoryItemForPage()
624{
625    HistoryItem* historyItem = 0;
626    WebView* webView = m_webFrame->webView();
627
628    if (Page* page = webView->page()) {
629        if (!page->settings()->privateBrowsingEnabled())
630            historyItem = page->backForward()->currentItem();
631    }
632
633    webView->setGlobalHistoryItem(historyItem);
634}
635
636void WebFrameLoaderClient::didDisplayInsecureContent()
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->didDisplayInsecureContent(webView);
648}
649
650void WebFrameLoaderClient::didRunInsecureContent(SecurityOrigin* origin, const KURL& insecureURL)
651{
652    COMPtr<IWebSecurityOrigin> webSecurityOrigin = WebSecurityOrigin::createInstance(origin);
653
654    WebView* webView = m_webFrame->webView();
655    COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
656    if (FAILED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) || !frameLoadDelegatePriv)
657        return;
658
659    COMPtr<IWebFrameLoadDelegatePrivate2> frameLoadDelegatePriv2(Query, frameLoadDelegatePriv);
660    if (!frameLoadDelegatePriv2)
661        return;
662
663    frameLoadDelegatePriv2->didRunInsecureContent(webView, webSecurityOrigin.get());
664}
665
666PassRefPtr<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
667{
668    RefPtr<WebDocumentLoader> loader = WebDocumentLoader::create(request, substituteData);
669
670    COMPtr<WebDataSource> dataSource(AdoptCOM, WebDataSource::createInstance(loader.get()));
671
672    loader->setDataSource(dataSource.get());
673    return loader.release();
674}
675
676void WebFrameLoaderClient::setTitle(const StringWithDirection& title, const KURL& url)
677{
678    WebView* webView = m_webFrame->webView();
679    COMPtr<IWebHistoryDelegate> historyDelegate;
680    webView->historyDelegate(&historyDelegate);
681    if (historyDelegate) {
682        BString titleBSTR(title.string());
683        BString urlBSTR(url.string());
684        historyDelegate->updateHistoryTitle(webView, titleBSTR, urlBSTR);
685        return;
686    }
687
688    BOOL privateBrowsingEnabled = FALSE;
689    COMPtr<IWebPreferences> preferences;
690    if (SUCCEEDED(m_webFrame->webView()->preferences(&preferences)))
691        preferences->privateBrowsingEnabled(&privateBrowsingEnabled);
692    if (privateBrowsingEnabled)
693        return;
694
695    // update title in global history
696    COMPtr<WebHistory> history = webHistory();
697    if (!history)
698        return;
699
700    COMPtr<IWebHistoryItem> item;
701    if (FAILED(history->itemForURL(BString(url.string()), &item)))
702        return;
703
704    COMPtr<IWebHistoryItemPrivate> itemPrivate(Query, item);
705    if (!itemPrivate)
706        return;
707
708    itemPrivate->setTitle(BString(title.string()));
709}
710
711void WebFrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame)
712{
713#if USE(CFNETWORK)
714    Frame* coreFrame = core(m_webFrame);
715    if (!coreFrame)
716        return;
717
718    ASSERT(coreFrame->loader()->documentLoader() == cachedFrame->documentLoader());
719
720    WebCachedFramePlatformData* webPlatformData = new WebCachedFramePlatformData(static_cast<IWebDataSource*>(getWebDataSource(coreFrame->loader()->documentLoader())));
721    cachedFrame->setCachedFramePlatformData(webPlatformData);
722#else
723    notImplemented();
724#endif
725}
726
727void WebFrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame*)
728{
729}
730
731void WebFrameLoaderClient::transitionToCommittedForNewPage()
732{
733    WebView* view = m_webFrame->webView();
734
735    RECT rect;
736    view->frameRect(&rect);
737    bool transparent = view->transparent();
738    Color backgroundColor = transparent ? Color::transparent : Color::white;
739    core(m_webFrame)->createView(IntRect(rect).size(), backgroundColor, transparent, IntSize(), false);
740}
741
742void WebFrameLoaderClient::didSaveToPageCache()
743{
744}
745
746void WebFrameLoaderClient::didRestoreFromPageCache()
747{
748}
749
750void WebFrameLoaderClient::dispatchDidBecomeFrameset(bool)
751{
752}
753
754bool WebFrameLoaderClient::canCachePage() const
755{
756    return true;
757}
758
759PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
760                            const String& referrer, bool /*allowsScrolling*/, int /*marginWidth*/, int /*marginHeight*/)
761{
762    RefPtr<Frame> result = createFrame(url, name, ownerElement, referrer);
763    if (!result)
764        return 0;
765    return result.release();
766}
767
768void WebFrameLoaderClient::didTransferChildFrameToNewDocument(Page*)
769{
770    Frame* coreFrame = core(m_webFrame);
771    ASSERT(coreFrame);
772    WebView* webView = kit(coreFrame->page());
773    if (m_webFrame->webView() != webView)
774        m_webFrame->setWebView(webView);
775}
776
777void WebFrameLoaderClient::transferLoadingResourceFromPage(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request, Page* oldPage)
778{
779    assignIdentifierToInitialRequest(identifier, loader, request);
780
781    WebView* oldWebView = kit(oldPage);
782    if (!oldWebView)
783        return;
784
785    COMPtr<IWebResourceLoadDelegate> oldResourceLoadDelegate;
786    if (FAILED(oldWebView->resourceLoadDelegate(&oldResourceLoadDelegate)))
787        return;
788
789    COMPtr<IWebResourceLoadDelegatePrivate2> oldResourceLoadDelegatePrivate2(Query, oldResourceLoadDelegate);
790    if (!oldResourceLoadDelegatePrivate2)
791        return;
792    oldResourceLoadDelegatePrivate2->removeIdentifierForRequest(oldWebView, identifier);
793}
794
795PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& URL, const String& name, HTMLFrameOwnerElement* ownerElement, const String& referrer)
796{
797    Frame* coreFrame = core(m_webFrame);
798    ASSERT(coreFrame);
799
800    COMPtr<WebFrame> webFrame(AdoptCOM, WebFrame::createInstance());
801
802    RefPtr<Frame> childFrame = webFrame->init(m_webFrame->webView(), coreFrame->page(), ownerElement);
803
804    childFrame->tree()->setName(name);
805    coreFrame->tree()->appendChild(childFrame);
806    childFrame->init();
807
808    coreFrame->loader()->loadURLIntoChildFrame(URL, referrer, childFrame.get());
809
810    // The frame's onload handler may have removed it from the document.
811    if (!childFrame->tree()->parent())
812        return 0;
813
814    return childFrame.release();
815}
816
817void WebFrameLoaderClient::dispatchDidFailToStartPlugin(const PluginView* pluginView) const
818{
819    WebView* webView = m_webFrame->webView();
820
821    COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
822    if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
823        return;
824
825    RetainPtr<CFMutableDictionaryRef> userInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
826
827    Frame* frame = core(m_webFrame);
828    ASSERT(frame == pluginView->parentFrame());
829
830    if (!pluginView->pluginsPage().isNull()) {
831        KURL pluginPageURL = frame->document()->completeURL(stripLeadingAndTrailingHTMLSpaces(pluginView->pluginsPage()));
832        if (pluginPageURL.protocolInHTTPFamily()) {
833            static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorPlugInPageURLStringKey);
834            RetainPtr<CFStringRef> str(AdoptCF, pluginPageURL.string().createCFString());
835            CFDictionarySetValue(userInfo.get(), key, str.get());
836        }
837    }
838
839    if (!pluginView->mimeType().isNull()) {
840        static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorMIMETypeKey);
841
842        RetainPtr<CFStringRef> str(AdoptCF, pluginView->mimeType().createCFString());
843        CFDictionarySetValue(userInfo.get(), key, str.get());
844    }
845
846    if (pluginView->plugin()) {
847        String pluginName = pluginView->plugin()->name();
848        if (!pluginName.isNull()) {
849            static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorPlugInNameKey);
850            RetainPtr<CFStringRef> str(AdoptCF, pluginName.createCFString());
851            CFDictionarySetValue(userInfo.get(), key, str.get());
852        }
853    }
854
855    COMPtr<CFDictionaryPropertyBag> userInfoBag = CFDictionaryPropertyBag::createInstance();
856    userInfoBag->setDictionary(userInfo.get());
857
858    int errorCode = 0;
859    switch (pluginView->status()) {
860        case PluginStatusCanNotFindPlugin:
861            errorCode = WebKitErrorCannotFindPlugIn;
862            break;
863        case PluginStatusCanNotLoadPlugin:
864            errorCode = WebKitErrorCannotLoadPlugIn;
865            break;
866        default:
867            ASSERT_NOT_REACHED();
868    }
869
870    ResourceError resourceError(String(WebKitErrorDomain), errorCode, pluginView->url().string(), String());
871    COMPtr<IWebError> error(AdoptCOM, WebError::createInstance(resourceError, userInfoBag.get()));
872
873    resourceLoadDelegate->plugInFailedWithError(webView, error.get(), getWebDataSource(frame->loader()->documentLoader()));
874}
875
876PassRefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize& pluginSize, HTMLPlugInElement* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
877{
878    WebView* webView = m_webFrame->webView();
879
880    COMPtr<IWebUIDelegate> ui;
881    if (SUCCEEDED(webView->uiDelegate(&ui)) && ui) {
882        COMPtr<IWebUIDelegatePrivate> uiPrivate(Query, ui);
883
884        if (uiPrivate) {
885            // Assemble the view arguments in a property bag.
886            HashMap<String, String> viewArguments;
887            for (unsigned i = 0; i < paramNames.size(); i++)
888                viewArguments.set(paramNames[i], paramValues[i]);
889            COMPtr<IPropertyBag> viewArgumentsBag(AdoptCOM, COMPropertyBag<String>::adopt(viewArguments));
890            COMPtr<IDOMElement> containingElement(AdoptCOM, DOMElement::createInstance(element));
891
892            HashMap<String, COMVariant> arguments;
893
894            arguments.set(WebEmbeddedViewAttributesKey, viewArgumentsBag);
895            arguments.set(WebEmbeddedViewBaseURLKey, url.string());
896            arguments.set(WebEmbeddedViewContainingElementKey, containingElement);
897            arguments.set(WebEmbeddedViewMIMETypeKey, mimeType);
898
899            COMPtr<IPropertyBag> argumentsBag(AdoptCOM, COMPropertyBag<COMVariant>::adopt(arguments));
900
901            COMPtr<IWebEmbeddedView> view;
902            HRESULT result = uiPrivate->embeddedViewWithArguments(webView, m_webFrame, argumentsBag.get(), &view);
903            if (SUCCEEDED(result)) {
904                HWND parentWindow;
905                HRESULT hr = webView->viewWindow((OLE_HANDLE*)&parentWindow);
906                ASSERT(SUCCEEDED(hr));
907
908                return EmbeddedWidget::create(view.get(), element, parentWindow, pluginSize);
909            }
910        }
911    }
912
913    Frame* frame = core(m_webFrame);
914    RefPtr<PluginView> pluginView = PluginView::create(frame, pluginSize, element, url, paramNames, paramValues, mimeType, loadManually);
915
916    if (pluginView->status() == PluginStatusLoadedSuccessfully)
917        return pluginView;
918
919    dispatchDidFailToStartPlugin(pluginView.get());
920
921    return 0;
922}
923
924void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
925{
926    // Ideally, this function shouldn't be necessary, see <rdar://problem/4852889>
927
928    if (pluginWidget->isPluginView())
929        m_manualLoader = static_cast<PluginView*>(pluginWidget);
930    else
931        m_manualLoader = static_cast<EmbeddedWidget*>(pluginWidget);
932}
933
934WebHistory* WebFrameLoaderClient::webHistory() const
935{
936    if (m_webFrame != m_webFrame->webView()->topLevelFrame())
937        return 0;
938
939    return WebHistory::sharedHistory();
940}
941
942bool WebFrameLoaderClient::shouldUsePluginDocument(const String& mimeType) const
943{
944    WebView* webView = m_webFrame->webView();
945    if (!webView)
946        return false;
947
948    return webView->shouldUseEmbeddedView(mimeType);
949}
950