[Qt] Separate QWidget dependant code into separate WebKitWidgets static library
[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 "QWebFrameAdapter.h"
63 #include "QWebPageAdapter.h"
64 #include "QWebPageClient.h"
65 #include "QtPluginWidgetAdapter.h"
66 #include "RenderPart.h"
67 #include "ResourceHandle.h"
68 #include "ResourceHandleInternal.h"
69 #include "ResourceRequest.h"
70 #include "ResourceResponse.h"
71 #include "ScriptController.h"
72 #include "Settings.h"
73 #include "ViewportArguments.h"
74 #include "WebEventConversion.h"
75 #include "qwebhistory.h"
76 #include "qwebhistory_p.h"
77 #include "qwebhistoryinterface.h"
78 #include "qwebpluginfactory.h"
79
80 #include <QCoreApplication>
81 #include <QDebug>
82 #include <QFileInfo>
83 #include <QMouseEvent>
84 #include <QNetworkReply>
85 #include <QNetworkRequest>
86 #include <QStringList>
87 #include <wtf/OwnPtr.h>
88 #include <wtf/text/StringBuilder.h>
89
90 static QMap<unsigned long, QString> dumpAssignedUrls;
91
92 // Compare with the file "WebKit/Tools/DumpRenderTree/mac/FrameLoadDelegate.mm".
93 static QString drtDescriptionSuitableForTestResult(WebCore::Frame* webCoreFrame)
94 {
95     QWebFrameAdapter* frame = QWebFrameAdapter::kit(webCoreFrame);
96     QString name = webCoreFrame->tree()->uniqueName();
97
98     bool isMainFrame = frame == frame->pageAdapter->mainFrameAdapter();
99     if (isMainFrame) {
100         if (!name.isEmpty())
101             return QString::fromLatin1("main frame \"%1\"").arg(name);
102         return QLatin1String("main frame");
103     }
104     if (!name.isEmpty())
105         return QString::fromLatin1("frame \"%1\"").arg(name);
106     return QLatin1String("frame (anonymous)");
107 }
108
109 static QString drtPrintFrameUserGestureStatus(WebCore::Frame* frame)
110 {
111     if (WebCore::ScriptController::processingUserGesture())
112         return QString::fromLatin1("Frame with user gesture \"%1\"").arg(QLatin1String("true"));
113     return QString::fromLatin1("Frame with user gesture \"%1\"").arg(QLatin1String("false"));
114 }
115
116 static QString drtDescriptionSuitableForTestResult(const WebCore::KURL& kurl)
117 {
118     if (kurl.isEmpty() || !kurl.isLocalFile())
119         return kurl.string();
120     // Remove the leading path from file urls.
121     return QString(kurl.string()).remove(WebCore::FrameLoaderClientQt::dumpResourceLoadCallbacksPath).mid(1);
122 }
123
124 static QString drtDescriptionSuitableForTestResult(const WebCore::ResourceError& error)
125 {
126     QString failingURL = error.failingURL();
127     return QString::fromLatin1("<NSError domain NSURLErrorDomain, code %1, failing URL \"%2\">").arg(error.errorCode()).arg(failingURL);
128 }
129
130 static QString drtDescriptionSuitableForTestResult(const WebCore::ResourceRequest& request)
131 {
132     QString url = drtDescriptionSuitableForTestResult(request.url());
133     QString httpMethod = request.httpMethod();
134     QString mainDocumentUrl = drtDescriptionSuitableForTestResult(request.firstPartyForCookies());
135     return QString::fromLatin1("<NSURLRequest URL %1, main document URL %2, http method %3>").arg(url).arg(mainDocumentUrl).arg(httpMethod);
136 }
137
138 static QString drtDescriptionSuitableForTestResult(const WebCore::ResourceResponse& response)
139 {
140     QString url = drtDescriptionSuitableForTestResult(response.url());
141     int httpStatusCode = response.httpStatusCode();
142     return QString::fromLatin1("<NSURLResponse %1, http status code %2>").arg(url).arg(httpStatusCode);
143 }
144
145 static QString drtDescriptionSuitableForTestResult(const RefPtr<WebCore::Node> node, int exception)
146 {
147     QString result;
148     if (exception) {
149         result.append(QLatin1String("ERROR"));
150         return result;
151     }
152     if (!node) {
153         result.append(QLatin1String("NULL"));
154         return result;
155     }
156     result.append(node->nodeName());
157     RefPtr<WebCore::Node> parent = node->parentNode();
158     if (parent) {
159         result.append(QLatin1String(" > "));
160         result.append(drtDescriptionSuitableForTestResult(parent, 0));
161     }
162     return result;
163 }
164
165 namespace WebCore {
166
167 bool FrameLoaderClientQt::dumpFrameLoaderCallbacks = false;
168 bool FrameLoaderClientQt::dumpProgressFinishedCallback = false;
169 bool FrameLoaderClientQt::dumpUserGestureInFrameLoaderCallbacks = false;
170 bool FrameLoaderClientQt::dumpWillCacheResponseCallbacks = false;
171 bool FrameLoaderClientQt::dumpResourceLoadCallbacks = false;
172 bool FrameLoaderClientQt::sendRequestReturnsNullOnRedirect = false;
173 bool FrameLoaderClientQt::sendRequestReturnsNull = false;
174 bool FrameLoaderClientQt::dumpResourceResponseMIMETypes = false;
175 bool FrameLoaderClientQt::deferMainResourceDataLoad = true;
176 bool FrameLoaderClientQt::dumpHistoryCallbacks = false;
177
178 QStringList FrameLoaderClientQt::sendRequestClearHeaders;
179 QString FrameLoaderClientQt::dumpResourceLoadCallbacksPath;
180 bool FrameLoaderClientQt::policyDelegateEnabled = false;
181 bool FrameLoaderClientQt::policyDelegatePermissive = false;
182 QMap<QString, QString> FrameLoaderClientQt::URLsToRedirect = QMap<QString, QString>();
183
184 // Taken from the file "WebKit/Tools/DumpRenderTree/chromium/WebViewHost.cpp".
185 static const char* navigationTypeToString(NavigationType type)
186 {
187     switch (type) {
188     case NavigationTypeLinkClicked:
189         return "link clicked";
190     case NavigationTypeFormSubmitted:
191         return "form submitted";
192     case NavigationTypeBackForward:
193         return "back/forward";
194     case NavigationTypeReload:
195         return "reload";
196     case NavigationTypeFormResubmitted:
197         return "form resubmitted";
198     case NavigationTypeOther:
199         return "other";
200     }
201     return "illegal value";
202 }
203
204 FrameLoaderClientQt::FrameLoaderClientQt()
205     : m_frame(0)
206     , m_webFrame(0)
207     , m_pluginView(0)
208     , m_hasSentResponseToPlugin(false)
209     , m_isOriginatingLoad(false)
210 {
211 }
212
213
214 FrameLoaderClientQt::~FrameLoaderClientQt()
215 {
216 }
217
218 void FrameLoaderClientQt::setFrame(QWebFrameAdapter* webFrame, Frame* frame)
219 {
220     m_webFrame = webFrame;
221     m_frame = frame;
222
223     if (!m_webFrame || !m_webFrame->pageAdapter) {
224         qWarning("FrameLoaderClientQt::setFrame frame without Page!");
225         return;
226     }
227
228     connect(this, SIGNAL(loadProgress(int)),
229         m_webFrame->pageAdapter->handle(), SIGNAL(loadProgress(int)));
230
231     connect(this, SIGNAL(unsupportedContent(QNetworkReply*)),
232         m_webFrame->pageAdapter->handle(), SIGNAL(unsupportedContent(QNetworkReply*)));
233
234     connect(this, SIGNAL(titleChanged(QString)),
235         m_webFrame->handle(), SIGNAL(titleChanged(QString)));
236 }
237
238 void FrameLoaderClientQt::callPolicyFunction(FramePolicyFunction function, PolicyAction action)
239 {
240     (m_frame->loader()->policyChecker()->*function)(action);
241 }
242
243 bool FrameLoaderClientQt::hasWebView() const
244 {
245     // notImplemented();
246     return true;
247 }
248
249 void FrameLoaderClientQt::savePlatformDataToCachedFrame(CachedFrame*) 
250 {
251     notImplemented();
252 }
253
254 void FrameLoaderClientQt::transitionToCommittedFromCachedFrame(CachedFrame*)
255 {
256 }
257
258 void FrameLoaderClientQt::transitionToCommittedForNewPage()
259 {
260     ASSERT(m_frame);
261     ASSERT(m_webFrame);
262
263     QObject* qWebPage = m_webFrame->pageAdapter->handle();
264     QBrush brush = qWebPage->property("palette").value<QPalette>().brush(QPalette::Base);
265     QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor();
266
267     const QSize preferredLayoutSize = qWebPage->property("preferredContentsSize").toSize();
268
269     ScrollbarMode hScrollbar = (ScrollbarMode) m_webFrame->scrollBarPolicy(Qt::Horizontal);
270     ScrollbarMode vScrollbar = (ScrollbarMode) m_webFrame->scrollBarPolicy(Qt::Vertical);
271     bool hLock = hScrollbar != ScrollbarAuto;
272     bool vLock = vScrollbar != ScrollbarAuto;
273
274     // The HistoryController will update the scroll position later if needed.
275     IntRect currentVisibleContentRect = m_frame->view() ? IntRect(IntPoint::zero(), m_frame->view()->fixedVisibleContentRect().size()) : IntRect();
276
277     m_frame->createView(qWebPage->property("viewportSize").toSize(),
278         backgroundColor, !backgroundColor.alpha(),
279         preferredLayoutSize.isValid() ? IntSize(preferredLayoutSize) : IntSize(),
280         currentVisibleContentRect,
281         preferredLayoutSize.isValid(),
282         hScrollbar, hLock,
283         vScrollbar, vLock);
284
285     bool isMainFrame = m_frame == m_frame->page()->mainFrame();
286     if (isMainFrame &&m_webFrame->pageAdapter->client) {
287         bool resizesToContents = m_webFrame->pageAdapter->client->viewResizesToContentsEnabled();
288
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->emitUrlChanged();
396     m_webFrame->pageAdapter->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     m_webFrame->didStartProvisionalLoad();
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->emitUrlChanged();
482     m_webFrame->pageAdapter->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->pageAdapter->emitViewportChangeRequested();
494 }
495
496
497 void FrameLoaderClientQt::dispatchDidFinishDocumentLoad()
498 {
499     if (dumpFrameLoaderCallbacks)
500         printf("%s - didFinishDocumentLoadForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
501
502     if (QWebPageAdapter::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->pageAdapter->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->pageAdapter->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         m_webFrame->emitInitialLayoutCompleted();
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, PassRefPtr<FormState>)
549 {
550     notImplemented();
551     // FIXME: This is surely too simple.
552     callPolicyFunction(function, PolicyUse);
553 }
554
555
556 void FrameLoaderClientQt::postProgressStartedNotification()
557 {
558     if (m_webFrame && m_frame->page())
559         m_isOriginatingLoad = true;
560     if (m_frame->tree()->parent() || !m_webFrame)
561         return;
562     m_webFrame->pageAdapter->updateNavigationActions();
563 }
564
565 void FrameLoaderClientQt::postProgressEstimateChangedNotification()
566 {
567     if (m_webFrame && m_frame->page())
568         emit loadProgress(qRound(m_frame->page()->progress()->estimatedProgress() * 100));
569 }
570
571 void FrameLoaderClientQt::postProgressFinishedNotification()
572 {
573     if (dumpProgressFinishedCallback)
574         printf("postProgressFinishedNotification\n");
575
576     // Send a mousemove event to:
577     // (1) update the cursor to change according to whatever is underneath the mouse cursor right now;
578     // (2) display the tool tip if the mouse hovers a node which has a tool tip.
579     if (m_frame && m_frame->eventHandler() && m_webFrame) {
580         QPoint localPos;
581         if (m_webFrame->handleProgressFinished(&localPos)) {
582             QMouseEvent event(QEvent::MouseMove, localPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier);
583             m_frame->eventHandler()->mouseMoved(convertMouseEvent(&event, 0));
584         }
585     }
586 }
587
588 void FrameLoaderClientQt::setMainFrameDocumentReady(bool)
589 {
590     // This is only interesting once we provide an external API for the DOM.
591 }
592
593
594 void FrameLoaderClientQt::willChangeTitle(DocumentLoader*)
595 {
596     // No need for, dispatchDidReceiveTitle is the right callback.
597 }
598
599
600 void FrameLoaderClientQt::didChangeTitle(DocumentLoader*)
601 {
602     // No need for, dispatchDidReceiveTitle is the right callback.
603 }
604
605
606 void FrameLoaderClientQt::finishedLoading(DocumentLoader*)
607 {
608     if (!m_pluginView)
609         return;
610     if (m_pluginView->isPluginView())
611         m_pluginView->didFinishLoading();
612     m_pluginView = 0;
613     m_hasSentResponseToPlugin = false;
614 }
615
616 bool FrameLoaderClientQt::canShowMIMETypeAsHTML(const String& MIMEType) const
617 {
618     notImplemented();
619     return false;
620 }
621     
622 bool FrameLoaderClientQt::canShowMIMEType(const String& MIMEType) const
623 {
624     String type = MIMEType;
625     type.makeLower();
626     if (MIMETypeRegistry::canShowMIMEType(type))
627         return true;
628
629     if (m_frame && m_frame->settings()  && m_frame->settings()->arePluginsEnabled()
630         && PluginDatabase::installedPlugins()->isMIMETypeRegistered(type))
631         return true;
632
633     return false;
634 }
635
636 bool FrameLoaderClientQt::representationExistsForURLScheme(const String&) const
637 {
638     return false;
639 }
640
641
642 String FrameLoaderClientQt::generatedMIMETypeForURLScheme(const String&) const
643 {
644     notImplemented();
645     return String();
646 }
647
648
649 void FrameLoaderClientQt::frameLoadCompleted()
650 {
651     // Note that this can be called multiple times.
652     if (!m_webFrame)
653         return;
654     m_webFrame->pageAdapter->updateNavigationActions();
655 }
656
657
658 void FrameLoaderClientQt::restoreViewState()
659 {
660     if (!m_webFrame)
661         return;
662     m_webFrame->pageAdapter->emitRestoreFrameStateRequested(m_webFrame);
663 }
664
665
666 void FrameLoaderClientQt::provisionalLoadStarted()
667 {
668     // Don't need to do anything here.
669 }
670
671
672 void FrameLoaderClientQt::didFinishLoad()
673 {
674     // notImplemented();
675 }
676
677
678 void FrameLoaderClientQt::prepareForDataSourceReplacement()
679 {
680 }
681
682 void FrameLoaderClientQt::setTitle(const StringWithDirection& title, const KURL& url)
683 {
684     // Used by Apple WebKit to update the title of an existing history item.
685     // QtWebKit doesn't accomodate this on history items. If it ever does,
686     // it should be privateBrowsing-aware. For now, we are just passing
687     // globalhistory layout tests.
688     // FIXME: Use direction of title.
689     if (dumpHistoryCallbacks) {
690         printf("WebView updated the title for history URL \"%s\" to \"%s\".\n",
691             qPrintable(drtDescriptionSuitableForTestResult(url)),
692             qPrintable(QString(title.string())));
693     }
694 }
695
696
697 String FrameLoaderClientQt::userAgent(const KURL& url)
698 {
699     if (m_webFrame)
700         return m_webFrame->pageAdapter->userAgentForUrl(url).remove(QLatin1Char('\n')).remove(QLatin1Char('\r'));
701     return String();
702 }
703
704 void FrameLoaderClientQt::dispatchDidReceiveIcon()
705 {
706     if (m_webFrame)
707         m_webFrame->emitIconChanged();
708 }
709
710 void FrameLoaderClientQt::frameLoaderDestroyed()
711 {
712     // Delete QWebFrame (handle()), which owns QWebFramePrivate, which
713     // _is_ a QWebFrameAdapter.
714     if (m_webFrame)
715         delete m_webFrame->handle();
716     m_frame = 0;
717     m_webFrame = 0;
718
719     delete this;
720 }
721
722 bool FrameLoaderClientQt::canHandleRequest(const WebCore::ResourceRequest&) const
723 {
724     return true;
725 }
726
727 void FrameLoaderClientQt::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world)
728 {
729     if (world != mainThreadNormalWorld())
730         return;
731
732     if (m_webFrame)
733         m_webFrame->didClearWindowObject();
734 }
735
736 void FrameLoaderClientQt::documentElementAvailable()
737 {
738     return;
739 }
740
741 void FrameLoaderClientQt::didPerformFirstNavigation() const
742 {
743     if (m_frame->tree()->parent() || !m_webFrame)
744         return;
745     m_webFrame->pageAdapter->updateNavigationActions();
746 }
747
748 void FrameLoaderClientQt::registerForIconNotification(bool shouldRegister)
749 {
750 #if ENABLE(ICONDATABASE)
751     if (shouldRegister)
752         connect(IconDatabaseClientQt::instance(), SIGNAL(iconLoadedForPageURL(QString)), this, SLOT(onIconLoadedForPageURL(QString)), Qt::UniqueConnection);
753     else
754         disconnect(IconDatabaseClientQt::instance(), SIGNAL(iconLoadedForPageURL(QString)), this, SLOT(onIconLoadedForPageURL(QString)));
755 #endif
756 }
757
758 void FrameLoaderClientQt::onIconLoadedForPageURL(const QString& url)
759 {
760 #if ENABLE(ICONDATABASE)
761     if (m_webFrame && m_webFrame->url == url)
762         m_webFrame->emitIconChanged();
763 #endif
764 }
765
766
767 void FrameLoaderClientQt::updateGlobalHistory()
768 {
769     QWebHistoryInterface* history = QWebHistoryInterface::defaultInterface();
770     WebCore::DocumentLoader* loader = m_frame->loader()->documentLoader();
771     if (history)
772         history->addHistoryEntry(loader->urlForHistory().string());
773
774     if (dumpHistoryCallbacks) {
775         printf("WebView navigated to url \"%s\" with title \"%s\" with HTTP equivalent method \"%s\".  The navigation was %s and was %s%s.\n",
776             qPrintable(drtDescriptionSuitableForTestResult(loader->urlForHistory())),
777             qPrintable(QString(loader->title().string())),
778             qPrintable(QString(loader->request().httpMethod())),
779             ((loader->substituteData().isValid() || (loader->response().httpStatusCode() >= 400)) ? "a failure" : "successful"),
780             ((!loader->clientRedirectSourceForHistory().isEmpty()) ? "a client redirect from " : "not a client redirect"),
781             (!loader->clientRedirectSourceForHistory().isEmpty()) ? qPrintable(drtDescriptionSuitableForTestResult(loader->clientRedirectSourceForHistory())) : "");
782     }
783 }
784
785 void FrameLoaderClientQt::updateGlobalHistoryRedirectLinks()
786 {
787     // Apple WebKit is the only port that makes use of this callback. It calls
788     // WebCore::HistoryItem::addRedirectURL() with the contents of
789     // loader->[server|client]RedirectDestinationForHistory().
790     // WebCore can associate a bunch of redirect URLs with a particular
791     // item in the history, presumably this allows Safari to skip the redirections
792     // when navigating to that history item. That might be a feature Qt wants to
793     // offer through QWebHistoryInterface in the future. For now, we're just
794     // passing tests in LayoutTests/http/tests/globalhistory.
795     WebCore::DocumentLoader* loader = m_frame->loader()->documentLoader();
796
797     if (!loader->clientRedirectSourceForHistory().isNull()) {
798         if (dumpHistoryCallbacks) {
799             printf("WebView performed a client redirect from \"%s\" to \"%s\".\n",
800                 qPrintable(QString(loader->clientRedirectSourceForHistory())),
801                 qPrintable(QString(loader->clientRedirectDestinationForHistory())));
802         }
803     }
804
805     if (!loader->serverRedirectSourceForHistory().isNull()) {
806         if (dumpHistoryCallbacks) {
807             printf("WebView performed a server redirect from \"%s\" to \"%s\".\n",
808                 qPrintable(QString(loader->serverRedirectSourceForHistory())),
809                 qPrintable(QString(loader->serverRedirectDestinationForHistory())));
810         }
811     }
812 }
813
814 bool FrameLoaderClientQt::shouldGoToHistoryItem(WebCore::HistoryItem*) const
815 {
816     return true;
817 }
818
819 bool FrameLoaderClientQt::shouldStopLoadingForHistoryItem(WebCore::HistoryItem*) const
820 {
821     return true;
822 }
823
824 void FrameLoaderClientQt::didDisplayInsecureContent()
825 {
826     if (dumpFrameLoaderCallbacks)
827         printf("didDisplayInsecureContent\n");
828
829     notImplemented();
830 }
831
832 void FrameLoaderClientQt::didRunInsecureContent(WebCore::SecurityOrigin*, const KURL&)
833 {
834     if (dumpFrameLoaderCallbacks)
835         printf("didRunInsecureContent\n");
836
837     notImplemented();
838 }
839
840 void FrameLoaderClientQt::didDetectXSS(const KURL&, bool)
841 {
842     if (dumpFrameLoaderCallbacks)
843         printf("didDetectXSS\n");
844
845     notImplemented();
846 }
847
848 void FrameLoaderClientQt::saveViewStateToItem(WebCore::HistoryItem* item)
849 {
850     QWebHistoryItem historyItem(new QWebHistoryItemPrivate(item));
851     m_webFrame->pageAdapter->emitSaveFrameStateRequested(m_webFrame, &historyItem);
852 }
853
854 bool FrameLoaderClientQt::canCachePage() const
855 {
856     return true;
857 }
858
859 void FrameLoaderClientQt::setMainDocumentError(WebCore::DocumentLoader* loader, const WebCore::ResourceError& error)
860 {
861     if (!m_pluginView)
862         return;
863     if (m_pluginView->isPluginView())
864         m_pluginView->didFail(error);
865     m_pluginView = 0;
866     m_hasSentResponseToPlugin = false;
867 }
868
869 // FIXME: This function should be moved into WebCore.
870 void FrameLoaderClientQt::committedLoad(WebCore::DocumentLoader* loader, const char* data, int length)
871 {
872     if (!m_pluginView)
873         loader->commitData(data, length);
874
875     // If we are sending data to MediaDocument, we should stop here and cancel the request.
876     if (m_frame->document()->isMediaDocument())
877         loader->cancelMainResourceLoad(pluginWillHandleLoadError(loader->response()));
878
879     // We re-check here as the plugin can have been created.
880     if (m_pluginView && m_pluginView->isPluginView()) {
881         if (!m_hasSentResponseToPlugin) {
882             m_pluginView->didReceiveResponse(loader->response());
883             // The function didReceiveResponse sets up a new stream to the plug-in.
884             // On a full-page plug-in, a failure in setting up this stream can cause the
885             // main document load to be cancelled, setting m_pluginView to null.
886             if (!m_pluginView)
887                 return;
888             m_hasSentResponseToPlugin = true;
889         }
890         m_pluginView->didReceiveData(data, length);
891     }
892 }
893
894 WebCore::ResourceError FrameLoaderClientQt::cancelledError(const WebCore::ResourceRequest& request)
895 {
896     ResourceError error = ResourceError("QtNetwork", QNetworkReply::OperationCanceledError, request.url().string(),
897         QCoreApplication::translate("QWebFrame", "Request cancelled", 0));
898     error.setIsCancellation(true);
899     return error;
900 }
901
902 // This was copied from file "WebKit/Source/WebKit/mac/Misc/WebKitErrors.h".
903 enum {
904     WebKitErrorCannotShowMIMEType =                             100,
905     WebKitErrorCannotShowURL =                                  101,
906     WebKitErrorFrameLoadInterruptedByPolicyChange =             102,
907     WebKitErrorCannotUseRestrictedPort =                        103,
908     WebKitErrorCannotFindPlugIn =                               200,
909     WebKitErrorCannotLoadPlugIn =                               201,
910     WebKitErrorJavaUnavailable =                                202,
911     WebKitErrorPluginWillHandleLoad =                           203
912 };
913
914 WebCore::ResourceError FrameLoaderClientQt::blockedError(const WebCore::ResourceRequest& request)
915 {
916     return ResourceError("WebKitErrorDomain", WebKitErrorCannotUseRestrictedPort, request.url().string(),
917         QCoreApplication::translate("QWebFrame", "Request blocked", 0));
918 }
919
920
921 WebCore::ResourceError FrameLoaderClientQt::cannotShowURLError(const WebCore::ResourceRequest& request)
922 {
923     return ResourceError("WebKitErrorDomain", WebKitErrorCannotShowURL, request.url().string(),
924         QCoreApplication::translate("QWebFrame", "Cannot show URL", 0));
925 }
926
927 WebCore::ResourceError FrameLoaderClientQt::interruptedForPolicyChangeError(const WebCore::ResourceRequest& request)
928 {
929     return ResourceError("WebKitErrorDomain", WebKitErrorFrameLoadInterruptedByPolicyChange, request.url().string(),
930         QCoreApplication::translate("QWebFrame", "Frame load interrupted by policy change", 0));
931 }
932
933 WebCore::ResourceError FrameLoaderClientQt::cannotShowMIMETypeError(const WebCore::ResourceResponse& response)
934 {
935     return ResourceError("WebKitErrorDomain", WebKitErrorCannotShowMIMEType, response.url().string(),
936         QCoreApplication::translate("QWebFrame", "Cannot show mimetype", 0));
937 }
938
939 WebCore::ResourceError FrameLoaderClientQt::fileDoesNotExistError(const WebCore::ResourceResponse& response)
940 {
941     return ResourceError("QtNetwork", QNetworkReply::ContentNotFoundError, response.url().string(),
942         QCoreApplication::translate("QWebFrame", "File does not exist", 0));
943 }
944
945 WebCore::ResourceError FrameLoaderClientQt::pluginWillHandleLoadError(const WebCore::ResourceResponse& response)
946 {
947     return ResourceError("WebKit", WebKitErrorPluginWillHandleLoad, response.url().string(),
948         QCoreApplication::translate("QWebFrame", "Loading is handled by the media engine", 0));
949 }
950
951 bool FrameLoaderClientQt::shouldFallBack(const WebCore::ResourceError& error)
952 {
953     DEFINE_STATIC_LOCAL(const ResourceError, cancelledError, (this->cancelledError(ResourceRequest())));
954     DEFINE_STATIC_LOCAL(const ResourceError, pluginWillHandleLoadError, (this->pluginWillHandleLoadError(ResourceResponse())));
955     DEFINE_STATIC_LOCAL(const ResourceError, errorInterruptedForPolicyChange, (this->interruptedForPolicyChangeError(ResourceRequest())));
956
957     if (error.errorCode() == cancelledError.errorCode() && error.domain() == cancelledError.domain())
958         return false;
959
960     if (error.errorCode() == errorInterruptedForPolicyChange.errorCode() && error.domain() == errorInterruptedForPolicyChange.domain())
961         return false;
962
963     if (error.errorCode() == pluginWillHandleLoadError.errorCode() && error.domain() == pluginWillHandleLoadError.domain())
964         return false;
965
966     return true;
967 }
968
969 WTF::PassRefPtr<WebCore::DocumentLoader> FrameLoaderClientQt::createDocumentLoader(const WebCore::ResourceRequest& request, const SubstituteData& substituteData)
970 {
971     RefPtr<DocumentLoader> loader = DocumentLoader::create(request, substituteData);
972     if (!deferMainResourceDataLoad || substituteData.isValid()) {
973         loader->setDeferMainResourceDataLoad(false);
974         // Use the default timeout interval for JS as the HTML tokenizer delay. This ensures
975         // that long-running JavaScript will still allow setHtml() to be synchronous, while
976         // still giving a reasonable timeout to prevent deadlock.
977         double delay = JSDOMWindowBase::commonJSGlobalData()->timeoutChecker.timeoutInterval() / 1000.0f;
978         m_frame->page()->setCustomHTMLTokenizerTimeDelay(delay);
979     } else
980         m_frame->page()->setCustomHTMLTokenizerTimeDelay(-1);
981     return loader.release();
982 }
983
984 void FrameLoaderClientQt::download(WebCore::ResourceHandle* handle, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&)
985 {
986     if (!m_webFrame)
987         return;
988
989     QNetworkReplyHandler* handler = handle->getInternal()->m_job;
990     QNetworkReply* reply = handler->release();
991     if (reply) {
992         if (m_webFrame->pageAdapter->forwardUnsupportedContent)
993             emit unsupportedContent(reply);
994         else
995             reply->abort();
996     }
997 }
998
999 void FrameLoaderClientQt::assignIdentifierToInitialRequest(unsigned long identifier, WebCore::DocumentLoader*, const WebCore::ResourceRequest& request)
1000 {
1001     if (dumpResourceLoadCallbacks)
1002         dumpAssignedUrls[identifier] = drtDescriptionSuitableForTestResult(request.url());
1003 }
1004
1005 static void blockRequest(WebCore::ResourceRequest& request)
1006 {
1007     request.setURL(QUrl());
1008 }
1009
1010 static bool isLocalhost(const QString& host)
1011 {
1012     return host == QLatin1String("127.0.0.1") || host == QLatin1String("localhost");
1013 }
1014
1015 static bool hostIsUsedBySomeTestsToGenerateError(const QString& host)
1016 {
1017     return host == QLatin1String("255.255.255.255");
1018 }
1019
1020 void FrameLoaderClientQt::dispatchWillSendRequest(WebCore::DocumentLoader*, unsigned long identifier, WebCore::ResourceRequest& newRequest, const WebCore::ResourceResponse& redirectResponse)
1021 {
1022     if (dumpResourceLoadCallbacks)
1023         printf("%s - willSendRequest %s redirectResponse %s\n",
1024             qPrintable(dumpAssignedUrls[identifier]),
1025             qPrintable(drtDescriptionSuitableForTestResult(newRequest)),
1026             (redirectResponse.isNull()) ? "(null)" : qPrintable(drtDescriptionSuitableForTestResult(redirectResponse)));
1027
1028     if (sendRequestReturnsNull) {
1029         blockRequest(newRequest);
1030         return;
1031     }
1032
1033     if (sendRequestReturnsNullOnRedirect && !redirectResponse.isNull()) {
1034         printf("Returning null for this redirect\n");
1035         blockRequest(newRequest);
1036         return;
1037     }
1038
1039     QUrl url = newRequest.url();
1040     QString host = url.host();
1041     QString urlScheme = url.scheme().toLower();
1042
1043     if (QWebPageAdapter::drtRun
1044         && !host.isEmpty()
1045         && (urlScheme == QLatin1String("http") || urlScheme == QLatin1String("https"))) {
1046
1047         QUrl testURL = m_webFrame->pageAdapter->mainFrameAdapter()->frameLoaderClient->lastRequestedUrl();
1048         QString testHost = testURL.host();
1049         QString testURLScheme = testURL.scheme().toLower();
1050
1051         if (!isLocalhost(host)
1052             && !hostIsUsedBySomeTestsToGenerateError(host)
1053             && ((testURLScheme != QLatin1String("http") && testURLScheme != QLatin1String("https")) || isLocalhost(testHost))) {
1054             printf("Blocked access to external URL %s\n", qPrintable(drtDescriptionSuitableForTestResult(newRequest.url())));
1055             blockRequest(newRequest);
1056             return;
1057         }
1058     }
1059
1060     for (int i = 0; i < sendRequestClearHeaders.size(); ++i)
1061         newRequest.setHTTPHeaderField(sendRequestClearHeaders.at(i).toLocal8Bit().constData(), QString());
1062
1063     if (QWebPageAdapter::drtRun) {
1064         QMap<QString, QString>::const_iterator it = URLsToRedirect.constFind(url.toString());
1065         if (it != URLsToRedirect.constEnd())
1066             newRequest.setURL(QUrl(it.value()));
1067     }
1068     // Seems like the Mac code doesn't do anything here by default neither.
1069     // qDebug() << "FrameLoaderClientQt::dispatchWillSendRequest" << request.isNull() << url;
1070 }
1071
1072 bool FrameLoaderClientQt::shouldUseCredentialStorage(DocumentLoader*, unsigned long)
1073 {
1074     notImplemented();
1075     return false;
1076 }
1077
1078 void FrameLoaderClientQt::dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long, const AuthenticationChallenge&)
1079 {
1080     notImplemented();
1081 }
1082
1083 void FrameLoaderClientQt::dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long, const AuthenticationChallenge&)
1084 {
1085     notImplemented();
1086 }
1087
1088 void FrameLoaderClientQt::dispatchDidReceiveResponse(WebCore::DocumentLoader*, unsigned long identifier, const WebCore::ResourceResponse& response)
1089 {
1090
1091     m_response = response;
1092     if (dumpWillCacheResponseCallbacks)
1093         printf("%s - willCacheResponse: called\n",
1094             qPrintable(dumpAssignedUrls[identifier]));
1095
1096     if (dumpResourceLoadCallbacks)
1097         printf("%s - didReceiveResponse %s\n",
1098             qPrintable(dumpAssignedUrls[identifier]),
1099             qPrintable(drtDescriptionSuitableForTestResult(response)));
1100
1101     if (dumpResourceResponseMIMETypes) {
1102         printf("%s has MIME type %s\n",
1103             qPrintable(QString(response.url().lastPathComponent())),
1104             qPrintable(QString(response.mimeType())));
1105     }
1106 }
1107
1108 void FrameLoaderClientQt::dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long, int)
1109 {
1110 }
1111
1112 void FrameLoaderClientQt::dispatchDidFinishLoading(WebCore::DocumentLoader*, unsigned long identifier)
1113 {
1114     if (dumpResourceLoadCallbacks)
1115         printf("%s - didFinishLoading\n",
1116             (dumpAssignedUrls.contains(identifier) ? qPrintable(dumpAssignedUrls[identifier]) : "<unknown>"));
1117 }
1118
1119 void FrameLoaderClientQt::dispatchDidFailLoading(WebCore::DocumentLoader* loader, unsigned long identifier, const WebCore::ResourceError& error)
1120 {
1121     if (dumpResourceLoadCallbacks)
1122         printf("%s - didFailLoadingWithError: %s\n",
1123             (dumpAssignedUrls.contains(identifier) ? qPrintable(dumpAssignedUrls[identifier]) : "<unknown>"),
1124             qPrintable(drtDescriptionSuitableForTestResult(error)));
1125 }
1126
1127 bool FrameLoaderClientQt::dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, int)
1128 {
1129     notImplemented();
1130     return false;
1131 }
1132
1133 bool FrameLoaderClientQt::callErrorPageExtension(const WebCore::ResourceError& error)
1134 {
1135     QWebPageAdapter* page = m_webFrame->pageAdapter;
1136     if (!page->supportsErrorPageExtension())
1137         return false;
1138     QWebPageAdapter::ErrorPageOption option;
1139     option.url = QUrl(error.failingURL());
1140     option.frame = m_webFrame;
1141     option.domain = error.domain();
1142     option.error = error.errorCode();
1143     option.errorString = error.localizedDescription();
1144
1145     QWebPageAdapter::ErrorPageReturn output;
1146
1147     if (!page->errorPageExtension(&option, &output))
1148         return false;
1149
1150     KURL baseUrl(output.baseUrl);
1151     KURL failingUrl(option.url);
1152
1153     WebCore::ResourceRequest request(baseUrl);
1154     WTF::RefPtr<WebCore::SharedBuffer> buffer = WebCore::SharedBuffer::create(output.content.constData(), output.content.length());
1155     WebCore::SubstituteData substituteData(buffer, output.contentType, output.encoding, failingUrl);
1156     m_frame->loader()->load(request, substituteData, false);
1157     return true;
1158 }
1159
1160 void FrameLoaderClientQt::dispatchDidFailProvisionalLoad(const WebCore::ResourceError& error)
1161 {
1162     if (dumpFrameLoaderCallbacks)
1163         printf("%s - didFailProvisionalLoadWithError\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
1164
1165     if (!error.isNull() && !error.isCancellation()) {
1166         if (callErrorPageExtension(error))
1167             return;
1168     }
1169
1170     if (m_webFrame)
1171         emitLoadFinished(false);
1172 }
1173
1174 void FrameLoaderClientQt::dispatchDidFailLoad(const WebCore::ResourceError& error)
1175 {
1176     if (dumpFrameLoaderCallbacks)
1177         printf("%s - didFailLoadWithError\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
1178
1179     if (!error.isNull() && !error.isCancellation()) {
1180         if (callErrorPageExtension(error))
1181             return;
1182     }
1183
1184     if (m_webFrame)
1185         emitLoadFinished(false);
1186 }
1187
1188 WebCore::Frame* FrameLoaderClientQt::dispatchCreatePage(const WebCore::NavigationAction&)
1189 {
1190     if (!m_webFrame)
1191         return 0;
1192     QWebPageAdapter* newPage = m_webFrame->pageAdapter->createWindow(/* modalDialog = */ false);
1193     if (!newPage)
1194         return 0;
1195     return newPage->mainFrameAdapter()->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_frame->loader()->networkingContext()));
1222
1223     if (!m_webFrame->pageAdapter->acceptNavigationRequest(0, r, (int)action.type())) {
1224         if (action.type() == NavigationTypeFormSubmitted || action.type() == NavigationTypeFormResubmitted)
1225             m_frame->loader()->resetMultipleFormSubmissionProtection();
1226
1227         if (action.type() == NavigationTypeLinkClicked && r.url().hasFragment()) {
1228             ResourceRequest emptyRequest;
1229             m_frame->loader()->activeDocumentLoader()->setLastCheckedRequest(emptyRequest);
1230         }
1231
1232         callPolicyFunction(function, PolicyIgnore);
1233         return;
1234     }
1235     callPolicyFunction(function, PolicyUse);
1236 }
1237
1238 void FrameLoaderClientQt::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, const WebCore::NavigationAction& action, const WebCore::ResourceRequest& request, PassRefPtr<WebCore::FormState>)
1239 {
1240     Q_ASSERT(m_webFrame);
1241     QNetworkRequest r(request.toNetworkRequest(m_frame->loader()->networkingContext()));
1242     PolicyAction result;
1243
1244     // Currently, this is only enabled by DRT.
1245     if (policyDelegateEnabled) {
1246         RefPtr<Node> node;
1247         for (const Event* event = action.event(); event; event = event->underlyingEvent()) {
1248             if (event->isMouseEvent()) {
1249                 const MouseEvent* mouseEvent =  static_cast<const MouseEvent*>(event);
1250                 node = m_webFrame->frame->eventHandler()->hitTestResultAtPoint(
1251                     mouseEvent->absoluteLocation(), false).innerNonSharedNode();
1252                 break;
1253             }
1254         }
1255
1256         printf("Policy delegate: attempt to load %s with navigation type '%s'%s\n",
1257             qPrintable(drtDescriptionSuitableForTestResult(request.url())), navigationTypeToString(action.type()),
1258             (node) ? qPrintable(QString::fromLatin1(" originating from ") + drtDescriptionSuitableForTestResult(node, 0)) : "");
1259
1260         if (policyDelegatePermissive)
1261             result = PolicyUse;
1262         else
1263             result = PolicyIgnore;
1264
1265         m_webFrame->pageAdapter->acceptNavigationRequest(m_webFrame, r, (int)action.type());
1266         callPolicyFunction(function, result);
1267         return;
1268     }
1269
1270     if (!m_webFrame->pageAdapter->acceptNavigationRequest(m_webFrame, r, (int)action.type())) {
1271         if (action.type() == NavigationTypeFormSubmitted || action.type() == NavigationTypeFormResubmitted)
1272             m_frame->loader()->resetMultipleFormSubmissionProtection();
1273
1274         if (action.type() == NavigationTypeLinkClicked && r.url().hasFragment()) {
1275             ResourceRequest emptyRequest;
1276             m_frame->loader()->activeDocumentLoader()->setLastCheckedRequest(emptyRequest);
1277         }
1278
1279         callPolicyFunction(function, PolicyIgnore);
1280         return;
1281     }
1282     callPolicyFunction(function, PolicyUse);
1283 }
1284
1285 void FrameLoaderClientQt::dispatchUnableToImplementPolicy(const WebCore::ResourceError&)
1286 {
1287     notImplemented();
1288 }
1289
1290 void FrameLoaderClientQt::startDownload(const WebCore::ResourceRequest& request, const String& /* suggestedName */)
1291 {
1292     if (!m_webFrame)
1293         return;
1294
1295     m_webFrame->pageAdapter->emitDownloadRequested(request.toNetworkRequest(m_frame->loader()->networkingContext()));
1296 }
1297
1298 PassRefPtr<Frame> FrameLoaderClientQt::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
1299 {
1300     if (!m_webFrame)
1301         return 0;
1302
1303     QWebFrameData frameData(m_frame->page(), m_frame, ownerElement, name);
1304
1305     frameData.referrer = referrer;
1306     frameData.allowsScrolling = allowsScrolling;
1307     frameData.marginWidth = marginWidth;
1308     frameData.marginHeight = marginHeight;
1309
1310     QWebFrameAdapter* childWebFrame = m_webFrame->createChildFrame(&frameData);
1311     // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
1312     if (!childWebFrame->frame->page()) {
1313         QPointer<QObject> qWebFrame = childWebFrame->handle();
1314         frameData.frame.release();
1315         ASSERT_UNUSED(qWebFrame, !qWebFrame);
1316         return 0;
1317     }
1318
1319     m_webFrame->pageAdapter->emitFrameCreated(childWebFrame);
1320
1321     // FIXME: Set override encoding if we have one.
1322
1323     KURL urlToLoad = url;
1324     if (urlToLoad.isEmpty())
1325         urlToLoad = blankURL();
1326
1327     m_frame->loader()->loadURLIntoChildFrame(urlToLoad, frameData.referrer, frameData.frame.get());
1328
1329     // The frame's onload handler may have removed it from the document.
1330     if (!frameData.frame->tree()->parent())
1331         return 0;
1332
1333     return frameData.frame.release();
1334 }
1335
1336 ObjectContentType FrameLoaderClientQt::objectContentType(const KURL& url, const String& mimeTypeIn, bool shouldPreferPlugInsForImages)
1337 {
1338     // qDebug()<<" ++++++++++++++++ url is "<<url.string()<<", mime = "<<mimeTypeIn;
1339     QFileInfo fi(url.path());
1340     String extension = fi.suffix();
1341     if (mimeTypeIn == "application/x-qt-plugin" || mimeTypeIn == "application/x-qt-styled-widget")
1342         return ObjectContentOtherPlugin;
1343
1344     if (url.isEmpty() && !mimeTypeIn.length())
1345         return ObjectContentNone;
1346
1347     String mimeType = mimeTypeIn;
1348     if (!mimeType.length())
1349         mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
1350
1351     if (!mimeType.length())
1352         mimeType = PluginDatabase::installedPlugins()->MIMETypeForExtension(extension);
1353
1354     if (!mimeType.length())
1355         return ObjectContentFrame;
1356
1357     ObjectContentType plugInType = ObjectContentNone;
1358     if (PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType))
1359         plugInType = ObjectContentNetscapePlugin;
1360     else if (m_frame->page() && m_frame->page()->pluginData() && m_frame->page()->pluginData()->supportsMimeType(mimeType))
1361         plugInType = ObjectContentOtherPlugin;
1362         
1363     if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
1364         return shouldPreferPlugInsForImages && plugInType != ObjectContentNone ? plugInType : ObjectContentImage;
1365     
1366     if (plugInType != ObjectContentNone)
1367         return plugInType;
1368
1369     if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
1370         return ObjectContentFrame;
1371
1372     if (url.protocol() == "about")
1373         return ObjectContentFrame;
1374
1375     return ObjectContentNone;
1376 }
1377
1378 static const CSSPropertyID qstyleSheetProperties[] = {
1379     CSSPropertyColor,
1380     CSSPropertyFontFamily,
1381     CSSPropertyFontSize,
1382     CSSPropertyFontStyle,
1383     CSSPropertyFontWeight
1384 };
1385
1386 const unsigned numqStyleSheetProperties = sizeof(qstyleSheetProperties) / sizeof(qstyleSheetProperties[0]);
1387
1388 class QtPluginWidget: public Widget {
1389 public:
1390     QtPluginWidget(QtPluginWidgetAdapter* w)
1391         : Widget(w->handle())
1392         , m_adapter(w)
1393     {
1394         setBindingObject(w->handle());
1395     }
1396
1397     ~QtPluginWidget()
1398     {
1399         delete m_adapter;
1400     }
1401
1402     inline QtPluginWidgetAdapter* widgetAdapter() const
1403     {
1404         return m_adapter;
1405     }
1406
1407     virtual void invalidateRect(const IntRect& r)
1408     { 
1409         if (platformWidget())
1410             widgetAdapter()->update(r);
1411     }
1412     virtual void frameRectsChanged()
1413     {
1414         QtPluginWidgetAdapter* widget = widgetAdapter();
1415         if (!widget)
1416             return;
1417         QRect windowRect = convertToContainingWindow(IntRect(0, 0, frameRect().width(), frameRect().height()));
1418
1419         ScrollView* parentScrollView = parent();
1420         QRect clipRect;
1421         if (parentScrollView) {
1422             ASSERT(parentScrollView->isFrameView());
1423             clipRect = static_cast<FrameView*>(parentScrollView)->windowClipRect();
1424             clipRect.translate(-windowRect.x(), -windowRect.y());
1425         }
1426         widget->setGeometryAndClip(windowRect, clipRect, isVisible());
1427     }
1428
1429     virtual void show()
1430     {
1431         Widget::show();
1432         handleVisibility();
1433     }
1434     virtual void hide()
1435     {
1436         if (platformWidget())
1437             widgetAdapter()->setVisible(false);
1438     }
1439
1440 private:
1441     QtPluginWidgetAdapter* m_adapter;
1442
1443     void handleVisibility()
1444     {
1445         if (!isVisible())
1446             return;
1447         widgetAdapter()->setVisible(true);
1448     }
1449 };
1450
1451
1452 PassRefPtr<Widget> FrameLoaderClientQt::createPlugin(const IntSize& pluginSize, HTMLPlugInElement* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
1453 {
1454     // qDebug()<<"------ Creating plugin in FrameLoaderClientQt::createPlugin for "<<url.string() << mimeType;
1455     // qDebug()<<"------\t url = "<<url.string();
1456
1457     if (!m_webFrame)
1458         return 0;
1459
1460     QStringList params;
1461     QStringList values;
1462     QString classid(element->getAttribute("classid"));
1463
1464     for (unsigned i = 0; i < paramNames.size(); ++i) {
1465         params.append(paramNames[i]);
1466         if (paramNames[i] == "classid")
1467             classid = paramValues[i];
1468     }
1469     for (unsigned i = 0; i < paramValues.size(); ++i)
1470         values.append(paramValues[i]);
1471
1472     QString urlStr(url.string());
1473     QUrl qurl = urlStr;
1474
1475     QObject* pluginAdapter = 0;
1476
1477     if (mimeType == "application/x-qt-plugin" || mimeType == "application/x-qt-styled-widget") {
1478         pluginAdapter = m_webFrame->pageAdapter->createPlugin(classid, qurl, params, values);
1479 #ifndef QT_NO_STYLE_STYLESHEET
1480         QtPluginWidgetAdapter* widget = qobject_cast<QtPluginWidgetAdapter*>(pluginAdapter);
1481         if (widget && mimeType == "application/x-qt-styled-widget") {
1482
1483             StringBuilder styleSheet;
1484             styleSheet.append(element->getAttribute("style"));
1485             if (!styleSheet.isEmpty())
1486                 styleSheet.append(';');
1487
1488             for (unsigned i = 0; i < numqStyleSheetProperties; ++i) {
1489                 CSSPropertyID property = qstyleSheetProperties[i];
1490
1491                 styleSheet.append(getPropertyName(property));
1492                 styleSheet.append(':');
1493                 styleSheet.append(CSSComputedStyleDeclaration::create(element)->getPropertyValue(property));
1494                 styleSheet.append(';');
1495             }
1496
1497             widget->setStyleSheet(styleSheet.toString());
1498         }
1499 #endif // QT_NO_STYLE_STYLESHEET
1500     }
1501
1502     if (!pluginAdapter) {
1503         QWebPluginFactory* factory = m_webFrame->pageAdapter->pluginFactory;
1504         if (factory)
1505             pluginAdapter = m_webFrame->pageAdapter->adapterForWidget(factory->create(mimeType, qurl, params, values));
1506     }
1507     if (pluginAdapter) {
1508         QtPluginWidgetAdapter* widget = qobject_cast<QtPluginWidgetAdapter*>(pluginAdapter);
1509         if (widget) {
1510             QObject* parentWidget = 0;
1511             if (m_webFrame->pageAdapter->client)
1512                 parentWidget = m_webFrame->pageAdapter->client->pluginParent();
1513             if (parentWidget) // Don't reparent to nothing (i.e. keep whatever parent QWebPage::createPlugin() chose.
1514                 widget->setWidgetParent(parentWidget);
1515             widget->setVisible(false);
1516             RefPtr<QtPluginWidget> w = adoptRef(new QtPluginWidget(widget));
1517             // Make sure it's invisible until properly placed into the layout.
1518             w->setFrameRect(IntRect(0, 0, 0, 0));
1519             return w;
1520         }
1521
1522         // FIXME: Make things work for widgetless plugins as well.
1523         delete pluginAdapter;
1524     }
1525 #if ENABLE(NETSCAPE_PLUGIN_API)
1526     else { // NPAPI Plugins
1527         Vector<String> params = paramNames;
1528         Vector<String> values = paramValues;
1529         if (mimeType == "application/x-shockwave-flash") {
1530             // Inject wmode=opaque when there is no client or the client is not a QWebView.
1531             size_t wmodeIndex = params.find("wmode");
1532             if (wmodeIndex == WTF::notFound) {
1533                 params.append("wmode");
1534                 values.append("opaque");
1535             } else if (equalIgnoringCase(values[wmodeIndex], "window"))
1536                 values[wmodeIndex] = "opaque";
1537         }
1538
1539         RefPtr<PluginView> pluginView = PluginView::create(m_frame, pluginSize, element, url,
1540             params, values, mimeType, loadManually);
1541         return pluginView;
1542     }
1543 #endif // ENABLE(NETSCAPE_PLUGIN_API)
1544
1545     return 0;
1546 }
1547
1548 void FrameLoaderClientQt::redirectDataToPlugin(Widget* pluginWidget)
1549 {
1550     m_pluginView = static_cast<PluginView*>(pluginWidget);
1551     if (pluginWidget)
1552         m_hasSentResponseToPlugin = false;
1553 }
1554
1555 PassRefPtr<Widget> FrameLoaderClientQt::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues)
1556 {
1557     return createPlugin(pluginSize, element, url, paramNames, paramValues, "application/x-java-applet", true);
1558 }
1559
1560 String FrameLoaderClientQt::overrideMediaType() const
1561 {
1562     return String();
1563 }
1564
1565 QString FrameLoaderClientQt::chooseFile(const QString& oldFile)
1566 {
1567     QStringList result = m_webFrame->pageAdapter->chooseFiles(m_webFrame, /*allowMulti*/ false, (QStringList() << oldFile));
1568     return result.isEmpty() ? QString() : result.first();
1569 }
1570
1571 PassRefPtr<FrameNetworkingContext> FrameLoaderClientQt::createNetworkingContext()
1572 {
1573     QVariant value = m_webFrame->pageAdapter->handle()->property("_q_MIMESniffingDisabled");
1574     bool MIMESniffingDisabled = value.isValid() && value.toBool();
1575
1576     return FrameNetworkingContextQt::create(m_frame, m_webFrame->handle(), !MIMESniffingDisabled);
1577 }
1578
1579 QWebFrameAdapter* FrameLoaderClientQt::webFrame() const
1580 {
1581     return m_webFrame;
1582 }
1583
1584 void FrameLoaderClientQt::emitLoadStarted()
1585 {
1586     m_webFrame->emitLoadStarted(m_isOriginatingLoad);
1587 }
1588
1589 void FrameLoaderClientQt::emitLoadFinished(bool ok)
1590 {
1591     // Signal handlers can lead to a new load, that will use the member again.
1592     const bool wasOriginatingLoad = m_isOriginatingLoad;
1593     m_isOriginatingLoad = false;
1594
1595     m_webFrame->emitLoadFinished(wasOriginatingLoad, ok);
1596 }
1597
1598 }
1599
1600 #include "moc_FrameLoaderClientQt.cpp"