Home | History | Annotate | Download | only in imports
      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/dom/custom/CustomElementSyncMicrotaskQueue.h"
     38 #include "core/html/imports/HTMLImportChildClient.h"
     39 #include "core/html/imports/HTMLImportLoader.h"
     40 #include "core/html/imports/HTMLImportTreeRoot.h"
     41 #include "core/html/imports/HTMLImportsController.h"
     42 
     43 namespace blink {
     44 
     45 HTMLImportChild::HTMLImportChild(const KURL& url, HTMLImportLoader* loader, SyncMode sync)
     46     : HTMLImport(sync)
     47     , m_url(url)
     48 #if !ENABLE(OILPAN)
     49     , m_weakFactory(this)
     50 #endif
     51     , m_loader(loader)
     52     , m_client(nullptr)
     53 {
     54 }
     55 
     56 HTMLImportChild::~HTMLImportChild()
     57 {
     58 #if !ENABLE(OILPAN)
     59     // importDestroyed() should be called before the destruction.
     60     ASSERT(!m_loader);
     61 
     62     if (m_client)
     63         m_client->importChildWasDestroyed(this);
     64 #endif
     65 }
     66 
     67 void HTMLImportChild::ownerInserted()
     68 {
     69     if (!m_loader->isDone())
     70         return;
     71     root()->document()->styleResolverChanged();
     72 }
     73 
     74 void HTMLImportChild::didShareLoader()
     75 {
     76     createCustomElementMicrotaskStepIfNeeded();
     77     stateWillChange();
     78 }
     79 
     80 void HTMLImportChild::didStartLoading()
     81 {
     82     createCustomElementMicrotaskStepIfNeeded();
     83 }
     84 
     85 void HTMLImportChild::didFinish()
     86 {
     87     if (m_client)
     88         m_client->didFinish();
     89 }
     90 
     91 void HTMLImportChild::didFinishLoading()
     92 {
     93     stateWillChange();
     94     CustomElement::didFinishLoadingImport(*(root()->document()));
     95 }
     96 
     97 void HTMLImportChild::didFinishUpgradingCustomElements()
     98 {
     99     stateWillChange();
    100     m_customElementMicrotaskStep.clear();
    101 }
    102 
    103 #if !ENABLE(OILPAN)
    104 void HTMLImportChild::importDestroyed()
    105 {
    106     if (parent())
    107         parent()->removeChild(this);
    108 
    109     ASSERT(m_loader);
    110     m_loader->removeImport(this);
    111     m_loader = nullptr;
    112 }
    113 #endif
    114 
    115 Document* HTMLImportChild::document() const
    116 {
    117     ASSERT(m_loader);
    118     return m_loader->document();
    119 }
    120 
    121 void HTMLImportChild::stateWillChange()
    122 {
    123     toHTMLImportTreeRoot(root())->scheduleRecalcState();
    124 }
    125 
    126 void HTMLImportChild::stateDidChange()
    127 {
    128     HTMLImport::stateDidChange();
    129 
    130     if (state().isReady())
    131         didFinish();
    132 }
    133 
    134 void HTMLImportChild::invalidateCustomElementMicrotaskStep()
    135 {
    136     if (!m_customElementMicrotaskStep)
    137         return;
    138     m_customElementMicrotaskStep->invalidate();
    139     m_customElementMicrotaskStep.clear();
    140 }
    141 
    142 void HTMLImportChild::createCustomElementMicrotaskStepIfNeeded()
    143 {
    144     ASSERT(!m_customElementMicrotaskStep);
    145 
    146     if (!isDone() && !formsCycle()) {
    147 #if ENABLE(OILPAN)
    148         m_customElementMicrotaskStep = CustomElement::didCreateImport(this);
    149 #else
    150         m_customElementMicrotaskStep = CustomElement::didCreateImport(this)->weakPtr();
    151 #endif
    152     }
    153 }
    154 
    155 bool HTMLImportChild::isDone() const
    156 {
    157     ASSERT(m_loader);
    158 
    159     return m_loader->isDone() && m_loader->microtaskQueue()->isEmpty() && !m_customElementMicrotaskStep;
    160 }
    161 
    162 HTMLImportLoader* HTMLImportChild::loader() const
    163 {
    164     // This should never be called after importDestroyed.
    165     ASSERT(m_loader);
    166     return m_loader;
    167 }
    168 
    169 void HTMLImportChild::setClient(HTMLImportChildClient* client)
    170 {
    171     ASSERT(client);
    172     ASSERT(!m_client);
    173     m_client = client;
    174 }
    175 
    176 #if !ENABLE(OILPAN)
    177 void HTMLImportChild::clearClient()
    178 {
    179     // Doesn't check m_client nullity because we allow
    180     // clearClient() to reenter.
    181     m_client = nullptr;
    182 }
    183 #endif
    184 
    185 HTMLLinkElement* HTMLImportChild::link() const
    186 {
    187     if (!m_client)
    188         return 0;
    189     return m_client->link();
    190 }
    191 
    192 // Ensuring following invariants against the import tree:
    193 // - HTMLImportChild::firstImport() is the "first import" of the DFS order of the import tree.
    194 // - The "first import" manages all the children that is loaded by the document.
    195 void HTMLImportChild::normalize()
    196 {
    197     if (!loader()->isFirstImport(this) && this->precedes(loader()->firstImport())) {
    198         HTMLImportChild* oldFirst = loader()->firstImport();
    199         loader()->moveToFirst(this);
    200         takeChildrenFrom(oldFirst);
    201     }
    202 
    203     for (HTMLImportChild* child = toHTMLImportChild(firstChild()); child; child = toHTMLImportChild(child->next())) {
    204         if (child->formsCycle())
    205             child->invalidateCustomElementMicrotaskStep();
    206         child->normalize();
    207     }
    208 }
    209 
    210 #if !defined(NDEBUG)
    211 void HTMLImportChild::showThis()
    212 {
    213     bool isFirst = loader() ? loader()->isFirstImport(this) : false;
    214     HTMLImport::showThis();
    215     fprintf(stderr, " loader=%p first=%d, step=%p sync=%s url=%s",
    216         m_loader.get(),
    217         isFirst,
    218         m_customElementMicrotaskStep.get(),
    219         isSync() ? "Y" : "N",
    220         url().string().utf8().data());
    221 }
    222 #endif
    223 
    224 void HTMLImportChild::trace(Visitor* visitor)
    225 {
    226     visitor->trace(m_customElementMicrotaskStep);
    227     visitor->trace(m_loader);
    228     visitor->trace(m_client);
    229     HTMLImport::trace(visitor);
    230 }
    231 
    232 } // namespace blink
    233