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