Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / imports / HTMLImportChild.cpp
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "core/html/imports/HTMLImportChild.h"
33
34 #include "core/dom/Document.h"
35 #include "core/dom/custom/CustomElement.h"
36 #include "core/dom/custom/CustomElementMicrotaskImportStep.h"
37 #include "core/html/imports/HTMLImportChildClient.h"
38 #include "core/html/imports/HTMLImportLoader.h"
39
40 namespace WebCore {
41
42 HTMLImportChild::HTMLImportChild(Document& master, const KURL& url, SyncMode sync)
43     : HTMLImport(sync)
44     , m_master(master)
45     , m_url(url)
46     , m_customElementMicrotaskStep(0)
47     , m_client(0)
48 {
49     m_master.guardRef();
50 }
51
52 HTMLImportChild::~HTMLImportChild()
53 {
54     // importDestroyed() should be called before the destruction.
55     ASSERT(!m_loader);
56
57     if (m_customElementMicrotaskStep) {
58         // if Custom Elements were blocked, must unblock them before death
59         m_customElementMicrotaskStep->importDidFinish();
60         m_customElementMicrotaskStep = 0;
61     }
62
63     if (m_client)
64         m_client->importChildWasDestroyed(this);
65
66     m_master.guardDeref();
67 }
68
69 void HTMLImportChild::wasAlreadyLoaded()
70 {
71     ASSERT(!m_loader);
72     ASSERT(m_client);
73     stateWillChange();
74 }
75
76 void HTMLImportChild::startLoading(const ResourcePtr<RawResource>& resource)
77 {
78     ASSERT(!this->resource());
79     ASSERT(!m_loader);
80
81     if (isSync()) {
82         ASSERT(!m_customElementMicrotaskStep);
83         m_customElementMicrotaskStep = CustomElement::didCreateImport(this);
84     }
85
86     setResource(resource);
87
88     // If the node is "document blocked", it cannot create HTMLImportLoader
89     // even if there is no sharable one found, as there is possibility that
90     // preceding imports load the sharable imports.
91     // In that case preceding one should win because it comes first in the tree order.
92     // See also didUnblockFromCreatingDocument().
93     if (state().shouldBlockDocumentCreation())
94         return;
95
96     ensureLoader();
97 }
98
99 void HTMLImportChild::didFinish()
100 {
101     if (m_client)
102         m_client->didFinish();
103
104     if (m_customElementMicrotaskStep) {
105         m_customElementMicrotaskStep->importDidFinish();
106         m_customElementMicrotaskStep = 0;
107     }
108 }
109
110 void HTMLImportChild::didFinishLoading()
111 {
112     clearResource();
113     stateWillChange();
114 }
115
116 Document* HTMLImportChild::importedDocument() const
117 {
118     if (!m_loader)
119         return 0;
120     return m_loader->importedDocument();
121 }
122
123 void HTMLImportChild::importDestroyed()
124 {
125     if (parent())
126         parent()->removeChild(this);
127     if (m_loader) {
128         m_loader->removeImport(this);
129         m_loader.clear();
130     }
131 }
132
133 HTMLImportRoot* HTMLImportChild::root()
134 {
135     return parent() ? parent()->root() : 0;
136 }
137
138 Document* HTMLImportChild::document() const
139 {
140     return (m_loader && m_loader->isOwnedBy(this)) ? m_loader->document() : 0;
141 }
142
143 void HTMLImportChild::wasDetachedFromDocument()
144 {
145     // For imported documens this shouldn't be called because Document::m_import is
146     // cleared before Document is destroyed by HTMLImportChild::importDestroyed().
147     ASSERT_NOT_REACHED();
148 }
149
150 void HTMLImportChild::didFinishParsing()
151 {
152     ASSERT(m_loader->isOwnedBy(this));
153     m_loader->didFinishParsing();
154 }
155
156 void HTMLImportChild::didRemoveAllPendingStylesheet()
157 {
158     ASSERT(m_loader->isOwnedBy(this));
159     m_loader->didRemoveAllPendingStylesheet();
160 }
161
162 void HTMLImportChild::stateDidChange()
163 {
164     HTMLImport::stateDidChange();
165
166     // Once all preceding imports are loaded,
167     // HTMLImportChild can decide whether it should load the import by itself
168     // or it can share existing one.
169     if (!state().shouldBlockDocumentCreation())
170         ensureLoader();
171     if (state().isReady())
172         didFinish();
173 }
174
175 void HTMLImportChild::ensureLoader()
176 {
177     if (m_loader)
178         return;
179
180     if (HTMLImportChild* found = root()->findLinkFor(m_url, this))
181         shareLoader(found);
182     else
183         createLoader();
184 }
185
186 void HTMLImportChild::createLoader()
187 {
188     ASSERT(!state().shouldBlockDocumentCreation());
189     ASSERT(!m_loader);
190     m_loader = HTMLImportLoader::create();
191     m_loader->addImport(this);
192     m_loader->startLoading(resource());
193 }
194
195 void HTMLImportChild::shareLoader(HTMLImportChild* loader)
196 {
197     ASSERT(!m_loader);
198     m_loader = loader->m_loader;
199     m_loader->addImport(this);
200     stateWillChange();
201 }
202
203 bool HTMLImportChild::isDone() const
204 {
205     return m_loader && m_loader->isDone();
206 }
207
208 bool HTMLImportChild::hasLoader() const
209 {
210     return m_loader;
211 }
212
213 bool HTMLImportChild::ownsLoader() const
214 {
215     return m_loader && m_loader->isOwnedBy(this);
216 }
217
218 bool HTMLImportChild::loaderHasError() const
219 {
220     return m_loader && m_loader->hasError();
221 }
222
223
224 void HTMLImportChild::setClient(HTMLImportChildClient* client)
225 {
226     ASSERT(client);
227     ASSERT(!m_client);
228     m_client = client;
229 }
230
231 void HTMLImportChild::clearClient()
232 {
233     // Doesn't check m_client nullity because we allow
234     // clearClient() to reenter.
235     m_client = 0;
236 }
237
238 HTMLLinkElement* HTMLImportChild::link() const
239 {
240     if (!m_client)
241         return 0;
242     return m_client->link();
243 }
244
245 #if !defined(NDEBUG)
246 void HTMLImportChild::showThis()
247 {
248     HTMLImport::showThis();
249     fprintf(stderr, " loader=%p own=%s async=%s url=%s",
250         m_loader.get(),
251         hasLoader() && ownsLoader() ? "Y" : "N",
252         isSync() ? "Y" : "N",
253         url().string().utf8().data());
254 }
255 #endif
256
257 } // namespace WebCore