#include "http_file_source.hpp" #include "http_request.hpp" #include #include #include #include #include #include namespace mbgl { HTTPFileSource::Impl::Impl(const ResourceOptions& resourceOptions, const ClientOptions& clientOptions) : m_manager(new QNetworkAccessManager(this)), m_resourceOptions(resourceOptions.clone()), m_clientOptions(clientOptions.clone()) { QNetworkProxyFactory::setUseSystemConfiguration(true); } void HTTPFileSource::Impl::request(HTTPRequest* req) { QUrl url = req->requestUrl(); QPair, QVector>& data = m_pending[url]; QVector& requestsVector = data.second; requestsVector.append(req); if (requestsVector.size() > 1) { return; } QNetworkRequest networkRequest = req->networkRequest(); data.first = m_manager->get(networkRequest); connect(data.first, &QNetworkReply::finished, this, &HTTPFileSource::Impl::onReplyFinished); connect(data.first, &QNetworkReply::errorOccurred, this, &HTTPFileSource::Impl::onReplyFinished); } void HTTPFileSource::Impl::cancel(HTTPRequest* req) { QUrl url = req->requestUrl(); auto it = m_pending.find(url); if (it == m_pending.end()) { return; } QPair, QVector>& data = it.value(); QNetworkReply* reply = data.first; QVector& requestsVector = data.second; for (int i = 0; i < requestsVector.size(); ++i) { if (req == requestsVector.at(i)) { requestsVector.remove(i); break; } } if (requestsVector.empty()) { m_pending.erase(it); if (reply) reply->abort(); } } void HTTPFileSource::Impl::onReplyFinished() { QNetworkReply* reply = qobject_cast(sender()); #if defined(Q_OS_WASM) const QUrl& url = reply->url(); #else const QUrl& url = reply->request().url(); #endif auto it = m_pending.find(url); if (it == m_pending.end()) { #if defined(Q_OS_WASM) reply->abort(); #else reply->deleteLater(); #endif return; } QByteArray data = reply->readAll(); QVector& requestsVector = it.value().second; // Cannot use the iterator to walk the requestsVector // because calling handleNetworkReply() might get // requests added to the requestsVector. while (!requestsVector.isEmpty()) { requestsVector.takeFirst()->handleNetworkReply(reply, data); } m_pending.erase(it); #if defined(Q_OS_WASM) reply->abort(); #else reply->deleteLater(); #endif } void HTTPFileSource::Impl::setResourceOptions(ResourceOptions options) { m_resourceOptions = options; } ResourceOptions HTTPFileSource::Impl::getResourceOptions() { return m_resourceOptions.clone(); } void HTTPFileSource::Impl::setClientOptions(ClientOptions options) { m_clientOptions = options; } ClientOptions HTTPFileSource::Impl::getClientOptions() { return m_clientOptions.clone(); } HTTPFileSource::HTTPFileSource(const ResourceOptions& resourceOptions, const ClientOptions& clientOptions) : impl(std::make_unique(resourceOptions, clientOptions)) {} HTTPFileSource::~HTTPFileSource() = default; std::unique_ptr HTTPFileSource::request(const Resource& resource, Callback callback) { return std::make_unique(impl.get(), resource, callback); } void HTTPFileSource::setResourceOptions(ResourceOptions options) { impl->setResourceOptions(options.clone()); } ResourceOptions HTTPFileSource::getResourceOptions() { return impl->getResourceOptions(); } void HTTPFileSource::setClientOptions(ClientOptions options) { impl->setClientOptions(options.clone()); } ClientOptions HTTPFileSource::getClientOptions() { return impl->getClientOptions(); } } // namespace mbgl