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

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

Issue 2820753002: Revert of Split PendingScript into PendingScript and ClassicPendingScript (Closed)
Patch Set: 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
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "core/dom/ClassicPendingScript.h"
6
7 #include "bindings/core/v8/ScriptSourceCode.h"
8 #include "bindings/core/v8/ScriptState.h"
9 #include "bindings/core/v8/V8Binding.h"
10 #include "core/dom/Document.h"
11 #include "core/dom/TaskRunnerHelper.h"
12 #include "core/frame/LocalFrame.h"
13 #include "core/frame/SubresourceIntegrity.h"
14 #include "platform/loader/fetch/MemoryCache.h"
15
16 namespace blink {
17
18 ClassicPendingScript* ClassicPendingScript::Create(ScriptElementBase* element,
19 ScriptResource* resource) {
20 return new ClassicPendingScript(element, resource, TextPosition());
21 }
22
23 ClassicPendingScript* ClassicPendingScript::Create(
24 ScriptElementBase* element,
25 const TextPosition& starting_position) {
26 return new ClassicPendingScript(element, nullptr, starting_position);
27 }
28
29 ClassicPendingScript* ClassicPendingScript::CreateForTesting(
30 ScriptResource* resource) {
31 return new ClassicPendingScript(nullptr, resource, TextPosition(), true);
32 }
33
34 ClassicPendingScript::ClassicPendingScript(
35 ScriptElementBase* element,
36 ScriptResource* resource,
37 const TextPosition& starting_position,
38 bool is_for_testing)
39 : PendingScript(element, starting_position),
40 integrity_failure_(false),
41 is_for_testing_(is_for_testing) {
42 CheckState();
43 SetResource(resource);
44 MemoryCoordinator::Instance().RegisterClient(this);
45 }
46
47 ClassicPendingScript::~ClassicPendingScript() {}
48
49 NOINLINE void ClassicPendingScript::CheckState() const {
50 // TODO(hiroshige): Turn these CHECK()s into DCHECK() before going to beta.
51 CHECK(is_for_testing_ || GetElement());
52 CHECK(GetResource() || !streamer_);
53 CHECK(!streamer_ || streamer_->GetResource() == GetResource());
54 }
55
56 void ClassicPendingScript::DisposeInternal() {
57 MemoryCoordinator::Instance().UnregisterClient(this);
58 SetResource(nullptr);
59 integrity_failure_ = false;
60 if (streamer_)
61 streamer_->Cancel();
62 streamer_ = nullptr;
63 }
64
65 void ClassicPendingScript::StreamingFinished() {
66 CheckState();
67 DCHECK(GetResource());
68 if (Client())
69 Client()->PendingScriptFinished(this);
70 }
71
72 // Returns true if SRI check passed.
73 static bool CheckScriptResourceIntegrity(Resource* resource,
74 ScriptElementBase* element) {
75 DCHECK_EQ(resource->GetType(), Resource::kScript);
76 ScriptResource* script_resource = ToScriptResource(resource);
77 String integrity_attr = element->IntegrityAttributeValue();
78
79 // It is possible to get back a script resource with integrity metadata
80 // for a request with an empty integrity attribute. In that case, the
81 // integrity check should be skipped, so this check ensures that the
82 // integrity attribute isn't empty in addition to checking if the
83 // resource has empty integrity metadata.
84 if (integrity_attr.IsEmpty() ||
85 script_resource->IntegrityMetadata().IsEmpty())
86 return true;
87
88 switch (script_resource->IntegrityDisposition()) {
89 case ResourceIntegrityDisposition::kPassed:
90 return true;
91
92 case ResourceIntegrityDisposition::kFailed:
93 // TODO(jww): This should probably also generate a console
94 // message identical to the one produced by
95 // CheckSubresourceIntegrity below. See https://crbug.com/585267.
96 return false;
97
98 case ResourceIntegrityDisposition::kNotChecked: {
99 if (!resource->ResourceBuffer())
100 return true;
101
102 bool passed = SubresourceIntegrity::CheckSubresourceIntegrity(
103 script_resource->IntegrityMetadata(), element->GetDocument(),
104 resource->ResourceBuffer()->Data(),
105 resource->ResourceBuffer()->size(), resource->Url(), *resource);
106 script_resource->SetIntegrityDisposition(
107 passed ? ResourceIntegrityDisposition::kPassed
108 : ResourceIntegrityDisposition::kFailed);
109 return passed;
110 }
111 }
112
113 NOTREACHED();
114 return true;
115 }
116
117 void ClassicPendingScript::NotifyFinished(Resource* resource) {
118 // The following SRI checks need to be here because, unfortunately, fetches
119 // are not done purely according to the Fetch spec. In particular,
120 // different requests for the same resource do not have different
121 // responses; the memory cache can (and will) return the exact same
122 // Resource object.
123 //
124 // For different requests, the same Resource object will be returned and
125 // will not be associated with the particular request. Therefore, when the
126 // body of the response comes in, there's no way to validate the integrity
127 // of the Resource object against a particular request (since there may be
128 // several pending requests all tied to the identical object, and the
129 // actual requests are not stored).
130 //
131 // In order to simulate the correct behavior, Blink explicitly does the SRI
132 // checks here, when a PendingScript tied to a particular request is
133 // finished (and in the case of a StyleSheet, at the point of execution),
134 // while having proper Fetch checks in the fetch module for use in the
135 // fetch JavaScript API. In a future world where the ResourceFetcher uses
136 // the Fetch algorithm, this should be fixed by having separate Response
137 // objects (perhaps attached to identical Resource objects) per request.
138 //
139 // See https://crbug.com/500701 for more information.
140 CheckState();
141 if (!is_for_testing_ && GetElement()) {
142 integrity_failure_ = !CheckScriptResourceIntegrity(resource, GetElement());
143 }
144
145 // If script streaming is in use, the client will be notified in
146 // streamingFinished.
147 if (streamer_)
148 streamer_->NotifyFinished(resource);
149 else if (Client())
150 Client()->PendingScriptFinished(this);
151 }
152
153 void ClassicPendingScript::NotifyAppendData(ScriptResource* resource) {
154 if (streamer_)
155 streamer_->NotifyAppendData(resource);
156 }
157
158 DEFINE_TRACE(ClassicPendingScript) {
159 visitor->Trace(streamer_);
160 ResourceOwner<ScriptResource>::Trace(visitor);
161 MemoryCoordinatorClient::Trace(visitor);
162 PendingScript::Trace(visitor);
163 }
164
165 ClassicScript* ClassicPendingScript::GetSource(const KURL& document_url,
166 bool& error_occurred) const {
167 CheckState();
168
169 error_occurred = this->ErrorOccurred();
170 if (GetResource()) {
171 DCHECK(GetResource()->IsLoaded());
172 if (streamer_ && !streamer_->StreamingSuppressed())
173 return ClassicScript::Create(ScriptSourceCode(streamer_, GetResource()));
174 return ClassicScript::Create(ScriptSourceCode(GetResource()));
175 }
176
177 return ClassicScript::Create(ScriptSourceCode(
178 GetElement()->TextContent(), document_url, StartingPosition()));
179 }
180
181 void ClassicPendingScript::SetStreamer(ScriptStreamer* streamer) {
182 DCHECK(!streamer_);
183 DCHECK(!IsWatchingForLoad());
184 streamer_ = streamer;
185 CheckState();
186 }
187
188 bool ClassicPendingScript::IsReady() const {
189 CheckState();
190 if (GetResource()) {
191 return GetResource()->IsLoaded() && (!streamer_ || streamer_->IsFinished());
192 }
193
194 return true;
195 }
196
197 bool ClassicPendingScript::ErrorOccurred() const {
198 CheckState();
199 if (GetResource())
200 return GetResource()->ErrorOccurred() || integrity_failure_;
201
202 return false;
203 }
204
205 void ClassicPendingScript::OnPurgeMemory() {
206 CheckState();
207 if (!streamer_)
208 return;
209 streamer_->Cancel();
210 streamer_ = nullptr;
211 }
212
213 void ClassicPendingScript::StartStreamingIfPossible(
214 Document* document,
215 ScriptStreamer::Type streamer_type) {
216 if (!document->GetFrame())
217 return;
218
219 ScriptState* script_state = ToScriptStateForMainWorld(document->GetFrame());
220 if (!script_state)
221 return;
222
223 ScriptStreamer::StartStreaming(
224 this, streamer_type, document->GetFrame()->GetSettings(), script_state,
225 TaskRunnerHelper::Get(TaskType::kNetworking, document));
226 }
227
228 bool ClassicPendingScript::WasCanceled() const {
229 return GetResource()->WasCanceled();
230 }
231
232 KURL ClassicPendingScript::Url() const {
233 return GetResource()->Url();
234 }
235
236 void ClassicPendingScript::RemoveFromMemoryCache() {
237 GetMemoryCache()->Remove(GetResource());
238 }
239
240 } // 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