| Index: Source/core/page/PageSerializer.cpp
|
| diff --git a/Source/core/page/PageSerializer.cpp b/Source/core/page/PageSerializer.cpp
|
| index 8e3e4ee6aabc03406b8a021f57ec9d5f2c9bf499..2fc85f93b97ae85b7e31a8b652792af555b930b9 100644
|
| --- a/Source/core/page/PageSerializer.cpp
|
| +++ b/Source/core/page/PageSerializer.cpp
|
| @@ -54,6 +54,7 @@
|
| #include "core/html/HTMLInputElement.h"
|
| #include "core/html/HTMLLinkElement.h"
|
| #include "core/html/HTMLStyleElement.h"
|
| +#include "core/html/ImageDocument.h"
|
| #include "core/html/parser/HTMLParserIdioms.h"
|
| #include "core/page/Page.h"
|
| #include "core/rendering/RenderImage.h"
|
| @@ -105,12 +106,11 @@ public:
|
| virtual ~SerializerMarkupAccumulator();
|
|
|
| protected:
|
| - virtual void appendText(StringBuilder& out, Text*);
|
| - virtual void appendElement(StringBuilder& out, Element*, Namespaces*);
|
| - virtual void appendCustomAttributes(StringBuilder& out, Element*, Namespaces*);
|
| - virtual void appendEndTag(Node*);
|
| + virtual void appendText(StringBuilder&, Text*) OVERRIDE;
|
| + virtual void appendElement(StringBuilder&, Element*, Namespaces*) OVERRIDE;
|
| + virtual void appendCustomAttributes(StringBuilder&, Element*, Namespaces*) OVERRIDE;
|
| + virtual void appendEndTag(Node*) OVERRIDE;
|
|
|
| -private:
|
| PageSerializer* m_serializer;
|
| Document* m_document;
|
| };
|
| @@ -126,28 +126,34 @@ SerializerMarkupAccumulator::~SerializerMarkupAccumulator()
|
| {
|
| }
|
|
|
| -void SerializerMarkupAccumulator::appendText(StringBuilder& out, Text* text)
|
| +void SerializerMarkupAccumulator::appendText(StringBuilder& result, Text* text)
|
| {
|
| Element* parent = text->parentElement();
|
| if (parent && !shouldIgnoreElement(parent))
|
| - MarkupAccumulator::appendText(out, text);
|
| + MarkupAccumulator::appendText(result, text);
|
| }
|
|
|
| -void SerializerMarkupAccumulator::appendElement(StringBuilder& out, Element* element, Namespaces* namespaces)
|
| +void SerializerMarkupAccumulator::appendElement(StringBuilder& result, Element* element, Namespaces* namespaces)
|
| {
|
| if (!shouldIgnoreElement(element))
|
| - MarkupAccumulator::appendElement(out, element, namespaces);
|
| + MarkupAccumulator::appendElement(result, element, namespaces);
|
|
|
| + // FIXME: Refactor MarkupAccumulator so it is easier to append an element like this, without special cases for XHTML
|
| if (element->hasTagName(HTMLNames::headTag)) {
|
| - out.append("<meta charset=\"");
|
| - out.append(m_document->charset());
|
| - out.append("\">");
|
| + result.appendLiteral("<meta http-equiv=\"Content-Type\" content=\"");
|
| + result.append(m_document->suggestedMIMEType());
|
| + result.appendLiteral("; charset=");
|
| + result.append(m_document->charset());
|
| + if (m_document->isXHTMLDocument())
|
| + result.appendLiteral("\" />");
|
| + else
|
| + result.appendLiteral("\">");
|
| }
|
|
|
| // FIXME: For object (plugins) tags and video tag we could replace them by an image of their current contents.
|
| }
|
|
|
| -void SerializerMarkupAccumulator::appendCustomAttributes(StringBuilder& out, Element* element, Namespaces* namespaces)
|
| +void SerializerMarkupAccumulator::appendCustomAttributes(StringBuilder& result, Element* element, Namespaces* namespaces)
|
| {
|
| if (!element->isFrameOwnerElement())
|
| return;
|
| @@ -163,7 +169,7 @@ void SerializerMarkupAccumulator::appendCustomAttributes(StringBuilder& out, Ele
|
|
|
| // We need to give a fake location to blank frames so they can be referenced by the serialized frame.
|
| url = m_serializer->urlForBlankFrame(frame);
|
| - appendAttribute(out, element, Attribute(frameOwnerURLAttributeName(*frameOwner), url.string()), namespaces);
|
| + appendAttribute(result, element, Attribute(frameOwnerURLAttributeName(*frameOwner), url.string()), namespaces);
|
| }
|
|
|
| void SerializerMarkupAccumulator::appendEndTag(Node* node)
|
| @@ -172,8 +178,89 @@ void SerializerMarkupAccumulator::appendEndTag(Node* node)
|
| MarkupAccumulator::appendEndTag(node);
|
| }
|
|
|
| -PageSerializer::PageSerializer(Vector<SerializedResource>* resources)
|
| +class LinkChangeSerializerMarkupAccumulator : public SerializerMarkupAccumulator {
|
| +public:
|
| + LinkChangeSerializerMarkupAccumulator(PageSerializer*, Document*, Vector<Node*>*, LinkLocalPathMap*, String);
|
| +
|
| +protected:
|
| + virtual void appendElement(StringBuilder&, Element*, Namespaces*) OVERRIDE;
|
| + virtual void appendAttribute(StringBuilder&, Element*, const Attribute&, Namespaces*) OVERRIDE;
|
| +
|
| +private:
|
| + // m_replaceLinks include all pair of local resource path and corresponding original link.
|
| + LinkLocalPathMap* m_replaceLinks;
|
| + String m_directoryName;
|
| +};
|
| +
|
| +LinkChangeSerializerMarkupAccumulator::LinkChangeSerializerMarkupAccumulator(PageSerializer* serializer, Document* document, Vector<Node*>* nodes, LinkLocalPathMap* links, String directoryName)
|
| + : SerializerMarkupAccumulator(serializer, document, nodes)
|
| + , m_replaceLinks(links)
|
| + , m_directoryName(directoryName)
|
| +{
|
| +}
|
| +
|
| +void LinkChangeSerializerMarkupAccumulator::appendElement(StringBuilder& result, Element* element, Namespaces* namespaces)
|
| +{
|
| + // FIXME: We could move the uncommenting to appendOpenTag and appendCloseTag, or just remove it
|
| + if (element->hasTagName(HTMLNames::baseTag)) {
|
| + // Comment the BASE tag when serializing dom.
|
| + result.append("<!--");
|
| + } else if (element->hasTagName(HTMLNames::htmlTag)) {
|
| + // Add MOTW (Mark of the Web) declaration before html tag.
|
| + // See http://msdn2.microsoft.com/en-us/library/ms537628(VS.85).aspx.
|
| + result.append(String::format("\n<!-- saved from url=(%04d)%s -->\n",
|
| + static_cast<int>(m_document->url().string().utf8().length()),
|
| + m_document->url().string().utf8().data()));
|
| + }
|
| +
|
| + SerializerMarkupAccumulator::appendElement(result, element, namespaces);
|
| +
|
| + if (element->hasTagName(HTMLNames::baseTag)) {
|
| + // Comment the BASE tag when serializing dom.
|
| + result.appendLiteral("-->");
|
| +
|
| + // FIXME: Refactor MarkupAccumulator so it is easier to append an element like this, without special cases for XHTML
|
| + // Append a new base tag declaration.
|
| + result.appendLiteral("<base href=\".\"");
|
| + if (!m_document->baseTarget().isEmpty()) {
|
| + result.appendLiteral(" target=\"");
|
| + result.append(m_document->baseTarget());
|
| + result.append('"');
|
| + }
|
| + if (m_document->isXHTMLDocument())
|
| + result.appendLiteral(" />");
|
| + else
|
| + result.appendLiteral(">");
|
| + }
|
| +}
|
| +void LinkChangeSerializerMarkupAccumulator::appendAttribute(StringBuilder& result, Element* element, const Attribute& attribute, Namespaces* namespaces)
|
| +{
|
| + if (m_replaceLinks && element->isURLAttribute(attribute) && !element->isJavaScriptURLAttribute(attribute)) {
|
| +
|
| + String completeURL = m_document->completeURL(attribute.value());
|
| +
|
| + if (m_replaceLinks->contains(completeURL)) {
|
| + // FIXME: Refactor MarkupAccumulator so it is easier to append an attribute like this.
|
| + result.append(' ');
|
| + result.append(attribute.name().toString());
|
| + result.appendLiteral("=\"");
|
| + if (!m_directoryName.isEmpty()) {
|
| + result.appendLiteral("./");
|
| + result.append(m_directoryName);
|
| + result.append('/');
|
| + }
|
| + result.append(m_replaceLinks->get(completeURL));
|
| + result.appendLiteral("\"");
|
| + return;
|
| + }
|
| + }
|
| + MarkupAccumulator::appendAttribute(result, element, attribute, namespaces);
|
| +}
|
| +
|
| +PageSerializer::PageSerializer(Vector<SerializedResource>* resources, LinkLocalPathMap* urls, String directory)
|
| : m_resources(resources)
|
| + , m_URLs(urls)
|
| + , m_directory(directory)
|
| , m_blankFrameCounter(0)
|
| {
|
| }
|
| @@ -199,15 +286,21 @@ void PageSerializer::serializeFrame(Frame* frame)
|
| return;
|
| }
|
|
|
| - Vector<Node*> nodes;
|
| - SerializerMarkupAccumulator accumulator(this, document, &nodes);
|
| - WTF::TextEncoding textEncoding(document->charset());
|
| - CString data;
|
| - if (!textEncoding.isValid()) {
|
| - // FIXME: iframes used as images trigger this. We should deal with them correctly.
|
| + // If frame is an image document, add the image and don't continue
|
| + if (document->isImageDocument()) {
|
| + ImageDocument* imageDocument = toImageDocument(document);
|
| + addImageToResources(imageDocument->cachedImage(), imageDocument->imageElement()->renderer(), url);
|
| return;
|
| }
|
| - String text = accumulator.serializeNodes(document, IncludeNode);
|
| +
|
| + Vector<Node*> nodes;
|
| + OwnPtr<SerializerMarkupAccumulator> accumulator;
|
| + if (m_URLs)
|
| + accumulator = adoptPtr(new LinkChangeSerializerMarkupAccumulator(this, document, &nodes, m_URLs, m_directory));
|
| + else
|
| + accumulator = adoptPtr(new SerializerMarkupAccumulator(this, document, &nodes));
|
| + String text = accumulator->serializeNodes(document, IncludeNode);
|
| + WTF::TextEncoding textEncoding(document->charset());
|
| CString frameHTML = textEncoding.normalizeAndEncode(text, WTF::EntitiesForUnencodables);
|
| m_resources->append(SerializedResource(url, document->suggestedMIMEType(), SharedBuffer::create(frameHTML.data(), frameHTML.length())));
|
| m_resourceURLs.add(url);
|
| @@ -219,8 +312,10 @@ void PageSerializer::serializeFrame(Frame* frame)
|
|
|
| Element* element = toElement(node);
|
| // We have to process in-line style as it might contain some resources (typically background images).
|
| - if (element->isStyledElement())
|
| + if (element->isStyledElement()) {
|
| retrieveResourcesForProperties(element->inlineStyle(), document);
|
| + retrieveResourcesForProperties(element->presentationAttributeStyle(), document);
|
| + }
|
|
|
| if (element->hasTagName(HTMLNames::imgTag)) {
|
| HTMLImageElement* imageElement = toHTMLImageElement(element);
|
| @@ -311,7 +406,7 @@ void PageSerializer::addImageToResources(ImageResource* image, RenderObject* ima
|
| if (!shouldAddURL(url))
|
| return;
|
|
|
| - if (!image || image->image() == Image::nullImage())
|
| + if (!image || !image->hasImage() || image->image() == Image::nullImage())
|
| return;
|
|
|
| RefPtr<SharedBuffer> data = imageRenderer ? image->imageForRenderer(imageRenderer)->data() : 0;
|
|
|