Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 80 // Check around HTMLImportsController::findLink() for more detail. | 80 // Check around HTMLImportsController::findLink() for more detail. |
| 81 // | 81 // |
| 82 // Note that HTMLImportLoader provides HTMLImportLoaderClient to hook it up. | 82 // Note that HTMLImportLoader provides HTMLImportLoaderClient to hook it up. |
| 83 // As it can be shared, HTMLImportLoader supports multiple clients. | 83 // As it can be shared, HTMLImportLoader supports multiple clients. |
| 84 // | 84 // |
| 85 // HTMLImportChild (1)-->(*) HTMLImportLoader | 85 // HTMLImportChild (1)-->(*) HTMLImportLoader |
| 86 // | 86 // |
| 87 // | 87 // |
| 88 // # Script Blocking | 88 // # Script Blocking |
| 89 // | 89 // |
| 90 // The HTML parser blocks on <script> when preceding <link>s aren't finish loadi ng imports. | 90 // - An import blocks the HTML parser of its own imported document from running <script> |
| 91 // Each HTMLImport instance tracks such a blocking state, that is called "script -blocked" | 91 // until all of its children are loaded. |
| 92 // or HTMLImport::isBlockedFromRunningScript(). | 92 // Note that dynamically added import won't block the parser. |
| 93 // | 93 // |
| 94 // ## Blocking Imports | 94 // - An import under loading also blocks imported documents that follow from bei ng created. |
| 95 // | 95 // This is because an import can include another import that has same URLs of following ones. |
| 96 // Each imports can become being script-blocked when new imports are added to th e import tree. | 96 // In such case, the preceding import should be loaded and following ones shou ld be de-duped. |
| 97 // For example, the parser of a parent import is blocked when new child import i s given. | |
| 98 // See HTMLImport::appendChild() to see how it is handled. Note that this blocki ng-ness is | |
| 99 // transitive. HTMLImport::blockPredecessorsOf() flips the flags iteratively to fullfill this transitivity. | |
| 100 // | |
| 101 // ## Unblocking Imports | |
| 102 // | |
| 103 // The blocking state can change when one of the imports finish loading. The Doc ument notices it through | |
| 104 // HTMLImportRoot::blockerGone(). The blockerGone() triggers HTMLImport::unblock FromRunningScript(), which traverses | |
| 105 // whole import tree and find unblock-able imports and unblock them. | |
| 106 // Ready imported documents are notified through Document::didLoadAllImports() s o that | |
| 107 // it can resume its parser. | |
| 108 // | |
| 109 // # Document Blocking | |
| 110 // | |
| 111 // There is another type of blocking state that is called | |
| 112 // "document-blocked". If the import is document-blocked, it cannot | |
| 113 // create its own document object because sharable imported document | |
| 114 // can appear later. The spec defines the loading order of the | |
| 115 // import: The earlier one in the import-tree order should win and | |
| 116 // later ones should share earlier one. | |
| 117 // | |
| 118 // The "document-blocked" state keeps the tree node from loading its | |
| 119 // import until all preceding imports are ready t respect the | |
| 120 // order. Note that the node may fetch the bytes from the URL | |
| 121 // speculatively, even though it doesn't process it. | |
| 122 // | |
| 123 // The node is "document-unblocked" when there are unfinished, | |
| 124 // preceeding import loading. Unblocking attempt for | |
| 125 // "document-blocked" happens at the same timing as unblocking | |
| 126 // "script-blocked". | |
| 127 // | 97 // |
| 128 | 98 |
| 129 // The superclass of HTMLImportsController and HTMLImportChild | 99 // The superclass of HTMLImportsController and HTMLImportChild |
| 130 // This represents the import tree data structure. | 100 // This represents the import tree data structure. |
| 131 class HTMLImport : public TreeNode<HTMLImport> { | 101 class HTMLImport : public TreeNode<HTMLImport> { |
| 132 public: | 102 public: |
| 133 static bool unblock(HTMLImport*); | |
| 134 static bool isMaster(Document*); | 103 static bool isMaster(Document*); |
| 135 | 104 |
| 136 virtual ~HTMLImport() { } | 105 virtual ~HTMLImport() { } |
| 137 | 106 |
| 138 Frame* frame(); | 107 Frame* frame(); |
| 139 Document* master(); | 108 Document* master(); |
| 140 HTMLImportsController* controller(); | 109 HTMLImportsController* controller(); |
| 141 | 110 |
| 142 bool isCreatedByParser() const { return m_createdByParser; } | 111 bool isCreatedByParser() const { return m_createdByParser; } |
| 143 bool isBlockedFromRunningScript() const { return m_state <= BlockedFromRunni ngScript; } | |
| 144 bool isBlocked() const { return m_state < Ready; } | |
| 145 | 112 |
| 146 bool isBlockedFromCreatingDocument() const; | 113 bool isStateBlockedFromRunningScript() const { return state() <= BlockedFrom RunningScript; } |
|
dglazkov
2014/01/22 17:45:56
Why not just query state() directly at the callsit
| |
| 114 bool isStateBlockedFromCreatingDocument() const { return state() <= BlockedF romCreatingDocument; } | |
| 115 bool isStateReady() const { return state() == Ready; } | |
| 147 | 116 |
| 148 void appendChild(HTMLImport*); | 117 void appendChild(HTMLImport*); |
| 149 | 118 |
| 150 virtual HTMLImportRoot* root() = 0; | 119 virtual HTMLImportRoot* root() = 0; |
| 151 virtual Document* document() const = 0; | 120 virtual Document* document() const = 0; |
| 152 virtual void wasDetachedFromDocument() = 0; | 121 virtual void wasDetachedFromDocument() = 0; |
| 153 virtual void didFinishParsing() = 0; | 122 virtual void didFinishParsing() { }; |
| 154 virtual bool isDone() const = 0; // FIXME: Should be renamed to haveFinished Loading() | 123 virtual bool isDone() const = 0; // FIXME: Should be renamed to haveFinished Loading() |
| 155 virtual bool hasLoader() const = 0; | 124 virtual bool hasLoader() const = 0; |
| 156 virtual bool ownsLoader() const { return false; } | 125 virtual bool ownsLoader() const { return false; } |
| 157 virtual CustomElementMicrotaskImportStep* customElementMicrotaskStep() const { return 0; } | 126 virtual CustomElementMicrotaskImportStep* customElementMicrotaskStep() const { return 0; } |
| 127 virtual void stateDidChange(); | |
| 128 | |
| 129 enum State { | |
| 130 BlockedFromCreatingDocument = 0, | |
| 131 BlockedFromRunningScript, | |
| 132 Active, | |
| 133 Ready, | |
| 134 Invalid | |
| 135 }; | |
| 158 | 136 |
| 159 protected: | 137 protected: |
| 160 enum State { | 138 // Stating from most conservative state. |
| 161 BlockedFromRunningScript, | 139 // It will be corrected through state update flow. |
| 162 WaitingLoaderOrChildren, | 140 explicit HTMLImport(bool createdByParser = false) |
| 163 Ready | 141 : m_cachedState(BlockedFromCreatingDocument) |
| 164 }; | |
| 165 | |
| 166 explicit HTMLImport(State state, bool createdByParser = false) | |
| 167 : m_state(state) | |
| 168 , m_createdByParser(createdByParser) | 142 , m_createdByParser(createdByParser) |
| 169 { } | 143 { } |
| 170 | 144 |
| 171 virtual void didUnblockFromCreatingDocument(); | 145 void stateWillChange(); |
| 172 virtual void didUnblockFromRunningScript(); | 146 State state() const; |
| 173 virtual void didBecomeReady(); | 147 static void recalcTreeState(HTMLImport* root); |
| 174 | 148 |
| 175 void loaderWasResolved(); | 149 #if !defined(NDEBUG) |
| 176 void loaderDidFinish(); | 150 void show(); |
| 151 void showTree(HTMLImport* highlight, unsigned depth); | |
| 152 virtual void showThis(); | |
| 153 #endif | |
| 177 | 154 |
| 178 private: | 155 private: |
| 179 static void block(HTMLImport*); | 156 void recalcState(); |
| 157 void forceBlock(); | |
| 158 void invalidateCachedState() { m_cachedState = Invalid; } | |
| 159 bool isStateCacheValid() const { return m_cachedState != Invalid; } | |
| 180 | 160 |
| 181 void blockPredecessorsOf(HTMLImport* child); | 161 State m_cachedState; |
| 182 void blockFromRunningScript(); | |
| 183 void waitLoaderOrChildren(); | |
| 184 void unblockFromRunningScript(); | |
| 185 void becomeReady(); | |
| 186 | |
| 187 bool isBlockedFromRunningScriptByPredecessors() const; | |
| 188 bool isBlockingFollowersFromRunningScript() const; | |
| 189 bool isBlockingFollowersFromCreatingDocument() const; | |
| 190 | |
| 191 State m_state; | |
| 192 | |
| 193 bool m_createdByParser : 1; | 162 bool m_createdByParser : 1; |
| 194 }; | 163 }; |
| 195 | 164 |
| 165 inline HTMLImport::State HTMLImport::state() const | |
| 166 { | |
| 167 ASSERT(isStateCacheValid()); | |
| 168 return m_cachedState; | |
|
dglazkov
2014/01/22 17:45:56
Why is this called cachedState and not just state?
| |
| 169 } | |
| 170 | |
| 171 | |
| 196 // An abstract class to decouple its sublcass HTMLImportsController. | 172 // An abstract class to decouple its sublcass HTMLImportsController. |
| 197 class HTMLImportRoot : public HTMLImport { | 173 class HTMLImportRoot : public HTMLImport { |
| 198 public: | 174 public: |
| 199 HTMLImportRoot() : HTMLImport(Ready) { } | 175 HTMLImportRoot() { } |
| 200 | 176 |
| 201 virtual void blockerGone() = 0; | 177 virtual void scheduleRecalcState() = 0; |
|
dglazkov
2014/01/22 17:45:56
You have a dichotomy here between "recalculate" an
| |
| 202 virtual HTMLImportsController* toController() = 0; | 178 virtual HTMLImportsController* toController() = 0; |
| 203 virtual HTMLImportChild* findLinkFor(const KURL&, HTMLImport* excluding = 0) const = 0; | 179 virtual HTMLImportChild* findLinkFor(const KURL&, HTMLImport* excluding = 0) const = 0; |
| 204 }; | 180 }; |
| 205 | 181 |
| 206 } // namespace WebCore | 182 } // namespace WebCore |
| 207 | 183 |
| 208 #endif // HTMLImport_h | 184 #endif // HTMLImport_h |
| OLD | NEW |