static void readCallback(GObject* source, GAsyncResult* res, gpointer data) { ResourceHandle* handle = static_cast<ResourceHandle*>(data); ResourceHandleInternal* d = handle->getInternal(); ResourceHandleClient* client = handle->client(); if (d->m_cancelled || !client) { cleanupGioOperation(handle); return; } gssize nread; GError *error = 0; nread = g_input_stream_read_finish(d->m_input_stream, res, &error); if (error) { cleanupGioOperation(handle); // FIXME: error client->didFinishLoading(handle); return; } else if (!nread) { client->didFinishLoading(handle); g_input_stream_close_async(d->m_input_stream, G_PRIORITY_DEFAULT, NULL, closeCallback, handle); return; } d->m_total += nread; client->didReceiveData(handle, d->m_buffer, nread, d->m_total); g_input_stream_read_async(d->m_input_stream, d->m_buffer, d->m_bufsize, G_PRIORITY_DEFAULT, d->m_cancellable, readCallback, handle); }
static void openCallback(GObject* source, GAsyncResult* res, gpointer data) { ResourceHandle* handle = static_cast<ResourceHandle*>(data); ResourceHandleInternal* d = handle->getInternal(); ResourceHandleClient* client = handle->client(); if (d->m_cancelled || !client) { cleanupGioOperation(handle); return; } GFileInputStream* in; GError *error = NULL; in = g_file_read_finish(G_FILE(source), res, &error); if (error) { cleanupGioOperation(handle); // FIXME: error client->didFinishLoading(handle); return; } d->m_input_stream = G_INPUT_STREAM(in); d->m_bufsize = 8192; d->m_buffer = static_cast<char*>(g_malloc(d->m_bufsize)); d->m_total = 0; g_input_stream_read_async(d->m_input_stream, d->m_buffer, d->m_bufsize, G_PRIORITY_DEFAULT, d->m_cancellable, readCallback, handle); }
// This callback will not be called if the content sniffer is disabled in startHttp. static void contentSniffedCallback(SoupMessage* msg, const char* sniffedType, GHashTable *params, gpointer data) { if (sniffedType) { const char* officialType = soup_message_headers_get_one(msg->response_headers, "Content-Type"); if (!officialType || strcmp(officialType, sniffedType)) soup_message_headers_set_content_type(msg->response_headers, sniffedType, params); } if (statusWillBeHandledBySoup(msg->status_code)) return; RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data); if (!handle) return; ResourceHandleInternal* d = handle->getInternal(); if (d->m_cancelled) return; ResourceHandleClient* client = handle->client(); if (!client) return; fillResponseFromMessage(msg, &d->m_response); client->didReceiveResponse(handle.get(), d->m_response); }
static gboolean parseDataUrl(gpointer callback_data) { ResourceHandle* handle = static_cast<ResourceHandle*>(callback_data); String data = handle->request().url().string(); ASSERT(data.startsWith("data:", false)); String header; bool base64 = false; int index = data.find(','); if (index != -1) { header = data.substring(5, index - 5).lower(); data = data.substring(index + 1); if (header.endsWith(";base64")) { base64 = true; header = header.left(header.length() - 7); } } else data = String(); data = decodeURLEscapeSequences(data); size_t outLength = 0; char* outData = 0; if (base64 && !data.isEmpty()) { // Use the GLib Base64 if available, since WebCore's decoder isn't // general-purpose and fails on Acid3 test 97 (whitespace). outData = reinterpret_cast<char*>(g_base64_decode(data.utf8().data(), &outLength)); } if (header.isEmpty()) header = "text/plain;charset=US-ASCII"; ResourceHandleClient* client = handle->getInternal()->client(); ResourceResponse response; response.setMimeType(extractMIMETypeFromMediaType(header)); response.setTextEncodingName(extractCharsetFromMediaType(header)); if (outData) response.setExpectedContentLength(outLength); else response.setExpectedContentLength(data.length()); response.setHTTPStatusCode(200); client->didReceiveResponse(handle, response); if (outData) client->didReceiveData(handle, outData, outLength, 0); else client->didReceiveData(handle, data.latin1().data(), data.length(), 0); g_free(outData); client->didFinishLoading(handle); return FALSE; }
static void contentSniffedCallback(SoupMessage* msg, const char* sniffedType, GHashTable *params, gpointer data) { if (sniffedType) { const char* officialType = soup_message_headers_get_one(msg->response_headers, "Content-Type"); if (!officialType || strcmp(officialType, sniffedType)) soup_message_headers_set_content_type(msg->response_headers, sniffedType, params); } // The 304 status code (SOUP_STATUS_NOT_MODIFIED) needs to be fed // into WebCore, as opposed to other kinds of redirections, which // are handled by soup directly, so we special-case it here and in // gotChunk. if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code) || (SOUP_STATUS_IS_REDIRECTION(msg->status_code) && (msg->status_code != SOUP_STATUS_NOT_MODIFIED)) || (msg->status_code == SOUP_STATUS_UNAUTHORIZED)) return; RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data); if (!handle) return; ResourceHandleInternal* d = handle->getInternal(); if (d->m_cancelled) return; ResourceHandleClient* client = handle->client(); if (!client) return; fillResponseFromMessage(msg, &d->m_response); client->didReceiveResponse(handle.get(), d->m_response); }
void QNetworkReplyHandler::sendResponseIfNeeded() { m_shouldSendResponse = (m_loadMode != LoadNormal); if (m_shouldSendResponse) return; if (m_reply->error()) return; if (m_responseSent || !m_resourceHandle) return; m_responseSent = true; ResourceHandleClient* client = m_resourceHandle->client(); if (!client) return; WebCore::String contentType = m_reply->header(QNetworkRequest::ContentTypeHeader).toString(); WebCore::String encoding = extractCharsetFromMediaType(contentType); WebCore::String mimeType = extractMIMETypeFromMediaType(contentType); if (mimeType.isEmpty()) { // let's try to guess from the extension QString extension = m_reply->url().path(); int index = extension.lastIndexOf(QLatin1Char('.')); if (index > 0) { extension = extension.mid(index + 1); mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension); } } KURL url(m_reply->url()); ResourceResponse response(url, mimeType, m_reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), encoding, String()); if (url.isLocalFile()) { client->didReceiveResponse(m_resourceHandle, response); return; } // The status code is equal to 0 for protocols not in the HTTP family. int statusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (url.protocolInHTTPFamily()) { String suggestedFilename = filenameFromHTTPContentDisposition(QString::fromAscii(m_reply->rawHeader("Content-Disposition"))); if (!suggestedFilename.isEmpty()) response.setSuggestedFilename(suggestedFilename); else response.setSuggestedFilename(url.lastPathComponent()); response.setHTTPStatusCode(statusCode); response.setHTTPStatusText(m_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray().constData()); // Add remaining headers. foreach (const QByteArray& headerName, m_reply->rawHeaderList()) { response.setHTTPHeaderField(QString::fromAscii(headerName), QString::fromAscii(m_reply->rawHeader(headerName))); } }
void QNetworkReplyHandler::finish() { ASSERT(m_replyWrapper && m_replyWrapper->reply() && !wasAborted()); ResourceHandleClient* client = m_resourceHandle->client(); if (!client) { m_replyWrapper = 0; return; } if (m_replyWrapper->wasRedirected()) { m_replyWrapper = 0; m_queue.push(&QNetworkReplyHandler::start); return; } if (!m_replyWrapper->reply()->error() || shouldIgnoreHttpError(m_replyWrapper->reply(), m_replyWrapper->responseContainsData())) client->didFinishLoading(m_resourceHandle, 0); else { QUrl url = m_replyWrapper->reply()->url(); int httpStatusCode = m_replyWrapper->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (httpStatusCode) { ResourceError error("HTTP", httpStatusCode, url.toString(), m_replyWrapper->reply()->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString()); client->didFail(m_resourceHandle, error); } else { ResourceError error("QtNetwork", m_replyWrapper->reply()->error(), url.toString(), m_replyWrapper->reply()->errorString()); client->didFail(m_resourceHandle, error); } } m_replyWrapper = 0; }
static void gotHeadersCallback(SoupMessage* msg, gpointer data) { // For 401, we will accumulate the resource body, and only use it // in case authentication with the soup feature doesn't happen if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) { soup_message_body_set_accumulate(msg->response_body, TRUE); return; } // For all the other responses, we handle each chunk ourselves, // and we don't need msg->response_body to contain all of the data // we got, when we finish downloading. soup_message_body_set_accumulate(msg->response_body, FALSE); RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data); // The content-sniffed callback will handle the response if WebCore // require us to sniff. if(!handle || statusWillBeHandledBySoup(msg->status_code) || handle->shouldContentSniff()) return; ResourceHandleInternal* d = handle->getInternal(); if (d->m_cancelled) return; ResourceHandleClient* client = handle->client(); if (!client) return; fillResponseFromMessage(msg, &d->m_response); client->didReceiveResponse(handle.get(), d->m_response); }
void QNetworkReplyHandler::sendResponseIfNeeded() { ASSERT(m_replyWrapper && m_replyWrapper->reply() && !wasAborted()); if (m_replyWrapper->reply()->error() && m_replyWrapper->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).isNull()) return; ResourceHandleClient* client = m_resourceHandle->client(); if (!client) return; WTF::String mimeType = m_replyWrapper->mimeType(); if (mimeType.isEmpty()) { // let's try to guess from the extension mimeType = MIMETypeRegistry::getMIMETypeForPath(m_replyWrapper->reply()->url().path()); } KURL url(m_replyWrapper->reply()->url()); ResourceResponse response(url, mimeType.lower(), m_replyWrapper->reply()->header(QNetworkRequest::ContentLengthHeader).toLongLong(), m_replyWrapper->encoding(), String()); if (url.isLocalFile()) { client->didReceiveResponse(m_resourceHandle, response); return; } // The status code is equal to 0 for protocols not in the HTTP family. int statusCode = m_replyWrapper->reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (url.protocolIsInHTTPFamily()) { String suggestedFilename = filenameFromHTTPContentDisposition(QString::fromLatin1(m_replyWrapper->reply()->rawHeader("Content-Disposition"))); if (!suggestedFilename.isEmpty()) response.setSuggestedFilename(suggestedFilename); else { Vector<String> extensions = MIMETypeRegistry::getExtensionsForMIMEType(mimeType); if (extensions.isEmpty()) response.setSuggestedFilename(url.lastPathComponent()); else { // If the suffix doesn't match the MIME type, correct the suffix. QString filename = url.lastPathComponent(); const String suffix = QMimeDatabase().suffixForFileName(filename); if (!extensions.contains(suffix)) { filename.chop(suffix.length()); filename += MIMETypeRegistry::getPreferredExtensionForMIMEType(mimeType); } response.setSuggestedFilename(filename); } } response.setHTTPStatusCode(statusCode); response.setHTTPStatusText(m_replyWrapper->reply()->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray().constData()); // Add remaining headers. foreach (const QNetworkReply::RawHeaderPair& pair, m_replyWrapper->reply()->rawHeaderPairs()) response.setHTTPHeaderField(QString::fromLatin1(pair.first), QString::fromLatin1(pair.second)); }
bool ResourceHandle::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace) { ResourceHandleClient* client = this->client(); if (d->m_usesAsyncCallbacks) { if (client) client->canAuthenticateAgainstProtectionSpaceAsync(this, protectionSpace); else continueCanAuthenticateAgainstProtectionSpace(false); return false; // Ignored by caller. } return client && client->canAuthenticateAgainstProtectionSpace(this, protectionSpace); }
/* * This is being called for each HTTP header in the response. This includes '\r\n' * for the last line of the header. * * We will add each HTTP Header to the ResourceResponse and on the termination * of the header (\r\n) we will parse Content-Type and Content-Disposition and * update the ResourceResponse and then send it away. * */ static size_t headerCallback(char* ptr, size_t size, size_t nmemb, void* data) { ResourceHandle* job = static_cast<ResourceHandle*>(data); ResourceHandleInternal* d = job->getInternal(); unsigned int totalSize = size * nmemb; ResourceHandleClient* client = d->client(); if (!client) { return totalSize; } String header(static_cast<const char*>(ptr), totalSize); /* * a) We can finish and send the ResourceResponse * b) We will add the current header to the HTTPHeaderMap of the ResourceResponse */ if (header == String("\r\n")) { CURL* h = d->m_handle; CURLcode err; double contentLength = 0; err = curl_easy_getinfo(h, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &contentLength); d->m_response.setExpectedContentLength(static_cast<long long int>(contentLength)); const char* hdr; err = curl_easy_getinfo(h, CURLINFO_EFFECTIVE_URL, &hdr); d->m_response.setUrl(KURL(hdr)); long httpCode = 0; err = curl_easy_getinfo(h, CURLINFO_RESPONSE_CODE, &httpCode); d->m_response.setHTTPStatusCode(httpCode); d->m_response.setMimeType(extractMIMETypeFromMediaType(d->m_response.httpHeaderField("Content-Type"))); d->m_response.setTextEncodingName(extractCharsetFromMediaType(d->m_response.httpHeaderField("Content-Type"))); d->m_response.setSuggestedFilename(filenameFromHTTPContentDisposition(d->m_response.httpHeaderField("Content-Disposition"))); client->didReceiveResponse(job, d->m_response); } else { int splitPos = header.find(":"); if (splitPos != -1) d->m_response.setHTTPHeaderField(header.left(splitPos), header.substring(splitPos+1).stripWhiteSpace()); } return totalSize; }
void ResourceHandleInternal::didFinishLoading(WebURLLoader*, double finishTime) { ASSERT(m_client); if (m_state != ConnectionStateReceivedResponse && m_state != ConnectionStateReceivingData) CRASH(); m_state = ConnectionStateFinishedLoading; m_client->didFinishLoading(m_owner, finishTime); }
void ResourceHandleInternal::didReceiveCachedMetadata(WebURLLoader*, const char* data, int dataLength) { ASSERT(m_client); if (m_state != ConnectionStateReceivedResponse && m_state != ConnectionStateReceivingData) CRASH(); m_client->didReceiveCachedMetadata(m_owner, data, dataLength); }
void ResourceHandleInternal::willSendRequest( WebURLLoader*, WebURLRequest& request, const WebURLResponse& response) { ASSERT(m_client); ASSERT(!request.isNull()); ASSERT(!response.isNull()); m_client->willSendRequest(m_owner, request.toMutableResourceRequest(), response.toResourceResponse()); }
static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data) { if (!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) return; ResourceHandle* handle = static_cast<ResourceHandle*>(data); if (!handle) return; ResourceHandleInternal* d = handle->getInternal(); if (d->m_cancelled) return; ResourceHandleClient* client = handle->client(); if (!client) return; client->didReceiveData(handle, chunk->data, chunk->length, false); }
static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data) { if (statusWillBeHandledBySoup(msg->status_code)) return; RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data); if (!handle) return; ResourceHandleInternal* d = handle->getInternal(); if (d->m_cancelled) return; ResourceHandleClient* client = handle->client(); if (!client) return; client->didReceiveData(handle.get(), chunk->data, chunk->length, false); }
void MyResourceLoader::loadData(const String& data) { LOGD("Loading data (%s) ...", data.latin1().data()); ResourceHandleClient* client = m_handle->client(); int index = data.find(','); if (index == -1) { client->cannotShowURL(m_handle); return; } String mediaType = data.substring(0, index); String base64 = data.substring(index + 1); bool decode = mediaType.endsWith(";base64", false); if (decode) mediaType = mediaType.left(mediaType.length() - 7); // 7 for base64; if (mediaType.isEmpty()) mediaType = "text/plain;charset=US-ASCII"; String mimeType = extractMIMETypeFromMediaType(mediaType); String charset = extractCharsetFromMediaType(mediaType); ResourceResponse response; response.setMimeType(mimeType); if (decode) { base64 = decodeURLEscapeSequences(base64); response.setTextEncodingName(charset); client->didReceiveResponse(m_handle, response); // FIXME: This is annoying. WebCore's Base64 decoder chokes on spaces. // That is correct with strict decoding but html authors (particularly // the acid3 authors) put spaces in the data which should be ignored. // Remove them here before sending to the decoder. Vector<char> in; CString str = base64.latin1(); const char* chars = str.data(); unsigned i = 0; while (i < str.length()) { char c = chars[i]; // Don't send spaces or control characters. if (c != ' ' && c != '\n' && c != '\t' && c != '\b' && c != '\f' && c != '\r') in.append(chars[i]); i++; } Vector<char> out; if (base64Decode(in, out) && out.size() > 0) client->didReceiveData(m_handle, out.data(), out.size(), 0); } else { base64 = decodeURLEscapeSequences(base64, TextEncoding(charset)); response.setTextEncodingName("UTF-16"); client->didReceiveResponse(m_handle, response); if (base64.length() > 0) client->didReceiveData(m_handle, (const char*)base64.characters(), base64.length() * sizeof(UChar), 0); } client->didFinishLoading(m_handle, 0); }
static void gotHeadersCallback(SoupMessage* msg, gpointer data) { if (!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) return; ResourceHandle* handle = static_cast<ResourceHandle*>(data); if (!handle) return; ResourceHandleInternal* d = handle->getInternal(); if (d->m_cancelled) return; ResourceHandleClient* client = handle->client(); if (!client) return; fillResponseFromMessage(msg, &d->m_response); client->didReceiveResponse(handle, d->m_response); soup_message_set_flags(msg, SOUP_MESSAGE_OVERWRITE_CHUNKS); }
static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data) { if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code) || (SOUP_STATUS_IS_REDIRECTION(msg->status_code) && (msg->status_code != SOUP_STATUS_NOT_MODIFIED)) || (msg->status_code == SOUP_STATUS_UNAUTHORIZED)) return; RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data); if (!handle) return; ResourceHandleInternal* d = handle->getInternal(); if (d->m_cancelled) return; ResourceHandleClient* client = handle->client(); if (!client) return; client->didReceiveData(handle.get(), chunk->data, chunk->length, false); }
// Called at the end of the message, with all the necessary about the last informations. // Doesn't get called for redirects. static void finishedCallback(SoupSession *session, SoupMessage* msg, gpointer data) { RefPtr<ResourceHandle> handle = adoptRef(static_cast<ResourceHandle*>(data)); // TODO: maybe we should run this code even if there's no client? if (!handle) return; ResourceHandleInternal* d = handle->getInternal(); ResourceHandleClient* client = handle->client(); if (!client) return; if (d->m_cancelled) return; if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code)) { char* uri = soup_uri_to_string(soup_message_get_uri(msg), false); ResourceError error(g_quark_to_string(SOUP_HTTP_ERROR), msg->status_code, uri, String::fromUTF8(msg->reason_phrase)); g_free(uri); client->didFail(handle.get(), error); return; } if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) { fillResponseFromMessage(msg, &d->m_response); client->didReceiveResponse(handle.get(), d->m_response); // WebCore might have cancelled the job in the while if (d->m_cancelled) return; if (msg->response_body->data) client->didReceiveData(handle.get(), msg->response_body->data, msg->response_body->length, true); } client->didFinishLoading(handle.get()); }
void QNetworkReplyHandler::finish() { m_shouldFinish = (m_loadMode != LoadNormal); if (m_shouldFinish) return; sendResponseIfNeeded(); if (!m_resourceHandle) return; ResourceHandleClient* client = m_resourceHandle->client(); if (!client) { m_reply->deleteLater(); m_reply = 0; return; } QNetworkReply* oldReply = m_reply; if (m_redirected) { resetState(); start(); } else if (!m_reply->error() || ignoreHttpError(m_reply, m_responseDataSent)) { client->didFinishLoading(m_resourceHandle); } else { QUrl url = m_reply->url(); int httpStatusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (httpStatusCode) { ResourceError error("HTTP", httpStatusCode, url.toString(), m_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString()); client->didFail(m_resourceHandle, error); } else { ResourceError error("QtNetwork", m_reply->error(), url.toString(), m_reply->errorString()); client->didFail(m_resourceHandle, error); } } oldReply->deleteLater(); if (oldReply == m_reply) m_reply = 0; }
void ResourceHandleInternal::didReceiveResponse(WebURLLoader*, const WebURLResponse& response) { ASSERT(m_client); ASSERT(!response.isNull()); bool isMultipart = response.isMultipartPayload(); bool isValidStateTransition = (m_state == ConnectionStateStarted || m_state == ConnectionStateReceivedResponse); // In the case of multipart loads, calls to didReceiveData & didReceiveResponse can be interleaved. if (!isMultipart && !isValidStateTransition) CRASH(); m_state = ConnectionStateReceivedResponse; m_client->didReceiveResponse(m_owner, response.toResourceResponse()); }
void ResourceHandleInternal::didReceiveData( WebURLLoader*, const char* data, int dataLength) { ASSERT(m_client); if (m_state != ConnectionStateReceivedResponse && m_state != ConnectionStateReceivingData) CRASH(); m_state = ConnectionStateReceivingData; // FIXME(yurys): it looks like lengthReceived is always the same as // dataLength and that the latter parameter can be eliminated. // See WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=31019 m_client->didReceiveData(m_owner, data, dataLength, dataLength); }
// Called at the end of the message, with all the necessary about the last informations. // Doesn't get called for redirects. static void finishedCallback(SoupSession *session, SoupMessage* msg, gpointer data) { ResourceHandle* handle = static_cast<ResourceHandle*>(data); // TODO: maybe we should run this code even if there's no client? if (!handle) return; ResourceHandleInternal* d = handle->getInternal(); // The message has been handled. d->m_msg = NULL; ResourceHandleClient* client = handle->client(); if (!client) return; if (d->m_cancelled) return; if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code)) { char* uri = soup_uri_to_string(soup_message_get_uri(msg), FALSE); ResourceError error("webkit-network-error", ERROR_TRANSPORT, uri, String::fromUTF8(msg->reason_phrase)); g_free(uri); client->didFail(handle, error); return; } else if (!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) { fillResponseFromMessage(msg, &d->m_response); client->didReceiveResponse(handle, d->m_response); // WebCore might have cancelled the job in the while if (d->m_cancelled) return; if (msg->response_body->data) client->didReceiveData(handle, msg->response_body->data, msg->response_body->length, true); } client->didFinishLoading(handle); }
void QNetworkReplyHandler::finish() { ASSERT(m_replyWrapper && m_replyWrapper->reply() && !wasAborted()); ResourceHandleClient* client = m_resourceHandle->client(); if (!client) { m_replyWrapper = nullptr; return; } if (m_replyWrapper->wasRedirected()) { m_replyWrapper = nullptr; m_queue.push(&QNetworkReplyHandler::start); return; } if (!m_replyWrapper->reply()->error() || shouldIgnoreHttpError(m_replyWrapper->reply(), m_replyWrapper->responseContainsData())) client->didFinishLoading(m_resourceHandle, 0); else client->didFail(m_resourceHandle, errorForReply(m_replyWrapper->reply())); m_replyWrapper = nullptr; }
void MyResourceLoader::loadFile(const String& file) { LOGD("Loading file (%s) ...", file.latin1().data()); FILE* f = fopen(file.latin1().data(), "r"); ResourceHandleClient* client = m_handle->client(); if (!f) { client->didFail(m_handle, ResourceError("", -14, file, "Could not open file")); } else { ResourceResponse response; response.setTextEncodingName("utf-8"); response.setMimeType(mimeTypeForExtension(file)); client->didReceiveResponse(m_handle, response); char buf[512]; while (true) { int res = fread(buf, 1, sizeof(buf), f); if (res <= 0) break; client->didReceiveData(m_handle, buf, res, 0); } fclose(f); client->didFinishLoading(m_handle, 0); } }
void QNetworkReplyHandler::timeout() { if (!m_replyWrapper || wasAborted()) return; // The request is already finished, but is probably just waiting in the queue to get processed. // In this case we ignore the timeout and proceed as normal. if (m_replyWrapper->isFinished()) return; ResourceHandleClient* client = m_resourceHandle->client(); if (!client) { m_replyWrapper.clear(); return; } ASSERT(m_replyWrapper->reply()); ResourceError timeoutError("QtNetwork", QNetworkReply::TimeoutError, m_replyWrapper->reply()->url().toString(), "Request timed out"); timeoutError.setIsTimeout(true); client->didFail(m_resourceHandle, timeoutError); m_replyWrapper.clear(); }
/* * This is being called for each HTTP header in the response. This includes '\r\n' * for the last line of the header. * * We will add each HTTP Header to the ResourceResponse and on the termination * of the header (\r\n) we will parse Content-Type and Content-Disposition and * update the ResourceResponse and then send it away. * */ static size_t headerCallback(char* ptr, size_t size, size_t nmemb, void* data) { ResourceHandle* job = static_cast<ResourceHandle*>(data); ResourceHandleInternal* d = job->getInternal(); if (d->m_cancelled) return 0; size_t totalSize = size * nmemb; ResourceHandleClient* client = d->client(); String header(static_cast<const char*>(ptr), totalSize); /* * a) We can finish and send the ResourceResponse * b) We will add the current header to the HTTPHeaderMap of the ResourceResponse * * The HTTP standard requires to use \r\n but for compatibility it recommends to * accept also \n. */ if (header == String("\r\n") || header == String("\n")) { CURL* h = d->m_handle; CURLcode err; double contentLength = 0; err = curl_easy_getinfo(h, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &contentLength); d->m_response.setExpectedContentLength(static_cast<long long int>(contentLength)); const char* hdr; err = curl_easy_getinfo(h, CURLINFO_EFFECTIVE_URL, &hdr); d->m_response.setUrl(KURL(hdr)); long httpCode = 0; err = curl_easy_getinfo(h, CURLINFO_RESPONSE_CODE, &httpCode); d->m_response.setHTTPStatusCode(httpCode); d->m_response.setMimeType(extractMIMETypeFromMediaType(d->m_response.httpHeaderField("Content-Type"))); d->m_response.setTextEncodingName(extractCharsetFromMediaType(d->m_response.httpHeaderField("Content-Type"))); d->m_response.setSuggestedFilename(filenameFromHTTPContentDisposition(d->m_response.httpHeaderField("Content-Disposition"))); // HTTP redirection if (httpCode >= 300 && httpCode < 400) { String location = d->m_response.httpHeaderField("location"); if (!location.isEmpty()) { KURL newURL = KURL(job->request().url(), location); ResourceRequest redirectedRequest = job->request(); redirectedRequest.setURL(newURL); if (client) client->willSendRequest(job, redirectedRequest, d->m_response); d->m_request.setURL(newURL); return totalSize; } } if (client) client->didReceiveResponse(job, d->m_response); d->m_response.setResponseFired(true); } else { int splitPos = header.find(":"); if (splitPos != -1) d->m_response.setHTTPHeaderField(header.left(splitPos), header.substring(splitPos+1).stripWhiteSpace()); } return totalSize; }
void ResourceHandleInternal::didSendData( WebURLLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) { ASSERT(m_client); m_client->didSendData(m_owner, bytesSent, totalBytesToBeSent); }
void ResourceHandleInternal::didFail(WebURLLoader*, const WebURLError& error) { ASSERT(m_client); m_state = ConnectionStateFailed; m_client->didFail(m_owner, error); }