13c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch/*
23c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * Copyright (C) 2013 Google Inc. All rights reserved.
33c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch *
43c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * Redistribution and use in source and binary forms, with or without
53c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * modification, are permitted provided that the following conditions are
63c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * met:
73c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch *
83c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch *     * Redistributions of source code must retain the above copyright
93c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * notice, this list of conditions and the following disclaimer.
103c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch *     * Redistributions in binary form must reproduce the above
113c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * copyright notice, this list of conditions and the following disclaimer
123c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * in the documentation and/or other materials provided with the
133c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * distribution.
143c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch *     * Neither the name of Google Inc. nor the names of its
153c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * contributors may be used to endorse or promote products derived from
163c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * this software without specific prior written permission.
173c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch *
183c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
193c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
203c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
213c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
223c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
233c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
243c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
253c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
263c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
273c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
283c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
293c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch */
303c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
313c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "config.h"
32e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)#include "core/html/HTMLImportLoader.h"
333c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
343c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "core/dom/Document.h"
351e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "core/dom/custom/CustomElementRegistrationContext.h"
36e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#include "core/fetch/ResourceFetcher.h"
37a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "core/frame/ContentSecurityPolicyResponseHeaders.h"
383c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "core/html/HTMLDocument.h"
39a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "core/html/HTMLImport.h"
40e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)#include "core/html/HTMLImportLoaderClient.h"
413c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch#include "core/loader/DocumentWriter.h"
423c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
433c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
44a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)namespace WebCore {
453c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
46e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)PassRefPtr<HTMLImportLoader> HTMLImportLoader::create(HTMLImport* import, ResourceFetcher* fetcher)
47e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles){
48e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)    RefPtr<HTMLImportLoader> self = adoptRef(new HTMLImportLoader(import, fetcher));
49a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    return self.release();
50e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)}
51e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
52e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)HTMLImportLoader::HTMLImportLoader(HTMLImport* import, ResourceFetcher* fetcher)
53a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    : m_import(import)
54a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    , m_fetcher(fetcher)
55a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    , m_state(StateLoading)
563c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
573c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
583c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
59e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)HTMLImportLoader::~HTMLImportLoader()
603c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
61a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (m_importedDocument)
62a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_importedDocument->setImport(0);
633c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
643c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
65e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)void HTMLImportLoader::startLoading(const ResourcePtr<RawResource>& resource)
663c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
67a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    setResource(resource);
683c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
693c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
70e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)void HTMLImportLoader::responseReceived(Resource* resource, const ResourceResponse& response)
713c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
72a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    // Current canAccess() implementation isn't sufficient for catching cross-domain redirects: http://crbug.com/256976
73a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (!m_fetcher->canAccess(resource, PotentiallyCORSEnabled)) {
74a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        setState(StateError);
753c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch        return;
763c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    }
773c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
78a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    setState(startWritingAndParsing(response));
793c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
803c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
81e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)void HTMLImportLoader::dataReceived(Resource*, const char* data, int length)
823c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
83a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    RefPtr<DocumentWriter> protectingWriter(m_writer);
84a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    m_writer->addData(data, length);
85a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
863c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
87e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)void HTMLImportLoader::notifyFinished(Resource* resource)
88a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){
89a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    // The writer instance indicates that a part of the document can be already loaded.
90a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    // We don't take such a case as an error because the partially-loaded document has been visible from script at this point.
91a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (resource->loadFailedOrCanceled() && !m_writer) {
92a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        setState(StateError);
93a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        return;
943c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    }
953c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
96a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    setState(finishWriting());
973c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
983c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
99e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)HTMLImportLoader::State HTMLImportLoader::startWritingAndParsing(const ResourceResponse& response)
1003c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
101a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    DocumentInit init = DocumentInit(response.url(), 0, m_import->master()->contextDocument(), m_import)
102a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        .withRegistrationContext(m_import->master()->registrationContext());
1038abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    m_importedDocument = HTMLDocument::create(init);
1043c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    m_importedDocument->initContentSecurityPolicy(ContentSecurityPolicyResponseHeaders(response));
1053c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    m_writer = DocumentWriter::create(m_importedDocument.get(), response.mimeType(), response.textEncodingName());
1063c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
1073c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    return StateLoading;
1083c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
1093c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
110e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)HTMLImportLoader::State HTMLImportLoader::finishWriting()
1113c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
1123c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    return StateWritten;
1133c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
1143c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
115e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)HTMLImportLoader::State HTMLImportLoader::finishParsing()
1163c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
1173c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch    return StateReady;
1183c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
1193c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
120e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)void HTMLImportLoader::setState(State state)
1213c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
122a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (m_state == state)
123a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        return;
1243c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
125a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    m_state = state;
1263c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
127a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (m_state == StateReady || m_state == StateError || m_state == StateWritten) {
128a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        if (RefPtr<DocumentWriter> writer = m_writer.release())
129a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)            writer->end();
130a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    }
131a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
132a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    // Since DocumentWriter::end() can let setState() reenter, we shouldn't refer to m_state here.
133a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (state == StateReady || state == StateError)
134a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        didFinish();
1353c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
1363c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
137e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)void HTMLImportLoader::didFinishParsing()
1383c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
139a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    setState(finishParsing());
1403c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
1413c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
142e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)Document* HTMLImportLoader::importedDocument() const
1433c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
144a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (m_state == StateError)
145a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        return 0;
146a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    return m_importedDocument.get();
1473c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
1483c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
149e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)bool HTMLImportLoader::isProcessing() const
1503c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
151a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (!m_importedDocument)
152a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        return !isDone();
153a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    return m_importedDocument->parsing();
1543c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
1553c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
156e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)void HTMLImportLoader::didFinish()
1573c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
158a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    for (size_t i = 0; i < m_clients.size(); ++i)
159a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        m_clients[i]->didFinish();
160a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
161a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    clearResource();
162a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
163a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    ASSERT(!m_importedDocument || !m_importedDocument->parsing());
1643c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
1653c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
166e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)void HTMLImportLoader::addClient(HTMLImportLoaderClient* client)
1673c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
168a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    ASSERT(kNotFound == m_clients.find(client));
169a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    m_clients.append(client);
170a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (isDone())
171a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        client->didFinish();
1723c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
1733c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
174e08f70592b3fc0d5e68b9b914c9196e813720070Torne (Richard Coles)void HTMLImportLoader::removeClient(HTMLImportLoaderClient* client)
1753c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch{
176a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    ASSERT(kNotFound != m_clients.find(client));
177a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    m_clients.remove(m_clients.find(client));
1783c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch}
1793c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch
180a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
1813c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch} // namespace WebCore
182