| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde
.org> | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde
.org> |
| 3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> | 3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org> |
| 4 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. | 4 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. |
| 5 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved. | 5 * Copyright (C) 2011 Torch Mobile (Beijing) Co. Ltd. All rights reserved. |
| 6 * Copyright (C) 2012 University of Szeged | 6 * Copyright (C) 2012 University of Szeged |
| 7 * Copyright (C) 2012 Renata Hodovan <reni@webkit.org> | 7 * Copyright (C) 2012 Renata Hodovan <reni@webkit.org> |
| 8 * | 8 * |
| 9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
| 10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 } | 246 } |
| 247 | 247 |
| 248 invalidateShadowTree(); | 248 invalidateShadowTree(); |
| 249 | 249 |
| 250 return; | 250 return; |
| 251 } | 251 } |
| 252 | 252 |
| 253 SVGGraphicsElement::svgAttributeChanged(attrName); | 253 SVGGraphicsElement::svgAttributeChanged(attrName); |
| 254 } | 254 } |
| 255 | 255 |
| 256 static bool isDisallowedElement(const Node* node) | 256 static bool isDisallowedElement(const Node& node) |
| 257 { | 257 { |
| 258 // Spec: "Any 'svg', 'symbol', 'g', graphics element or other 'use' is poten
tially a template object that can be re-used | 258 // Spec: "Any 'svg', 'symbol', 'g', graphics element or other 'use' is poten
tially a template object that can be re-used |
| 259 // (i.e., "instanced") in the SVG document via a 'use' element." | 259 // (i.e., "instanced") in the SVG document via a 'use' element." |
| 260 // "Graphics Element" is defined as 'circle', 'ellipse', 'image', 'line', 'p
ath', 'polygon', 'polyline', 'rect', 'text' | 260 // "Graphics Element" is defined as 'circle', 'ellipse', 'image', 'line', 'p
ath', 'polygon', 'polyline', 'rect', 'text' |
| 261 // Excluded are anything that is used by reference or that only make sense t
o appear once in a document. | 261 // Excluded are anything that is used by reference or that only make sense t
o appear once in a document. |
| 262 // We must also allow the shadow roots of other use elements. | 262 // We must also allow the shadow roots of other use elements. |
| 263 if (node->isShadowRoot() || node->isTextNode()) | 263 if (node.isShadowRoot() || node.isTextNode()) |
| 264 return false; | 264 return false; |
| 265 | 265 |
| 266 if (!node->isSVGElement()) | 266 if (!node.isSVGElement()) |
| 267 return true; | 267 return true; |
| 268 | 268 |
| 269 const Element* element = toElement(node); | 269 const Element& element = toElement(node); |
| 270 | 270 |
| 271 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, allowedElementTags, ()); | 271 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, allowedElementTags, ()); |
| 272 if (allowedElementTags.isEmpty()) { | 272 if (allowedElementTags.isEmpty()) { |
| 273 allowedElementTags.add(SVGNames::aTag); | 273 allowedElementTags.add(SVGNames::aTag); |
| 274 allowedElementTags.add(SVGNames::circleTag); | 274 allowedElementTags.add(SVGNames::circleTag); |
| 275 allowedElementTags.add(SVGNames::descTag); | 275 allowedElementTags.add(SVGNames::descTag); |
| 276 allowedElementTags.add(SVGNames::ellipseTag); | 276 allowedElementTags.add(SVGNames::ellipseTag); |
| 277 allowedElementTags.add(SVGNames::gTag); | 277 allowedElementTags.add(SVGNames::gTag); |
| 278 allowedElementTags.add(SVGNames::imageTag); | 278 allowedElementTags.add(SVGNames::imageTag); |
| 279 allowedElementTags.add(SVGNames::lineTag); | 279 allowedElementTags.add(SVGNames::lineTag); |
| 280 allowedElementTags.add(SVGNames::metadataTag); | 280 allowedElementTags.add(SVGNames::metadataTag); |
| 281 allowedElementTags.add(SVGNames::pathTag); | 281 allowedElementTags.add(SVGNames::pathTag); |
| 282 allowedElementTags.add(SVGNames::polygonTag); | 282 allowedElementTags.add(SVGNames::polygonTag); |
| 283 allowedElementTags.add(SVGNames::polylineTag); | 283 allowedElementTags.add(SVGNames::polylineTag); |
| 284 allowedElementTags.add(SVGNames::rectTag); | 284 allowedElementTags.add(SVGNames::rectTag); |
| 285 allowedElementTags.add(SVGNames::svgTag); | 285 allowedElementTags.add(SVGNames::svgTag); |
| 286 allowedElementTags.add(SVGNames::switchTag); | 286 allowedElementTags.add(SVGNames::switchTag); |
| 287 allowedElementTags.add(SVGNames::symbolTag); | 287 allowedElementTags.add(SVGNames::symbolTag); |
| 288 allowedElementTags.add(SVGNames::textTag); | 288 allowedElementTags.add(SVGNames::textTag); |
| 289 allowedElementTags.add(SVGNames::textPathTag); | 289 allowedElementTags.add(SVGNames::textPathTag); |
| 290 allowedElementTags.add(SVGNames::titleTag); | 290 allowedElementTags.add(SVGNames::titleTag); |
| 291 allowedElementTags.add(SVGNames::tspanTag); | 291 allowedElementTags.add(SVGNames::tspanTag); |
| 292 allowedElementTags.add(SVGNames::useTag); | 292 allowedElementTags.add(SVGNames::useTag); |
| 293 } | 293 } |
| 294 return !allowedElementTags.contains<SVGAttributeHashTranslator>(element->tag
QName()); | 294 return !allowedElementTags.contains<SVGAttributeHashTranslator>(element.tagQ
Name()); |
| 295 } | |
| 296 | |
| 297 static bool subtreeContainsDisallowedElement(const Node* start) | |
| 298 { | |
| 299 if (isDisallowedElement(start)) | |
| 300 return true; | |
| 301 | |
| 302 for (const Node* cur = start->firstChild(); cur; cur = cur->nextSibling()) { | |
| 303 if (subtreeContainsDisallowedElement(cur)) | |
| 304 return true; | |
| 305 } | |
| 306 | |
| 307 return false; | |
| 308 } | 295 } |
| 309 | 296 |
| 310 void SVGUseElement::scheduleShadowTreeRecreation() | 297 void SVGUseElement::scheduleShadowTreeRecreation() |
| 311 { | 298 { |
| 312 if (inUseShadowTree()) | 299 if (inUseShadowTree()) |
| 313 return; | 300 return; |
| 314 m_needsShadowTreeRecreation = true; | 301 m_needsShadowTreeRecreation = true; |
| 315 document().scheduleUseShadowTreeUpdate(*this); | 302 document().scheduleUseShadowTreeUpdate(*this); |
| 316 } | 303 } |
| 317 | 304 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 ASSERT(!m_needsShadowTreeRecreation); | 378 ASSERT(!m_needsShadowTreeRecreation); |
| 392 | 379 |
| 393 // <use> creates a "user agent" shadow root. Do not build the shadow/instanc
e tree for <use> | 380 // <use> creates a "user agent" shadow root. Do not build the shadow/instanc
e tree for <use> |
| 394 // elements living in a user agent shadow tree because they will get expande
d in a second | 381 // elements living in a user agent shadow tree because they will get expande
d in a second |
| 395 // pass -- see expandUseElementsInShadowTree(). | 382 // pass -- see expandUseElementsInShadowTree(). |
| 396 if (inUseShadowTree()) | 383 if (inUseShadowTree()) |
| 397 return; | 384 return; |
| 398 | 385 |
| 399 // Do not allow self-referencing. | 386 // Do not allow self-referencing. |
| 400 // 'target' may be null, if it's a non SVG namespaced element. | 387 // 'target' may be null, if it's a non SVG namespaced element. |
| 401 if (!target || target == this || isDisallowedElement(target)) | 388 if (!target || target == this || isDisallowedElement(*target)) |
| 402 return; | 389 return; |
| 403 | 390 |
| 404 // Set up root SVG element in shadow tree. | 391 // Set up root SVG element in shadow tree. |
| 405 RefPtrWillBeRawPtr<Element> newChild = target->cloneElementWithoutChildren()
; | 392 RefPtrWillBeRawPtr<Element> newChild = target->cloneElementWithoutChildren()
; |
| 406 m_targetElementInstance = toSVGElement(newChild.get()); | 393 m_targetElementInstance = toSVGElement(newChild.get()); |
| 407 ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); | 394 ShadowRoot* shadowTreeRootElement = userAgentShadowRoot(); |
| 408 shadowTreeRootElement->appendChild(newChild.release()); | 395 shadowTreeRootElement->appendChild(newChild.release()); |
| 409 | 396 |
| 410 // Clone the target subtree into the shadow tree, not handling <use> and <sy
mbol> yet. | 397 // Clone the target subtree into the shadow tree, not handling <use> and <sy
mbol> yet. |
| 411 | 398 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 return nullptr; | 486 return nullptr; |
| 500 } | 487 } |
| 501 | 488 |
| 502 return &toSVGGraphicsElement(element); | 489 return &toSVGGraphicsElement(element); |
| 503 } | 490 } |
| 504 | 491 |
| 505 void SVGUseElement::buildShadowTree(SVGElement* target, SVGElement* targetInstan
ce, bool foundUse) | 492 void SVGUseElement::buildShadowTree(SVGElement* target, SVGElement* targetInstan
ce, bool foundUse) |
| 506 { | 493 { |
| 507 ASSERT(target); | 494 ASSERT(target); |
| 508 ASSERT(targetInstance); | 495 ASSERT(targetInstance); |
| 509 ASSERT(!isDisallowedElement(target)); | 496 ASSERT(!isDisallowedElement(*target)); |
| 510 | 497 |
| 511 // Spec: If the referenced object is itself a 'use', or if there are 'use' s
ubelements within the referenced | 498 // Spec: If the referenced object is itself a 'use', or if there are 'use' s
ubelements within the referenced |
| 512 // object, the instance tree will contain recursive expansion of the indirec
t references to form a complete tree. | 499 // object, the instance tree will contain recursive expansion of the indirec
t references to form a complete tree. |
| 513 if (isSVGUseElement(*target)) { | 500 if (isSVGUseElement(*target)) { |
| 514 // We only need to track first degree <use> dependencies. Indirect refer
ences are handled | 501 // We only need to track first degree <use> dependencies. Indirect refer
ences are handled |
| 515 // as the invalidation bubbles up the dependency chain. | 502 // as the invalidation bubbles up the dependency chain. |
| 516 if (!foundUse && !isStructurallyExternal()) { | 503 if (!foundUse && !isStructurallyExternal()) { |
| 517 addReferenceTo(target); | 504 addReferenceTo(target); |
| 518 foundUse = true; | 505 foundUse = true; |
| 519 } | 506 } |
| 520 } | 507 } |
| 521 | 508 |
| 522 targetInstance->setCorrespondingElement(target); | 509 targetInstance->setCorrespondingElement(target); |
| 523 | 510 |
| 524 for (RefPtrWillBeRawPtr<Node> child = target->firstChild(); child; child = c
hild->nextSibling()) { | 511 for (RefPtrWillBeRawPtr<Node> child = target->firstChild(); child; child = c
hild->nextSibling()) { |
| 525 // Skip any disallowed element. | 512 // Skip any disallowed element. |
| 526 if (isDisallowedElement(child.get())) | 513 if (isDisallowedElement(*child)) |
| 527 continue; | 514 continue; |
| 528 | 515 |
| 529 RefPtrWillBeRawPtr<Node> newChild = child->cloneNode(false); | 516 RefPtrWillBeRawPtr<Node> newChild = child->cloneNode(false); |
| 530 targetInstance->appendChild(newChild.get()); | 517 targetInstance->appendChild(newChild.get()); |
| 531 if (newChild->isSVGElement()) { | 518 if (newChild->isSVGElement()) { |
| 532 // Enter recursion, appending new instance tree nodes to the "instan
ce" object. | 519 // Enter recursion, appending new instance tree nodes to the "instan
ce" object. |
| 533 buildShadowTree(toSVGElement(child), toSVGElement(newChild), foundUs
e); | 520 buildShadowTree(toSVGElement(child), toSVGElement(newChild), foundUs
e); |
| 534 } | 521 } |
| 535 } | 522 } |
| 536 } | 523 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 563 while (instance && instance->isSVGElement()) { | 550 while (instance && instance->isSVGElement()) { |
| 564 SVGElement* element = toSVGElement(instance); | 551 SVGElement* element = toSVGElement(instance); |
| 565 if (element->hasID() && element->getIdAttribute() == targetId && element
->document() == newTarget->document()) | 552 if (element->hasID() && element->getIdAttribute() == targetId && element
->document() == newTarget->document()) |
| 566 return true; | 553 return true; |
| 567 | 554 |
| 568 instance = instance->parentNode(); | 555 instance = instance->parentNode(); |
| 569 } | 556 } |
| 570 return false; | 557 return false; |
| 571 } | 558 } |
| 572 | 559 |
| 573 static inline void removeDisallowedElementsFromSubtree(Element& subtree) | 560 // We don't walk the target tree element-by-element, and clone each element, |
| 561 // but instead use cloneNode(deep=true). This is an optimization for the common |
| 562 // case where <use> doesn't contain disallowed elements (ie. <foreignObject>). |
| 563 // Though if there are disallowed elements in the subtree, we have to remove |
| 564 // them. For instance: <use> on <g> containing <foreignObject> (indirect |
| 565 // case). |
| 566 static inline void removeDisallowedElementsFromSubtree(SVGElement& subtree) |
| 574 { | 567 { |
| 575 ASSERT(!subtree.inDocument()); | 568 ASSERT(!subtree.inDocument()); |
| 576 Element* element = ElementTraversal::firstWithin(subtree); | 569 Element* element = ElementTraversal::firstWithin(subtree); |
| 577 while (element) { | 570 while (element) { |
| 578 if (isDisallowedElement(element)) { | 571 if (isDisallowedElement(*element)) { |
| 579 Element* next = ElementTraversal::nextSkippingChildren(*element, &su
btree); | 572 Element* next = ElementTraversal::nextSkippingChildren(*element, &su
btree); |
| 580 // The subtree is not in document so this won't generate events that
could mutate the tree. | 573 // The subtree is not in document so this won't generate events that
could mutate the tree. |
| 581 element->parentNode()->removeChild(element); | 574 element->parentNode()->removeChild(element); |
| 582 element = next; | 575 element = next; |
| 583 } else { | 576 } else { |
| 584 element = ElementTraversal::next(*element, &subtree); | 577 element = ElementTraversal::next(*element, &subtree); |
| 585 } | 578 } |
| 586 } | 579 } |
| 587 } | 580 } |
| 588 | 581 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 615 // actual shadow tree (after the special case modification for svg/symbol) w
e have | 608 // actual shadow tree (after the special case modification for svg/symbol) w
e have |
| 616 // to walk it completely and expand all <use> elements. | 609 // to walk it completely and expand all <use> elements. |
| 617 ShadowRoot* shadowRoot = userAgentShadowRoot(); | 610 ShadowRoot* shadowRoot = userAgentShadowRoot(); |
| 618 for (RefPtrWillBeRawPtr<SVGUseElement> use = Traversal<SVGUseElement>::first
Within(*shadowRoot); use; ) { | 611 for (RefPtrWillBeRawPtr<SVGUseElement> use = Traversal<SVGUseElement>::first
Within(*shadowRoot); use; ) { |
| 619 ASSERT(!use->resourceIsStillLoading()); | 612 ASSERT(!use->resourceIsStillLoading()); |
| 620 | 613 |
| 621 SVGElement* target = 0; | 614 SVGElement* target = 0; |
| 622 if (hasCycleUseReferencing(toSVGUseElement(use->correspondingElement()),
use.get(), target)) | 615 if (hasCycleUseReferencing(toSVGUseElement(use->correspondingElement()),
use.get(), target)) |
| 623 return false; | 616 return false; |
| 624 | 617 |
| 625 if (target && isDisallowedElement(target)) | 618 if (target && isDisallowedElement(*target)) |
| 626 return false; | 619 return false; |
| 627 // Don't ASSERT(target) here, it may be "pending", too. | 620 // Don't ASSERT(target) here, it may be "pending", too. |
| 628 // Setup sub-shadow tree root node | 621 // Setup sub-shadow tree root node |
| 629 RefPtrWillBeRawPtr<SVGGElement> cloneParent = SVGGElement::create(refere
ncedScope()->document()); | 622 RefPtrWillBeRawPtr<SVGGElement> cloneParent = SVGGElement::create(refere
ncedScope()->document()); |
| 630 // Transfer all data (attributes, etc.) from <use> to the new <g> elemen
t. | 623 // Transfer all data (attributes, etc.) from <use> to the new <g> elemen
t. |
| 631 cloneParent->cloneDataFromElement(*use); | 624 cloneParent->cloneDataFromElement(*use); |
| 632 cloneParent->setCorrespondingElement(use->correspondingElement()); | 625 cloneParent->setCorrespondingElement(use->correspondingElement()); |
| 633 | 626 |
| 634 // Spec: In the generated content, the 'use' will be replaced by 'g', wh
ere all attributes from the | 627 // Spec: In the generated content, the 'use' will be replaced by 'g', wh
ere all attributes from the |
| 635 // 'use' element except for x, y, width, height and xlink:href are trans
ferred to the generated 'g' element. | 628 // 'use' element except for x, y, width, height and xlink:href are trans
ferred to the generated 'g' element. |
| 636 removeAttributesFromReplacementElement(*cloneParent); | 629 removeAttributesFromReplacementElement(*cloneParent); |
| 637 | 630 |
| 638 // Move already cloned elements to the new <g> element. | 631 // Move already cloned elements to the new <g> element. |
| 639 moveChildrenToReplacementElement(*use, *cloneParent); | 632 moveChildrenToReplacementElement(*use, *cloneParent); |
| 640 | 633 |
| 641 if (target) { | 634 if (target) { |
| 642 RefPtrWillBeRawPtr<Node> newChild = cloneNodeAndAssociate(*target); | 635 RefPtrWillBeRawPtr<Node> newChild = cloneNodeAndAssociate(*target); |
| 643 ASSERT(newChild->isSVGElement()); | 636 ASSERT(newChild->isSVGElement()); |
| 644 transferUseWidthAndHeightIfNeeded(*use, toSVGElement(newChild.get())
, *target); | 637 transferUseWidthAndHeightIfNeeded(*use, toSVGElement(newChild.get())
, *target); |
| 645 cloneParent->appendChild(newChild.release()); | 638 cloneParent->appendChild(newChild.release()); |
| 646 } | 639 } |
| 647 | 640 |
| 648 // We don't walk the target tree element-by-element, and clone each elem
ent, | 641 removeDisallowedElementsFromSubtree(*cloneParent); |
| 649 // but instead use cloneElementWithChildren(). This is an optimization f
or the common | |
| 650 // case where <use> doesn't contain disallowed elements (ie. <foreignObj
ect>). | |
| 651 // Though if there are disallowed elements in the subtree, we have to re
move them. | |
| 652 // For instance: <use> on <g> containing <foreignObject> (indirect case)
. | |
| 653 if (subtreeContainsDisallowedElement(cloneParent.get())) | |
| 654 removeDisallowedElementsFromSubtree(*cloneParent); | |
| 655 | 642 |
| 656 RefPtrWillBeRawPtr<SVGElement> replacingElement(cloneParent.get()); | 643 RefPtrWillBeRawPtr<SVGElement> replacingElement(cloneParent.get()); |
| 657 | 644 |
| 658 // Replace <use> with referenced content. | 645 // Replace <use> with referenced content. |
| 659 use->parentNode()->replaceChild(cloneParent.release(), use); | 646 use->parentNode()->replaceChild(cloneParent.release(), use); |
| 660 | 647 |
| 661 use = Traversal<SVGUseElement>::next(*replacingElement, shadowRoot); | 648 use = Traversal<SVGUseElement>::next(*replacingElement, shadowRoot); |
| 662 } | 649 } |
| 663 return true; | 650 return true; |
| 664 } | 651 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 675 // 'svg' element will use values of 100% for these attributes. | 662 // 'svg' element will use values of 100% for these attributes. |
| 676 ASSERT(referencedScope()); | 663 ASSERT(referencedScope()); |
| 677 RefPtrWillBeRawPtr<SVGSVGElement> svgElement = SVGSVGElement::create(ref
erencedScope()->document()); | 664 RefPtrWillBeRawPtr<SVGSVGElement> svgElement = SVGSVGElement::create(ref
erencedScope()->document()); |
| 678 // Transfer all data (attributes, etc.) from <symbol> to the new <svg> e
lement. | 665 // Transfer all data (attributes, etc.) from <symbol> to the new <svg> e
lement. |
| 679 svgElement->cloneDataFromElement(*symbol); | 666 svgElement->cloneDataFromElement(*symbol); |
| 680 svgElement->setCorrespondingElement(symbol->correspondingElement()); | 667 svgElement->setCorrespondingElement(symbol->correspondingElement()); |
| 681 | 668 |
| 682 // Move already cloned elements to the new <svg> element. | 669 // Move already cloned elements to the new <svg> element. |
| 683 moveChildrenToReplacementElement(*symbol, *svgElement); | 670 moveChildrenToReplacementElement(*symbol, *svgElement); |
| 684 | 671 |
| 685 // We don't walk the target tree element-by-element, and clone each elem
ent, | 672 removeDisallowedElementsFromSubtree(*svgElement); |
| 686 // but instead use cloneNode(deep=true). This is an optimization for the
common | |
| 687 // case where <use> doesn't contain disallowed elements (ie. <foreignObj
ect>). | |
| 688 // Though if there are disallowed elements in the subtree, we have to re
move them. | |
| 689 // For instance: <use> on <g> containing <foreignObject> (indirect case)
. | |
| 690 if (subtreeContainsDisallowedElement(svgElement.get())) | |
| 691 removeDisallowedElementsFromSubtree(*svgElement); | |
| 692 | 673 |
| 693 RefPtrWillBeRawPtr<SVGElement> replacingElement(svgElement.get()); | 674 RefPtrWillBeRawPtr<SVGElement> replacingElement(svgElement.get()); |
| 694 | 675 |
| 695 // Replace <symbol> with <svg>. | 676 // Replace <symbol> with <svg>. |
| 696 symbol->parentNode()->replaceChild(svgElement.release(), symbol); | 677 symbol->parentNode()->replaceChild(svgElement.release(), symbol); |
| 697 | 678 |
| 698 symbol = Traversal<SVGSymbolElement>::next(*replacingElement, shadowRoot
); | 679 symbol = Traversal<SVGSymbolElement>::next(*replacingElement, shadowRoot
); |
| 699 } | 680 } |
| 700 } | 681 } |
| 701 | 682 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 | 796 |
| 816 if (m_resource) | 797 if (m_resource) |
| 817 m_resource->removeClient(this); | 798 m_resource->removeClient(this); |
| 818 | 799 |
| 819 m_resource = resource; | 800 m_resource = resource; |
| 820 if (m_resource) | 801 if (m_resource) |
| 821 m_resource->addClient(this); | 802 m_resource->addClient(this); |
| 822 } | 803 } |
| 823 | 804 |
| 824 } // namespace blink | 805 } // namespace blink |
| OLD | NEW |