Changeset 91855 in webkit
- Timestamp:
- Jul 27, 2011 10:40:57 AM (13 years ago)
- Location:
- trunk/Source/WebKit/qt
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/qt/Api/qwebframe.cpp
r88534 r91855 803 803 static inline void clearCoreFrame(WebCore::Frame* frame) 804 804 { 805 frame->loader()->activeDocumentLoader()->writer()->begin(); 806 frame->loader()->activeDocumentLoader()->writer()->end(); 805 WebCore::DocumentLoader* documentLoader = frame->loader()->activeDocumentLoader(); 806 Q_ASSERT(documentLoader); 807 documentLoader->writer()->begin(); 808 documentLoader->writer()->end(); 807 809 } 808 810 -
trunk/Source/WebKit/qt/ChangeLog
r91845 r91855 1 2011-07-27 Caio Marcelo de Oliveira Filho <caio.oliveira@openbossa.org> 2 3 [Qt] QtWebkit never finishes loading sites when they are loaded after an initial QUrl fails to load. 4 https://bugs.webkit.org/show_bug.cgi?id=61328 5 6 Reviewed by Andreas Kling. 7 8 Change the hooks in FrameLoaderClient we use for emitting signals. Instead of 9 emitting signals in the progress notification functions, we use the 10 dispatchDid{Start,Finish,Fail}* functions. The main reason behind this change is 11 that loading code is prepared to handle load() when inside those functions. 12 13 The crash was being caused by setUrl() (and load()) being called when 14 loadFinished(false) was emitted. The problem here is that when 15 postProgressFinishedNotification the FrameLoader wasn't ready for taking a load() 16 call again, because it was still the ProvisionalLoadState but with the 17 provisionalDocumentLoader already removed. 18 19 To emulate the same behavior that QtWebKit had when using 20 postProgressFinishedNotification, we now keep track of the frame originating the 21 load, and emit the signals when this frame's client is called. 22 23 The patch keeps the existing semantics for QWebPage signals, but we now emit the 24 QWebFrame signals everytime, not only when they are the originating frame for 25 loading. 26 27 * Api/qwebframe.cpp: 28 (clearCoreFrame): Document our assumption that activeDocumentLoader will exist. 29 30 * WebCoreSupport/FrameLoaderClientQt.h: Remove m_loadError, add a boolean to keep 31 track whether the frame is originating the load. Remove the signals from 32 FrameLoaderClientQt since we will emit QWebFrame and QWebPage signals directly. 33 34 * WebCoreSupport/FrameLoaderClientQt.cpp: 35 (WebCore::FrameLoaderClientQt::FrameLoaderClientQt): Initialize m_isOriginatingLoad. 36 37 (WebCore::FrameLoaderClientQt::setFrame): Do not connect QWebFrame and QWebPage 38 signals to our signals for load/finished, signal emission will be done manually. 39 40 (WebCore::FrameLoaderClientQt::dispatchDidStartProvisionalLoad): Emit 41 loadStarted() signal and make the first notification of estimation change, that 42 Qt API tests expect to exist and notify 10%. 43 44 (WebCore::FrameLoaderClientQt::dispatchDidFinishLoad): Remove reference to 45 m_loadError and emit loadFinished() signal. 46 47 (WebCore::FrameLoaderClientQt::postProgressStartedNotification): Remove signal 48 emission and mark the originating load as true, since only the originating frame 49 gets this call in its client. 50 51 (WebCore::FrameLoaderClientQt::postProgressFinishedNotification): Remove signal 52 emission. 53 54 (WebCore::FrameLoaderClientQt::callErrorPageExtension): Return whether the call 55 was successful or not. This wasn't necessary before because a successful call for 56 error page would lead to a load(), that cleared the m_loadError. 57 (WebCore::FrameLoaderClientQt::dispatchDidFailProvisionalLoad): Remove reference 58 to m_loadError and emit finished signal indicating error if ErrorPage extension 59 doesn't handle it. 60 (WebCore::FrameLoaderClientQt::dispatchDidFailLoad): Ditto. 61 62 (WebCore::FrameLoaderClientQt::emitLoadStarted): Emit the loadStarted() signal 63 for the QWebFrame, and if the originating load also do for the QWebPage. 64 65 (WebCore::FrameLoaderClientQt::emitLoadFinished): Same as before but for 66 loadFinished(). Take care to reset the originating load flag before the signals 67 are emitted, since they might want to set it back again. 68 69 * tests/qwebframe/tst_qwebframe.cpp: 70 (URLSetter::URLSetter): Object that sets the url using either load() or setUrl() 71 when a certain signal is emitted in the frame. 72 73 (URLSetter::execute): 74 (tst_QWebFrame::loadInSignalHandlers_data): 75 (tst_QWebFrame::loadInSignalHandlers): New test inspired by the bug test case. This test 76 crashes without this patch applied. 77 1 78 2011-07-27 Caio Marcelo de Oliveira Filho <caio.oliveira@openbossa.org> 2 79 -
trunk/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp
r91797 r91855 211 211 , m_hasSentResponseToPlugin(false) 212 212 , m_hasRepresentation(false) 213 , m_ loadError(ResourceError())213 , m_isOriginatingLoad(false) 214 214 { 215 215 } … … 230 230 } 231 231 232 connect(this, SIGNAL(loadStarted()),233 m_webFrame->page(), SIGNAL(loadStarted()));234 connect(this, SIGNAL(loadStarted()),235 m_webFrame, SIGNAL(loadStarted()));236 232 connect(this, SIGNAL(loadProgress(int)), 237 233 m_webFrame->page(), SIGNAL(loadProgress(int))); 238 connect(this, SIGNAL(loadFinished(bool)),239 m_webFrame->page(), SIGNAL(loadFinished(bool)));240 234 241 235 // FIXME: The queued connection here is needed because of a problem with QNetworkAccessManager. … … 244 238 m_webFrame->page(), SIGNAL(unsupportedContent(QNetworkReply*)), Qt::QueuedConnection); 245 239 246 connect(this, SIGNAL(loadFinished(bool)),247 m_webFrame, SIGNAL(loadFinished(bool)));248 240 connect(this, SIGNAL(titleChanged(QString)), 249 241 m_webFrame, SIGNAL(titleChanged(QString))); … … 455 447 m_lastRequestedUrl = m_frame->loader()->activeDocumentLoader()->requestURL(); 456 448 457 if (m_webFrame) 458 emit m_webFrame->provisionalLoad(); 449 if (!m_webFrame) 450 return; 451 emitLoadStarted(); 452 postProgressEstimateChangedNotification(); 453 emit m_webFrame->provisionalLoad(); 459 454 } 460 455 … … 533 528 printf("%s - didFinishLoadForFrame\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame))); 534 529 535 // Clears the previous error.536 m_loadError = ResourceError();537 538 530 if (!m_webFrame) 539 531 return; 532 540 533 m_webFrame->page()->d->updateNavigationActions(); 534 emitLoadFinished(true); 541 535 } 542 536 … … 586 580 void FrameLoaderClientQt::postProgressStartedNotification() 587 581 { 588 if (m_webFrame && m_frame->page()) { 589 // As a new load have started, clear the previous error. 590 m_loadError = ResourceError(); 591 emit loadStarted(); 592 postProgressEstimateChangedNotification(); 593 } 582 if (m_webFrame && m_frame->page()) 583 m_isOriginatingLoad = true; 594 584 if (m_frame->tree()->parent() || !m_webFrame) 595 585 return; … … 618 608 } 619 609 } 620 621 if (m_webFrame && m_frame->page())622 emit loadFinished(m_loadError.isNull());623 610 } 624 611 … … 1139 1126 } 1140 1127 1141 voidFrameLoaderClientQt::callErrorPageExtension(const WebCore::ResourceError& error)1128 bool FrameLoaderClientQt::callErrorPageExtension(const WebCore::ResourceError& error) 1142 1129 { 1143 1130 QWebPage* page = m_webFrame->page(); 1144 if (page->supportsExtension(QWebPage::ErrorPageExtension)) { 1145 QWebPage::ErrorPageExtensionOption option; 1146 1147 if (error.domain() == "QtNetwork") 1148 option.domain = QWebPage::QtNetwork; 1149 else if (error.domain() == "HTTP") 1150 option.domain = QWebPage::Http; 1151 else if (error.domain() == "WebKit") 1152 option.domain = QWebPage::WebKit; 1153 else 1154 return; 1155 1156 option.url = QUrl(error.failingURL()); 1157 option.frame = m_webFrame; 1158 option.error = error.errorCode(); 1159 option.errorString = error.localizedDescription(); 1160 1161 QWebPage::ErrorPageExtensionReturn output; 1162 if (!page->extension(QWebPage::ErrorPageExtension, &option, &output)) 1163 return; 1164 1165 KURL baseUrl(output.baseUrl); 1166 KURL failingUrl(option.url); 1167 1168 WebCore::ResourceRequest request(baseUrl); 1169 WTF::RefPtr<WebCore::SharedBuffer> buffer = WebCore::SharedBuffer::create(output.content.constData(), output.content.length()); 1170 WebCore::SubstituteData substituteData(buffer, output.contentType, output.encoding, failingUrl); 1171 m_frame->loader()->load(request, substituteData, false); 1172 } 1131 if (!page->supportsExtension(QWebPage::ErrorPageExtension)) 1132 return false; 1133 1134 QWebPage::ErrorPageExtensionOption option; 1135 if (error.domain() == "QtNetwork") 1136 option.domain = QWebPage::QtNetwork; 1137 else if (error.domain() == "HTTP") 1138 option.domain = QWebPage::Http; 1139 else if (error.domain() == "WebKit") 1140 option.domain = QWebPage::WebKit; 1141 else 1142 return false; 1143 1144 option.url = QUrl(error.failingURL()); 1145 option.frame = m_webFrame; 1146 option.error = error.errorCode(); 1147 option.errorString = error.localizedDescription(); 1148 1149 QWebPage::ErrorPageExtensionReturn output; 1150 if (!page->extension(QWebPage::ErrorPageExtension, &option, &output)) 1151 return false; 1152 1153 KURL baseUrl(output.baseUrl); 1154 KURL failingUrl(option.url); 1155 1156 WebCore::ResourceRequest request(baseUrl); 1157 WTF::RefPtr<WebCore::SharedBuffer> buffer = WebCore::SharedBuffer::create(output.content.constData(), output.content.length()); 1158 WebCore::SubstituteData substituteData(buffer, output.contentType, output.encoding, failingUrl); 1159 m_frame->loader()->load(request, substituteData, false); 1160 return true; 1173 1161 } 1174 1162 … … 1178 1166 printf("%s - didFailProvisionalLoadWithError\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame))); 1179 1167 1180 m_loadError = error; 1181 if (!error.isNull() && !error.isCancellation()) 1182 callErrorPageExtension(error); 1168 if (!error.isNull() && !error.isCancellation()) { 1169 if (callErrorPageExtension(error)) 1170 return; 1171 } 1172 1173 if (m_webFrame) 1174 emitLoadFinished(false); 1183 1175 } 1184 1176 … … 1188 1180 printf("%s - didFailLoadWithError\n", qPrintable(drtDescriptionSuitableForTestResult(m_frame))); 1189 1181 1190 m_loadError = error; 1191 if (!error.isNull() && !error.isCancellation()) 1192 callErrorPageExtension(error); 1182 if (!error.isNull() && !error.isCancellation()) { 1183 if (callErrorPageExtension(error)) 1184 return; 1185 } 1186 1187 if (m_webFrame) 1188 emitLoadFinished(false); 1193 1189 } 1194 1190 … … 1689 1685 } 1690 1686 1687 void FrameLoaderClientQt::emitLoadStarted() 1688 { 1689 QWebPage* webPage = m_webFrame->page(); 1690 if (m_isOriginatingLoad && webPage) 1691 emit webPage->loadStarted(); 1692 emit m_webFrame->loadStarted(); 1693 } 1694 1695 void FrameLoaderClientQt::emitLoadFinished(bool ok) 1696 { 1697 // Signal handlers can lead to a new load, that will use the member again. 1698 const bool wasOriginatingLoad = m_isOriginatingLoad; 1699 m_isOriginatingLoad = false; 1700 1701 QWebPage* webPage = m_webFrame->page(); 1702 if (wasOriginatingLoad && webPage) 1703 emit webPage->loadFinished(ok); 1704 emit m_webFrame->loadFinished(ok); 1705 } 1706 1691 1707 } 1692 1708 -
trunk/Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.h
r91797 r91855 68 68 friend class ::QWebFrame; 69 69 void callPolicyFunction(FramePolicyFunction function, PolicyAction action); 70 void callErrorPageExtension(const ResourceError&); 70 bool callErrorPageExtension(const ResourceError&); 71 71 72 signals: 72 void loadStarted();73 73 void loadProgress(int d); 74 void loadFinished(bool);75 74 void titleChanged(const QString& title); 76 75 void unsupportedContent(QNetworkReply*); … … 266 265 267 266 private: 267 void emitLoadStarted(); 268 void emitLoadFinished(bool ok); 269 268 270 Frame *m_frame; 269 271 QWebFrame *m_webFrame; … … 280 282 281 283 KURL m_lastRequestedUrl; 282 ResourceError m_loadError;284 bool m_isOriginatingLoad; 283 285 }; 284 286 -
trunk/Source/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp
r91669 r91855 661 661 void setUrlThenLoads(); 662 662 void loadFinishedAfterNotFoundError(); 663 void loadInSignalHandlers_data(); 664 void loadInSignalHandlers(); 663 665 664 666 private: … … 3704 3706 } 3705 3707 3708 class URLSetter : public QObject { 3709 Q_OBJECT 3710 3711 public: 3712 enum Signal { 3713 LoadStarted, 3714 LoadFinished, 3715 ProvisionalLoad 3716 }; 3717 3718 enum Type { 3719 UseLoad, 3720 UseSetUrl 3721 }; 3722 3723 URLSetter(QWebFrame*, Signal, Type, const QUrl&); 3724 3725 public slots: 3726 void execute(); 3727 3728 signals: 3729 void finished(); 3730 3731 private: 3732 QWebFrame* m_frame; 3733 QUrl m_url; 3734 Type m_type; 3735 }; 3736 3737 Q_DECLARE_METATYPE(URLSetter::Signal) 3738 Q_DECLARE_METATYPE(URLSetter::Type) 3739 3740 URLSetter::URLSetter(QWebFrame* frame, Signal signal, URLSetter::Type type, const QUrl& url) 3741 : m_frame(frame), m_url(url), m_type(type) 3742 { 3743 if (signal == LoadStarted) 3744 connect(m_frame, SIGNAL(loadStarted()), SLOT(execute())); 3745 else if (signal == LoadFinished) 3746 connect(m_frame, SIGNAL(loadFinished(bool)), SLOT(execute())); 3747 else 3748 connect(m_frame, SIGNAL(provisionalLoad()), SLOT(execute())); 3749 } 3750 3751 void URLSetter::execute() 3752 { 3753 // We track only the first emission. 3754 m_frame->disconnect(this); 3755 if (m_type == URLSetter::UseLoad) 3756 m_frame->load(m_url); 3757 else 3758 m_frame->setUrl(m_url); 3759 connect(m_frame, SIGNAL(loadFinished(bool)), SIGNAL(finished())); 3760 } 3761 3762 void tst_QWebFrame::loadInSignalHandlers_data() 3763 { 3764 QTest::addColumn<URLSetter::Type>("type"); 3765 QTest::addColumn<URLSetter::Signal>("signal"); 3766 QTest::addColumn<QUrl>("url"); 3767 3768 const QUrl validUrl("qrc:/test2.html"); 3769 const QUrl invalidUrl("qrc:/invalid"); 3770 3771 QTest::newRow("call load() in loadStarted() after valid url") << URLSetter::UseLoad << URLSetter::LoadStarted << validUrl; 3772 QTest::newRow("call load() in loadStarted() after invalid url") << URLSetter::UseLoad << URLSetter::LoadStarted << invalidUrl; 3773 QTest::newRow("call load() in loadFinished() after valid url") << URLSetter::UseLoad << URLSetter::LoadFinished << validUrl; 3774 QTest::newRow("call load() in loadFinished() after invalid url") << URLSetter::UseLoad << URLSetter::LoadFinished << invalidUrl; 3775 QTest::newRow("call load() in provisionalLoad() after valid url") << URLSetter::UseLoad << URLSetter::ProvisionalLoad << validUrl; 3776 QTest::newRow("call load() in provisionalLoad() after invalid url") << URLSetter::UseLoad << URLSetter::ProvisionalLoad << invalidUrl; 3777 3778 QTest::newRow("call setUrl() in loadStarted() after valid url") << URLSetter::UseSetUrl << URLSetter::LoadStarted << validUrl; 3779 QTest::newRow("call setUrl() in loadStarted() after invalid url") << URLSetter::UseSetUrl << URLSetter::LoadStarted << invalidUrl; 3780 QTest::newRow("call setUrl() in loadFinished() after valid url") << URLSetter::UseSetUrl << URLSetter::LoadFinished << validUrl; 3781 QTest::newRow("call setUrl() in loadFinished() after invalid url") << URLSetter::UseSetUrl << URLSetter::LoadFinished << invalidUrl; 3782 QTest::newRow("call setUrl() in provisionalLoad() after valid url") << URLSetter::UseSetUrl << URLSetter::ProvisionalLoad << validUrl; 3783 QTest::newRow("call setUrl() in provisionalLoad() after invalid url") << URLSetter::UseSetUrl << URLSetter::ProvisionalLoad << invalidUrl; 3784 } 3785 3786 void tst_QWebFrame::loadInSignalHandlers() 3787 { 3788 QFETCH(URLSetter::Type, type); 3789 QFETCH(URLSetter::Signal, signal); 3790 QFETCH(QUrl, url); 3791 3792 QWebFrame* frame = m_page->mainFrame(); 3793 const QUrl urlForSetter("qrc:/test1.html"); 3794 URLSetter setter(frame, signal, type, urlForSetter); 3795 3796 frame->load(url); 3797 waitForSignal(&setter, SIGNAL(finished()), 200); 3798 QCOMPARE(frame->url(), urlForSetter); 3799 } 3800 3706 3801 QTEST_MAIN(tst_QWebFrame) 3707 3802 #include "tst_qwebframe.moc"
Note: See TracChangeset
for help on using the changeset viewer.