2009-03-29 Darin Adler <darin@apple.com>
[WebKit-https.git] / WebKit / qt / WebCoreSupport / FrameLoaderClientQt.cpp
1 /*
2  * Copyright (C) 2006 Zack Rusin <zack@kde.org>
3  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
4  * Copyright (C) 2008 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  *
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
27  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "config.h"
33 #include "CSSComputedStyleDeclaration.h"
34 #include "CSSPropertyNames.h"
35 #include "FormState.h"
36 #include "FrameLoaderClientQt.h"
37 #include "FrameTree.h"
38 #include "FrameView.h"
39 #include "DocumentLoader.h"
40 #include "MIMETypeRegistry.h"
41 #include "ResourceResponse.h"
42 #include "Page.h"
43 #include "PluginData.h"
44 #include "PluginDatabase.h"
45 #include "ProgressTracker.h"
46 #include "RenderPart.h"
47 #include "ResourceRequest.h"
48 #include "HistoryItem.h"
49 #include "HTMLAppletElement.h"
50 #include "HTMLFormElement.h"
51 #include "HTMLPlugInElement.h"
52 #include "NotImplemented.h"
53 #include "QNetworkReplyHandler.h"
54 #include "ResourceHandleInternal.h"
55 #include "ResourceHandle.h"
56 #include "Settings.h"
57
58 #include "qwebpage.h"
59 #include "qwebframe.h"
60 #include "qwebframe_p.h"
61 #include "qwebhistoryinterface.h"
62 #include "qwebpluginfactory.h"
63
64 #include <qfileinfo.h>
65
66 #include <QCoreApplication>
67 #include <QDebug>
68 #if QT_VERSION >= 0x040400
69 #include <QNetworkRequest>
70 #include <QNetworkReply>
71 #else
72 #include "qwebnetworkinterface_p.h"
73 #endif
74 #include "qwebhistory_p.h"
75
76 static bool dumpFrameLoaderCallbacks = false;
77 static bool dumpResourceLoadCallbacks = false;
78
79 static QMap<unsigned long, QString> dumpAssignedUrls;
80
81 void QWEBKIT_EXPORT qt_dump_frame_loader(bool b)
82 {
83     dumpFrameLoaderCallbacks = b;
84 }
85
86 void QWEBKIT_EXPORT qt_dump_resource_load_callbacks(bool b)
87 {
88     dumpResourceLoadCallbacks = b;
89 }
90
91 // Compare with WebKitTools/DumpRenderTree/mac/FrameLoadDelegate.mm
92 static QString drtDescriptionSuitableForTestResult(WebCore::Frame* _frame)
93 {
94     QWebFrame* frame = QWebFramePrivate::kit(_frame);
95     QString name = frame->frameName();
96
97     bool isMainFrame = frame == frame->page()->mainFrame();
98     if (isMainFrame) {
99         if (!name.isEmpty())
100             return QString::fromLatin1("main frame \"%1\"").arg(name);
101         return QLatin1String("main frame");
102     } else {
103         if (!name.isEmpty())
104             return QString::fromLatin1("frame \"%1\"").arg(name);
105         return QLatin1String("frame (anonymous)");
106     }
107 }
108
109 static QString drtDescriptionSuitableForTestResult(const WebCore::KURL& _url)
110 {
111     QUrl url = _url;
112     return url.toString();
113 }
114
115 static QString drtDescriptionSuitableForTestResult(const WebCore::ResourceError& error)
116 {
117     QString failingURL = error.failingURL();
118     return QString::fromLatin1("<NSError domain NSURLErrorDomain, code %1, failing URL \"%2\">").arg(error.errorCode()).arg(failingURL);
119 }
120
121 static QString drtDescriptionSuitableForTestResult(const WebCore::ResourceRequest& request)
122 {
123     QString url = request.url().string();
124     return QString::fromLatin1("<NSURLRequest %1>").arg(url);
125 }
126
127 static QString drtDescriptionSuitableForTestResult(const WebCore::ResourceResponse& response)
128 {
129     QString text = response.httpStatusText();
130     if (text.isEmpty())
131         return QLatin1String("(null)");
132
133     return text;
134 }
135
136
137 namespace WebCore
138 {
139
140 FrameLoaderClientQt::FrameLoaderClientQt()
141     : m_frame(0)
142     , m_webFrame(0)
143     , m_pluginView(0)
144     , m_hasSentResponseToPlugin(false)
145     , m_firstData(false)
146     , m_policyFunction(0)
147     , m_loadSucceeded(false)
148 {
149     connect(this, SIGNAL(sigCallPolicyFunction(int)), this, SLOT(slotCallPolicyFunction(int)), Qt::QueuedConnection);
150 }
151
152
153 FrameLoaderClientQt::~FrameLoaderClientQt()
154 {
155 }
156
157 void FrameLoaderClientQt::setFrame(QWebFrame* webFrame, Frame* frame)
158 {
159     m_webFrame = webFrame;
160     m_frame = frame;
161     if (!m_webFrame || !m_webFrame->page()) {
162         qWarning("FrameLoaderClientQt::setFrame frame without Page!");
163         return;
164     }
165
166     connect(this, SIGNAL(loadStarted()),
167             m_webFrame->page(), SIGNAL(loadStarted()));
168     connect(this, SIGNAL(loadProgress(int)),
169             m_webFrame->page(), SIGNAL(loadProgress(int)));
170     connect(this, SIGNAL(loadFinished(bool)),
171             m_webFrame->page(), SIGNAL(loadFinished(bool)));
172     connect(this, SIGNAL(titleChanged(const QString&)),
173             m_webFrame, SIGNAL(titleChanged(const QString&)));
174 }
175
176 QWebFrame* FrameLoaderClientQt::webFrame() const
177 {
178     return m_webFrame;
179 }
180
181 void FrameLoaderClientQt::callPolicyFunction(FramePolicyFunction function, PolicyAction action)
182 {
183     ASSERT(!m_policyFunction);
184     ASSERT(function);
185
186     m_policyFunction = function;
187     emit sigCallPolicyFunction(action);
188 }
189
190 void FrameLoaderClientQt::slotCallPolicyFunction(int action)
191 {
192     if (!m_frame || !m_policyFunction)
193         return;
194     FramePolicyFunction function = m_policyFunction;
195     m_policyFunction = 0;
196     (m_frame->loader()->*function)(WebCore::PolicyAction(action));
197 }
198
199 bool FrameLoaderClientQt::hasWebView() const
200 {
201     //notImplemented();
202     return true;
203 }
204
205 void FrameLoaderClientQt::savePlatformDataToCachedFrame(CachedFrame*) 
206 {
207     notImplemented();
208 }
209
210 void FrameLoaderClientQt::transitionToCommittedFromCachedFrame(CachedFrame*)
211 {
212 }
213
214 void FrameLoaderClientQt::transitionToCommittedForNewPage()
215 {
216     ASSERT(m_frame);
217     ASSERT(m_webFrame);
218
219     QBrush brush = m_webFrame->page()->palette().brush(QPalette::Base);
220     QColor backgroundColor = brush.style() == Qt::SolidPattern ? brush.color() : QColor();
221     m_frame->createView(m_webFrame->page()->viewportSize(),
222                         backgroundColor, !backgroundColor.alpha(),
223                         m_webFrame->page()->fixedLayoutSize(),
224                         m_webFrame->page()->useFixedLayout(),
225                         (ScrollbarMode)m_webFrame->scrollBarPolicy(Qt::Horizontal),
226                         (ScrollbarMode)m_webFrame->scrollBarPolicy(Qt::Vertical));
227 }
228
229
230 void FrameLoaderClientQt::makeRepresentation(DocumentLoader*)
231 {
232     // don't need this for now I think.
233 }
234
235
236 void FrameLoaderClientQt::forceLayout()
237 {
238     FrameView* view = m_frame->view();
239     if (view)
240         view->forceLayout(true);
241 }
242
243
244 void FrameLoaderClientQt::forceLayoutForNonHTML()
245 {
246 }
247
248
249 void FrameLoaderClientQt::setCopiesOnScroll()
250 {
251     // apparently mac specific
252 }
253
254
255 void FrameLoaderClientQt::detachedFromParent2()
256 {
257 }
258
259
260 void FrameLoaderClientQt::detachedFromParent3()
261 {
262 }
263
264 void FrameLoaderClientQt::dispatchDidHandleOnloadEvents()
265 {
266     // don't need this one
267     if (dumpFrameLoaderCallbacks)
268         printf("%s - didHandleOnloadEventsForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
269
270 }
271
272
273 void FrameLoaderClientQt::dispatchDidReceiveServerRedirectForProvisionalLoad()
274 {
275     if (dumpFrameLoaderCallbacks)
276         printf("%s - didReceiveServerRedirectForProvisionalLoadForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
277
278     notImplemented();
279 }
280
281
282 void FrameLoaderClientQt::dispatchDidCancelClientRedirect()
283 {
284     if (dumpFrameLoaderCallbacks)
285         printf("%s - didCancelClientRedirectForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
286
287     notImplemented();
288 }
289
290
291 void FrameLoaderClientQt::dispatchWillPerformClientRedirect(const KURL& url,
292                                                             double interval,
293                                                             double fireDate)
294 {
295     if (dumpFrameLoaderCallbacks)
296         printf("%s - willPerformClientRedirectToURL: %s \n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)), qPrintable(drtDescriptionSuitableForTestResult(url)));
297
298     notImplemented();
299 }
300
301
302 void FrameLoaderClientQt::dispatchDidChangeLocationWithinPage()
303 {
304     if (dumpFrameLoaderCallbacks)
305         printf("%s - didChangeLocationWithinPageForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
306
307     if (!m_webFrame)
308         return;
309
310     emit m_webFrame->urlChanged(m_webFrame->url());
311     m_webFrame->page()->d->updateNavigationActions();
312 }
313
314
315 void FrameLoaderClientQt::dispatchWillClose()
316 {
317     if (dumpFrameLoaderCallbacks)
318         printf("%s - willCloseFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
319 }
320
321
322 void FrameLoaderClientQt::dispatchDidStartProvisionalLoad()
323 {
324     if (dumpFrameLoaderCallbacks)
325         printf("%s - didStartProvisionalLoadForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
326
327     if (m_webFrame)
328         emit m_webFrame->provisionalLoad();
329 }
330
331
332 void FrameLoaderClientQt::dispatchDidReceiveTitle(const String& title)
333 {
334     if (dumpFrameLoaderCallbacks)
335         printf("%s - didReceiveTitle: %s\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)), qPrintable(QString(title)));
336
337     if (!m_webFrame)
338         return;
339
340
341
342     // ### hack
343     emit m_webFrame->urlChanged(m_webFrame->url());
344     emit titleChanged(title);
345 }
346
347
348 void FrameLoaderClientQt::dispatchDidCommitLoad()
349 {
350     if (dumpFrameLoaderCallbacks)
351         printf("%s - didCommitLoadForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
352
353     if (m_frame->tree()->parent() || !m_webFrame)
354         return;
355
356     m_webFrame->page()->d->updateNavigationActions();
357
358     // We should assume first the frame has no title. If it has, then the above dispatchDidReceiveTitle()
359     // will be called very soon with the correct title.
360     // This properly resets the title when we navigate to a URI without a title.
361     emit titleChanged(String());
362 }
363
364
365 void FrameLoaderClientQt::dispatchDidFinishDocumentLoad()
366 {
367     if (dumpFrameLoaderCallbacks)
368         printf("%s - didFinishDocumentLoadForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
369
370     if (QWebPagePrivate::drtRun) {
371         int unloadEventCount = m_frame->eventHandler()->pendingFrameUnloadEventCount();
372         if (unloadEventCount)
373             printf("%s - has %u onunload handler(s)\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)), unloadEventCount);
374     }
375
376     if (m_frame->tree()->parent() || !m_webFrame)
377         return;
378
379     m_webFrame->page()->d->updateNavigationActions();
380 }
381
382
383 void FrameLoaderClientQt::dispatchDidFinishLoad()
384 {
385     if (dumpFrameLoaderCallbacks)
386         printf("%s - didFinishLoadForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
387
388     m_loadSucceeded = true;
389
390     if (m_frame->tree()->parent() || !m_webFrame)
391         return;
392     m_webFrame->page()->d->updateNavigationActions();
393 }
394
395
396 void FrameLoaderClientQt::dispatchDidFirstLayout()
397 {
398     if (m_webFrame)
399         emit m_webFrame->initialLayoutCompleted();
400 }
401
402 void FrameLoaderClientQt::dispatchDidFirstVisuallyNonEmptyLayout()
403 {
404     notImplemented();
405 }
406
407 void FrameLoaderClientQt::dispatchShow()
408 {
409     notImplemented();
410 }
411
412
413 void FrameLoaderClientQt::cancelPolicyCheck()
414 {
415 //    qDebug() << "FrameLoaderClientQt::cancelPolicyCheck";
416     m_policyFunction = 0;
417 }
418
419
420 void FrameLoaderClientQt::dispatchWillSubmitForm(FramePolicyFunction function,
421                                                  PassRefPtr<FormState>)
422 {
423     notImplemented();
424     Q_ASSERT(!m_policyFunction);
425     // FIXME: This is surely too simple
426     callPolicyFunction(function, PolicyUse);
427 }
428
429
430 void FrameLoaderClientQt::dispatchDidLoadMainResource(DocumentLoader*)
431 {
432 }
433
434
435 void FrameLoaderClientQt::revertToProvisionalState(DocumentLoader*)
436 {
437     notImplemented();
438 }
439
440
441 void FrameLoaderClientQt::postProgressStartedNotification()
442 {
443     if (m_webFrame && m_frame->page()) {
444         emit loadStarted();
445         postProgressEstimateChangedNotification();
446     }
447     if (m_frame->tree()->parent() || !m_webFrame)
448         return;
449     m_webFrame->page()->d->updateNavigationActions();
450 }
451
452 void FrameLoaderClientQt::postProgressEstimateChangedNotification()
453 {
454     if (m_webFrame && m_frame->page())
455         emit loadProgress(qRound(m_frame->page()->progress()->estimatedProgress() * 100));
456 }
457
458 void FrameLoaderClientQt::postProgressFinishedNotification()
459 {
460     // send a mousemove event to
461     // (1) update the cursor to change according to whatever is underneath the mouse cursor right now
462     // (2) display the tool tip if the mouse hovers a node which has a tool tip
463     if (m_frame && m_frame->eventHandler() && m_webFrame->page()) {
464         QWidget* view = m_webFrame->page()->view();
465         if (view && view->hasFocus()) {
466             QPoint localPos = view->mapFromGlobal(QCursor::pos());
467             if (view->rect().contains(localPos)) {
468                 QMouseEvent event(QEvent::MouseMove, localPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier);
469                 m_frame->eventHandler()->mouseMoved(PlatformMouseEvent(&event, 0));
470             }
471         }
472     }
473
474     if (m_webFrame && m_frame->page())
475         emit loadFinished(m_loadSucceeded);
476 }
477
478 void FrameLoaderClientQt::setMainFrameDocumentReady(bool b)
479 {
480     // this is only interesting once we provide an external API for the DOM
481 }
482
483
484 void FrameLoaderClientQt::willChangeTitle(DocumentLoader*)
485 {
486     // no need for, dispatchDidReceiveTitle is the right callback
487 }
488
489
490 void FrameLoaderClientQt::didChangeTitle(DocumentLoader *)
491 {
492     // no need for, dispatchDidReceiveTitle is the right callback
493 }
494
495
496 void FrameLoaderClientQt::finishedLoading(DocumentLoader* loader)
497 {
498     if (!m_pluginView) {
499         if(m_firstData) {
500             FrameLoader *fl = loader->frameLoader();
501             fl->setEncoding(m_response.textEncodingName(), false);
502             m_firstData = false; 
503         }
504     }
505     else {
506         m_pluginView->didFinishLoading();
507         m_pluginView = 0;
508         m_hasSentResponseToPlugin = false;
509     }
510 }
511
512
513 bool FrameLoaderClientQt::canShowMIMEType(const String& MIMEType) const
514 {
515     if (MIMETypeRegistry::isSupportedImageMIMEType(MIMEType))
516         return true;
517
518     if (MIMETypeRegistry::isSupportedNonImageMIMEType(MIMEType))
519         return true;
520
521     if (m_frame && m_frame->settings()  && m_frame->settings()->arePluginsEnabled()
522         && PluginDatabase::installedPlugins()->isMIMETypeRegistered(MIMEType))
523         return true;
524
525     return false;
526 }
527
528 bool FrameLoaderClientQt::representationExistsForURLScheme(const String& URLScheme) const
529 {
530     return false;
531 }
532
533
534 String FrameLoaderClientQt::generatedMIMETypeForURLScheme(const String& URLScheme) const
535 {
536     notImplemented();
537     return String();
538 }
539
540
541 void FrameLoaderClientQt::frameLoadCompleted()
542 {
543     // Note: Can be called multiple times.
544 }
545
546
547 void FrameLoaderClientQt::restoreViewState()
548 {
549     if (!m_webFrame)
550         return;
551     emit m_webFrame->page()->restoreFrameStateRequested(m_webFrame);
552 }
553
554
555 void FrameLoaderClientQt::provisionalLoadStarted()
556 {
557     // don't need to do anything here
558 }
559
560
561 void FrameLoaderClientQt::didFinishLoad()
562 {
563 //     notImplemented();
564 }
565
566
567 void FrameLoaderClientQt::prepareForDataSourceReplacement()
568 {
569 }
570
571 void FrameLoaderClientQt::setTitle(const String&, const KURL&)
572 {
573     // no need for, dispatchDidReceiveTitle is the right callback
574 }
575
576
577 String FrameLoaderClientQt::userAgent(const KURL& url)
578 {
579     if (m_webFrame) {
580         return m_webFrame->page()->userAgentForUrl(url);
581     }
582     return String();
583 }
584
585 void FrameLoaderClientQt::dispatchDidReceiveIcon()
586 {
587     if (dumpFrameLoaderCallbacks)
588         printf("%s - didReceiveIconForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
589
590     if (m_webFrame) {
591         emit m_webFrame->iconChanged();
592     }
593 }
594
595 void FrameLoaderClientQt::frameLoaderDestroyed()
596 {
597     delete m_webFrame;
598     m_frame = 0;
599     m_webFrame = 0;
600
601     delete this;
602 }
603
604 bool FrameLoaderClientQt::canHandleRequest(const WebCore::ResourceRequest&) const
605 {
606     return true;
607 }
608
609 void FrameLoaderClientQt::windowObjectCleared()
610 {
611     if (dumpFrameLoaderCallbacks)
612         printf("%s - didClearWindowObjectForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
613
614     if (m_webFrame)
615         emit m_webFrame->javaScriptWindowObjectCleared();
616 }
617
618 void FrameLoaderClientQt::documentElementAvailable()
619 {
620     return;
621 }
622
623 void FrameLoaderClientQt::didPerformFirstNavigation() const
624 {
625     if (m_frame->tree()->parent() || !m_webFrame)
626         return;
627     m_webFrame->page()->d->updateNavigationActions();
628 }
629
630 void FrameLoaderClientQt::registerForIconNotification(bool)
631 {
632     notImplemented();
633 }
634
635 void FrameLoaderClientQt::updateGlobalHistory()
636 {
637     QWebHistoryInterface *history = QWebHistoryInterface::defaultInterface();
638     if (history)
639         history->addHistoryEntry(m_frame->loader()->documentLoader()->urlForHistory().prettyURL());
640 }
641
642 void FrameLoaderClientQt::updateGlobalHistoryRedirectLinks()
643 {
644 }
645
646 bool FrameLoaderClientQt::shouldGoToHistoryItem(WebCore::HistoryItem *item) const
647 {
648     return true;
649 }
650
651 void FrameLoaderClientQt::saveViewStateToItem(WebCore::HistoryItem* item)
652 {
653     QWebHistoryItem historyItem(new QWebHistoryItemPrivate(item));
654     emit m_webFrame->page()->saveFrameStateRequested(m_webFrame, &historyItem);
655 }
656
657 bool FrameLoaderClientQt::canCachePage() const
658 {
659     return true;
660 }
661
662 void FrameLoaderClientQt::setMainDocumentError(WebCore::DocumentLoader* loader, const WebCore::ResourceError& error)
663 {
664     if (!m_pluginView) {
665         if (m_firstData) {
666             loader->frameLoader()->setEncoding(m_response.textEncodingName(), false);
667             m_firstData = false;
668         }
669     } else {
670         m_pluginView->didFail(error);
671         m_pluginView = 0;
672         m_hasSentResponseToPlugin = false;
673     }
674 }
675
676 void FrameLoaderClientQt::committedLoad(WebCore::DocumentLoader* loader, const char* data, int length)
677 {
678     if (!m_pluginView) {
679         if (!m_frame)
680             return;
681         FrameLoader *fl = loader->frameLoader();
682         if (m_firstData) {
683             fl->setEncoding(m_response.textEncodingName(), false);
684             m_firstData = false;
685         }
686         fl->addData(data, length);
687     }
688     
689     // We re-check here as the plugin can have been created
690     if (m_pluginView) {
691         if (!m_hasSentResponseToPlugin) {
692             m_pluginView->didReceiveResponse(loader->response());
693             m_hasSentResponseToPlugin = true;
694         }
695         m_pluginView->didReceiveData(data, length);
696     }
697 }
698
699 WebCore::ResourceError FrameLoaderClientQt::cancelledError(const WebCore::ResourceRequest& request)
700 {
701     return ResourceError("Error", -999, request.url().prettyURL(),
702             QCoreApplication::translate("QWebFrame", "Request cancelled", 0, QCoreApplication::UnicodeUTF8));
703 }
704
705 // copied from WebKit/Misc/WebKitErrors[Private].h
706 enum {
707     WebKitErrorCannotShowMIMEType =                             100,
708     WebKitErrorCannotShowURL =                                  101,
709     WebKitErrorFrameLoadInterruptedByPolicyChange =             102,
710     WebKitErrorCannotUseRestrictedPort = 103,
711     WebKitErrorCannotFindPlugIn =                               200,
712     WebKitErrorCannotLoadPlugIn =                               201,
713     WebKitErrorJavaUnavailable =                                202,
714 };
715
716 WebCore::ResourceError FrameLoaderClientQt::blockedError(const WebCore::ResourceRequest& request)
717 {
718     return ResourceError("Error", WebKitErrorCannotUseRestrictedPort, request.url().prettyURL(),
719             QCoreApplication::translate("QWebFrame", "Request blocked", 0, QCoreApplication::UnicodeUTF8));
720 }
721
722
723 WebCore::ResourceError FrameLoaderClientQt::cannotShowURLError(const WebCore::ResourceRequest& request)
724 {
725     return ResourceError("Error", WebKitErrorCannotShowURL, request.url().string(),
726             QCoreApplication::translate("QWebFrame", "Cannot show URL", 0, QCoreApplication::UnicodeUTF8));
727 }
728
729 WebCore::ResourceError FrameLoaderClientQt::interruptForPolicyChangeError(const WebCore::ResourceRequest& request)
730 {
731     return ResourceError("Error", WebKitErrorFrameLoadInterruptedByPolicyChange, request.url().string(),
732             QCoreApplication::translate("QWebFrame", "Frame load interruped by policy change", 0, QCoreApplication::UnicodeUTF8));
733 }
734
735 WebCore::ResourceError FrameLoaderClientQt::cannotShowMIMETypeError(const WebCore::ResourceResponse& response)
736 {
737     return ResourceError("Error", WebKitErrorCannotShowMIMEType, response.url().string(),
738             QCoreApplication::translate("QWebFrame", "Cannot show mimetype", 0, QCoreApplication::UnicodeUTF8));
739 }
740
741 WebCore::ResourceError FrameLoaderClientQt::fileDoesNotExistError(const WebCore::ResourceResponse& response)
742 {
743     return ResourceError("Error", -998 /* ### */, response.url().string(),
744             QCoreApplication::translate("QWebFrame", "File does not exist", 0, QCoreApplication::UnicodeUTF8));
745 }
746
747 WebCore::ResourceError FrameLoaderClientQt::pluginWillHandleLoadError(const WebCore::ResourceResponse& response)
748 {
749     notImplemented();
750     return ResourceError();
751 }
752
753 bool FrameLoaderClientQt::shouldFallBack(const WebCore::ResourceError&)
754 {
755     notImplemented();
756     return false;
757 }
758
759 WTF::PassRefPtr<WebCore::DocumentLoader> FrameLoaderClientQt::createDocumentLoader(const WebCore::ResourceRequest& request, const SubstituteData& substituteData)
760 {
761     RefPtr<DocumentLoader> loader = DocumentLoader::create(request, substituteData);
762     if (substituteData.isValid())
763         loader->setDeferMainResourceDataLoad(false);
764     return loader.release();
765 }
766
767 void FrameLoaderClientQt::download(WebCore::ResourceHandle* handle, const WebCore::ResourceRequest&, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&)
768 {
769 #if QT_VERSION >= 0x040400
770     if (!m_webFrame)
771         return;
772
773     QNetworkReplyHandler* handler = handle->getInternal()->m_job;
774     QNetworkReply* reply = handler->release();
775     if (reply) {
776         QWebPage *page = m_webFrame->page();
777         if (page->forwardUnsupportedContent())
778             emit m_webFrame->page()->unsupportedContent(reply);
779         else
780             reply->abort();
781     }
782 #endif
783 }
784
785 void FrameLoaderClientQt::assignIdentifierToInitialRequest(unsigned long identifier, WebCore::DocumentLoader* loader, const WebCore::ResourceRequest& request)
786 {
787     if (dumpResourceLoadCallbacks)
788         dumpAssignedUrls[identifier] = drtDescriptionSuitableForTestResult(request.url());
789 }
790
791 void FrameLoaderClientQt::dispatchWillSendRequest(WebCore::DocumentLoader*, unsigned long identifier, WebCore::ResourceRequest& newRequest, const WebCore::ResourceResponse& redirectResponse)
792 {
793     if (dumpResourceLoadCallbacks)
794         printf("%s - willSendRequest %s redirectResponse %s\n",
795                qPrintable(dumpAssignedUrls[identifier]),
796                qPrintable(drtDescriptionSuitableForTestResult(newRequest)),
797                qPrintable(drtDescriptionSuitableForTestResult(redirectResponse)));
798
799     // seems like the Mac code doesn't do anything here by default neither
800     //qDebug() << "FrameLoaderClientQt::dispatchWillSendRequest" << request.isNull() << request.url().string`();
801 }
802
803 bool
804 FrameLoaderClientQt::shouldUseCredentialStorage(DocumentLoader*, unsigned long)
805 {
806     notImplemented();
807     return false;
808 }
809
810 void FrameLoaderClientQt::dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long, const AuthenticationChallenge&)
811 {
812     notImplemented();
813 }
814
815 void FrameLoaderClientQt::dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long, const AuthenticationChallenge&)
816 {
817     notImplemented();
818 }
819
820 void FrameLoaderClientQt::dispatchDidReceiveResponse(WebCore::DocumentLoader*, unsigned long, const WebCore::ResourceResponse& response)
821 {
822
823     m_response = response;
824     m_firstData = true;
825     //qDebug() << "    got response from" << response.url().string();
826 }
827
828 void FrameLoaderClientQt::dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long, int)
829 {
830 }
831
832 void FrameLoaderClientQt::dispatchDidFinishLoading(WebCore::DocumentLoader* loader, unsigned long)
833 {
834 }
835
836 void FrameLoaderClientQt::dispatchDidFailLoading(WebCore::DocumentLoader* loader, unsigned long identifier, const WebCore::ResourceError& error)
837 {
838     if (dumpResourceLoadCallbacks)
839         printf("%s - didFailLoadingWithError: %s\n", qPrintable(dumpAssignedUrls[identifier]), qPrintable(drtDescriptionSuitableForTestResult(error)));
840
841     if (m_firstData) {
842         FrameLoader *fl = loader->frameLoader();
843         fl->setEncoding(m_response.textEncodingName(), false);
844         m_firstData = false;
845     }
846 }
847
848 bool FrameLoaderClientQt::dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&, int)
849 {
850     notImplemented();
851     return false;
852 }
853
854 void FrameLoaderClientQt::dispatchDidFailProvisionalLoad(const WebCore::ResourceError&)
855 {
856     if (dumpFrameLoaderCallbacks)
857         printf("%s - didFailProvisionalLoadWithError\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
858
859     m_loadSucceeded = false;
860 }
861
862 void FrameLoaderClientQt::dispatchDidFailLoad(const WebCore::ResourceError&)
863 {
864     if (dumpFrameLoaderCallbacks)
865         printf("%s - didFailLoadWithError\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame)));
866
867     m_loadSucceeded = false;
868 }
869
870 WebCore::Frame* FrameLoaderClientQt::dispatchCreatePage()
871 {
872     if (!m_webFrame)
873         return 0;
874     QWebPage *newPage = m_webFrame->page()->createWindow(QWebPage::WebBrowserWindow);
875     if (!newPage)
876         return 0;
877     return newPage->mainFrame()->d->frame;
878 }
879
880 void FrameLoaderClientQt::dispatchDecidePolicyForMIMEType(FramePolicyFunction function, const WebCore::String& MIMEType, const WebCore::ResourceRequest&)
881 {
882     // we need to call directly here
883     Q_ASSERT(!m_policyFunction);
884     m_policyFunction = function;
885     if (canShowMIMEType(MIMEType))
886         slotCallPolicyFunction(PolicyUse);
887     else
888         slotCallPolicyFunction(PolicyDownload);
889 }
890
891 void FrameLoaderClientQt::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function, const WebCore::NavigationAction& action, const WebCore::ResourceRequest& request, PassRefPtr<WebCore::FormState>, const WebCore::String&)
892 {
893     Q_ASSERT(!m_policyFunction);
894     Q_ASSERT(m_webFrame);
895     m_policyFunction = function;
896 #if QT_VERSION < 0x040400
897     QWebNetworkRequest r(request);
898 #else
899     QNetworkRequest r(request.toNetworkRequest());
900 #endif
901     QWebPage* page = m_webFrame->page();
902
903     if (!page->d->acceptNavigationRequest(0, r, QWebPage::NavigationType(action.type()))) {
904         if (action.type() == NavigationTypeFormSubmitted || action.type() == NavigationTypeFormResubmitted)
905             m_frame->loader()->resetMultipleFormSubmissionProtection();
906
907         if (action.type() == NavigationTypeLinkClicked && r.url().hasFragment()) {
908             ResourceRequest emptyRequest;
909             m_frame->loader()->activeDocumentLoader()->setLastCheckedRequest(emptyRequest);
910         }
911
912         slotCallPolicyFunction(PolicyIgnore);
913         return;
914     }
915     slotCallPolicyFunction(PolicyUse);
916 }
917
918 void FrameLoaderClientQt::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function, const WebCore::NavigationAction& action, const WebCore::ResourceRequest& request, PassRefPtr<WebCore::FormState>)
919 {
920     Q_ASSERT(!m_policyFunction);
921     Q_ASSERT(m_webFrame);
922     m_policyFunction = function;
923 #if QT_VERSION < 0x040400
924     QWebNetworkRequest r(request);
925 #else
926     QNetworkRequest r(request.toNetworkRequest());
927 #endif
928     QWebPage*page = m_webFrame->page();
929
930     if (!page->d->acceptNavigationRequest(m_webFrame, r, QWebPage::NavigationType(action.type()))) {
931         if (action.type() == NavigationTypeFormSubmitted || action.type() == NavigationTypeFormResubmitted)
932             m_frame->loader()->resetMultipleFormSubmissionProtection();
933
934         if (action.type() == NavigationTypeLinkClicked && r.url().hasFragment()) {
935             ResourceRequest emptyRequest;
936             m_frame->loader()->activeDocumentLoader()->setLastCheckedRequest(emptyRequest);
937         }
938
939         slotCallPolicyFunction(PolicyIgnore);
940         return;
941     }
942     slotCallPolicyFunction(PolicyUse);
943 }
944
945 void FrameLoaderClientQt::dispatchUnableToImplementPolicy(const WebCore::ResourceError&)
946 {
947     notImplemented();
948 }
949
950 void FrameLoaderClientQt::startDownload(const WebCore::ResourceRequest& request)
951 {
952 #if QT_VERSION >= 0x040400
953     if (!m_webFrame)
954         return;
955
956     QWebPage *page = m_webFrame->page();
957     emit m_webFrame->page()->downloadRequested(request.toNetworkRequest());
958 #endif
959 }
960
961 PassRefPtr<Frame> FrameLoaderClientQt::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
962                                         const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
963 {
964     if (!m_webFrame)
965         return 0;
966
967     QWebFrameData frameData;
968     frameData.url = url;
969     frameData.name = name;
970     frameData.ownerElement = ownerElement;
971     frameData.referrer = referrer;
972     frameData.allowsScrolling = allowsScrolling;
973     frameData.marginWidth = marginWidth;
974     frameData.marginHeight = marginHeight;
975
976     QWebFrame* webFrame = new QWebFrame(m_webFrame, &frameData);
977     emit m_webFrame->page()->frameCreated(webFrame);
978
979     RefPtr<Frame> childFrame = adoptRef(webFrame->d->frame);
980
981     // ### set override encoding if we have one
982
983     FrameLoadType loadType = m_frame->loader()->loadType();
984     FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedBackForwardList;
985
986     childFrame->loader()->loadURLIntoChildFrame(frameData.url, frameData.referrer, childFrame.get());
987
988     // The frame's onload handler may have removed it from the document.
989     if (!childFrame->tree()->parent())
990         return 0;
991
992     return childFrame.release();
993 }
994
995 ObjectContentType FrameLoaderClientQt::objectContentType(const KURL& url, const String& _mimeType)
996 {
997 //    qDebug()<<" ++++++++++++++++ url is "<<url.prettyURL()<<", mime = "<<_mimeType;
998     if (_mimeType == "application/x-qt-plugin" || _mimeType == "application/x-qt-styled-widget")
999         return ObjectContentOtherPlugin;
1000
1001     if (url.isEmpty() && !_mimeType.length())
1002         return ObjectContentNone;
1003
1004     String mimeType = _mimeType;
1005     if (!mimeType.length()) {
1006         QFileInfo fi(url.path());
1007         mimeType = MIMETypeRegistry::getMIMETypeForExtension(fi.suffix());
1008     }
1009
1010     if (!mimeType.length())
1011         return ObjectContentFrame;
1012
1013     if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
1014         return ObjectContentImage;
1015
1016     if (PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType))
1017         return ObjectContentNetscapePlugin;
1018
1019     if (m_frame->page() && m_frame->page()->pluginData() && m_frame->page()->pluginData()->supportsMimeType(mimeType))
1020         return ObjectContentOtherPlugin;
1021
1022     if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
1023         return ObjectContentFrame;
1024
1025     if (url.protocol() == "about")
1026         return ObjectContentFrame;
1027
1028     return ObjectContentNone;
1029 }
1030
1031 static const CSSPropertyID qstyleSheetProperties[] = {
1032     CSSPropertyColor,
1033     CSSPropertyFontFamily,
1034     CSSPropertyFontSize,
1035     CSSPropertyFontStyle,
1036     CSSPropertyFontWeight
1037 };
1038
1039 const unsigned numqStyleSheetProperties = sizeof(qstyleSheetProperties) / sizeof(qstyleSheetProperties[0]);
1040
1041 class QtPluginWidget: public Widget
1042 {
1043 public:
1044     QtPluginWidget(QWidget* w = 0): Widget(w) {}
1045     ~QtPluginWidget()
1046     {
1047         if (platformWidget())
1048             platformWidget()->deleteLater();
1049     }
1050     virtual void invalidateRect(const IntRect& r)
1051     { 
1052         if (platformWidget())
1053             platformWidget()->update(r);
1054     }
1055     virtual void frameRectsChanged()
1056     {
1057         if (!platformWidget())
1058             return;
1059
1060         IntRect windowRect = convertToContainingWindow(IntRect(0, 0, frameRect().width(), frameRect().height()));
1061         platformWidget()->setGeometry(windowRect);
1062
1063         ScrollView* parentScrollView = parent();
1064         if (!parentScrollView)
1065             return;
1066
1067         ASSERT(parentScrollView->isFrameView());
1068         IntRect clipRect(static_cast<FrameView*>(parentScrollView)->windowClipRect());
1069         clipRect.move(-windowRect.x(), -windowRect.y());
1070         clipRect.intersect(platformWidget()->rect());
1071         platformWidget()->setMask(QRegion(clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height()));
1072     }
1073 };
1074
1075 Widget* FrameLoaderClientQt::createPlugin(const IntSize& pluginSize, HTMLPlugInElement* element, const KURL& url, const Vector<String>& paramNames,
1076                                           const Vector<String>& paramValues, const String& mimeType, bool loadManually)
1077 {
1078 //     qDebug()<<"------ Creating plugin in FrameLoaderClientQt::createPlugin for "<<url.prettyURL() << mimeType;
1079 //     qDebug()<<"------\t url = "<<url.prettyURL();
1080
1081     if (!m_webFrame)
1082         return 0;
1083
1084     QStringList params;
1085     QStringList values;
1086     QString classid(element->getAttribute("classid"));
1087
1088     for (int i = 0; i < paramNames.size(); ++i) {
1089         params.append(paramNames[i]);
1090         if (paramNames[i] == "classid")
1091             classid = paramValues[i];
1092     }
1093     for (int i = 0; i < paramValues.size(); ++i)
1094         values.append(paramValues[i]);
1095
1096     QString urlStr(url.string());
1097     QUrl qurl = urlStr;
1098
1099     QObject* object = 0;
1100
1101     if (mimeType == "application/x-qt-plugin" || mimeType == "application/x-qt-styled-widget") {
1102         object = m_webFrame->page()->createPlugin(classid, qurl, params, values);
1103 #ifndef QT_NO_STYLE_STYLESHEET
1104         QWidget* widget = qobject_cast<QWidget*>(object);
1105         if (widget && mimeType == "application/x-qt-styled-widget") {
1106
1107             QString styleSheet = element->getAttribute("style");
1108             if (!styleSheet.isEmpty())
1109                 styleSheet += QLatin1Char(';');
1110
1111             for (int i = 0; i < numqStyleSheetProperties; ++i) {
1112                 CSSPropertyID property = qstyleSheetProperties[i];
1113
1114                 styleSheet += QString::fromLatin1(::getPropertyName(property));
1115                 styleSheet += QLatin1Char(':');
1116                 styleSheet += computedStyle(element)->getPropertyValue(property);
1117                 styleSheet += QLatin1Char(';');
1118             }
1119
1120             widget->setStyleSheet(styleSheet);
1121         }
1122 #endif // QT_NO_STYLE_STYLESHEET
1123     }
1124
1125 #if QT_VERSION >= 0x040400
1126         if (!object) {
1127             QWebPluginFactory* factory = m_webFrame->page()->pluginFactory();
1128             if (factory)
1129                 object = factory->create(mimeType, qurl, params, values);
1130         }
1131 #endif
1132
1133         if (object) {
1134             QWidget* widget = qobject_cast<QWidget*>(object);
1135             if (widget) {
1136                 QWidget* view = m_webFrame->page()->view();
1137                 if (view)
1138                     widget->setParent(view);
1139                 QtPluginWidget* w = new QtPluginWidget();
1140                 w->setPlatformWidget(widget);
1141                 // Make sure it's invisible until properly placed into the layout
1142                 w->setFrameRect(IntRect(0, 0, 0, 0));
1143                 return w;
1144             }
1145             // FIXME: make things work for widgetless plugins as well
1146             delete object;
1147     } else { // NPAPI Plugins
1148         PluginView* pluginView = PluginView::create(m_frame, pluginSize, element, url,
1149             paramNames, paramValues, mimeType, loadManually);
1150         return pluginView;
1151     }
1152
1153     return 0;
1154 }
1155
1156 void FrameLoaderClientQt::redirectDataToPlugin(Widget* pluginWidget)
1157 {
1158     ASSERT(!m_pluginView);
1159     m_pluginView = static_cast<PluginView*>(pluginWidget);
1160     m_hasSentResponseToPlugin = false;
1161 }
1162
1163 Widget* FrameLoaderClientQt::createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL& baseURL,
1164                                                     const Vector<String>& paramNames, const Vector<String>& paramValues)
1165 {
1166     notImplemented();
1167     return 0;
1168 }
1169
1170 String FrameLoaderClientQt::overrideMediaType() const
1171 {
1172     return String();
1173 }
1174
1175 QString FrameLoaderClientQt::chooseFile(const QString& oldFile)
1176 {
1177     return webFrame()->page()->chooseFile(webFrame(), oldFile);
1178 }
1179
1180 }
1181
1182 #include "moc_FrameLoaderClientQt.cpp"