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