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

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

Issue 23861003: Enable srcset support in HTMLImageElement (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Addressed issues raised in review. Merged Romain Perier's new parser implementation. Created 7 years, 3 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 /*
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 * Copyright (C) 2009 Torch Mobile, Inc. http://www.torchmobile.com/ 3 * Copyright (C) 2009 Torch Mobile, Inc. http://www.torchmobile.com/
4 * Copyright (C) 2010 Google Inc. All Rights Reserved. 4 * Copyright (C) 2010 Google Inc. All Rights Reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. 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 11 matching lines...) Expand all
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28 #include "config.h" 28 #include "config.h"
29 #include "core/html/parser/HTMLPreloadScanner.h" 29 #include "core/html/parser/HTMLPreloadScanner.h"
30 30
31 #include "HTMLNames.h" 31 #include "HTMLNames.h"
32 #include "RuntimeEnabledFeatures.h"
32 #include "core/html/InputTypeNames.h" 33 #include "core/html/InputTypeNames.h"
33 #include "core/html/LinkRelAttribute.h" 34 #include "core/html/LinkRelAttribute.h"
34 #include "core/html/parser/HTMLParserIdioms.h" 35 #include "core/html/parser/HTMLParserIdioms.h"
36 #include "core/html/parser/HTMLSrcsetParser.h"
35 #include "core/html/parser/HTMLTokenizer.h" 37 #include "core/html/parser/HTMLTokenizer.h"
36 #include "core/platform/chromium/TraceEvent.h" 38 #include "core/platform/chromium/TraceEvent.h"
37 #include "wtf/MainThread.h" 39 #include "wtf/MainThread.h"
38 40
39 namespace WebCore { 41 namespace WebCore {
40 42
41 using namespace HTMLNames; 43 using namespace HTMLNames;
42 44
43 static bool match(const StringImpl* impl, const QualifiedName& qName) 45 static bool match(const StringImpl* impl, const QualifiedName& qName)
44 { 46 {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 if (match(tagImpl, linkTag)) 85 if (match(tagImpl, linkTag))
84 return linkTag.localName(); 86 return linkTag.localName();
85 if (match(tagImpl, scriptTag)) 87 if (match(tagImpl, scriptTag))
86 return scriptTag.localName(); 88 return scriptTag.localName();
87 ASSERT_NOT_REACHED(); 89 ASSERT_NOT_REACHED();
88 return emptyString(); 90 return emptyString();
89 } 91 }
90 92
91 class TokenPreloadScanner::StartTagScanner { 93 class TokenPreloadScanner::StartTagScanner {
92 public: 94 public:
93 explicit StartTagScanner(const StringImpl* tagImpl) 95 explicit StartTagScanner(const StringImpl* tagImpl, float deviceScaleFactor)
94 : m_tagImpl(tagImpl) 96 : m_tagImpl(tagImpl)
95 , m_linkIsStyleSheet(false) 97 , m_linkIsStyleSheet(false)
96 , m_inputIsImage(false) 98 , m_inputIsImage(false)
99 , m_deviceScaleFactor(deviceScaleFactor)
97 { 100 {
98 if (!match(m_tagImpl, imgTag) 101 if (!match(m_tagImpl, imgTag)
99 && !match(m_tagImpl, inputTag) 102 && !match(m_tagImpl, inputTag)
100 && !match(m_tagImpl, linkTag) 103 && !match(m_tagImpl, linkTag)
101 && !match(m_tagImpl, scriptTag)) 104 && !match(m_tagImpl, scriptTag))
102 m_tagImpl = 0; 105 m_tagImpl = 0;
103 } 106 }
104 107
108 enum URLReplacement { URLReplacementAllow, URLReplacementDisallow };
abarth-chromium 2013/09/13 22:24:06 Each of these should be on its own line.
109
110
abarth-chromium 2013/09/13 22:24:06 Please remove this extra blank line.
111 void applySrcset()
112 {
113 // Resolve between src and srcSet if we have them.
abarth-chromium 2013/09/13 22:24:06 This "what" comment isn't needed. Please remove i
114 if (RuntimeEnabledFeatures::srcsetEnabled() && match(m_tagImpl, imgTag) && !m_srcSetAttribute.isEmpty())
115 setUrlToLoad(bestFitSourceForImageAttributes(m_deviceScaleFactor, m_ urlToLoad, m_srcSetAttribute), URLReplacementAllow);
116 }
117
105 void processAttributes(const HTMLToken::AttributeList& attributes) 118 void processAttributes(const HTMLToken::AttributeList& attributes)
106 { 119 {
107 ASSERT(isMainThread()); 120 ASSERT(isMainThread());
108 if (!m_tagImpl) 121 if (!m_tagImpl)
109 return; 122 return;
110 for (HTMLToken::AttributeList::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) { 123 for (HTMLToken::AttributeList::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) {
111 AtomicString attributeName(iter->name); 124 AtomicString attributeName(iter->name);
112 String attributeValue = StringImpl::create8BitIfPossible(iter->value ); 125 String attributeValue = StringImpl::create8BitIfPossible(iter->value );
113 processAttribute(attributeName, attributeValue); 126 processAttribute(attributeName, attributeValue);
114 } 127 }
128
129 applySrcset();
abarth-chromium 2013/09/13 22:24:06 As I wrote before, we don't want to do any srcset
115 } 130 }
116 131
117 void processAttributes(const Vector<CompactHTMLToken::Attribute>& attributes ) 132 void processAttributes(const Vector<CompactHTMLToken::Attribute>& attributes )
118 { 133 {
119 if (!m_tagImpl) 134 if (!m_tagImpl)
120 return; 135 return;
121 for (Vector<CompactHTMLToken::Attribute>::const_iterator iter = attribut es.begin(); iter != attributes.end(); ++iter) 136 for (Vector<CompactHTMLToken::Attribute>::const_iterator iter = attribut es.begin(); iter != attributes.end(); ++iter)
122 processAttribute(iter->name, iter->value); 137 processAttribute(iter->name, iter->value);
138
139 applySrcset();
123 } 140 }
124 141
125 PassOwnPtr<PreloadRequest> createPreloadRequest(const KURL& predictedBaseURL , const SegmentedString& source) 142 PassOwnPtr<PreloadRequest> createPreloadRequest(const KURL& predictedBaseURL , const SegmentedString& source)
126 { 143 {
127 if (!shouldPreload()) 144 if (!shouldPreload())
128 return nullptr; 145 return nullptr;
129 146
130 TRACE_EVENT_INSTANT1("net", "PreloadRequest", "url", m_urlToLoad.ascii() ); 147 TRACE_EVENT_INSTANT1("net", "PreloadRequest", "url", m_urlToLoad.ascii() );
131 TextPosition position = TextPosition(source.currentLine(), source.curren tColumn()); 148 TextPosition position = TextPosition(source.currentLine(), source.curren tColumn());
132 OwnPtr<PreloadRequest> request = PreloadRequest::create(initiatorFor(m_t agImpl), position, m_urlToLoad, predictedBaseURL, resourceType(), m_mediaAttribu te); 149 OwnPtr<PreloadRequest> request = PreloadRequest::create(initiatorFor(m_t agImpl), position, m_urlToLoad, predictedBaseURL, resourceType(), m_mediaAttribu te);
133 request->setCrossOriginModeAllowsCookies(crossOriginModeAllowsCookies()) ; 150 request->setCrossOriginModeAllowsCookies(crossOriginModeAllowsCookies()) ;
134 request->setCharset(charset()); 151 request->setCharset(charset());
135 return request.release(); 152 return request.release();
136 } 153 }
137 154
138 private: 155 private:
139 template<typename NameType> 156 template<typename NameType>
140 void processAttribute(const NameType& attributeName, const String& attribute Value) 157 void processAttribute(const NameType& attributeName, const String& attribute Value)
141 { 158 {
142 if (match(attributeName, charsetAttr)) 159 if (match(attributeName, charsetAttr))
143 m_charset = attributeValue; 160 m_charset = attributeValue;
144 161
145 if (match(m_tagImpl, scriptTag) || match(m_tagImpl, imgTag)) { 162 if (match(m_tagImpl, scriptTag) || match(m_tagImpl, imgTag)) {
146 if (match(attributeName, srcAttr)) 163 if (match(attributeName, srcAttr))
147 setUrlToLoad(attributeValue); 164 setUrlToLoad(attributeValue, URLReplacementDisallow);
abarth-chromium 2013/09/13 22:24:06 URLReplacementDisallow -> DisallowURLReplacement
148 else if (match(attributeName, crossoriginAttr) && !attributeValue.is Null()) 165 else if (match(attributeName, crossoriginAttr) && !attributeValue.is Null())
149 m_crossOriginMode = stripLeadingAndTrailingHTMLSpaces(attributeV alue); 166 m_crossOriginMode = stripLeadingAndTrailingHTMLSpaces(attributeV alue);
167 else if (match(m_tagImpl, imgTag) && match(attributeName, srcsetAttr ))
168 m_srcSetAttribute = attributeValue;
169
150 } else if (match(m_tagImpl, linkTag)) { 170 } else if (match(m_tagImpl, linkTag)) {
151 if (match(attributeName, hrefAttr)) 171 if (match(attributeName, hrefAttr))
152 setUrlToLoad(attributeValue); 172 setUrlToLoad(attributeValue, URLReplacementDisallow);
153 else if (match(attributeName, relAttr)) 173 else if (match(attributeName, relAttr))
154 m_linkIsStyleSheet = relAttributeIsStyleSheet(attributeValue); 174 m_linkIsStyleSheet = relAttributeIsStyleSheet(attributeValue);
155 else if (match(attributeName, mediaAttr)) 175 else if (match(attributeName, mediaAttr))
156 m_mediaAttribute = attributeValue; 176 m_mediaAttribute = attributeValue;
157 } else if (match(m_tagImpl, inputTag)) { 177 } else if (match(m_tagImpl, inputTag)) {
158 if (match(attributeName, srcAttr)) 178 if (match(attributeName, srcAttr))
159 setUrlToLoad(attributeValue); 179 setUrlToLoad(attributeValue, URLReplacementDisallow);
160 else if (match(attributeName, typeAttr)) 180 else if (match(attributeName, typeAttr))
161 m_inputIsImage = equalIgnoringCase(attributeValue, InputTypeName s::image()); 181 m_inputIsImage = equalIgnoringCase(attributeValue, InputTypeName s::image());
162 } 182 }
163 } 183 }
164 184
165 static bool relAttributeIsStyleSheet(const String& attributeValue) 185 static bool relAttributeIsStyleSheet(const String& attributeValue)
166 { 186 {
167 LinkRelAttribute rel(attributeValue); 187 LinkRelAttribute rel(attributeValue);
168 return rel.isStyleSheet() && !rel.isAlternate() && rel.iconType() == Inv alidIcon && !rel.isDNSPrefetch(); 188 return rel.isStyleSheet() && !rel.isAlternate() && rel.iconType() == Inv alidIcon && !rel.isDNSPrefetch();
169 } 189 }
170 190
171 void setUrlToLoad(const String& attributeValue) 191 void setUrlToLoad(const String& value, URLReplacement replacement)
172 { 192 {
173 // We only respect the first src/href, per HTML5: 193 // We only respect the first src/href, per HTML5:
174 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenizat ion.html#attribute-name-state 194 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenizat ion.html#attribute-name-state
175 if (!m_urlToLoad.isEmpty()) 195 if (replacement == URLReplacementDisallow && !m_urlToLoad.isEmpty())
176 return; 196 return;
177 m_urlToLoad = stripLeadingAndTrailingHTMLSpaces(attributeValue); 197 String url = stripLeadingAndTrailingHTMLSpaces(value);
198 if (url.isEmpty())
199 return;
200 m_urlToLoad = url;
178 } 201 }
179 202
180 const String& charset() const 203 const String& charset() const
181 { 204 {
182 // FIXME: Its not clear that this if is needed, the loader probably igno res charset for image requests anyway. 205 // FIXME: Its not clear that this if is needed, the loader probably igno res charset for image requests anyway.
183 if (match(m_tagImpl, imgTag)) 206 if (match(m_tagImpl, imgTag))
184 return emptyString(); 207 return emptyString();
185 return m_charset; 208 return m_charset;
186 } 209 }
187 210
(...skipping 20 matching lines...) Expand all
208 return true; 231 return true;
209 } 232 }
210 233
211 bool crossOriginModeAllowsCookies() 234 bool crossOriginModeAllowsCookies()
212 { 235 {
213 return m_crossOriginMode.isNull() || equalIgnoringCase(m_crossOriginMode , "use-credentials"); 236 return m_crossOriginMode.isNull() || equalIgnoringCase(m_crossOriginMode , "use-credentials");
214 } 237 }
215 238
216 const StringImpl* m_tagImpl; 239 const StringImpl* m_tagImpl;
217 String m_urlToLoad; 240 String m_urlToLoad;
241 String m_srcSetAttribute;
218 String m_charset; 242 String m_charset;
219 String m_crossOriginMode; 243 String m_crossOriginMode;
220 bool m_linkIsStyleSheet; 244 bool m_linkIsStyleSheet;
221 String m_mediaAttribute; 245 String m_mediaAttribute;
222 bool m_inputIsImage; 246 bool m_inputIsImage;
247 float m_deviceScaleFactor;
223 }; 248 };
224 249
225 TokenPreloadScanner::TokenPreloadScanner(const KURL& documentURL) 250 TokenPreloadScanner::TokenPreloadScanner(const KURL& documentURL, float deviceSc aleFactor)
226 : m_documentURL(documentURL) 251 : m_documentURL(documentURL)
227 , m_inStyle(false) 252 , m_inStyle(false)
253 , m_deviceScaleFactor(deviceScaleFactor)
228 , m_templateCount(0) 254 , m_templateCount(0)
229 { 255 {
230 } 256 }
231 257
232 TokenPreloadScanner::~TokenPreloadScanner() 258 TokenPreloadScanner::~TokenPreloadScanner()
233 { 259 {
234 } 260 }
235 261
236 TokenPreloadScannerCheckpoint TokenPreloadScanner::createCheckpoint() 262 TokenPreloadScannerCheckpoint TokenPreloadScanner::createCheckpoint()
237 { 263 {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 return; 324 return;
299 } 325 }
300 if (match(tagImpl, baseTag)) { 326 if (match(tagImpl, baseTag)) {
301 // The first <base> element is the one that wins. 327 // The first <base> element is the one that wins.
302 if (!m_predictedBaseElementURL.isEmpty()) 328 if (!m_predictedBaseElementURL.isEmpty())
303 return; 329 return;
304 updatePredictedBaseURL(token); 330 updatePredictedBaseURL(token);
305 return; 331 return;
306 } 332 }
307 333
308 StartTagScanner scanner(tagImpl); 334 StartTagScanner scanner(tagImpl, m_deviceScaleFactor);
309 scanner.processAttributes(token.attributes()); 335 scanner.processAttributes(token.attributes());
310 OwnPtr<PreloadRequest> request = scanner.createPreloadRequest(m_predicte dBaseElementURL, source); 336 OwnPtr<PreloadRequest> request = scanner.createPreloadRequest(m_predicte dBaseElementURL, source);
311 if (request) 337 if (request)
312 requests.append(request.release()); 338 requests.append(request.release());
313 return; 339 return;
314 } 340 }
315 default: { 341 default: {
316 return; 342 return;
317 } 343 }
318 } 344 }
319 } 345 }
320 346
321 template<typename Token> 347 template<typename Token>
322 void TokenPreloadScanner::updatePredictedBaseURL(const Token& token) 348 void TokenPreloadScanner::updatePredictedBaseURL(const Token& token)
323 { 349 {
324 ASSERT(m_predictedBaseElementURL.isEmpty()); 350 ASSERT(m_predictedBaseElementURL.isEmpty());
325 if (const typename Token::Attribute* hrefAttribute = token.getAttributeItem( hrefAttr)) 351 if (const typename Token::Attribute* hrefAttribute = token.getAttributeItem( hrefAttr))
326 m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingH TMLSpaces(hrefAttribute->value)).copy(); 352 m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingH TMLSpaces(hrefAttribute->value)).copy();
327 } 353 }
328 354
329 HTMLPreloadScanner::HTMLPreloadScanner(const HTMLParserOptions& options, const K URL& documentURL) 355 HTMLPreloadScanner::HTMLPreloadScanner(const HTMLParserOptions& options, const K URL& documentURL, float deviceScaleFactor)
330 : m_scanner(documentURL) 356 : m_scanner(documentURL, deviceScaleFactor)
331 , m_tokenizer(HTMLTokenizer::create(options)) 357 , m_tokenizer(HTMLTokenizer::create(options))
332 { 358 {
333 } 359 }
334 360
335 HTMLPreloadScanner::~HTMLPreloadScanner() 361 HTMLPreloadScanner::~HTMLPreloadScanner()
336 { 362 {
337 } 363 }
338 364
339 void HTMLPreloadScanner::appendToEnd(const SegmentedString& source) 365 void HTMLPreloadScanner::appendToEnd(const SegmentedString& source)
340 { 366 {
(...skipping 14 matching lines...) Expand all
355 if (m_token.type() == HTMLToken::StartTag) 381 if (m_token.type() == HTMLToken::StartTag)
356 m_tokenizer->updateStateFor(AtomicString(m_token.name())); 382 m_tokenizer->updateStateFor(AtomicString(m_token.name()));
357 m_scanner.scan(m_token, m_source, requests); 383 m_scanner.scan(m_token, m_source, requests);
358 m_token.clear(); 384 m_token.clear();
359 } 385 }
360 386
361 preloader->takeAndPreload(requests); 387 preloader->takeAndPreload(requests);
362 } 388 }
363 389
364 } 390 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698