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

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

Powered by Google App Engine
This is Rietveld 408576698