OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions are | |
6 * met: | |
7 * | |
8 * * Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * * Redistributions in binary form must reproduce the above | |
11 * copyright notice, this list of conditions and the following disclaimer | |
12 * in the documentation and/or other materials provided with the | |
13 * distribution. | |
14 * * Neither the name of Google Inc. nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 */ | |
30 | |
31 /** | |
32 * @interface | |
33 */ | |
34 WebInspector.OutputStreamDelegate = function() | |
35 { | |
36 } | |
37 | |
38 WebInspector.OutputStreamDelegate.prototype = { | |
39 onTransferStarted: function() { }, | |
40 | |
41 onTransferFinished: function() { }, | |
42 | |
43 /** | |
44 * @param {!WebInspector.ChunkedReader} reader | |
45 */ | |
46 onChunkTransferred: function(reader) { }, | |
47 | |
48 /** | |
49 * @param {!WebInspector.ChunkedReader} reader | |
50 * @param {!Event} event | |
51 */ | |
52 onError: function(reader, event) { }, | |
53 } | |
54 | |
55 /** | |
56 * @interface | |
57 */ | |
58 WebInspector.OutputStream = function() | |
59 { | |
60 } | |
61 | |
62 WebInspector.OutputStream.prototype = { | |
63 /** | |
64 * @param {string} data | |
65 * @param {function(!WebInspector.OutputStream)=} callback | |
66 */ | |
67 write: function(data, callback) { }, | |
68 | |
69 close: function() { } | |
70 } | |
71 | |
72 /** | |
73 * @interface | |
74 */ | |
75 WebInspector.ChunkedReader = function() | |
76 { | |
77 } | |
78 | |
79 WebInspector.ChunkedReader.prototype = { | |
80 /** | |
81 * @return {number} | |
82 */ | |
83 fileSize: function() { }, | |
84 | |
85 /** | |
86 * @return {number} | |
87 */ | |
88 loadedSize: function() { }, | |
89 | |
90 /** | |
91 * @return {string} | |
92 */ | |
93 fileName: function() { }, | |
94 | |
95 cancel: function() { } | |
96 } | |
97 | |
98 /** | |
99 * @constructor | |
100 * @implements {WebInspector.ChunkedReader} | |
101 * @param {!File} file | |
102 * @param {number} chunkSize | |
103 * @param {!WebInspector.OutputStreamDelegate} delegate | |
104 */ | |
105 WebInspector.ChunkedFileReader = function(file, chunkSize, delegate) | |
106 { | |
107 this._file = file; | |
108 this._fileSize = file.size; | |
109 this._loadedSize = 0; | |
110 this._chunkSize = chunkSize; | |
111 this._delegate = delegate; | |
112 this._isCanceled = false; | |
113 } | |
114 | |
115 WebInspector.ChunkedFileReader.prototype = { | |
116 /** | |
117 * @param {!WebInspector.OutputStream} output | |
118 */ | |
119 start: function(output) | |
120 { | |
121 this._output = output; | |
122 | |
123 this._reader = new FileReader(); | |
124 this._reader.onload = this._onChunkLoaded.bind(this); | |
125 this._reader.onerror = this._delegate.onError.bind(this._delegate, this)
; | |
126 this._delegate.onTransferStarted(); | |
127 this._loadChunk(); | |
128 }, | |
129 | |
130 cancel: function() | |
131 { | |
132 this._isCanceled = true; | |
133 }, | |
134 | |
135 /** | |
136 * @return {number} | |
137 */ | |
138 loadedSize: function() | |
139 { | |
140 return this._loadedSize; | |
141 }, | |
142 | |
143 /** | |
144 * @return {number} | |
145 */ | |
146 fileSize: function() | |
147 { | |
148 return this._fileSize; | |
149 }, | |
150 | |
151 /** | |
152 * @return {string} | |
153 */ | |
154 fileName: function() | |
155 { | |
156 return this._file.name; | |
157 }, | |
158 | |
159 /** | |
160 * @param {!Event} event | |
161 */ | |
162 _onChunkLoaded: function(event) | |
163 { | |
164 if (this._isCanceled) | |
165 return; | |
166 | |
167 if (event.target.readyState !== FileReader.DONE) | |
168 return; | |
169 | |
170 var data = event.target.result; | |
171 this._loadedSize += data.length; | |
172 | |
173 this._output.write(data); | |
174 if (this._isCanceled) | |
175 return; | |
176 this._delegate.onChunkTransferred(this); | |
177 | |
178 if (this._loadedSize === this._fileSize) { | |
179 this._file = null; | |
180 this._reader = null; | |
181 this._output.close(); | |
182 this._delegate.onTransferFinished(); | |
183 return; | |
184 } | |
185 | |
186 this._loadChunk(); | |
187 }, | |
188 | |
189 _loadChunk: function() | |
190 { | |
191 var chunkStart = this._loadedSize; | |
192 var chunkEnd = Math.min(this._fileSize, chunkStart + this._chunkSize) | |
193 var nextPart = this._file.slice(chunkStart, chunkEnd); | |
194 this._reader.readAsText(nextPart); | |
195 } | |
196 } | |
197 | |
198 /** | |
199 * @param {function(!File)} callback | |
200 * @return {!Node} | |
201 */ | |
202 WebInspector.createFileSelectorElement = function(callback) { | |
203 var fileSelectorElement = document.createElement("input"); | |
204 fileSelectorElement.type = "file"; | |
205 fileSelectorElement.style.display = "none"; | |
206 fileSelectorElement.setAttribute("tabindex", -1); | |
207 fileSelectorElement.onchange = onChange; | |
208 function onChange(event) | |
209 { | |
210 callback(fileSelectorElement.files[0]); | |
211 }; | |
212 return fileSelectorElement; | |
213 } | |
214 | |
215 /** | |
216 * @constructor | |
217 * @implements {WebInspector.OutputStream} | |
218 */ | |
219 WebInspector.FileOutputStream = function() | |
220 { | |
221 } | |
222 | |
223 WebInspector.FileOutputStream.prototype = { | |
224 /** | |
225 * @param {string} fileName | |
226 * @param {function(boolean)} callback | |
227 */ | |
228 open: function(fileName, callback) | |
229 { | |
230 this._closed = false; | |
231 this._writeCallbacks = []; | |
232 this._fileName = fileName; | |
233 | |
234 /** | |
235 * @param {boolean} accepted | |
236 * @this {WebInspector.FileOutputStream} | |
237 */ | |
238 function callbackWrapper(accepted) | |
239 { | |
240 if (accepted) | |
241 WebInspector.fileManager.addEventListener(WebInspector.FileManag
er.EventTypes.AppendedToURL, this._onAppendDone, this); | |
242 callback(accepted); | |
243 } | |
244 WebInspector.fileManager.save(this._fileName, "", true, callbackWrapper.
bind(this)); | |
245 }, | |
246 | |
247 /** | |
248 * @param {string} data | |
249 * @param {function(!WebInspector.OutputStream)=} callback | |
250 */ | |
251 write: function(data, callback) | |
252 { | |
253 this._writeCallbacks.push(callback); | |
254 WebInspector.fileManager.append(this._fileName, data); | |
255 }, | |
256 | |
257 close: function() | |
258 { | |
259 this._closed = true; | |
260 if (this._writeCallbacks.length) | |
261 return; | |
262 WebInspector.fileManager.removeEventListener(WebInspector.FileManager.Ev
entTypes.AppendedToURL, this._onAppendDone, this); | |
263 WebInspector.fileManager.close(this._fileName); | |
264 }, | |
265 | |
266 /** | |
267 * @param {!WebInspector.Event} event | |
268 */ | |
269 _onAppendDone: function(event) | |
270 { | |
271 if (event.data !== this._fileName) | |
272 return; | |
273 var callback = this._writeCallbacks.shift(); | |
274 if (callback) | |
275 callback(this); | |
276 if (!this._writeCallbacks.length) { | |
277 if (this._closed) { | |
278 WebInspector.fileManager.removeEventListener(WebInspector.FileMa
nager.EventTypes.AppendedToURL, this._onAppendDone, this); | |
279 WebInspector.fileManager.close(this._fileName); | |
280 } | |
281 } | |
282 } | |
283 } | |
OLD | NEW |