| Index: Source/core/loader/DocumentLoader.cpp | 
| diff --git a/Source/core/loader/DocumentLoader.cpp b/Source/core/loader/DocumentLoader.cpp | 
| index 3d45f54c1537d10a453a9d9cf9d9777a88a90169..f267b9a165e5fde9a9862d07ce50e789ee73f85a 100644 | 
| --- a/Source/core/loader/DocumentLoader.cpp | 
| +++ b/Source/core/loader/DocumentLoader.cpp | 
| @@ -72,6 +72,7 @@ | 
| #include "public/platform/Platform.h" | 
| #include "public/platform/WebMimeRegistry.h" | 
| #include "wtf/Assertions.h" | 
| +#include "wtf/TemporaryChange.h" | 
| #include "wtf/text/WTFString.h" | 
|  | 
| namespace blink { | 
| @@ -93,6 +94,7 @@ DocumentLoader::DocumentLoader(LocalFrame* frame, const ResourceRequest& req, co | 
| , m_timeOfLastDataReceived(0.0) | 
| , m_applicationCacheHost(ApplicationCacheHost::create(this)) | 
| , m_state(NotStarted) | 
| +    , m_inDataReceived(false) | 
| { | 
| } | 
|  | 
| @@ -554,11 +556,39 @@ void DocumentLoader::dataReceived(Resource* resource, const char* data, unsigned | 
| ASSERT(!m_response.isNull()); | 
| ASSERT(!mainResourceLoader() || !mainResourceLoader()->defersLoading()); | 
|  | 
| +    if (m_inDataReceived) { | 
| +        // If this function is reentered, defer processing of the additional | 
| +        // data to the top-level invocation. Reentrant calls can occur because | 
| +        // of web platform (mis-)features that require running a nested message | 
| +        // loop: | 
| +        // - alert(), confirm(), prompt() | 
| +        // - Detach of plugin elements. | 
| +        // - Synchronous XMLHTTPRequest | 
| +        OwnPtr<Vector<char>> chunk = adoptPtr(new Vector<char>(length)); | 
| +        memcpy(chunk->data(), data, length); | 
| +        m_dataQueue.append(chunk.release()); | 
| +        return; | 
| +    } | 
| +    TemporaryChange<bool> reentrancyProtector(m_inDataReceived, true); | 
| + | 
| // 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.get()); | 
| RefPtrWillBeRawPtr<DocumentLoader> protectLoader(this); | 
|  | 
| +    processData(data, length); | 
| + | 
| +    // Process chunks received in reentrant invocations. Note that the | 
| +    // invocations of processData() may queue more chunks in reentrant | 
| +    // invocations, so iterate until it's empty. | 
| +    while (m_dataQueue.size() > 0) { | 
| +        OwnPtr<Vector<char>> chunk = m_dataQueue.takeFirst(); | 
| +        processData(chunk->data(), chunk->size()); | 
| +    } | 
| +} | 
| + | 
| +void DocumentLoader::processData(const char* data, unsigned length) | 
| +{ | 
| m_applicationCacheHost->mainResourceDataReceived(data, length); | 
| m_timeOfLastDataReceived = monotonicallyIncreasingTime(); | 
|  | 
|  |