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