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