Я унаследовал от QWebEngineUrlSchemeHandler.
Переопределенный метод requestStarted (QWebEngineUrlRequestJob * request)
После того, как я пытаюсь вызвать QWebEngineUrlRequestJob :: reply
например
void CustomUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *request)
{
qDebug() << "CustomUrlSchemeHandler::requestStarted -->>> " << request->requestUrl();
QMimeDatabase HelpViewer;
QMimeType mt = HelpViewer.mimeTypeForUrl(request->requestUrl());
const QString mimeType = mt.name();
QByteArray arr = QString::fromStdString("<html><body>Hello world</body></html>").toUtf8();
QBuffer *buffer = new QBuffer(&arr, this);
buffer->open(QIODevice::ReadOnly);
request->reply(mimeType.toLatin1(), buffer);
return;
}
Но программа вылетает.
см журнал:
[1126/113403:FATAL:weak_ptr.cc(26)] Check failed: sequence_checker_.CalledOnValidSequencedThread(). WeakPtrs must be checked on the same sequenced thread.
Backtrace:
base::debug::StackTrace::StackTrace [0x11A78691+33] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\debug\stack_trace_win.cc:205)
logging::LogMessage::~LogMessage [0x119CB2AF+63] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\logging.cc:544)
base::internal::WeakReference::Flag::IsValid [0x119FB75A+234] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\memory\weak_ptr.cc:28)
base::internal::WeakReference::is_valid [0x119FB7B2+50] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\memory\weak_ptr.cc:43)
base::WeakPtr<base::ObserverListBase<content::ServiceWorkerContextObserver> >::get [0x109EF57F+31] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\memory\weak_ptr.h:204)
base::internal::InvokeHelper<1,void,base::internal::RunnableAdapter<void (__thiscall content::DownloadResourceHandler::*)(void)>,base::internal::TypeList<base::WeakPtr<content::DownloadResourceHandler> const &> >::MakeItSo [0x107B8ADB+11] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\bind_internal.h:300)
base::internal::Invoker<base::IndexSequence<0>,base::internal::BindState<base::internal::RunnableAdapter<void (__thiscall content::DownloadResourceHandler::*)(void)>,void __cdecl(content::DownloadResourceHandler *),base::internal::TypeList<base::WeakPtr<c [0x107BAD0A+58] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\bind_internal.h:346)
base::Callback<net::URLRequestContext * __cdecl(void)>::Run [0x1096CACF+47] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\callback.h:396)
base::debug::TaskAnnotator::RunTask [0x11A9580D+541] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\debug\task_annotator.cc:64)
base::MessageLoop::RunTask [0x119DAAF8+456] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\message_loop\message_loop.cc:475)
base::MessageLoop::DeferOrRunPendingTask [0x119D9204+52] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\message_loop\message_loop.cc:485)
base::MessageLoop::DoWork [0x119D974D+221] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\message_loop\message_loop.cc:594)
base::MessagePumpForIO::DoRunLoop [0x11A980A2+50] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\message_loop\message_pump_win.cc:524)
base::MessagePumpWin::RunWithDispatcher [0x11A99B42+130] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\message_loop\message_pump_win.cc:51)
base::MessagePumpWin::Run [0x11A99AAC+28] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\message_loop\message_pump_win.cc:58)
base::MessageLoop::RunHandler [0x119DA907+247] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\message_loop\message_loop.cc:438)
base::RunLoop::Run [0x11A0A2E6+70] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\run_loop.cc:56)
base::MessageLoop::Run [0x119DA7BD+237] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\message_loop\message_loop.cc:288)
base::Thread::Run [0x11A20AF6+22] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\threading\thread.cc:199)
content::BrowserThreadImpl::IOThreadRun [0x10603B74+52] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\content\browser\browser_thread_impl.cc:212)
content::BrowserThreadImpl::Run [0x1060498B+235] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\content\browser\browser_thread_impl.cc:246)
base::Thread::ThreadMain [0x11A215F9+745] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\threading\thread.cc:248)
base::`anonymous namespace'::ThreadFunc [0x11A283B6+262] (e:\lib\qt\qt_git\qt5\qtwebengine\src\3rdparty\chromium\base\threading\platform_thread_win.cc:84)
BaseThreadInitThunk [0x75D57C04+36]
RtlInitializeExceptionChain [0x77E4AD1F+143]
RtlInitializeExceptionChain [0x77E4ACEA+90]
(No symbol) [0x00000000]
Одна из причин аварии заключается в том, что прибытие выходит за рамки.
Вы должны изменить
QByteArray arr = QString::fromStdString("<html><body>Hello world</body></html>").toUtf8();
QBuffer *buffer = new QBuffer(&arr, this);
в
QByteArray *pArr = new QByteArray(QString::fromStdString("<html><body>Hello world</body></html>").toUtf8());
QBuffer *buffer = new QBuffer(pArr, this);
Причина аварии не очевидна, потому что Документация Qt неясно на деталях, как QWebEngineUrlSchemeHandler
должно быть реализовано.
Ваша программа падает, потому что QWebEngineUrlRequestJob::reply()
использует буфер параметр позже, вне области действия вызывающего, вероятно, из другого потока. Локальная переменная QByteArray
прибытие который вы объявили в стеке (и использовал его в качестве резервного хранилища для буфера), к тому времени выйдет из области видимости, и QWebEngine будет обращаться к неверному указателю.
Другое дело, reply()
не берут на себя ответственность переданного буфер объект и никогда не удаляет его. Это приводит к утечке памяти. Вы не можете просто удалить его сразу после звонка reply()
по той же причине, что и выше. Для обеспечения буфер объект больше не нужен, подключите запрос«s destroyed()
сигнал к буфер«s deleteLater()
слот.
Вот полный рабочий и без утечек пример:
void CustomUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *request)
{
QBuffer *buffer = new QBuffer;
connect(request, SIGNAL(destroyed()), buffer, SLOT(deleteLater()));
buffer->open(QIODevice::WriteOnly);
buffer->write("<html><body>Hello world!</body></html>");
buffer->close();
request->reply("text/html", buffer);
}
Примечание: вам не нужно использовать QByteArray
совсем. Конструктор по умолчанию для QBuffer
выделяет собственное хранилище.