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" | |
57 #include "core/html/parser/HTMLMetaCharsetParser.h" | 56 #include "core/html/parser/HTMLMetaCharsetParser.h" |
58 #include "core/frame/Frame.h" | 57 #include "core/frame/Frame.h" |
59 #include "core/page/Page.h" | 58 #include "core/page/Page.h" |
60 #include "core/platform/graphics/Image.h" | 59 #include "core/platform/graphics/Image.h" |
61 #include "core/rendering/RenderImage.h" | 60 #include "core/rendering/RenderImage.h" |
62 #include "core/rendering/style/StyleFetchedImage.h" | 61 #include "core/rendering/style/StyleFetchedImage.h" |
63 #include "core/rendering/style/StyleImage.h" | 62 #include "core/rendering/style/StyleImage.h" |
64 #include "platform/SerializedResource.h" | 63 #include "platform/SerializedResource.h" |
65 #include "wtf/text/CString.h" | 64 #include "wtf/text/CString.h" |
66 #include "wtf/text/StringBuilder.h" | 65 #include "wtf/text/StringBuilder.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 // FIXME: We should support all frame owners including applets. | 98 // FIXME: We should support all frame owners including applets. |
100 return frameOwner.hasTagName(HTMLNames::objectTag) ? HTMLNames::dataAttr : H
TMLNames::srcAttr; | 99 return frameOwner.hasTagName(HTMLNames::objectTag) ? HTMLNames::dataAttr : H
TMLNames::srcAttr; |
101 } | 100 } |
102 | 101 |
103 class SerializerMarkupAccumulator : public WebCore::MarkupAccumulator { | 102 class SerializerMarkupAccumulator : public WebCore::MarkupAccumulator { |
104 public: | 103 public: |
105 SerializerMarkupAccumulator(PageSerializer*, Document*, Vector<Node*>*); | 104 SerializerMarkupAccumulator(PageSerializer*, Document*, Vector<Node*>*); |
106 virtual ~SerializerMarkupAccumulator(); | 105 virtual ~SerializerMarkupAccumulator(); |
107 | 106 |
108 protected: | 107 protected: |
109 virtual void appendText(StringBuilder&, Text*) OVERRIDE; | 108 virtual void appendText(StringBuilder& out, Text*); |
110 virtual void appendElement(StringBuilder&, Element*, Namespaces*) OVERRIDE; | 109 virtual void appendElement(StringBuilder& out, Element*, Namespaces*); |
111 virtual void appendCustomAttributes(StringBuilder&, Element*, Namespaces*) O
VERRIDE; | 110 virtual void appendCustomAttributes(StringBuilder& out, Element*, Namespaces
*); |
112 virtual void appendEndTag(Node*) OVERRIDE; | 111 virtual void appendEndTag(Node*); |
113 | 112 |
| 113 private: |
114 PageSerializer* m_serializer; | 114 PageSerializer* m_serializer; |
115 Document* m_document; | 115 Document* m_document; |
116 }; | 116 }; |
117 | 117 |
118 SerializerMarkupAccumulator::SerializerMarkupAccumulator(PageSerializer* seriali
zer, Document* document, Vector<Node*>* nodes) | 118 SerializerMarkupAccumulator::SerializerMarkupAccumulator(PageSerializer* seriali
zer, Document* document, Vector<Node*>* nodes) |
119 : MarkupAccumulator(nodes, ResolveAllURLs) | 119 : MarkupAccumulator(nodes, ResolveAllURLs) |
120 , m_serializer(serializer) | 120 , m_serializer(serializer) |
121 , m_document(document) | 121 , m_document(document) |
122 { | 122 { |
123 } | 123 } |
124 | 124 |
125 SerializerMarkupAccumulator::~SerializerMarkupAccumulator() | 125 SerializerMarkupAccumulator::~SerializerMarkupAccumulator() |
126 { | 126 { |
127 } | 127 } |
128 | 128 |
129 void SerializerMarkupAccumulator::appendText(StringBuilder& result, Text* text) | 129 void SerializerMarkupAccumulator::appendText(StringBuilder& out, Text* text) |
130 { | 130 { |
131 Element* parent = text->parentElement(); | 131 Element* parent = text->parentElement(); |
132 if (parent && !shouldIgnoreElement(parent)) | 132 if (parent && !shouldIgnoreElement(parent)) |
133 MarkupAccumulator::appendText(result, text); | 133 MarkupAccumulator::appendText(out, text); |
134 } | 134 } |
135 | 135 |
136 void SerializerMarkupAccumulator::appendElement(StringBuilder& result, Element*
element, Namespaces* namespaces) | 136 void SerializerMarkupAccumulator::appendElement(StringBuilder& out, Element* ele
ment, Namespaces* namespaces) |
137 { | 137 { |
138 if (!shouldIgnoreElement(element)) | 138 if (!shouldIgnoreElement(element)) |
139 MarkupAccumulator::appendElement(result, element, namespaces); | 139 MarkupAccumulator::appendElement(out, element, namespaces); |
140 | 140 |
141 // FIXME: Refactor MarkupAccumulator so it is easier to append an element li
ke this, without special cases for XHTML | |
142 if (element->hasTagName(HTMLNames::headTag)) { | 141 if (element->hasTagName(HTMLNames::headTag)) { |
143 result.appendLiteral("<meta charset=\""); | 142 out.append("<meta charset=\""); |
144 result.append(m_document->charset()); | 143 out.append(m_document->charset()); |
145 if (m_document->isXHTMLDocument()) | 144 out.append("\">"); |
146 result.appendLiteral("\" />"); | |
147 else | |
148 result.appendLiteral("\">"); | |
149 } | 145 } |
150 | 146 |
151 // FIXME: For object (plugins) tags and video tag we could replace them by a
n image of their current contents. | 147 // FIXME: For object (plugins) tags and video tag we could replace them by a
n image of their current contents. |
152 } | 148 } |
153 | 149 |
154 void SerializerMarkupAccumulator::appendCustomAttributes(StringBuilder& result,
Element* element, Namespaces* namespaces) | 150 void SerializerMarkupAccumulator::appendCustomAttributes(StringBuilder& out, Ele
ment* element, Namespaces* namespaces) |
155 { | 151 { |
156 if (!element->isFrameOwnerElement()) | 152 if (!element->isFrameOwnerElement()) |
157 return; | 153 return; |
158 | 154 |
159 HTMLFrameOwnerElement* frameOwner = toHTMLFrameOwnerElement(element); | 155 HTMLFrameOwnerElement* frameOwner = toHTMLFrameOwnerElement(element); |
160 Frame* frame = frameOwner->contentFrame(); | 156 Frame* frame = frameOwner->contentFrame(); |
161 if (!frame) | 157 if (!frame) |
162 return; | 158 return; |
163 | 159 |
164 KURL url = frame->document()->url(); | 160 KURL url = frame->document()->url(); |
165 if (url.isValid() && !url.isBlankURL()) | 161 if (url.isValid() && !url.isBlankURL()) |
166 return; | 162 return; |
167 | 163 |
168 // We need to give a fake location to blank frames so they can be referenced
by the serialized frame. | 164 // We need to give a fake location to blank frames so they can be referenced
by the serialized frame. |
169 url = m_serializer->urlForBlankFrame(frame); | 165 url = m_serializer->urlForBlankFrame(frame); |
170 appendAttribute(result, element, Attribute(frameOwnerURLAttributeName(*frame
Owner), url.string()), namespaces); | 166 appendAttribute(out, element, Attribute(frameOwnerURLAttributeName(*frameOwn
er), url.string()), namespaces); |
171 } | 167 } |
172 | 168 |
173 void SerializerMarkupAccumulator::appendEndTag(Node* node) | 169 void SerializerMarkupAccumulator::appendEndTag(Node* node) |
174 { | 170 { |
175 if (node->isElementNode() && !shouldIgnoreElement(toElement(node))) | 171 if (node->isElementNode() && !shouldIgnoreElement(toElement(node))) |
176 MarkupAccumulator::appendEndTag(node); | 172 MarkupAccumulator::appendEndTag(node); |
177 } | 173 } |
178 | 174 |
179 class LinkChangeSerializerMarkupAccumulator : public SerializerMarkupAccumulator
{ | 175 PageSerializer::PageSerializer(Vector<SerializedResource>* resources) |
180 public: | |
181 LinkChangeSerializerMarkupAccumulator(PageSerializer*, Document*, Vector<Nod
e*>*, LinkLocalPathMap*, String); | |
182 | |
183 protected: | |
184 virtual void appendElement(StringBuilder&, Element*, Namespaces*) OVERRIDE; | |
185 virtual void appendAttribute(StringBuilder&, Element*, const Attribute&, Nam
espaces*) OVERRIDE; | |
186 | |
187 private: | |
188 // m_replaceLinks include all pair of local resource path and corresponding
original link. | |
189 LinkLocalPathMap* m_replaceLinks; | |
190 String m_directoryName; | |
191 }; | |
192 | |
193 LinkChangeSerializerMarkupAccumulator::LinkChangeSerializerMarkupAccumulator(Pag
eSerializer* serializer, Document* document, Vector<Node*>* nodes, LinkLocalPath
Map* links, String directoryName) | |
194 : SerializerMarkupAccumulator(serializer, document, nodes) | |
195 , m_replaceLinks(links) | |
196 , m_directoryName(directoryName) | |
197 { | |
198 } | |
199 | |
200 void LinkChangeSerializerMarkupAccumulator::appendElement(StringBuilder& result,
Element* element, Namespaces* namespaces) | |
201 { | |
202 // FIXME: We could move the uncommenting to appendOpenTag and appendCloseTag
, or just remove it | |
203 if (element->hasTagName(HTMLNames::baseTag)) { | |
204 // Comment the BASE tag when serializing dom. | |
205 result.append("<!--"); | |
206 } else if (element->hasTagName(HTMLNames::htmlTag)) { | |
207 // Add MOTW (Mark of the Web) declaration before html tag. | |
208 // See http://msdn2.microsoft.com/en-us/library/ms537628(VS.85).aspx. | |
209 result.append(String::format("\n<!-- saved from url=(%04d)%s -->\n", | |
210 static_cast<int>(m_document->url().string().utf8().length()), | |
211 m_document->url().string().utf8().data())); | |
212 } | |
213 | |
214 SerializerMarkupAccumulator::appendElement(result, element, namespaces); | |
215 | |
216 if (element->hasTagName(HTMLNames::baseTag)) { | |
217 // Comment the BASE tag when serializing dom. | |
218 result.appendLiteral("-->"); | |
219 | |
220 // FIXME: Refactor MarkupAccumulator so it is easier to append an elemen
t like this, without special cases for XHTML | |
221 // Append a new base tag declaration. | |
222 result.appendLiteral("<base href=\".\""); | |
223 if (!m_document->baseTarget().isEmpty()) { | |
224 result.appendLiteral(" target=\""); | |
225 result.append(m_document->baseTarget()); | |
226 result.append('"'); | |
227 } | |
228 if (m_document->isXHTMLDocument()) | |
229 result.appendLiteral(" />"); | |
230 else | |
231 result.appendLiteral(">"); | |
232 } | |
233 } | |
234 void LinkChangeSerializerMarkupAccumulator::appendAttribute(StringBuilder& resul
t, Element* element, const Attribute& attribute, Namespaces* namespaces) | |
235 { | |
236 if (m_replaceLinks && element->isURLAttribute(attribute) && !element->isJava
ScriptURLAttribute(attribute)) { | |
237 | |
238 String completeURL = m_document->completeURL(attribute.value()); | |
239 | |
240 if (m_replaceLinks->contains(completeURL)) { | |
241 // FIXME: Refactor MarkupAccumulator so it is easier to append an at
tribute like this. | |
242 result.append(' '); | |
243 result.append(attribute.name().toString()); | |
244 result.appendLiteral("=\""); | |
245 if (!m_directoryName.isEmpty()) { | |
246 result.appendLiteral("./"); | |
247 result.append(m_directoryName); | |
248 result.append('/'); | |
249 } | |
250 result.append(m_replaceLinks->get(completeURL)); | |
251 result.appendLiteral("\""); | |
252 return; | |
253 } | |
254 } | |
255 MarkupAccumulator::appendAttribute(result, element, attribute, namespaces); | |
256 } | |
257 | |
258 PageSerializer::PageSerializer(Vector<SerializedResource>* resources, LinkLocalP
athMap* urls, String directory) | |
259 : m_resources(resources) | 176 : m_resources(resources) |
260 , m_URLs(urls) | |
261 , m_directory(directory) | |
262 , m_blankFrameCounter(0) | 177 , m_blankFrameCounter(0) |
263 { | 178 { |
264 } | 179 } |
265 | 180 |
266 void PageSerializer::serialize(Page* page) | 181 void PageSerializer::serialize(Page* page) |
267 { | 182 { |
268 serializeFrame(page->mainFrame()); | 183 serializeFrame(page->mainFrame()); |
269 } | 184 } |
270 | 185 |
271 void PageSerializer::serializeFrame(Frame* frame) | 186 void PageSerializer::serializeFrame(Frame* frame) |
272 { | 187 { |
273 Document* document = frame->document(); | 188 Document* document = frame->document(); |
274 KURL url = document->url(); | 189 KURL url = document->url(); |
275 if (!url.isValid() || url.isBlankURL()) { | 190 if (!url.isValid() || url.isBlankURL()) { |
276 // For blank frames we generate a fake URL so they can be referenced by
their containing frame. | 191 // For blank frames we generate a fake URL so they can be referenced by
their containing frame. |
277 url = urlForBlankFrame(frame); | 192 url = urlForBlankFrame(frame); |
278 } | 193 } |
279 | 194 |
280 if (m_resourceURLs.contains(url)) { | 195 if (m_resourceURLs.contains(url)) { |
281 // FIXME: We could have 2 frame with the same URL but which were dynamic
ally changed and have now | 196 // FIXME: We could have 2 frame with the same URL but which were dynamic
ally changed and have now |
282 // different content. So we should serialize both and somehow rename the
frame src in the containing | 197 // different content. So we should serialize both and somehow rename the
frame src in the containing |
283 // frame. Arg! | 198 // frame. Arg! |
284 return; | 199 return; |
285 } | 200 } |
286 | 201 |
287 // If frame is an image document, add the image and don't continue | |
288 if (document->isImageDocument()) { | |
289 ImageDocument* imageDocument = toImageDocument(document); | |
290 addImageToResources(imageDocument->cachedImage(), imageDocument->imageEl
ement()->renderer(), url); | |
291 return; | |
292 } | |
293 | |
294 Vector<Node*> nodes; | 202 Vector<Node*> nodes; |
295 OwnPtr<SerializerMarkupAccumulator> accumulator; | 203 SerializerMarkupAccumulator accumulator(this, document, &nodes); |
296 if (m_URLs) | |
297 accumulator = adoptPtr(new LinkChangeSerializerMarkupAccumulator(this, d
ocument, &nodes, m_URLs, m_directory)); | |
298 else | |
299 accumulator = adoptPtr(new SerializerMarkupAccumulator(this, document, &
nodes)); | |
300 String text = accumulator->serializeNodes(document, IncludeNode); | |
301 WTF::TextEncoding textEncoding(document->charset()); | 204 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); |
302 CString frameHTML = textEncoding.normalizeAndEncode(text, WTF::EntitiesForUn
encodables); | 211 CString frameHTML = textEncoding.normalizeAndEncode(text, WTF::EntitiesForUn
encodables); |
303 m_resources->append(SerializedResource(url, document->suggestedMIMEType(), S
haredBuffer::create(frameHTML.data(), frameHTML.length()))); | 212 m_resources->append(SerializedResource(url, document->suggestedMIMEType(), S
haredBuffer::create(frameHTML.data(), frameHTML.length()))); |
304 m_resourceURLs.add(url); | 213 m_resourceURLs.add(url); |
305 | 214 |
306 for (Vector<Node*>::iterator iter = nodes.begin(); iter != nodes.end(); ++it
er) { | 215 for (Vector<Node*>::iterator iter = nodes.begin(); iter != nodes.end(); ++it
er) { |
307 Node* node = *iter; | 216 Node* node = *iter; |
308 if (!node->isElementNode()) | 217 if (!node->isElementNode()) |
309 continue; | 218 continue; |
310 | 219 |
311 Element* element = toElement(node); | 220 Element* element = toElement(node); |
312 // We have to process in-line style as it might contain some resources (
typically background images). | 221 // We have to process in-line style as it might contain some resources (
typically background images). |
313 if (element->isStyledElement()) { | 222 if (element->isStyledElement()) |
314 retrieveResourcesForProperties(element->inlineStyle(), document); | 223 retrieveResourcesForProperties(element->inlineStyle(), document); |
315 retrieveResourcesForProperties(element->presentationAttributeStyle()
, document); | |
316 } | |
317 | 224 |
318 if (element->hasTagName(HTMLNames::imgTag)) { | 225 if (element->hasTagName(HTMLNames::imgTag)) { |
319 HTMLImageElement* imageElement = toHTMLImageElement(element); | 226 HTMLImageElement* imageElement = toHTMLImageElement(element); |
320 KURL url = document->completeURL(imageElement->getAttribute(HTMLName
s::srcAttr)); | 227 KURL url = document->completeURL(imageElement->getAttribute(HTMLName
s::srcAttr)); |
321 ImageResource* cachedImage = imageElement->cachedImage(); | 228 ImageResource* cachedImage = imageElement->cachedImage(); |
322 addImageToResources(cachedImage, imageElement->renderer(), url); | 229 addImageToResources(cachedImage, imageElement->renderer(), url); |
323 } else if (element->hasTagName(HTMLNames::inputTag)) { | 230 } else if (element->hasTagName(HTMLNames::inputTag)) { |
324 HTMLInputElement* inputElement = toHTMLInputElement(element); | 231 HTMLInputElement* inputElement = toHTMLInputElement(element); |
325 if (inputElement->isImageButton() && inputElement->hasImageLoader())
{ | 232 if (inputElement->isImageButton() && inputElement->hasImageLoader())
{ |
326 KURL url = inputElement->src(); | 233 KURL url = inputElement->src(); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 String mimeType = resource->response().mimeType(); | 304 String mimeType = resource->response().mimeType(); |
398 m_resources->append(SerializedResource(url, mimeType, data)); | 305 m_resources->append(SerializedResource(url, mimeType, data)); |
399 m_resourceURLs.add(url); | 306 m_resourceURLs.add(url); |
400 } | 307 } |
401 | 308 |
402 void PageSerializer::addImageToResources(ImageResource* image, RenderObject* ima
geRenderer, const KURL& url) | 309 void PageSerializer::addImageToResources(ImageResource* image, RenderObject* ima
geRenderer, const KURL& url) |
403 { | 310 { |
404 if (!shouldAddURL(url)) | 311 if (!shouldAddURL(url)) |
405 return; | 312 return; |
406 | 313 |
407 if (!image || !image->hasImage() || image->image() == Image::nullImage()) | 314 if (!image || image->image() == Image::nullImage()) |
408 return; | 315 return; |
409 | 316 |
410 RefPtr<SharedBuffer> data = imageRenderer ? image->imageForRenderer(imageRen
derer)->data() : 0; | 317 RefPtr<SharedBuffer> data = imageRenderer ? image->imageForRenderer(imageRen
derer)->data() : 0; |
411 if (!data) | 318 if (!data) |
412 data = image->image()->data(); | 319 data = image->image()->data(); |
413 | 320 |
414 addToResources(image, data, url); | 321 addToResources(image, data, url); |
415 } | 322 } |
416 | 323 |
417 void PageSerializer::addFontToResources(FontResource* font) | 324 void PageSerializer::addFontToResources(FontResource* font) |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 if (iter != m_blankFrameURLs.end()) | 376 if (iter != m_blankFrameURLs.end()) |
470 return iter->value; | 377 return iter->value; |
471 String url = "wyciwyg://frame/" + String::number(m_blankFrameCounter++); | 378 String url = "wyciwyg://frame/" + String::number(m_blankFrameCounter++); |
472 KURL fakeURL(ParsedURLString, url); | 379 KURL fakeURL(ParsedURLString, url); |
473 m_blankFrameURLs.add(frame, fakeURL); | 380 m_blankFrameURLs.add(frame, fakeURL); |
474 | 381 |
475 return fakeURL; | 382 return fakeURL; |
476 } | 383 } |
477 | 384 |
478 } | 385 } |
OLD | NEW |