Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: third_party/WebKit/Source/core/dom/ClassicPendingScript.cpp

Issue 2653923008: Reland of Split PendingScript into PendingScript and ClassicPendingScript (Closed)
Patch Set: Fix file header Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. 2 // Use of this source code is governed by a BSD-style license that can be
3 * 3 // found in the LICENSE file.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
24 */
25 4
26 #include "core/dom/PendingScript.h" 5 #include "core/dom/ClassicPendingScript.h"
27 6
28 #include "bindings/core/v8/ScriptSourceCode.h" 7 #include "bindings/core/v8/ScriptSourceCode.h"
29 #include "bindings/core/v8/ScriptState.h" 8 #include "bindings/core/v8/ScriptState.h"
30 #include "bindings/core/v8/V8Binding.h" 9 #include "bindings/core/v8/V8Binding.h"
31 #include "core/dom/ClassicScript.h"
32 #include "core/dom/Document.h" 10 #include "core/dom/Document.h"
33 #include "core/dom/ScriptElementBase.h"
34 #include "core/dom/TaskRunnerHelper.h" 11 #include "core/dom/TaskRunnerHelper.h"
35 #include "core/frame/LocalFrame.h" 12 #include "core/frame/LocalFrame.h"
36 #include "core/frame/SubresourceIntegrity.h" 13 #include "core/frame/SubresourceIntegrity.h"
37 #include "platform/SharedBuffer.h"
38 #include "wtf/CurrentTime.h"
39 14
40 namespace blink { 15 namespace blink {
41 16
42 PendingScript* PendingScript::create(ScriptElementBase* element, 17 ClassicPendingScript* ClassicPendingScript::create(ScriptElementBase* element,
43 ScriptResource* resource) { 18 ScriptResource* resource) {
44 return new PendingScript(element, resource, TextPosition()); 19 return new ClassicPendingScript(element, resource, TextPosition());
45 } 20 }
46 21
47 PendingScript* PendingScript::create(ScriptElementBase* element, 22 ClassicPendingScript* ClassicPendingScript::create(
48 const TextPosition& startingPosition) { 23 ScriptElementBase* element,
49 return new PendingScript(element, nullptr, startingPosition); 24 const TextPosition& startingPosition) {
25 return new ClassicPendingScript(element, nullptr, startingPosition);
50 } 26 }
51 27
52 PendingScript* PendingScript::createForTesting(ScriptResource* resource) { 28 ClassicPendingScript* ClassicPendingScript::createForTesting(
53 return new PendingScript(nullptr, resource, TextPosition(), true); 29 ScriptResource* resource) {
30 return new ClassicPendingScript(nullptr, resource, TextPosition(), true);
54 } 31 }
55 32
56 PendingScript::PendingScript(ScriptElementBase* element, 33 ClassicPendingScript::ClassicPendingScript(ScriptElementBase* element,
57 ScriptResource* resource, 34 ScriptResource* resource,
58 const TextPosition& startingPosition, 35 const TextPosition& startingPosition,
59 bool isForTesting) 36 bool isForTesting)
60 : m_watchingForLoad(false), 37 : PendingScript(element, startingPosition),
61 m_element(element),
62 m_startingPosition(startingPosition),
63 m_integrityFailure(false), 38 m_integrityFailure(false),
64 m_parserBlockingLoadStartTime(0),
65 m_client(nullptr),
66 m_isForTesting(isForTesting) { 39 m_isForTesting(isForTesting) {
67 checkState(); 40 checkState();
68 setResource(resource); 41 setResource(resource);
69 MemoryCoordinator::instance().registerClient(this); 42 MemoryCoordinator::instance().registerClient(this);
70 } 43 }
71 44
72 PendingScript::~PendingScript() {} 45 ClassicPendingScript::~ClassicPendingScript() {}
73 46
74 NOINLINE void PendingScript::checkState() const { 47 NOINLINE void ClassicPendingScript::checkState() const {
75 // TODO(hiroshige): Turn these CHECK()s into DCHECK() before going to beta. 48 // TODO(hiroshige): Turn these CHECK()s into DCHECK() before going to beta.
76 CHECK(m_isForTesting || m_element); 49 CHECK(m_isForTesting || element());
77 CHECK(resource() || !m_streamer); 50 CHECK(resource() || !m_streamer);
78 CHECK(!m_streamer || m_streamer->resource() == resource()); 51 CHECK(!m_streamer || m_streamer->resource() == resource());
79 } 52 }
80 53
81 void PendingScript::dispose() { 54 void ClassicPendingScript::disposeInternal() {
82 stopWatchingForLoad();
83 DCHECK(!m_client);
84 DCHECK(!m_watchingForLoad);
85
86 MemoryCoordinator::instance().unregisterClient(this); 55 MemoryCoordinator::instance().unregisterClient(this);
87 setResource(nullptr); 56 setResource(nullptr);
88 m_startingPosition = TextPosition::belowRangePosition();
89 m_integrityFailure = false; 57 m_integrityFailure = false;
90 m_parserBlockingLoadStartTime = 0;
91 if (m_streamer) 58 if (m_streamer)
92 m_streamer->cancel(); 59 m_streamer->cancel();
93 m_streamer = nullptr; 60 m_streamer = nullptr;
94 m_element = nullptr;
95 } 61 }
96 62
97 void PendingScript::watchForLoad(PendingScriptClient* client) { 63 void ClassicPendingScript::streamingFinished() {
98 checkState();
99
100 DCHECK(!m_watchingForLoad);
101 // addClient() will call streamingFinished() if the load is complete. Callers
102 // who do not expect to be re-entered from this call should not call
103 // watchForLoad for a PendingScript which isReady. We also need to set
104 // m_watchingForLoad early, since addClient() can result in calling
105 // notifyFinished and further stopWatchingForLoad().
106 m_watchingForLoad = true;
107 m_client = client;
108 if (isReady())
109 m_client->pendingScriptFinished(this);
110 }
111
112 void PendingScript::stopWatchingForLoad() {
113 if (!m_watchingForLoad)
114 return;
115 checkState(); 64 checkState();
116 DCHECK(resource()); 65 DCHECK(resource());
117 m_client = nullptr; 66 if (client())
118 m_watchingForLoad = false; 67 client()->pendingScriptFinished(this);
119 }
120
121 ScriptElementBase* PendingScript::element() const {
122 // As mentioned in the comment at |m_element| declaration,
123 // |m_element| must point to the corresponding ScriptLoader's
124 // client.
125 CHECK(m_element);
126 return m_element.get();
127 }
128
129 void PendingScript::streamingFinished() {
130 checkState();
131 DCHECK(resource());
132 if (m_client)
133 m_client->pendingScriptFinished(this);
134 }
135
136 void PendingScript::markParserBlockingLoadStartTime() {
137 DCHECK_EQ(m_parserBlockingLoadStartTime, 0.0);
138 m_parserBlockingLoadStartTime = monotonicallyIncreasingTime();
139 } 68 }
140 69
141 // Returns true if SRI check passed. 70 // Returns true if SRI check passed.
142 static bool checkScriptResourceIntegrity(Resource* resource, 71 static bool checkScriptResourceIntegrity(Resource* resource,
143 ScriptElementBase* element) { 72 ScriptElementBase* element) {
144 DCHECK_EQ(resource->getType(), Resource::Script); 73 DCHECK_EQ(resource->getType(), Resource::Script);
145 ScriptResource* scriptResource = toScriptResource(resource); 74 ScriptResource* scriptResource = toScriptResource(resource);
146 String integrityAttr = element->integrityAttributeValue(); 75 String integrityAttr = element->integrityAttributeValue();
147 76
148 // It is possible to get back a script resource with integrity metadata 77 // It is possible to get back a script resource with integrity metadata
(...skipping 26 matching lines...) Expand all
175 passed ? ResourceIntegrityDisposition::Passed 104 passed ? ResourceIntegrityDisposition::Passed
176 : ResourceIntegrityDisposition::Failed); 105 : ResourceIntegrityDisposition::Failed);
177 return passed; 106 return passed;
178 } 107 }
179 } 108 }
180 109
181 NOTREACHED(); 110 NOTREACHED();
182 return true; 111 return true;
183 } 112 }
184 113
185 void PendingScript::notifyFinished(Resource* resource) { 114 void ClassicPendingScript::notifyFinished(Resource* resource) {
186 // The following SRI checks need to be here because, unfortunately, fetches 115 // The following SRI checks need to be here because, unfortunately, fetches
187 // are not done purely according to the Fetch spec. In particular, 116 // are not done purely according to the Fetch spec. In particular,
188 // different requests for the same resource do not have different 117 // different requests for the same resource do not have different
189 // responses; the memory cache can (and will) return the exact same 118 // responses; the memory cache can (and will) return the exact same
190 // Resource object. 119 // Resource object.
191 // 120 //
192 // For different requests, the same Resource object will be returned and 121 // For different requests, the same Resource object will be returned and
193 // will not be associated with the particular request. Therefore, when the 122 // will not be associated with the particular request. Therefore, when the
194 // body of the response comes in, there's no way to validate the integrity 123 // body of the response comes in, there's no way to validate the integrity
195 // of the Resource object against a particular request (since there may be 124 // of the Resource object against a particular request (since there may be
196 // several pending requests all tied to the identical object, and the 125 // several pending requests all tied to the identical object, and the
197 // actual requests are not stored). 126 // actual requests are not stored).
198 // 127 //
199 // In order to simulate the correct behavior, Blink explicitly does the SRI 128 // In order to simulate the correct behavior, Blink explicitly does the SRI
200 // checks here, when a PendingScript tied to a particular request is 129 // checks here, when a PendingScript tied to a particular request is
201 // finished (and in the case of a StyleSheet, at the point of execution), 130 // finished (and in the case of a StyleSheet, at the point of execution),
202 // while having proper Fetch checks in the fetch module for use in the 131 // while having proper Fetch checks in the fetch module for use in the
203 // fetch JavaScript API. In a future world where the ResourceFetcher uses 132 // fetch JavaScript API. In a future world where the ResourceFetcher uses
204 // the Fetch algorithm, this should be fixed by having separate Response 133 // the Fetch algorithm, this should be fixed by having separate Response
205 // objects (perhaps attached to identical Resource objects) per request. 134 // objects (perhaps attached to identical Resource objects) per request.
206 // 135 //
207 // See https://crbug.com/500701 for more information. 136 // See https://crbug.com/500701 for more information.
208 checkState(); 137 checkState();
209 if (m_element) { 138 if (!m_isForTesting && element()) {
210 m_integrityFailure = !checkScriptResourceIntegrity(resource, m_element); 139 m_integrityFailure = !checkScriptResourceIntegrity(resource, element());
211 } 140 }
212 141
213 // If script streaming is in use, the client will be notified in 142 // If script streaming is in use, the client will be notified in
214 // streamingFinished. 143 // streamingFinished.
215 if (m_streamer) 144 if (m_streamer)
216 m_streamer->notifyFinished(resource); 145 m_streamer->notifyFinished(resource);
217 else if (m_client) 146 else if (client())
218 m_client->pendingScriptFinished(this); 147 client()->pendingScriptFinished(this);
219 } 148 }
220 149
221 void PendingScript::notifyAppendData(ScriptResource* resource) { 150 void ClassicPendingScript::notifyAppendData(ScriptResource* resource) {
222 if (m_streamer) 151 if (m_streamer)
223 m_streamer->notifyAppendData(resource); 152 m_streamer->notifyAppendData(resource);
224 } 153 }
225 154
226 DEFINE_TRACE(PendingScript) { 155 DEFINE_TRACE(ClassicPendingScript) {
227 visitor->trace(m_element);
228 visitor->trace(m_streamer); 156 visitor->trace(m_streamer);
229 visitor->trace(m_client);
230 ResourceOwner<ScriptResource>::trace(visitor); 157 ResourceOwner<ScriptResource>::trace(visitor);
231 MemoryCoordinatorClient::trace(visitor); 158 MemoryCoordinatorClient::trace(visitor);
159 PendingScript::trace(visitor);
232 } 160 }
233 161
234 ClassicScript* PendingScript::getSource(const KURL& documentURL, 162 ClassicScript* ClassicPendingScript::getSource(const KURL& documentURL,
235 bool& errorOccurred) const { 163 bool& errorOccurred) const {
236 checkState(); 164 checkState();
237 165
238 errorOccurred = this->errorOccurred(); 166 errorOccurred = this->errorOccurred();
239 if (resource()) { 167 if (resource()) {
240 DCHECK(resource()->isLoaded()); 168 DCHECK(resource()->isLoaded());
241 if (m_streamer && !m_streamer->streamingSuppressed()) 169 if (m_streamer && !m_streamer->streamingSuppressed())
242 return ClassicScript::create(ScriptSourceCode(m_streamer, resource())); 170 return ClassicScript::create(ScriptSourceCode(m_streamer, resource()));
243 return ClassicScript::create(ScriptSourceCode(resource())); 171 return ClassicScript::create(ScriptSourceCode(resource()));
244 } 172 }
245 173
246 return ClassicScript::create(ScriptSourceCode( 174 return ClassicScript::create(ScriptSourceCode(
247 m_element->textContent(), documentURL, startingPosition())); 175 element()->textContent(), documentURL, startingPosition()));
248 } 176 }
249 177
250 void PendingScript::setStreamer(ScriptStreamer* streamer) { 178 void ClassicPendingScript::setStreamer(ScriptStreamer* streamer) {
251 DCHECK(!m_streamer); 179 DCHECK(!m_streamer);
252 DCHECK(!m_watchingForLoad); 180 DCHECK(!isWatchingForLoad());
253 m_streamer = streamer; 181 m_streamer = streamer;
254 checkState(); 182 checkState();
255 } 183 }
256 184
257 bool PendingScript::isReady() const { 185 bool ClassicPendingScript::isReady() const {
258 checkState(); 186 checkState();
259 if (resource()) { 187 if (resource()) {
260 return resource()->isLoaded() && (!m_streamer || m_streamer->isFinished()); 188 return resource()->isLoaded() && (!m_streamer || m_streamer->isFinished());
261 } 189 }
262 190
263 return true; 191 return true;
264 } 192 }
265 193
266 bool PendingScript::errorOccurred() const { 194 bool ClassicPendingScript::errorOccurred() const {
267 checkState(); 195 checkState();
268 if (resource()) 196 if (resource())
269 return resource()->errorOccurred() || m_integrityFailure; 197 return resource()->errorOccurred() || m_integrityFailure;
270 198
271 return false; 199 return false;
272 } 200 }
273 201
274 void PendingScript::onPurgeMemory() { 202 void ClassicPendingScript::onPurgeMemory() {
275 checkState(); 203 checkState();
276 if (!m_streamer) 204 if (!m_streamer)
277 return; 205 return;
278 m_streamer->cancel(); 206 m_streamer->cancel();
279 m_streamer = nullptr; 207 m_streamer = nullptr;
280 } 208 }
281 209
282 void PendingScript::startStreamingIfPossible( 210 void ClassicPendingScript::startStreamingIfPossible(
283 Document* document, 211 Document* document,
284 ScriptStreamer::Type streamerType) { 212 ScriptStreamer::Type streamerType) {
285 if (!document->frame()) 213 if (!document->frame())
286 return; 214 return;
287 215
288 ScriptState* scriptState = toScriptStateForMainWorld(document->frame()); 216 ScriptState* scriptState = toScriptStateForMainWorld(document->frame());
289 if (!scriptState) 217 if (!scriptState)
290 return; 218 return;
291 219
292 ScriptStreamer::startStreaming( 220 ScriptStreamer::startStreaming(
293 this, streamerType, document->frame()->settings(), scriptState, 221 this, streamerType, document->frame()->settings(), scriptState,
294 TaskRunnerHelper::get(TaskType::Networking, document)); 222 TaskRunnerHelper::get(TaskType::Networking, document));
295 } 223 }
296 224
225 bool ClassicPendingScript::wasCanceled() const {
226 return resource()->wasCanceled();
227 }
228
229 KURL ClassicPendingScript::url() const {
230 return resource()->url();
231 }
232
297 } // namespace blink 233 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698