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

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

Issue 2698613007: Refactor SRI check in PendingScript::notifyFinished() (Closed)
Patch Set: fix Created 3 years, 10 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 DCHECK(resource()); 112 DCHECK(resource());
113 if (m_client) 113 if (m_client)
114 m_client->pendingScriptFinished(this); 114 m_client->pendingScriptFinished(this);
115 } 115 }
116 116
117 void PendingScript::markParserBlockingLoadStartTime() { 117 void PendingScript::markParserBlockingLoadStartTime() {
118 DCHECK_EQ(m_parserBlockingLoadStartTime, 0.0); 118 DCHECK_EQ(m_parserBlockingLoadStartTime, 0.0);
119 m_parserBlockingLoadStartTime = monotonicallyIncreasingTime(); 119 m_parserBlockingLoadStartTime = monotonicallyIncreasingTime();
120 } 120 }
121 121
122 // Returns true if SRI check passed.
123 static bool checkScriptResourceIntegrity(Resource* resource, Element* element) {
124 DCHECK_EQ(resource->getType(), Resource::Script);
125 ScriptResource* scriptResource = toScriptResource(resource);
126 String integrityAttr = element->fastGetAttribute(HTMLNames::integrityAttr);
127
128 // It is possible to get back a script resource with integrity metadata
129 // for a request with an empty integrity attribute. In that case, the
130 // integrity check should be skipped, so this check ensures that the
131 // integrity attribute isn't empty in addition to checking if the
132 // resource has empty integrity metadata.
133 if (integrityAttr.isEmpty() || scriptResource->integrityMetadata().isEmpty())
134 return true;
135
136 switch (scriptResource->integrityDisposition()) {
137 case ResourceIntegrityDisposition::Passed:
138 return true;
139
140 case ResourceIntegrityDisposition::Failed:
141 // TODO(jww): This should probably also generate a console
142 // message identical to the one produced by
143 // CheckSubresourceIntegrity below. See https://crbug.com/585267.
144 return false;
145
146 case ResourceIntegrityDisposition::NotChecked: {
147 if (!resource->resourceBuffer())
148 return true;
149
150 bool passed = SubresourceIntegrity::CheckSubresourceIntegrity(
151 scriptResource->integrityMetadata(), *element,
152 resource->resourceBuffer()->data(),
153 resource->resourceBuffer()->size(), resource->url(), *resource);
154 scriptResource->setIntegrityDisposition(
155 passed ? ResourceIntegrityDisposition::Passed
156 : ResourceIntegrityDisposition::Failed);
157 return passed;
158 }
159 }
160
161 NOTREACHED();
162 return true;
163 }
164
122 void PendingScript::notifyFinished(Resource* resource) { 165 void PendingScript::notifyFinished(Resource* resource) {
123 // The following SRI checks need to be here because, unfortunately, fetches 166 // The following SRI checks need to be here because, unfortunately, fetches
124 // are not done purely according to the Fetch spec. In particular, 167 // are not done purely according to the Fetch spec. In particular,
125 // different requests for the same resource do not have different 168 // different requests for the same resource do not have different
126 // responses; the memory cache can (and will) return the exact same 169 // responses; the memory cache can (and will) return the exact same
127 // Resource object. 170 // Resource object.
128 // 171 //
129 // For different requests, the same Resource object will be returned and 172 // For different requests, the same Resource object will be returned and
130 // will not be associated with the particular request. Therefore, when the 173 // will not be associated with the particular request. Therefore, when the
131 // body of the response comes in, there's no way to validate the integrity 174 // body of the response comes in, there's no way to validate the integrity
132 // of the Resource object against a particular request (since there may be 175 // of the Resource object against a particular request (since there may be
133 // several pending requests all tied to the identical object, and the 176 // several pending requests all tied to the identical object, and the
134 // actual requests are not stored). 177 // actual requests are not stored).
135 // 178 //
136 // In order to simulate the correct behavior, Blink explicitly does the SRI 179 // In order to simulate the correct behavior, Blink explicitly does the SRI
137 // checks here, when a PendingScript tied to a particular request is 180 // checks here, when a PendingScript tied to a particular request is
138 // finished (and in the case of a StyleSheet, at the point of execution), 181 // finished (and in the case of a StyleSheet, at the point of execution),
139 // while having proper Fetch checks in the fetch module for use in the 182 // while having proper Fetch checks in the fetch module for use in the
140 // fetch JavaScript API. In a future world where the ResourceFetcher uses 183 // fetch JavaScript API. In a future world where the ResourceFetcher uses
141 // the Fetch algorithm, this should be fixed by having separate Response 184 // the Fetch algorithm, this should be fixed by having separate Response
142 // objects (perhaps attached to identical Resource objects) per request. 185 // objects (perhaps attached to identical Resource objects) per request.
143 // 186 //
144 // See https://crbug.com/500701 for more information. 187 // See https://crbug.com/500701 for more information.
145 CHECK(m_isForTesting || m_element); 188 CHECK(m_isForTesting || m_element);
146 if (m_element) { 189 if (m_element)
147 DCHECK_EQ(resource->getType(), Resource::Script); 190 m_integrityFailure = !checkScriptResourceIntegrity(resource, m_element);
148 ScriptResource* scriptResource = toScriptResource(resource);
149 String integrityAttr =
150 m_element->fastGetAttribute(HTMLNames::integrityAttr);
151
152 // It is possible to get back a script resource with integrity metadata
153 // for a request with an empty integrity attribute. In that case, the
154 // integrity check should be skipped, so this check ensures that the
155 // integrity attribute isn't empty in addition to checking if the
156 // resource has empty integrity metadata.
157 if (!integrityAttr.isEmpty() &&
158 !scriptResource->integrityMetadata().isEmpty()) {
159 ResourceIntegrityDisposition disposition =
160 scriptResource->integrityDisposition();
161 if (disposition == ResourceIntegrityDisposition::Failed) {
162 // TODO(jww): This should probably also generate a console
163 // message identical to the one produced by
164 // CheckSubresourceIntegrity below. See https://crbug.com/585267.
165 m_integrityFailure = true;
166 } else if (disposition == ResourceIntegrityDisposition::NotChecked &&
167 resource->resourceBuffer()) {
168 m_integrityFailure = !SubresourceIntegrity::CheckSubresourceIntegrity(
169 scriptResource->integrityMetadata(), *m_element,
170 resource->resourceBuffer()->data(),
171 resource->resourceBuffer()->size(), resource->url(), *resource);
172 scriptResource->setIntegrityDisposition(
173 m_integrityFailure ? ResourceIntegrityDisposition::Failed
174 : ResourceIntegrityDisposition::Passed);
175 }
176 }
177 }
178 191
179 // If script streaming is in use, the client will be notified in 192 // If script streaming is in use, the client will be notified in
180 // streamingFinished. 193 // streamingFinished.
181 if (m_streamer) 194 if (m_streamer)
182 m_streamer->notifyFinished(resource); 195 m_streamer->notifyFinished(resource);
183 else if (m_client) 196 else if (m_client)
184 m_client->pendingScriptFinished(this); 197 m_client->pendingScriptFinished(this);
185 } 198 }
186 199
187 void PendingScript::notifyAppendData(ScriptResource* resource) { 200 void PendingScript::notifyAppendData(ScriptResource* resource) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 } 247 }
235 248
236 void PendingScript::onPurgeMemory() { 249 void PendingScript::onPurgeMemory() {
237 if (!m_streamer) 250 if (!m_streamer)
238 return; 251 return;
239 m_streamer->cancel(); 252 m_streamer->cancel();
240 m_streamer = nullptr; 253 m_streamer = nullptr;
241 } 254 }
242 255
243 } // namespace blink 256 } // namespace blink
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698