| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights
reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights |
| 3 * reserved. |
| 3 * Copyright (C) 2009, 2010 Google Inc. All rights reserved. | 4 * Copyright (C) 2009, 2010 Google Inc. All rights reserved. |
| 4 * | 5 * |
| 5 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
| 7 * are met: | 8 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 11 * 2. Redistributions in binary form must reproduce the above copyright |
| 11 * notice, this list of conditions and the following disclaimer in the | 12 * notice, this list of conditions and the following disclaimer in the |
| 12 * documentation and/or other materials provided with the distribution. | 13 * documentation and/or other materials provided with the distribution. |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 strippedURLString.replace('"', """); | 228 strippedURLString.replace('"', """); |
| 228 else | 229 else |
| 229 quoteChar = '\''; | 230 quoteChar = '\''; |
| 230 } | 231 } |
| 231 result.append(quoteChar); | 232 result.append(quoteChar); |
| 232 result.append(strippedURLString); | 233 result.append(strippedURLString); |
| 233 result.append(quoteChar); | 234 result.append(quoteChar); |
| 234 return; | 235 return; |
| 235 } | 236 } |
| 236 | 237 |
| 237 // FIXME: This does not fully match other browsers. Firefox percent-escapes no
n-ASCII characters for innerHTML. | 238 // FIXME: This does not fully match other browsers. Firefox percent-escapes |
| 239 // non-ASCII characters for innerHTML. |
| 238 result.append(quoteChar); | 240 result.append(quoteChar); |
| 239 appendAttributeValue(result, resolvedURLString, false); | 241 appendAttributeValue(result, resolvedURLString, false); |
| 240 result.append(quoteChar); | 242 result.append(quoteChar); |
| 241 } | 243 } |
| 242 | 244 |
| 243 void MarkupFormatter::appendNamespace(StringBuilder& result, | 245 void MarkupFormatter::appendNamespace(StringBuilder& result, |
| 244 const AtomicString& prefix, | 246 const AtomicString& prefix, |
| 245 const AtomicString& namespaceURI, | 247 const AtomicString& namespaceURI, |
| 246 Namespaces& namespaces) { | 248 Namespaces& namespaces) { |
| 247 if (namespaceURI.isEmpty()) | 249 if (namespaceURI.isEmpty()) |
| (...skipping 17 matching lines...) Expand all Loading... |
| 265 } | 267 } |
| 266 | 268 |
| 267 void MarkupFormatter::appendText(StringBuilder& result, Text& text) { | 269 void MarkupFormatter::appendText(StringBuilder& result, Text& text) { |
| 268 const String& str = text.data(); | 270 const String& str = text.data(); |
| 269 appendCharactersReplacingEntities(result, str, 0, str.length(), | 271 appendCharactersReplacingEntities(result, str, 0, str.length(), |
| 270 entityMaskForText(text)); | 272 entityMaskForText(text)); |
| 271 } | 273 } |
| 272 | 274 |
| 273 void MarkupFormatter::appendComment(StringBuilder& result, | 275 void MarkupFormatter::appendComment(StringBuilder& result, |
| 274 const String& comment) { | 276 const String& comment) { |
| 275 // FIXME: Comment content is not escaped, but XMLSerializer (and possibly othe
r callers) should raise an exception if it includes "-->". | 277 // FIXME: Comment content is not escaped, but XMLSerializer (and possibly |
| 278 // other callers) should raise an exception if it includes "-->". |
| 276 result.append("<!--"); | 279 result.append("<!--"); |
| 277 result.append(comment); | 280 result.append(comment); |
| 278 result.append("-->"); | 281 result.append("-->"); |
| 279 } | 282 } |
| 280 | 283 |
| 281 void MarkupFormatter::appendXMLDeclaration(StringBuilder& result, | 284 void MarkupFormatter::appendXMLDeclaration(StringBuilder& result, |
| 282 const Document& document) { | 285 const Document& document) { |
| 283 if (!document.hasXMLDeclaration()) | 286 if (!document.hasXMLDeclaration()) |
| 284 return; | 287 return; |
| 285 | 288 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 result.append(" SYSTEM \""); | 324 result.append(" SYSTEM \""); |
| 322 result.append(n.systemId()); | 325 result.append(n.systemId()); |
| 323 result.append('"'); | 326 result.append('"'); |
| 324 } | 327 } |
| 325 result.append('>'); | 328 result.append('>'); |
| 326 } | 329 } |
| 327 | 330 |
| 328 void MarkupFormatter::appendProcessingInstruction(StringBuilder& result, | 331 void MarkupFormatter::appendProcessingInstruction(StringBuilder& result, |
| 329 const String& target, | 332 const String& target, |
| 330 const String& data) { | 333 const String& data) { |
| 331 // FIXME: PI data is not escaped, but XMLSerializer (and possibly other caller
s) this should raise an exception if it includes "?>". | 334 // FIXME: PI data is not escaped, but XMLSerializer (and possibly other |
| 335 // callers) this should raise an exception if it includes "?>". |
| 332 result.append("<?"); | 336 result.append("<?"); |
| 333 result.append(target); | 337 result.append(target); |
| 334 result.append(' '); | 338 result.append(' '); |
| 335 result.append(data); | 339 result.append(data); |
| 336 result.append("?>"); | 340 result.append("?>"); |
| 337 } | 341 } |
| 338 | 342 |
| 339 void MarkupFormatter::appendOpenTag(StringBuilder& result, | 343 void MarkupFormatter::appendOpenTag(StringBuilder& result, |
| 340 const Element& element, | 344 const Element& element, |
| 341 Namespaces* namespaces) { | 345 Namespaces* namespaces) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 371 bool documentIsHTML = serializeAsHTMLDocument(element); | 375 bool documentIsHTML = serializeAsHTMLDocument(element); |
| 372 | 376 |
| 373 QualifiedName prefixedName = attribute.name(); | 377 QualifiedName prefixedName = attribute.name(); |
| 374 if (documentIsHTML && !attributeIsInSerializedNamespace(attribute)) { | 378 if (documentIsHTML && !attributeIsInSerializedNamespace(attribute)) { |
| 375 result.append(' '); | 379 result.append(' '); |
| 376 result.append(attribute.name().localName()); | 380 result.append(attribute.name().localName()); |
| 377 } else { | 381 } else { |
| 378 if (attribute.namespaceURI() == XMLNSNames::xmlnsNamespaceURI) { | 382 if (attribute.namespaceURI() == XMLNSNames::xmlnsNamespaceURI) { |
| 379 if (!attribute.prefix() && attribute.localName() != xmlnsAtom) | 383 if (!attribute.prefix() && attribute.localName() != xmlnsAtom) |
| 380 prefixedName.setPrefix(xmlnsAtom); | 384 prefixedName.setPrefix(xmlnsAtom); |
| 381 if (namespaces) { // Account for the namespace attribute we're about to a
ppend. | 385 // Account for the namespace attribute we're about to append. |
| 386 if (namespaces) { |
| 382 const AtomicString& lookupKey = | 387 const AtomicString& lookupKey = |
| 383 (!attribute.prefix()) ? emptyAtom : attribute.localName(); | 388 (!attribute.prefix()) ? emptyAtom : attribute.localName(); |
| 384 namespaces->set(lookupKey, attribute.value()); | 389 namespaces->set(lookupKey, attribute.value()); |
| 385 } | 390 } |
| 386 } else if (attribute.namespaceURI() == XMLNames::xmlNamespaceURI) { | 391 } else if (attribute.namespaceURI() == XMLNames::xmlNamespaceURI) { |
| 387 if (!attribute.prefix()) | 392 if (!attribute.prefix()) |
| 388 prefixedName.setPrefix(xmlAtom); | 393 prefixedName.setPrefix(xmlAtom); |
| 389 } else { | 394 } else { |
| 390 if (attribute.namespaceURI() == XLinkNames::xlinkNamespaceURI) { | 395 if (attribute.namespaceURI() == XLinkNames::xlinkNamespaceURI) { |
| 391 if (!attribute.prefix()) | 396 if (!attribute.prefix()) |
| 392 prefixedName.setPrefix(xlinkAtom); | 397 prefixedName.setPrefix(xlinkAtom); |
| 393 } | 398 } |
| 394 | 399 |
| 395 if (namespaces && shouldAddNamespaceAttribute(attribute, element)) { | 400 if (namespaces && shouldAddNamespaceAttribute(attribute, element)) { |
| 396 if (!prefixedName.prefix()) { | 401 if (!prefixedName.prefix()) { |
| 397 // This behavior is in process of being standardized. See crbug.com/24
8044 and https://www.w3.org/Bugs/Public/show_bug.cgi?id=24208 | 402 // This behavior is in process of being standardized. See |
| 403 // crbug.com/248044 and |
| 404 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=24208 |
| 398 String prefixPrefix("ns", 2); | 405 String prefixPrefix("ns", 2); |
| 399 for (unsigned i = attribute.namespaceURI().impl()->existingHash();; | 406 for (unsigned i = attribute.namespaceURI().impl()->existingHash();; |
| 400 ++i) { | 407 ++i) { |
| 401 AtomicString newPrefix(String(prefixPrefix + String::number(i))); | 408 AtomicString newPrefix(String(prefixPrefix + String::number(i))); |
| 402 AtomicString foundURI = namespaces->get(newPrefix); | 409 AtomicString foundURI = namespaces->get(newPrefix); |
| 403 if (foundURI == attribute.namespaceURI() || foundURI == nullAtom) { | 410 if (foundURI == attribute.namespaceURI() || foundURI == nullAtom) { |
| 404 // We already generated a prefix for this namespace. | 411 // We already generated a prefix for this namespace. |
| 405 prefixedName.setPrefix(newPrefix); | 412 prefixedName.setPrefix(newPrefix); |
| 406 break; | 413 break; |
| 407 } | 414 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 422 appendQuotedURLAttributeValue(result, element, attribute); | 429 appendQuotedURLAttributeValue(result, element, attribute); |
| 423 } else { | 430 } else { |
| 424 result.append('"'); | 431 result.append('"'); |
| 425 appendAttributeValue(result, attribute.value(), documentIsHTML); | 432 appendAttributeValue(result, attribute.value(), documentIsHTML); |
| 426 result.append('"'); | 433 result.append('"'); |
| 427 } | 434 } |
| 428 } | 435 } |
| 429 | 436 |
| 430 void MarkupFormatter::appendCDATASection(StringBuilder& result, | 437 void MarkupFormatter::appendCDATASection(StringBuilder& result, |
| 431 const String& section) { | 438 const String& section) { |
| 432 // FIXME: CDATA content is not escaped, but XMLSerializer (and possibly other
callers) should raise an exception if it includes "]]>". | 439 // FIXME: CDATA content is not escaped, but XMLSerializer (and possibly other |
| 440 // callers) should raise an exception if it includes "]]>". |
| 433 result.append("<![CDATA["); | 441 result.append("<![CDATA["); |
| 434 result.append(section); | 442 result.append(section); |
| 435 result.append("]]>"); | 443 result.append("]]>"); |
| 436 } | 444 } |
| 437 | 445 |
| 438 bool MarkupFormatter::shouldAddNamespaceElement(const Element& element, | 446 bool MarkupFormatter::shouldAddNamespaceElement(const Element& element, |
| 439 Namespaces& namespaces) const { | 447 Namespaces& namespaces) const { |
| 440 // Don't add namespace attribute if it is already defined for this elem. | 448 // Don't add namespace attribute if it is already defined for this elem. |
| 441 const AtomicString& prefix = element.prefix(); | 449 const AtomicString& prefix = element.prefix(); |
| 442 if (prefix.isEmpty()) { | 450 if (prefix.isEmpty()) { |
| 443 if (element.hasAttribute(xmlnsAtom)) { | 451 if (element.hasAttribute(xmlnsAtom)) { |
| 444 namespaces.set(emptyAtom, element.namespaceURI()); | 452 namespaces.set(emptyAtom, element.namespaceURI()); |
| 445 return false; | 453 return false; |
| 446 } | 454 } |
| 447 return true; | 455 return true; |
| 448 } | 456 } |
| 449 | 457 |
| 450 return !element.hasAttribute(WTF::xmlnsWithColon + prefix); | 458 return !element.hasAttribute(WTF::xmlnsWithColon + prefix); |
| 451 } | 459 } |
| 452 | 460 |
| 453 bool MarkupFormatter::shouldAddNamespaceAttribute( | 461 bool MarkupFormatter::shouldAddNamespaceAttribute( |
| 454 const Attribute& attribute, | 462 const Attribute& attribute, |
| 455 const Element& element) const { | 463 const Element& element) const { |
| 456 // xmlns and xmlns:prefix attributes should be handled by another branch in ap
pendAttribute. | 464 // xmlns and xmlns:prefix attributes should be handled by another branch in |
| 465 // appendAttribute. |
| 457 DCHECK_NE(attribute.namespaceURI(), XMLNSNames::xmlnsNamespaceURI); | 466 DCHECK_NE(attribute.namespaceURI(), XMLNSNames::xmlnsNamespaceURI); |
| 458 | 467 |
| 459 // Attributes are in the null namespace by default. | 468 // Attributes are in the null namespace by default. |
| 460 if (!attribute.namespaceURI()) | 469 if (!attribute.namespaceURI()) |
| 461 return false; | 470 return false; |
| 462 | 471 |
| 463 // Attributes without a prefix will need one generated for them, and an xmlns
attribute for that prefix. | 472 // Attributes without a prefix will need one generated for them, and an xmlns |
| 473 // attribute for that prefix. |
| 464 if (!attribute.prefix()) | 474 if (!attribute.prefix()) |
| 465 return true; | 475 return true; |
| 466 | 476 |
| 467 return !element.hasAttribute(WTF::xmlnsWithColon + attribute.prefix()); | 477 return !element.hasAttribute(WTF::xmlnsWithColon + attribute.prefix()); |
| 468 } | 478 } |
| 469 | 479 |
| 470 EntityMask MarkupFormatter::entityMaskForText(const Text& text) const { | 480 EntityMask MarkupFormatter::entityMaskForText(const Text& text) const { |
| 471 if (!serializeAsHTMLDocument(text)) | 481 if (!serializeAsHTMLDocument(text)) |
| 472 return EntityMaskInPCDATA; | 482 return EntityMaskInPCDATA; |
| 473 | 483 |
| 474 // TODO(hajimehoshi): We need to switch EditingStrategy. | 484 // TODO(hajimehoshi): We need to switch EditingStrategy. |
| 475 const QualifiedName* parentName = nullptr; | 485 const QualifiedName* parentName = nullptr; |
| 476 if (text.parentElement()) | 486 if (text.parentElement()) |
| 477 parentName = &(text.parentElement())->tagQName(); | 487 parentName = &(text.parentElement())->tagQName(); |
| 478 | 488 |
| 479 if (parentName && (*parentName == scriptTag || *parentName == styleTag || | 489 if (parentName && (*parentName == scriptTag || *parentName == styleTag || |
| 480 *parentName == xmpTag)) | 490 *parentName == xmpTag)) |
| 481 return EntityMaskInCDATA; | 491 return EntityMaskInCDATA; |
| 482 return EntityMaskInHTMLPCDATA; | 492 return EntityMaskInHTMLPCDATA; |
| 483 } | 493 } |
| 484 | 494 |
| 485 // Rules of self-closure | 495 // Rules of self-closure |
| 486 // 1. No elements in HTML documents use the self-closing syntax. | 496 // 1. No elements in HTML documents use the self-closing syntax. |
| 487 // 2. Elements w/ children never self-close because they use a separate end tag. | 497 // 2. Elements w/ children never self-close because they use a separate end tag. |
| 488 // 3. HTML elements which do not have a "forbidden" end tag will close with a se
parate end tag. | 498 // 3. HTML elements which do not have a "forbidden" end tag will close with a |
| 499 // separate end tag. |
| 489 // 4. Other elements self-close. | 500 // 4. Other elements self-close. |
| 490 bool MarkupFormatter::shouldSelfClose(const Element& element) const { | 501 bool MarkupFormatter::shouldSelfClose(const Element& element) const { |
| 491 if (serializeAsHTMLDocument(element)) | 502 if (serializeAsHTMLDocument(element)) |
| 492 return false; | 503 return false; |
| 493 if (element.hasChildren()) | 504 if (element.hasChildren()) |
| 494 return false; | 505 return false; |
| 495 if (element.isHTMLElement() && !elementCannotHaveEndTag(element)) | 506 if (element.isHTMLElement() && !elementCannotHaveEndTag(element)) |
| 496 return false; | 507 return false; |
| 497 return true; | 508 return true; |
| 498 } | 509 } |
| 499 | 510 |
| 500 bool MarkupFormatter::serializeAsHTMLDocument(const Node& node) const { | 511 bool MarkupFormatter::serializeAsHTMLDocument(const Node& node) const { |
| 501 if (m_serializationType == SerializationType::ForcedXML) | 512 if (m_serializationType == SerializationType::ForcedXML) |
| 502 return false; | 513 return false; |
| 503 return node.document().isHTMLDocument(); | 514 return node.document().isHTMLDocument(); |
| 504 } | 515 } |
| 505 | 516 |
| 506 } // namespace blink | 517 } // namespace blink |
| OLD | NEW |