Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: third_party/WebKit/Source/platform/mhtml/MHTMLArchive.cpp

Issue 2379823003: Move MHTML file writing out of the renderer main thread. (Closed)
Patch Set: Removed unneeded std::move calls that clang was complaining about. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 27 matching lines...) Expand all
38 #include "platform/mhtml/MHTMLParser.h" 38 #include "platform/mhtml/MHTMLParser.h"
39 #include "platform/text/QuotedPrintable.h" 39 #include "platform/text/QuotedPrintable.h"
40 #include "platform/weborigin/SchemeRegistry.h" 40 #include "platform/weborigin/SchemeRegistry.h"
41 #include "wtf/Assertions.h" 41 #include "wtf/Assertions.h"
42 #include "wtf/CryptographicallyRandomNumber.h" 42 #include "wtf/CryptographicallyRandomNumber.h"
43 #include "wtf/CurrentTime.h" 43 #include "wtf/CurrentTime.h"
44 #include "wtf/DateMath.h" 44 #include "wtf/DateMath.h"
45 #include "wtf/text/Base64.h" 45 #include "wtf/text/Base64.h"
46 #include "wtf/text/StringBuilder.h" 46 #include "wtf/text/StringBuilder.h"
47 47
48 namespace blink { 48 namespace {
49 49
50 const char* const quotedPrintable = "quoted-printable"; 50 const char* const quotedPrintable = "quoted-printable";
51 const char* const base64 = "base64"; 51 const char* const base64 = "base64";
52 const char* const binary = "binary"; 52 const char* const binary = "binary";
53 53
54 enum class Encoding {
55 QuotedPrintable,
56 Base64,
57 Binary,
58 };
59 }
60
61 namespace blink {
62
54 static String replaceNonPrintableCharacters(const String& text) { 63 static String replaceNonPrintableCharacters(const String& text) {
55 StringBuilder stringBuilder; 64 StringBuilder stringBuilder;
56 for (size_t i = 0; i < text.length(); ++i) { 65 for (size_t i = 0; i < text.length(); ++i) {
57 if (isASCIIPrintable(text[i])) 66 if (isASCIIPrintable(text[i]))
58 stringBuilder.append(text[i]); 67 stringBuilder.append(text[i]);
59 else 68 else
60 stringBuilder.append('?'); 69 stringBuilder.append('?');
61 } 70 }
62 return stringBuilder.toString(); 71 return stringBuilder.toString();
63 } 72 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 #if OS(ANDROID) 112 #if OS(ANDROID)
104 if (url.protocolIs("content")) 113 if (url.protocolIs("content"))
105 return true; 114 return true;
106 #endif 115 #endif
107 return false; 116 return false;
108 } 117 }
109 118
110 void MHTMLArchive::generateMHTMLHeader(const String& boundary, 119 void MHTMLArchive::generateMHTMLHeader(const String& boundary,
111 const String& title, 120 const String& title,
112 const String& mimeType, 121 const String& mimeType,
113 SharedBuffer& outputBuffer) { 122 std::vector<char>& outputBuffer) {
114 ASSERT(!boundary.isEmpty()); 123 ASSERT(!boundary.isEmpty());
115 ASSERT(!mimeType.isEmpty()); 124 ASSERT(!mimeType.isEmpty());
116 125
117 DateComponents now; 126 DateComponents now;
118 now.setMillisecondsSinceEpochForDateTime(currentTimeMS()); 127 now.setMillisecondsSinceEpochForDateTime(currentTimeMS());
119 // TODO(lukasza): Passing individual date/time components seems fragile. 128 // TODO(lukasza): Passing individual date/time components seems fragile.
120 String dateString = makeRFC2822DateString( 129 String dateString = makeRFC2822DateString(
121 now.weekDay(), now.monthDay(), now.month(), now.fullYear(), now.hour(), 130 now.weekDay(), now.monthDay(), now.month(), now.fullYear(), now.hour(),
122 now.minute(), now.second(), 0); 131 now.minute(), now.second(), 0);
123 132
(...skipping 11 matching lines...) Expand all
135 stringBuilder.append("\";\r\n"); 144 stringBuilder.append("\";\r\n");
136 stringBuilder.append("\tboundary=\""); 145 stringBuilder.append("\tboundary=\"");
137 stringBuilder.append(boundary); 146 stringBuilder.append(boundary);
138 stringBuilder.append("\"\r\n\r\n"); 147 stringBuilder.append("\"\r\n\r\n");
139 148
140 // We use utf8() below instead of ascii() as ascii() replaces CRLFs with ?? 149 // We use utf8() below instead of ascii() as ascii() replaces CRLFs with ??
141 // (we still only have put ASCII characters in it). 150 // (we still only have put ASCII characters in it).
142 ASSERT(stringBuilder.toString().containsOnlyASCII()); 151 ASSERT(stringBuilder.toString().containsOnlyASCII());
143 CString asciiString = stringBuilder.toString().utf8(); 152 CString asciiString = stringBuilder.toString().utf8();
144 153
145 outputBuffer.append(asciiString.data(), asciiString.length()); 154 outputBuffer.reserve(outputBuffer.size() + asciiString.length());
155 outputBuffer.insert(outputBuffer.end(), asciiString.data(),
156 asciiString.data() + asciiString.length());
146 } 157 }
147 158
148 void MHTMLArchive::generateMHTMLPart(const String& boundary, 159 void MHTMLArchive::generateMHTMLPart(const String& boundary,
149 const String& contentID, 160 const String& contentID,
150 EncodingPolicy encodingPolicy, 161 EncodingPolicy encodingPolicy,
151 const SerializedResource& resource, 162 const SerializedResource& resource,
152 SharedBuffer& outputBuffer) { 163 std::vector<char>& outputBuffer) {
153 ASSERT(!boundary.isEmpty()); 164 ASSERT(!boundary.isEmpty());
154 ASSERT(contentID.isEmpty() || contentID[0] == '<'); 165 ASSERT(contentID.isEmpty() || contentID[0] == '<');
155 166
156 StringBuilder stringBuilder; 167 StringBuilder stringBuilder;
157 stringBuilder.append("--"); 168 stringBuilder.append("--");
158 stringBuilder.append(boundary); 169 stringBuilder.append(boundary);
159 stringBuilder.append("\r\n"); 170 stringBuilder.append("\r\n");
160 171
161 stringBuilder.append("Content-Type: "); 172 stringBuilder.append("Content-Type: ");
162 stringBuilder.append(resource.mimeType); 173 stringBuilder.append(resource.mimeType);
163 stringBuilder.append("\r\n"); 174 stringBuilder.append("\r\n");
164 175
165 if (!contentID.isEmpty()) { 176 if (!contentID.isEmpty()) {
166 stringBuilder.append("Content-ID: "); 177 stringBuilder.append("Content-ID: ");
167 stringBuilder.append(contentID); 178 stringBuilder.append(contentID);
168 stringBuilder.append("\r\n"); 179 stringBuilder.append("\r\n");
169 } 180 }
170 181
171 const char* contentEncoding = 0; 182 const char* contentEncodingText = 0;
172 if (encodingPolicy == UseBinaryEncoding) 183 Encoding encoding = Encoding::Base64;
173 contentEncoding = binary; 184 if (encodingPolicy == UseBinaryEncoding) {
174 else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(resource.mimeType) || 185 contentEncodingText = binary;
175 MIMETypeRegistry::isSupportedNonImageMIMEType(resource.mimeType)) 186 encoding = Encoding::Binary;
176 contentEncoding = quotedPrintable; 187 } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(
177 else 188 resource.mimeType) ||
178 contentEncoding = base64; 189 MIMETypeRegistry::isSupportedNonImageMIMEType(resource.mimeType)) {
190 contentEncodingText = quotedPrintable;
191 encoding = Encoding::QuotedPrintable;
192 } else {
193 contentEncodingText = base64;
194 }
179 195
180 stringBuilder.append("Content-Transfer-Encoding: "); 196 stringBuilder.append("Content-Transfer-Encoding: ");
181 stringBuilder.append(contentEncoding); 197 stringBuilder.append(contentEncodingText);
182 stringBuilder.append("\r\n"); 198 stringBuilder.append("\r\n");
183 199
184 if (!resource.url.protocolIsAbout()) { 200 if (!resource.url.protocolIsAbout()) {
185 stringBuilder.append("Content-Location: "); 201 stringBuilder.append("Content-Location: ");
186 stringBuilder.append(resource.url.getString()); 202 stringBuilder.append(resource.url.getString());
187 stringBuilder.append("\r\n"); 203 stringBuilder.append("\r\n");
188 } 204 }
189 205
190 stringBuilder.append("\r\n"); 206 stringBuilder.append("\r\n");
191 207
192 CString asciiString = stringBuilder.toString().utf8(); 208 CString asciiString = stringBuilder.toString().utf8();
193 outputBuffer.append(asciiString.data(), asciiString.length());
194 209
195 if (!strcmp(contentEncoding, binary)) { 210 // Best guess for a reserved size. It should work well for binary and base64
211 // (see https://en.wikipedia.org/wiki/Base64#MIME); not so much for
212 // quoted-printable which is harder to estimate.
213 std::size_t expectedFinalSize = outputBuffer.size() + asciiString.length();
214 if (encoding == Encoding::Base64)
215 expectedFinalSize += static_cast<std::size_t>(resource.data->size() * 1.37);
216 else
217 expectedFinalSize += resource.data->size();
218 outputBuffer.reserve(expectedFinalSize);
219
220 outputBuffer.insert(outputBuffer.end(), asciiString.data(),
221 asciiString.data() + asciiString.length());
222
223 if (encoding == Encoding::Binary) {
196 const char* data; 224 const char* data;
197 size_t position = 0; 225 size_t position = 0;
198 while (size_t length = resource.data->getSomeData(data, position)) { 226 while (size_t length = resource.data->getSomeData(data, position)) {
199 outputBuffer.append(data, length); 227 outputBuffer.insert(outputBuffer.end(), data, data + length);
200 position += length; 228 position += length;
201 } 229 }
202 } else { 230 } else {
203 // FIXME: ideally we would encode the content as a stream without having to 231 // FIXME: ideally we would encode the content as a stream without having to
204 // fetch it all. 232 // fetch it all.
205 const char* data = resource.data->data(); 233 const char* data = resource.data->data();
206 size_t dataLength = resource.data->size(); 234 size_t dataLength = resource.data->size();
207 Vector<char> encodedData; 235 Vector<char> encodedData;
208 if (!strcmp(contentEncoding, quotedPrintable)) { 236 if (encoding == Encoding::QuotedPrintable) {
209 quotedPrintableEncode(data, dataLength, encodedData); 237 quotedPrintableEncode(data, dataLength, encodedData);
210 outputBuffer.append(encodedData.data(), encodedData.size()); 238 outputBuffer.insert(outputBuffer.end(), encodedData.data(),
211 outputBuffer.append("\r\n", 2u); 239 encodedData.data() + encodedData.size());
240 outputBuffer.push_back('\r');
241 outputBuffer.push_back('\n');
212 } else { 242 } else {
213 ASSERT(!strcmp(contentEncoding, base64)); 243 DCHECK(encoding == Encoding::Base64);
214 // We are not specifying insertLFs = true below as it would cut the lines 244 // We are not specifying insertLFs = true below as it would cut the lines
215 // with LFs and MHTML requires CRLFs. 245 // with LFs and MHTML requires CRLFs.
216 base64Encode(data, dataLength, encodedData); 246 base64Encode(data, dataLength, encodedData);
217 const size_t maximumLineLength = 76; 247 const size_t maximumLineLength = 76;
218 size_t index = 0; 248 size_t index = 0;
219 size_t encodedDataLength = encodedData.size(); 249 size_t encodedDataLength = encodedData.size();
220 do { 250 do {
221 size_t lineLength = 251 size_t lineLength =
222 std::min(encodedDataLength - index, maximumLineLength); 252 std::min(encodedDataLength - index, maximumLineLength);
223 outputBuffer.append(encodedData.data() + index, lineLength); 253 outputBuffer.insert(outputBuffer.end(), encodedData.data() + index,
224 outputBuffer.append("\r\n", 2u); 254 encodedData.data() + index + lineLength);
255 outputBuffer.push_back('\r');
256 outputBuffer.push_back('\n');
225 index += maximumLineLength; 257 index += maximumLineLength;
226 } while (index < encodedDataLength); 258 } while (index < encodedDataLength);
227 } 259 }
228 } 260 }
229 } 261 }
230 262
231 void MHTMLArchive::generateMHTMLFooter(const String& boundary, 263 void MHTMLArchive::generateMHTMLFooter(const String& boundary,
232 SharedBuffer& outputBuffer) { 264 std::vector<char>& outputBuffer) {
233 ASSERT(!boundary.isEmpty()); 265 ASSERT(!boundary.isEmpty());
234 CString asciiString = String("--" + boundary + "--\r\n").utf8(); 266 CString asciiString = String("--" + boundary + "--\r\n").utf8();
235 outputBuffer.append(asciiString.data(), asciiString.length()); 267 outputBuffer.reserve(outputBuffer.size() + asciiString.length());
268 outputBuffer.insert(outputBuffer.end(), asciiString.data(),
269 asciiString.data() + asciiString.length());
236 } 270 }
237 271
238 void MHTMLArchive::setMainResource(ArchiveResource* mainResource) { 272 void MHTMLArchive::setMainResource(ArchiveResource* mainResource) {
239 m_mainResource = mainResource; 273 m_mainResource = mainResource;
240 } 274 }
241 275
242 void MHTMLArchive::addSubresource(ArchiveResource* resource) { 276 void MHTMLArchive::addSubresource(ArchiveResource* resource) {
243 const KURL& url = resource->url(); 277 const KURL& url = resource->url();
244 m_subresources.set(url, resource); 278 m_subresources.set(url, resource);
245 KURL cidURI = MHTMLParser::convertContentIDToURI(resource->contentID()); 279 KURL cidURI = MHTMLParser::convertContentIDToURI(resource->contentID());
246 if (cidURI.isValid()) 280 if (cidURI.isValid())
247 m_subresources.set(cidURI, resource); 281 m_subresources.set(cidURI, resource);
248 } 282 }
249 283
250 ArchiveResource* MHTMLArchive::subresourceForURL(const KURL& url) const { 284 ArchiveResource* MHTMLArchive::subresourceForURL(const KURL& url) const {
251 return m_subresources.get(url.getString()); 285 return m_subresources.get(url.getString());
252 } 286 }
253 287
254 DEFINE_TRACE(MHTMLArchive) { 288 DEFINE_TRACE(MHTMLArchive) {
255 visitor->trace(m_mainResource); 289 visitor->trace(m_mainResource);
256 visitor->trace(m_subresources); 290 visitor->trace(m_subresources);
257 } 291 }
258 292
259 } // namespace blink 293 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698