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