OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
46 #include "core/dom/Element.h" | 46 #include "core/dom/Element.h" |
47 #include "core/dom/Text.h" | 47 #include "core/dom/Text.h" |
48 #include "core/editing/MarkupAccumulator.h" | 48 #include "core/editing/MarkupAccumulator.h" |
49 #include "core/fetch/FontResource.h" | 49 #include "core/fetch/FontResource.h" |
50 #include "core/fetch/ImageResource.h" | 50 #include "core/fetch/ImageResource.h" |
51 #include "core/html/HTMLFrameOwnerElement.h" | 51 #include "core/html/HTMLFrameOwnerElement.h" |
52 #include "core/html/HTMLImageElement.h" | 52 #include "core/html/HTMLImageElement.h" |
53 #include "core/html/HTMLInputElement.h" | 53 #include "core/html/HTMLInputElement.h" |
54 #include "core/html/HTMLLinkElement.h" | 54 #include "core/html/HTMLLinkElement.h" |
55 #include "core/html/HTMLStyleElement.h" | 55 #include "core/html/HTMLStyleElement.h" |
56 #include "core/html/ImageDocument.h" | |
56 #include "core/html/parser/HTMLMetaCharsetParser.h" | 57 #include "core/html/parser/HTMLMetaCharsetParser.h" |
57 #include "core/frame/Frame.h" | 58 #include "core/frame/Frame.h" |
58 #include "core/page/Page.h" | 59 #include "core/page/Page.h" |
59 #include "core/platform/graphics/Image.h" | 60 #include "core/platform/graphics/Image.h" |
60 #include "core/rendering/RenderImage.h" | 61 #include "core/rendering/RenderImage.h" |
61 #include "core/rendering/style/StyleFetchedImage.h" | 62 #include "core/rendering/style/StyleFetchedImage.h" |
62 #include "core/rendering/style/StyleImage.h" | 63 #include "core/rendering/style/StyleImage.h" |
63 #include "platform/SerializedResource.h" | 64 #include "platform/SerializedResource.h" |
65 #include "wtf/OwnPtr.h" | |
abarth-chromium
2013/11/14 16:55:03
Undoubtedly one of these other headers pulls in Ow
| |
64 #include "wtf/text/CString.h" | 66 #include "wtf/text/CString.h" |
65 #include "wtf/text/StringBuilder.h" | 67 #include "wtf/text/StringBuilder.h" |
66 #include "wtf/text/TextEncoding.h" | 68 #include "wtf/text/TextEncoding.h" |
67 #include "wtf/text/WTFString.h" | 69 #include "wtf/text/WTFString.h" |
68 | 70 |
69 namespace WebCore { | 71 namespace WebCore { |
70 | 72 |
71 static bool isCharsetSpecifyingNode(Node* node) | 73 static bool isCharsetSpecifyingNode(Node* node) |
72 { | 74 { |
73 if (!node->isHTMLElement()) | 75 if (!node->isHTMLElement()) |
(...skipping 24 matching lines...) Expand all Loading... | |
98 // FIXME: We should support all frame owners including applets. | 100 // FIXME: We should support all frame owners including applets. |
99 return frameOwner.hasTagName(HTMLNames::objectTag) ? HTMLNames::dataAttr : H TMLNames::srcAttr; | 101 return frameOwner.hasTagName(HTMLNames::objectTag) ? HTMLNames::dataAttr : H TMLNames::srcAttr; |
100 } | 102 } |
101 | 103 |
102 class SerializerMarkupAccumulator : public WebCore::MarkupAccumulator { | 104 class SerializerMarkupAccumulator : public WebCore::MarkupAccumulator { |
103 public: | 105 public: |
104 SerializerMarkupAccumulator(PageSerializer*, Document*, Vector<Node*>*); | 106 SerializerMarkupAccumulator(PageSerializer*, Document*, Vector<Node*>*); |
105 virtual ~SerializerMarkupAccumulator(); | 107 virtual ~SerializerMarkupAccumulator(); |
106 | 108 |
107 protected: | 109 protected: |
108 virtual void appendText(StringBuilder& out, Text*); | 110 virtual void appendText(StringBuilder&, Text*) OVERRIDE; |
109 virtual void appendElement(StringBuilder& out, Element*, Namespaces*); | 111 virtual void appendElement(StringBuilder&, Element*, Namespaces*) OVERRIDE; |
110 virtual void appendCustomAttributes(StringBuilder& out, Element*, Namespaces *); | 112 virtual void appendCustomAttributes(StringBuilder&, Element*, Namespaces*) O VERRIDE; |
111 virtual void appendEndTag(Node*); | 113 virtual void appendEndTag(Node*) OVERRIDE; |
112 | 114 |
113 private: | |
114 PageSerializer* m_serializer; | 115 PageSerializer* m_serializer; |
115 Document* m_document; | 116 Document* m_document; |
116 }; | 117 }; |
117 | 118 |
118 SerializerMarkupAccumulator::SerializerMarkupAccumulator(PageSerializer* seriali zer, Document* document, Vector<Node*>* nodes) | 119 SerializerMarkupAccumulator::SerializerMarkupAccumulator(PageSerializer* seriali zer, Document* document, Vector<Node*>* nodes) |
119 : MarkupAccumulator(nodes, ResolveAllURLs) | 120 : MarkupAccumulator(nodes, ResolveAllURLs) |
120 , m_serializer(serializer) | 121 , m_serializer(serializer) |
121 , m_document(document) | 122 , m_document(document) |
122 { | 123 { |
124 | |
abarth-chromium
2013/11/14 16:55:03
This blank line is not needed.
| |
123 } | 125 } |
124 | 126 |
125 SerializerMarkupAccumulator::~SerializerMarkupAccumulator() | 127 SerializerMarkupAccumulator::~SerializerMarkupAccumulator() |
126 { | 128 { |
127 } | 129 } |
128 | 130 |
129 void SerializerMarkupAccumulator::appendText(StringBuilder& out, Text* text) | 131 void SerializerMarkupAccumulator::appendText(StringBuilder& result, Text* text) |
130 { | 132 { |
131 Element* parent = text->parentElement(); | 133 Element* parent = text->parentElement(); |
132 if (parent && !shouldIgnoreElement(parent)) | 134 if (parent && !shouldIgnoreElement(parent)) |
133 MarkupAccumulator::appendText(out, text); | 135 MarkupAccumulator::appendText(result, text); |
134 } | 136 } |
135 | 137 |
136 void SerializerMarkupAccumulator::appendElement(StringBuilder& out, Element* ele ment, Namespaces* namespaces) | 138 void SerializerMarkupAccumulator::appendElement(StringBuilder& result, Element* element, Namespaces* namespaces) |
137 { | 139 { |
138 if (!shouldIgnoreElement(element)) | 140 if (!shouldIgnoreElement(element)) |
139 MarkupAccumulator::appendElement(out, element, namespaces); | 141 MarkupAccumulator::appendElement(result, element, namespaces); |
140 | 142 |
141 if (element->hasTagName(HTMLNames::headTag)) { | 143 if (element->hasTagName(HTMLNames::headTag)) { |
142 out.append("<meta charset=\""); | 144 result.appendLiteral("<meta charset=\""); |
143 out.append(m_document->charset()); | 145 result.append(m_document->charset()); |
144 out.append("\">"); | 146 if (m_document->isXHTMLDocument()) |
147 result.appendLiteral("\" />"); | |
148 else | |
149 result.appendLiteral("\">"); | |
145 } | 150 } |
146 | 151 |
147 // FIXME: For object (plugins) tags and video tag we could replace them by a n image of their current contents. | 152 // FIXME: For object (plugins) tags and video tag we could replace them by a n image of their current contents. |
148 } | 153 } |
149 | 154 |
150 void SerializerMarkupAccumulator::appendCustomAttributes(StringBuilder& out, Ele ment* element, Namespaces* namespaces) | 155 void SerializerMarkupAccumulator::appendCustomAttributes(StringBuilder& result, Element* element, Namespaces* namespaces) |
151 { | 156 { |
152 if (!element->isFrameOwnerElement()) | 157 if (!element->isFrameOwnerElement()) |
153 return; | 158 return; |
154 | 159 |
155 HTMLFrameOwnerElement* frameOwner = toHTMLFrameOwnerElement(element); | 160 HTMLFrameOwnerElement* frameOwner = toHTMLFrameOwnerElement(element); |
156 Frame* frame = frameOwner->contentFrame(); | 161 Frame* frame = frameOwner->contentFrame(); |
157 if (!frame) | 162 if (!frame) |
158 return; | 163 return; |
159 | 164 |
160 KURL url = frame->document()->url(); | 165 KURL url = frame->document()->url(); |
161 if (url.isValid() && !url.isBlankURL()) | 166 if (url.isValid() && !url.isBlankURL()) |
162 return; | 167 return; |
163 | 168 |
164 // We need to give a fake location to blank frames so they can be referenced by the serialized frame. | 169 // We need to give a fake location to blank frames so they can be referenced by the serialized frame. |
165 url = m_serializer->urlForBlankFrame(frame); | 170 url = m_serializer->urlForBlankFrame(frame); |
166 appendAttribute(out, element, Attribute(frameOwnerURLAttributeName(*frameOwn er), url.string()), namespaces); | 171 appendAttribute(result, element, Attribute(frameOwnerURLAttributeName(*frame Owner), url.string()), namespaces); |
167 } | 172 } |
168 | 173 |
169 void SerializerMarkupAccumulator::appendEndTag(Node* node) | 174 void SerializerMarkupAccumulator::appendEndTag(Node* node) |
170 { | 175 { |
171 if (node->isElementNode() && !shouldIgnoreElement(toElement(node))) | 176 if (node->isElementNode() && !shouldIgnoreElement(toElement(node))) |
172 MarkupAccumulator::appendEndTag(node); | 177 MarkupAccumulator::appendEndTag(node); |
173 } | 178 } |
174 | 179 |
175 PageSerializer::PageSerializer(Vector<SerializedResource>* resources) | 180 |
176 : m_resources(resources) | 181 |
abarth-chromium
2013/11/14 16:55:03
You've got two extra blank lines here.
| |
177 , m_blankFrameCounter(0) | 182 class LinkChangeSerializerMarkupAccumulator : public SerializerMarkupAccumulator { |
183 public: | |
184 LinkChangeSerializerMarkupAccumulator(PageSerializer*, Document*, Vector<Nod e*>*, LinkLocalPathMap*, String); | |
185 | |
186 protected: | |
187 virtual void appendElement(StringBuilder&, Element*, Namespaces*) OVERRIDE; | |
188 virtual void appendAttribute(StringBuilder&, Element*, const Attribute&, Nam espaces*) OVERRIDE; | |
189 | |
190 private: | |
191 // local_links_ include all pair of local resource path and corresponding | |
192 // original link. | |
193 LinkLocalPathMap* m_replaceLinks; | |
194 String m_directoryName; | |
195 }; | |
196 | |
197 LinkChangeSerializerMarkupAccumulator::LinkChangeSerializerMarkupAccumulator(Pag eSerializer* serializer, Document* document, Vector<Node*>* nodes, LinkLocalPath Map* links, String directoryName) | |
198 : SerializerMarkupAccumulator(serializer, document, nodes) | |
199 , m_replaceLinks(links) | |
200 , m_directoryName(directoryName) | |
178 { | 201 { |
179 } | 202 } |
180 | 203 |
204 void LinkChangeSerializerMarkupAccumulator::appendElement(StringBuilder& result, Element* element, Namespaces* namespaces) | |
205 { | |
206 // TODO: or move to append open tag / close tag | |
abarth-chromium
2013/11/14 16:55:03
TODO -> FIXME
Also, please use complete sentences
| |
207 | |
208 if (element->hasTagName(HTMLNames::baseTag)) { | |
209 // Comment the BASE tag when serializing dom. | |
210 result.append("<!--"); | |
211 } else if (element->hasTagName(HTMLNames::htmlTag)) { | |
212 // Add MOTW (Mark of the Web) declaration before html tag. | |
213 // See http://msdn2.microsoft.com/en-us/library/ms537628(VS.85).aspx. | |
214 result.append(String::format("\n<!-- saved from url=(%04d)%s -->\n", | |
215 static_cast<int>(m_document->url().string().utf8().length()), | |
216 m_document->url().string().utf8().data())); | |
217 } | |
218 | |
219 SerializerMarkupAccumulator::appendElement(result, element, namespaces); | |
220 | |
221 if (element->hasTagName(HTMLNames::baseTag)) { | |
222 // Comment the BASE tag when serializing dom. | |
223 result.appendLiteral("-->"); | |
224 | |
225 // Append a new base tag declaration. | |
226 result.appendLiteral("<base href=\".\""); | |
227 if (!m_document->baseTarget().isEmpty()) { | |
228 result.appendLiteral(" target=\""); | |
229 result.append(m_document->baseTarget()); | |
230 result.append('"'); | |
231 } | |
232 if (m_document->isXHTMLDocument()) | |
233 result.appendLiteral(" />"); | |
234 else | |
235 result.appendLiteral(">"); | |
236 } | |
237 } | |
238 void LinkChangeSerializerMarkupAccumulator::appendAttribute(StringBuilder& resul t, Element* element, const Attribute& attribute, Namespaces* namespaces) | |
239 { | |
240 if (m_replaceLinks && element->isURLAttribute(attribute) | |
241 && !element->isJavaScriptURLAttribute(attribute)) { | |
242 | |
243 // Get the absolute link | |
abarth-chromium
2013/11/14 16:55:03
You can remove these comments that just way what t
| |
244 String completeURL = m_document->completeURL(attribute.value()); | |
245 | |
246 // Check whether we have local files for those link. | |
247 if (m_replaceLinks->contains(completeURL)) { | |
248 // TODO: refactor markupaccumulator, reuse code | |
abarth-chromium
2013/11/14 16:55:03
TODO -> FIXME
| |
249 result.append(' '); | |
250 result.append(attribute.name().toString()); | |
251 result.appendLiteral("=\""); | |
252 if (!m_directoryName.isEmpty()) { | |
253 result.appendLiteral("./"); | |
254 result.append(m_directoryName); | |
255 result.append('/'); | |
256 } | |
257 result.append(m_replaceLinks->get(completeURL)); | |
258 result.appendLiteral("\""); | |
259 return; | |
260 } | |
261 } | |
262 MarkupAccumulator::appendAttribute(result, element, attribute, namespaces); | |
263 } | |
264 | |
265 | |
abarth-chromium
2013/11/14 16:55:03
You've got an extra blank line here.
| |
266 PageSerializer::PageSerializer(Vector<SerializedResource>* resources, LinkLocalP athMap* urls, String directory) | |
267 : m_resources(resources) | |
268 , m_URLs(urls) | |
269 , m_directory(directory) | |
270 , m_blankFrameCounter(0) | |
271 { | |
272 | |
273 } | |
274 | |
181 void PageSerializer::serialize(Page* page) | 275 void PageSerializer::serialize(Page* page) |
182 { | 276 { |
183 serializeFrame(page->mainFrame()); | 277 serializeFrame(page->mainFrame()); |
184 } | 278 } |
185 | 279 |
186 void PageSerializer::serializeFrame(Frame* frame) | 280 void PageSerializer::serializeFrame(Frame* frame) |
187 { | 281 { |
188 Document* document = frame->document(); | 282 Document* document = frame->document(); |
189 KURL url = document->url(); | 283 KURL url = document->url(); |
190 if (!url.isValid() || url.isBlankURL()) { | 284 if (!url.isValid() || url.isBlankURL()) { |
191 // For blank frames we generate a fake URL so they can be referenced by their containing frame. | 285 // For blank frames we generate a fake URL so they can be referenced by their containing frame. |
192 url = urlForBlankFrame(frame); | 286 url = urlForBlankFrame(frame); |
193 } | 287 } |
194 | 288 |
195 if (m_resourceURLs.contains(url)) { | 289 if (m_resourceURLs.contains(url)) { |
196 // FIXME: We could have 2 frame with the same URL but which were dynamic ally changed and have now | 290 // FIXME: We could have 2 frame with the same URL but which were dynamic ally changed and have now |
197 // different content. So we should serialize both and somehow rename the frame src in the containing | 291 // different content. So we should serialize both and somehow rename the frame src in the containing |
198 // frame. Arg! | 292 // frame. Arg! |
199 return; | 293 return; |
200 } | 294 } |
201 | 295 |
296 // If frame is an image document, add the image and don't continue | |
297 if (document->isImageDocument()) { | |
298 ImageDocument* imageDocument = toImageDocument(document); | |
299 addImageToResources(imageDocument->cachedImage(), imageDocument->imageEl ement()->renderer(), url); | |
300 return; | |
301 } | |
302 | |
202 Vector<Node*> nodes; | 303 Vector<Node*> nodes; |
203 SerializerMarkupAccumulator accumulator(this, document, &nodes); | 304 WTF::OwnPtr<SerializerMarkupAccumulator> accumulator; |
abarth-chromium
2013/11/14 16:55:03
No need for WTF:: here. OwnPtr has a using WTF::O
| |
305 if (m_URLs) { | |
306 accumulator = adoptPtr(new LinkChangeSerializerMarkupAccumulator(this, d ocument, &nodes, m_URLs, m_directory)); | |
307 } else { | |
308 accumulator = adoptPtr(new SerializerMarkupAccumulator(this, document, & nodes)); | |
309 } | |
abarth-chromium
2013/11/14 16:55:03
No need for { } in either branch of the if here.
| |
310 String text = accumulator->serializeNodes(document, IncludeNode); | |
204 WTF::TextEncoding textEncoding(document->charset()); | 311 WTF::TextEncoding textEncoding(document->charset()); |
205 CString data; | |
206 if (!textEncoding.isValid()) { | |
207 // FIXME: iframes used as images trigger this. We should deal with them correctly. | |
208 return; | |
209 } | |
210 String text = accumulator.serializeNodes(document, IncludeNode); | |
211 CString frameHTML = textEncoding.normalizeAndEncode(text, WTF::EntitiesForUn encodables); | 312 CString frameHTML = textEncoding.normalizeAndEncode(text, WTF::EntitiesForUn encodables); |
212 m_resources->append(SerializedResource(url, document->suggestedMIMEType(), S haredBuffer::create(frameHTML.data(), frameHTML.length()))); | 313 m_resources->append(SerializedResource(url, document->suggestedMIMEType(), S haredBuffer::create(frameHTML.data(), frameHTML.length()))); |
213 m_resourceURLs.add(url); | 314 m_resourceURLs.add(url); |
214 | 315 |
215 for (Vector<Node*>::iterator iter = nodes.begin(); iter != nodes.end(); ++it er) { | 316 for (Vector<Node*>::iterator iter = nodes.begin(); iter != nodes.end(); ++it er) { |
216 Node* node = *iter; | 317 Node* node = *iter; |
217 if (!node->isElementNode()) | 318 if (!node->isElementNode()) |
218 continue; | 319 continue; |
219 | 320 |
220 Element* element = toElement(node); | 321 Element* element = toElement(node); |
221 // We have to process in-line style as it might contain some resources ( typically background images). | 322 // We have to process in-line style as it might contain some resources ( typically background images). |
222 if (element->isStyledElement()) | 323 if (element->isStyledElement()) { |
223 retrieveResourcesForProperties(element->inlineStyle(), document); | 324 retrieveResourcesForProperties(element->inlineStyle(), document); |
325 retrieveResourcesForProperties(element->presentationAttributeStyle() , document); | |
326 } | |
224 | 327 |
225 if (element->hasTagName(HTMLNames::imgTag)) { | 328 if (element->hasTagName(HTMLNames::imgTag)) { |
226 HTMLImageElement* imageElement = toHTMLImageElement(element); | 329 HTMLImageElement* imageElement = toHTMLImageElement(element); |
227 KURL url = document->completeURL(imageElement->getAttribute(HTMLName s::srcAttr)); | 330 KURL url = document->completeURL(imageElement->getAttribute(HTMLName s::srcAttr)); |
228 ImageResource* cachedImage = imageElement->cachedImage(); | 331 ImageResource* cachedImage = imageElement->cachedImage(); |
229 addImageToResources(cachedImage, imageElement->renderer(), url); | 332 addImageToResources(cachedImage, imageElement->renderer(), url); |
230 } else if (element->hasTagName(HTMLNames::inputTag)) { | 333 } else if (element->hasTagName(HTMLNames::inputTag)) { |
231 HTMLInputElement* inputElement = toHTMLInputElement(element); | 334 HTMLInputElement* inputElement = toHTMLInputElement(element); |
232 if (inputElement->isImageButton() && inputElement->hasImageLoader()) { | 335 if (inputElement->isImageButton() && inputElement->hasImageLoader()) { |
233 KURL url = inputElement->src(); | 336 KURL url = inputElement->src(); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
304 String mimeType = resource->response().mimeType(); | 407 String mimeType = resource->response().mimeType(); |
305 m_resources->append(SerializedResource(url, mimeType, data)); | 408 m_resources->append(SerializedResource(url, mimeType, data)); |
306 m_resourceURLs.add(url); | 409 m_resourceURLs.add(url); |
307 } | 410 } |
308 | 411 |
309 void PageSerializer::addImageToResources(ImageResource* image, RenderObject* ima geRenderer, const KURL& url) | 412 void PageSerializer::addImageToResources(ImageResource* image, RenderObject* ima geRenderer, const KURL& url) |
310 { | 413 { |
311 if (!shouldAddURL(url)) | 414 if (!shouldAddURL(url)) |
312 return; | 415 return; |
313 | 416 |
314 if (!image || image->image() == Image::nullImage()) | 417 if (!image->hasImage() || image->image() == Image::nullImage()) |
315 return; | 418 return; |
316 | 419 |
317 RefPtr<SharedBuffer> data = imageRenderer ? image->imageForRenderer(imageRen derer)->data() : 0; | 420 RefPtr<SharedBuffer> data = imageRenderer ? image->imageForRenderer(imageRen derer)->data() : 0; |
318 if (!data) | 421 if (!data) |
319 data = image->image()->data(); | 422 data = image->image()->data(); |
320 | 423 |
321 addToResources(image, data, url); | 424 addToResources(image, data, url); |
322 } | 425 } |
323 | 426 |
324 void PageSerializer::addFontToResources(FontResource* font) | 427 void PageSerializer::addFontToResources(FontResource* font) |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
376 if (iter != m_blankFrameURLs.end()) | 479 if (iter != m_blankFrameURLs.end()) |
377 return iter->value; | 480 return iter->value; |
378 String url = "wyciwyg://frame/" + String::number(m_blankFrameCounter++); | 481 String url = "wyciwyg://frame/" + String::number(m_blankFrameCounter++); |
379 KURL fakeURL(ParsedURLString, url); | 482 KURL fakeURL(ParsedURLString, url); |
380 m_blankFrameURLs.add(frame, fakeURL); | 483 m_blankFrameURLs.add(frame, fakeURL); |
381 | 484 |
382 return fakeURL; | 485 return fakeURL; |
383 } | 486 } |
384 | 487 |
385 } | 488 } |
489 | |
abarth-chromium
2013/11/14 16:55:03
No need for this blank line.
| |
OLD | NEW |