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

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: A few move semantics fixes (I think). 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
49 namespace {
49 50
50 const char* const quotedPrintable = "quoted-printable"; 51 const char* const quotedPrintable = "quoted-printable";
51 const char* const base64 = "base64"; 52 const char* const base64 = "base64";
52 const char* const binary = "binary"; 53 const char* const binary = "binary";
53 54
55 enum class Encoding {
56 QuotedPrintable,
57 Base64,
58 Binary,
59 };
60
61 }
62
63 namespace blink {
64
54 static String replaceNonPrintableCharacters(const String& text) 65 static String replaceNonPrintableCharacters(const String& text)
55 { 66 {
56 StringBuilder stringBuilder; 67 StringBuilder stringBuilder;
57 for (size_t i = 0; i < text.length(); ++i) { 68 for (size_t i = 0; i < text.length(); ++i) {
58 if (isASCIIPrintable(text[i])) 69 if (isASCIIPrintable(text[i]))
59 stringBuilder.append(text[i]); 70 stringBuilder.append(text[i]);
60 else 71 else
61 stringBuilder.append('?'); 72 stringBuilder.append('?');
62 } 73 }
63 return stringBuilder.toString(); 74 return stringBuilder.toString();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 return true; 112 return true;
102 #if OS(ANDROID) 113 #if OS(ANDROID)
103 if (url.protocolIs("content")) 114 if (url.protocolIs("content"))
104 return true; 115 return true;
105 #endif 116 #endif
106 return false; 117 return false;
107 } 118 }
108 119
109 void MHTMLArchive::generateMHTMLHeader( 120 void MHTMLArchive::generateMHTMLHeader(
110 const String& boundary, const String& title, const String& mimeType, 121 const String& boundary, const String& title, const String& mimeType,
111 SharedBuffer& outputBuffer) 122 std::vector<char>& outputBuffer)
112 { 123 {
113 ASSERT(!boundary.isEmpty()); 124 ASSERT(!boundary.isEmpty());
114 ASSERT(!mimeType.isEmpty()); 125 ASSERT(!mimeType.isEmpty());
115 126
116 DateComponents now; 127 DateComponents now;
117 now.setMillisecondsSinceEpochForDateTime(currentTimeMS()); 128 now.setMillisecondsSinceEpochForDateTime(currentTimeMS());
118 // TODO(lukasza): Passing individual date/time components seems fragile. 129 // TODO(lukasza): Passing individual date/time components seems fragile.
119 String dateString = makeRFC2822DateString( 130 String dateString = makeRFC2822DateString(
120 now.weekDay(), now.monthDay(), now.month(), now.fullYear(), 131 now.weekDay(), now.monthDay(), now.month(), now.fullYear(),
121 now.hour(), now.minute(), now.second(), 0); 132 now.hour(), now.minute(), now.second(), 0);
(...skipping 12 matching lines...) Expand all
134 stringBuilder.append("\";\r\n"); 145 stringBuilder.append("\";\r\n");
135 stringBuilder.append("\tboundary=\""); 146 stringBuilder.append("\tboundary=\"");
136 stringBuilder.append(boundary); 147 stringBuilder.append(boundary);
137 stringBuilder.append("\"\r\n\r\n"); 148 stringBuilder.append("\"\r\n\r\n");
138 149
139 // We use utf8() below instead of ascii() as ascii() replaces CRLFs with ?? 150 // We use utf8() below instead of ascii() as ascii() replaces CRLFs with ??
140 // (we still only have put ASCII characters in it). 151 // (we still only have put ASCII characters in it).
141 ASSERT(stringBuilder.toString().containsOnlyASCII()); 152 ASSERT(stringBuilder.toString().containsOnlyASCII());
142 CString asciiString = stringBuilder.toString().utf8(); 153 CString asciiString = stringBuilder.toString().utf8();
143 154
144 outputBuffer.append(asciiString.data(), asciiString.length()); 155 outputBuffer.reserve(outputBuffer.size() + asciiString.length());
156 outputBuffer.insert(outputBuffer.end(), asciiString.data(), asciiString.data () + asciiString.length());
145 } 157 }
146 158
147 void MHTMLArchive::generateMHTMLPart( 159 void MHTMLArchive::generateMHTMLPart(
148 const String& boundary, 160 const String& boundary,
149 const String& contentID, 161 const String& contentID,
150 EncodingPolicy encodingPolicy, 162 EncodingPolicy encodingPolicy,
151 const SerializedResource& resource, 163 const SerializedResource& resource,
152 SharedBuffer& outputBuffer) 164 std::vector<char>& outputBuffer)
153 { 165 {
154 ASSERT(!boundary.isEmpty()); 166 ASSERT(!boundary.isEmpty());
155 ASSERT(contentID.isEmpty() || contentID[0] == '<'); 167 ASSERT(contentID.isEmpty() || contentID[0] == '<');
156 168
157 StringBuilder stringBuilder; 169 StringBuilder stringBuilder;
158 stringBuilder.append("--"); 170 stringBuilder.append("--");
159 stringBuilder.append(boundary); 171 stringBuilder.append(boundary);
160 stringBuilder.append("\r\n"); 172 stringBuilder.append("\r\n");
161 173
162 stringBuilder.append("Content-Type: "); 174 stringBuilder.append("Content-Type: ");
163 stringBuilder.append(resource.mimeType); 175 stringBuilder.append(resource.mimeType);
164 stringBuilder.append("\r\n"); 176 stringBuilder.append("\r\n");
165 177
166 if (!contentID.isEmpty()) { 178 if (!contentID.isEmpty()) {
167 stringBuilder.append("Content-ID: "); 179 stringBuilder.append("Content-ID: ");
168 stringBuilder.append(contentID); 180 stringBuilder.append(contentID);
169 stringBuilder.append("\r\n"); 181 stringBuilder.append("\r\n");
170 } 182 }
171 183
172 const char* contentEncoding = 0; 184 const char* contentEncodingText = 0;
173 if (encodingPolicy == UseBinaryEncoding) 185 Encoding encoding = Encoding::Base64;
174 contentEncoding = binary; 186 if (encodingPolicy == UseBinaryEncoding) {
175 else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(resource.mimeType) || MIMETypeRegistry::isSupportedNonImageMIMEType(resource.mimeType)) 187 contentEncodingText = binary;
176 contentEncoding = quotedPrintable; 188 encoding = Encoding::Binary;
177 else 189 } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(resource.mimeType ) || MIMETypeRegistry::isSupportedNonImageMIMEType(resource.mimeType)) {
178 contentEncoding = base64; 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(), asciiString.data () + asciiString.length());
221
222 if (encoding == Encoding::Binary) {
196 const char* data; 223 const char* data;
197 size_t position = 0; 224 size_t position = 0;
198 while (size_t length = resource.data->getSomeData(data, position)) { 225 while (size_t length = resource.data->getSomeData(data, position)) {
199 outputBuffer.append(data, length); 226 outputBuffer.insert(outputBuffer.end(), data, data + length);
200 position += length; 227 position += length;
201 } 228 }
202 } else { 229 } else {
203 // FIXME: ideally we would encode the content as a stream without having to fetch it all. 230 // FIXME: ideally we would encode the content as a stream without having to fetch it all.
204 const char* data = resource.data->data(); 231 const char* data = resource.data->data();
205 size_t dataLength = resource.data->size(); 232 size_t dataLength = resource.data->size();
206 Vector<char> encodedData; 233 Vector<char> encodedData;
207 if (!strcmp(contentEncoding, quotedPrintable)) { 234 if (encoding == Encoding::QuotedPrintable) {
208 quotedPrintableEncode(data, dataLength, encodedData); 235 quotedPrintableEncode(data, dataLength, encodedData);
209 outputBuffer.append(encodedData.data(), encodedData.size()); 236 outputBuffer.insert(outputBuffer.end(), encodedData.data(), encodedD ata.data() + encodedData.size());
210 outputBuffer.append("\r\n", 2u); 237 outputBuffer.push_back('\r');
238 outputBuffer.push_back('\n');
211 } else { 239 } else {
212 ASSERT(!strcmp(contentEncoding, base64)); 240 DCHECK(encoding == Encoding::Base64);
carlosk 2016/10/03 23:51:05 I replaced ASSERT with DCHECK here as I understand
213 // We are not specifying insertLFs = true below as it would cut the lines with LFs and MHTML requires CRLFs. 241 // We are not specifying insertLFs = true below as it would cut the lines with LFs and MHTML requires CRLFs.
214 base64Encode(data, dataLength, encodedData); 242 base64Encode(data, dataLength, encodedData);
215 const size_t maximumLineLength = 76; 243 const size_t maximumLineLength = 76;
216 size_t index = 0; 244 size_t index = 0;
217 size_t encodedDataLength = encodedData.size(); 245 size_t encodedDataLength = encodedData.size();
218 do { 246 do {
219 size_t lineLength = std::min(encodedDataLength - index, maximumL ineLength); 247 size_t lineLength = std::min(encodedDataLength - index, maximumL ineLength);
220 outputBuffer.append(encodedData.data() + index, lineLength); 248 outputBuffer.insert(outputBuffer.end(), encodedData.data() + ind ex, encodedData.data() + index + lineLength);
221 outputBuffer.append("\r\n", 2u); 249 outputBuffer.push_back('\r');
250 outputBuffer.push_back('\n');
222 index += maximumLineLength; 251 index += maximumLineLength;
223 } while (index < encodedDataLength); 252 } while (index < encodedDataLength);
224 } 253 }
225 } 254 }
226 } 255 }
227 256
228 void MHTMLArchive::generateMHTMLFooter( 257 void MHTMLArchive::generateMHTMLFooter(
229 const String& boundary, 258 const String& boundary,
230 SharedBuffer& outputBuffer) 259 std::vector<char>& outputBuffer)
231 { 260 {
232 ASSERT(!boundary.isEmpty()); 261 ASSERT(!boundary.isEmpty());
233 CString asciiString = String("--" + boundary + "--\r\n").utf8(); 262 CString asciiString = String("--" + boundary + "--\r\n").utf8();
234 outputBuffer.append(asciiString.data(), asciiString.length()); 263 outputBuffer.reserve(outputBuffer.size() + asciiString.length());
264 outputBuffer.insert(outputBuffer.end(), asciiString.data(), asciiString.data () + asciiString.length());
235 } 265 }
236 266
237 void MHTMLArchive::setMainResource(ArchiveResource* mainResource) 267 void MHTMLArchive::setMainResource(ArchiveResource* mainResource)
238 { 268 {
239 m_mainResource = mainResource; 269 m_mainResource = mainResource;
240 } 270 }
241 271
242 void MHTMLArchive::addSubresource(ArchiveResource* resource) 272 void MHTMLArchive::addSubresource(ArchiveResource* resource)
243 { 273 {
244 const KURL& url = resource->url(); 274 const KURL& url = resource->url();
245 m_subresources.set(url, resource); 275 m_subresources.set(url, resource);
246 KURL cidURI = MHTMLParser::convertContentIDToURI(resource->contentID()); 276 KURL cidURI = MHTMLParser::convertContentIDToURI(resource->contentID());
247 if (cidURI.isValid()) 277 if (cidURI.isValid())
248 m_subresources.set(cidURI, resource); 278 m_subresources.set(cidURI, resource);
249 } 279 }
250 280
251 ArchiveResource* MHTMLArchive::subresourceForURL(const KURL& url) const 281 ArchiveResource* MHTMLArchive::subresourceForURL(const KURL& url) const
252 { 282 {
253 return m_subresources.get(url.getString()); 283 return m_subresources.get(url.getString());
254 } 284 }
255 285
256 DEFINE_TRACE(MHTMLArchive) 286 DEFINE_TRACE(MHTMLArchive)
257 { 287 {
258 visitor->trace(m_mainResource); 288 visitor->trace(m_mainResource);
259 visitor->trace(m_subresources); 289 visitor->trace(m_subresources);
260 } 290 }
261 291
262 } // namespace blink 292 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698