Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / bindings / TempFile.js
1 /*
2  * Copyright (C) 2013 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 window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
32
33 /**
34  * @constructor
35  * @param {!string} dirPath
36  * @param {!string} name
37  * @param {!function(?WebInspector.TempFile)} callback
38  */
39 WebInspector.TempFile = function(dirPath, name, callback)
40 {
41     this._fileEntry = null;
42     this._writer = null;
43
44     /**
45      * @param {!FileSystem} fs
46      * @this {WebInspector.TempFile}
47      */
48     function didInitFs(fs)
49     {
50         fs.root.getDirectory(dirPath, { create: true }, didGetDir.bind(this), errorHandler);
51     }
52
53     /**
54      * @param {!DirectoryEntry} dir
55      * @this {WebInspector.TempFile}
56      */
57     function didGetDir(dir)
58     {
59         dir.getFile(name, { create: true }, didCreateFile.bind(this), errorHandler);
60     }
61
62     /**
63      * @param {!FileEntry} fileEntry
64      * @this {WebInspector.TempFile}
65      */
66     function didCreateFile(fileEntry)
67     {
68         this._fileEntry = fileEntry;
69         fileEntry.createWriter(didCreateWriter.bind(this), errorHandler);
70     }
71
72     /**
73      * @param {!FileWriter} writer
74      * @this {WebInspector.TempFile}
75      */
76     function didCreateWriter(writer)
77     {
78         /**
79          * @this {WebInspector.TempFile}
80          */
81         function didTruncate(e)
82         {
83             this._writer = writer;
84             writer.onwriteend = null;
85             writer.onerror = null;
86             callback(this);
87         }
88
89         function onTruncateError(e)
90         {
91             WebInspector.console.error("Failed to truncate temp file " + e.code + " : " + e.message);
92             callback(null);
93         }
94
95         if (writer.length) {
96             writer.onwriteend = didTruncate.bind(this);
97             writer.onerror = onTruncateError;
98             writer.truncate(0);
99         } else {
100             this._writer = writer;
101             callback(this);
102         }
103     }
104
105     function errorHandler(e)
106     {
107         WebInspector.console.error("Failed to create temp file " + e.code + " : " + e.message);
108         callback(null);
109     }
110
111     /**
112      * @this {WebInspector.TempFile}
113      */
114     function didClearTempStorage()
115     {
116         window.requestFileSystem(window.TEMPORARY, 10, didInitFs.bind(this), errorHandler);
117     }
118     WebInspector.TempFile._ensureTempStorageCleared(didClearTempStorage.bind(this));
119 }
120
121 WebInspector.TempFile.prototype = {
122     /**
123      * @param {!Array.<string>} strings
124      * @param {!function(boolean)} callback
125      */
126     write: function(strings, callback)
127     {
128         var blob = new Blob(strings, {type: 'text/plain'});
129         this._writer.onerror = function(e)
130         {
131             WebInspector.console.error("Failed to write into a temp file: " + e.target.error.message);
132             callback(false);
133         }
134         this._writer.onwriteend = function(e)
135         {
136             callback(true);
137         }
138         this._writer.write(blob);
139     },
140
141     finishWriting: function()
142     {
143         this._writer = null;
144     },
145
146     /**
147      * @param {function(?string)} callback
148      */
149     read: function(callback)
150     {
151         this.readRange(undefined, undefined, callback);
152     },
153
154     /**
155      * @param {number|undefined} startOffset
156      * @param {number|undefined} endOffset
157      * @param {function(?string)} callback
158      */
159     readRange: function(startOffset, endOffset, callback)
160     {
161         /**
162          * @param {!Blob} file
163          */
164         function didGetFile(file)
165         {
166             var reader = new FileReader();
167
168             if (typeof startOffset === "number" || typeof endOffset === "number")
169                 file = file.slice(/** @type {number} */ (startOffset), /** @type {number} */ (endOffset));
170             /**
171              * @this {FileReader}
172              */
173             reader.onloadend = function(e)
174             {
175                 callback(/** @type {?string} */ (this.result));
176             }
177             reader.onerror = function(error)
178             {
179                 WebInspector.console.error("Failed to read from temp file: " + error.message);
180             }
181             reader.readAsText(file);
182         }
183         function didFailToGetFile(error)
184         {
185             WebInspector.console.error("Failed to load temp file: " + error.message);
186             callback(null);
187         }
188         this._fileEntry.file(didGetFile, didFailToGetFile);
189     },
190
191     /**
192      * @param {!WebInspector.OutputStream} outputStream
193      * @param {!WebInspector.OutputStreamDelegate} delegate
194      */
195     writeToOutputSteam: function(outputStream, delegate)
196     {
197         /**
198          * @param {!File} file
199          */
200         function didGetFile(file)
201         {
202             var reader = new WebInspector.ChunkedFileReader(file, 10*1000*1000, delegate);
203             reader.start(outputStream);
204         }
205
206         function didFailToGetFile(error)
207         {
208             WebInspector.console.error("Failed to load temp file: " + error.message);
209             outputStream.close();
210         }
211
212         this._fileEntry.file(didGetFile, didFailToGetFile);
213     },
214
215     remove: function()
216     {
217         if (this._fileEntry)
218             this._fileEntry.remove(function() {});
219     }
220 }
221
222 /**
223  * @constructor
224  * @param {!string} dirPath
225  * @param {!string} name
226  */
227 WebInspector.DeferredTempFile = function(dirPath, name)
228 {
229     this._chunks = [];
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));
237 }
238
239 WebInspector.DeferredTempFile.prototype = {
240     /**
241      * @param {!Array.<string>} strings
242      */
243     write: function(strings)
244     {
245         if (!this._chunks)
246             return;
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();
252     },
253
254     /**
255      * @param {!function(?WebInspector.TempFile)} callback
256      */
257     finishWriting: function(callback)
258     {
259         this._finishCallback = callback;
260         if (this._finishedWriting)
261             callback(this._tempFile);
262         else if (!this._isWriting && !this._chunks.length)
263             this._notifyFinished();
264     },
265
266     _didCreateTempFile: function(tempFile)
267     {
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]();
273         if (!tempFile) {
274             this._chunks = null;
275             this._notifyFinished();
276             return;
277         }
278         if (this._chunks.length)
279             this._writeNextChunk();
280     },
281
282     _writeNextChunk: function()
283     {
284         var chunks = this._chunks;
285         this._chunks = [];
286         this._isWriting = true;
287         this._tempFile.write(chunks, this._didWriteChunk.bind(this));
288     },
289
290     _didWriteChunk: function(success)
291     {
292         this._isWriting = false;
293         if (!success) {
294             this._tempFile = null;
295             this._chunks = null;
296             this._notifyFinished();
297             return;
298         }
299         if (this._chunks.length)
300             this._writeNextChunk();
301         else if (this._finishCallback)
302             this._notifyFinished();
303     },
304
305     _notifyFinished: function()
306     {
307         this._finishedWriting = true;
308         if (this._tempFile)
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 = [];
316     },
317
318     /**
319      * @param {number|undefined} startOffset
320      * @param {number|undefined} endOffset
321      * @param {function(string?)} callback
322      */
323     readRange: function(startOffset, endOffset, callback)
324     {
325         if (!this._finishedWriting) {
326             this._pendingReads.push(this.readRange.bind(this, startOffset, endOffset, callback));
327             return;
328         }
329         if (!this._tempFile) {
330             callback(null);
331             return;
332         }
333         this._tempFile.readRange(startOffset, endOffset, callback);
334     },
335
336     /**
337      * @param {!WebInspector.OutputStream} outputStream
338      * @param {!WebInspector.OutputStreamDelegate} delegate
339      */
340     writeToOutputStream: function(outputStream, delegate)
341     {
342         if (this._callsPendingOpen) {
343             this._callsPendingOpen.push(this.writeToOutputStream.bind(this, outputStream, delegate));
344             return;
345         }
346         if (this._tempFile)
347             this._tempFile.writeToOutputSteam(outputStream, delegate);
348     },
349
350     remove: function()
351     {
352         if (this._callsPendingOpen) {
353             this._callsPendingOpen.push(this.remove.bind(this));
354             return;
355         }
356         if (this._tempFile)
357             this._tempFile.remove();
358     }
359 }
360
361 /**
362  * @constructor
363  */
364 WebInspector.TempStorageCleaner = function()
365 {
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);
371 }
372
373 WebInspector.TempStorageCleaner.prototype = {
374     /**
375      * @param {!function()} callback
376      */
377     ensureStorageCleared: function(callback)
378     {
379         if (this._callbacks)
380             this._callbacks.push(callback);
381         else
382             callback();
383     },
384
385     _handleMessage: function(event)
386     {
387         if (event.data.type === "tempStorageCleared") {
388             if (event.data.error)
389                 WebInspector.console.error(event.data.error);
390             this._notifyCallbacks();
391         }
392     },
393
394     _handleError: function(event)
395     {
396         WebInspector.console.error(WebInspector.UIString("Failed to clear temp storage: %s", event.data));
397         this._notifyCallbacks();
398     },
399
400     _notifyCallbacks: function()
401     {
402         var callbacks = this._callbacks;
403         this._callbacks = null;
404         for (var i = 0; i < callbacks.length; i++)
405             callbacks[i]();
406     }
407 }
408
409 /**
410  * @param {!function()} callback
411  */
412 WebInspector.TempFile._ensureTempStorageCleared = function(callback)
413 {
414     if (!WebInspector.TempFile._storageCleaner)
415         WebInspector.TempFile._storageCleaner = new WebInspector.TempStorageCleaner();
416     WebInspector.TempFile._storageCleaner.ensureStorageCleared(callback);
417 }