| 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 // TODO(yosin): We should utilize |MarkupFormatter| here to share code, | 284 // TODO(yosin): We should utilize |MarkupFormatter| here to share code, |
| 291 // especially escaping attribute values, done by |WebEntities| |m_htmlEntities| | 285 // especially escaping attribute values, done by |WebEntities| |m_htmlEntities| |
| 292 // and |m_xmlEntities|. | 286 // and |m_xmlEntities|. |
| 293 void WebPageSerializerImpl::openTagToString(Element* element, | 287 void WebPageSerializerImpl::openTagToString(Element* element, |
| 294 SerializeDomParam* param) | 288 SerializeDomParam* param) |
| 295 { | 289 { |
| 296 bool needSkip; | 290 bool needSkip; |
| 297 StringBuilder result; | 291 StringBuilder result; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 314 const String& attrValue = it->value(); | 308 const String& attrValue = it->value(); |
| 315 | 309 |
| 316 // Check whether we need to replace some resource links | 310 // Check whether we need to replace some resource links |
| 317 // with local resource paths. | 311 // with local resource paths. |
| 318 const QualifiedName& attrName = it->name(); | 312 const QualifiedName& attrName = it->name(); |
| 319 if (element->hasLegalLinkAttribute(attrName)) { | 313 if (element->hasLegalLinkAttribute(attrName)) { |
| 320 // For links start with "javascript:", we do not change it. | 314 // For links start with "javascript:", we do not change it. |
| 321 if (attrValue.startsWith("javascript:", TextCaseInsensitive)) { | 315 if (attrValue.startsWith("javascript:", TextCaseInsensitive)) { |
| 322 result.append(m_htmlEntities.convertEntitiesInString(attrVal
ue)); | 316 result.append(m_htmlEntities.convertEntitiesInString(attrVal
ue)); |
| 323 } else { | 317 } else { |
| 324 // Get the absolute link | 318 saveHTMLContentToBuffer(result.toString(), param); |
| 325 WebLocalFrameImpl* subFrame = WebLocalFrameImpl::fromFrameOw
nerElement(element); | 319 encodeAndFlushBuffer(param, ForceFlush); |
| 326 String completeURL = subFrame ? subFrame->frame()->document(
)->url() : | 320 result.clear(); |
| 327 param->document->completeURL
(attrValue); | 321 |
| 328 // Check whether we have local files for those link. | 322 handleLinkAttr(element, param, attrValue); |
| 329 if (m_localLinks.contains(completeURL)) { | |
| 330 if (!param->directoryName.isEmpty()) { | |
| 331 result.appendLiteral("./"); | |
| 332 result.append(param->directoryName); | |
| 333 result.append('/'); | |
| 334 } | |
| 335 result.append(m_htmlEntities.convertEntitiesInString(m_l
ocalLinks.get(completeURL))); | |
| 336 } else { | |
| 337 result.append(m_htmlEntities.convertEntitiesInString(com
pleteURL)); | |
| 338 } | |
| 339 } | 323 } |
| 340 } else { | 324 } else { |
| 341 if (param->isHTMLDocument) | 325 if (param->isHTMLDocument) |
| 342 result.append(m_htmlEntities.convertEntitiesInString(attrVal
ue)); | 326 result.append(m_htmlEntities.convertEntitiesInString(attrVal
ue)); |
| 343 else | 327 else |
| 344 result.append(m_xmlEntities.convertEntitiesInString(attrValu
e)); | 328 result.append(m_xmlEntities.convertEntitiesInString(attrValu
e)); |
| 345 } | 329 } |
| 346 } | 330 } |
| 347 result.append('\"'); | 331 result.append('\"'); |
| 348 } | 332 } |
| 349 | 333 |
| 350 // Do post action for open tag. | 334 // Do post action for open tag. |
| 351 String addedContents = postActionAfterSerializeOpenTag(element, param); | 335 String addedContents = postActionAfterSerializeOpenTag(element, param); |
| 352 // Complete the open tag for element when it has child/children. | 336 // Complete the open tag for element when it has child/children. |
| 353 if (element->hasChildren() || param->haveAddedContentsBeforeEnd) | 337 if (element->hasChildren() || param->haveAddedContentsBeforeEnd) |
| 354 result.append('>'); | 338 result.append('>'); |
| 355 // Append the added contents generate in post action of open tag. | 339 // Append the added contents generate in post action of open tag. |
| 356 result.append(addedContents); | 340 result.append(addedContents); |
| 357 // Save the result to data buffer. | 341 // Save the result to data buffer. |
| 358 saveHTMLContentToBuffer(result.toString(), param); | 342 saveHTMLContentToBuffer(result.toString(), param); |
| 359 } | 343 } |
| 360 | 344 |
| 345 void WebPageSerializerImpl::handleLinkAttr( |
| 346 Element* element, SerializeDomParam* param, const String& attrValue) |
| 347 { |
| 348 if (isHTMLFrameElementBase(element)) { |
| 349 WebFrame* subframe = WebFrame::fromFrame( |
| 350 toHTMLFrameElementBase(element)->contentFrame()); |
| 351 m_client->writeLocalPathForSubframe(*subframe); |
| 352 } else { |
| 353 KURL completeURL = param->document->completeURL(attrValue); |
| 354 m_client->writeLocalPathForSavableResource(completeURL); |
| 355 } |
| 356 } |
| 357 |
| 361 // Serialize end tag of an specified element. | 358 // Serialize end tag of an specified element. |
| 362 void WebPageSerializerImpl::endTagToString(Element* element, | 359 void WebPageSerializerImpl::handleEndTag( |
| 363 SerializeDomParam* param) | 360 Element* element, SerializeDomParam* param) |
| 364 { | 361 { |
| 365 bool needSkip; | 362 bool needSkip; |
| 366 StringBuilder result; | 363 StringBuilder result; |
| 367 // Do pre action for end tag. | 364 // Do pre action for end tag. |
| 368 result.append(preActionBeforeSerializeEndTag(element, param, &needSkip)); | 365 result.append(preActionBeforeSerializeEndTag(element, param, &needSkip)); |
| 369 if (needSkip) | 366 if (needSkip) |
| 370 return; | 367 return; |
| 371 // Write end tag when element has child/children. | 368 // Write end tag when element has child/children. |
| 372 if (element->hasChildren() || param->haveAddedContentsBeforeEnd) { | 369 if (element->hasChildren() || param->haveAddedContentsBeforeEnd) { |
| 373 result.appendLiteral("</"); | 370 result.appendLiteral("</"); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 394 // Save the result to data buffer. | 391 // Save the result to data buffer. |
| 395 saveHTMLContentToBuffer(result.toString(), param); | 392 saveHTMLContentToBuffer(result.toString(), param); |
| 396 } | 393 } |
| 397 | 394 |
| 398 void WebPageSerializerImpl::buildContentForNode(Node* node, | 395 void WebPageSerializerImpl::buildContentForNode(Node* node, |
| 399 SerializeDomParam* param) | 396 SerializeDomParam* param) |
| 400 { | 397 { |
| 401 switch (node->nodeType()) { | 398 switch (node->nodeType()) { |
| 402 case Node::ELEMENT_NODE: | 399 case Node::ELEMENT_NODE: |
| 403 // Process open tag of element. | 400 // Process open tag of element. |
| 404 openTagToString(toElement(node), param); | 401 handleOpenTag(toElement(node), param); |
| 405 // Walk through the children nodes and process it. | 402 // Walk through the children nodes and process it. |
| 406 for (Node *child = node->firstChild(); child; child = child->nextSibling
()) | 403 for (Node *child = node->firstChild(); child; child = child->nextSibling
()) |
| 407 buildContentForNode(child, param); | 404 buildContentForNode(child, param); |
| 408 // Process end tag of element. | 405 // Process end tag of element. |
| 409 endTagToString(toElement(node), param); | 406 handleEndTag(toElement(node), param); |
| 410 break; | 407 break; |
| 411 case Node::TEXT_NODE: | 408 case Node::TEXT_NODE: |
| 412 saveHTMLContentToBuffer(createMarkup(node), param); | 409 saveHTMLContentToBuffer(createMarkup(node), param); |
| 413 break; | 410 break; |
| 414 case Node::ATTRIBUTE_NODE: | 411 case Node::ATTRIBUTE_NODE: |
| 415 case Node::DOCUMENT_NODE: | 412 case Node::DOCUMENT_NODE: |
| 416 case Node::DOCUMENT_FRAGMENT_NODE: | 413 case Node::DOCUMENT_FRAGMENT_NODE: |
| 417 // Should not exist. | 414 // Should not exist. |
| 418 ASSERT_NOT_REACHED(); | 415 ASSERT_NOT_REACHED(); |
| 419 break; | 416 break; |
| 420 // Document type node can be in DOM? | 417 // Document type node can be in DOM? |
| 421 case Node::DOCUMENT_TYPE_NODE: | 418 case Node::DOCUMENT_TYPE_NODE: |
| 422 param->haveSeenDocType = true; | 419 param->haveSeenDocType = true; |
| 423 default: | 420 default: |
| 424 // For other type node, call default action. | 421 // For other type node, call default action. |
| 425 saveHTMLContentToBuffer(createMarkup(node), param); | 422 saveHTMLContentToBuffer(createMarkup(node), param); |
| 426 break; | 423 break; |
| 427 } | 424 } |
| 428 } | 425 } |
| 429 | 426 |
| 430 WebPageSerializerImpl::WebPageSerializerImpl(WebFrame* frame, | 427 WebPageSerializerImpl::WebPageSerializerImpl( |
| 431 WebPageSerializerClient* client, | 428 WebFrame* frame, |
| 432 const WebVector<WebURL>& links, | 429 WebPageSerializerClient* client) |
| 433 const WebVector<WebString>& localPa
ths, | |
| 434 const WebString& localDirectoryName
) | |
| 435 : m_client(client) | 430 : m_client(client) |
| 436 , m_localDirectoryName(localDirectoryName) | |
| 437 , m_htmlEntities(false) | 431 , m_htmlEntities(false) |
| 438 , m_xmlEntities(true) | 432 , m_xmlEntities(true) |
| 439 { | 433 { |
| 440 // Must specify available webframe. | 434 // Must specify available webframe. |
| 441 ASSERT(frame); | 435 ASSERT(frame); |
| 442 m_specifiedWebLocalFrameImpl = toWebLocalFrameImpl(frame); | 436 m_specifiedWebLocalFrameImpl = toWebLocalFrameImpl(frame); |
| 443 // Make sure we have non 0 client. | 437 // Make sure we have non 0 client. |
| 444 ASSERT(client); | 438 ASSERT(client); |
| 445 // Build local resources map. | |
| 446 ASSERT(links.size() == localPaths.size()); | |
| 447 for (size_t i = 0; i < links.size(); i++) { | |
| 448 KURL url = links[i]; | |
| 449 ASSERT(!m_localLinks.contains(url.string())); | |
| 450 m_localLinks.set(url.string(), localPaths[i]); | |
| 451 } | |
| 452 | 439 |
| 453 ASSERT(m_dataBuffer.isEmpty()); | 440 ASSERT(m_dataBuffer.isEmpty()); |
| 454 } | 441 } |
| 455 | 442 |
| 456 bool WebPageSerializerImpl::serialize() | 443 bool WebPageSerializerImpl::serialize() |
| 457 { | 444 { |
| 458 bool didSerialization = false; | 445 bool didSerialization = false; |
| 459 KURL mainURL = m_specifiedWebLocalFrameImpl->frame()->document()->url(); | 446 KURL mainURL = m_specifiedWebLocalFrameImpl->frame()->document()->url(); |
| 460 | 447 |
| 461 WebLocalFrameImpl* webFrame = m_specifiedWebLocalFrameImpl; | 448 WebLocalFrameImpl* webFrame = m_specifiedWebLocalFrameImpl; |
| 462 Document* document = webFrame->frame()->document(); | 449 Document* document = webFrame->frame()->document(); |
| 463 const KURL& url = document->url(); | 450 const KURL& url = document->url(); |
| 464 | 451 |
| 465 if (url.isValid() && m_localLinks.contains(url.string())) { | 452 if (url.isValid()) { |
| 466 didSerialization = true; | 453 didSerialization = true; |
| 467 | 454 |
| 468 const WTF::TextEncoding& textEncoding = document->encoding().isValid() ?
document->encoding() : UTF8Encoding(); | 455 const WTF::TextEncoding& textEncoding = document->encoding().isValid() ?
document->encoding() : UTF8Encoding(); |
| 469 String directoryName = url == mainURL ? m_localDirectoryName : ""; | |
| 470 | 456 |
| 471 SerializeDomParam param(url, textEncoding, document, directoryName); | 457 SerializeDomParam param(url, textEncoding, document); |
| 472 | 458 |
| 473 Element* documentElement = document->documentElement(); | 459 Element* documentElement = document->documentElement(); |
| 474 if (documentElement) | 460 if (documentElement) |
| 475 buildContentForNode(documentElement, ¶m); | 461 buildContentForNode(documentElement, ¶m); |
| 476 | 462 |
| 477 encodeAndFlushBuffer(WebPageSerializerClient::CurrentFrameIsFinished, &p
aram, ForceFlush); | 463 encodeAndFlushBuffer(¶m, ForceFlush); |
| 478 } | 464 } |
| 479 | 465 |
| 480 ASSERT(m_dataBuffer.isEmpty()); | 466 ASSERT(m_dataBuffer.isEmpty()); |
| 481 m_client->didSerializeDataForFrame(KURL(), WebCString("", 0), WebPageSeriali
zerClient::AllFramesAreFinished); | 467 m_client->endOfFrame(); |
| 482 return didSerialization; | 468 return didSerialization; |
| 483 } | 469 } |
| 484 | 470 |
| 485 } // namespace blink | 471 } // namespace blink |
| OLD | NEW |