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