Don't include substitute data URLs in global history redirect chains
[WebKit-https.git] / WebKit / win / WebCoreSupport / WebFrameLoaderClient.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008 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 "WebNotificationCenter.h"
47 #include "WebScriptDebugServer.h"
48 #include "WebURLAuthenticationChallenge.h"
49 #include "WebURLResponse.h"
50 #include "WebView.h"
51 #pragma warning(push, 0)
52 #include <WebCore/CachedFrame.h>
53 #include <WebCore/DocumentLoader.h>
54 #include <WebCore/FrameLoader.h>
55 #include <WebCore/FrameTree.h>
56 #include <WebCore/FrameView.h>
57 #include <WebCore/HTMLAppletElement.h>
58 #include <WebCore/HTMLFrameElement.h>
59 #include <WebCore/HTMLFrameOwnerElement.h>
60 #include <WebCore/HTMLNames.h>
61 #include <WebCore/HTMLPlugInElement.h>
62 #include <WebCore/HistoryItem.h>
63 #include <WebCore/Page.h>
64 #include <WebCore/PluginPackage.h>
65 #include <WebCore/PluginView.h>
66 #include <WebCore/RenderPart.h>
67 #include <WebCore/ResourceHandle.h>
68 #pragma warning(pop)
69
70 using namespace WebCore;
71 using namespace HTMLNames;
72
73 static WebDataSource* getWebDataSource(DocumentLoader* loader)
74 {
75     return loader ? static_cast<WebDocumentLoader*>(loader)->dataSource() : 0;
76 }
77
78 WebFrameLoaderClient::WebFrameLoaderClient(WebFrame* webFrame)
79     : m_webFrame(webFrame)
80     , m_manualLoader(0) 
81     , m_hasSentResponseToPlugin(false) 
82 {
83     ASSERT_ARG(webFrame, webFrame);
84 }
85
86 WebFrameLoaderClient::~WebFrameLoaderClient()
87 {
88 }
89
90 bool WebFrameLoaderClient::hasWebView() const
91 {
92     return m_webFrame->webView();
93 }
94
95 void WebFrameLoaderClient::forceLayout()
96 {
97     FrameView* view = core(m_webFrame)->view();
98     if (view)
99         view->forceLayout(true);
100 }
101
102 void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
103 {
104     WebView* webView = m_webFrame->webView();
105     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
106     if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
107         return;
108
109     COMPtr<WebMutableURLRequest> webURLRequest(AdoptCOM, WebMutableURLRequest::createInstance(request));
110     resourceLoadDelegate->identifierForInitialRequest(webView, webURLRequest.get(), getWebDataSource(loader), identifier);
111 }
112
113 bool WebFrameLoaderClient::shouldUseCredentialStorage(DocumentLoader* loader, unsigned long identifier)
114 {
115     WebView* webView = m_webFrame->webView();
116     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
117     if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
118         return true;
119
120     COMPtr<IWebResourceLoadDelegatePrivate2> resourceLoadDelegatePrivate;
121     if (FAILED(resourceLoadDelegate->QueryInterface(IID_IWebResourceLoadDelegatePrivate2, reinterpret_cast<void**>(&resourceLoadDelegatePrivate))))
122         return true;
123
124     BOOL shouldUse;
125     if (SUCCEEDED(resourceLoadDelegatePrivate->shouldUseCredentialStorage(webView, identifier, getWebDataSource(loader), &shouldUse)))
126         return shouldUse;
127
128     return true;
129 }
130
131 void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge)
132 {
133 #if USE(CFNETWORK)
134     ASSERT(challenge.sourceHandle());
135
136     WebView* webView = m_webFrame->webView();
137     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
138     if (SUCCEEDED(webView->resourceLoadDelegate(&resourceLoadDelegate))) {
139         COMPtr<WebURLAuthenticationChallenge> webChallenge(AdoptCOM, WebURLAuthenticationChallenge::createInstance(challenge));
140         if (SUCCEEDED(resourceLoadDelegate->didReceiveAuthenticationChallenge(webView, identifier, webChallenge.get(), getWebDataSource(loader))))
141             return;
142     }
143
144     // If the ResourceLoadDelegate doesn't exist or fails to handle the call, we tell the ResourceHandle
145     // to continue without credential - this is the best approximation of Mac behavior
146     challenge.sourceHandle()->receivedRequestToContinueWithoutCredential(challenge);
147 #else
148    notImplemented();
149 #endif
150 }
151
152 void WebFrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge)
153 {
154     WebView* webView = m_webFrame->webView();
155     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
156     if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
157         return;
158
159     COMPtr<WebURLAuthenticationChallenge> webChallenge(AdoptCOM, WebURLAuthenticationChallenge::createInstance(challenge));
160     resourceLoadDelegate->didCancelAuthenticationChallenge(webView, identifier, webChallenge.get(), getWebDataSource(loader));
161 }
162
163 void WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
164 {
165     WebView* webView = m_webFrame->webView();
166     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
167     if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
168         return;
169
170     COMPtr<WebMutableURLRequest> webURLRequest(AdoptCOM, WebMutableURLRequest::createInstance(request));
171     COMPtr<WebURLResponse> webURLRedirectResponse(AdoptCOM, WebURLResponse::createInstance(redirectResponse));
172
173     COMPtr<IWebURLRequest> newWebURLRequest;
174     if (FAILED(resourceLoadDelegate->willSendRequest(webView, identifier, webURLRequest.get(), webURLRedirectResponse.get(), getWebDataSource(loader), &newWebURLRequest)))
175         return;
176
177     if (webURLRequest == newWebURLRequest)
178         return;
179
180     COMPtr<WebMutableURLRequest> newWebURLRequestImpl(Query, newWebURLRequest);
181     if (!newWebURLRequestImpl)
182         return;
183
184     request = newWebURLRequestImpl->resourceRequest();
185 }
186
187 void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response)
188 {
189     WebView* webView = m_webFrame->webView();
190     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
191     if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
192         return;
193
194     COMPtr<WebURLResponse> webURLResponse(AdoptCOM, WebURLResponse::createInstance(response));
195     resourceLoadDelegate->didReceiveResponse(webView, identifier, webURLResponse.get(), getWebDataSource(loader));
196 }
197
198 void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int length)
199 {
200     WebView* webView = m_webFrame->webView();
201     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
202     if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
203         return;
204
205     resourceLoadDelegate->didReceiveContentLength(webView, identifier, length, getWebDataSource(loader));
206 }
207
208 void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier)
209 {
210     WebView* webView = m_webFrame->webView();
211     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
212     if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
213         return;
214
215     resourceLoadDelegate->didFinishLoadingFromDataSource(webView, identifier, getWebDataSource(loader));
216 }
217
218 void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
219 {
220     WebView* webView = m_webFrame->webView();
221     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
222     if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
223         return;
224
225     COMPtr<WebError> webError(AdoptCOM, WebError::createInstance(error));
226     resourceLoadDelegate->didFailLoadingWithError(webView, identifier, webError.get(), getWebDataSource(loader));
227 }
228
229 bool WebFrameLoaderClient::shouldCacheResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response, const unsigned char* data, const unsigned long long length)
230 {
231     WebView* webView = m_webFrame->webView();
232     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
233     if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
234         return true;
235
236     COMPtr<IWebResourceLoadDelegatePrivate3> resourceLoadDelegatePrivate(Query, resourceLoadDelegate);
237     if (!resourceLoadDelegatePrivate)
238         return true;
239
240     COMPtr<IWebURLResponse> urlResponse(WebURLResponse::createInstance(response));
241     BOOL shouldCache;
242     if (SUCCEEDED(resourceLoadDelegatePrivate->shouldCacheResponse(webView, identifier, urlResponse.get(), data, length, getWebDataSource(loader), &shouldCache)))
243         return shouldCache;
244
245     return true;
246 }
247
248 void WebFrameLoaderClient::dispatchDidHandleOnloadEvents()
249 {
250     WebView* webView = m_webFrame->webView();
251     COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
252     if (SUCCEEDED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv)
253         frameLoadDelegatePriv->didHandleOnloadEventsForFrame(webView, m_webFrame);
254 }
255
256 void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
257 {
258     WebView* webView = m_webFrame->webView();
259     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
260     if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
261         frameLoadDelegate->didReceiveServerRedirectForProvisionalLoadForFrame(webView, m_webFrame);
262 }
263
264 void WebFrameLoaderClient::dispatchDidCancelClientRedirect()
265 {
266     WebView* webView = m_webFrame->webView();
267     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
268     if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
269         frameLoadDelegate->didCancelClientRedirectForFrame(webView, m_webFrame);
270 }
271
272 void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const KURL& url, double delay, double fireDate)
273 {
274     WebView* webView = m_webFrame->webView();
275     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
276     if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
277         frameLoadDelegate->willPerformClientRedirectToURL(webView, BString(url.string()), delay, MarshallingHelpers::CFAbsoluteTimeToDATE(fireDate), m_webFrame);
278 }
279
280 void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage()
281 {
282     WebView* webView = m_webFrame->webView();
283     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
284     if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
285         frameLoadDelegate->didChangeLocationWithinPageForFrame(webView, m_webFrame);
286 }
287
288 void WebFrameLoaderClient::dispatchWillClose()
289 {
290     WebView* webView = m_webFrame->webView();
291     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
292     if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
293         frameLoadDelegate->willCloseFrame(webView, m_webFrame);
294 }
295
296 void WebFrameLoaderClient::dispatchDidReceiveIcon()
297 {
298     m_webFrame->webView()->dispatchDidReceiveIconFromWebFrame(m_webFrame);
299 }
300
301 void WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
302 {
303     WebView* webView = m_webFrame->webView();
304     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
305     if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
306         frameLoadDelegate->didStartProvisionalLoadForFrame(webView, m_webFrame);
307 }
308
309 void WebFrameLoaderClient::dispatchDidReceiveTitle(const String& title)
310 {
311     WebView* webView = m_webFrame->webView();
312     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
313     if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
314         frameLoadDelegate->didReceiveTitle(webView, BString(title), m_webFrame);
315 }
316
317 void WebFrameLoaderClient::dispatchDidCommitLoad()
318 {
319     WebView* webView = m_webFrame->webView();
320     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
321     if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
322         frameLoadDelegate->didCommitLoadForFrame(webView, m_webFrame);
323 }
324
325 void WebFrameLoaderClient::dispatchDidFinishDocumentLoad()
326 {
327     WebView* webView = m_webFrame->webView();
328     COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
329     if (SUCCEEDED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv)
330         frameLoadDelegatePriv->didFinishDocumentLoadForFrame(webView, m_webFrame);
331 }
332
333 void WebFrameLoaderClient::dispatchDidFinishLoad()
334 {
335     WebView* webView = m_webFrame->webView();
336     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;
337     if (SUCCEEDED(webView->frameLoadDelegate(&frameLoadDelegate)))
338         frameLoadDelegate->didFinishLoadForFrame(webView, m_webFrame);
339 }
340
341 void WebFrameLoaderClient::dispatchDidFirstLayout()
342 {
343     WebView* webView = m_webFrame->webView();
344     COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePriv;
345     if (SUCCEEDED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePriv)) && frameLoadDelegatePriv)
346         frameLoadDelegatePriv->didFirstLayoutInFrame(webView, m_webFrame);
347 }
348
349 void WebFrameLoaderClient::dispatchDidFirstVisuallyNonEmptyLayout()
350 {
351     WebView* webView = m_webFrame->webView();
352     COMPtr<IWebFrameLoadDelegatePrivate> frameLoadDelegatePrivate;
353     if (SUCCEEDED(webView->frameLoadDelegatePrivate(&frameLoadDelegatePrivate)) && frameLoadDelegatePrivate) {
354         COMPtr<IWebFrameLoadDelegatePrivate2> frameLoadDelegatePrivate2(Query, frameLoadDelegatePrivate);
355         if (frameLoadDelegatePrivate2)
356             frameLoadDelegatePrivate2->didFirstVisuallyNonEmptyLayoutInFrame(webView, m_webFrame);
357     }
358 }
359
360 Frame* WebFrameLoaderClient::dispatchCreatePage()
361 {
362     WebView* webView = m_webFrame->webView();
363
364     COMPtr<IWebUIDelegate> ui;
365     if (FAILED(webView->uiDelegate(&ui)))
366         return 0;
367
368     COMPtr<IWebView> newWebView;
369     if (FAILED(ui->createWebViewWithRequest(webView, 0, &newWebView)))
370         return 0;
371
372     COMPtr<IWebFrame> mainFrame;
373     if (FAILED(newWebView->mainFrame(&mainFrame)))
374         return 0;
375
376     COMPtr<WebFrame> mainFrameImpl(Query, mainFrame);
377     return core(mainFrameImpl.get());
378 }
379
380 void WebFrameLoaderClient::dispatchShow()
381 {
382     WebView* webView = m_webFrame->webView();
383     COMPtr<IWebUIDelegate> ui;
384     if (SUCCEEDED(webView->uiDelegate(&ui)))
385         ui->webViewShow(webView);
386 }
387
388 void WebFrameLoaderClient::dispatchDidLoadMainResource(DocumentLoader*)
389 {
390 }
391
392 void WebFrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError& error)
393 {
394     if (!m_manualLoader)
395         return;
396
397     m_manualLoader->didFail(error);
398     m_manualLoader = 0;
399     m_hasSentResponseToPlugin = false;
400 }
401
402 void WebFrameLoaderClient::postProgressStartedNotification()
403 {
404     static BSTR progressStartedName = SysAllocString(WebViewProgressStartedNotification);
405     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
406     notifyCenter->postNotificationName(progressStartedName, static_cast<IWebView*>(m_webFrame->webView()), 0);
407 }
408
409 void WebFrameLoaderClient::postProgressEstimateChangedNotification()
410 {
411     static BSTR progressEstimateChangedName = SysAllocString(WebViewProgressEstimateChangedNotification);
412     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
413     notifyCenter->postNotificationName(progressEstimateChangedName, static_cast<IWebView*>(m_webFrame->webView()), 0);
414 }
415
416 void WebFrameLoaderClient::postProgressFinishedNotification()
417 {
418     static BSTR progressFinishedName = SysAllocString(WebViewProgressFinishedNotification);
419     IWebNotificationCenter* notifyCenter = WebNotificationCenter::defaultCenterInternal();
420     notifyCenter->postNotificationName(progressFinishedName, static_cast<IWebView*>(m_webFrame->webView()), 0);
421 }
422
423 void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
424 {
425     // FIXME: This should probably go through the data source.
426     const String& textEncoding = loader->response().textEncodingName();
427
428     if (!m_manualLoader)
429         receivedData(data, length, textEncoding);
430
431     if (!m_manualLoader)
432         return;
433
434     if (!m_hasSentResponseToPlugin) {
435         m_manualLoader->didReceiveResponse(core(m_webFrame)->loader()->documentLoader()->response());
436         // didReceiveResponse sets up a new stream to the plug-in. on a full-page plug-in, a failure in
437         // setting up this stream can cause the main document load to be cancelled, setting m_manualLoader
438         // to null
439         if (!m_manualLoader)
440             return;
441         m_hasSentResponseToPlugin = true;
442     }
443     m_manualLoader->didReceiveData(data, length);
444 }
445
446 void WebFrameLoaderClient::receivedData(const char* data, int length, const String& textEncoding)
447 {
448     Frame* coreFrame = core(m_webFrame);
449     if (!coreFrame)
450         return;
451
452     // Set the encoding. This only needs to be done once, but it's harmless to do it again later.
453     String encoding = coreFrame->loader()->documentLoader()->overrideEncoding();
454     bool userChosen = !encoding.isNull();
455     if (encoding.isNull())
456         encoding = textEncoding;
457     coreFrame->loader()->setEncoding(encoding, userChosen);
458
459     coreFrame->loader()->addData(data, length);
460 }
461
462 void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
463 {
464     // Telling the frame we received some data and passing 0 as the data is our
465     // way to get work done that is normally done when the first bit of data is
466     // received, even for the case of a document with no data (like about:blank)
467     if (!m_manualLoader) {
468         committedLoad(loader, 0, 0);
469         return;
470     }
471
472     m_manualLoader->didFinishLoading();
473     m_manualLoader = 0;
474     m_hasSentResponseToPlugin = false;
475 }
476
477 void WebFrameLoaderClient::updateGlobalHistory()
478 {
479     WebHistory* history = WebHistory::sharedHistory();
480     if (!history)
481         return;
482
483     DocumentLoader* loader = core(m_webFrame)->loader()->documentLoader();
484     history->visitedURL(loader->urlForHistory(), loader->title(), loader->originalRequestCopy().httpMethod(), loader->urlForHistoryReflectsFailure());
485 }
486
487 void WebFrameLoaderClient::updateGlobalHistoryRedirectLinks()
488 {
489     WebHistory* history = WebHistory::sharedHistory();
490     if (!history)
491         return;
492
493     DocumentLoader* loader = core(m_webFrame)->loader()->documentLoader();
494     ASSERT(loader->unreachableURL().isEmpty());
495
496     if (!loader->clientRedirectSourceForHistory().isNull()) {
497         if (COMPtr<IWebHistoryItem> iWebHistoryItem = history->itemForURLString(loader->clientRedirectSourceForHistory())) {
498             COMPtr<WebHistoryItem> webHistoryItem(Query, iWebHistoryItem);
499             webHistoryItem->historyItem()->addRedirectURL(loader->clientRedirectDestinationForHistory());
500         }
501     }
502
503     if (!loader->serverRedirectSourceForHistory().isNull()) {
504         if (COMPtr<IWebHistoryItem> iWebHistoryItem = history->itemForURLString(loader->serverRedirectSourceForHistory())) {
505             COMPtr<WebHistoryItem> webHistoryItem(Query, iWebHistoryItem);
506             webHistoryItem->historyItem()->addRedirectURL(loader->serverRedirectDestinationForHistory());
507         }
508     }
509 }
510
511 bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem*) const
512 {
513     return true;
514 }
515
516 PassRefPtr<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
517 {
518     RefPtr<WebDocumentLoader> loader = WebDocumentLoader::create(request, substituteData);
519
520     COMPtr<WebDataSource> dataSource(AdoptCOM, WebDataSource::createInstance(loader.get()));
521
522     loader->setDataSource(dataSource.get());
523     return loader.release();
524 }
525
526 void WebFrameLoaderClient::setTitle(const String& title, const KURL& url)
527 {
528     BOOL privateBrowsingEnabled = FALSE;
529     COMPtr<IWebPreferences> preferences;
530     if (SUCCEEDED(m_webFrame->webView()->preferences(&preferences)))
531         preferences->privateBrowsingEnabled(&privateBrowsingEnabled);
532     if (privateBrowsingEnabled)
533         return;
534
535     // update title in global history
536     COMPtr<WebHistory> history = webHistory();
537     if (!history)
538         return;
539
540     COMPtr<IWebHistoryItem> item;
541     if (FAILED(history->itemForURL(BString(url.string()), &item)))
542         return;
543
544     COMPtr<IWebHistoryItemPrivate> itemPrivate(Query, item);
545     if (!itemPrivate)
546         return;
547
548     itemPrivate->setTitle(BString(title));
549 }
550
551 void WebFrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame)
552 {
553 #if USE(CFNETWORK)
554     Frame* coreFrame = core(m_webFrame);
555     if (!coreFrame)
556         return;
557
558     ASSERT(coreFrame->loader()->documentLoader() == cachedFrame->documentLoader());
559
560     WebCachedFramePlatformData* webPlatformData = new WebCachedFramePlatformData(static_cast<IWebDataSource*>(getWebDataSource(coreFrame->loader()->documentLoader())));
561     cachedFrame->setCachedFramePlatformData(webPlatformData);
562 #else
563     notImplemented();
564 #endif
565 }
566
567 void WebFrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame*)
568 {
569 }
570
571 void WebFrameLoaderClient::transitionToCommittedForNewPage()
572 {
573     WebView* view = m_webFrame->webView();
574
575     RECT rect;
576     view->frameRect(&rect);
577     bool transparent = view->transparent();
578     Color backgroundColor = transparent ? Color::transparent : Color::white;
579     core(m_webFrame)->createView(IntRect(rect).size(), backgroundColor, transparent, IntSize(), false);
580 }
581
582 bool WebFrameLoaderClient::canCachePage() const
583 {
584     return true;
585 }
586
587 PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
588                             const String& referrer, bool /*allowsScrolling*/, int /*marginWidth*/, int /*marginHeight*/)
589 {
590     RefPtr<Frame> result = createFrame(url, name, ownerElement, referrer);
591     if (!result)
592         return 0;
593     return result.release();
594 }
595
596 PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& URL, const String& name, HTMLFrameOwnerElement* ownerElement, const String& referrer)
597 {
598     Frame* coreFrame = core(m_webFrame);
599     ASSERT(coreFrame);
600
601     COMPtr<WebFrame> webFrame(AdoptCOM, WebFrame::createInstance());
602
603     RefPtr<Frame> childFrame = webFrame->init(m_webFrame->webView(), coreFrame->page(), ownerElement);
604
605     coreFrame->tree()->appendChild(childFrame);
606     childFrame->tree()->setName(name);
607     childFrame->init();
608
609     loadURLIntoChild(URL, referrer, webFrame.get());
610
611     // The frame's onload handler may have removed it from the document.
612     if (!childFrame->tree()->parent())
613         return 0;
614
615     return childFrame.release();
616 }
617
618 void WebFrameLoaderClient::loadURLIntoChild(const KURL& originalURL, const String& referrer, WebFrame* childFrame)
619 {
620     ASSERT(childFrame);
621     ASSERT(core(childFrame));
622
623     Frame* coreFrame = core(m_webFrame);
624     ASSERT(coreFrame);
625
626     HistoryItem* parentItem = coreFrame->loader()->currentHistoryItem();
627     FrameLoadType loadType = coreFrame->loader()->loadType();
628     FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedBackForwardList;
629
630     KURL url = originalURL;
631
632     // If we're moving in the backforward list, we might want to replace the content
633     // of this child frame with whatever was there at that point.
634     // Reload will maintain the frame contents, LoadSame will not.
635     if (parentItem && parentItem->children().size() && isBackForwardLoadType(loadType)) {
636         if (HistoryItem* childItem = parentItem->childItemWithName(core(childFrame)->tree()->name())) {
637             // Use the original URL to ensure we get all the side-effects, such as
638             // onLoad handlers, of any redirects that happened. An example of where
639             // this is needed is Radar 3213556.
640             url = childItem->originalURL();
641             // These behaviors implied by these loadTypes should apply to the child frames
642             childLoadType = loadType;
643
644             if (isBackForwardLoadType(loadType))
645                 // For back/forward, remember this item so we can traverse any child items as child frames load
646                 core(childFrame)->loader()->setProvisionalHistoryItem(childItem);
647             else
648                 // For reload, just reinstall the current item, since a new child frame was created but we won't be creating a new BF item
649                 core(childFrame)->loader()->setCurrentHistoryItem(childItem);
650         }
651     }
652
653     // FIXME: Handle loading WebArchives here
654     String frameName = core(childFrame)->tree()->name();
655     core(childFrame)->loader()->loadURL(url, referrer, frameName, false, childLoadType, 0, 0);
656 }
657
658 Widget* WebFrameLoaderClient::createPlugin(const IntSize& pluginSize, HTMLPlugInElement* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
659 {
660     WebView* webView = m_webFrame->webView();
661
662     COMPtr<IWebUIDelegate> ui;
663     if (SUCCEEDED(webView->uiDelegate(&ui)) && ui) {
664         COMPtr<IWebUIDelegatePrivate4> uiPrivate(Query, ui);
665
666         if (uiPrivate) {
667             // Assemble the view arguments in a property bag.
668             HashMap<String, String> viewArguments;
669             for (unsigned i = 0; i < paramNames.size(); i++) 
670                 viewArguments.set(paramNames[i], paramValues[i]);
671             COMPtr<IPropertyBag> viewArgumentsBag(AdoptCOM, COMPropertyBag<String>::adopt(viewArguments));
672             COMPtr<IDOMElement> containingElement(AdoptCOM, DOMElement::createInstance(element));
673
674             HashMap<String, COMVariant> arguments;
675
676             arguments.set(WebEmbeddedViewAttributesKey, viewArgumentsBag);
677             arguments.set(WebEmbeddedViewBaseURLKey, url.string());
678             arguments.set(WebEmbeddedViewContainingElementKey, containingElement);
679             arguments.set(WebEmbeddedViewMIMETypeKey, mimeType);
680
681             COMPtr<IPropertyBag> argumentsBag(AdoptCOM, COMPropertyBag<COMVariant>::adopt(arguments));
682
683             COMPtr<IWebEmbeddedView> view;
684             HRESULT result = uiPrivate->embeddedViewWithArguments(webView, m_webFrame, argumentsBag.get(), &view);
685             if (SUCCEEDED(result)) {
686                 HWND parentWindow;
687                 HRESULT hr = webView->viewWindow((OLE_HANDLE*)&parentWindow);
688                 ASSERT(SUCCEEDED(hr));
689
690                 return EmbeddedWidget::create(view.get(), element, parentWindow, pluginSize);
691             }
692         }
693     }
694
695     Frame* frame = core(m_webFrame);
696     PluginView* pluginView = PluginView::create(frame, pluginSize, element, url, paramNames, paramValues, mimeType, loadManually);
697
698     if (pluginView->status() == PluginStatusLoadedSuccessfully)
699         return pluginView;
700
701     COMPtr<IWebResourceLoadDelegate> resourceLoadDelegate;
702
703     if (FAILED(webView->resourceLoadDelegate(&resourceLoadDelegate)))
704         return pluginView;
705
706     RetainPtr<CFMutableDictionaryRef> userInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
707
708     unsigned count = (unsigned)paramNames.size();
709     for (unsigned i = 0; i < count; i++) {
710         if (paramNames[i] == "pluginspage") {
711             static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorPlugInPageURLStringKey);
712             RetainPtr<CFStringRef> str(AdoptCF, paramValues[i].createCFString());
713             CFDictionarySetValue(userInfo.get(), key, str.get());
714             break;
715         }
716     }
717
718     if (!mimeType.isNull()) {
719         static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorMIMETypeKey);
720
721         RetainPtr<CFStringRef> str(AdoptCF, mimeType.createCFString());
722         CFDictionarySetValue(userInfo.get(), key, str.get());
723     }
724
725     String pluginName;
726     if (pluginView->plugin())
727         pluginName = pluginView->plugin()->name();
728     if (!pluginName.isNull()) {
729         static CFStringRef key = MarshallingHelpers::LPCOLESTRToCFStringRef(WebKitErrorPlugInNameKey);
730         RetainPtr<CFStringRef> str(AdoptCF, pluginName.createCFString());
731         CFDictionarySetValue(userInfo.get(), key, str.get());
732     }
733
734     COMPtr<CFDictionaryPropertyBag> userInfoBag(AdoptCOM, CFDictionaryPropertyBag::createInstance());
735     userInfoBag->setDictionary(userInfo.get());
736  
737     int errorCode = 0;
738     switch (pluginView->status()) {
739         case PluginStatusCanNotFindPlugin:
740             errorCode = WebKitErrorCannotFindPlugIn;
741             break;
742         case PluginStatusCanNotLoadPlugin:
743             errorCode = WebKitErrorCannotLoadPlugIn;
744             break;
745         default:
746             ASSERT_NOT_REACHED();
747     }
748
749     ResourceError resourceError(String(WebKitErrorDomain), errorCode, url.string(), String());
750     COMPtr<IWebError> error(AdoptCOM, WebError::createInstance(resourceError, userInfoBag.get()));
751      
752     resourceLoadDelegate->plugInFailedWithError(webView, error.get(), getWebDataSource(frame->loader()->documentLoader()));
753
754     return pluginView;
755 }
756
757 void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
758 {
759     // Ideally, this function shouldn't be necessary, see <rdar://problem/4852889>
760
761     if (pluginWidget->isPluginView())
762         m_manualLoader = static_cast<PluginView*>(pluginWidget);
763     else 
764         m_manualLoader = static_cast<EmbeddedWidget*>(pluginWidget);
765 }
766
767 WebHistory* WebFrameLoaderClient::webHistory() const
768 {
769     if (m_webFrame != m_webFrame->webView()->topLevelFrame())
770         return 0;
771
772     return WebHistory::sharedHistory();
773 }
774
775 bool WebFrameLoaderClient::shouldUsePluginDocument(const String& mimeType) const
776 {
777     WebView* webView = m_webFrame->webView();
778     if (!webView)
779         return false;
780
781     return webView->shouldUseEmbeddedView(mimeType);
782 }