void ResourceHandle::onRedirect() { ResourceRequest newRequest = firstRequest(); newRequest.setURL(KURL(ParsedURLString, d->m_redirectUrl)); ResourceResponse response(firstRequest().url(), String(), 0, String(), String()); if (ResourceHandleClient* resourceHandleClient = client()) resourceHandleClient->willSendRequest(this, newRequest, response); }
void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge) { LOG(Network, "CFNet - didReceiveAuthenticationChallenge()"); ASSERT(d->m_currentWebChallenge.isNull()); // Since CFURLConnection networking relies on keeping a reference to the original CFURLAuthChallengeRef, // we make sure that is actually present ASSERT(challenge.cfURLAuthChallengeRef()); ASSERT(challenge.authenticationClient() == this); // Should be already set. if (!d->m_user.isNull() && !d->m_pass.isNull()) { RetainPtr<CFStringRef> user(AdoptCF, d->m_user.createCFString()); RetainPtr<CFStringRef> pass(AdoptCF, d->m_pass.createCFString()); RetainPtr<CFURLCredentialRef> credential(AdoptCF, CFURLCredentialCreate(kCFAllocatorDefault, user.get(), pass.get(), 0, kCFURLCredentialPersistenceNone)); KURL urlToStore; if (challenge.failureResponse().httpStatusCode() == 401) urlToStore = firstRequest().url(); CredentialStorage::set(core(credential.get()), challenge.protectionSpace(), urlToStore); CFURLConnectionUseCredential(d->m_connection.get(), credential.get(), challenge.cfURLAuthChallengeRef()); d->m_user = String(); d->m_pass = String(); // FIXME: Per the specification, the user shouldn't be asked for credentials if there were incorrect ones provided explicitly. return; } if (!client() || client()->shouldUseCredentialStorage(this)) { if (!d->m_initialCredential.isEmpty() || challenge.previousFailureCount()) { // The stored credential wasn't accepted, stop using it. // There is a race condition here, since a different credential might have already been stored by another ResourceHandle, // but the observable effect should be very minor, if any. CredentialStorage::remove(challenge.protectionSpace()); } if (!challenge.previousFailureCount()) { Credential credential = CredentialStorage::get(challenge.protectionSpace()); if (!credential.isEmpty() && credential != d->m_initialCredential) { ASSERT(credential.persistence() == CredentialPersistenceNone); if (challenge.failureResponse().httpStatusCode() == 401) { // Store the credential back, possibly adding it as a default for this directory. CredentialStorage::set(credential, challenge.protectionSpace(), firstRequest().url()); } RetainPtr<CFURLCredentialRef> cfCredential(AdoptCF, createCF(credential)); CFURLConnectionUseCredential(d->m_connection.get(), cfCredential.get(), challenge.cfURLAuthChallengeRef()); return; } } } d->m_currentWebChallenge = challenge; if (client()) client()->didReceiveAuthenticationChallenge(this, d->m_currentWebChallenge); }
void ResourceHandle::fileLoadTimer(Timer<ResourceHandle>*) { RefPtr<ResourceHandle> protector(this); deref(); // balances ref in start if (firstRequest().url().protocolIsData()) { handleDataURL(this); return; } String fileName = firstRequest().url().fileSystemPath(); HANDLE fileHandle = CreateFileW(fileName.charactersWithNullTermination(), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (fileHandle == INVALID_HANDLE_VALUE) { client()->didFail(this, ResourceError()); return; } ResourceResponse response; int dotPos = fileName.reverseFind('.'); int slashPos = fileName.reverseFind('/'); if (slashPos < dotPos && dotPos != -1) { String ext = fileName.substring(dotPos + 1); response.setMimeType(MIMETypeRegistry::getMIMETypeForExtension(ext)); } client()->didReceiveResponse(this, response); bool result = false; DWORD bytesRead = 0; do { const int bufferSize = 8192; char buffer[bufferSize]; result = ReadFile(fileHandle, &buffer, bufferSize, &bytesRead, 0); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=19793 // -1 means we do not provide any data about transfer size to inspector so it would use // Content-Length headers or content size to show transfer size. if (result && bytesRead) client()->didReceiveData(this, buffer, bytesRead, -1); // Check for end of file. } while (result && bytesRead); CloseHandle(fileHandle); client()->didFinishLoading(this, 0); }
void BlobResourceHandle::notifyResponseOnSuccess() { ASSERT(isMainThread()); bool isRangeRequest = m_rangeOffset != kPositionNotSpecified; ResourceResponse response(firstRequest().url(), m_blobData->contentType(), m_totalRemainingSize, String()); response.setHTTPStatusCode(isRangeRequest ? httpPartialContent : httpOK); response.setHTTPStatusText(isRangeRequest ? httpPartialContentText : httpOKText); response.setHTTPHeaderField(HTTPHeaderName::ContentType, m_blobData->contentType()); response.setHTTPHeaderField(HTTPHeaderName::ContentLength, String::number(m_totalRemainingSize)); if (isRangeRequest) response.setHTTPHeaderField(HTTPHeaderName::ContentRange, ParsedContentRange(m_rangeOffset, m_rangeEnd, m_totalSize).headerValue()); // FIXME: If a resource identified with a blob: URL is a File object, user agents must use that file's name attribute, // as if the response had a Content-Disposition header with the filename parameter set to the File's name attribute. // Notably, this will affect a name suggested in "File Save As". // BlobResourceHandle cannot be used with downloading, and doesn't even wait for continueDidReceiveResponse. // It's currently client's responsibility to know that didReceiveResponseAsync cannot be used to convert a // load into a download or blobs. if (usesAsyncCallbacks()) client()->didReceiveResponseAsync(this, WTFMove(response)); else client()->didReceiveResponse(this, WTFMove(response)); }
bool ResourceHandle::start() { if (!d->m_context) return false; // If NetworkingContext is invalid then we are no longer attached to a Page, // this must be an attempted load from an unload handler, so let's just block it. if (!d->m_context->isValid()) return false; d->m_storageSession = d->m_context->storageSession().platformSession(); bool shouldUseCredentialStorage = !client() || client()->shouldUseCredentialStorage(this); #if ENABLE(WEB_TIMING) && PLATFORM(COCOA) setCollectsTimingData(); #endif createCFURLConnection(shouldUseCredentialStorage, d->m_shouldContentSniff, SchedulingBehavior::Asynchronous, client()->connectionProperties(this).get()); d->m_connectionDelegate->setupConnectionScheduling(d->m_connection.get()); CFURLConnectionStart(d->m_connection.get()); LOG(Network, "CFNet - Starting URL %s (handle=%p, conn=%p)", firstRequest().url().string().utf8().data(), this, d->m_connection.get()); return true; }
void BlobResourceHandle::notifyResponseOnError() { ASSERT(m_errorCode); ResourceResponse response(firstRequest().url(), String(), 0, String(), String()); switch (m_errorCode) { case rangeError: response.setHTTPStatusCode(httpRequestedRangeNotSatisfiable); response.setHTTPStatusText(httpRequestedRangeNotSatisfiableText); break; case notFoundError: response.setHTTPStatusCode(httpNotFound); response.setHTTPStatusText(httpNotFoundText); break; case securityError: response.setHTTPStatusCode(httpNotAllowed); response.setHTTPStatusText(httpNotAllowedText); break; default: response.setHTTPStatusCode(httpInternalError); response.setHTTPStatusText(httpInternalErrorText); break; } client()->didReceiveResponse(this, response); }
void BlobResourceHandle::doStart() { // Do not continue if the request is aborted or an error occurs. if (m_aborted || m_errorCode) return; // If the blob data is not found, fail now. if (!m_blobData) { m_errorCode = notFoundError; notifyResponse(); return; } // Parse the "Range" header we care about. String range = firstRequest().httpHeaderField("Range"); if (!range.isEmpty() && !parseRange(range, m_rangeOffset, m_rangeEnd, m_rangeSuffixLength)) { m_errorCode = rangeError; notifyResponse(); return; } if (m_async) getSizeForNext(); else { for (size_t i = 0; i < m_blobData->items().size() && !m_aborted && !m_errorCode; ++i) getSizeForNext(); notifyResponse(); } }
void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge, const Credential& credential) { LOG(Network, "CFNet - receivedCredential()"); ASSERT(!challenge.isNull()); ASSERT(challenge.cfURLAuthChallengeRef()); if (challenge != d->m_currentWebChallenge) return; // FIXME: Support empty credentials. Currently, an empty credential cannot be stored in WebCore credential storage, as that's empty value for its map. if (credential.isEmpty()) { receivedRequestToContinueWithoutCredential(challenge); return; } if (credential.persistence() == CredentialPersistenceForSession) { // Manage per-session credentials internally, because once NSURLCredentialPersistencePerSession is used, there is no way // to ignore it for a particular request (short of removing it altogether). Credential webCredential(credential.user(), credential.password(), CredentialPersistenceNone); RetainPtr<CFURLCredentialRef> cfCredential(AdoptCF, createCF(webCredential)); KURL urlToStore; if (challenge.failureResponse().httpStatusCode() == 401) urlToStore = firstRequest().url(); CredentialStorage::set(webCredential, challenge.protectionSpace(), urlToStore); CFURLConnectionUseCredential(d->m_connection.get(), cfCredential.get(), challenge.cfURLAuthChallengeRef()); } else { RetainPtr<CFURLCredentialRef> cfCredential(AdoptCF, createCF(credential)); CFURLConnectionUseCredential(d->m_connection.get(), cfCredential.get(), challenge.cfURLAuthChallengeRef()); } clearAuthentication(); }
void BlobResourceHandle::notifyResponseOnError() { ASSERT(m_errorCode); ResourceResponse response(firstRequest().url(), "text/plain", 0, String()); switch (m_errorCode) { case rangeError: response.setHTTPStatusCode(httpRequestedRangeNotSatisfiable); response.setHTTPStatusText(httpRequestedRangeNotSatisfiableText); break; case notFoundError: response.setHTTPStatusCode(httpNotFound); response.setHTTPStatusText(httpNotFoundText); break; case securityError: response.setHTTPStatusCode(httpNotAllowed); response.setHTTPStatusText(httpNotAllowedText); break; default: response.setHTTPStatusCode(httpInternalError); response.setHTTPStatusText(httpInternalErrorText); break; } // Note that we don't wait for continueDidReceiveResponse when using didReceiveResponseAsync. // This is not formally correct, but the client has to be a no-op anyway, because blobs can't be downloaded. if (usesAsyncCallbacks()) client()->didReceiveResponseAsync(this, response); else client()->didReceiveResponse(this, response); }
bool ResourceHandle::start(NetworkingContext* context) { if (!context) return false; // If NetworkingContext is invalid then we are no longer attached to a Page, // this must be an attempted load from an unload handler, so let's just block it. if (!context->isValid()) return false; d->m_storageSession = context->storageSession(); bool shouldUseCredentialStorage = !client() || client()->shouldUseCredentialStorage(this); createCFURLConnection(shouldUseCredentialStorage, shouldRelaxThirdPartyCookiePolicy(context, firstRequest().url()), d->m_shouldContentSniff); #if PLATFORM(WIN) CFURLConnectionScheduleWithCurrentMessageQueue(d->m_connection.get()); #else CFURLConnectionScheduleWithRunLoop(d->m_connection.get(), CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); #endif CFURLConnectionScheduleDownloadWithRunLoop(d->m_connection.get(), loaderRunLoop(), kCFRunLoopDefaultMode); CFURLConnectionStart(d->m_connection.get()); LOG(Network, "CFNet - Starting URL %s (handle=%p, conn=%p)", firstRequest().url().string().utf8().data(), this, d->m_connection.get()); return true; }
int main(int argc , char *argv[]) { const char * hostName = "pb-homework.appspot.com"; WSADATA wsa; SOCKET s; struct sockaddr_in server; char server_reply[MAX_REP_LEN]; int recv_size; printf("\nInitialising Winsock..."); if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) { printf("Failed. Error Code : %d",WSAGetLastError()); return 1; } printf("Initialised.\n"); if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET) { printf("Could not create socket : %d" , WSAGetLastError()); } printf("Socket created.\n"); server.sin_addr.s_addr = inet_addr("216.58.214.241"); server.sin_family = AF_INET; server.sin_port = htons(PORT); int code; if ((code = connect(s, (struct sockaddr *)&server , sizeof(server))) < 0) { printf("Error code: %d", code); return 1; } puts("Connected"); char request[200]; firstRequest(s, request, hostName); getSecret(s, server_reply, &recv_size); secondRequest(s, request, server_reply, hostName); char * result[200]; getResultName(s, server_reply, result, &recv_size); thirdRequest(s, request, server_reply, result, hostName); getResult(s, server_reply, recv_size); closesocket(s); WSACleanup(); return 0; }
void BlobResourceHandle::notifyResponseOnSuccess() { bool isRangeRequest = m_rangeOffset != positionNotSpecified; ResourceResponse response(firstRequest().url(), m_blobData->contentType(), m_totalRemainingSize, String(), String()); response.setExpectedContentLength(m_totalRemainingSize); response.setHTTPStatusCode(isRangeRequest ? httpPartialContent : httpOK); response.setHTTPStatusText(isRangeRequest ? httpPartialContentText : httpOKText); if (!m_blobData->contentDisposition().isEmpty()) response.setHTTPHeaderField("Content-Disposition", m_blobData->contentDisposition()); client()->didReceiveResponse(this, response); }
void BlobResourceHandle::doStart() { ASSERT(isMainThread()); // Do not continue if the request is aborted or an error occurs. if (m_aborted || m_errorCode) return; if (!equalLettersIgnoringASCIICase(firstRequest().httpMethod(), "get")) { notifyFail(methodNotAllowed); return; } // If the blob data is not found, fail now. if (!m_blobData) { m_errorCode = notFoundError; notifyResponse(); return; } // Parse the "Range" header we care about. String range = firstRequest().httpHeaderField(HTTPHeaderName::Range); if (!range.isEmpty() && !parseRange(range, m_rangeOffset, m_rangeEnd, m_rangeSuffixLength)) { m_errorCode = rangeError; notifyResponse(); return; } if (m_async) getSizeForNext(); else { Ref<BlobResourceHandle> protectedThis(*this); // getSizeForNext calls the client for (size_t i = 0; i < m_blobData->items().size() && !m_aborted && !m_errorCode; ++i) getSizeForNext(); notifyResponse(); } }
bool ResourceHandle::start() { // If NetworkingContext is invalid then we are no longer attached to a Page, // this must be an attempted load from an unload event handler, so let's just block it. if (d->m_context && !d->m_context->isValid()) return false; if (!d->m_user.isEmpty() || !d->m_pass.isEmpty()) { // If credentials were specified for this request, add them to the url, // so that they will be passed to QNetworkRequest. URL urlWithCredentials(firstRequest().url()); urlWithCredentials.setUser(d->m_user); urlWithCredentials.setPass(d->m_pass); d->m_firstRequest.setURL(urlWithCredentials); } ResourceHandleInternal *d = getInternal(); d->m_job = new QNetworkReplyHandler(this, QNetworkReplyHandler::AsynchronousLoad, d->m_defersLoading); return true; }
void ResourceHandle::createCFURLConnection(bool shouldUseCredentialStorage, bool shouldContentSniff, CFDictionaryRef clientProperties) { if ((!d->m_user.isEmpty() || !d->m_pass.isEmpty()) && !firstRequest().url().protocolInHTTPFamily()) { // Credentials for ftp can only be passed in URL, the didReceiveAuthenticationChallenge delegate call won't be made. KURL urlWithCredentials(firstRequest().url()); urlWithCredentials.setUser(d->m_user); urlWithCredentials.setPass(d->m_pass); firstRequest().setURL(urlWithCredentials); } // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, // try and reuse the credential preemptively, as allowed by RFC 2617. if (shouldUseCredentialStorage && firstRequest().url().protocolInHTTPFamily()) { if (d->m_user.isEmpty() && d->m_pass.isEmpty()) { // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, // try and reuse the credential preemptively, as allowed by RFC 2617. d->m_initialCredential = CredentialStorage::get(firstRequest().url()); } else { // If there is already a protection space known for the URL, update stored credentials before sending a request. // This makes it possible to implement logout by sending an XMLHttpRequest with known incorrect credentials, and aborting it immediately // (so that an authentication dialog doesn't pop up). CredentialStorage::set(Credential(d->m_user, d->m_pass, CredentialPersistenceNone), firstRequest().url()); } } if (!d->m_initialCredential.isEmpty()) { // FIXME: Support Digest authentication, and Proxy-Authorization. applyBasicAuthorizationHeader(firstRequest(), d->m_initialCredential); } RetainPtr<CFURLRequestRef> request(AdoptCF, makeFinalRequest(firstRequest(), shouldContentSniff)); #if HAVE(CFNETWORK_DATA_ARRAY_CALLBACK) && USE(PROTECTION_SPACE_AUTH_CALLBACK) CFURLConnectionClient_V6 client = { 6, this, 0, 0, 0, WebCore::willSendRequest, didReceiveResponse, didReceiveData, 0, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge, didSendBodyData, shouldUseCredentialStorageCallback, 0, canRespondToProtectionSpace, 0, didReceiveDataArray}; #else CFURLConnectionClient_V3 client = { 3, this, 0, 0, 0, WebCore::willSendRequest, didReceiveResponse, didReceiveData, 0, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge, didSendBodyData, shouldUseCredentialStorageCallback, 0}; #endif RetainPtr<CFDictionaryRef> connectionProperties(AdoptCF, createConnectionProperties(shouldUseCredentialStorage, clientProperties)); CFURLRequestSetShouldStartSynchronously(request.get(), 1); d->m_connection.adoptCF(CFURLConnectionCreateWithProperties(0, request.get(), reinterpret_cast<CFURLConnectionClient*>(&client), connectionProperties.get())); }
bool ResourceHandle::start(NetworkingContext* context) { if (!context) return false; // If NetworkingContext is invalid then we are no longer attached to a Page, // this must be an attempted load from an unload handler, so let's just block it. if (!context->isValid()) return false; bool shouldUseCredentialStorage = !client() || client()->shouldUseCredentialStorage(this); createCFURLConnection(shouldUseCredentialStorage, d->m_shouldContentSniff, client()->connectionProperties(this)); CFURLConnectionScheduleWithRunLoop(d->m_connection.get(), WebThreadRunLoop(), kCFRunLoopDefaultMode); CFURLConnectionScheduleDownloadWithRunLoop(d->m_connection.get(), loaderRunLoop(), kCFRunLoopDefaultMode); CFURLConnectionStart(d->m_connection.get()); LOG(Network, "CFNet - Starting URL %s (handle=%p, conn=%p)", firstRequest().url().string().utf8().data(), this, d->m_connection.get()); return true; }
void BlobResourceHandle::notifyFail(int errorCode) { if (client()) client()->didFail(this, ResourceError(String(), errorCode, firstRequest().url(), String())); }
bool ResourceHandle::start() { if (firstRequest().url().isLocalFile() || firstRequest().url().protocolIsData()) { ref(); // balanced by deref in fileLoadTimer if (d->m_loadSynchronously) fileLoadTimer(0); else d->m_fileLoadTimer.startOneShot(0.0); return true; } if (!d->m_internetHandle) d->m_internetHandle = asynchronousInternetHandle(d->m_context->userAgent()); if (!d->m_internetHandle) return false; DWORD flags = INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_RELOAD; d->m_connectHandle = InternetConnectW(d->m_internetHandle, firstRequest().url().host().charactersWithNullTermination(), firstRequest().url().port(), 0, 0, INTERNET_SERVICE_HTTP, flags, reinterpret_cast<DWORD_PTR>(this)); if (!d->m_connectHandle) return false; String urlStr = firstRequest().url().path(); String urlQuery = firstRequest().url().query(); if (!urlQuery.isEmpty()) { urlStr.append('?'); urlStr.append(urlQuery); } String httpMethod = firstRequest().httpMethod(); String httpReferrer = firstRequest().httpReferrer(); LPCWSTR httpAccept[] = { L"*/*", 0 }; d->m_requestHandle = HttpOpenRequestW(d->m_connectHandle, httpMethod.charactersWithNullTermination(), urlStr.charactersWithNullTermination(), 0, httpReferrer.charactersWithNullTermination(), httpAccept, flags, reinterpret_cast<DWORD_PTR>(this)); if (!d->m_requestHandle) { InternetCloseHandle(d->m_connectHandle); return false; } if (firstRequest().httpBody()) { firstRequest().httpBody()->flatten(d->m_formData); d->m_bytesRemainingToWrite = d->m_formData.size(); } Vector<UChar> httpHeaders; const HTTPHeaderMap& httpHeaderFields = firstRequest().httpHeaderFields(); for (HTTPHeaderMap::const_iterator it = httpHeaderFields.begin(); it != httpHeaderFields.end(); ++it) { if (equalIgnoringCase(it->key, "Accept") || equalIgnoringCase(it->key, "Referer") || equalIgnoringCase(it->key, "User-Agent")) continue; if (!httpHeaders.isEmpty()) httpHeaders.append('\n'); httpHeaders.append(it->key.characters(), it->key.length()); httpHeaders.append(':'); httpHeaders.append(it->value.characters(), it->value.length()); } INTERNET_BUFFERSW internetBuffers; ZeroMemory(&internetBuffers, sizeof(internetBuffers)); internetBuffers.dwStructSize = sizeof(internetBuffers); internetBuffers.lpcszHeader = httpHeaders.data(); internetBuffers.dwHeadersLength = httpHeaders.size(); internetBuffers.dwBufferTotal = d->m_bytesRemainingToWrite; HttpSendRequestExW(d->m_requestHandle, &internetBuffers, 0, 0, reinterpret_cast<DWORD_PTR>(this)); ref(); // balanced by deref in onRequestComplete if (d->m_loadSynchronously) while (onRequestComplete()) { // Loop until finished. } return true; }
bool ResourceHandle::onRequestComplete() { if (!d->m_internetHandle) { // 0 if canceled. deref(); // balances ref in start return false; } if (d->m_bytesRemainingToWrite) { DWORD bytesWritten; InternetWriteFile(d->m_requestHandle, d->m_formData.data() + (d->m_formData.size() - d->m_bytesRemainingToWrite), d->m_bytesRemainingToWrite, &bytesWritten); d->m_bytesRemainingToWrite -= bytesWritten; if (d->m_bytesRemainingToWrite) return true; d->m_formData.clear(); } if (!d->m_sentEndRequest) { HttpEndRequestW(d->m_requestHandle, 0, 0, reinterpret_cast<DWORD_PTR>(this)); d->m_sentEndRequest = true; return true; } static const int bufferSize = 32768; char buffer[bufferSize]; INTERNET_BUFFERSA buffers; buffers.dwStructSize = sizeof(INTERNET_BUFFERSA); buffers.lpvBuffer = buffer; buffers.dwBufferLength = bufferSize; BOOL ok = FALSE; while ((ok = InternetReadFileExA(d->m_requestHandle, &buffers, d->m_loadSynchronously ? 0 : IRF_NO_WAIT, reinterpret_cast<DWORD_PTR>(this))) && buffers.dwBufferLength) { if (!d->m_hasReceivedResponse) { d->m_hasReceivedResponse = true; ResourceResponse response; response.setURL(firstRequest().url()); String httpStatusText = queryHTTPHeader(d->m_requestHandle, HTTP_QUERY_STATUS_TEXT); if (!httpStatusText.isNull()) response.setHTTPStatusText(httpStatusText); String httpStatusCode = queryHTTPHeader(d->m_requestHandle, HTTP_QUERY_STATUS_CODE); if (!httpStatusCode.isNull()) response.setHTTPStatusCode(httpStatusCode.toInt()); String httpContentLength = queryHTTPHeader(d->m_requestHandle, HTTP_QUERY_CONTENT_LENGTH); if (!httpContentLength.isNull()) response.setExpectedContentLength(httpContentLength.toInt()); String httpContentType = queryHTTPHeader(d->m_requestHandle, HTTP_QUERY_CONTENT_TYPE); if (!httpContentType.isNull()) { response.setMimeType(extractMIMETypeFromMediaType(httpContentType)); response.setTextEncodingName(extractCharsetFromMediaType(httpContentType)); } if (ResourceHandleClient* resourceHandleClient = client()) resourceHandleClient->didReceiveResponse(this, response); } // FIXME: https://bugs.webkit.org/show_bug.cgi?id=19793 // -1 means we do not provide any data about transfer size to inspector so it would use // Content-Length headers or content size to show transfer size. if (ResourceHandleClient* resourceHandleClient = client()) resourceHandleClient->didReceiveData(this, buffer, buffers.dwBufferLength, -1); buffers.dwBufferLength = bufferSize; } if (!ok && GetLastError() == ERROR_IO_PENDING) return true; if (ResourceHandleClient* resourceHandleClient = client()) resourceHandleClient->didFinishLoading(this, 0); InternetCloseHandle(d->m_requestHandle); InternetCloseHandle(d->m_connectHandle); deref(); // balances ref in start return false; }
bool ResourceHandle::shouldUseCredentialStorage() { return (!client() || client()->shouldUseCredentialStorage(this)) && firstRequest().url().protocolIsInHTTPFamily(); }
void ResourceHandle::createCFURLConnection(bool shouldUseCredentialStorage, bool shouldContentSniff, SchedulingBehavior schedulingBehavior, CFDictionaryRef clientProperties) { if ((!d->m_user.isEmpty() || !d->m_pass.isEmpty()) && !firstRequest().url().protocolIsInHTTPFamily()) { // Credentials for ftp can only be passed in URL, the didReceiveAuthenticationChallenge delegate call won't be made. URL urlWithCredentials(firstRequest().url()); urlWithCredentials.setUser(d->m_user); urlWithCredentials.setPass(d->m_pass); firstRequest().setURL(urlWithCredentials); } // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, // try and reuse the credential preemptively, as allowed by RFC 2617. if (shouldUseCredentialStorage && firstRequest().url().protocolIsInHTTPFamily()) { if (d->m_user.isEmpty() && d->m_pass.isEmpty()) { // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, // try and reuse the credential preemptively, as allowed by RFC 2617. d->m_initialCredential = CredentialStorage::get(firstRequest().url()); } else { // If there is already a protection space known for the URL, update stored credentials before sending a request. // This makes it possible to implement logout by sending an XMLHttpRequest with known incorrect credentials, and aborting it immediately // (so that an authentication dialog doesn't pop up). CredentialStorage::set(Credential(d->m_user, d->m_pass, CredentialPersistenceNone), firstRequest().url()); } } if (!d->m_initialCredential.isEmpty()) { // FIXME: Support Digest authentication, and Proxy-Authorization. applyBasicAuthorizationHeader(firstRequest(), d->m_initialCredential); } RetainPtr<CFMutableURLRequestRef> request = adoptCF(CFURLRequestCreateMutableCopy(kCFAllocatorDefault, firstRequest().cfURLRequest(UpdateHTTPBody))); wkSetRequestStorageSession(d->m_storageSession.get(), request.get()); if (!shouldContentSniff) wkSetCFURLRequestShouldContentSniff(request.get(), false); RetainPtr<CFMutableDictionaryRef> sslProps; #if PLATFORM(IOS) sslProps = adoptCF(ResourceHandle::createSSLPropertiesFromNSURLRequest(firstRequest())); #else if (allowsAnyHTTPSCertificateHosts().contains(firstRequest().url().host().lower())) { sslProps = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); CFDictionaryAddValue(sslProps.get(), kCFStreamSSLAllowsAnyRoot, kCFBooleanTrue); CFDictionaryAddValue(sslProps.get(), kCFStreamSSLAllowsExpiredRoots, kCFBooleanTrue); CFDictionaryAddValue(sslProps.get(), kCFStreamSSLAllowsExpiredCertificates, kCFBooleanTrue); CFDictionaryAddValue(sslProps.get(), kCFStreamSSLValidatesCertificateChain, kCFBooleanFalse); } HashMap<String, RetainPtr<CFDataRef>>::iterator clientCert = clientCerts().find(firstRequest().url().host().lower()); if (clientCert != clientCerts().end()) { if (!sslProps) sslProps = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); #if PLATFORM(WIN) wkSetClientCertificateInSSLProperties(sslProps.get(), (clientCert->value).get()); #endif } #endif // PLATFORM(IOS) if (sslProps) CFURLRequestSetSSLProperties(request.get(), sslProps.get()); #if PLATFORM(WIN) if (CFHTTPCookieStorageRef cookieStorage = overridenCookieStorage()) { // Overridden cookie storage doesn't come from a session, so the request does not have it yet. CFURLRequestSetHTTPCookieStorage(request.get(), cookieStorage); } #endif CFMutableDictionaryRef streamProperties = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!shouldUseCredentialStorage) { // Avoid using existing connections, because they may be already authenticated. CFDictionarySetValue(streamProperties, CFSTR("_kCFURLConnectionSessionID"), CFSTR("WebKitPrivateSession")); } if (schedulingBehavior == SchedulingBehavior::Synchronous) { // Synchronous requests should not be subject to regular connection count limit to avoid deadlocks. // If we are using all available connections for async requests, and make a sync request, then prior // requests may get stuck waiting for delegate calls while we are in nested run loop, and the sync // request won't start because there are no available connections. // Connections are grouped by their socket stream properties, with each group having a separate count. CFDictionarySetValue(streamProperties, CFSTR("_WebKitSynchronousRequest"), kCFBooleanTrue); } #if PLATFORM(IOS) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) RetainPtr<CFDataRef> sourceApplicationAuditData = d->m_context->sourceApplicationAuditData(); if (sourceApplicationAuditData) CFDictionarySetValue(streamProperties, CFSTR("kCFStreamPropertySourceApplication"), sourceApplicationAuditData.get()); #endif static const CFStringRef kCFURLConnectionSocketStreamProperties = CFSTR("kCFURLConnectionSocketStreamProperties"); RetainPtr<CFMutableDictionaryRef> propertiesDictionary; if (clientProperties) propertiesDictionary = adoptCF(CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, clientProperties)); else propertiesDictionary = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); // FIXME: This code is different from iOS code in ResourceHandleMac.mm in that here we ignore stream properties that were present in client properties. CFDictionaryAddValue(propertiesDictionary.get(), kCFURLConnectionSocketStreamProperties, streamProperties); CFRelease(streamProperties); #if PLATFORM(COCOA) if (client() && client()->usesAsyncCallbacks()) d->m_connectionDelegate = adoptRef(new ResourceHandleCFURLConnectionDelegateWithOperationQueue(this)); else d->m_connectionDelegate = adoptRef(new SynchronousResourceHandleCFURLConnectionDelegate(this)); #else d->m_connectionDelegate = adoptRef(new SynchronousResourceHandleCFURLConnectionDelegate(this)); #endif d->m_connectionDelegate->setupRequest(request.get()); CFURLConnectionClient_V6 client = d->m_connectionDelegate->makeConnectionClient(); d->m_connection = adoptCF(CFURLConnectionCreateWithProperties(0, request.get(), reinterpret_cast<CFURLConnectionClient*>(&client), propertiesDictionary.get())); }
void ResourceHandle::createCFURLConnection(bool shouldUseCredentialStorage, bool shouldRelaxThirdPartyCookiePolicy, bool shouldContentSniff) { if ((!d->m_user.isEmpty() || !d->m_pass.isEmpty()) && !firstRequest().url().protocolIsInHTTPFamily()) { // Credentials for ftp can only be passed in URL, the didReceiveAuthenticationChallenge delegate call won't be made. KURL urlWithCredentials(firstRequest().url()); urlWithCredentials.setUser(d->m_user); urlWithCredentials.setPass(d->m_pass); firstRequest().setURL(urlWithCredentials); } if (shouldRelaxThirdPartyCookiePolicy) firstRequest().setFirstPartyForCookies(firstRequest().url()); // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, // try and reuse the credential preemptively, as allowed by RFC 2617. if (shouldUseCredentialStorage && firstRequest().url().protocolIsInHTTPFamily()) { if (d->m_user.isEmpty() && d->m_pass.isEmpty()) { // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, // try and reuse the credential preemptively, as allowed by RFC 2617. d->m_initialCredential = CredentialStorage::get(firstRequest().url()); } else { // If there is already a protection space known for the URL, update stored credentials before sending a request. // This makes it possible to implement logout by sending an XMLHttpRequest with known incorrect credentials, and aborting it immediately // (so that an authentication dialog doesn't pop up). CredentialStorage::set(Credential(d->m_user, d->m_pass, CredentialPersistenceNone), firstRequest().url()); } } if (!d->m_initialCredential.isEmpty()) { // FIXME: Support Digest authentication, and Proxy-Authorization. applyBasicAuthorizationHeader(firstRequest(), d->m_initialCredential); } RetainPtr<CFMutableURLRequestRef> request = adoptCF(CFURLRequestCreateMutableCopy(kCFAllocatorDefault, firstRequest().cfURLRequest())); wkSetRequestStorageSession(d->m_storageSession.get(), request.get()); if (!shouldContentSniff) wkSetCFURLRequestShouldContentSniff(request.get(), false); RetainPtr<CFMutableDictionaryRef> sslProps; if (allowsAnyHTTPSCertificateHosts().contains(firstRequest().url().host().lower())) { sslProps.adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); CFDictionaryAddValue(sslProps.get(), kCFStreamSSLAllowsAnyRoot, kCFBooleanTrue); CFDictionaryAddValue(sslProps.get(), kCFStreamSSLAllowsExpiredRoots, kCFBooleanTrue); CFDictionaryAddValue(sslProps.get(), kCFStreamSSLAllowsExpiredCertificates, kCFBooleanTrue); CFDictionaryAddValue(sslProps.get(), kCFStreamSSLValidatesCertificateChain, kCFBooleanFalse); } HashMap<String, RetainPtr<CFDataRef> >::iterator clientCert = clientCerts().find(firstRequest().url().host().lower()); if (clientCert != clientCerts().end()) { if (!sslProps) sslProps.adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); #if PLATFORM(WIN) wkSetClientCertificateInSSLProperties(sslProps.get(), (clientCert->value).get()); #endif } if (sslProps) CFURLRequestSetSSLProperties(request.get(), sslProps.get()); #if PLATFORM(WIN) if (CFHTTPCookieStorageRef cookieStorage = overridenCookieStorage()) { // Overridden cookie storage doesn't come from a session, so the request does not have it yet. CFURLRequestSetHTTPCookieStorage(request.get(), cookieStorage); } #endif CFURLConnectionClient_V6 client = { 6, this, 0, 0, 0, WebCore::willSendRequest, didReceiveResponse, didReceiveData, 0, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge, didSendBodyData, shouldUseCredentialStorageCallback, 0, #if USE(PROTECTION_SPACE_AUTH_CALLBACK) canRespondToProtectionSpace, #else 0, #endif 0, #if USE(NETWORK_CFDATA_ARRAY_CALLBACK) didReceiveDataArray #else 0 #endif }; RetainPtr<CFDictionaryRef> connectionProperties(AdoptCF, createConnectionProperties(shouldUseCredentialStorage)); d->m_connection.adoptCF(CFURLConnectionCreateWithProperties(0, request.get(), reinterpret_cast<CFURLConnectionClient*>(&client), connectionProperties.get())); }