Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / HTMLImportLoader.cpp
index 3f8ca2f..e0a0c00 100644 (file)
 #include "core/html/HTMLImportLoader.h"
 
 #include "core/dom/Document.h"
-#include "core/dom/custom/CustomElementRegistrationContext.h"
 #include "core/fetch/ResourceFetcher.h"
+#include "core/frame/ContentSecurityPolicyResponseHeaders.h"
 #include "core/html/HTMLDocument.h"
+#include "core/html/HTMLImport.h"
 #include "core/html/HTMLImportLoaderClient.h"
 #include "core/loader/DocumentWriter.h"
-#include "core/frame/ContentSecurityPolicyResponseHeaders.h"
+
 
 namespace WebCore {
 
-HTMLImportLoader::HTMLImportLoader(HTMLImport* parent, const KURL& url)
-    : m_parent(parent)
+HTMLImportLoader::HTMLImportLoader(HTMLImport* import)
+    : m_import(import)
     , m_state(StateLoading)
-    , m_url(url)
 {
 }
 
 HTMLImportLoader::~HTMLImportLoader()
 {
-    // importDestroyed() should be called before the destruction.
-    ASSERT(!m_parent);
-    ASSERT(!m_importedDocument);
-    if (m_resource)
-        m_resource->removeClient(this);
+    if (m_importedDocument)
+        m_importedDocument->setImport(0);
 }
 
-void HTMLImportLoader::setResource(const ResourcePtr<RawResource>& resource)
+void HTMLImportLoader::startLoading(const ResourcePtr<RawResource>& resource)
 {
-    m_resource = resource;
-    m_resource->addClient(this);
+    setResource(resource);
 }
 
-void HTMLImportLoader::responseReceived(Resource*, const ResourceResponse& response)
+void HTMLImportLoader::responseReceived(Resource* resource, const ResourceResponse& response)
 {
+    // Resource may already have been loaded with the import loader
+    // being added as a client later & now being notified. Fail early.
+    if (resource->loadFailedOrCanceled() || response.httpStatusCode() >= 400) {
+        setState(StateError);
+        return;
+    }
     setState(startWritingAndParsing(response));
 }
 
@@ -74,50 +76,22 @@ void HTMLImportLoader::dataReceived(Resource*, const char* data, int length)
     m_writer->addData(data, length);
 }
 
