OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/search_engines/template_url_parser.h" | 5 #include "chrome/browser/search_engines/template_url_parser.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <map> | 8 #include <map> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 static void StartElementImpl(void* ctx, | 138 static void StartElementImpl(void* ctx, |
139 const xmlChar* name, | 139 const xmlChar* name, |
140 const xmlChar** atts); | 140 const xmlChar** atts); |
141 static void EndElementImpl(void* ctx, const xmlChar* name); | 141 static void EndElementImpl(void* ctx, const xmlChar* name); |
142 static void CharactersImpl(void* ctx, const xmlChar* ch, int len); | 142 static void CharactersImpl(void* ctx, const xmlChar* ch, int len); |
143 | 143 |
144 // Returns a heap-allocated TemplateURL representing the result of parsing. | 144 // Returns a heap-allocated TemplateURL representing the result of parsing. |
145 // This will be NULL if parsing failed or if the results were invalid for some | 145 // This will be NULL if parsing failed or if the results were invalid for some |
146 // reason (e.g. the resulting URL was not HTTP[S], a name wasn't supplied, | 146 // reason (e.g. the resulting URL was not HTTP[S], a name wasn't supplied, |
147 // etc.). | 147 // etc.). |
148 TemplateURL* GetTemplateURL(Profile* profile); | 148 TemplateURL* GetTemplateURL(Profile* profile, bool show_in_default_list); |
149 | 149 |
150 private: | 150 private: |
151 // Key is UTF8 encoded. | 151 // Key is UTF8 encoded. |
152 typedef std::map<std::string, ElementType> ElementNameToElementTypeMap; | 152 typedef std::map<std::string, ElementType> ElementNameToElementTypeMap; |
153 | 153 |
154 static void InitMapping(); | 154 static void InitMapping(); |
155 | 155 |
156 void ParseURL(const xmlChar** atts); | 156 void ParseURL(const xmlChar** atts); |
157 void ParseImage(const xmlChar** atts); | 157 void ParseImage(const xmlChar** atts); |
158 void ParseParam(const xmlChar** atts); | 158 void ParseParam(const xmlChar** atts); |
159 void ProcessURLParams(); | 159 void ProcessURLParams(); |
160 | 160 |
161 // Returns the current ElementType. | 161 // Returns the current ElementType. |
162 ElementType GetKnownType(); | 162 ElementType GetKnownType(); |
163 | 163 |
164 static ElementNameToElementTypeMap* kElementNameToElementTypeMap; | 164 static ElementNameToElementTypeMap* kElementNameToElementTypeMap; |
165 | 165 |
166 scoped_ptr<TemplateURL> url_; | 166 // Data that gets updated as we parse, and is converted to a TemplateURL by |
| 167 // GetTemplateURL(). |
| 168 TemplateURLData data_; |
167 | 169 |
168 std::vector<ElementType> elements_; | 170 std::vector<ElementType> elements_; |
169 bool image_is_valid_for_favicon_; | 171 bool image_is_valid_for_favicon_; |
170 | 172 |
171 // Character content for the current element. | 173 // Character content for the current element. |
172 string16 string_; | 174 string16 string_; |
173 | 175 |
174 TemplateURLParser::ParameterFilter* parameter_filter_; | 176 TemplateURLParser::ParameterFilter* parameter_filter_; |
175 | 177 |
176 // The list of parameters parsed in the Param nodes of a Url node. | 178 // The list of parameters parsed in the Param nodes of a Url node. |
(...skipping 13 matching lines...) Expand all Loading... |
190 | 192 |
191 DISALLOW_COPY_AND_ASSIGN(TemplateURLParsingContext); | 193 DISALLOW_COPY_AND_ASSIGN(TemplateURLParsingContext); |
192 }; | 194 }; |
193 | 195 |
194 // static | 196 // static |
195 TemplateURLParsingContext::ElementNameToElementTypeMap* | 197 TemplateURLParsingContext::ElementNameToElementTypeMap* |
196 TemplateURLParsingContext::kElementNameToElementTypeMap = NULL; | 198 TemplateURLParsingContext::kElementNameToElementTypeMap = NULL; |
197 | 199 |
198 TemplateURLParsingContext::TemplateURLParsingContext( | 200 TemplateURLParsingContext::TemplateURLParsingContext( |
199 TemplateURLParser::ParameterFilter* parameter_filter) | 201 TemplateURLParser::ParameterFilter* parameter_filter) |
200 : url_(new TemplateURL()), | 202 : image_is_valid_for_favicon_(false), |
201 image_is_valid_for_favicon_(false), | |
202 parameter_filter_(parameter_filter), | 203 parameter_filter_(parameter_filter), |
203 method_(GET), | 204 method_(GET), |
204 suggestion_method_(GET), | 205 suggestion_method_(GET), |
205 is_suggest_url_(false), | 206 is_suggest_url_(false), |
206 derive_image_from_url_(false) { | 207 derive_image_from_url_(false) { |
207 if (kElementNameToElementTypeMap == NULL) | 208 if (kElementNameToElementTypeMap == NULL) |
208 InitMapping(); | 209 InitMapping(); |
209 // When combined with proscriptions elsewhere against updating url_->url_ to | 210 // When combined with proscriptions elsewhere against updating data_->url_ to |
210 // the empty string, this call ensures url_->url() will never be NULL. | 211 // the empty string, this call ensures data_->url() will never be NULL. |
211 url_->SetURL("x"); | 212 data_.SetURL("x"); |
212 } | 213 } |
213 | 214 |
214 // static | 215 // static |
215 void TemplateURLParsingContext::StartElementImpl(void* ctx, | 216 void TemplateURLParsingContext::StartElementImpl(void* ctx, |
216 const xmlChar* name, | 217 const xmlChar* name, |
217 const xmlChar** atts) { | 218 const xmlChar** atts) { |
218 // Remove the namespace from |name|, ex: os:Url -> Url. | 219 // Remove the namespace from |name|, ex: os:Url -> Url. |
219 std::string node_name(XMLCharToString(name)); | 220 std::string node_name(XMLCharToString(name)); |
220 size_t index = node_name.find_first_of(":"); | 221 size_t index = node_name.find_first_of(":"); |
221 if (index != std::string::npos) | 222 if (index != std::string::npos) |
(...skipping 20 matching lines...) Expand all Loading... |
242 } | 243 } |
243 context->string_.clear(); | 244 context->string_.clear(); |
244 } | 245 } |
245 | 246 |
246 // static | 247 // static |
247 void TemplateURLParsingContext::EndElementImpl(void* ctx, const xmlChar* name) { | 248 void TemplateURLParsingContext::EndElementImpl(void* ctx, const xmlChar* name) { |
248 TemplateURLParsingContext* context = | 249 TemplateURLParsingContext* context = |
249 reinterpret_cast<TemplateURLParsingContext*>(ctx); | 250 reinterpret_cast<TemplateURLParsingContext*>(ctx); |
250 switch (context->GetKnownType()) { | 251 switch (context->GetKnownType()) { |
251 case TemplateURLParsingContext::SHORT_NAME: | 252 case TemplateURLParsingContext::SHORT_NAME: |
252 context->url_->short_name_ = context->string_; | 253 context->data_.short_name = context->string_; |
253 break; | 254 break; |
254 case TemplateURLParsingContext::IMAGE: { | 255 case TemplateURLParsingContext::IMAGE: { |
255 GURL image_url(UTF16ToUTF8(context->string_)); | 256 GURL image_url(UTF16ToUTF8(context->string_)); |
256 if (image_url.SchemeIs(chrome::kDataScheme)) { | 257 if (image_url.SchemeIs(chrome::kDataScheme)) { |
257 // TODO (jcampan): bug 1169256: when dealing with data URL, we need to | 258 // TODO (jcampan): bug 1169256: when dealing with data URL, we need to |
258 // decode the data URL in the renderer. For now, we'll just point to the | 259 // decode the data URL in the renderer. For now, we'll just point to the |
259 // favicon from the URL. | 260 // favicon from the URL. |
260 context->derive_image_from_url_ = true; | 261 context->derive_image_from_url_ = true; |
261 } else if (context->image_is_valid_for_favicon_ && image_url.is_valid() && | 262 } else if (context->image_is_valid_for_favicon_ && image_url.is_valid() && |
262 (image_url.SchemeIs(chrome::kHttpScheme) || | 263 (image_url.SchemeIs(chrome::kHttpScheme) || |
263 image_url.SchemeIs(chrome::kHttpsScheme))) { | 264 image_url.SchemeIs(chrome::kHttpsScheme))) { |
264 context->url_->set_favicon_url(image_url); | 265 context->data_.favicon_url = image_url; |
265 } | 266 } |
266 context->image_is_valid_for_favicon_ = false; | 267 context->image_is_valid_for_favicon_ = false; |
267 break; | 268 break; |
268 } | 269 } |
269 case TemplateURLParsingContext::INPUT_ENCODING: { | 270 case TemplateURLParsingContext::INPUT_ENCODING: { |
270 std::string input_encoding = UTF16ToASCII(context->string_); | 271 std::string input_encoding = UTF16ToASCII(context->string_); |
271 if (IsValidEncodingString(input_encoding)) | 272 if (IsValidEncodingString(input_encoding)) |
272 context->url_->input_encodings_.push_back(input_encoding); | 273 context->data_.input_encodings.push_back(input_encoding); |
273 break; | 274 break; |
274 } | 275 } |
275 case TemplateURLParsingContext::URL: | 276 case TemplateURLParsingContext::URL: |
276 context->ProcessURLParams(); | 277 context->ProcessURLParams(); |
277 break; | 278 break; |
278 default: | 279 default: |
279 break; | 280 break; |
280 } | 281 } |
281 context->string_.clear(); | 282 context->string_.clear(); |
282 context->elements_.pop_back(); | 283 context->elements_.pop_back(); |
283 } | 284 } |
284 | 285 |
285 // static | 286 // static |
286 void TemplateURLParsingContext::CharactersImpl(void* ctx, | 287 void TemplateURLParsingContext::CharactersImpl(void* ctx, |
287 const xmlChar* ch, | 288 const xmlChar* ch, |
288 int len) { | 289 int len) { |
289 reinterpret_cast<TemplateURLParsingContext*>(ctx)->string_ += | 290 reinterpret_cast<TemplateURLParsingContext*>(ctx)->string_ += |
290 UTF8ToUTF16(std::string(reinterpret_cast<const char*>(ch), len)); | 291 UTF8ToUTF16(std::string(reinterpret_cast<const char*>(ch), len)); |
291 } | 292 } |
292 | 293 |
293 TemplateURL* TemplateURLParsingContext::GetTemplateURL(Profile* profile) { | 294 TemplateURL* TemplateURLParsingContext::GetTemplateURL( |
| 295 Profile* profile, |
| 296 bool show_in_default_list) { |
294 // Basic legality checks. | 297 // Basic legality checks. |
295 if (url_->short_name_.empty() || !IsHTTPRef(url_->url()) || | 298 if (data_.short_name.empty() || !IsHTTPRef(data_.url()) || |
296 !IsHTTPRef(url_->suggestions_url())) | 299 !IsHTTPRef(data_.suggestions_url)) |
297 return NULL; | 300 return NULL; |
298 | 301 |
299 // If the image was a data URL, use the favicon from the search URL instead. | 302 // If the image was a data URL, use the favicon from the search URL instead. |
300 // (see TODO inEndElementImpl()). | 303 // (see TODO inEndElementImpl()). |
301 GURL url(url_->url()); | 304 GURL url(data_.url()); |
302 if (derive_image_from_url_ && url_->favicon_url().is_empty()) | 305 if (derive_image_from_url_ && data_.favicon_url.is_empty()) |
303 url_->set_favicon_url(TemplateURL::GenerateFaviconURL(url)); | 306 data_.favicon_url = TemplateURL::GenerateFaviconURL(url); |
304 | 307 |
305 // TODO(jcampan): http://b/issue?id=1196285 we do not support search engines | 308 // TODO(jcampan): http://b/issue?id=1196285 we do not support search engines |
306 // that use POST yet. | 309 // that use POST yet. |
307 if (method_ == TemplateURLParsingContext::POST) | 310 if (method_ == TemplateURLParsingContext::POST) |
308 return NULL; | 311 return NULL; |
309 if (suggestion_method_ == TemplateURLParsingContext::POST) | 312 if (suggestion_method_ == TemplateURLParsingContext::POST) |
310 url_->SetSuggestionsURL(std::string()); | 313 data_.suggestions_url.clear(); |
311 | 314 |
312 // Give this a keyword to facilitate tab-to-search. | 315 // Give this a keyword to facilitate tab-to-search. |
313 string16 keyword(TemplateURLService::GenerateKeyword(url, false)); | 316 string16 keyword(TemplateURLService::GenerateKeyword(url, false)); |
314 DCHECK(!keyword.empty()); | 317 DCHECK(!keyword.empty()); |
315 url_->set_keyword(keyword); | 318 data_.SetKeyword(keyword); |
316 return url_.release(); | 319 data_.show_in_default_list = show_in_default_list; |
| 320 return new TemplateURL(data_); |
317 } | 321 } |
318 | 322 |
319 // static | 323 // static |
320 void TemplateURLParsingContext::InitMapping() { | 324 void TemplateURLParsingContext::InitMapping() { |
321 kElementNameToElementTypeMap = new std::map<std::string, ElementType>; | 325 kElementNameToElementTypeMap = new std::map<std::string, ElementType>; |
322 (*kElementNameToElementTypeMap)[kURLElement] = URL; | 326 (*kElementNameToElementTypeMap)[kURLElement] = URL; |
323 (*kElementNameToElementTypeMap)[kParamElement] = PARAM; | 327 (*kElementNameToElementTypeMap)[kParamElement] = PARAM; |
324 (*kElementNameToElementTypeMap)[kShortNameElement] = SHORT_NAME; | 328 (*kElementNameToElementTypeMap)[kShortNameElement] = SHORT_NAME; |
325 (*kElementNameToElementTypeMap)[kImageElement] = IMAGE; | 329 (*kElementNameToElementTypeMap)[kImageElement] = IMAGE; |
326 (*kElementNameToElementTypeMap)[kOpenSearchDescriptionElement] = | 330 (*kElementNameToElementTypeMap)[kOpenSearchDescriptionElement] = |
(...skipping 19 matching lines...) Expand all Loading... |
346 is_html_url = (type == kHTMLType); | 350 is_html_url = (type == kHTMLType); |
347 is_suggest_url = (type == kSuggestionType); | 351 is_suggest_url = (type == kSuggestionType); |
348 } else if (name == kURLTemplateAttribute) { | 352 } else if (name == kURLTemplateAttribute) { |
349 template_url = XMLCharToString(value); | 353 template_url = XMLCharToString(value); |
350 } else if (name == kParamMethodAttribute) { | 354 } else if (name == kParamMethodAttribute) { |
351 is_post = LowerCaseEqualsASCII(XMLCharToString(value), "post"); | 355 is_post = LowerCaseEqualsASCII(XMLCharToString(value), "post"); |
352 } | 356 } |
353 } | 357 } |
354 | 358 |
355 if (is_html_url && !template_url.empty()) { | 359 if (is_html_url && !template_url.empty()) { |
356 url_->SetURL(template_url); | 360 data_.SetURL(template_url); |
357 is_suggest_url_ = false; | 361 is_suggest_url_ = false; |
358 if (is_post) | 362 if (is_post) |
359 method_ = POST; | 363 method_ = POST; |
360 } else if (is_suggest_url) { | 364 } else if (is_suggest_url) { |
361 url_->SetSuggestionsURL(template_url); | 365 data_.suggestions_url = template_url; |
362 is_suggest_url_ = true; | 366 is_suggest_url_ = true; |
363 if (is_post) | 367 if (is_post) |
364 suggestion_method_ = POST; | 368 suggestion_method_ = POST; |
365 } | 369 } |
366 } | 370 } |
367 | 371 |
368 void TemplateURLParsingContext::ParseImage(const xmlChar** atts) { | 372 void TemplateURLParsingContext::ParseImage(const xmlChar** atts) { |
369 if (!atts) | 373 if (!atts) |
370 return; | 374 return; |
371 | 375 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 | 410 |
407 if (!key.empty() && | 411 if (!key.empty() && |
408 (!parameter_filter_ || parameter_filter_->KeepParameter(key, value))) | 412 (!parameter_filter_ || parameter_filter_->KeepParameter(key, value))) |
409 extra_params_.push_back(Param(key, value)); | 413 extra_params_.push_back(Param(key, value)); |
410 } | 414 } |
411 | 415 |
412 void TemplateURLParsingContext::ProcessURLParams() { | 416 void TemplateURLParsingContext::ProcessURLParams() { |
413 if (!parameter_filter_ && extra_params_.empty()) | 417 if (!parameter_filter_ && extra_params_.empty()) |
414 return; | 418 return; |
415 | 419 |
416 GURL url(is_suggest_url_ ? url_->suggestions_url() : url_->url()); | 420 GURL url(is_suggest_url_ ? data_.suggestions_url : data_.url()); |
417 if (url.is_empty()) | 421 if (url.is_empty()) |
418 return; | 422 return; |
419 | 423 |
420 // If there is a parameter filter, parse the existing URL and remove any | 424 // If there is a parameter filter, parse the existing URL and remove any |
421 // unwanted parameter. | 425 // unwanted parameter. |
422 std::string new_query; | 426 std::string new_query; |
423 bool modified = false; | 427 bool modified = false; |
424 if (parameter_filter_) { | 428 if (parameter_filter_) { |
425 url_parse::Component query = url.parsed_for_possibly_invalid_spec().query; | 429 url_parse::Component query = url.parsed_for_possibly_invalid_spec().query; |
426 url_parse::Component key, value; | 430 url_parse::Component key, value; |
(...skipping 17 matching lines...) Expand all Loading... |
444 for (std::vector<Param>::const_iterator iter(extra_params_.begin()); | 448 for (std::vector<Param>::const_iterator iter(extra_params_.begin()); |
445 iter != extra_params_.end(); ++iter) | 449 iter != extra_params_.end(); ++iter) |
446 AppendParamToQuery(iter->first, iter->second, &new_query); | 450 AppendParamToQuery(iter->first, iter->second, &new_query); |
447 } | 451 } |
448 | 452 |
449 if (modified) { | 453 if (modified) { |
450 GURL::Replacements repl; | 454 GURL::Replacements repl; |
451 repl.SetQueryStr(new_query); | 455 repl.SetQueryStr(new_query); |
452 url = url.ReplaceComponents(repl); | 456 url = url.ReplaceComponents(repl); |
453 if (is_suggest_url_) | 457 if (is_suggest_url_) |
454 url_->SetSuggestionsURL(url.spec()); | 458 data_.suggestions_url = url.spec(); |
455 else if (url.is_valid()) | 459 else if (url.is_valid()) |
456 url_->SetURL(url.spec()); | 460 data_.SetURL(url.spec()); |
457 } | 461 } |
458 } | 462 } |
459 | 463 |
460 TemplateURLParsingContext::ElementType | 464 TemplateURLParsingContext::ElementType |
461 TemplateURLParsingContext::GetKnownType() { | 465 TemplateURLParsingContext::GetKnownType() { |
462 if (elements_.size() == 2 && elements_[0] == OPEN_SEARCH_DESCRIPTION) | 466 if (elements_.size() == 2 && elements_[0] == OPEN_SEARCH_DESCRIPTION) |
463 return elements_[1]; | 467 return elements_[1]; |
464 // We only expect PARAM nodes under the URL node. | 468 // We only expect PARAM nodes under the URL node. |
465 return (elements_.size() == 3 && elements_[0] == OPEN_SEARCH_DESCRIPTION && | 469 return (elements_.size() == 3 && elements_[0] == OPEN_SEARCH_DESCRIPTION && |
466 elements_[1] == URL && elements_[2] == PARAM) ? PARAM : UNKNOWN; | 470 elements_[1] == URL && elements_[2] == PARAM) ? PARAM : UNKNOWN; |
467 } | 471 } |
468 | 472 |
469 | 473 |
470 // TemplateURLParser ---------------------------------------------------------- | 474 // TemplateURLParser ---------------------------------------------------------- |
471 | 475 |
472 // static | 476 // static |
473 TemplateURL* TemplateURLParser::Parse( | 477 TemplateURL* TemplateURLParser::Parse( |
474 Profile* profile, | 478 Profile* profile, |
| 479 bool show_in_default_list, |
475 const char* data, | 480 const char* data, |
476 size_t length, | 481 size_t length, |
477 TemplateURLParser::ParameterFilter* param_filter) { | 482 TemplateURLParser::ParameterFilter* param_filter) { |
478 // xmlSubstituteEntitiesDefault(1) makes it so that & isn't mapped to | 483 // xmlSubstituteEntitiesDefault(1) makes it so that & isn't mapped to |
479 // & . Unfortunately xmlSubstituteEntitiesDefault affects global state. | 484 // & . Unfortunately xmlSubstituteEntitiesDefault affects global state. |
480 // If this becomes problematic we'll need to provide our own entity | 485 // If this becomes problematic we'll need to provide our own entity |
481 // type for &, or strip out & by hand after parsing. | 486 // type for &, or strip out & by hand after parsing. |
482 int last_sub_entities_value = xmlSubstituteEntitiesDefault(1); | 487 int last_sub_entities_value = xmlSubstituteEntitiesDefault(1); |
483 TemplateURLParsingContext context(param_filter); | 488 TemplateURLParsingContext context(param_filter); |
484 xmlSAXHandler sax_handler; | 489 xmlSAXHandler sax_handler; |
485 memset(&sax_handler, 0, sizeof(sax_handler)); | 490 memset(&sax_handler, 0, sizeof(sax_handler)); |
486 sax_handler.startElement = &TemplateURLParsingContext::StartElementImpl; | 491 sax_handler.startElement = &TemplateURLParsingContext::StartElementImpl; |
487 sax_handler.endElement = &TemplateURLParsingContext::EndElementImpl; | 492 sax_handler.endElement = &TemplateURLParsingContext::EndElementImpl; |
488 sax_handler.characters = &TemplateURLParsingContext::CharactersImpl; | 493 sax_handler.characters = &TemplateURLParsingContext::CharactersImpl; |
489 xmlSAXUserParseMemory(&sax_handler, &context, data, static_cast<int>(length)); | 494 xmlSAXUserParseMemory(&sax_handler, &context, data, static_cast<int>(length)); |
490 xmlSubstituteEntitiesDefault(last_sub_entities_value); | 495 xmlSubstituteEntitiesDefault(last_sub_entities_value); |
491 | 496 |
492 return context.GetTemplateURL(profile); | 497 return context.GetTemplateURL(profile, show_in_default_list); |
493 } | 498 } |
OLD | NEW |