void DocumentLoader::dataReceived(Resource* resource, const char* data, unsigned length) { ASSERT(data); ASSERT(length); ASSERT_UNUSED(resource, resource == m_mainResource); ASSERT(!m_response.isNull()); ASSERT(!mainResourceLoader() || !mainResourceLoader()->defersLoading()); // Both unloading the old page and parsing the new page may execute JavaScript which destroys the datasource // by starting a new load, so retain temporarily. RefPtrWillBeRawPtr<LocalFrame> protectFrame(m_frame); RefPtr<DocumentLoader> protectLoader(this); m_applicationCacheHost->mainResourceDataReceived(data, length); m_timeOfLastDataReceived = monotonicallyIncreasingTime(); if (isArchiveMIMEType(response().mimeType())) return; commitIfReady(); if (!frameLoader()) return; commitData(data, length); // If we are sending data to MediaDocument, we should stop here // and cancel the request. if (m_frame && m_frame->document()->isMediaDocument()) cancelMainResourceLoad(ResourceError::cancelledError(m_request.url())); }
void V8AbstractEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event) { // EventListener could be disconnected from the frame. if (disconnected()) return; // The callback function on XMLHttpRequest can clear the event listener and destroys 'this' object. Keep a local reference to it. // See issue 889829. RefPtr<V8AbstractEventListener> protect(this); v8::HandleScope handleScope; if (!m_context) return; // Create a new local handle since the persistent handle stored in // m_context may be disposed before we're done. v8::Handle<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context->get()); if (v8Context.IsEmpty()) return; // m_frame can removed by the callback function, protect it until the callback function returns. RefPtr<Frame> protectFrame(m_frame); // Enter the V8 context in which to perform the event handling. v8::Context::Scope scope(v8Context); // Get the V8 wrapper for the event object. v8::Handle<v8::Value> jsEvent = V8DOMWrapper::convertEventToV8Object(event); invokeEventHandler(v8Context, event, jsEvent); Document::updateStyleForAllDocuments(); }
// Cancels the data source's pending loads. Conceptually, a data source only loads // one document at a time, but one document may have many related resources. // stopLoading will stop all loads initiated by the data source, // but not loads initiated by child frames' data sources -- that's the WebFrame's job. void DocumentLoader::stopLoading() { // In some rare cases, calling FrameLoader::stopLoading could set m_loading to false. // (This can happen when there's a single XMLHttpRequest currently loading and stopLoading causes it // to stop loading. Because of this, we need to save it so we don't return early. bool loading = m_loading; if (m_committed) { // Attempt to stop the frame if the document loader is loading, or if it is done loading but // still parsing. Failure to do so can cause a world leak. Document* doc = m_frame->document(); if (loading || doc->parsing()) m_frame->loader()->stopLoading(UnloadEventPolicyNone); } // Always cancel multipart loaders cancelAll(m_multipartSubresourceLoaders); // Appcache uses ResourceHandle directly, DocumentLoader doesn't count these loads. m_applicationCacheHost->stopLoadingInFrame(m_frame); if (!loading) { // If something above restarted loading we might run into mysterious crashes like // https://bugs.webkit.org/show_bug.cgi?id=62764 and <rdar://problem/9328684> ASSERT(!m_loading); return; } // We might run in to infinite recursion if we're stopping loading as the result of // detaching from the frame, so break out of that recursion here. // See <rdar://problem/9673866> for more details. if (m_isStopping) return; RefPtr<Frame> protectFrame(m_frame); RefPtr<DocumentLoader> protectLoader(this); m_isStopping = true; FrameLoader* frameLoader = DocumentLoader::frameLoader(); if (m_mainResourceLoader) // Stop the main resource loader and let it send the cancelled message. m_mainResourceLoader->cancel(); else if (!m_subresourceLoaders.isEmpty()) // The main resource loader already finished loading. Set the cancelled error on the // document and let the subresourceLoaders send individual cancelled messages below. setMainDocumentError(frameLoader->cancelledError(m_request)); else // If there are no resource loaders, we need to manufacture a cancelled message. // (A back/forward navigation has no resource loaders because its resources are cached.) mainReceivedError(frameLoader->cancelledError(m_request), true); stopLoadingSubresources(); stopLoadingPlugIns(); m_isStopping = false; }
void MainResourceLoader::receivedError(const ResourceError& error) { // Calling receivedMainResourceError will likely result in the last reference to this object to go away. RefPtr<MainResourceLoader> protect(this); RefPtr<Frame> protectFrame(m_documentLoader->frame()); // It is important that we call DocumentLoader::mainReceivedError before calling // ResourceLoadNotifier::didFailToLoad because mainReceivedError clears out the relevant // document loaders. Also, mainReceivedError ends up calling a FrameLoadDelegate method // and didFailToLoad calls a ResourceLoadDelegate method and they need to be in the correct order. documentLoader()->mainReceivedError(error); }
// Cancels the data source's pending loads. Conceptually, a data source only loads // one document at a time, but one document may have many related resources. // stopLoading will stop all loads initiated by the data source, // but not loads initiated by child frames' data sources -- that's the WebFrame's job. void DocumentLoader::stopLoading(DatabasePolicy databasePolicy) { // In some rare cases, calling FrameLoader::stopLoading could set m_loading to false. // (This can happen when there's a single XMLHttpRequest currently loading and stopLoading causes it // to stop loading. Because of this, we need to save it so we don't return early. bool loading = m_loading; if (m_committed) { // Attempt to stop the frame if the document loader is loading, or if it is done loading but // still parsing. Failure to do so can cause a world leak. Document* doc = m_frame->document(); if (loading || doc->parsing()) m_frame->loader()->stopLoading(UnloadEventPolicyNone, databasePolicy); } // Always cancel multipart loaders cancelAll(m_multipartSubresourceLoaders); // Appcache uses ResourceHandle directly, DocumentLoader doesn't count these loads. #if ENABLE(OFFLINE_WEB_APPLICATIONS) m_applicationCacheHost->stopLoadingInFrame(m_frame); #endif if (!loading) return; RefPtr<Frame> protectFrame(m_frame); RefPtr<DocumentLoader> protectLoader(this); m_isStopping = true; FrameLoader* frameLoader = DocumentLoader::frameLoader(); if (m_mainResourceLoader) // Stop the main resource loader and let it send the cancelled message. m_mainResourceLoader->cancel(); else if (!m_subresourceLoaders.isEmpty()) // The main resource loader already finished loading. Set the cancelled error on the // document and let the subresourceLoaders send individual cancelled messages below. setMainDocumentError(frameLoader->cancelledError(m_request)); else // If there are no resource loaders, we need to manufacture a cancelled message. // (A back/forward navigation has no resource loaders because its resources are cached.) mainReceivedError(frameLoader->cancelledError(m_request), true); stopLoadingSubresources(); stopLoadingPlugIns(); m_isStopping = false; }
void DocumentLoader::detachFromFrame() { ASSERT(m_frame); RefPtr<Frame> protectFrame(m_frame); RefPtr<DocumentLoader> protectLoader(this); // It never makes sense to have a document loader that is detached from its // frame have any loads active, so go ahead and kill all the loads. stopLoading(); m_applicationCacheHost->setDOMApplicationCache(0); InspectorInstrumentation::loaderDetachedFromFrame(m_frame, this); m_frame = 0; }
void DocumentLoader::commitLoad(const char* data, int length) { // Both unloading the old page and parsing the new page may execute JavaScript which destroys the datasource // by starting a new load, so retain temporarily. RefPtr<Frame> protectFrame(m_frame); RefPtr<DocumentLoader> protectLoader(this); commitIfReady(); FrameLoader* frameLoader = DocumentLoader::frameLoader(); if (!frameLoader) return; if (isArchiveMIMEType(response().mimeType())) return; frameLoader->client()->committedLoad(this, data, length); }
void MainResourceLoader::receivedError(const ResourceError& error) { // Calling receivedMainResourceError will likely result in the last reference to this object to go away. RefPtr<MainResourceLoader> protect(this); RefPtr<Frame> protectFrame(m_frame); // It is important that we call FrameLoader::receivedMainResourceError before calling // FrameLoader::didFailToLoad because receivedMainResourceError clears out the relevant // document loaders. Also, receivedMainResourceError ends up calling a FrameLoadDelegate method // and didFailToLoad calls a ResourceLoadDelegate method and they need to be in the correct order. frameLoader()->receivedMainResourceError(error, true); if (!cancelled()) { ASSERT(!reachedTerminalState()); frameLoader()->notifier()->didFailToLoad(this, error); releaseResources(); } ASSERT(reachedTerminalState()); }
// Cancels the data source's pending loads. Conceptually, a data source only loads // one document at a time, but one document may have many related resources. // stopLoading will stop all loads initiated by the data source, // but not loads initiated by child frames' data sources -- that's the WebFrame's job. void DocumentLoader::stopLoading() { RefPtrWillBeRawPtr<LocalFrame> protectFrame(m_frame); RefPtr<DocumentLoader> protectLoader(this); // In some rare cases, calling FrameLoader::stopLoading could cause isLoading() to return false. // (This can happen when there's a single XMLHttpRequest currently loading and stopLoading causes it // to stop loading. Because of this, we need to save it so we don't return early. bool loading = isLoading(); if (m_committed) { // Attempt to stop the frame if the document loader is loading, or if it is done loading but // still parsing. Failure to do so can cause a world leak. Document* doc = m_frame->document(); if (loading || doc->parsing()) m_frame->loader().stopLoading(); } if (!loading) { m_fetcher->stopFetching(); return; } if (m_loadingMainResource) { // Stop the main resource loader and let it send the cancelled message. cancelMainResourceLoad(ResourceError::cancelledError(m_request.url())); } else if (m_fetcher->isFetching()) { // The main resource loader already finished loading. Set the cancelled error on the // document and let the resourceLoaders send individual cancelled messages below. setMainDocumentError(ResourceError::cancelledError(m_request.url())); } else { // If there are no resource loaders, we need to manufacture a cancelled message. // (A back/forward navigation has no resource loaders because its resources are cached.) mainReceivedError(ResourceError::cancelledError(m_request.url())); } m_fetcher->stopFetching(); }