Chromium Code Reviews| Index: third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp |
| diff --git a/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp b/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp |
| index 65b80bb57f24fd2b79b42d806b99db30182bea19..3d4bd00f6b3d11f7ed7d126ebf38c6f33678cb60 100644 |
| --- a/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp |
| +++ b/third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp |
| @@ -45,12 +45,23 @@ |
| #include "wtf/text/Base64.h" |
| #include "wtf/text/StringBuilder.h" |
| -namespace blink { |
| + |
| +namespace { |
| const char* const quotedPrintable = "quoted-printable"; |
| const char* const base64 = "base64"; |
| const char* const binary = "binary"; |
| +enum class Encoding { |
| + QuotedPrintable, |
| + Base64, |
| + Binary, |
| +}; |
| + |
| +} |
| + |
| +namespace blink { |
| + |
| static String replaceNonPrintableCharacters(const String& text) |
| { |
| StringBuilder stringBuilder; |
| @@ -108,7 +119,7 @@ bool MHTMLArchive::canLoadArchive(const KURL& url) |
| void MHTMLArchive::generateMHTMLHeader( |
| const String& boundary, const String& title, const String& mimeType, |
| - SharedBuffer& outputBuffer) |
| + std::vector<char>& outputBuffer) |
| { |
| ASSERT(!boundary.isEmpty()); |
| ASSERT(!mimeType.isEmpty()); |
| @@ -141,7 +152,8 @@ void MHTMLArchive::generateMHTMLHeader( |
| ASSERT(stringBuilder.toString().containsOnlyASCII()); |
| CString asciiString = stringBuilder.toString().utf8(); |
| - outputBuffer.append(asciiString.data(), asciiString.length()); |
| + outputBuffer.reserve(outputBuffer.size() + asciiString.length()); |
| + outputBuffer.insert(outputBuffer.end(), asciiString.data(), asciiString.data() + asciiString.length()); |
| } |
| void MHTMLArchive::generateMHTMLPart( |
| @@ -149,7 +161,7 @@ void MHTMLArchive::generateMHTMLPart( |
| const String& contentID, |
| EncodingPolicy encodingPolicy, |
| const SerializedResource& resource, |
| - SharedBuffer& outputBuffer) |
| + std::vector<char>& outputBuffer) |
| { |
| ASSERT(!boundary.isEmpty()); |
| ASSERT(contentID.isEmpty() || contentID[0] == '<'); |
| @@ -169,16 +181,20 @@ void MHTMLArchive::generateMHTMLPart( |
| stringBuilder.append("\r\n"); |
| } |
| - const char* contentEncoding = 0; |
| - if (encodingPolicy == UseBinaryEncoding) |
| - contentEncoding = binary; |
| - else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(resource.mimeType) || MIMETypeRegistry::isSupportedNonImageMIMEType(resource.mimeType)) |
| - contentEncoding = quotedPrintable; |
| - else |
| - contentEncoding = base64; |
| + const char* contentEncodingText = 0; |
| + Encoding encoding = Encoding::Base64; |
| + if (encodingPolicy == UseBinaryEncoding) { |
| + contentEncodingText = binary; |
| + encoding = Encoding::Binary; |
| + } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(resource.mimeType) || MIMETypeRegistry::isSupportedNonImageMIMEType(resource.mimeType)) { |
| + contentEncodingText = quotedPrintable; |
| + encoding = Encoding::QuotedPrintable; |
| + } else { |
| + contentEncodingText = base64; |
| + } |
| stringBuilder.append("Content-Transfer-Encoding: "); |
| - stringBuilder.append(contentEncoding); |
| + stringBuilder.append(contentEncodingText); |
| stringBuilder.append("\r\n"); |
| if (!resource.url.protocolIsAbout()) { |
| @@ -190,13 +206,24 @@ void MHTMLArchive::generateMHTMLPart( |
| stringBuilder.append("\r\n"); |
| CString asciiString = stringBuilder.toString().utf8(); |
| - outputBuffer.append(asciiString.data(), asciiString.length()); |
| - if (!strcmp(contentEncoding, binary)) { |
| + // Best guess for a reserved size. It should work well for binary and base64 |
| + // (see https://en.wikipedia.org/wiki/Base64#MIME); not so much for |
| + // quoted-printable which is harder to estimate. |
| + std::size_t expectedFinalSize = outputBuffer.size() + asciiString.length(); |
| + if (encoding == Encoding::Base64) |
| + expectedFinalSize += static_cast<std::size_t>(resource.data->size() * 1.37); |
| + else |
| + expectedFinalSize += resource.data->size(); |
| + outputBuffer.reserve(expectedFinalSize); |
| + |
| + outputBuffer.insert(outputBuffer.end(), asciiString.data(), asciiString.data() + asciiString.length()); |
| + |
| + if (encoding == Encoding::Binary) { |
| const char* data; |
| size_t position = 0; |
| while (size_t length = resource.data->getSomeData(data, position)) { |
| - outputBuffer.append(data, length); |
| + outputBuffer.insert(outputBuffer.end(), data, data + length); |
| position += length; |
| } |
| } else { |
| @@ -204,12 +231,13 @@ void MHTMLArchive::generateMHTMLPart( |
| const char* data = resource.data->data(); |
| size_t dataLength = resource.data->size(); |
| Vector<char> encodedData; |
| - if (!strcmp(contentEncoding, quotedPrintable)) { |
| + if (encoding == Encoding::QuotedPrintable) { |
| quotedPrintableEncode(data, dataLength, encodedData); |
| - outputBuffer.append(encodedData.data(), encodedData.size()); |
| - outputBuffer.append("\r\n", 2u); |
| + outputBuffer.insert(outputBuffer.end(), encodedData.data(), encodedData.data() + encodedData.size()); |
| + outputBuffer.push_back('\r'); |
| + outputBuffer.push_back('\n'); |
| } else { |
| - ASSERT(!strcmp(contentEncoding, base64)); |
| + DCHECK(encoding == Encoding::Base64); |
|
carlosk
2016/10/03 23:51:05
I replaced ASSERT with DCHECK here as I understand
|
| // We are not specifying insertLFs = true below as it would cut the lines with LFs and MHTML requires CRLFs. |
| base64Encode(data, dataLength, encodedData); |
| const size_t maximumLineLength = 76; |
| @@ -217,8 +245,9 @@ void MHTMLArchive::generateMHTMLPart( |
| size_t encodedDataLength = encodedData.size(); |
| do { |
| size_t lineLength = std::min(encodedDataLength - index, maximumLineLength); |
| - outputBuffer.append(encodedData.data() + index, lineLength); |
| - outputBuffer.append("\r\n", 2u); |
| + outputBuffer.insert(outputBuffer.end(), encodedData.data() + index, encodedData.data() + index + lineLength); |
| + outputBuffer.push_back('\r'); |
| + outputBuffer.push_back('\n'); |
| index += maximumLineLength; |
| } while (index < encodedDataLength); |
| } |
| @@ -227,11 +256,12 @@ void MHTMLArchive::generateMHTMLPart( |
| void MHTMLArchive::generateMHTMLFooter( |
| const String& boundary, |
| - SharedBuffer& outputBuffer) |
| + std::vector<char>& outputBuffer) |
| { |
| ASSERT(!boundary.isEmpty()); |
| CString asciiString = String("--" + boundary + "--\r\n").utf8(); |
| - outputBuffer.append(asciiString.data(), asciiString.length()); |
| + outputBuffer.reserve(outputBuffer.size() + asciiString.length()); |
| + outputBuffer.insert(outputBuffer.end(), asciiString.data(), asciiString.data() + asciiString.length()); |
| } |
| void MHTMLArchive::setMainResource(ArchiveResource* mainResource) |