-void HTMLImportLoader::notifyFinished(Resource*)
+void HTMLImportLoader::notifyFinished(Resource* resource)
 {
-    setState(finishWriting());
-}
-
-void HTMLImportLoader::setState(State state)
-{
-    if (m_state == state)
+    // The writer instance indicates that a part of the document can be already loaded.
+    // We don't take such a case as an error because the partially-loaded document has been visible from script at this point.
+    if (resource->loadFailedOrCanceled() && !m_writer) {
+        setState(StateError);
         return;
-
-    m_state = state;
-
-    if (m_state == StateReady || m_state == StateError || m_state == StateWritten) {
-        if (RefPtr<DocumentWriter> writer = m_writer.release())
-            writer->end();
     }
 
-    // Since DocumentWriter::end() let setState() reenter, we shouldn't refer to m_state here.
-    if (state == StateReady || state == StateError)
-        didFinish();
-}
-
-void HTMLImportLoader::didFinish()
-{
-    for (size_t i = 0; i < m_clients.size(); ++i)
-        m_clients[i]->didFinish();
-
-    if (m_resource) {
-        m_resource->removeClient(this);
-        m_resource = 0;
-    }
-
-    ASSERT(!document() || !document()->parsing());
-    root()->importWasDisposed();
+    setState(finishWriting());
 }
 
 HTMLImportLoader::State HTMLImportLoader::startWritingAndParsing(const ResourceResponse& response)
 {
-    // Current canAccess() implementation isn't sufficient for catching cross-domain redirects: http://crbug.com/256976
-    if (!m_parent->document()->fetcher()->canAccess(m_resource.get()))
-        return StateError;
-
-    DocumentInit init = DocumentInit(response.url(), 0, root()->document()->contextDocument(), this)
-        .withRegistrationContext(root()->document()->registrationContext());
+    DocumentInit init = DocumentInit(response.url(), 0, m_import->master()->contextDocument(), m_import)
+        .withRegistrationContext(m_import->master()->registrationContext());
     m_importedDocument = HTMLDocument::create(init);
     m_importedDocument->initContentSecurityPolicy(ContentSecurityPolicyResponseHeaders(response));
     m_writer = DocumentWriter::create(m_importedDocument.get(), response.mimeType(), response.textEncodingName());
@@ -127,83 +101,65 @@ HTMLImportLoader::State HTMLImportLoader::startWritingAndParsing(const ResourceR
 
 HTMLImportLoader::State HTMLImportLoader::finishWriting()
 {
-    if (!m_parent)
-        return StateError;
-    // The writer instance indicates that a part of the document can be already loaded.
-    // We don't take such a case as an error because the partially-loaded document has been visible from script at this point.
-    if (m_resource->loadFailedOrCanceled() && !m_writer)
-        return StateError;
-
     return StateWritten;
 }
 
 HTMLImportLoader::State HTMLImportLoader::finishParsing()
 {
-    if (!m_parent)
-        return StateError;
     return StateReady;
 }
 
-Document* HTMLImportLoader::importedDocument() const
-{
-    if (m_state == StateError)
-        return 0;
-    return m_importedDocument.get();
-}
-
-void HTMLImportLoader::addClient(HTMLImportLoaderClient* client)
+void HTMLImportLoader::setState(State state)
 {
-    ASSERT(kNotFound == m_clients.find(client));
-    m_clients.append(client);
-    if (isDone())
-        client->didFinish();
-}
+    if (m_state == state)
+        return;
 
-void HTMLImportLoader::removeClient(HTMLImportLoaderClient* client)
-{
-    ASSERT(kNotFound != m_clients.find(client));
-    m_clients.remove(m_clients.find(client));
-}
+    m_state = state;
 
-void HTMLImportLoader::importDestroyed()
-{
-    m_parent = 0;
-    if (RefPtr<Document> document = m_importedDocument.release())
-        document->setImport(0);
-}
+    if (m_state == StateReady || m_state == StateError || m_state == StateWritten) {
+        if (RefPtr<DocumentWriter> writer = m_writer.release())
+            writer->end();
+    }
 
-HTMLImportRoot* HTMLImportLoader::root()
-{
-    return m_parent ? m_parent->root() : 0;
+    // Since DocumentWriter::end() can let setState() reenter, we shouldn't refer to m_state here.
+    if (state == StateReady || state == StateError)
+        didFinish();
 }
 
-HTMLImport* HTMLImportLoader::parent() const
+void HTMLImportLoader::didFinishParsing()
 {
-    return m_parent;
+    setState(finishParsing());
 }
 
-Document* HTMLImportLoader::document() const
+Document* HTMLImportLoader::importedDocument() const
 {
+    if (m_state == StateError)
+        return 0;
     return m_importedDocument.get();
 }
 
-void HTMLImportLoader::wasDetachedFromDocument()
+void HTMLImportLoader::didFinish()
 {
-    // For imported documens this shouldn't be called because Document::m_import is
-    // cleared before Document is destroyed by HTMLImportLoader::importDestroyed().
-    ASSERT_NOT_REACHED();
+    for (size_t i = 0; i < m_clients.size(); ++i)
+        m_clients[i]->didFinishLoading();
+
+    clearResource();
+
+    ASSERT(!m_importedDocument || !m_importedDocument->parsing());
 }
 
-void HTMLImportLoader::didFinishParsing()
+void HTMLImportLoader::addClient(HTMLImportLoaderClient* client)
 {
-    setState(finishParsing());
+    ASSERT(kNotFound == m_clients.find(client));
+    m_clients.append(client);
+    if (isDone())
+        client->didFinishLoading();
 }
 
-bool HTMLImportLoader::isProcessing() const
+void HTMLImportLoader::removeClient(HTMLImportLoaderClient* client)
 {
-    if (!m_importedDocument)
-        return !isDone();
-    return m_importedDocument->parsing();
+    ASSERT(kNotFound != m_clients.find(client));
+    m_clients.remove(m_clients.find(client));
 }
 
 } // namespace WebCore