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