| 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 |