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

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

Powered by Google App Engine
This is Rietveld 408576698