| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2009 Google Inc. All rights reserved. | 2 * Copyright (C) 2009 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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 #include "web/WebPageSerializerImpl.h" | 79 #include "web/WebPageSerializerImpl.h" |
| 80 | 80 |
| 81 #include "core/HTMLNames.h" | 81 #include "core/HTMLNames.h" |
| 82 #include "core/dom/Document.h" | 82 #include "core/dom/Document.h" |
| 83 #include "core/dom/DocumentType.h" | 83 #include "core/dom/DocumentType.h" |
| 84 #include "core/dom/Element.h" | 84 #include "core/dom/Element.h" |
| 85 #include "core/editing/serializers/Serialization.h" | 85 #include "core/editing/serializers/Serialization.h" |
| 86 #include "core/html/HTMLAllCollection.h" | 86 #include "core/html/HTMLAllCollection.h" |
| 87 #include "core/html/HTMLElement.h" | 87 #include "core/html/HTMLElement.h" |
| 88 #include "core/html/HTMLFormElement.h" | 88 #include "core/html/HTMLFormElement.h" |
| 89 #include "core/html/HTMLFrameElementBase.h" |
| 89 #include "core/html/HTMLHtmlElement.h" | 90 #include "core/html/HTMLHtmlElement.h" |
| 90 #include "core/html/HTMLMetaElement.h" | 91 #include "core/html/HTMLMetaElement.h" |
| 91 #include "core/loader/DocumentLoader.h" | 92 #include "core/loader/DocumentLoader.h" |
| 92 #include "core/loader/FrameLoader.h" | 93 #include "core/loader/FrameLoader.h" |
| 93 #include "public/platform/WebVector.h" | 94 #include "public/platform/WebVector.h" |
| 94 #include "web/WebLocalFrameImpl.h" | 95 #include "web/WebLocalFrameImpl.h" |
| 95 #include "wtf/text/TextEncoding.h" | 96 #include "wtf/text/TextEncoding.h" |
| 96 | 97 |
| 97 namespace blink { | 98 namespace blink { |
| 98 | 99 |
| 99 // Maximum length of data buffer which is used to temporary save generated | 100 // Maximum length of data buffer which is used to temporary save generated |
| 100 // html content data. This is a soft limit which might be passed if a very large | 101 // html content data. This is a soft limit which might be passed if a very large |
| 101 // contegious string is found in the page. | 102 // contegious string is found in the page. |
| 102 static const unsigned dataBufferCapacity = 65536; | 103 static const unsigned dataBufferCapacity = 65536; |
| 103 | 104 |
| 104 WebPageSerializerImpl::SerializeDomParam::SerializeDomParam(const KURL& url, | 105 WebPageSerializerImpl::SerializeDomParam::SerializeDomParam(const KURL& url, |
| 105 const WTF::TextEncod
ing& textEncoding, | 106 const WTF::TextEncod
ing& textEncoding, |
| 106 Document* document, | 107 Document* document) |
| 107 const String& direct
oryName) | |
| 108 : url(url) | 108 : url(url) |
| 109 , textEncoding(textEncoding) | 109 , textEncoding(textEncoding) |
| 110 , document(document) | 110 , document(document) |
| 111 , directoryName(directoryName) | |
| 112 , isHTMLDocument(document->isHTMLDocument()) | 111 , isHTMLDocument(document->isHTMLDocument()) |
| 113 , haveSeenDocType(false) | 112 , haveSeenDocType(false) |
| 114 , haveAddedCharsetDeclaration(false) | 113 , haveAddedCharsetDeclaration(false) |
| 115 , skipMetaElement(nullptr) | 114 , skipMetaElement(nullptr) |
| 116 , isInScriptOrStyleTag(false) | 115 , isInScriptOrStyleTag(false) |
| 117 , haveAddedXMLProcessingDirective(false) | 116 , haveAddedXMLProcessingDirective(false) |
| 118 , haveAddedContentsBeforeEnd(false) | 117 , haveAddedContentsBeforeEnd(false) |
| 119 { | 118 { |
| 120 } | 119 } |
| 121 | 120 |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 param->document->baseTarget())); | 254 param->document->baseTarget())); |
| 256 } | 255 } |
| 257 | 256 |
| 258 return result.toString(); | 257 return result.toString(); |
| 259 } | 258 } |
| 260 | 259 |
| 261 void WebPageSerializerImpl::saveHTMLContentToBuffer( | 260 void WebPageSerializerImpl::saveHTMLContentToBuffer( |
| 262 const String& result, SerializeDomParam* param) | 261 const String& result, SerializeDomParam* param) |
| 263 { | 262 { |
| 264 m_dataBuffer.append(result); | 263 m_dataBuffer.append(result); |
| 265 encodeAndFlushBuffer(WebPageSerializerClient::CurrentFrameIsNotFinished, | 264 encodeAndFlushBuffer(param, DoNotForceFlush); |
| 266 param, | |
| 267 DoNotForceFlush); | |
| 268 } | 265 } |
| 269 | 266 |
| 270 void WebPageSerializerImpl::encodeAndFlushBuffer( | 267 void WebPageSerializerImpl::encodeAndFlushBuffer( |
| 271 WebPageSerializerClient::PageSerializationStatus status, | |
| 272 SerializeDomParam* param, | 268 SerializeDomParam* param, |
| 273 FlushOption flushOption) | 269 FlushOption flushOption) |
| 274 { | 270 { |
| 275 // Data buffer is not full nor do we want to force flush. | 271 // Data buffer is not full nor do we want to force flush. |
| 276 if (flushOption != ForceFlush && m_dataBuffer.length() <= dataBufferCapacity
) | 272 if (flushOption != ForceFlush && m_dataBuffer.length() <= dataBufferCapacity
) |
| 277 return; | 273 return; |
| 278 | 274 |
| 279 String content = m_dataBuffer.toString(); | 275 String content = m_dataBuffer.toString(); |
| 280 m_dataBuffer.clear(); | 276 m_dataBuffer.clear(); |
| 281 | 277 |
| 282 CString encodedContent = param->textEncoding.normalizeAndEncode(content, WTF
::EntitiesForUnencodables); | 278 CString encodedContent = param->textEncoding.normalizeAndEncode(content, WTF
::EntitiesForUnencodables); |
| 283 | 279 |
| 284 // Send result to the client. | 280 // Send result to the client. |
| 285 m_client->didSerializeDataForFrame(param->url, | 281 m_client->writeHtmlFragment(WebCString(encodedContent.data(), encodedContent
.length())); |
| 286 WebCString(encodedContent.data(), encoded
Content.length()), | |
| 287 status); | |
| 288 } | 282 } |
| 289 | 283 |
| 290 void WebPageSerializerImpl::openTagToString(Element* element, | 284 void WebPageSerializerImpl::handleOpenTag( |
| 291 SerializeDomParam* param) | 285 Element* element, SerializeDomParam* param) |
| 292 { | 286 { |
| 293 bool needSkip; | 287 bool needSkip; |
| 294 StringBuilder result; | 288 StringBuilder result; |
| 295 // Do pre action for open tag. | 289 // Do pre action for open tag. |
| 296 result.append(preActionBeforeSerializeOpenTag(element, param, &needSkip)); | 290 result.append(preActionBeforeSerializeOpenTag(element, param, &needSkip)); |
| 297 if (needSkip) | 291 if (needSkip) |
| 298 return; | 292 return; |
| 299 // Add open tag | 293 // Add open tag |
| 300 result.append('<'); | 294 result.append('<'); |
| 301 result.append(element->nodeName().lower()); | 295 result.append(element->nodeName().lower()); |
| 302 // Go through all attributes and serialize them. | 296 // Go through all attributes and serialize them. |
| 303 AttributeCollection attributes = element->attributes(); | 297 AttributeCollection attributes = element->attributes(); |
| 304 AttributeCollection::iterator end = attributes.end(); | 298 AttributeCollection::iterator end = attributes.end(); |
| 305 for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it)
{ | 299 for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it)
{ |
| 306 result.append(' '); | 300 result.append(' '); |
| 307 // Add attribute pair | 301 // Add attribute pair |
| 308 result.append(it->name().toString()); | 302 result.append(it->name().toString()); |
| 309 result.appendLiteral("=\""); | 303 result.appendLiteral("=\""); |
| 310 if (!it->value().isEmpty()) { | 304 if (!it->value().isEmpty()) { |
| 311 const String& attrValue = it->value(); | 305 const String& attrValue = it->value(); |
| 312 | 306 |
| 313 // Check whether we need to replace some resource links | 307 // Check whether we need to replace some resource links |
| 314 // with local resource paths. | 308 // with local resource paths. |
| 315 const QualifiedName& attrName = it->name(); | 309 const QualifiedName& attrName = it->name(); |
| 316 if (element->hasLegalLinkAttribute(attrName)) { | 310 if (element->hasLegalLinkAttribute(attrName)) { |
| 317 // For links start with "javascript:", we do not change it. | 311 // For links start with "javascript:", we do not change it. |
| 318 if (attrValue.startsWith("javascript:", TextCaseInsensitive)) { | 312 if (attrValue.startsWith("javascript:", TextCaseInsensitive)) { |
| 319 result.append(attrValue); | 313 result.append(attrValue); |
| 320 } else { | 314 } else { |
| 321 // Get the absolute link | 315 saveHTMLContentToBuffer(result.toString(), param); |
| 322 WebLocalFrameImpl* subFrame = WebLocalFrameImpl::fromFrameOw
nerElement(element); | 316 encodeAndFlushBuffer(param, ForceFlush); |
| 323 String completeURL = subFrame ? subFrame->frame()->document(
)->url() : | 317 result.clear(); |
| 324 param->document->completeURL
(attrValue); | 318 |
| 325 // Check whether we have local files for those link. | 319 handleLinkAttr(element, param, attrValue); |
| 326 if (m_localLinks.contains(completeURL)) { | |
| 327 if (!param->directoryName.isEmpty()) { | |
| 328 result.appendLiteral("./"); | |
| 329 result.append(param->directoryName); | |
| 330 result.append('/'); | |
| 331 } | |
| 332 result.append(m_localLinks.get(completeURL)); | |
| 333 } else { | |
| 334 result.append(completeURL); | |
| 335 } | |
| 336 } | 320 } |
| 337 } else { | 321 } else { |
| 338 if (param->isHTMLDocument) | 322 if (param->isHTMLDocument) |
| 339 result.append(m_htmlEntities.convertEntitiesInString(attrVal
ue)); | 323 result.append(m_htmlEntities.convertEntitiesInString(attrVal
ue)); |
| 340 else | 324 else |
| 341 result.append(m_xmlEntities.convertEntitiesInString(attrValu
e)); | 325 result.append(m_xmlEntities.convertEntitiesInString(attrValu
e)); |
| 342 } | 326 } |
| 343 } | 327 } |
| 344 result.append('\"'); | 328 result.append('\"'); |
| 345 } | 329 } |
| 346 | 330 |
| 347 // Do post action for open tag. | 331 // Do post action for open tag. |
| 348 String addedContents = postActionAfterSerializeOpenTag(element, param); | 332 String addedContents = postActionAfterSerializeOpenTag(element, param); |
| 349 // Complete the open tag for element when it has child/children. | 333 // Complete the open tag for element when it has child/children. |
| 350 if (element->hasChildren() || param->haveAddedContentsBeforeEnd) | 334 if (element->hasChildren() || param->haveAddedContentsBeforeEnd) |
| 351 result.append('>'); | 335 result.append('>'); |
| 352 // Append the added contents generate in post action of open tag. | 336 // Append the added contents generate in post action of open tag. |
| 353 result.append(addedContents); | 337 result.append(addedContents); |
| 354 // Save the result to data buffer. | 338 // Save the result to data buffer. |
| 355 saveHTMLContentToBuffer(result.toString(), param); | 339 saveHTMLContentToBuffer(result.toString(), param); |
| 356 } | 340 } |
| 357 | 341 |
| 342 void WebPageSerializerImpl::handleLinkAttr( |
| 343 Element* element, SerializeDomParam* param, const String& attrValue) |
| 344 { |
| 345 if (isHTMLFrameElementBase(element)) { |
| 346 WebFrame* subFrame = WebFrame::fromFrame( |
| 347 toHTMLFrameElementBase(element)->contentFrame()); |
| 348 m_client->writeLocalPathForSubFrame(*subFrame); |
| 349 } else { |
| 350 KURL completeURL = param->document->completeURL(attrValue); |
| 351 m_client->writeLocalPathForSavableResource(completeURL); |
| 352 } |
| 353 } |
| 354 |
| 358 // Serialize end tag of an specified element. | 355 // Serialize end tag of an specified element. |
| 359 void WebPageSerializerImpl::endTagToString(Element* element, | 356 void WebPageSerializerImpl::handleEndTag( |
| 360 SerializeDomParam* param) | 357 Element* element, SerializeDomParam* param) |
| 361 { | 358 { |
| 362 bool needSkip; | 359 bool needSkip; |
| 363 StringBuilder result; | 360 StringBuilder result; |
| 364 // Do pre action for end tag. | 361 // Do pre action for end tag. |
| 365 result.append(preActionBeforeSerializeEndTag(element, param, &needSkip)); | 362 result.append(preActionBeforeSerializeEndTag(element, param, &needSkip)); |
| 366 if (needSkip) | 363 if (needSkip) |
| 367 return; | 364 return; |
| 368 // Write end tag when element has child/children. | 365 // Write end tag when element has child/children. |
| 369 if (element->hasChildren() || param->haveAddedContentsBeforeEnd) { | 366 if (element->hasChildren() || param->haveAddedContentsBeforeEnd) { |
| 370 result.appendLiteral("</"); | 367 result.appendLiteral("</"); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 391 // Save the result to data buffer. | 388 // Save the result to data buffer. |
| 392 saveHTMLContentToBuffer(result.toString(), param); | 389 saveHTMLContentToBuffer(result.toString(), param); |
| 393 } | 390 } |
| 394 | 391 |
| 395 void WebPageSerializerImpl::buildContentForNode(Node* node, | 392 void WebPageSerializerImpl::buildContentForNode(Node* node, |
| 396 SerializeDomParam* param) | 393 SerializeDomParam* param) |
| 397 { | 394 { |
| 398 switch (node->nodeType()) { | 395 switch (node->nodeType()) { |
| 399 case Node::ELEMENT_NODE: | 396 case Node::ELEMENT_NODE: |
| 400 // Process open tag of element. | 397 // Process open tag of element. |
| 401 openTagToString(toElement(node), param); | 398 handleOpenTag(toElement(node), param); |
| 402 // Walk through the children nodes and process it. | 399 // Walk through the children nodes and process it. |
| 403 for (Node *child = node->firstChild(); child; child = child->nextSibling
()) | 400 for (Node *child = node->firstChild(); child; child = child->nextSibling
()) |
| 404 buildContentForNode(child, param); | 401 buildContentForNode(child, param); |
| 405 // Process end tag of element. | 402 // Process end tag of element. |
| 406 endTagToString(toElement(node), param); | 403 handleEndTag(toElement(node), param); |
| 407 break; | 404 break; |
| 408 case Node::TEXT_NODE: | 405 case Node::TEXT_NODE: |
| 409 saveHTMLContentToBuffer(createMarkup(node), param); | 406 saveHTMLContentToBuffer(createMarkup(node), param); |
| 410 break; | 407 break; |
| 411 case Node::ATTRIBUTE_NODE: | 408 case Node::ATTRIBUTE_NODE: |
| 412 case Node::DOCUMENT_NODE: | 409 case Node::DOCUMENT_NODE: |
| 413 case Node::DOCUMENT_FRAGMENT_NODE: | 410 case Node::DOCUMENT_FRAGMENT_NODE: |
| 414 // Should not exist. | 411 // Should not exist. |
| 415 ASSERT_NOT_REACHED(); | 412 ASSERT_NOT_REACHED(); |
| 416 break; | 413 break; |
| 417 // Document type node can be in DOM? | 414 // Document type node can be in DOM? |
| 418 case Node::DOCUMENT_TYPE_NODE: | 415 case Node::DOCUMENT_TYPE_NODE: |
| 419 param->haveSeenDocType = true; | 416 param->haveSeenDocType = true; |
| 420 default: | 417 default: |
| 421 // For other type node, call default action. | 418 // For other type node, call default action. |
| 422 saveHTMLContentToBuffer(createMarkup(node), param); | 419 saveHTMLContentToBuffer(createMarkup(node), param); |
| 423 break; | 420 break; |
| 424 } | 421 } |
| 425 } | 422 } |
| 426 | 423 |
| 427 WebPageSerializerImpl::WebPageSerializerImpl(WebFrame* frame, | 424 WebPageSerializerImpl::WebPageSerializerImpl( |
| 428 WebPageSerializerClient* client, | 425 WebFrame* frame, |
| 429 const WebVector<WebURL>& links, | 426 WebPageSerializerClient* client) |
| 430 const WebVector<WebString>& localPa
ths, | |
| 431 const WebString& localDirectoryName
) | |
| 432 : m_client(client) | 427 : m_client(client) |
| 433 , m_localDirectoryName(localDirectoryName) | |
| 434 , m_htmlEntities(false) | 428 , m_htmlEntities(false) |
| 435 , m_xmlEntities(true) | 429 , m_xmlEntities(true) |
| 436 { | 430 { |
| 437 // Must specify available webframe. | 431 // Must specify available webframe. |
| 438 ASSERT(frame); | 432 ASSERT(frame); |
| 439 m_specifiedWebLocalFrameImpl = toWebLocalFrameImpl(frame); | 433 m_specifiedWebLocalFrameImpl = toWebLocalFrameImpl(frame); |
| 440 // Make sure we have non 0 client. | 434 // Make sure we have non 0 client. |
| 441 ASSERT(client); | 435 ASSERT(client); |
| 442 // Build local resources map. | |
| 443 ASSERT(links.size() == localPaths.size()); | |
| 444 for (size_t i = 0; i < links.size(); i++) { | |
| 445 KURL url = links[i]; | |
| 446 ASSERT(!m_localLinks.contains(url.string())); | |
| 447 m_localLinks.set(url.string(), localPaths[i]); | |
| 448 } | |
| 449 | 436 |
| 450 ASSERT(m_dataBuffer.isEmpty()); | 437 ASSERT(m_dataBuffer.isEmpty()); |
| 451 } | 438 } |
| 452 | 439 |
| 453 bool WebPageSerializerImpl::serialize() | 440 bool WebPageSerializerImpl::serialize() |
| 454 { | 441 { |
| 455 bool didSerialization = false; | 442 bool didSerialization = false; |
| 456 KURL mainURL = m_specifiedWebLocalFrameImpl->frame()->document()->url(); | 443 KURL mainURL = m_specifiedWebLocalFrameImpl->frame()->document()->url(); |
| 457 | 444 |
| 458 WebLocalFrameImpl* webFrame = m_specifiedWebLocalFrameImpl; | 445 WebLocalFrameImpl* webFrame = m_specifiedWebLocalFrameImpl; |
| 459 Document* document = webFrame->frame()->document(); | 446 Document* document = webFrame->frame()->document(); |
| 460 const KURL& url = document->url(); | 447 const KURL& url = document->url(); |
| 461 | 448 |
| 462 if (url.isValid() && m_localLinks.contains(url.string())) { | 449 if (url.isValid()) { |
| 463 didSerialization = true; | 450 didSerialization = true; |
| 464 | 451 |
| 465 const WTF::TextEncoding& textEncoding = document->encoding().isValid() ?
document->encoding() : UTF8Encoding(); | 452 const WTF::TextEncoding& textEncoding = document->encoding().isValid() ?
document->encoding() : UTF8Encoding(); |
| 466 String directoryName = url == mainURL ? m_localDirectoryName : ""; | |
| 467 | 453 |
| 468 SerializeDomParam param(url, textEncoding, document, directoryName); | 454 SerializeDomParam param(url, textEncoding, document); |
| 469 | 455 |
| 470 Element* documentElement = document->documentElement(); | 456 Element* documentElement = document->documentElement(); |
| 471 if (documentElement) | 457 if (documentElement) |
| 472 buildContentForNode(documentElement, ¶m); | 458 buildContentForNode(documentElement, ¶m); |
| 473 | 459 |
| 474 encodeAndFlushBuffer(WebPageSerializerClient::CurrentFrameIsFinished, &p
aram, ForceFlush); | 460 encodeAndFlushBuffer(¶m, ForceFlush); |
| 475 } | 461 } |
| 476 | 462 |
| 477 ASSERT(m_dataBuffer.isEmpty()); | 463 ASSERT(m_dataBuffer.isEmpty()); |
| 478 m_client->didSerializeDataForFrame(KURL(), WebCString("", 0), WebPageSeriali
zerClient::AllFramesAreFinished); | 464 m_client->endOfFrame(); |
| 479 return didSerialization; | 465 return didSerialization; |
| 480 } | 466 } |
| 481 | 467 |
| 482 } // namespace blink | 468 } // namespace blink |
| OLD | NEW |