15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011 Google Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met: 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Redistributions of source code must retain the above copyright 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Redistributions in binary form must reproduce the above 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution. 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Neither the name of Google Inc. nor the names of its 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission. 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/PageSerializer.h" 3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "HTMLNames.h" 3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/css/CSSImageValue.h" 3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/css/CSSImportRule.h" 3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/css/CSSStyleRule.h" 3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/css/StylePropertySet.h" 3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/css/StyleRule.h" 4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/css/StyleSheetContents.h" 4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Document.h" 4253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Element.h" 4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Text.h" 4453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/MarkupAccumulator.h" 4553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLFrameOwnerElement.h" 4653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLImageElement.h" 471fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch#include "core/html/HTMLInputElement.h" 4853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLLinkElement.h" 4953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLStyleElement.h" 5053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/parser/HTMLMetaCharsetParser.h" 51e6d4491e48613634a83c1957c72759da80987961Ben Murdoch#include "core/loader/cache/ImageResource.h" 5253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/Frame.h" 5353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/Page.h" 545267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "core/platform/SerializedResource.h" 5553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/graphics/Image.h" 561fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch#include "core/rendering/RenderImage.h" 57e6d4491e48613634a83c1957c72759da80987961Ben Murdoch#include "core/rendering/style/StyleFetchedImage.h" 5853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/style/StyleImage.h" 5981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)#include "wtf/text/CString.h" 6081a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)#include "wtf/text/StringBuilder.h" 6181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)#include "wtf/text/TextEncoding.h" 6281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)#include "wtf/text/WTFString.h" 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool isCharsetSpecifyingNode(Node* node) 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!node->isHTMLElement()) 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) HTMLElement* element = toHTMLElement(node); 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!element->hasTagName(HTMLNames::metaTag)) 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) HTMLMetaCharsetParser::AttributeList attributes; 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (element->hasAttributes()) { 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < element->attributeCount(); ++i) { 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const Attribute* attribute = element->attributeItem(i); 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: We should deal appropriately with the attribute if they have a namespace. 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) attributes.append(std::make_pair(attribute->name().toString(), attribute->value().string())); 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 8281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) WTF::TextEncoding textEncoding = HTMLMetaCharsetParser::encodingFromMetaAttributes(attributes); 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return textEncoding.isValid(); 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool shouldIgnoreElement(Element* element) 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return element->hasTagName(HTMLNames::scriptTag) || element->hasTagName(HTMLNames::noscriptTag) || isCharsetSpecifyingNode(element); 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const QualifiedName& frameOwnerURLAttributeName(const HTMLFrameOwnerElement& frameOwner) 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: We should support all frame owners including applets. 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return frameOwner.hasTagName(HTMLNames::objectTag) ? HTMLNames::dataAttr : HTMLNames::srcAttr; 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class SerializerMarkupAccumulator : public WebCore::MarkupAccumulator { 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public: 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SerializerMarkupAccumulator(PageSerializer*, Document*, Vector<Node*>*); 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtual ~SerializerMarkupAccumulator(); 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)protected: 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtual void appendText(StringBuilder& out, Text*); 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtual void appendElement(StringBuilder& out, Element*, Namespaces*); 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtual void appendCustomAttributes(StringBuilder& out, Element*, Namespaces*); 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtual void appendEndTag(Node*); 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private: 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) PageSerializer* m_serializer; 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Document* m_document; 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SerializerMarkupAccumulator::SerializerMarkupAccumulator(PageSerializer* serializer, Document* document, Vector<Node*>* nodes) 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : MarkupAccumulator(nodes, ResolveAllURLs) 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_serializer(serializer) 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_document(document) 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // MarkupAccumulator does not serialize the <?xml ... line, so we add it explicitely to ensure the right encoding is specified. 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_document->isXHTMLDocument() || m_document->xmlStandalone() || m_document->isSVGDocument()) 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendString("<?xml version=\"" + m_document->xmlVersion() + "\" encoding=\"" + m_document->charset() + "\"?>"); 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)SerializerMarkupAccumulator::~SerializerMarkupAccumulator() 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SerializerMarkupAccumulator::appendText(StringBuilder& out, Text* text) 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Element* parent = text->parentElement(); 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (parent && !shouldIgnoreElement(parent)) 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) MarkupAccumulator::appendText(out, text); 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SerializerMarkupAccumulator::appendElement(StringBuilder& out, Element* element, Namespaces* namespaces) 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!shouldIgnoreElement(element)) 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) MarkupAccumulator::appendElement(out, element, namespaces); 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (element->hasTagName(HTMLNames::headTag)) { 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) out.append("<meta charset=\""); 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) out.append(m_document->charset()); 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) out.append("\">"); 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: For object (plugins) tags and video tag we could replace them by an image of their current contents. 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SerializerMarkupAccumulator::appendCustomAttributes(StringBuilder& out, Element* element, Namespaces* namespaces) 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!element->isFrameOwnerElement()) 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) HTMLFrameOwnerElement* frameOwner = toFrameOwnerElement(element); 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Frame* frame = frameOwner->contentFrame(); 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!frame) 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) KURL url = frame->document()->url(); 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (url.isValid() && !url.isBlankURL()) 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We need to give a fake location to blank frames so they can be referenced by the serialized frame. 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) url = m_serializer->urlForBlankFrame(frame); 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) appendAttribute(out, element, Attribute(frameOwnerURLAttributeName(*frameOwner), url.string()), namespaces); 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SerializerMarkupAccumulator::appendEndTag(Node* node) 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (node->isElementNode() && !shouldIgnoreElement(toElement(node))) 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) MarkupAccumulator::appendEndTag(node); 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)PageSerializer::PageSerializer(Vector<SerializedResource>* resources) 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : m_resources(resources) 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_blankFrameCounter(0) 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void PageSerializer::serialize(Page* page) 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) serializeFrame(page->mainFrame()); 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void PageSerializer::serializeFrame(Frame* frame) 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Document* document = frame->document(); 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) KURL url = document->url(); 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!url.isValid() || url.isBlankURL()) { 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // For blank frames we generate a fake URL so they can be referenced by their containing frame. 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) url = urlForBlankFrame(frame); 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_resourceURLs.contains(url)) { 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: We could have 2 frame with the same URL but which were dynamically changed and have now 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // different content. So we should serialize both and somehow rename the frame src in the containing 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // frame. Arg! 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Vector<Node*> nodes; 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SerializerMarkupAccumulator accumulator(this, document, &nodes); 20281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) WTF::TextEncoding textEncoding(document->charset()); 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CString data; 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!textEncoding.isValid()) { 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: iframes used as images trigger this. We should deal with them correctly. 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 20853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) String text = accumulator.serializeNodes(document->documentElement(), IncludeNode); 20902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch CString frameHTML = textEncoding.normalizeAndEncode(text, WTF::EntitiesForUnencodables); 2105267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) m_resources->append(SerializedResource(url, document->suggestedMIMEType(), SharedBuffer::create(frameHTML.data(), frameHTML.length()))); 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_resourceURLs.add(url); 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (Vector<Node*>::iterator iter = nodes.begin(); iter != nodes.end(); ++iter) { 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Node* node = *iter; 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!node->isElementNode()) 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Element* element = toElement(node); 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We have to process in-line style as it might contain some resources (typically background images). 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (element->isStyledElement()) 221591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch retrieveResourcesForProperties(element->inlineStyle(), document); 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (element->hasTagName(HTMLNames::imgTag)) { 224521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) HTMLImageElement* imageElement = toHTMLImageElement(element); 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) KURL url = document->completeURL(imageElement->getAttribute(HTMLNames::srcAttr)); 226e6d4491e48613634a83c1957c72759da80987961Ben Murdoch ImageResource* cachedImage = imageElement->cachedImage(); 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) addImageToResources(cachedImage, imageElement->renderer(), url); 2281fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch } else if (element->hasTagName(HTMLNames::inputTag)) { 2291fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch HTMLInputElement* inputElement = toHTMLInputElement(element); 2301fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch if (inputElement->isImageButton() && inputElement->hasImageLoader()) { 2311fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch KURL url = inputElement->src(); 232e6d4491e48613634a83c1957c72759da80987961Ben Murdoch ImageResource* cachedImage = inputElement->imageLoader()->image(); 2331fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch addImageToResources(cachedImage, inputElement->renderer(), url); 2341fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch } 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (element->hasTagName(HTMLNames::linkTag)) { 236e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch HTMLLinkElement* linkElement = toHTMLLinkElement(element); 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (CSSStyleSheet* sheet = linkElement->sheet()) { 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) KURL url = document->completeURL(linkElement->getAttribute(HTMLNames::hrefAttr)); 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) serializeCSSStyleSheet(sheet, url); 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_resourceURLs.contains(url)); 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (element->hasTagName(HTMLNames::styleTag)) { 243591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch HTMLStyleElement* styleElement = toHTMLStyleElement(element); 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (CSSStyleSheet* sheet = styleElement->sheet()) 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) serializeCSSStyleSheet(sheet, KURL()); 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (Frame* childFrame = frame->tree()->firstChild(); childFrame; childFrame = childFrame->tree()->nextSibling()) 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) serializeFrame(childFrame); 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void PageSerializer::serializeCSSStyleSheet(CSSStyleSheet* styleSheet, const KURL& url) 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) StringBuilder cssText; 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < styleSheet->length(); ++i) { 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CSSRule* rule = styleSheet->item(i); 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) String itemText = rule->cssText(); 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!itemText.isEmpty()) { 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cssText.append(itemText); 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (i < styleSheet->length() - 1) 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) cssText.append("\n\n"); 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Document* document = styleSheet->ownerDocument(); 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Some rules have resources associated with them that we need to retrieve. 266926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (rule->type() == CSSRule::IMPORT_RULE) { 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CSSImportRule* importRule = static_cast<CSSImportRule*>(rule); 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) KURL importURL = document->completeURL(importRule->href()); 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_resourceURLs.contains(importURL)) 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) serializeCSSStyleSheet(importRule->styleSheet(), importURL); 272926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } else if (rule->type() == CSSRule::FONT_FACE_RULE) { 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: Add support for font face rule. It is not clear to me at this point if the actual otf/eot file can 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // be retrieved from the CSSFontFaceRule object. 2751fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch } else if (rule->type() == CSSRule::STYLE_RULE) { 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retrieveResourcesForRule(static_cast<CSSStyleRule*>(rule)->styleRule(), document); 2771fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch } 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (url.isValid() && !m_resourceURLs.contains(url)) { 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: We should check whether a charset has been specified and if none was found add one. 28281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles) WTF::TextEncoding textEncoding(styleSheet->contents()->charset()); 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(textEncoding.isValid()); 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) String textString = cssText.toString(); 28502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch CString text = textEncoding.normalizeAndEncode(textString, WTF::EntitiesForUnencodables); 2865267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) m_resources->append(SerializedResource(url, String("text/css"), SharedBuffer::create(text.data(), text.length()))); 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_resourceURLs.add(url); 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 291e6d4491e48613634a83c1957c72759da80987961Ben Murdochvoid PageSerializer::addImageToResources(ImageResource* image, RenderObject* imageRenderer, const KURL& url) 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 29383750176c3ee2cea66c8a9751271026a5901be3aBen Murdoch if (!url.isValid() || m_resourceURLs.contains(url) || url.protocolIsData()) 2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!image || image->image() == Image::nullImage()) 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<SharedBuffer> data = imageRenderer ? image->imageForRenderer(imageRenderer)->data() : 0; 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!data) 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) data = image->image()->data(); 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!data) { 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LOG_ERROR("No data for image %s", url.string().utf8().data()); 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) String mimeType = image->response().mimeType(); 3095267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) m_resources->append(SerializedResource(url, mimeType, data)); 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_resourceURLs.add(url); 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void PageSerializer::retrieveResourcesForRule(StyleRule* rule, Document* document) 3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) retrieveResourcesForProperties(rule->properties(), document); 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void PageSerializer::retrieveResourcesForProperties(const StylePropertySet* styleDeclaration, Document* document) 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!styleDeclaration) 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The background-image and list-style-image (for ul or ol) are the CSS properties 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // that make use of images. We iterate to make sure we include any other 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // image properties there might be. 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned propertyCount = styleDeclaration->propertyCount(); 3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < propertyCount; ++i) { 3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<CSSValue> cssValue = styleDeclaration->propertyAt(i).value(); 3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!cssValue->isImageValue()) 3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 332e6d4491e48613634a83c1957c72759da80987961Ben Murdoch CSSImageValue* imageValue = toCSSImageValue(cssValue.get()); 3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) StyleImage* styleImage = imageValue->cachedOrPendingImage(); 3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Non cached-images are just place-holders and do not contain data. 335e6d4491e48613634a83c1957c72759da80987961Ben Murdoch if (!styleImage || !styleImage->isImageResource()) 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 338e6d4491e48613634a83c1957c72759da80987961Ben Murdoch ImageResource* image = static_cast<StyleFetchedImage*>(styleImage)->cachedImage(); 33993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) addImageToResources(image, 0, image->url()); 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)KURL PageSerializer::urlForBlankFrame(Frame* frame) 3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) HashMap<Frame*, KURL>::iterator iter = m_blankFrameURLs.find(frame); 3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (iter != m_blankFrameURLs.end()) 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return iter->value; 3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) String url = "wyciwyg://frame/" + String::number(m_blankFrameCounter++); 3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) KURL fakeURL(ParsedURLString, url); 3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_blankFrameURLs.add(frame, fakeURL); 3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return fakeURL; 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 356