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

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

Issue 2555653002: [WIP Prototype] ES6 https://html.spec.whatwg.org/#fetch-a-single-module-script implementation (Closed)
Patch Set: rebased 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" 14 #include "platform/loader/fetch/MemoryCache.h"
38 #include "platform/wtf/CurrentTime.h"
39 15
40 namespace blink { 16 namespace blink {
41 17
42 PendingScript* PendingScript::Create(ScriptElementBase* element, 18 ClassicPendingScript* ClassicPendingScript::Create(ScriptElementBase* element,
43 ScriptResource* resource) { 19 ScriptResource* resource) {
44 return new PendingScript(element, resource, TextPosition()); 20 return new ClassicPendingScript(element, resource, TextPosition());
45 } 21 }
46 22
47 PendingScript* PendingScript::Create(ScriptElementBase* element, 23 ClassicPendingScript* ClassicPendingScript::Create(
48 const TextPosition& starting_position) { 24 ScriptElementBase* element,
49 return new PendingScript(element, nullptr, starting_position); 25 const TextPosition& starting_position) {
26 return new ClassicPendingScript(element, nullptr, starting_position);
50 } 27 }
51 28
52 PendingScript* PendingScript::CreateForTesting(ScriptResource* resource) { 29 ClassicPendingScript* ClassicPendingScript::CreateForTesting(
53 return new PendingScript(nullptr, resource, TextPosition(), true); 30 ScriptResource* resource) {
31 return new ClassicPendingScript(nullptr, resource, TextPosition(), true);
54 } 32 }
55 33
56 PendingScript::PendingScript(ScriptElementBase* element, 34 ClassicPendingScript::ClassicPendingScript(
57 ScriptResource* resource, 35 ScriptElementBase* element,
58 const TextPosition& starting_position, 36 ScriptResource* resource,
59 bool is_for_testing) 37 const TextPosition& starting_position,
60 : watching_for_load_(false), 38 bool is_for_testing)
61 element_(element), 39 : PendingScript(element, starting_position),
62 starting_position_(starting_position),
63 integrity_failure_(false), 40 integrity_failure_(false),
64 parser_blocking_load_start_time_(0),
65 client_(nullptr),
66 is_for_testing_(is_for_testing) { 41 is_for_testing_(is_for_testing) {
67 CheckState(); 42 CheckState();
68 SetResource(resource); 43 SetResource(resource);
69 MemoryCoordinator::Instance().RegisterClient(this); 44 MemoryCoordinator::Instance().RegisterClient(this);
70 } 45 }
71 46
72 PendingScript::~PendingScript() {} 47 ClassicPendingScript::~ClassicPendingScript() {}
73 48
74 NOINLINE void PendingScript::CheckState() const { 49 NOINLINE void ClassicPendingScript::CheckState() const {
75 // TODO(hiroshige): Turn these CHECK()s into DCHECK() before going to beta. 50 // TODO(hiroshige): Turn these CHECK()s into DCHECK() before going to beta.
76 CHECK(is_for_testing_ || element_); 51 CHECK(is_for_testing_ || GetElement());
77 CHECK(GetResource() || !streamer_); 52 CHECK(GetResource() || !streamer_);
78 CHECK(!streamer_ || streamer_->GetResource() == GetResource()); 53 CHECK(!streamer_ || streamer_->GetResource() == GetResource());
79 } 54 }
80 55
81 void PendingScript::Dispose() { 56 void ClassicPendingScript::DisposeInternal() {
82 StopWatchingForLoad();
83 DCHECK(!client_);
84 DCHECK(!watching_for_load_);
85
86 MemoryCoordinator::Instance().UnregisterClient(this); 57 MemoryCoordinator::Instance().UnregisterClient(this);
87 SetResource(nullptr); 58 SetResource(nullptr);
88 starting_position_ = TextPosition::BelowRangePosition();
89 integrity_failure_ = false; 59 integrity_failure_ = false;
90 parser_blocking_load_start_time_ = 0;
91 if (streamer_) 60 if (streamer_)
92 streamer_->Cancel(); 61 streamer_->Cancel();
93 streamer_ = nullptr; 62 streamer_ = nullptr;
94 element_ = nullptr;
95 } 63 }
96 64
97 void PendingScript::WatchForLoad(PendingScriptClient* client) { 65 void ClassicPendingScript::StreamingFinished() {
98 CheckState();
99
100 DCHECK(!watching_for_load_);
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 watching_for_load_ = true;
107 client_ = client;
108 if (IsReady())
109 client_->PendingScriptFinished(this);
110 }
111
112 void PendingScript::StopWatchingForLoad() {
113 if (!watching_for_load_)
114 return;
115 CheckState(); 66 CheckState();
116 DCHECK(GetResource()); 67 DCHECK(GetResource());
117 client_ = nullptr; 68 if (Client())
118 watching_for_load_ = false; 69 Client()->PendingScriptFinished(this);
119 }
120
121 ScriptElementBase* PendingScript::GetElement() 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(element_);
126 return element_.Get();
127 }
128
129 void PendingScript::StreamingFinished() {
130 CheckState();
131 DCHECK(GetResource());
132 if (client_)
133 client_->PendingScriptFinished(this);
134 }
135
136 void PendingScript::MarkParserBlockingLoadStartTime() {
137 DCHECK_EQ(parser_blocking_load_start_time_, 0.0);
138 parser_blocking_load_start_time_ = MonotonicallyIncreasingTime();
139 } 70 }
140 71
141 // Returns true if SRI check passed. 72 // Returns true if SRI check passed.
142 static bool CheckScriptResourceIntegrity(Resource* resource, 73 static bool CheckScriptResourceIntegrity(Resource* resource,
143 ScriptElementBase* element) { 74 ScriptElementBase* element) {
144 DCHECK_EQ(resource->GetType(), Resource::kScript); 75 DCHECK_EQ(resource->GetType(), Resource::kScript);
145 ScriptResource* script_resource = ToScriptResource(resource); 76 ScriptResource* script_resource = ToScriptResource(resource);
146 String integrity_attr = element->IntegrityAttributeValue(); 77 String integrity_attr = element->IntegrityAttributeValue();
147 78
148 // It is possible to get back a script resource with integrity metadata 79 // It is possible to get back a script resource with integrity metadata
(...skipping 27 matching lines...) Expand all
176 passed ? ResourceIntegrityDisposition::kPassed 107 passed ? ResourceIntegrityDisposition::kPassed
177 : ResourceIntegrityDisposition::kFailed); 108 : ResourceIntegrityDisposition::kFailed);
178 return passed; 109 return passed;
179 } 110 }
180 } 111 }
181 112
182 NOTREACHED(); 113 NOTREACHED();
183 return true; 114 return true;
184 } 115 }
185 116
186 void PendingScript::NotifyFinished(Resource* resource) { 117 void ClassicPendingScript::NotifyFinished(Resource* resource) {
187 // The following SRI checks need to be here because, unfortunately, fetches 118 // The following SRI checks need to be here because, unfortunately, fetches
188 // are not done purely according to the Fetch spec. In particular, 119 // are not done purely according to the Fetch spec. In particular,
189 // different requests for the same resource do not have different 120 // different requests for the same resource do not have different
190 // responses; the memory cache can (and will) return the exact same 121 // responses; the memory cache can (and will) return the exact same
191 // Resource object. 122 // Resource object.
192 // 123 //
193 // For different requests, the same Resource object will be returned and 124 // For different requests, the same Resource object will be returned and
194 // will not be associated with the particular request. Therefore, when the 125 // will not be associated with the particular request. Therefore, when the
195 // body of the response comes in, there's no way to validate the integrity 126 // body of the response comes in, there's no way to validate the integrity
196 // of the Resource object against a particular request (since there may be 127 // of the Resource object against a particular request (since there may be
197 // several pending requests all tied to the identical object, and the 128 // several pending requests all tied to the identical object, and the
198 // actual requests are not stored). 129 // actual requests are not stored).
199 // 130 //
200 // In order to simulate the correct behavior, Blink explicitly does the SRI 131 // In order to simulate the correct behavior, Blink explicitly does the SRI
201 // checks here, when a PendingScript tied to a particular request is 132 // checks here, when a PendingScript tied to a particular request is
202 // finished (and in the case of a StyleSheet, at the point of execution), 133 // finished (and in the case of a StyleSheet, at the point of execution),
203 // while having proper Fetch checks in the fetch module for use in the 134 // while having proper Fetch checks in the fetch module for use in the
204 // fetch JavaScript API. In a future world where the ResourceFetcher uses 135 // fetch JavaScript API. In a future world where the ResourceFetcher uses
205 // the Fetch algorithm, this should be fixed by having separate Response 136 // the Fetch algorithm, this should be fixed by having separate Response
206 // objects (perhaps attached to identical Resource objects) per request. 137 // objects (perhaps attached to identical Resource objects) per request.
207 // 138 //
208 // See https://crbug.com/500701 for more information. 139 // See https://crbug.com/500701 for more information.
209 CheckState(); 140 CheckState();
210 if (element_) { 141 if (!is_for_testing_ && GetElement()) {
211 integrity_failure_ = !CheckScriptResourceIntegrity(resource, element_); 142 integrity_failure_ = !CheckScriptResourceIntegrity(resource, GetElement());
212 } 143 }
213 144
214 // If script streaming is in use, the client will be notified in 145 // If script streaming is in use, the client will be notified in
215 // streamingFinished. 146 // streamingFinished.
216 if (streamer_) 147 if (streamer_)
217 streamer_->NotifyFinished(resource); 148 streamer_->NotifyFinished(resource);
218 else if (client_) 149 else if (Client())
219 client_->PendingScriptFinished(this); 150 Client()->PendingScriptFinished(this);
220 } 151 }
221 152
222 void PendingScript::NotifyAppendData(ScriptResource* resource) { 153 void ClassicPendingScript::NotifyAppendData(ScriptResource* resource) {
223 if (streamer_) 154 if (streamer_)
224 streamer_->NotifyAppendData(resource); 155 streamer_->NotifyAppendData(resource);
225 } 156 }
226 157
227 DEFINE_TRACE(PendingScript) { 158 DEFINE_TRACE(ClassicPendingScript) {
228 visitor->Trace(element_);
229 visitor->Trace(streamer_); 159 visitor->Trace(streamer_);
230 visitor->Trace(client_);
231 ResourceOwner<ScriptResource>::Trace(visitor); 160 ResourceOwner<ScriptResource>::Trace(visitor);
232 MemoryCoordinatorClient::Trace(visitor); 161 MemoryCoordinatorClient::Trace(visitor);
162 PendingScript::Trace(visitor);
233 } 163 }
234 164
235 ClassicScript* PendingScript::GetSource(const KURL& document_url, 165 ClassicScript* ClassicPendingScript::GetSource(const KURL& document_url,
236 bool& error_occurred) const { 166 bool& error_occurred) const {
237 CheckState(); 167 CheckState();
238 168
239 error_occurred = this->ErrorOccurred(); 169 error_occurred = this->ErrorOccurred();
240 if (GetResource()) { 170 if (GetResource()) {
241 DCHECK(GetResource()->IsLoaded()); 171 DCHECK(GetResource()->IsLoaded());
242 if (streamer_ && !streamer_->StreamingSuppressed()) 172 if (streamer_ && !streamer_->StreamingSuppressed())
243 return ClassicScript::Create(ScriptSourceCode(streamer_, GetResource())); 173 return ClassicScript::Create(ScriptSourceCode(streamer_, GetResource()));
244 return ClassicScript::Create(ScriptSourceCode(GetResource())); 174 return ClassicScript::Create(ScriptSourceCode(GetResource()));
245 } 175 }
246 176
247 return ClassicScript::Create(ScriptSourceCode( 177 return ClassicScript::Create(ScriptSourceCode(
248 element_->TextContent(), document_url, StartingPosition())); 178 GetElement()->TextContent(), document_url, StartingPosition()));
249 } 179 }
250 180
251 void PendingScript::SetStreamer(ScriptStreamer* streamer) { 181 void ClassicPendingScript::SetStreamer(ScriptStreamer* streamer) {
252 DCHECK(!streamer_); 182 DCHECK(!streamer_);
253 DCHECK(!watching_for_load_); 183 DCHECK(!IsWatchingForLoad());
254 streamer_ = streamer; 184 streamer_ = streamer;
255 CheckState(); 185 CheckState();
256 } 186 }
257 187
258 bool PendingScript::IsReady() const { 188 bool ClassicPendingScript::IsReady() const {
259 CheckState(); 189 CheckState();
260 if (GetResource()) { 190 if (GetResource()) {
261 return GetResource()->IsLoaded() && (!streamer_ || streamer_->IsFinished()); 191 return GetResource()->IsLoaded() && (!streamer_ || streamer_->IsFinished());
262 } 192 }
263 193
264 return true; 194 return true;
265 } 195 }
266 196
267 bool PendingScript::ErrorOccurred() const { 197 bool ClassicPendingScript::ErrorOccurred() const {
268 CheckState(); 198 CheckState();
269 if (GetResource()) 199 if (GetResource())
270 return GetResource()->ErrorOccurred() || integrity_failure_; 200 return GetResource()->ErrorOccurred() || integrity_failure_;
271 201
272 return false; 202 return false;
273 } 203 }
274 204
275 void PendingScript::OnPurgeMemory() { 205 void ClassicPendingScript::OnPurgeMemory() {
276 CheckState(); 206 CheckState();
277 if (!streamer_) 207 if (!streamer_)
278 return; 208 return;
279 streamer_->Cancel(); 209 streamer_->Cancel();
280 streamer_ = nullptr; 210 streamer_ = nullptr;
281 } 211 }
282 212
283 void PendingScript::StartStreamingIfPossible( 213 void ClassicPendingScript::StartStreamingIfPossible(
284 Document* document, 214 Document* document,
285 ScriptStreamer::Type streamer_type) { 215 ScriptStreamer::Type streamer_type) {
286 if (!document->GetFrame()) 216 if (!document->GetFrame())
287 return; 217 return;
288 218
289 ScriptState* script_state = ToScriptStateForMainWorld(document->GetFrame()); 219 ScriptState* script_state = ToScriptStateForMainWorld(document->GetFrame());
290 if (!script_state) 220 if (!script_state)
291 return; 221 return;
292 222
293 ScriptStreamer::StartStreaming( 223 ScriptStreamer::StartStreaming(
294 this, streamer_type, document->GetFrame()->GetSettings(), script_state, 224 this, streamer_type, document->GetFrame()->GetSettings(), script_state,
295 TaskRunnerHelper::Get(TaskType::kNetworking, document)); 225 TaskRunnerHelper::Get(TaskType::kNetworking, document));
296 } 226 }
297 227
228 bool ClassicPendingScript::WasCanceled() const {
229 return GetResource()->WasCanceled();
230 }
231
232 KURL ClassicPendingScript::UrlForClassicScript() const {
233 return GetResource()->Url();
234 }
235
236 void ClassicPendingScript::RemoveFromMemoryCache() {
237 GetMemoryCache()->Remove(GetResource());
238 }
239
298 } // namespace blink 240 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/dom/ClassicPendingScript.h ('k') | third_party/WebKit/Source/core/dom/Modulator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698