| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. | 2 * Copyright (C) 2010 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 | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| 11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
| 12 * | 12 * |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #include "core/dom/PendingScript.h" | 26 #include "core/dom/PendingScript.h" |
| 27 | 27 |
| 28 #include "bindings/core/v8/ScriptSourceCode.h" | 28 #include "bindings/core/v8/ScriptSourceCode.h" |
| 29 #include "core/dom/Element.h" | 29 #include "core/dom/ScriptElementBase.h" |
| 30 #include "core/frame/SubresourceIntegrity.h" | 30 #include "core/frame/SubresourceIntegrity.h" |
| 31 #include "platform/SharedBuffer.h" | 31 #include "platform/SharedBuffer.h" |
| 32 #include "wtf/CurrentTime.h" | 32 #include "wtf/CurrentTime.h" |
| 33 | 33 |
| 34 namespace blink { | 34 namespace blink { |
| 35 | 35 |
| 36 PendingScript* PendingScript::create(Element* element, | 36 PendingScript* PendingScript::create(ScriptElementBase* element, |
| 37 ScriptResource* resource) { | 37 ScriptResource* resource) { |
| 38 return new PendingScript(element, resource, TextPosition()); | 38 return new PendingScript(element, resource, TextPosition()); |
| 39 } | 39 } |
| 40 | 40 |
| 41 PendingScript* PendingScript::create(Element* element, | 41 PendingScript* PendingScript::create(ScriptElementBase* element, |
| 42 const TextPosition& startingPosition) { | 42 const TextPosition& startingPosition) { |
| 43 return new PendingScript(element, nullptr, startingPosition); | 43 return new PendingScript(element, nullptr, startingPosition); |
| 44 } | 44 } |
| 45 | 45 |
| 46 PendingScript* PendingScript::createForTesting(ScriptResource* resource) { | 46 PendingScript* PendingScript::createForTesting(ScriptResource* resource) { |
| 47 return new PendingScript(nullptr, resource, TextPosition(), true); | 47 return new PendingScript(nullptr, resource, TextPosition(), true); |
| 48 } | 48 } |
| 49 | 49 |
| 50 PendingScript::PendingScript(Element* element, | 50 PendingScript::PendingScript(ScriptElementBase* element, |
| 51 ScriptResource* resource, | 51 ScriptResource* resource, |
| 52 const TextPosition& startingPosition, | 52 const TextPosition& startingPosition, |
| 53 bool isForTesting) | 53 bool isForTesting) |
| 54 : m_watchingForLoad(false), | 54 : m_watchingForLoad(false), |
| 55 m_element(element), | 55 m_element(element), |
| 56 m_startingPosition(startingPosition), | 56 m_startingPosition(startingPosition), |
| 57 m_integrityFailure(false), | 57 m_integrityFailure(false), |
| 58 m_parserBlockingLoadStartTime(0), | 58 m_parserBlockingLoadStartTime(0), |
| 59 m_client(nullptr), | 59 m_client(nullptr), |
| 60 m_isForTesting(isForTesting) { | 60 m_isForTesting(isForTesting) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 | 104 |
| 105 void PendingScript::stopWatchingForLoad() { | 105 void PendingScript::stopWatchingForLoad() { |
| 106 if (!m_watchingForLoad) | 106 if (!m_watchingForLoad) |
| 107 return; | 107 return; |
| 108 checkState(); | 108 checkState(); |
| 109 DCHECK(resource()); | 109 DCHECK(resource()); |
| 110 m_client = nullptr; | 110 m_client = nullptr; |
| 111 m_watchingForLoad = false; | 111 m_watchingForLoad = false; |
| 112 } | 112 } |
| 113 | 113 |
| 114 Element* PendingScript::element() const { | 114 ScriptElementBase* PendingScript::element() const { |
| 115 // As mentioned in the comment at |m_element| declaration, |m_element| | 115 // As mentioned in the comment at |m_element| declaration, |
| 116 // must points to the corresponding ScriptLoader's element. | 116 // |m_element| must point to the corresponding ScriptLoader's |
| 117 // client. |
| 117 CHECK(m_element); | 118 CHECK(m_element); |
| 118 return m_element.get(); | 119 return m_element.get(); |
| 119 } | 120 } |
| 120 | 121 |
| 121 void PendingScript::streamingFinished() { | 122 void PendingScript::streamingFinished() { |
| 122 checkState(); | 123 checkState(); |
| 123 DCHECK(resource()); | 124 DCHECK(resource()); |
| 124 if (m_client) | 125 if (m_client) |
| 125 m_client->pendingScriptFinished(this); | 126 m_client->pendingScriptFinished(this); |
| 126 } | 127 } |
| 127 | 128 |
| 128 void PendingScript::markParserBlockingLoadStartTime() { | 129 void PendingScript::markParserBlockingLoadStartTime() { |
| 129 DCHECK_EQ(m_parserBlockingLoadStartTime, 0.0); | 130 DCHECK_EQ(m_parserBlockingLoadStartTime, 0.0); |
| 130 m_parserBlockingLoadStartTime = monotonicallyIncreasingTime(); | 131 m_parserBlockingLoadStartTime = monotonicallyIncreasingTime(); |
| 131 } | 132 } |
| 132 | 133 |
| 133 // Returns true if SRI check passed. | 134 // Returns true if SRI check passed. |
| 134 static bool checkScriptResourceIntegrity(Resource* resource, Element* element) { | 135 static bool checkScriptResourceIntegrity(Resource* resource, |
| 136 ScriptElementBase* element) { |
| 135 DCHECK_EQ(resource->getType(), Resource::Script); | 137 DCHECK_EQ(resource->getType(), Resource::Script); |
| 136 ScriptResource* scriptResource = toScriptResource(resource); | 138 ScriptResource* scriptResource = toScriptResource(resource); |
| 137 String integrityAttr = element->fastGetAttribute(HTMLNames::integrityAttr); | 139 String integrityAttr = element->integrityAttributeValue(); |
| 138 | 140 |
| 139 // It is possible to get back a script resource with integrity metadata | 141 // It is possible to get back a script resource with integrity metadata |
| 140 // for a request with an empty integrity attribute. In that case, the | 142 // for a request with an empty integrity attribute. In that case, the |
| 141 // integrity check should be skipped, so this check ensures that the | 143 // integrity check should be skipped, so this check ensures that the |
| 142 // integrity attribute isn't empty in addition to checking if the | 144 // integrity attribute isn't empty in addition to checking if the |
| 143 // resource has empty integrity metadata. | 145 // resource has empty integrity metadata. |
| 144 if (integrityAttr.isEmpty() || scriptResource->integrityMetadata().isEmpty()) | 146 if (integrityAttr.isEmpty() || scriptResource->integrityMetadata().isEmpty()) |
| 145 return true; | 147 return true; |
| 146 | 148 |
| 147 switch (scriptResource->integrityDisposition()) { | 149 switch (scriptResource->integrityDisposition()) { |
| 148 case ResourceIntegrityDisposition::Passed: | 150 case ResourceIntegrityDisposition::Passed: |
| 149 return true; | 151 return true; |
| 150 | 152 |
| 151 case ResourceIntegrityDisposition::Failed: | 153 case ResourceIntegrityDisposition::Failed: |
| 152 // TODO(jww): This should probably also generate a console | 154 // TODO(jww): This should probably also generate a console |
| 153 // message identical to the one produced by | 155 // message identical to the one produced by |
| 154 // CheckSubresourceIntegrity below. See https://crbug.com/585267. | 156 // CheckSubresourceIntegrity below. See https://crbug.com/585267. |
| 155 return false; | 157 return false; |
| 156 | 158 |
| 157 case ResourceIntegrityDisposition::NotChecked: { | 159 case ResourceIntegrityDisposition::NotChecked: { |
| 158 if (!resource->resourceBuffer()) | 160 if (!resource->resourceBuffer()) |
| 159 return true; | 161 return true; |
| 160 | 162 |
| 161 bool passed = SubresourceIntegrity::CheckSubresourceIntegrity( | 163 bool passed = SubresourceIntegrity::CheckSubresourceIntegrity( |
| 162 scriptResource->integrityMetadata(), *element, | 164 scriptResource->integrityMetadata(), element->document(), |
| 163 resource->resourceBuffer()->data(), | 165 resource->resourceBuffer()->data(), |
| 164 resource->resourceBuffer()->size(), resource->url(), *resource); | 166 resource->resourceBuffer()->size(), resource->url(), *resource); |
| 165 scriptResource->setIntegrityDisposition( | 167 scriptResource->setIntegrityDisposition( |
| 166 passed ? ResourceIntegrityDisposition::Passed | 168 passed ? ResourceIntegrityDisposition::Passed |
| 167 : ResourceIntegrityDisposition::Failed); | 169 : ResourceIntegrityDisposition::Failed); |
| 168 return passed; | 170 return passed; |
| 169 } | 171 } |
| 170 } | 172 } |
| 171 | 173 |
| 172 NOTREACHED(); | 174 NOTREACHED(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 190 // In order to simulate the correct behavior, Blink explicitly does the SRI | 192 // In order to simulate the correct behavior, Blink explicitly does the SRI |
| 191 // checks here, when a PendingScript tied to a particular request is | 193 // checks here, when a PendingScript tied to a particular request is |
| 192 // finished (and in the case of a StyleSheet, at the point of execution), | 194 // finished (and in the case of a StyleSheet, at the point of execution), |
| 193 // while having proper Fetch checks in the fetch module for use in the | 195 // while having proper Fetch checks in the fetch module for use in the |
| 194 // fetch JavaScript API. In a future world where the ResourceFetcher uses | 196 // fetch JavaScript API. In a future world where the ResourceFetcher uses |
| 195 // the Fetch algorithm, this should be fixed by having separate Response | 197 // the Fetch algorithm, this should be fixed by having separate Response |
| 196 // objects (perhaps attached to identical Resource objects) per request. | 198 // objects (perhaps attached to identical Resource objects) per request. |
| 197 // | 199 // |
| 198 // See https://crbug.com/500701 for more information. | 200 // See https://crbug.com/500701 for more information. |
| 199 checkState(); | 201 checkState(); |
| 200 if (m_element) | 202 if (m_element) { |
| 201 m_integrityFailure = !checkScriptResourceIntegrity(resource, m_element); | 203 m_integrityFailure = !checkScriptResourceIntegrity(resource, m_element); |
| 204 } |
| 202 | 205 |
| 203 // If script streaming is in use, the client will be notified in | 206 // If script streaming is in use, the client will be notified in |
| 204 // streamingFinished. | 207 // streamingFinished. |
| 205 if (m_streamer) | 208 if (m_streamer) |
| 206 m_streamer->notifyFinished(resource); | 209 m_streamer->notifyFinished(resource); |
| 207 else if (m_client) | 210 else if (m_client) |
| 208 m_client->pendingScriptFinished(this); | 211 m_client->pendingScriptFinished(this); |
| 209 } | 212 } |
| 210 | 213 |
| 211 void PendingScript::notifyAppendData(ScriptResource* resource) { | 214 void PendingScript::notifyAppendData(ScriptResource* resource) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 | 266 |
| 264 void PendingScript::onPurgeMemory() { | 267 void PendingScript::onPurgeMemory() { |
| 265 checkState(); | 268 checkState(); |
| 266 if (!m_streamer) | 269 if (!m_streamer) |
| 267 return; | 270 return; |
| 268 m_streamer->cancel(); | 271 m_streamer->cancel(); |
| 269 m_streamer = nullptr; | 272 m_streamer = nullptr; |
| 270 } | 273 } |
| 271 | 274 |
| 272 } // namespace blink | 275 } // namespace blink |
| OLD | NEW |