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