[Qt] Simplify QT_VERSION_CHECKS for Qt5 by introducing HAVE(QT5)
[WebKit-https.git] / Source / WebKit / qt / WebCoreSupport / FrameLoaderClientQt.cpp
1 /*
2  * Copyright (C) 2006 Zack Rusin <zack@kde.org>
3  * Copyright (C) 2006, 2011 Apple Inc. All rights reserved.
4  * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
5  * Copyright (C) 2008 Collabora Ltd. All rights reserved.
6  * Coypright (C) 2008 Holger Hans Peter Freyther
7  * Coypright (C) 2009, 2010 Girish Ramakrishnan <girish@forwardbias.in>
8  *
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
21  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
28  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "config.h"
34 #include "FrameLoaderClientQt.h"
35
36 #include "CSSComputedStyleDeclaration.h"
37 #include "CSSPropertyNames.h"
38 #include "DocumentLoader.h"
39 #include "FormState.h"
40 #include "FrameNetworkingContextQt.h"
41 #include "FrameTree.h"
42 #include "FrameView.h"
43 #include "HTMLAppletElement.h"
44 #include "HTMLFormElement.h"
45 #include "HTMLPlugInElement.h"
46 #include "HTTPParsers.h"
47 #include "HTTPStatusCodes.h"
48 #include "HistoryItem.h"
49 #include "HitTestResult.h"
50 #if ENABLE(ICONDATABASE)
51 #include "IconDatabaseClientQt.h"
52 #endif
53 #if USE(JSC)
54 #include "JSDOMWindowBase.h"
55 #endif
56 #include "MIMETypeRegistry.h"
57 #include "MouseEvent.h"
58 #include "NotImplemented.h"
59 #include "Page.h"
60 #include "PluginData.h"
61 #include "PluginDatabase.h"
62 #include "ProgressTracker.h"
63 #include "QNetworkReplyHandler.h"
64 #include "QWebPageClient.h"
65 #include "RenderPart.h"
66 #include "ResourceHandle.h"
67 #include "ResourceHandleInternal.h"
68 #include "ResourceRequest.h"
69 #include "ResourceResponse.h"
70 #include "ScriptController.h"
71 #include "Settings.h"
72 #if USE(V8)
73 #include "V8DOMWindow.h"
74 #endif
75 #include "ViewportArguments.h"
76 #include "WebEventConversion.h"
77
78 #include "qwebframe.h"
79 #include "qwebframe_p.h"
80 #include "qwebhistory_p.h"
81 #include "qwebhistoryinterface.h"
82 #include "qwebpage.h"
83 #include "qwebpage_p.h"
84 #include "qwebpluginfactory.h"
85
86 #include <QCoreApplication>
87 #include <QDebug>
88 #include <QFileInfo>
89 #include <QGraphicsScene>
90 #include <QGraphicsWidget>
91 #include <QNetworkReply>
92 #include <QNetworkRequest>
93 #include <QStringList>
94 #include <wtf/OwnPtr.h>
95
96 static QMap<unsigned long, QString> dumpAssignedUrls;
97
98 // Compare with the file "WebKit/Tools/DumpRenderTree/mac/FrameLoadDelegate.mm".
99 static QString drtDescriptionSuitableForTestResult(WebCore::Frame* webCoreFrame)
100 {
101     QWebFrame* frame = QWebFramePrivate::kit(webCoreFrame);
102     QString name = frame->frameName();
103
104     bool isMainFrame = frame == frame->page()->mainFrame();
105     if (isMainFrame) {
106         if (!name.isEmpty())
107             return QString::fromLatin1("main frame \"%1\"").arg(name);
108         return QLatin1String("main frame");
109     }
110     if (!name.isEmpty())
111         return QString::fromLatin1("frame \"%1\"").arg(name);
112     return QLatin1String("frame (anonymous)");
113 }
114
115 static QString drtPrintFrameUserGestureStatus(WebCore::Frame* frame)
116 {
117     if (WebCore::ScriptController::processingUserGesture())
118         return QString::fromLatin1("Frame with user gesture \"%1\"").arg(QLatin1String("true"));
119     return QString::fromLatin1("Frame with user gesture \"%1\"").arg(QLatin1String("false"));
120 }
121
122 static QString drtDescriptionSuitableForTestResult(const WebCore::KURL& kurl)
123 {
124     if (kurl.isEmpty() || !kurl.isLocalFile())
125         return kurl.string();
126     // Remove the leading path from file urls.
127     return QString(kurl.string()).remove(WebCore::FrameLoaderClientQt::dumpResourceLoadCallbacksPath).mid(1);
128 }
129
130 static QString drtDescriptionSuitableForTestResult(const WebCore::ResourceError& error)
131 {
132     QString failingURL = error.failingURL();
133     return QString::fromLatin1("<NSError domain NSURLErrorDomain, code %1, failing URL \"%2\">").arg(error.errorCode()).arg(failingURL);
134 }
135
136 static QString drtDescriptionSuitableForTestResult(const WebCore::ResourceRequest& request)
137 {
138     QString url = drtDescriptionSuitableForTestResult(request.url());
139     QString httpMethod = request.httpMethod();
140     QString mainDocumentUrl = drtDescriptionSuitableForTestResult(request.firstPartyForCookies());
141     return QString::fromLatin1("<NSURLRequest URL %1, main document URL %2, http method %3>").arg(url).arg(mainDocumentUrl).arg(httpMethod);
142 }
143
144 static QString drtDescriptionSuitableForTestResult(const WebCore::ResourceResponse& response)
145 {
146     QString url = drtDescriptionSuitableForTestResult(response.url());
147     int httpStatusCode = response.httpStatusCode();
148     return QString::fromLatin1("<NSURLResponse %1, http status code %2>").arg(url).arg(httpStatusCode);
149 }
150
151 static QString drtDescriptionSuitableForTestResult(const RefPtr<WebCore::Node> node, int exception)
152 {
153     QString result;
154     if (exception) {
155         result.append(QLatin1String("ERROR"));
156         return result;
157     }
158     if (!node) {
159         result.append(QLatin1String("NULL"));
160         return result;
161     }
162     result.append(node->nodeName());
163     RefPtr<WebCore::Node> parent = node->parentNode();
164     if (parent) {
165         result.append(QLatin1String(" > "));
166         result.append(drtDescriptionSuitableForTestResult(parent, 0));
167     }
168     return result;
169 }
170
171 namespace WebCore {
172
173 bool FrameLoaderClientQt::dumpFrameLoaderCallbacks = false;
174 bool FrameLoaderClientQt::dumpProgressFinishedCallback = false;
175 bool FrameLoaderClientQt::dumpUserGestureInFrameLoaderCallbacks = false;
176 bool FrameLoaderClientQt::dumpWillCacheResponseCallbacks = false;
177 bool FrameLoaderClientQt::dumpResourceLoadCallbacks = false;
178 bool FrameLoaderClientQt::sendRequestReturnsNullOnRedirect = false;
179 bool FrameLoaderClientQt::sendRequestReturnsNull = false;
180 bool FrameLoaderClientQt::dumpResourceResponseMIMETypes = false;
181 bool FrameLoaderClientQt::deferMainResourceDataLoad = true;
182 bool FrameLoaderClientQt::dumpHistoryCallbacks = false;
183
184 QStringList FrameLoaderClientQt::sendRequestClearHeaders;
185 QString FrameLoaderClientQt::dumpResourceLoadCallbacksPath;
186 bool FrameLoaderClientQt::policyDelegateEnabled = false;
187 bool FrameLoaderClientQt::policyDelegatePermissive = false;
188 QMap<QString, QString> FrameLoaderClientQt::URLsToRedirect = QMap<QString, QString>();
189
190 // Taken from the file "WebKit/Tools/DumpRenderTree/chromium/WebViewHost.cpp".
191 static const char* navigationTypeToString(NavigationType type)
192 {
193     switch (type) {
194     case NavigationTypeLinkClicked:
195         return "link clicked";
196     case NavigationTypeFormSubmitted:
197         return "form submitted";
198     case NavigationTypeBackForward:
199         return "back/forward";
200     case NavigationTypeReload:
201         return "reload";
202     case NavigationTypeFormResubmitted:
203         return "form resubmitted";
204     case NavigationTypeOther:
205         return "other";
206     }
207     return "illegal value";
208 }
209
210 FrameLoaderClientQt::FrameLoaderClientQt()
211     : m_frame(0)
212     , m_webFrame(0)
213     , m_pluginView(0)
214     , m_hasSentResponseToPlugin(false)
215     , m_isOriginatingLoad(false)
216 {
217 }
218
219
220 FrameLoaderClientQt::~FrameLoaderClientQt()
221 {
222 }
223
224 void FrameLoaderClientQt::setFrame(QWebFrame* webFrame, Frame* frame)
225 {
226     m_webFrame = webFrame;
227     m_frame = frame;
228
229     if (!m_webFrame || !m_webFrame->page()) {
230         qWarning("FrameLoaderClientQt::setFrame frame without Page!");
231         return;
232     }
233
234     connect(this, SIGNAL(loadProgress(int)),
235             m_webFrame->page(), SIGNAL(loadProgress(int)));
236
237     connect(this, SIGNAL(unsupportedContent(QNetworkReply*)),
238             m_webFrame->page(), SIGNAL(unsupportedContent(QNetworkReply*)));
239
240     connect(this, SIGNAL(titleChanged(QString)),
241             m_webFrame, SIGNAL(titleChanged(QString)));
242 }
243
244 void FrameLoaderClientQt::callPolicyFunction(FramePolicyFunction function, PolicyAction action)
245 {
246     (m_frame->loader()->policyChecker()->*function)(action);
247 }
248
249 bool FrameLoaderClientQt::hasWebView() const
250 {
251     // notImplemented();
252     return true;
253 }
254
255 void FrameLoaderClientQt::savePlatformDataToCachedFrame(CachedFrame*) 
256 {
257     notImplemented();
258 }
259
260 void FrameLoaderClientQt::transitionToCommittedFromCachedFrame(CachedFrame*)
261 {
262 }
263
264 void FrameLoaderClientQt::transitionToCommittedForNewPage()
265 {
266     ASSERT(m_frame);
267     ASSERT(m_webFrame);
268
269     QBrush brush = m_webFrame->page()->palette().brush(QPalette::Base);
270     QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor();
271
272     QWebPage* page = m_webFrame->page();
273     const QSize preferredLayoutSize = page->preferredContentsSize();
274
275     ScrollbarMode hScrollbar = (ScrollbarMode) m_webFrame->scrollBarPolicy(Qt::Horizontal);
276     ScrollbarMode vScrollbar = (ScrollbarMode) m_webFrame->scrollBarPolicy(Qt::Vertical);
277     bool hLock = hScrollbar != ScrollbarAuto;
278     bool vLock = vScrollbar != ScrollbarAuto;
279
280     IntSize currentVisibleContentSize = m_frame->view() ? m_frame->view()->visibleContentRect().size() : IntSize();
281
282     m_frame->createView(m_webFrame->page()->viewportSize(),
283                         backgroundColor, !backgroundColor.alpha(),
284                         preferredLayoutSize.isValid() ? IntSize(preferredLayoutSize) : IntSize(),
285                         preferredLayoutSize.isValid(),
286                         hScrollbar, hLock,
287                         vScrollbar, vLock);
288
289     bool isMainFrame = m_frame == m_frame->page()->mainFrame();
290     if (isMainFrame && page->d->client) {
291         bool resizesToContents = page->d->client->viewResizesToContentsEnabled();
292
293         m_frame->view()->setPaintsEntireContents(resizesToContents);
294         m_frame->view()->setDelegatesScrolling(resizesToContents);
295
296         // The HistoryController will update the scroll position later if needed.
297         IntRect rect = resizesToContents ? IntRect(IntPoint::zero(), currentVisibleContentSize) : IntRect();
298         m_frame->view()->setFixedVisibleContentRect(rect);
299     }
300 }
301
302 void FrameLoaderClientQt::didSaveToPageCache()
303 {
304 }
305
306 void FrameLoaderClientQt::didRestoreFromPageCache()
307 {
308 }
309
310 void FrameLoaderClientQt::dispatchDidBecomeFrameset(bool)
311 {
312 }
313
314
315 void FrameLoaderClientQt::forceLayout()
316 {
317     FrameView* view = m_frame->view();
318     if (view)
319         view->layout(true);
320 }
321
322
323 void FrameLoaderClientQt::forceLayoutForNonHTML()
324 {
325 }
326
327
328 void FrameLoaderClientQt::setCopiesOnScroll()
329 {
330     // Apparently this is mac specific.
331 }
332
333
334 void FrameLoaderClientQt::detachedFromParent2()
335 {
336 }
337
338
339 void FrameLoaderClientQt::detachedFromParent3()
340 {
341 }
342
343 void FrameLoaderClientQt::dispatchDidHandleOnloadEvents()
344 {
345     // Don't need this one.
346     if (dumpFrameLoaderCallbacks)
347         printf("%s - didHandleOnloadEventsForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
348 }
349
350
351 void FrameLoaderClientQt::dispatchDidReceiveServerRedirectForProvisionalLoad()
352 {
353     if (dumpFrameLoaderCallbacks)
354         printf("%s - didReceiveServerRedirectForProvisionalLoadForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
355
356     notImplemented();
357 }
358
359
360 void FrameLoaderClientQt::dispatchDidCancelClientRedirect()
361 {
362     if (dumpFrameLoaderCallbacks)
363         printf("%s - didCancelClientRedirectForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
364
365     notImplemented();
366 }
367
368
369 void FrameLoaderClientQt::dispatchWillPerformClientRedirect(const KURL& url, double, double)
370 {
371     if (dumpFrameLoaderCallbacks)
372         printf("%s - willPerformClientRedirectToURL: %s \n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)), qPrintable(drtDescriptionSuitableForTestResult(url)));
373
374     if (dumpUserGestureInFrameLoaderCallbacks)
375         printf("%s - in willPerformClientRedirect\n", qPrintable(drtPrintFrameUserGestureStatus(m_frame)));
376
377     notImplemented();
378 }
379
380
381 void FrameLoaderClientQt::dispatchDidChangeLocationWithinPage()
382 {
383     if (dumpFrameLoaderCallbacks)
384         printf("%s - didChangeLocationWithinPageForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
385
386     if (!m_webFrame)
387         return;
388
389     m_webFrame->d->emitUrlChanged();
390     m_webFrame->page()->d->updateNavigationActions();
391 }
392
393 #if USE(V8)
394 void FrameLoaderClientQt::didCreateScriptContext(v8::Handle<v8::Context>, int, int)
395 {
396 }
397 void FrameLoaderClientQt::willReleaseScriptContext(v8::Handle<v8::Context>, int)
398 {
399 }
400 void FrameLoaderClientQt::didCreateIsolatedScriptContext()
401 {
402 }
403 #endif
404
405 void FrameLoaderClientQt::dispatchDidPushStateWithinPage()
406 {
407     if (dumpFrameLoaderCallbacks)
408         printf("%s - dispatchDidPushStateWithinPage\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
409
410     notImplemented();
411 }
412
413 void FrameLoaderClientQt::dispatchDidReplaceStateWithinPage()
414 {
415     if (dumpFrameLoaderCallbacks)
416         printf("%s - dispatchDidReplaceStateWithinPage\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
417
418     notImplemented();
419 }
420
421 void FrameLoaderClientQt::dispatchDidPopStateWithinPage()
422 {
423     if (dumpFrameLoaderCallbacks)
424         printf("%s - dispatchDidPopStateWithinPage\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
425
426     notImplemented();
427 }
428
429 void FrameLoaderClientQt::dispatchWillClose()
430 {
431 }
432
433
434 void FrameLoaderClientQt::dispatchDidStartProvisionalLoad()
435 {
436     if (dumpFrameLoaderCallbacks)
437         printf("%s - didStartProvisionalLoadForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
438
439     if (dumpUserGestureInFrameLoaderCallbacks)
440         printf("%s - in didStartProvisionalLoadForFrame\n", qPrintable(drtPrintFrameUserGestureStatus(m_frame)));
441
442     m_lastRequestedUrl = m_frame->loader()->activeDocumentLoader()->requestURL();
443
444     if (!m_webFrame)
445         return;
446     emitLoadStarted();
447     postProgressEstimateChangedNotification();
448     emit m_webFrame->provisionalLoad();
449 }
450
451
452 void FrameLoaderClientQt::dispatchDidReceiveTitle(const StringWithDirection& title)
453 {
454     // FIXME: Use direction of title.
455     if (dumpFrameLoaderCallbacks)
456         printf("%s - didReceiveTitle: %s\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)), qPrintable(QString(title.string())));
457
458     if (!m_webFrame)
459         return;
460
461     emit titleChanged(title.string());
462 }
463
464
465 void FrameLoaderClientQt::dispatchDidChangeIcons(WebCore::IconType)
466 {
467     if (dumpFrameLoaderCallbacks)
468         printf("%s - didChangeIcons\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
469
470     if (!m_webFrame)
471         return;
472
473     // FIXME: In order to get notified of icon URLS' changes, add a notification.
474     // emit iconsChanged();
475 }
476
477
478 void FrameLoaderClientQt::dispatchDidCommitLoad()
479 {
480     if (dumpFrameLoaderCallbacks)
481         printf("%s - didCommitLoadForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
482
483     if (m_frame->tree()->parent() || !m_webFrame)
484         return;
485
486     m_webFrame->d->emitUrlChanged();
487     m_webFrame->page()->d->updateNavigationActions();
488
489     // We should assume first the frame has no title. If it has, then the above dispatchDidReceiveTitle()
490     // will be called very soon with the correct title.
491     // This properly resets the title when we navigate to a URI without a title.
492     emit titleChanged(QString());
493
494     bool isMainFrame = (m_frame == m_frame->page()->mainFrame());
495     if (!isMainFrame)
496         return;
497
498     emit m_webFrame->page()->viewportChangeRequested();
499 }
500
501
502 void FrameLoaderClientQt::dispatchDidFinishDocumentLoad()
503 {
504     if (dumpFrameLoaderCallbacks)
505         printf("%s - didFinishDocumentLoadForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
506
507     if (QWebPagePrivate::drtRun) {
508         int unloadEventCount = m_frame->domWindow()->pendingUnloadEventListeners();
509         if (unloadEventCount)
510             printf("%s - has %u onunload handler(s)\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)), unloadEventCount);
511     }
512
513     if (m_frame->tree()->parent() || !m_webFrame)
514         return;
515
516     m_webFrame->page()->d->updateNavigationActions();
517 }
518
519
520 void FrameLoaderClientQt::dispatchDidFinishLoad()
521 {
522     if (dumpFrameLoaderCallbacks)
523         printf("%s - didFinishLoadForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
524
525     if (!m_webFrame)
526         return;
527
528     m_webFrame->page()->d->updateNavigationActions();
529     emitLoadFinished(true);
530 }
531
532
533 void FrameLoaderClientQt::dispatchDidFirstLayout()
534 {
535 }
536
537 void FrameLoaderClientQt::dispatchDidFirstVisuallyNonEmptyLayout()
538 {
539     if (m_webFrame)
540         emit m_webFrame->initialLayoutCompleted();
541 }
542
543 void FrameLoaderClientQt::dispatchShow()
544 {
545     notImplemented();
546 }
547
548
549 void FrameLoaderClientQt::cancelPolicyCheck()
550 {
551     // qDebug() << "FrameLoaderClientQt::cancelPolicyCheck";
552 }
553
554
555 void FrameLoaderClientQt::dispatchWillSubmitForm(FramePolicyFunction function,
556                                                  PassRefPtr<FormState>)
557 {
558     notImplemented();
559     // FIXME: This is surely too simple.
560     callPolicyFunction(function, PolicyUse);
561 }
562
563
564 void FrameLoaderClientQt::postProgressStartedNotification()
565 {
566     if (m_webFrame && m_frame->page())
567         m_isOriginatingLoad = true;
568     if (m_frame->tree()->parent() || !m_webFrame)
569         return;
570     m_webFrame->page()->d->updateNavigationActions();
571 }
572
573 void FrameLoaderClientQt::postProgressEstimateChangedNotification()
574 {
575     if (m_webFrame && m_frame->page())
576         emit loadProgress(qRound(m_frame->page()->progress()->estimatedProgress() * 100));
577 }
578
579 void FrameLoaderClientQt::postProgressFinishedNotification()
580 {
581     if (dumpProgressFinishedCallback)
582         printf("postProgressFinishedNotification\n");
583
584     // Send a mousemove event to:
585     // (1) update the cursor to change according to whatever is underneath the mouse cursor right now;
586     // (2) display the tool tip if the mouse hovers a node which has a tool tip.
587     if (m_frame && m_frame->eventHandler() && m_webFrame->page()) {
588         QWidget* view = m_webFrame->page()->view();
589         if (view && view->hasFocus()) {
590             QPoint localPos = view->mapFromGlobal(QCursor::pos());
591             if (view->rect().contains(localPos)) {
592                 QMouseEvent event(QEvent::MouseMove, localPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier);
593                 m_frame->eventHandler()->mouseMoved(convertMouseEvent(&event, 0));
594             }
595         }
596     }
597 }
598
599 void FrameLoaderClientQt::setMainFrameDocumentReady(bool)
600 {
601     // This is only interesting once we provide an external API for the DOM.
602 }
603
604
605 void FrameLoaderClientQt::willChangeTitle(DocumentLoader*)
606 {
607     // No need for, dispatchDidReceiveTitle is the right callback.
608 }
609
610
611 void FrameLoaderClientQt::didChangeTitle(DocumentLoader*)
612 {
613     // No need for, dispatchDidReceiveTitle is the right callback.
614 }
615
616
617 void FrameLoaderClientQt::finishedLoading(DocumentLoader*)
618 {
619     if (!m_pluginView)
620         return;
621     if (m_pluginView->isPluginView())
622         m_pluginView->didFinishLoading();
623     m_pluginView = 0;
624     m_hasSentResponseToPlugin = false;
625 }
626
627 bool FrameLoaderClientQt::canShowMIMETypeAsHTML(const String& MIMEType) const
628 {
629     notImplemented();
630     return false;
631 }
632     
633 bool FrameLoaderClientQt::canShowMIMEType(const String& MIMEType) const
634 {
635     String type = MIMEType;
636     type.makeLower();
637     if (MIMETypeRegistry::isSupportedImageMIMEType(type))
638         return true;
639
640     if (MIMETypeRegistry::isSupportedNonImageMIMEType(type))
641         return true;
642
643     if (MIMETypeRegistry::isSupportedMediaMIMEType(type))
644         return true;
645
646     if (m_frame && m_frame->settings()  && m_frame->settings()->arePluginsEnabled()
647         && PluginDatabase::installedPlugins()->isMIMETypeRegistered(type))
648         return true;
649
650     return false;
651 }
652
653 bool FrameLoaderClientQt::representationExistsForURLScheme(const String&) const
654 {
655     return false;
656 }
657
658
659 String FrameLoaderClientQt::generatedMIMETypeForURLScheme(const String&) const
660 {
661     notImplemented();
662     return String();
663 }
664
665
666 void FrameLoaderClientQt::frameLoadCompleted()
667 {
668     // Note that this can be called multiple times.
669     if (!m_webFrame)
670         return;
671     m_webFrame->page()->d->updateNavigationActions();
672 }
673
674
675 void FrameLoaderClientQt::restoreViewState()
676 {
677     if (!m_webFrame)
678         return;
679     emit m_webFrame->page()->restoreFrameStateRequested(m_webFrame);
680 }
681
682
683 void FrameLoaderClientQt::provisionalLoadStarted()
684 {
685     // Don't need to do anything here.
686 }
687
688
689 void FrameLoaderClientQt::didFinishLoad()
690 {
691     // notImplemented();
692 }
693
694
695 void FrameLoaderClientQt::prepareForDataSourceReplacement()
696 {
697 }
698
699 void FrameLoaderClientQt::setTitle(const StringWithDirection& title, const KURL& url)
700 {
701     // Used by Apple WebKit to update the title of an existing history item.
702     // QtWebKit doesn't accomodate this on history items. If it ever does,
703     // it should be privateBrowsing-aware. For now, we are just passing
704     // globalhistory layout tests.
705     // FIXME: Use direction of title.
706     if (dumpHistoryCallbacks) {
707         printf("WebView updated the title for history URL \"%s\" to \"%s\".\n",
708             qPrintable(drtDescriptionSuitableForTestResult(url)),
709             qPrintable(QString(title.string())));
710     }
711 }
712
713
714 String FrameLoaderClientQt::userAgent(const KURL& url)
715 {
716     if (m_webFrame) {
717         return m_webFrame->page()->userAgentForUrl(url).remove(QLatin1Char('\n')).remove(QLatin1Char('\r'));
718     }
719     return String();
720 }
721
722 void FrameLoaderClientQt::dispatchDidReceiveIcon()
723 {
724     if (m_webFrame)
725         emit m_webFrame->iconChanged();
726 }
727
728 void FrameLoaderClientQt::frameLoaderDestroyed()
729 {
730     delete m_webFrame;
731     m_frame = 0;
732     m_webFrame = 0;
733
734     delete this;
735 }
736
737 bool FrameLoaderClientQt::canHandleRequest(const WebCore::ResourceRequest&) const
738 {
739     return true;
740 }
741
742 void FrameLoaderClientQt::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world)
743 {
744     if (world != mainThreadNormalWorld())
745         return;
746
747     if (m_webFrame)
748         m_webFrame->d->didClearWindowObject();
749 }
750
751 void FrameLoaderClientQt::documentElementAvailable()
752 {
753     return;
754 }
755
756 void FrameLoaderClientQt::didPerformFirstNavigation() const
757 {
758     if (m_frame->tree()->parent() || !m_webFrame)
759         return;
760     m_webFrame->page()->d->updateNavigationActions();
761 }
762
763 void FrameLoaderClientQt::registerForIconNotification(bool shouldRegister)
764 {
765 #if ENABLE(ICONDATABASE)
766     if (shouldRegister)
767         connect(IconDatabaseClientQt::instance(), SIGNAL(iconLoadedForPageURL(QString)), this, SLOT(onIconLoadedForPageURL(QString)), Qt::UniqueConnection);
768     else
769         disconnect(IconDatabaseClientQt::instance(), SIGNAL(iconLoadedForPageURL(QString)), this, SLOT(onIconLoadedForPageURL(QString)));
770 #endif
771 }
772
773 void FrameLoaderClientQt::onIconLoadedForPageURL(const QString& url)
774 {
775 #if ENABLE(ICONDATABASE)
776     if (m_webFrame && m_webFrame->url() == url)
777         emit m_webFrame->iconChanged();
778 #endif
779 }
780
781
782 void FrameLoaderClientQt::updateGlobalHistory()
783 {
784     QWebHistoryInterface* history = QWebHistoryInterface::defaultInterface();
785     WebCore::DocumentLoader* loader = m_frame->loader()->documentLoader();
786     if (history)
787         history->addHistoryEntry(loader->urlForHistory().string());
788
789     if (dumpHistoryCallbacks) {
790         printf("WebView navigated to url \"%s\" with title \"%s\" with HTTP equivalent method \"%s\".  The navigation was %s and was %s%s.\n",
791             qPrintable(drtDescriptionSuitableForTestResult(loader->urlForHistory())),
792             qPrintable(QString(loader->title().string())),
793             qPrintable(QString(loader->request().httpMethod())),
794             ((loader->substituteData().isValid() || (loader->response().httpStatusCode() >= 400)) ? "a failure" : "successful"),
795             ((!loader->clientRedirectSourceForHistory().isEmpty()) ? "a client redirect from " : "not a client redirect"),
796             (!loader->clientRedirectSourceForHistory().isEmpty()) ? qPrintable(drtDescriptionSuitableForTestResult(loader->clientRedirectSourceForHistory())) : "");
797     }
798 }
799
800 void FrameLoaderClientQt::updateGlobalHistoryRedirectLinks()
801 {
802     // Apple WebKit is the only port that makes use of this callback. It calls
803     // WebCore::HistoryItem::addRedirectURL() with the contents of
804     // loader->[server|client]RedirectDestinationForHistory().
805     // WebCore can associate a bunch of redirect URLs with a particular
806     // item in the history, presumably this allows Safari to skip the redirections
807     // when navigating to that history item. That might be a feature Qt wants to
808     // offer through QWebHistoryInterface in the future. For now, we're just
809     // passing tests in LayoutTests/http/tests/globalhistory.
810     WebCore::DocumentLoader* loader = m_frame->loader()->documentLoader();
811
812     if (!loader->clientRedirectSourceForHistory().isNull()) {
813         if (dumpHistoryCallbacks) {
814             printf("WebView performed a client redirect from \"%s\" to \"%s\".\n",
815                   qPrintable(QString(loader->clientRedirectSourceForHistory())),
816                   qPrintable(QString(loader->clientRedirectDestinationForHistory())));
817         }
818     }
819
820     if (!loader->serverRedirectSourceForHistory().isNull()) {
821         if (dumpHistoryCallbacks) {
822             printf("WebView performed a server redirect from \"%s\" to \"%s\".\n",
823                   qPrintable(QString(loader->serverRedirectSourceForHistory())),
824                   qPrintable(QString(loader->serverRedirectDestinationForHistory())));
825         }
826     }
827 }
828
829 bool FrameLoaderClientQt::shouldGoToHistoryItem(WebCore::HistoryItem*) const
830 {
831     return true;
832 }
833
834 bool FrameLoaderClientQt::shouldStopLoadingForHistoryItem(WebCore::HistoryItem*) const
835 {
836     return true;
837 }
838
839 void FrameLoaderClientQt::didDisplayInsecureContent()
840 {
841     if (dumpFrameLoaderCallbacks)
842         printf("didDisplayInsecureContent\n");
843
844     notImplemented();
845 }
846
847 void FrameLoaderClientQt::didRunInsecureContent(WebCore::SecurityOrigin*, const KURL&)
848 {
849     if (dumpFrameLoaderCallbacks)
850         printf("didRunInsecureContent\n");
851
852     notImplemented();
853 }
854
855 void FrameLoaderClientQt::didDetectXSS(const KURL&, bool)
856 {
857     if (dumpFrameLoaderCallbacks)
858         printf("didDetectXSS\n");
859
860     notImplemented();
861 }
862
863 void FrameLoaderClientQt::saveViewStateToItem(WebCore::HistoryItem* item)
864 {
865     QWebHistoryItem historyItem(new QWebHistoryItemPrivate(item));
866     emit m_webFrame->page()->saveFrameStateRequested(m_webFrame, &historyItem);
867 }
868
869 bool FrameLoaderClientQt::canCachePage() const
870 {
871     return true;
872 }
873
874 void FrameLoaderClientQt::setMainDocumentError(WebCore::DocumentLoader* loader, const WebCore::ResourceError& error)
875 {
876     if (!m_pluginView)
877         return;
878     if (m_pluginView->isPluginView())
879         m_pluginView->didFail(error);
880     m_pluginView = 0;
881     m_hasSentResponseToPlugin = false;
882 }
883
884 // FIXME: This function should be moved into WebCore.
885 void FrameLoaderClientQt::committedLoad(WebCore::DocumentLoader* loader, const char* data, int length)
886 {
887     if (!m_pluginView)
888         loader->commitData(data, length);
889
890     // If we are sending data to MediaDocument, we should stop here and cancel the request.
891     if (m_frame->document()->isMediaDocument())
892         loader->cancelMainResourceLoad(pluginWillHandleLoadError(loader->response()));
893
894     // We re-check here as the plugin can have been created.
895     if (m_pluginView && m_pluginView->isPluginView()) {
896         if (!m_hasSentResponseToPlugin) {
897             m_pluginView->didReceiveResponse(loader->response());
898             // The function didReceiveResponse sets up a new stream to the plug-in.
899             // On a full-page plug-in, a failure in setting up this stream can cause the
900             // main document load to be cancelled, setting m_pluginView to null.
901             if (!m_pluginView)
902                 return;
903             m_hasSentResponseToPlugin = true;
904         }
905         m_pluginView->didReceiveData(data, length);
906     }
907 }
908
909 WebCore::ResourceError FrameLoaderClientQt::cancelledError(const WebCore::ResourceRequest& request)
910 {
911     ResourceError error = ResourceError("QtNetwork", QNetworkReply::OperationCanceledError, request.url().string(),
912             QCoreApplication::translate("QWebFrame", "Request cancelled", 0));
913     error.setIsCancellation(true);
914     return error;
915 }
916
917 // This was copied from file "WebKit/Source/WebKit/mac/Misc/WebKitErrors.h".
918 enum {
919     WebKitErrorCannotShowMIMEType =                             100,
920     WebKitErrorCannotShowURL =                                  101,
921     WebKitErrorFrameLoadInterruptedByPolicyChange =             102,
922     WebKitErrorCannotUseRestrictedPort =                        103,
923     WebKitErrorCannotFindPlugIn =                               200,
924     WebKitErrorCannotLoadPlugIn =                               201,
925     WebKitErrorJavaUnavailable =                                202,
926     WebKitErrorPluginWillHandleLoad =                           203
927 };
928
929 WebCore::ResourceError FrameLoaderClientQt::blockedError(const WebCore::ResourceRequest& request)
930 {
931     return ResourceError("WebKitErrorDomain", WebKitErrorCannotUseRestrictedPort, request.url().string(),
932             QCoreApplication::translate("QWebFrame", "Request blocked", 0));
933 }
934
935
936 WebCore::ResourceError FrameLoaderClientQt::cannotShowURLError(const WebCore::ResourceRequest& request)
937 {
938     return ResourceError("WebKitErrorDomain", WebKitErrorCannotShowURL, request.url().string(),
939             QCoreApplication::translate("QWebFrame", "Cannot show URL", 0));
940 }
941
942 WebCore::ResourceError FrameLoaderClientQt::interruptedForPolicyChangeError(const WebCore::ResourceRequest& request)
943 {
944     return ResourceError("WebKitErrorDomain", WebKitErrorFrameLoadInterruptedByPolicyChange, request.url().string(),
945             QCoreApplication::translate("QWebFrame", "Frame load interrupted by policy change", 0));
946 }
947
948 WebCore::ResourceError FrameLoaderClientQt::cannotShowMIMETypeError(const WebCore::ResourceResponse& response)
949 {
950     return ResourceError("WebKitErrorDomain", WebKitErrorCannotShowMIMEType, response.url().string(),
951             QCoreApplication::translate("QWebFrame", "Cannot show mimetype", 0));
952 }
953
954 WebCore::ResourceError FrameLoaderClientQt::fileDoesNotExistError(const WebCore::ResourceResponse& response)
955 {
956     return ResourceError("QtNetwork", QNetworkReply::ContentNotFoundError, response.url().string(),
957             QCoreApplication::translate("QWebFrame", "File does not exist", 0));
958 }
959
960 WebCore::ResourceError FrameLoaderClientQt::pluginWillHandleLoadError(const WebCore::ResourceResponse& response)
961 {
962     return ResourceError("WebKit", WebKitErrorPluginWillHandleLoad, response.url().string(),
963                          QCoreApplication::translate("QWebFrame", "Loading is handled by the media engine", 0));
964 }
965
966 bool FrameLoaderClientQt::shouldFallBack(const WebCore::ResourceError& error)
967 {
968     DEFINE_STATIC_LOCAL(const ResourceError, cancelledError, (this->cancelledError(ResourceRequest())));
969     DEFINE_STATIC_LOCAL(const ResourceError, pluginWillHandleLoadError, (this->pluginWillHandleLoadError(ResourceResponse())));
970     DEFINE_STATIC_LOCAL(const ResourceError, errorInterruptedForPolicyChange, (this->interruptedForPolicyChangeError(ResourceRequest())));
971
972     if (error.errorCode() == cancelledError.errorCode() && error.domain() == cancelledError.domain())
973         return false;
974
975     if (error.errorCode() == errorInterruptedForPolicyChange.errorCode() && error.domain() == errorInterruptedForPolicyChange.domain())
976         return false;
977
978     if (error.errorCode() == pluginWillHandleLoadError.errorCode() && error.domain() == pluginWillHandleLoadError.domain())
979         return false;
980
981     return true;
982 }
983
984 WTF::PassRefPtr<WebCore::DocumentLoader> FrameLoaderClientQt::createDocumentLoader(const WebCore::ResourceRequest& request, const SubstituteData& substituteData)
985 {
986     RefPtr<DocumentLoader> loader = DocumentLoader::create(request, substituteData);
987     if (!deferMainResourceDataLoad || substituteData.isValid()) {
988         loader->setDeferMainResourceDataLoad(false);
989         // Use the default timeout interval for JS as the HTML tokenizer delay. This ensures
990         // that long-running JavaScript will still allow setHtml() to be synchronous, while
991         // still giving a reasonable timeout to prevent deadlock.
992 #if USE(JSC)
993         double delay = JSDOMWindowBase::commonJSGlobalData()->timeoutChecker.timeoutInterval() / 1000.0f;
994 #elif USE(V8)
995         // FIXME: Hard coded for now.
996         double delay = 10000 / 1000.0f;
997 #endif
998         m_frame->page()->setCustomHTMLTokenizerTimeDelay(delay);
999     } else
1000         m_frame->page()->setCustomHTMLTokenizerTimeDelay(-1);
1001     return loader.release();
1002 }
1003
1004 void FrameLoaderClientQt::download(WebCore::ResourceHandle* handle, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&)
1005 {
1006     if (!m_webFrame)
1007         return;
1008
1009     QNetworkReplyHandler* handler = handle->getInternal()->m_job;
1010     QNetworkReply* reply = handler->release();
1011     if (reply) {
1012         QWebPage* page = m_webFrame->page();
1013         if (page->forwardUnsupportedContent())
1014             emit unsupportedContent(reply);
1015         else
1016             reply->abort();
1017     }
1018 }
1019
1020 void FrameLoaderClientQt::assignIdentifierToInitialRequest(unsigned long identifier, WebCore::DocumentLoader*, const WebCore::ResourceRequest& request)
1021 {
1022     if (dumpResourceLoadCallbacks)
1023         dumpAssignedUrls[identifier] = drtDescriptionSuitableForTestResult(request.url());
1024 }
1025
1026 void FrameLoaderClientQt::dispatchWillSendRequest(WebCore::DocumentLoader*, unsigned long identifier, WebCore::ResourceRequest& newRequest, const WebCore::ResourceResponse& redirectResponse)
1027 {
1028     QUrl url = newRequest.url();
1029
1030     if (dumpResourceLoadCallbacks)
1031         printf("%s - willSendRequest %s redirectResponse %s\n",
1032                qPrintable(dumpAssignedUrls[identifier]),
1033                qPrintable(drtDescriptionSuitableForTestResult(newRequest)),
1034                (redirectResponse.isNull()) ? "(null)" : qPrintable(drtDescriptionSuitableForTestResult(redirectResponse)));
1035
1036     if (sendRequestReturnsNull) {
1037         newRequest.setURL(QUrl());
1038         return;
1039     }
1040
1041     if (sendRequestReturnsNullOnRedirect && !redirectResponse.isNull()) {
1042         printf("Returning null for this redirect\n");
1043         newRequest.setURL(QUrl());
1044         return;
1045     }
1046
1047     if (QWebPagePrivate::drtRun
1048         && url.isValid()
1049         && (url.scheme().toLower() == QLatin1String("http") || url.scheme().toLower() == QLatin1String("https"))
1050         && url.host() != QLatin1String("127.0.0.1")
1051         && url.host() != QLatin1String("255.255.255.255")
1052         && url.host().toLower() != QLatin1String("localhost")) {
1053
1054         printf("Blocked access to external URL %s\n", qPrintable(drtDescriptionSuitableForTestResult(newRequest.url())));
1055         newRequest.setURL(QUrl());
1056         return;
1057     }
1058
1059     for (int i = 0; i < sendRequestClearHeaders.size(); ++i)
1060           newRequest.setHTTPHeaderField(sendRequestClearHeaders.at(i).toLocal8Bit().constData(), QString());
1061
1062     if (QWebPagePrivate::drtRun) {
1063         QMap<QString, QString>::const_iterator it = URLsToRedirect.constFind(url.toString());
1064         if (it != URLsToRedirect.constEnd())
1065             newRequest.setURL(QUrl(it.value()));
1066     }
1067     // Seems like the Mac code doesn't do anything here by default neither.
1068     // qDebug() << "FrameLoaderClientQt::dispatchWillSendRequest" << request.isNull() << url;
1069 }
1070
1071 bool FrameLoaderClientQt::shouldUseCredentialStorage(DocumentLoader*, unsigned long)
1072 {
1073     notImplemented();
1074     return false;
1075 }
1076
1077 void FrameLoaderClientQt::dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long, const AuthenticationChallenge&)
1078 {
1079     notImplemented();
1080 }
1081
1082 void FrameLoaderClientQt::dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long, const AuthenticationChallenge&)
1083 {
1084     notImplemented();
1085 }
1086
1087 void FrameLoaderClientQt::dispatchDidReceiveResponse(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::ResourceResponse& response)
1088 {
1089
1090     m_response = response;
1091     if (dumpWillCacheResponseCallbacks)
1092         printf("%s - willCacheResponse: called\n",
1093                qPrintable(dumpAssignedUrls[identifier]));
1094
1095     if (dumpResourceLoadCallbacks)
1096         printf("%s - didReceiveResponse %s\n",
1097                qPrintable(dumpAssignedUrls[identifier]),
1098                qPrintable(drtDescriptionSuitableForTestResult(response)));
1099
1100     if (dumpResourceResponseMIMETypes) {
1101         printf("%s has MIME type %s\n",
1102                qPrintable(QString(response.url().lastPathComponent())),
1103                qPrintable(QString(response.mimeType())));
1104     }
1105 }
1106
1107 void FrameLoaderClientQt::dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long, int)
1108 {
1109 }
1110
1111 void FrameLoaderClientQt::dispatchDidFinishLoading(WebCore::DocumentLoader*, unsigned long identifier)
1112 {
1113     if (dumpResourceLoadCallbacks)
1114         printf("%s - didFinishLoading\n",
1115                (dumpAssignedUrls.contains(identifier) ? qPrintable(dumpAssignedUrls[identifier]) : "<unknown>"));
1116 }
1117
1118 void FrameLoaderClientQt::dispatchDidFailLoading(WebCore::DocumentLoader* loader, unsigned long identifier, const WebCore::ResourceError& error)
1119 {
1120     if (dumpResourceLoadCallbacks)
1121         printf("%s - didFailLoadingWithError: %s\n",
1122                (dumpAssignedUrls.contains(identifier) ? qPrintable(dumpAssignedUrls[identifier]) : "<unknown>"),
1123                qPrintable(drtDescriptionSuitableForTestResult(error)));
1124 }
1125
1126 bool FrameLoaderClientQt::dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, int)
1127 {
1128     notImplemented();
1129     return false;
1130 }
1131
1132 bool FrameLoaderClientQt::callErrorPageExtension(const WebCore::ResourceError& error)
1133 {
1134     QWebPage* page = m_webFrame->page();
1135     if (!page->supportsExtension(QWebPage::ErrorPageExtension))
1136         return false;
1137
1138     QWebPage::ErrorPageExtensionOption option;
1139     if (error.domain() == "QtNetwork")
1140         option.domain = QWebPage::QtNetwork;
1141     else if (error.domain() == "HTTP")
1142         option.domain = QWebPage::Http;
1143     else if (error.domain() == "WebKit")
1144         option.domain = QWebPage::WebKit;
1145     else
1146         return false;
1147
1148     option.url = QUrl(error.failingURL());
1149     option.frame = m_webFrame;
1150     option.error = error.errorCode();
1151     option.errorString = error.localizedDescription();
1152
1153     QWebPage::ErrorPageExtensionReturn output;
1154     if (!page->extension(QWebPage::ErrorPageExtension, &option, &output))
1155         return false;
1156
1157     KURL baseUrl(output.baseUrl);
1158     KURL failingUrl(option.url);
1159
1160     WebCore::ResourceRequest request(baseUrl);
1161     WTF::RefPtr<WebCore::SharedBuffer> buffer = WebCore::SharedBuffer::create(output.content.constData(), output.content.length());
1162     WebCore::SubstituteData substituteData(buffer, output.contentType, output.encoding, failingUrl);
1163     m_frame->loader()->load(request, substituteData, false);
1164     return true;
1165 }
1166
1167 void FrameLoaderClientQt::dispatchDidFailProvisionalLoad(const WebCore::ResourceError& error)
1168 {
1169     if (dumpFrameLoaderCallbacks)
1170         printf("%s - didFailProvisionalLoadWithError\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
1171
1172     if (!error.isNull() && !error.isCancellation()) {
1173         if (callErrorPageExtension(error))
1174             return;
1175     }
1176
1177     if (m_webFrame)
1178         emitLoadFinished(false);
1179 }
1180
1181 void FrameLoaderClientQt::dispatchDidFailLoad(const WebCore::ResourceError& error)
1182 {
1183     if (dumpFrameLoaderCallbacks)
1184         printf("%s - didFailLoadWithError\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
1185
1186     if (!error.isNull() && !error.isCancellation()) {
1187         if (callErrorPageExtension(error))
1188             return;
1189     }
1190
1191     if (m_webFrame)
1192         emitLoadFinished(false);
1193 }
1194
1195 WebCore::Frame* FrameLoaderClientQt::dispatchCreatePage(const WebCore::NavigationAction&)
1196 {
1197     if (!m_webFrame)
1198         return 0;
1199     QWebPage *newPage = m_webFrame->page()->createWindow(QWebPage::WebBrowserWindow);
1200     if (!newPage)
1201         return 0;
1202     return newPage->mainFrame()->d->frame;
1203 }
1204
1205 void FrameLoaderClientQt::dispatchDecidePolicyForResponse(FramePolicyFunction function, const WebCore::ResourceResponse& response, const WebCore::ResourceRequest&)
1206 {
1207     // We need to call directly here.
1208     switch (response.httpStatusCode()) {
1209     case HTTPResetContent:
1210         // FIXME: a 205 response requires that the requester reset the document view.
1211         // Fallthrough
1212     case HTTPNoContent:
1213         callPolicyFunction(function, PolicyIgnore);
1214         return;
1215     }
1216
1217     if (WebCore::contentDispositionType(response.httpHeaderField("Content-Disposition")) == WebCore::ContentDispositionAttachment)
1218         callPolicyFunction(function, PolicyDownload);
1219     else if (canShowMIMEType(response.mimeType()))
1220         callPolicyFunction(function, PolicyUse);
1221     else
1222         callPolicyFunction(function, PolicyDownload);
1223 }
1224
1225 void FrameLoaderClientQt::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function, const WebCore::NavigationAction& action, const WebCore::ResourceRequest& request, PassRefPtr<WebCore::FormState>, const WTF::String&)
1226 {
1227     Q_ASSERT(m_webFrame);
1228     QNetworkRequest r(request.toNetworkRequest(m_frame->loader()->networkingContext()));
1229     QWebPage* page = m_webFrame->page();
1230
1231     if (!page->d->acceptNavigationRequest(0, r, QWebPage::NavigationType(action.type()))) {
1232         if (action.type() == NavigationTypeFormSubmitted || action.type() == NavigationTypeFormResubmitted)
1233             m_frame->loader()->resetMultipleFormSubmissionProtection();
1234
1235         if (action.type() == NavigationTypeLinkClicked && r.url().hasFragment()) {
1236             ResourceRequest emptyRequest;
1237             m_frame->loader()->activeDocumentLoader()->setLastCheckedRequest(emptyRequest);
1238         }
1239
1240         callPolicyFunction(function, PolicyIgnore);
1241         return;
1242     }
1243     callPolicyFunction(function, PolicyUse);
1244 }
1245
1246 void FrameLoaderClientQt::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, const WebCore::NavigationAction& action, const WebCore::ResourceRequest& request, PassRefPtr<WebCore::FormState>)
1247 {
1248     Q_ASSERT(m_webFrame);
1249     QNetworkRequest r(request.toNetworkRequest(m_frame->loader()->networkingContext()));
1250     QWebPage*page = m_webFrame->page();
1251     PolicyAction result;
1252
1253     // Currently, this is only enabled by DRT.
1254     if (policyDelegateEnabled) {
1255         RefPtr<Node> node;
1256         for (const Event* event = action.event(); event; event = event->underlyingEvent()) {
1257             if (event->isMouseEvent()) {
1258                 const MouseEvent* mouseEvent =  static_cast<const MouseEvent*>(event);
1259                 node = QWebFramePrivate::core(m_webFrame)->eventHandler()->hitTestResultAtPoint(
1260                     mouseEvent->absoluteLocation(), false).innerNonSharedNode();
1261                 break;
1262             }
1263         }
1264
1265         printf("Policy delegate: attempt to load %s with navigation type '%s'%s\n",
1266                qPrintable(drtDescriptionSuitableForTestResult(request.url())), navigationTypeToString(action.type()),
1267                (node) ? qPrintable(QString::fromLatin1(" originating from ") + drtDescriptionSuitableForTestResult(node, 0)) : "");
1268
1269         if (policyDelegatePermissive)
1270             result = PolicyUse;
1271         else
1272             result = PolicyIgnore;
1273
1274         page->d->acceptNavigationRequest(m_webFrame, r, QWebPage::NavigationType(action.type()));
1275         callPolicyFunction(function, result);
1276         return;
1277     }
1278
1279     if (!page->d->acceptNavigationRequest(m_webFrame, r, QWebPage::NavigationType(action.type()))) {
1280         if (action.type() == NavigationTypeFormSubmitted || action.type() == NavigationTypeFormResubmitted)
1281             m_frame->loader()->resetMultipleFormSubmissionProtection();
1282
1283         if (action.type() == NavigationTypeLinkClicked && r.url().hasFragment()) {
1284             ResourceRequest emptyRequest;
1285             m_frame->loader()->activeDocumentLoader()->setLastCheckedRequest(emptyRequest);
1286         }
1287
1288         callPolicyFunction(function, PolicyIgnore);
1289         return;
1290     }
1291     callPolicyFunction(function, PolicyUse);
1292 }
1293
1294 void FrameLoaderClientQt::dispatchUnableToImplementPolicy(const WebCore::ResourceError&)
1295 {
1296     notImplemented();
1297 }
1298
1299 void FrameLoaderClientQt::startDownload(const WebCore::ResourceRequest& request, const String& /* suggestedName */)
1300 {
1301     if (!m_webFrame)
1302         return;
1303
1304     emit m_webFrame->page()->downloadRequested(request.toNetworkRequest(m_frame->loader()->networkingContext()));
1305 }
1306
1307 PassRefPtr<Frame> FrameLoaderClientQt::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
1308                                         const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
1309 {
1310     if (!m_webFrame)
1311         return 0;
1312
1313     QWebFrameData frameData(m_frame->page(), m_frame, ownerElement, name);
1314
1315     if (url.isEmpty())
1316         frameData.url = blankURL();
1317     else
1318         frameData.url = url;
1319
1320     frameData.referrer = referrer;
1321     frameData.allowsScrolling = allowsScrolling;
1322     frameData.marginWidth = marginWidth;
1323     frameData.marginHeight = marginHeight;
1324
1325     QWeakPointer<QWebFrame> webFrame = new QWebFrame(m_webFrame, &frameData);
1326     // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
1327     if (!webFrame.data()->d->frame->page()) {
1328         frameData.frame.release();
1329         ASSERT(webFrame.isNull());
1330         return 0;
1331     }
1332
1333     emit m_webFrame->page()->frameCreated(webFrame.data());
1334
1335     // FIXME: Set override encoding if we have one.
1336
1337     m_frame->loader()->loadURLIntoChildFrame(frameData.url, frameData.referrer, frameData.frame.get());
1338
1339     // The frame's onload handler may have removed it from the document.
1340     if (!frameData.frame->tree()->parent())
1341         return 0;
1342
1343     return frameData.frame.release();
1344 }
1345
1346 ObjectContentType FrameLoaderClientQt::objectContentType(const KURL& url, const String& mimeTypeIn, bool shouldPreferPlugInsForImages)
1347 {
1348     // qDebug()<<" ++++++++++++++++ url is "<<url.string()<<", mime = "<<mimeTypeIn;
1349     QFileInfo fi(url.path());
1350     String extension = fi.suffix();
1351     if (mimeTypeIn == "application/x-qt-plugin" || mimeTypeIn == "application/x-qt-styled-widget")
1352         return ObjectContentOtherPlugin;
1353
1354     if (url.isEmpty() && !mimeTypeIn.length())
1355         return ObjectContentNone;
1356
1357     String mimeType = mimeTypeIn;
1358     if (!mimeType.length())
1359         mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
1360
1361     if (!mimeType.length())
1362         mimeType = PluginDatabase::installedPlugins()->MIMETypeForExtension(extension);
1363
1364     if (!mimeType.length())
1365         return ObjectContentFrame;
1366
1367     ObjectContentType plugInType = ObjectContentNone;
1368     if (PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType))
1369         plugInType = ObjectContentNetscapePlugin;
1370     else if (m_frame->page() && m_frame->page()->pluginData() && m_frame->page()->pluginData()->supportsMimeType(mimeType))
1371         plugInType = ObjectContentOtherPlugin;
1372         
1373     if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
1374         return shouldPreferPlugInsForImages && plugInType != ObjectContentNone ? plugInType : ObjectContentImage;
1375     
1376     if (plugInType != ObjectContentNone)
1377         return plugInType;
1378
1379     if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
1380         return ObjectContentFrame;
1381
1382     if (url.protocol() == "about")
1383         return ObjectContentFrame;
1384
1385     return ObjectContentNone;
1386 }
1387
1388 static const CSSPropertyID qstyleSheetProperties[] = {
1389     CSSPropertyColor,
1390     CSSPropertyFontFamily,
1391     CSSPropertyFontSize,
1392     CSSPropertyFontStyle,
1393     CSSPropertyFontWeight
1394 };
1395
1396 const unsigned numqStyleSheetProperties = sizeof(qstyleSheetProperties) / sizeof(qstyleSheetProperties[0]);
1397
1398 class QtPluginWidget: public Widget
1399 {
1400 public:
1401     QtPluginWidget(QWidget* w = 0): Widget(w) {}
1402     ~QtPluginWidget()
1403     {
1404         if (platformWidget())
1405             platformWidget()->deleteLater();
1406     }
1407     virtual void invalidateRect(const IntRect& r)
1408     { 
1409         if (platformWidget())
1410             static_cast<QWidget*>(platformWidget())->update(r);
1411     }
1412     virtual void frameRectsChanged()
1413     {
1414         QWidget* widget = static_cast<QWidget*>(platformWidget());
1415         if (!widget)
1416             return;
1417
1418         IntRect windowRect = convertToContainingWindow(IntRect(0, 0, frameRect().width(), frameRect().height()));
1419         widget->setGeometry(windowRect);
1420
1421         ScrollView* parentScrollView = parent();
1422         if (!parentScrollView)
1423             return;
1424
1425         ASSERT(parentScrollView->isFrameView());
1426         IntRect clipRect(static_cast<FrameView*>(parentScrollView)->windowClipRect());
1427         clipRect.move(-windowRect.x(), -windowRect.y());
1428         clipRect.intersect(widget->rect());
1429
1430         QRegion clipRegion = QRegion(clipRect);
1431         widget->setMask(clipRegion);
1432
1433         handleVisibility();
1434
1435         widget->update();
1436     }
1437
1438     virtual void show()
1439     {
1440         Widget::show();
1441         handleVisibility();
1442     }
1443
1444 private:
1445     void handleVisibility()
1446     {
1447         if (!isVisible())
1448             return;
1449
1450         QWidget* widget = static_cast<QWidget*>(platformWidget());
1451         // If setMask is set with an empty QRegion, no clipping will
1452         // be performed, so in that case we hide the platformWidget.
1453         QRegion mask = widget->mask();
1454         widget->setVisible(!mask.isEmpty());
1455     }
1456 };
1457
1458 #if !defined(QT_NO_GRAPHICSVIEW)
1459 class QtPluginGraphicsWidget: public Widget
1460 {
1461 public:
1462     static RefPtr<QtPluginGraphicsWidget> create(QGraphicsWidget* w = 0)
1463     {
1464         return adoptRef(new QtPluginGraphicsWidget(w));
1465     }
1466
1467     ~QtPluginGraphicsWidget()
1468     {
1469         if (graphicsWidget)
1470             graphicsWidget->deleteLater();
1471     }
1472     virtual void invalidateRect(const IntRect& r)
1473     {
1474         QGraphicsScene* scene = graphicsWidget ? graphicsWidget->scene() : 0;
1475         if (scene)
1476             scene->update(QRect(r));
1477     }
1478     virtual void frameRectsChanged()
1479     {
1480         if (!graphicsWidget)
1481             return;
1482
1483         IntRect windowRect = convertToContainingWindow(IntRect(0, 0, frameRect().width(), frameRect().height()));
1484         graphicsWidget->setGeometry(QRect(windowRect));
1485
1486         // FIXME: Make the code handle clipping of graphics widgets.
1487     }
1488     virtual void show()
1489     {
1490         if (graphicsWidget)
1491             graphicsWidget->show();
1492     }
1493     virtual void hide()
1494     {
1495         if (graphicsWidget)
1496             graphicsWidget->hide();
1497     }
1498 private:
1499     QtPluginGraphicsWidget(QGraphicsWidget* w = 0)
1500         : Widget(0)
1501         , graphicsWidget(w)
1502     {
1503         setBindingObject(graphicsWidget);
1504     }
1505
1506     QGraphicsWidget* graphicsWidget;
1507 };
1508 #endif // QT_NO_GRAPHICSVIEW
1509
1510 PassRefPtr<Widget> FrameLoaderClientQt::createPlugin(const IntSize& pluginSize, HTMLPlugInElement* element, const KURL& url, const Vector<String>& paramNames,
1511                                           const Vector<String>& paramValues, const String& mimeType, bool loadManually)
1512 {
1513     // qDebug()<<"------ Creating plugin in FrameLoaderClientQt::createPlugin for "<<url.string() << mimeType;
1514     // qDebug()<<"------\t url = "<<url.string();
1515
1516     if (!m_webFrame)
1517         return 0;
1518
1519     QStringList params;
1520     QStringList values;
1521     QString classid(element->getAttribute("classid"));
1522
1523     for (unsigned i = 0; i < paramNames.size(); ++i) {
1524         params.append(paramNames[i]);
1525         if (paramNames[i] == "classid")
1526             classid = paramValues[i];
1527     }
1528     for (unsigned i = 0; i < paramValues.size(); ++i)
1529         values.append(paramValues[i]);
1530
1531     QString urlStr(url.string());
1532     QUrl qurl = urlStr;
1533
1534     QObject* object = 0;
1535
1536     if (mimeType == "application/x-qt-plugin" || mimeType == "application/x-qt-styled-widget") {
1537         object = m_webFrame->page()->createPlugin(classid, qurl, params, values);
1538 #ifndef QT_NO_STYLE_STYLESHEET
1539         QWidget* widget = qobject_cast<QWidget*>(object);
1540         if (widget && mimeType == "application/x-qt-styled-widget") {
1541
1542             QString styleSheet = element->getAttribute("style");
1543             if (!styleSheet.isEmpty())
1544                 styleSheet += QLatin1Char(';');
1545
1546             for (unsigned i = 0; i < numqStyleSheetProperties; ++i) {
1547                 CSSPropertyID property = qstyleSheetProperties[i];
1548
1549                 styleSheet += QString::fromLatin1(getPropertyName(property));
1550                 styleSheet += QLatin1Char(':');
1551                 styleSheet += CSSComputedStyleDeclaration::create(element)->getPropertyValue(property);
1552                 styleSheet += QLatin1Char(';');
1553             }
1554
1555             widget->setStyleSheet(styleSheet);
1556         }
1557 #endif // QT_NO_STYLE_STYLESHEET
1558     }
1559
1560     if (!object) {
1561         QWebPluginFactory* factory = m_webFrame->page()->pluginFactory();
1562         if (factory)
1563             object = factory->create(mimeType, qurl, params, values);
1564     }
1565
1566     if (object) {
1567         QWidget* widget = qobject_cast<QWidget*>(object);
1568         if (widget) {
1569             QWidget* parentWidget = 0;
1570             if (m_webFrame->page()->d->client)
1571                 parentWidget = qobject_cast<QWidget*>(m_webFrame->page()->d->client->pluginParent());
1572             if (parentWidget) // Don't reparent to nothing (i.e. keep whatever parent QWebPage::createPlugin() chose.
1573                 widget->setParent(parentWidget);
1574             widget->hide();
1575             RefPtr<QtPluginWidget> w = adoptRef(new QtPluginWidget());
1576             w->setPlatformWidget(widget);
1577             // Make sure it's invisible until properly placed into the layout.
1578             w->setFrameRect(IntRect(0, 0, 0, 0));
1579             return w;
1580         }
1581
1582 #if !defined(QT_NO_GRAPHICSVIEW)
1583         QGraphicsWidget* graphicsWidget = qobject_cast<QGraphicsWidget*>(object);
1584         if (graphicsWidget) {
1585             QGraphicsObject* parentWidget = 0;
1586             if (m_webFrame->page()->d->client)
1587                 parentWidget = qobject_cast<QGraphicsObject*>(m_webFrame->page()->d->client->pluginParent());
1588             graphicsWidget->hide();
1589             if (parentWidget) // Don't reparent to nothing (i.e. keep whatever parent QWebPage::createPlugin() chose.
1590                 graphicsWidget->setParentItem(parentWidget);
1591             RefPtr<QtPluginGraphicsWidget> w = QtPluginGraphicsWidget::create(graphicsWidget);
1592             // Make sure it's invisible until properly placed into the layout.
1593             w->setFrameRect(IntRect(0, 0, 0, 0));
1594             return w;
1595         }
1596 #endif // QT_NO_GRAPHICSVIEW
1597
1598         // FIXME: Make things work for widgetless plugins as well.
1599         delete object;
1600     }
1601 #if ENABLE(NETSCAPE_PLUGIN_API)
1602     else { // NPAPI Plugins
1603         Vector<String> params = paramNames;
1604         Vector<String> values = paramValues;
1605         if (mimeType == "application/x-shockwave-flash") {
1606 #if HAVE(QT5)
1607             const bool shouldInjectWmode = true;
1608 #else
1609             // Inject wmode=opaque when there is no client or the client is not a QWebView.
1610             QWebPageClient* client = m_webFrame->page()->d->client.get();
1611             const bool shouldInjectWmode = !(client && qobject_cast<QWidget*>(client->pluginParent()));
1612 #endif
1613             if (shouldInjectWmode) {
1614                 // Inject wmode=opaque when there is no client or the client is not a QWebView.
1615                 size_t wmodeIndex = params.find("wmode");
1616                 if (wmodeIndex == WTF::notFound) {
1617                     params.append("wmode");
1618                     values.append("opaque");
1619                 } else if (equalIgnoringCase(values[wmodeIndex], "window"))
1620                     values[wmodeIndex] = "opaque";
1621             }
1622         }
1623
1624         RefPtr<PluginView> pluginView = PluginView::create(m_frame, pluginSize, element, url,
1625             params, values, mimeType, loadManually);
1626         return pluginView;
1627     }
1628 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1629
1630     return 0;
1631 }
1632
1633 void FrameLoaderClientQt::redirectDataToPlugin(Widget* pluginWidget)
1634 {
1635     ASSERT(!m_pluginView);
1636     m_pluginView = static_cast<PluginView*>(pluginWidget);
1637     m_hasSentResponseToPlugin = false;
1638 }
1639
1640 PassRefPtr<Widget> FrameLoaderClientQt::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement* element, const KURL& url,
1641                                                     const Vector<String>& paramNames, const Vector<String>& paramValues)
1642 {
1643     return createPlugin(pluginSize, element, url, paramNames, paramValues, "application/x-java-applet", true);
1644 }
1645
1646 String FrameLoaderClientQt::overrideMediaType() const
1647 {
1648     return String();
1649 }
1650
1651 QString FrameLoaderClientQt::chooseFile(const QString& oldFile)
1652 {
1653     return m_webFrame->page()->chooseFile(m_webFrame, oldFile);
1654 }
1655
1656 PassRefPtr<FrameNetworkingContext> FrameLoaderClientQt::createNetworkingContext()
1657 {
1658     QVariant value = m_webFrame->page()->property("_q_MIMESniffingDisabled");
1659     bool MIMESniffingDisabled = value.isValid() && value.toBool();
1660
1661     return FrameNetworkingContextQt::create(m_frame, m_webFrame, !MIMESniffingDisabled, m_webFrame->page()->networkAccessManager());
1662 }
1663
1664 void FrameLoaderClientQt::emitLoadStarted()
1665 {
1666     QWebPage* webPage = m_webFrame->page();
1667     if (m_isOriginatingLoad && webPage)
1668         emit webPage->loadStarted();
1669     emit m_webFrame->loadStarted();
1670 }
1671
1672 void FrameLoaderClientQt::emitLoadFinished(bool ok)
1673 {
1674     // Signal handlers can lead to a new load, that will use the member again.
1675     const bool wasOriginatingLoad = m_isOriginatingLoad;
1676     m_isOriginatingLoad = false;
1677
1678     QWebPage* webPage = m_webFrame->page();
1679     if (wasOriginatingLoad && webPage)
1680         emit webPage->loadFinished(ok);
1681     emit m_webFrame->loadFinished(ok);
1682 }
1683
1684 }
1685
1686 #include "moc_FrameLoaderClientQt.cpp"