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