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