Index: third_party/WebKit/Source/web/WebPageSerializer.cpp |
diff --git a/third_party/WebKit/Source/web/WebPageSerializer.cpp b/third_party/WebKit/Source/web/WebPageSerializer.cpp |
index c6954126ab227b4c3426e95364bc56011dc3c294..71786e05a37d62ab240161c0316513302e930d39 100644 |
--- a/third_party/WebKit/Source/web/WebPageSerializer.cpp |
+++ b/third_party/WebKit/Source/web/WebPageSerializer.cpp |
@@ -45,6 +45,7 @@ |
#include "core/page/PageSerializer.h" |
#include "platform/SerializedResource.h" |
#include "platform/mhtml/MHTMLArchive.h" |
+#include "platform/mhtml/MHTMLParser.h" |
#include "platform/weborigin/KURL.h" |
#include "public/platform/WebCString.h" |
#include "public/platform/WebString.h" |
@@ -56,6 +57,8 @@ |
#include "web/WebLocalFrameImpl.h" |
#include "web/WebPageSerializerImpl.h" |
#include "web/WebViewImpl.h" |
+#include "wtf/Assertions.h" |
+#include "wtf/HashMap.h" |
#include "wtf/Vector.h" |
#include "wtf/text/StringConcatenate.h" |
@@ -65,12 +68,16 @@ namespace { |
class MHTMLPageSerializerDelegate final : public PageSerializer::Delegate { |
public: |
- ~MHTMLPageSerializerDelegate() override; |
+ MHTMLPageSerializerDelegate(HashMap<Frame*, String>* frameToContentID); |
bool shouldIgnoreAttribute(const Attribute&) override; |
+ String rewriteLink(const Element&) override; |
+private: |
+ HashMap<Frame*, String>* m_frameToContentID; |
}; |
- |
-MHTMLPageSerializerDelegate::~MHTMLPageSerializerDelegate() |
+MHTMLPageSerializerDelegate::MHTMLPageSerializerDelegate( |
+ HashMap<Frame*, String>* frameToContentID) |
+ : m_frameToContentID(frameToContentID) |
{ |
} |
@@ -82,12 +89,58 @@ bool MHTMLPageSerializerDelegate::shouldIgnoreAttribute(const Attribute& attribu |
return attribute.localName() == HTMLNames::srcsetAttr; |
} |
+String MHTMLPageSerializerDelegate::rewriteLink(const Element& element) |
+{ |
+ if (!element.isFrameOwnerElement()) |
+ return String(); |
+ |
+ auto* frameOwnerElement = toHTMLFrameOwnerElement(&element); |
+ Frame* frame = frameOwnerElement->contentFrame(); |
+ if (!frame) |
+ return String(); |
+ |
+ KURL cidURI = MHTMLParser::convertContentIDToURI(m_frameToContentID->get(frame)); |
+ ASSERT(cidURI.isValid()); |
+ |
+ if (isHTMLFrameElementBase(&element)) |
+ return cidURI.string(); |
+ |
+ if (isHTMLObjectElement(&element)) { |
+ Document* doc = frameOwnerElement->contentDocument(); |
+ bool isHandledBySerializer = doc->isHTMLDocument() |
+ || doc->isXHTMLDocument() || doc->isImageDocument(); |
+ if (isHandledBySerializer) |
+ return cidURI.string(); |
+ } |
+ |
+ return String(); |
+} |
+ |
} // namespace |
+static HashMap<Frame*, String> generateFrameContentIDs(Page* page) |
+{ |
+ HashMap<Frame*, String> frameToContentID; |
+ int frameID = 0; |
+ for (Frame* frame = page->mainFrame(); frame; frame = frame->tree().traverseNext()) { |
+ // TODO(lukasza): Move cid generation to the browser + use base/guid.h |
+ // (see the draft at crrev.com/1386873003). |
+ StringBuilder contentIDBuilder; |
+ contentIDBuilder.appendLiteral("<frame"); |
+ contentIDBuilder.appendNumber(frameID++); |
+ contentIDBuilder.appendLiteral("@mhtml.blink>"); |
+ |
+ frameToContentID.add(frame, contentIDBuilder.toString()); |
+ } |
+ return frameToContentID; |
+} |
+ |
static PassRefPtr<SharedBuffer> serializePageToMHTML(Page* page, MHTMLArchive::EncodingPolicy encodingPolicy) |
{ |
Vector<SerializedResource> resources; |
- PageSerializer serializer(&resources, adoptPtr(new MHTMLPageSerializerDelegate)); |
+ HashMap<Frame*, String> frameToContentID = generateFrameContentIDs(page); |
+ MHTMLPageSerializerDelegate delegate(&frameToContentID); |
+ PageSerializer serializer(&resources, &delegate); |
RefPtr<SharedBuffer> output = SharedBuffer::create(); |
String boundary = MHTMLArchive::generateMHTMLBoundary(); |
@@ -105,9 +158,16 @@ static PassRefPtr<SharedBuffer> serializePageToMHTML(Page* page, MHTMLArchive::E |
resources.clear(); |
serializer.serializeFrame(*toLocalFrame(frame)); |
- for (const auto& resource : resources) { |
+ bool isFirstResource = true; |
+ for (const SerializedResource& resource : resources) { |
+ // Frame is the 1st resource (see PageSerializer::serializeFrame doc |
+ // comment). Frames need a Content-ID header. |
+ String contentID = isFirstResource ? frameToContentID.get(frame) : String(); |
+ |
MHTMLArchive::generateMHTMLPart( |
- boundary, encodingPolicy, resource, *output); |
+ boundary, contentID, encodingPolicy, resource, *output); |
+ |
+ isFirstResource = false; |
} |
} |