void Loader::didFail(SubresourceLoader* loader, bool cancelled) { RequestMap::iterator i = m_requestsLoading.find(loader); if (i == m_requestsLoading.end()) return; Request* req = i->second; m_requestsLoading.remove(i); DocLoader* docLoader = req->docLoader(); if (!req->isMultipart()) docLoader->decrementRequestCount(); CachedResource* object = req->cachedResource(); if (!cancelled) { docLoader->setLoadInProgress(true); object->error(); } docLoader->setLoadInProgress(false); cache()->remove(object); delete req; servePendingRequests(); }
static void* openFunc(const char* uri) { ASSERT(XMLTokenizerScope::currentDocLoader); ASSERT(currentThread() == libxmlLoaderThread); KURL url(KURL(), uri); if (!shouldAllowExternalLoad(url)) return &globalDescriptor; ResourceError error; ResourceResponse response; Vector<char> data; { DocLoader* docLoader = XMLTokenizerScope::currentDocLoader; XMLTokenizerScope scope(0); // FIXME: We should restore the original global error handler as well. if (docLoader->frame()) docLoader->frame()->loader()->loadResourceSynchronously(url, AllowStoredCredentials, error, response, data); } // We have to check the URL again after the load to catch redirects. // See <https://bugs.webkit.org/show_bug.cgi?id=21963>. if (!shouldAllowExternalLoad(response.url())) return &globalDescriptor; return new OffsetBuffer(data); }
void Loader::Host::didFail(SubresourceLoader* loader, bool cancelled) { loader->clearClient(); RequestMap::iterator i = m_requestsLoading.find(loader); if (i == m_requestsLoading.end()) return; Request* request = i->second; m_requestsLoading.remove(i); DocLoader* docLoader = request->docLoader(); if (!request->isMultipart()) docLoader->decrementRequestCount(); CachedResource* resource = request->cachedResource(); if (!cancelled) { docLoader->setLoadInProgress(true); resource->error(); } docLoader->setLoadInProgress(false); if (cancelled || !resource->isPreloaded()) cache()->remove(resource); delete request; servePendingRequests(); }
void Loader::Host::didFinishLoading(SubresourceLoader* loader) { RequestMap::iterator i = m_requestsLoading.find(loader); if (i == m_requestsLoading.end()) return; Request* request = i->second; m_requestsLoading.remove(i); DocLoader* docLoader = request->docLoader(); if (!request->isMultipart()) docLoader->decrementRequestCount(); CachedResource* resource = request->cachedResource(); // If we got a 4xx response, we're pretending to have received a network // error, so we can't send the successful data() and finish() callbacks. if (!resource->errorOccurred()) { docLoader->setLoadInProgress(true); resource->data(loader->resourceData(), true); resource->finish(); } delete request; docLoader->setLoadInProgress(false); #if REQUEST_DEBUG KURL u(resource->url()); printf("HOST %s COUNT %d RECEIVED %s\n", u.host().latin1().data(), m_requestsLoading.size(), resource->url().latin1().data()); #endif servePendingRequests(); }
void Loader::Host::servePendingRequests(RequestQueue& requestsPending, bool& serveLowerPriority) { while (!requestsPending.isEmpty()) { Request* request = requestsPending.first(); DocLoader* docLoader = request->docLoader(); bool resourceIsCacheValidator = request->cachedResource()->isCacheValidator(); // For named hosts - which are only http(s) hosts - we should always enforce the connection limit. // For non-named hosts - everything but http(s) - we should only enforce the limit if the document isn't done parsing // and we don't know all stylesheets yet. bool shouldLimitRequests = !m_name.isNull() || docLoader->doc()->parsing() || !docLoader->doc()->haveStylesheetsLoaded(); if (shouldLimitRequests && m_requestsLoading.size() + m_nonCachedRequestsInFlight >= m_maxRequestsInFlight) { serveLowerPriority = false; cache()->loader()->scheduleServePendingRequests(); return; } requestsPending.removeFirst(); ResourceRequest resourceRequest(request->cachedResource()->url()); resourceRequest.setTargetType(cachedResourceTypeToTargetType(request->cachedResource()->type())); if (!request->cachedResource()->accept().isEmpty()) resourceRequest.setHTTPAccept(request->cachedResource()->accept()); // Do not set the referrer or HTTP origin here. That's handled by SubresourceLoader::create. if (resourceIsCacheValidator) { CachedResource* resourceToRevalidate = request->cachedResource()->resourceToRevalidate(); ASSERT(resourceToRevalidate->canUseCacheValidator()); ASSERT(resourceToRevalidate->isLoaded()); const String& lastModified = resourceToRevalidate->response().httpHeaderField("Last-Modified"); const String& eTag = resourceToRevalidate->response().httpHeaderField("ETag"); if (!lastModified.isEmpty() || !eTag.isEmpty()) { ASSERT(docLoader->cachePolicy() != CachePolicyReload); if (docLoader->cachePolicy() == CachePolicyRevalidate) resourceRequest.setHTTPHeaderField("Cache-Control", "max-age=0"); if (!lastModified.isEmpty()) resourceRequest.setHTTPHeaderField("If-Modified-Since", lastModified); if (!eTag.isEmpty()) resourceRequest.setHTTPHeaderField("If-None-Match", eTag); } } RefPtr<SubresourceLoader> loader = SubresourceLoader::create(docLoader->doc()->frame(), this, resourceRequest, request->shouldDoSecurityCheck(), request->sendResourceLoadCallbacks()); if (loader) { m_requestsLoading.add(loader.release(), request); request->cachedResource()->setRequestedFromNetworkingLayer(); #if REQUEST_DEBUG printf("HOST %s COUNT %d LOADING %s\n", resourceRequest.url().host().latin1().data(), m_requestsLoading.size(), request->cachedResource()->url().latin1().data()); #endif } else { docLoader->decrementRequestCount(); docLoader->setLoadInProgress(true); request->cachedResource()->error(); docLoader->setLoadInProgress(false); delete request; } } }
void Loader::Host::servePendingRequests(RequestQueue& requestsPending) { while (m_requestsLoading.size() < m_maxRequestsInFlight && !requestsPending.isEmpty()) { Request* request = requestsPending.first(); requestsPending.removeFirst(); DocLoader* docLoader = request->docLoader(); ResourceRequest resourceRequest(request->cachedResource()->url()); if (!request->cachedResource()->accept().isEmpty()) resourceRequest.setHTTPAccept(request->cachedResource()->accept()); KURL referrer = docLoader->doc()->url(); if ((referrer.protocolIs("http") || referrer.protocolIs("https")) && referrer.path().isEmpty()) referrer.setPath("/"); resourceRequest.setHTTPReferrer(referrer.string()); RefPtr<SubresourceLoader> loader = SubresourceLoader::create(docLoader->doc()->frame(), this, resourceRequest, request->shouldSkipCanLoadCheck(), request->sendResourceLoadCallbacks()); if (loader) { m_requestsLoading.add(loader.release(), request); request->cachedResource()->setRequestedFromNetworkingLayer(); #if REQUEST_DEBUG printf("HOST %s COUNT %d LOADING %s\n", resourceRequest.url().host().latin1().data(), m_requestsLoading.size(), request->cachedResource()->url().latin1().data()); #endif } else { docLoader->decrementRequestCount(); docLoader->setLoadInProgress(true); request->cachedResource()->error(); docLoader->setLoadInProgress(false); delete request; } } }
void CSSImportRule::insertedIntoParent() { CSSStyleSheet* parentSheet = parentStyleSheet(); if (!parentSheet) return; DocLoader* docLoader = parentSheet->doc()->docLoader(); if (!docLoader) return; String absHref = m_strHref; if (!parentSheet->finalURL().isNull()) // use parent styleheet's URL as the base URL absHref = KURL(parentSheet->finalURL(), m_strHref).string(); // Check for a cycle in our import chain. If we encounter a stylesheet // in our parent chain with the same URL, then just bail. StyleBase* root = this; for (StyleBase* curr = parent(); curr; curr = curr->parent()) { // FIXME: This is wrong if the finalURL was updated via document::updateBaseURL. if (curr->isCSSStyleSheet() && absHref == static_cast<CSSStyleSheet*>(curr)->finalURL().string()) return; root = curr; } if (parentSheet->isUserStyleSheet()) m_cachedSheet = docLoader->requestUserCSSStyleSheet(absHref, parentSheet->charset()); else m_cachedSheet = docLoader->requestCSSStyleSheet(absHref, parentSheet->charset()); if (m_cachedSheet) { // if the import rule is issued dynamically, the sheet may be // removed from the pending sheet count, so let the doc know // the sheet being imported is pending. if (parentSheet && parentSheet->loadCompleted() && root == parentSheet) parentSheet->doc()->addPendingSheet(); m_loading = true; m_cachedSheet->addClient(this); } }
void Loader::didFinishLoading(SubresourceLoader* loader) { RequestMap::iterator i = m_requestsLoading.find(loader); if (i == m_requestsLoading.end()) return; Request* req = i->second; m_requestsLoading.remove(i); DocLoader* docLoader = req->docLoader(); if (!req->isMultipart()) docLoader->decrementRequestCount(); CachedResource* object = req->cachedResource(); docLoader->setLoadInProgress(true); object->data(loader->resourceData(), true); docLoader->setLoadInProgress(false); object->finish(); delete req; servePendingRequests(); }
void Loader::servePendingRequests() { while (!m_requestsPending.isEmpty()) { // get the first pending request Request* req = m_requestsPending.take(0); DocLoader* dl = req->docLoader(); dl->decrementRequestCount(); ResourceRequest request(req->cachedResource()->url()); if (!req->cachedResource()->accept().isEmpty()) request.setHTTPAccept(req->cachedResource()->accept()); KURL r = dl->doc()->URL(); if (r.protocol().startsWith("http") && r.path().isEmpty()) r.setPath("/"); request.setHTTPReferrer(r.url()); DeprecatedString domain = r.host(); if (dl->doc()->isHTMLDocument()) domain = static_cast<HTMLDocument*>(dl->doc())->domain().deprecatedString(); RefPtr<SubresourceLoader> loader = SubresourceLoader::create(dl->doc()->frame(), this, request, req->shouldSkipCanLoadCheck(), req->sendResourceLoadCallbacks()); if (loader) { m_requestsLoading.add(loader.release(), req); dl->incrementRequestCount(); break; } dl->setLoadInProgress(true); req->cachedResource()->error(); dl->setLoadInProgress(false); delete req; } }
void Loader::Host::didFinishLoading(SubresourceLoader* loader) { RefPtr<Host> myProtector(this); RequestMap::iterator i = m_requestsLoading.find(loader); if (i == m_requestsLoading.end()) return; Request* request = i->second; m_requestsLoading.remove(i); DocLoader* docLoader = request->docLoader(); // Prevent the document from being destroyed before we are done with // the docLoader that it will delete when the document gets deleted. RefPtr<Document> protector(docLoader->doc()); if (!request->isMultipart()) docLoader->decrementRequestCount(); CachedResource* resource = request->cachedResource(); ASSERT(!resource->resourceToRevalidate()); // If we got a 4xx response, we're pretending to have received a network // error, so we can't send the successful data() and finish() callbacks. if (!resource->errorOccurred()) { docLoader->setLoadInProgress(true); resource->data(loader->resourceData(), true); resource->finish(); } delete request; docLoader->setLoadInProgress(false); docLoader->checkForPendingPreloads(); #if REQUEST_DEBUG KURL u(ParsedURLString, resource->url()); printf("HOST %s COUNT %d RECEIVED %s\n", u.host().latin1().data(), m_requestsLoading.size(), resource->url().latin1().data()); #endif servePendingRequests(); }
void Loader::Host::didFail(SubresourceLoader* loader, bool cancelled) { RefPtr<Host> myProtector(this); loader->clearClient(); RequestMap::iterator i = m_requestsLoading.find(loader); if (i == m_requestsLoading.end()) return; Request* request = i->second; m_requestsLoading.remove(i); DocLoader* docLoader = request->docLoader(); // Prevent the document from being destroyed before we are done with // the docLoader that it will delete when the document gets deleted. RefPtr<Document> protector(docLoader->doc()); if (!request->isMultipart()) docLoader->decrementRequestCount(); CachedResource* resource = request->cachedResource(); if (resource->resourceToRevalidate()) cache()->revalidationFailed(resource); if (!cancelled) { docLoader->setLoadInProgress(true); resource->error(); } docLoader->setLoadInProgress(false); if (cancelled || !resource->isPreloaded()) cache()->remove(resource); delete request; docLoader->checkForPendingPreloads(); servePendingRequests(); }
void Loader::Host::servePendingRequests(RequestQueue& requestsPending, bool& serveLowerPriority) { while (!requestsPending.isEmpty()) { Request* request = requestsPending.first(); DocLoader* docLoader = request->docLoader(); bool resourceIsCacheValidator = request->cachedResource()->isCacheValidator(); // If the document is fully parsed and there are no pending stylesheets there won't be any more // resources that we would want to push to the front of the queue. Just hand off the remaining resources // to the networking layer. bool parsedAndStylesheetsKnown = !docLoader->doc()->parsing() && docLoader->doc()->haveStylesheetsLoaded(); if (!parsedAndStylesheetsKnown && !resourceIsCacheValidator && m_requestsLoading.size() >= m_maxRequestsInFlight) { serveLowerPriority = false; return; } requestsPending.removeFirst(); ResourceRequest resourceRequest(request->cachedResource()->url()); if (!request->cachedResource()->accept().isEmpty()) resourceRequest.setHTTPAccept(request->cachedResource()->accept()); KURL referrer = docLoader->doc()->url(); if ((referrer.protocolIs("http") || referrer.protocolIs("https")) && referrer.path().isEmpty()) referrer.setPath("/"); resourceRequest.setHTTPReferrer(referrer.string()); FrameLoader::addHTTPOriginIfNeeded(resourceRequest, docLoader->doc()->securityOrigin()->toString()); if (resourceIsCacheValidator) { CachedResource* resourceToRevalidate = request->cachedResource()->resourceToRevalidate(); ASSERT(resourceToRevalidate->canUseCacheValidator()); ASSERT(resourceToRevalidate->isLoaded()); const String& lastModified = resourceToRevalidate->response().httpHeaderField("Last-Modified"); const String& eTag = resourceToRevalidate->response().httpHeaderField("ETag"); if (!lastModified.isEmpty() || !eTag.isEmpty()) { ASSERT(docLoader->cachePolicy() != CachePolicyReload); if (docLoader->cachePolicy() == CachePolicyRevalidate) resourceRequest.setHTTPHeaderField("Cache-Control", "max-age=0"); if (!lastModified.isEmpty()) resourceRequest.setHTTPHeaderField("If-Modified-Since", lastModified); if (!eTag.isEmpty()) resourceRequest.setHTTPHeaderField("If-None-Match", eTag); } } RefPtr<SubresourceLoader> loader = SubresourceLoader::create(docLoader->doc()->frame(), this, resourceRequest, request->shouldSkipCanLoadCheck(), request->sendResourceLoadCallbacks()); if (loader) { m_requestsLoading.add(loader.release(), request); request->cachedResource()->setRequestedFromNetworkingLayer(); #if REQUEST_DEBUG printf("HOST %s COUNT %d LOADING %s\n", resourceRequest.url().host().latin1().data(), m_requestsLoading.size(), request->cachedResource()->url().latin1().data()); #endif } else { docLoader->decrementRequestCount(); docLoader->setLoadInProgress(true); request->cachedResource()->error(); docLoader->setLoadInProgress(false); delete request; } } }
bool DragController::concludeEditDrag(DragData* dragData) { ASSERT(dragData); ASSERT(!m_isHandlingDrag); if (!m_documentUnderMouse) return false; IntPoint point = m_documentUnderMouse->view()->windowToContents(dragData->clientPosition()); Element* element = elementUnderMouse(m_documentUnderMouse, point); Frame* innerFrame = element->ownerDocument()->frame(); ASSERT(innerFrame); if (dragData->containsColor()) { Color color = dragData->asColor(); if (!color.isValid()) return false; if (!innerFrame) return false; RefPtr<Range> innerRange = innerFrame->selection()->toNormalizedRange(); RefPtr<CSSStyleDeclaration> style = m_documentUnderMouse->createCSSStyleDeclaration(); ExceptionCode ec; style->setProperty("color", color.name(), ec); if (!innerFrame->editor()->shouldApplyStyle(style.get(), innerRange.get())) return false; m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData); innerFrame->editor()->applyStyle(style.get(), EditActionSetColor); return true; } if (!m_page->dragController()->canProcessDrag(dragData)) { m_page->dragCaretController()->clear(); return false; } if (HTMLInputElement* fileInput = asFileInput(element)) { if (!fileInput->isEnabledFormControl()) return false; if (!dragData->containsFiles()) return false; Vector<String> filenames; dragData->asFilenames(filenames); if (filenames.isEmpty()) return false; // Ugly. For security none of the APIs available to us can set the input value // on file inputs. Even forcing a change in HTMLInputElement doesn't work as // RenderFileUploadControl clears the file when doing updateFromElement(). RenderFileUploadControl* renderer = toRenderFileUploadControl(fileInput->renderer()); if (!renderer) return false; renderer->receiveDroppedFiles(filenames); return true; } VisibleSelection dragCaret(m_page->dragCaretController()->selection()); m_page->dragCaretController()->clear(); RefPtr<Range> range = dragCaret.toNormalizedRange(); // For range to be null a WebKit client must have done something bad while // manually controlling drag behaviour if (!range) return false; DocLoader* loader = range->ownerDocument()->docLoader(); loader->setAllowStaleResources(true); if (dragIsMove(innerFrame->selection()) || dragCaret.isContentRichlyEditable()) { bool chosePlainText = false; RefPtr<DocumentFragment> fragment = documentFragmentFromDragData(dragData, range, true, chosePlainText); if (!fragment || !innerFrame->editor()->shouldInsertFragment(fragment, range, EditorInsertActionDropped)) { loader->setAllowStaleResources(false); return false; } m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData); if (dragIsMove(innerFrame->selection())) { bool smartMove = innerFrame->selectionGranularity() == WordGranularity && innerFrame->editor()->smartInsertDeleteEnabled() && dragData->canSmartReplace(); applyCommand(MoveSelectionCommand::create(fragment, dragCaret.base(), smartMove)); } else { if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse, fragment, true, dragData->canSmartReplace(), chosePlainText)); } } else { String text = dragData->asPlainText(); if (text.isEmpty() || !innerFrame->editor()->shouldInsertText(text, range.get(), EditorInsertActionDropped)) { loader->setAllowStaleResources(false); return false; } m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData); if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse, createFragmentFromText(range.get(), text), true, false, true)); } loader->setAllowStaleResources(false); return true; }