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

Side by Side Diff: Source/core/html/parser/HTMLSrcsetParser.cpp

Issue 649183007: Add console errors and usecounter when srcset candidates are dropped (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: improved log messages Created 6 years, 2 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 | « Source/core/html/parser/HTMLSrcsetParser.h ('k') | 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) 2013 Apple Inc. All rights reserved. 2 * Copyright (C) 2013 Apple Inc. All rights reserved.
3 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are 6 * modification, are permitted provided that the following conditions are
7 * met: 7 * met:
8 * 8 *
9 * * Redistributions of source code must retain the above copyright 9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 14 matching lines...) Expand all
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32 #include "config.h" 32 #include "config.h"
33 #include "core/html/parser/HTMLSrcsetParser.h" 33 #include "core/html/parser/HTMLSrcsetParser.h"
34 34
35 #include "core/dom/Document.h"
36 #include "core/frame/FrameConsole.h"
37 #include "core/frame/LocalFrame.h"
38 #include "core/frame/UseCounter.h"
35 #include "core/html/parser/HTMLParserIdioms.h" 39 #include "core/html/parser/HTMLParserIdioms.h"
40 #include "core/inspector/ConsoleMessage.h"
36 #include "platform/ParsingUtilities.h" 41 #include "platform/ParsingUtilities.h"
37 #include "platform/RuntimeEnabledFeatures.h" 42 #include "platform/RuntimeEnabledFeatures.h"
38 43
39 namespace blink { 44 namespace blink {
40 45
41 static bool compareByDensity(const ImageCandidate& first, const ImageCandidate& second) 46 static bool compareByDensity(const ImageCandidate& first, const ImageCandidate& second)
42 { 47 {
43 return first.density() < second.density(); 48 return first.density() < second.density();
44 } 49 }
45 50
46 enum DescriptorTokenizerState { 51 enum DescriptorTokenizerState {
47 Start, 52 TokenStart,
48 InParenthesis, 53 InParenthesis,
49 AfterToken, 54 AfterToken,
50 }; 55 };
51 56
52 struct DescriptorToken { 57 struct DescriptorToken {
53 unsigned start; 58 unsigned start;
54 unsigned length; 59 unsigned length;
55 60
56 DescriptorToken(unsigned start, unsigned length) 61 DescriptorToken(unsigned start, unsigned length)
57 : start(start) 62 : start(start)
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 { 122 {
118 return position >= end; 123 return position >= end;
119 } 124 }
120 125
121 template<typename CharType> 126 template<typename CharType>
122 static void tokenizeDescriptors(const CharType* attributeStart, 127 static void tokenizeDescriptors(const CharType* attributeStart,
123 const CharType*& position, 128 const CharType*& position,
124 const CharType* attributeEnd, 129 const CharType* attributeEnd,
125 Vector<DescriptorToken>& descriptors) 130 Vector<DescriptorToken>& descriptors)
126 { 131 {
127 DescriptorTokenizerState state = Start; 132 DescriptorTokenizerState state = TokenStart;
128 const CharType* descriptorsStart = position; 133 const CharType* descriptorsStart = position;
129 const CharType* currentDescriptorStart = descriptorsStart; 134 const CharType* currentDescriptorStart = descriptorsStart;
130 while (true) { 135 while (true) {
131 switch (state) { 136 switch (state) {
132 case Start: 137 case TokenStart:
133 if (isEOF(position, attributeEnd)) { 138 if (isEOF(position, attributeEnd)) {
134 appendDescriptorAndReset(attributeStart, currentDescriptorStart, attributeEnd, descriptors); 139 appendDescriptorAndReset(attributeStart, currentDescriptorStart, attributeEnd, descriptors);
135 return; 140 return;
136 } 141 }
137 if (isComma(*position)) { 142 if (isComma(*position)) {
138 appendDescriptorAndReset(attributeStart, currentDescriptorStart, position, descriptors); 143 appendDescriptorAndReset(attributeStart, currentDescriptorStart, position, descriptors);
139 ++position; 144 ++position;
140 return; 145 return;
141 } 146 }
142 if (isHTMLSpace(*position)) { 147 if (isHTMLSpace(*position)) {
143 appendDescriptorAndReset(attributeStart, currentDescriptorStart, position, descriptors); 148 appendDescriptorAndReset(attributeStart, currentDescriptorStart, position, descriptors);
144 currentDescriptorStart = position + 1; 149 currentDescriptorStart = position + 1;
145 state = AfterToken; 150 state = AfterToken;
146 } else if (*position == '(') { 151 } else if (*position == '(') {
147 appendCharacter(currentDescriptorStart, position); 152 appendCharacter(currentDescriptorStart, position);
148 state = InParenthesis; 153 state = InParenthesis;
149 } else { 154 } else {
150 appendCharacter(currentDescriptorStart, position); 155 appendCharacter(currentDescriptorStart, position);
151 } 156 }
152 break; 157 break;
153 case InParenthesis: 158 case InParenthesis:
154 if (isEOF(position, attributeEnd)) { 159 if (isEOF(position, attributeEnd)) {
155 appendDescriptorAndReset(attributeStart, currentDescriptorStart, attributeEnd, descriptors); 160 appendDescriptorAndReset(attributeStart, currentDescriptorStart, attributeEnd, descriptors);
156 return; 161 return;
157 } 162 }
158 if (*position == ')') { 163 if (*position == ')') {
159 appendCharacter(currentDescriptorStart, position); 164 appendCharacter(currentDescriptorStart, position);
160 state = Start; 165 state = TokenStart;
161 } else { 166 } else {
162 appendCharacter(currentDescriptorStart, position); 167 appendCharacter(currentDescriptorStart, position);
163 } 168 }
164 break; 169 break;
165 case AfterToken: 170 case AfterToken:
166 if (isEOF(position, attributeEnd)) 171 if (isEOF(position, attributeEnd))
167 return; 172 return;
168 if (!isHTMLSpace(*position)) { 173 if (!isHTMLSpace(*position)) {
169 state = Start; 174 state = TokenStart;
170 currentDescriptorStart = position; 175 currentDescriptorStart = position;
171 --position; 176 --position;
172 } 177 }
173 break; 178 break;
174 } 179 }
175 ++position; 180 ++position;
176 } 181 }
177 } 182 }
178 183
184 static void srcsetError(Document* document, String message)
185 {
186 if (document && document->frame()) {
187 StringBuilder errorMessage;
Mike West 2014/10/21 09:36:25 StringBuilder is probably overkill here. '+' would
188 errorMessage.append("Failed parsing 'srcset' attribute value since ");
189 errorMessage.append(message);
190 document->frame()->console().addMessage(ConsoleMessage::create(OtherMess ageSource, ErrorMessageLevel, errorMessage.toString()));
191 }
192 }
193
179 template<typename CharType> 194 template<typename CharType>
180 static bool parseDescriptors(const CharType* attribute, Vector<DescriptorToken>& descriptors, DescriptorParsingResult& result) 195 static bool parseDescriptors(const CharType* attribute, Vector<DescriptorToken>& descriptors, DescriptorParsingResult& result, Document* document)
181 { 196 {
182 for (Vector<DescriptorToken>::iterator it = descriptors.begin(); it != descr iptors.end(); ++it) { 197 for (Vector<DescriptorToken>::iterator it = descriptors.begin(); it != descr iptors.end(); ++it) {
183 if (it->length == 0) 198 if (it->length == 0)
184 continue; 199 continue;
185 CharType c = attribute[it->lastIndex()]; 200 CharType c = attribute[it->lastIndex()];
186 bool isValid = false; 201 bool isValid = false;
187 if (RuntimeEnabledFeatures::pictureSizesEnabled() && c == 'w') { 202 if (RuntimeEnabledFeatures::pictureSizesEnabled() && c == 'w') {
188 if (result.hasDensity() || result.hasWidth()) 203 if (result.hasDensity() || result.hasWidth()) {
204 srcsetError(document, "it has multiple 'w' descriptors or a mix of 'x' and 'w' descriptors.");
189 return false; 205 return false;
206 }
190 int resourceWidth = it->toInt(attribute, isValid); 207 int resourceWidth = it->toInt(attribute, isValid);
191 if (!isValid || resourceWidth <= 0) 208 if (!isValid || resourceWidth <= 0) {
209 srcsetError(document, "its 'w' descriptor is invalid.");
192 return false; 210 return false;
211 }
193 result.setResourceWidth(resourceWidth); 212 result.setResourceWidth(resourceWidth);
194 } else if (RuntimeEnabledFeatures::pictureSizesEnabled() && c == 'h') { 213 } else if (RuntimeEnabledFeatures::pictureSizesEnabled() && c == 'h') {
195 // This is here only for future compat purposes. 214 // This is here only for future compat purposes.
196 // The value of the 'h' descriptor is not used. 215 // The value of the 'h' descriptor is not used.
197 if (result.hasDensity() || result.hasHeight()) 216 if (result.hasDensity() || result.hasHeight()) {
217 srcsetError(document, "it has multiple 'h' descriptors or a mix of 'x' and 'h' descriptors.");
198 return false; 218 return false;
219 }
199 int resourceHeight = it->toInt(attribute, isValid); 220 int resourceHeight = it->toInt(attribute, isValid);
200 if (!isValid || resourceHeight <= 0) 221 if (!isValid || resourceHeight <= 0) {
222 srcsetError(document, "its 'h' descriptor is invalid.");
201 return false; 223 return false;
224 }
202 result.setResourceHeight(resourceHeight); 225 result.setResourceHeight(resourceHeight);
203 } else if (c == 'x') { 226 } else if (c == 'x') {
204 if (result.hasDensity() || result.hasHeight() || result.hasWidth()) 227 if (result.hasDensity() || result.hasHeight() || result.hasWidth()) {
228 srcsetError(document, "it has multiple 'x' descriptors or a mix of 'x' and 'w'/'h' descriptors.");
205 return false; 229 return false;
230 }
206 float density = it->toFloat(attribute, isValid); 231 float density = it->toFloat(attribute, isValid);
207 if (!isValid || density < 0) 232 if (!isValid || density < 0) {
233 srcsetError(document, "its 'x' descriptor is invalid.");
208 return false; 234 return false;
235 }
209 result.setDensity(density); 236 result.setDensity(density);
210 } else { 237 } else {
238 srcsetError(document, "it has an unknown descriptor.");
211 return false; 239 return false;
212 } 240 }
213 } 241 }
214 return (!result.hasHeight() || result.hasWidth()); 242 bool res = !result.hasHeight() || result.hasWidth();
243 if (!res)
244 srcsetError(document, "it has an 'h' descriptor and no 'w' descriptor.") ;
245 return res;
215 } 246 }
216 247
217 static bool parseDescriptors(const String& attribute, Vector<DescriptorToken>& d escriptors, DescriptorParsingResult& result) 248 static bool parseDescriptors(const String& attribute, Vector<DescriptorToken>& d escriptors, DescriptorParsingResult& result, Document* document)
218 { 249 {
219 // FIXME: See if StringView can't be extended to replace DescriptorToken her e. 250 // FIXME: See if StringView can't be extended to replace DescriptorToken her e.
220 if (attribute.is8Bit()) { 251 if (attribute.is8Bit()) {
221 return parseDescriptors(attribute.characters8(), descriptors, result); 252 return parseDescriptors(attribute.characters8(), descriptors, result, do cument);
222 } 253 }
223 return parseDescriptors(attribute.characters16(), descriptors, result); 254 return parseDescriptors(attribute.characters16(), descriptors, result, docum ent);
224 } 255 }
225 256
226 // http://picture.responsiveimages.org/#parse-srcset-attr 257 // http://picture.responsiveimages.org/#parse-srcset-attr
227 template<typename CharType> 258 template<typename CharType>
228 static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, con st CharType* attributeStart, unsigned length, Vector<ImageCandidate>& imageCandi dates) 259 static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, con st CharType* attributeStart, unsigned length, Vector<ImageCandidate>& imageCandi dates, Document* document)
229 { 260 {
230 const CharType* position = attributeStart; 261 const CharType* position = attributeStart;
231 const CharType* attributeEnd = position + length; 262 const CharType* attributeEnd = position + length;
232 263
233 while (position < attributeEnd) { 264 while (position < attributeEnd) {
234 // 4. Splitting loop: Collect a sequence of characters that are space ch aracters or U+002C COMMA characters. 265 // 4. Splitting loop: Collect a sequence of characters that are space ch aracters or U+002C COMMA characters.
235 skipWhile<CharType, isHTMLSpaceOrComma<CharType> >(position, attributeEn d); 266 skipWhile<CharType, isHTMLSpaceOrComma<CharType> >(position, attributeEn d);
236 if (position == attributeEnd) { 267 if (position == attributeEnd) {
237 // Contrary to spec language - descriptor parsing happens on each ca ndidate, so when we reach the attributeEnd, we can exit. 268 // Contrary to spec language - descriptor parsing happens on each ca ndidate, so when we reach the attributeEnd, we can exit.
238 break; 269 break;
239 } 270 }
240 const CharType* imageURLStart = position; 271 const CharType* imageURLStart = position;
272
241 // 6. Collect a sequence of characters that are not space characters, an d let that be url. 273 // 6. Collect a sequence of characters that are not space characters, an d let that be url.
242
243 skipUntil<CharType, isHTMLSpace<CharType> >(position, attributeEnd); 274 skipUntil<CharType, isHTMLSpace<CharType> >(position, attributeEnd);
244 const CharType* imageURLEnd = position; 275 const CharType* imageURLEnd = position;
245 276
246 DescriptorParsingResult result; 277 DescriptorParsingResult result;
247 278
248 // 8. If url ends with a U+002C COMMA character (,) 279 // 8. If url ends with a U+002C COMMA character (,)
249 if (isComma(*(position - 1))) { 280 if (isComma(*(position - 1))) {
250 // Remove all trailing U+002C COMMA characters from url. 281 // Remove all trailing U+002C COMMA characters from url.
251 imageURLEnd = position - 1; 282 imageURLEnd = position - 1;
252 reverseSkipWhile<CharType, isComma>(imageURLEnd, imageURLStart); 283 reverseSkipWhile<CharType, isComma>(imageURLEnd, imageURLStart);
253 ++imageURLEnd; 284 ++imageURLEnd;
254 // If url is empty, then jump to the step labeled splitting loop. 285 // If url is empty, then jump to the step labeled splitting loop.
255 if (imageURLStart == imageURLEnd) 286 if (imageURLStart == imageURLEnd)
256 continue; 287 continue;
257 } else { 288 } else {
258 // Advancing position here (contrary to spec) to avoid an useless ex tra state machine step. 289 skipWhile<CharType, isHTMLSpace<CharType> >(position, attributeEnd);
259 // Filed a spec bug: https://github.com/ResponsiveImagesCG/picture-e lement/issues/189
260 ++position;
261 Vector<DescriptorToken> descriptorTokens; 290 Vector<DescriptorToken> descriptorTokens;
262 tokenizeDescriptors(attributeStart, position, attributeEnd, descript orTokens); 291 tokenizeDescriptors(attributeStart, position, attributeEnd, descript orTokens);
263 // Contrary to spec language - descriptor parsing happens on each ca ndidate. 292 // Contrary to spec language - descriptor parsing happens on each ca ndidate.
264 // This is a black-box equivalent, to avoid storing descriptor lists for each candidate. 293 // This is a black-box equivalent, to avoid storing descriptor lists for each candidate.
265 if (!parseDescriptors(attribute, descriptorTokens, result)) 294 if (!parseDescriptors(attribute, descriptorTokens, result, document) ) {
295 if (document) {
296 UseCounter::count(document, UseCounter::SrcsetDroppedCandida te);
297 if (document->frame())
298 document->frame()->console().addMessage(ConsoleMessage:: create(OtherMessageSource, ErrorMessageLevel, String("Dropped srcset candidate " ) + String(imageURLStart, imageURLEnd - imageURLStart)));
299 }
266 continue; 300 continue;
301 }
267 } 302 }
268 303
269 ASSERT(imageURLEnd > attributeStart); 304 ASSERT(imageURLEnd > attributeStart);
270 unsigned imageURLStartingPosition = imageURLStart - attributeStart; 305 unsigned imageURLStartingPosition = imageURLStart - attributeStart;
271 ASSERT(imageURLEnd > imageURLStart); 306 ASSERT(imageURLEnd > imageURLStart);
272 unsigned imageURLLength = imageURLEnd - imageURLStart; 307 unsigned imageURLLength = imageURLEnd - imageURLStart;
273 imageCandidates.append(ImageCandidate(attribute, imageURLStartingPositio n, imageURLLength, result, ImageCandidate::SrcsetOrigin)); 308 imageCandidates.append(ImageCandidate(attribute, imageURLStartingPositio n, imageURLLength, result, ImageCandidate::SrcsetOrigin));
274 // 11. Return to the step labeled splitting loop. 309 // 11. Return to the step labeled splitting loop.
275 } 310 }
276 } 311 }
277 312
278 static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, Vec tor<ImageCandidate>& imageCandidates) 313 static void parseImageCandidatesFromSrcsetAttribute(const String& attribute, Vec tor<ImageCandidate>& imageCandidates, Document* document)
279 { 314 {
280 if (attribute.isNull()) 315 if (attribute.isNull())
281 return; 316 return;
282 317
283 if (attribute.is8Bit()) 318 if (attribute.is8Bit())
284 parseImageCandidatesFromSrcsetAttribute<LChar>(attribute, attribute.char acters8(), attribute.length(), imageCandidates); 319 parseImageCandidatesFromSrcsetAttribute<LChar>(attribute, attribute.char acters8(), attribute.length(), imageCandidates, document);
285 else 320 else
286 parseImageCandidatesFromSrcsetAttribute<UChar>(attribute, attribute.char acters16(), attribute.length(), imageCandidates); 321 parseImageCandidatesFromSrcsetAttribute<UChar>(attribute, attribute.char acters16(), attribute.length(), imageCandidates, document);
287 } 322 }
288 323
289 static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, float sour ceSize, Vector<ImageCandidate>& imageCandidates) 324 static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, float sour ceSize, Vector<ImageCandidate>& imageCandidates)
290 { 325 {
291 const float defaultDensityValue = 1.0; 326 const float defaultDensityValue = 1.0;
292 bool ignoreSrc = false; 327 bool ignoreSrc = false;
293 if (imageCandidates.isEmpty()) 328 if (imageCandidates.isEmpty())
294 return ImageCandidate(); 329 return ImageCandidate();
295 330
296 // http://picture.responsiveimages.org/#normalize-source-densities 331 // http://picture.responsiveimages.org/#normalize-source-densities
(...skipping 22 matching lines...) Expand all
319 354
320 unsigned winner = i; 355 unsigned winner = i;
321 // 16. If an entry b in candidates has the same associated ... pixel density as an earlier entry a in candidates, 356 // 16. If an entry b in candidates has the same associated ... pixel density as an earlier entry a in candidates,
322 // then remove entry b 357 // then remove entry b
323 while ((i > 0) && (imageCandidates[--i].density() == winningDensity)) 358 while ((i > 0) && (imageCandidates[--i].density() == winningDensity))
324 winner = i; 359 winner = i;
325 360
326 return imageCandidates[winner]; 361 return imageCandidates[winner];
327 } 362 }
328 363
329 ImageCandidate bestFitSourceForSrcsetAttribute(float deviceScaleFactor, float so urceSize, const String& srcsetAttribute) 364 ImageCandidate bestFitSourceForSrcsetAttribute(float deviceScaleFactor, float so urceSize, const String& srcsetAttribute, Document* document)
330 { 365 {
331 Vector<ImageCandidate> imageCandidates; 366 Vector<ImageCandidate> imageCandidates;
332 367
333 parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates); 368 parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates, do cument);
334 369
335 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates ); 370 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates );
336 } 371 }
337 372
338 ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, float so urceSize, const String& srcAttribute, const String& srcsetAttribute) 373 ImageCandidate bestFitSourceForImageAttributes(float deviceScaleFactor, float so urceSize, const String& srcAttribute, const String& srcsetAttribute, Document* d ocument)
339 { 374 {
340 if (srcsetAttribute.isNull()) { 375 if (srcsetAttribute.isNull()) {
341 if (srcAttribute.isNull()) 376 if (srcAttribute.isNull())
342 return ImageCandidate(); 377 return ImageCandidate();
343 return ImageCandidate(srcAttribute, 0, srcAttribute.length(), Descriptor ParsingResult(), ImageCandidate::SrcOrigin); 378 return ImageCandidate(srcAttribute, 0, srcAttribute.length(), Descriptor ParsingResult(), ImageCandidate::SrcOrigin);
344 } 379 }
345 380
346 Vector<ImageCandidate> imageCandidates; 381 Vector<ImageCandidate> imageCandidates;
347 382
348 parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates); 383 parseImageCandidatesFromSrcsetAttribute(srcsetAttribute, imageCandidates, do cument);
349 384
350 if (!srcAttribute.isEmpty()) 385 if (!srcAttribute.isEmpty())
351 imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.leng th(), DescriptorParsingResult(), ImageCandidate::SrcOrigin)); 386 imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.leng th(), DescriptorParsingResult(), ImageCandidate::SrcOrigin));
352 387
353 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates ); 388 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates );
354 } 389 }
355 390
356 String bestFitSourceForImageAttributes(float deviceScaleFactor, float sourceSize , const String& srcAttribute, ImageCandidate& srcsetImageCandidate) 391 String bestFitSourceForImageAttributes(float deviceScaleFactor, float sourceSize , const String& srcAttribute, ImageCandidate& srcsetImageCandidate)
357 { 392 {
358 if (srcsetImageCandidate.isEmpty()) 393 if (srcsetImageCandidate.isEmpty())
359 return srcAttribute; 394 return srcAttribute;
360 395
361 Vector<ImageCandidate> imageCandidates; 396 Vector<ImageCandidate> imageCandidates;
362 imageCandidates.append(srcsetImageCandidate); 397 imageCandidates.append(srcsetImageCandidate);
363 398
364 if (!srcAttribute.isEmpty()) 399 if (!srcAttribute.isEmpty())
365 imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.leng th(), DescriptorParsingResult(), ImageCandidate::SrcOrigin)); 400 imageCandidates.append(ImageCandidate(srcAttribute, 0, srcAttribute.leng th(), DescriptorParsingResult(), ImageCandidate::SrcOrigin));
366 401
367 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates ).toString(); 402 return pickBestImageCandidate(deviceScaleFactor, sourceSize, imageCandidates ).toString();
368 } 403 }
369 404
370 } 405 }
OLDNEW
« no previous file with comments | « Source/core/html/parser/HTMLSrcsetParser.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698