2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
31 window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
35 * @param {!string} dirPath
36 * @param {!string} name
37 * @param {!function(?WebInspector.TempFile)} callback
39 WebInspector.TempFile = function(dirPath, name, callback)
41 this._fileEntry = null;
45 * @param {!FileSystem} fs
46 * @this {WebInspector.TempFile}
48 function didInitFs(fs)
50 fs.root.getDirectory(dirPath, { create: true }, didGetDir.bind(this), errorHandler);
54 * @param {!DirectoryEntry} dir
55 * @this {WebInspector.TempFile}
57 function didGetDir(dir)
59 dir.getFile(name, { create: true }, didCreateFile.bind(this), errorHandler);
63 * @param {!FileEntry} fileEntry
64 * @this {WebInspector.TempFile}
66 function didCreateFile(fileEntry)
68 this._fileEntry = fileEntry;
69 fileEntry.createWriter(didCreateWriter.bind(this), errorHandler);
73 * @param {!FileWriter} writer
74 * @this {WebInspector.TempFile}
76 function didCreateWriter(writer)
79 * @this {WebInspector.TempFile}
81 function didTruncate(e)
83 this._writer = writer;
84 writer.onwriteend = null;
85 writer.onerror = null;
89 function onTruncateError(e)
91 WebInspector.console.error("Failed to truncate temp file " + e.code + " : " + e.message);
96 writer.onwriteend = didTruncate.bind(this);
97 writer.onerror = onTruncateError;
100 this._writer = writer;
105 function errorHandler(e)
107 WebInspector.console.error("Failed to create temp file " + e.code + " : " + e.message);
112 * @this {WebInspector.TempFile}
114 function didClearTempStorage()
116 window.requestFileSystem(window.TEMPORARY, 10, didInitFs.bind(this), errorHandler);
118 WebInspector.TempFile._ensureTempStorageCleared(didClearTempStorage.bind(this));
121 WebInspector.TempFile.prototype = {
123 * @param {!Array.<string>} strings
124 * @param {!function(boolean)} callback
126 write: function(strings, callback)
128 var blob = new Blob(strings, {type: 'text/plain'});
129 this._writer.onerror = function(e)
131 WebInspector.console.error("Failed to write into a temp file: " + e.target.error.message);
134 this._writer.onwriteend = function(e)
138 this._writer.write(blob);
141 finishWriting: function()
147 * @param {function(?string)} callback
149 read: function(callback)
151 this.readRange(undefined, undefined, callback);
155 * @param {number|undefined} startOffset
156 * @param {number|undefined} endOffset
157 * @param {function(?string)} callback
159 readRange: function(startOffset, endOffset, callback)
162 * @param {!Blob} file
164 function didGetFile(file)
166 var reader = new FileReader();
168 if (typeof startOffset === "number" || typeof endOffset === "number")
169 file = file.slice(/** @type {number} */ (startOffset), /** @type {number} */ (endOffset));
173 reader.onloadend = function(e)
175 callback(/** @type {?string} */ (this.result));
177 reader.onerror = function(error)
179 WebInspector.console.error("Failed to read from temp file: " + error.message);
181 reader.readAsText(file);
183 function didFailToGetFile(error)
185 WebInspector.console.error("Failed to load temp file: " + error.message);
188 this._fileEntry.file(didGetFile, didFailToGetFile);
192 * @param {!WebInspector.OutputStream} outputStream
193 * @param {!WebInspector.OutputStreamDelegate} delegate
195 writeToOutputSteam: function(outputStream, delegate)
198 * @param {!File} file
200 function didGetFile(file)
202 var reader = new WebInspector.ChunkedFileReader(file, 10*1000*1000, delegate);
203 reader.start(outputStream);
206 function didFailToGetFile(error)
208 WebInspector.console.error("Failed to load temp file: " + error.message);
209 outputStream.close();
212 this._fileEntry.file(didGetFile, didFailToGetFile);
218 this._fileEntry.remove(function() {});
224 * @param {!string} dirPath
225 * @param {!string} name
227 WebInspector.DeferredTempFile = function(dirPath, name)
230 this._tempFile = null;
231 this._isWriting = false;
232 this._finishCallback = null;
233 this._finishedWriting = false;
234 this._callsPendingOpen = [];
235 this._pendingReads = [];
236 new WebInspector.TempFile(dirPath, name, this._didCreateTempFile.bind(this));
239 WebInspector.DeferredTempFile.prototype = {
241 * @param {!Array.<string>} strings
243 write: function(strings)
247 if (this._finishCallback)
248 throw new Error("No writes are allowed after close.");
249 this._chunks.push.apply(this._chunks, strings);
250 if (this._tempFile && !this._isWriting)
251 this._writeNextChunk();
255 * @param {!function(?WebInspector.TempFile)} callback
257 finishWriting: function(callback)
259 this._finishCallback = callback;
260 if (this._finishedWriting)
261 callback(this._tempFile);
262 else if (!this._isWriting && !this._chunks.length)
263 this._notifyFinished();
266 _didCreateTempFile: function(tempFile)
268 this._tempFile = tempFile;
269 var callsPendingOpen = this._callsPendingOpen;
270 this._callsPendingOpen = null;
271 for (var i = 0; i < callsPendingOpen.length; ++i)
272 callsPendingOpen[i]();
275 this._notifyFinished();
278 if (this._chunks.length)
279 this._writeNextChunk();
282 _writeNextChunk: function()
284 var chunks = this._chunks;
286 this._isWriting = true;
287 this._tempFile.write(chunks, this._didWriteChunk.bind(this));
290 _didWriteChunk: function(success)
292 this._isWriting = false;
294 this._tempFile = null;
296 this._notifyFinished();
299 if (this._chunks.length)
300 this._writeNextChunk();
301 else if (this._finishCallback)
302 this._notifyFinished();
305 _notifyFinished: function()
307 this._finishedWriting = true;
309 this._tempFile.finishWriting();
310 if (this._finishCallback)
311 this._finishCallback(this._tempFile);
312 var pendingReads = this._pendingReads;
313 for (var i = 0; i < this._pendingReads.length; ++i)
314 this._pendingReads[i]();
315 this._pendingReads = [];
319 * @param {number|undefined} startOffset
320 * @param {number|undefined} endOffset
321 * @param {function(string?)} callback
323 readRange: function(startOffset, endOffset, callback)
325 if (!this._finishedWriting) {
326 this._pendingReads.push(this.readRange.bind(this, startOffset, endOffset, callback));
329 if (!this._tempFile) {
333 this._tempFile.readRange(startOffset, endOffset, callback);
337 * @param {!WebInspector.OutputStream} outputStream
338 * @param {!WebInspector.OutputStreamDelegate} delegate
340 writeToOutputStream: function(outputStream, delegate)
342 if (this._callsPendingOpen) {
343 this._callsPendingOpen.push(this.writeToOutputStream.bind(this, outputStream, delegate));
347 this._tempFile.writeToOutputSteam(outputStream, delegate);
352 if (this._callsPendingOpen) {
353 this._callsPendingOpen.push(this.remove.bind(this));
357 this._tempFile.remove();
364 WebInspector.TempStorageCleaner = function()
366 this._worker = Runtime.startSharedWorker("temp_storage_shared_worker", "TempStorage");
367 this._worker.onerror = this._handleError.bind(this);
368 this._callbacks = [];
369 this._worker.port.onmessage = this._handleMessage.bind(this);
370 this._worker.port.onerror = this._handleError.bind(this);
373 WebInspector.TempStorageCleaner.prototype = {
375 * @param {!function()} callback
377 ensureStorageCleared: function(callback)
380 this._callbacks.push(callback);
385 _handleMessage: function(event)
387 if (event.data.type === "tempStorageCleared") {
388 if (event.data.error)
389 WebInspector.console.error(event.data.error);
390 this._notifyCallbacks();
394 _handleError: function(event)
396 WebInspector.console.error(WebInspector.UIString("Failed to clear temp storage: %s", event.data));
397 this._notifyCallbacks();
400 _notifyCallbacks: function()
402 var callbacks = this._callbacks;
403 this._callbacks = null;
404 for (var i = 0; i < callbacks.length; i++)
410 * @param {!function()} callback
412 WebInspector.TempFile._ensureTempStorageCleared = function(callback)
414 if (!WebInspector.TempFile._storageCleaner)
415 WebInspector.TempFile._storageCleaner = new WebInspector.TempStorageCleaner();
416 WebInspector.TempFile._storageCleaner.ensureStorageCleared(callback);