Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/workspace/IsolatedFileSystem.js

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 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 * @constructor 31 * @unrestricted
33 * @param {!WebInspector.IsolatedFileSystemManager} manager
34 * @param {string} path
35 * @param {string} embedderPath
36 * @param {!DOMFileSystem} domFileSystem
37 */ 32 */
38 WebInspector.IsolatedFileSystem = function(manager, path, embedderPath, domFileS ystem) 33 WebInspector.IsolatedFileSystem = class {
39 { 34 /**
35 * @param {!WebInspector.IsolatedFileSystemManager} manager
36 * @param {string} path
37 * @param {string} embedderPath
38 * @param {!DOMFileSystem} domFileSystem
39 */
40 constructor(manager, path, embedderPath, domFileSystem) {
40 this._manager = manager; 41 this._manager = manager;
41 this._path = path; 42 this._path = path;
42 this._embedderPath = embedderPath; 43 this._embedderPath = embedderPath;
43 this._domFileSystem = domFileSystem; 44 this._domFileSystem = domFileSystem;
44 this._excludedFoldersSetting = WebInspector.settings.createLocalSetting("wor kspaceExcludedFolders", {}); 45 this._excludedFoldersSetting = WebInspector.settings.createLocalSetting('wor kspaceExcludedFolders', {});
45 /** @type {!Set<string>} */ 46 /** @type {!Set<string>} */
46 this._excludedFolders = new Set(this._excludedFoldersSetting.get()[path] || []); 47 this._excludedFolders = new Set(this._excludedFoldersSetting.get()[path] || []);
47 /** @type {!Set<string>} */ 48 /** @type {!Set<string>} */
48 this._nonConfigurableExcludedFolders = new Set(); 49 this._nonConfigurableExcludedFolders = new Set();
49 50
50 /** @type {!Set<string>} */ 51 /** @type {!Set<string>} */
51 this._filePaths = new Set(); 52 this._filePaths = new Set();
52 /** @type {!Set<string>} */ 53 /** @type {!Set<string>} */
53 this._gitFolders = new Set(); 54 this._gitFolders = new Set();
54 }; 55 }
55 56
56 WebInspector.IsolatedFileSystem.ImageExtensions = new Set(["jpeg", "jpg", "svg", "gif", "webp", "png", "ico", "tiff", "tif", "bmp"]); 57 /**
57 58 * @param {!WebInspector.IsolatedFileSystemManager} manager
58 /** 59 * @param {string} path
59 * @constructor 60 * @param {string} embedderPath
60 * @param {!WebInspector.IsolatedFileSystemManager} manager 61 * @param {string} name
61 * @param {string} path 62 * @param {string} rootURL
62 * @param {string} embedderPath 63 * @return {!Promise<?WebInspector.IsolatedFileSystem>}
63 * @param {string} name 64 */
64 * @param {string} rootURL 65 static create(manager, path, embedderPath, name, rootURL) {
65 * @return {!Promise<?WebInspector.IsolatedFileSystem>}
66 */
67 WebInspector.IsolatedFileSystem.create = function(manager, path, embedderPath, n ame, rootURL)
68 {
69 var domFileSystem = InspectorFrontendHost.isolatedFileSystem(name, rootURL); 66 var domFileSystem = InspectorFrontendHost.isolatedFileSystem(name, rootURL);
70 if (!domFileSystem) 67 if (!domFileSystem)
71 return Promise.resolve(/** @type {?WebInspector.IsolatedFileSystem} */(n ull)); 68 return Promise.resolve(/** @type {?WebInspector.IsolatedFileSystem} */ (nu ll));
72 69
73 var fileSystem = new WebInspector.IsolatedFileSystem(manager, path, embedder Path, domFileSystem); 70 var fileSystem = new WebInspector.IsolatedFileSystem(manager, path, embedder Path, domFileSystem);
74 var fileContentPromise = fileSystem.requestFileContentPromise(".devtools"); 71 var fileContentPromise = fileSystem.requestFileContentPromise('.devtools');
75 return fileContentPromise.then(onConfigAvailable) 72 return fileContentPromise.then(onConfigAvailable)
76 .then(() => fileSystem) 73 .then(() => fileSystem)
77 .catchException(/** @type {?WebInspector.IsolatedFileSystem} */(null)); 74 .catchException(/** @type {?WebInspector.IsolatedFileSystem} */ (null));
78 75
79 /** 76 /**
80 * @param {?string} projectText 77 * @param {?string} projectText
81 * @return {!Promise} 78 * @return {!Promise}
82 */ 79 */
83 function onConfigAvailable(projectText) 80 function onConfigAvailable(projectText) {
84 { 81 if (projectText) {
85 if (projectText) { 82 try {
86 try { 83 var projectObject = JSON.parse(projectText);
87 var projectObject = JSON.parse(projectText); 84 fileSystem._initializeProject(
88 fileSystem._initializeProject(typeof projectObject === "object" ? /** @type {!Object} */ (projectObject) : null); 85 typeof projectObject === 'object' ? /** @type {!Object} */ (projec tObject) : null);
89 } catch (e) { 86 } catch (e) {
90 WebInspector.console.error("Invalid project file: " + projectTex t); 87 WebInspector.console.error('Invalid project file: ' + projectText);
91 }
92 } 88 }
93 return fileSystem._initializeFilePaths(); 89 }
94 } 90 return fileSystem._initializeFilePaths();
91 }
92 }
93
94 /**
95 * @param {!DOMError} error
96 * @return {string}
97 */
98 static errorMessage(error) {
99 return WebInspector.UIString('File system error: %s', error.message);
100 }
101
102 /**
103 * @param {string} path
104 * @return {!Promise<?{modificationTime: !Date, size: number}>}
105 */
106 getMetadata(path) {
107 var fulfill;
108 var promise = new Promise(f => fulfill = f);
109 this._domFileSystem.root.getFile(path, null, fileEntryLoaded, errorHandler);
110 return promise;
111
112 /**
113 * @param {!FileEntry} entry
114 */
115 function fileEntryLoaded(entry) {
116 entry.getMetadata(fulfill, errorHandler);
117 }
118
119 /**
120 * @param {!FileError} error
121 */
122 function errorHandler(error) {
123 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(error);
124 console.error(errorMessage + ' when getting file metadata \'' + path);
125 fulfill(null);
126 }
127 }
128
129 /**
130 * @return {!Array<string>}
131 */
132 filePaths() {
133 return this._filePaths.valuesArray();
134 }
135
136 /**
137 * @return {!Array<string>}
138 */
139 gitFolders() {
140 return this._gitFolders.valuesArray();
141 }
142
143 /**
144 * @return {string}
145 */
146 path() {
147 return this._path;
148 }
149
150 /**
151 * @return {string}
152 */
153 embedderPath() {
154 return this._embedderPath;
155 }
156
157 /**
158 * @param {?Object} projectObject
159 */
160 _initializeProject(projectObject) {
161 this._projectObject = projectObject;
162
163 var projectExcludes = this.projectProperty('excludes');
164 if (Array.isArray(projectExcludes)) {
165 for (var folder of /** @type {!Array<*>} */ (projectExcludes)) {
166 if (typeof folder === 'string')
167 this._nonConfigurableExcludedFolders.add(folder);
168 }
169 }
170 }
171
172 /**
173 * @param {string} key
174 * @return {*}
175 */
176 projectProperty(key) {
177 return this._projectObject ? this._projectObject[key] : null;
178 }
179
180 /**
181 * @return {!Promise}
182 */
183 _initializeFilePaths() {
184 var fulfill;
185 var promise = new Promise(x => fulfill = x);
186 var pendingRequests = 1;
187 var boundInnerCallback = innerCallback.bind(this);
188 this._requestEntries('', boundInnerCallback);
189 return promise;
190
191 /**
192 * @param {!Array.<!FileEntry>} entries
193 * @this {WebInspector.IsolatedFileSystem}
194 */
195 function innerCallback(entries) {
196 for (var i = 0; i < entries.length; ++i) {
197 var entry = entries[i];
198 if (!entry.isDirectory) {
199 if (this._isFileExcluded(entry.fullPath))
200 continue;
201 this._filePaths.add(entry.fullPath.substr(1));
202 } else {
203 if (entry.fullPath.endsWith('/.git')) {
204 var lastSlash = entry.fullPath.lastIndexOf('/');
205 var parentFolder = entry.fullPath.substring(1, lastSlash);
206 this._gitFolders.add(parentFolder);
207 }
208 if (this._isFileExcluded(entry.fullPath + '/'))
209 continue;
210 ++pendingRequests;
211 this._requestEntries(entry.fullPath, boundInnerCallback);
212 }
213 }
214 if ((--pendingRequests === 0))
215 fulfill();
216 }
217 }
218
219 /**
220 * @param {string} path
221 * @param {?string} name
222 * @param {function(?string)} callback
223 */
224 createFile(path, name, callback) {
225 var newFileIndex = 1;
226 if (!name)
227 name = 'NewFile';
228 var nameCandidate;
229
230 this._domFileSystem.root.getDirectory(path, null, dirEntryLoaded.bind(this), errorHandler.bind(this));
231
232 /**
233 * @param {!DirectoryEntry} dirEntry
234 * @this {WebInspector.IsolatedFileSystem}
235 */
236 function dirEntryLoaded(dirEntry) {
237 var nameCandidate = name;
238 if (newFileIndex > 1)
239 nameCandidate += newFileIndex;
240 ++newFileIndex;
241 dirEntry.getFile(nameCandidate, {create: true, exclusive: true}, fileCreat ed, fileCreationError.bind(this));
242
243 function fileCreated(entry) {
244 callback(entry.fullPath.substr(1));
245 }
246
247 /**
248 * @this {WebInspector.IsolatedFileSystem}
249 */
250 function fileCreationError(error) {
251 if (error.name === 'InvalidModificationError') {
252 dirEntryLoaded.call(this, dirEntry);
253 return;
254 }
255
256 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(error);
257 console.error(
258 errorMessage + ' when testing if file exists \'' + (this._path + '/' + path + '/' + nameCandidate) + '\'');
259 callback(null);
260 }
261 }
262
263 /**
264 * @this {WebInspector.IsolatedFileSystem}
265 */
266 function errorHandler(error) {
267 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(error);
268 var filePath = this._path + '/' + path;
269 if (nameCandidate)
270 filePath += '/' + nameCandidate;
271 console.error(errorMessage + ' when getting content for file \'' + (filePa th) + '\'');
272 callback(null);
273 }
274 }
275
276 /**
277 * @param {string} path
278 */
279 deleteFile(path) {
280 this._domFileSystem.root.getFile(path, null, fileEntryLoaded.bind(this), err orHandler.bind(this));
281
282 /**
283 * @param {!FileEntry} fileEntry
284 * @this {WebInspector.IsolatedFileSystem}
285 */
286 function fileEntryLoaded(fileEntry) {
287 fileEntry.remove(fileEntryRemoved, errorHandler.bind(this));
288 }
289
290 function fileEntryRemoved() {
291 }
292
293 /**
294 * @param {!FileError} error
295 * @this {WebInspector.IsolatedFileSystem}
296 * @suppress {checkTypes}
297 * TODO(jsbell): Update externs replacing FileError with DOMException. https ://crbug.com/496901
298 */
299 function errorHandler(error) {
300 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(error);
301 console.error(errorMessage + ' when deleting file \'' + (this._path + '/' + path) + '\'');
302 }
303 }
304
305 /**
306 * @param {string} path
307 * @return {!Promise<?string>}
308 */
309 requestFileContentPromise(path) {
310 var fulfill;
311 var promise = new Promise(x => fulfill = x);
312 this.requestFileContent(path, fulfill);
313 return promise;
314 }
315
316 /**
317 * @param {string} path
318 * @param {function(?string)} callback
319 */
320 requestFileContent(path, callback) {
321 this._domFileSystem.root.getFile(path, null, fileEntryLoaded.bind(this), err orHandler.bind(this));
322
323 /**
324 * @param {!FileEntry} entry
325 * @this {WebInspector.IsolatedFileSystem}
326 */
327 function fileEntryLoaded(entry) {
328 entry.file(fileLoaded, errorHandler.bind(this));
329 }
330
331 /**
332 * @param {!Blob} file
333 */
334 function fileLoaded(file) {
335 var reader = new FileReader();
336 reader.onloadend = readerLoadEnd;
337 if (WebInspector.IsolatedFileSystem.ImageExtensions.has(WebInspector.Parse dURL.extractExtension(path)))
338 reader.readAsDataURL(file);
339 else
340 reader.readAsText(file);
341 }
342
343 /**
344 * @this {!FileReader}
345 */
346 function readerLoadEnd() {
347 /** @type {?string} */
348 var string = null;
349 try {
350 string = /** @type {string} */ (this.result);
351 } catch (e) {
352 console.error('Can\'t read file: ' + path + ': ' + e);
353 }
354 callback(string);
355 }
356
357 /**
358 * @this {WebInspector.IsolatedFileSystem}
359 */
360 function errorHandler(error) {
361 if (error.name === 'NotFoundError') {
362 callback(null);
363 return;
364 }
365
366 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(error);
367 console.error(errorMessage + ' when getting content for file \'' + (this._ path + '/' + path) + '\'');
368 callback(null);
369 }
370 }
371
372 /**
373 * @param {string} path
374 * @param {string} content
375 * @param {function()} callback
376 */
377 setFileContent(path, content, callback) {
378 WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Action.FileSav edInWorkspace);
379 this._domFileSystem.root.getFile(path, {create: true}, fileEntryLoaded.bind( this), errorHandler.bind(this));
380
381 /**
382 * @param {!FileEntry} entry
383 * @this {WebInspector.IsolatedFileSystem}
384 */
385 function fileEntryLoaded(entry) {
386 entry.createWriter(fileWriterCreated.bind(this), errorHandler.bind(this));
387 }
388
389 /**
390 * @param {!FileWriter} fileWriter
391 * @this {WebInspector.IsolatedFileSystem}
392 */
393 function fileWriterCreated(fileWriter) {
394 fileWriter.onerror = errorHandler.bind(this);
395 fileWriter.onwriteend = fileWritten;
396 var blob = new Blob([content], {type: 'text/plain'});
397 fileWriter.write(blob);
398
399 function fileWritten() {
400 fileWriter.onwriteend = callback;
401 fileWriter.truncate(blob.size);
402 }
403 }
404
405 /**
406 * @this {WebInspector.IsolatedFileSystem}
407 */
408 function errorHandler(error) {
409 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(error);
410 console.error(errorMessage + ' when setting content for file \'' + (this._ path + '/' + path) + '\'');
411 callback();
412 }
413 }
414
415 /**
416 * @param {string} path
417 * @param {string} newName
418 * @param {function(boolean, string=)} callback
419 */
420 renameFile(path, newName, callback) {
421 newName = newName ? newName.trim() : newName;
422 if (!newName || newName.indexOf('/') !== -1) {
423 callback(false);
424 return;
425 }
426 var fileEntry;
427 var dirEntry;
428
429 this._domFileSystem.root.getFile(path, null, fileEntryLoaded.bind(this), err orHandler.bind(this));
430
431 /**
432 * @param {!FileEntry} entry
433 * @this {WebInspector.IsolatedFileSystem}
434 */
435 function fileEntryLoaded(entry) {
436 if (entry.name === newName) {
437 callback(false);
438 return;
439 }
440
441 fileEntry = entry;
442 fileEntry.getParent(dirEntryLoaded.bind(this), errorHandler.bind(this));
443 }
444
445 /**
446 * @param {!Entry} entry
447 * @this {WebInspector.IsolatedFileSystem}
448 */
449 function dirEntryLoaded(entry) {
450 dirEntry = entry;
451 dirEntry.getFile(newName, null, newFileEntryLoaded, newFileEntryLoadErrorH andler.bind(this));
452 }
453
454 /**
455 * @param {!FileEntry} entry
456 */
457 function newFileEntryLoaded(entry) {
458 callback(false);
459 }
460
461 /**
462 * @this {WebInspector.IsolatedFileSystem}
463 */
464 function newFileEntryLoadErrorHandler(error) {
465 if (error.name !== 'NotFoundError') {
466 callback(false);
467 return;
468 }
469 fileEntry.moveTo(dirEntry, newName, fileRenamed, errorHandler.bind(this));
470 }
471
472 /**
473 * @param {!FileEntry} entry
474 */
475 function fileRenamed(entry) {
476 callback(true, entry.name);
477 }
478
479 /**
480 * @this {WebInspector.IsolatedFileSystem}
481 */
482 function errorHandler(error) {
483 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(error);
484 console.error(errorMessage + ' when renaming file \'' + (this._path + '/' + path) + '\' to \'' + newName + '\'');
485 callback(false);
486 }
487 }
488
489 /**
490 * @param {!DirectoryEntry} dirEntry
491 * @param {function(!Array.<!FileEntry>)} callback
492 */
493 _readDirectory(dirEntry, callback) {
494 var dirReader = dirEntry.createReader();
495 var entries = [];
496
497 function innerCallback(results) {
498 if (!results.length) {
499 callback(entries.sort());
500 } else {
501 entries = entries.concat(toArray(results));
502 dirReader.readEntries(innerCallback, errorHandler);
503 }
504 }
505
506 function toArray(list) {
507 return Array.prototype.slice.call(list || [], 0);
508 }
509
510 dirReader.readEntries(innerCallback, errorHandler);
511
512 function errorHandler(error) {
513 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(error);
514 console.error(errorMessage + ' when reading directory \'' + dirEntry.fullP ath + '\'');
515 callback([]);
516 }
517 }
518
519 /**
520 * @param {string} path
521 * @param {function(!Array.<!FileEntry>)} callback
522 */
523 _requestEntries(path, callback) {
524 this._domFileSystem.root.getDirectory(path, null, innerCallback.bind(this), errorHandler);
525
526 /**
527 * @param {!DirectoryEntry} dirEntry
528 * @this {WebInspector.IsolatedFileSystem}
529 */
530 function innerCallback(dirEntry) {
531 this._readDirectory(dirEntry, callback);
532 }
533
534 function errorHandler(error) {
535 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(error);
536 console.error(errorMessage + ' when requesting entry \'' + path + '\'');
537 callback([]);
538 }
539 }
540
541 _saveExcludedFolders() {
542 var settingValue = this._excludedFoldersSetting.get();
543 settingValue[this._path] = this._excludedFolders.valuesArray();
544 this._excludedFoldersSetting.set(settingValue);
545 }
546
547 /**
548 * @param {string} path
549 */
550 addExcludedFolder(path) {
551 this._excludedFolders.add(path);
552 this._saveExcludedFolders();
553 this._manager.dispatchEventToListeners(WebInspector.IsolatedFileSystemManage r.Events.ExcludedFolderAdded, path);
554 }
555
556 /**
557 * @param {string} path
558 */
559 removeExcludedFolder(path) {
560 this._excludedFolders.delete(path);
561 this._saveExcludedFolders();
562 this._manager.dispatchEventToListeners(WebInspector.IsolatedFileSystemManage r.Events.ExcludedFolderRemoved, path);
563 }
564
565 fileSystemRemoved() {
566 var settingValue = this._excludedFoldersSetting.get();
567 delete settingValue[this._path];
568 this._excludedFoldersSetting.set(settingValue);
569 }
570
571 /**
572 * @param {string} folderPath
573 * @return {boolean}
574 */
575 _isFileExcluded(folderPath) {
576 if (this._nonConfigurableExcludedFolders.has(folderPath) || this._excludedFo lders.has(folderPath))
577 return true;
578 var regex = this._manager.workspaceFolderExcludePatternSetting().asRegExp();
579 return !!(regex && regex.test(folderPath));
580 }
581
582 /**
583 * @return {!Set<string>}
584 */
585 excludedFolders() {
586 return this._excludedFolders;
587 }
588
589 /**
590 * @return {!Set<string>}
591 */
592 nonConfigurableExcludedFolders() {
593 return this._nonConfigurableExcludedFolders;
594 }
595
596 /**
597 * @param {string} query
598 * @param {!WebInspector.Progress} progress
599 * @param {function(!Array.<string>)} callback
600 */
601 searchInPath(query, progress, callback) {
602 var requestId = this._manager.registerCallback(innerCallback);
603 InspectorFrontendHost.searchInPath(requestId, this._embedderPath, query);
604
605 /**
606 * @param {!Array.<string>} files
607 */
608 function innerCallback(files) {
609 files = files.map(embedderPath => WebInspector.ParsedURL.platformPathToURL (embedderPath));
610 progress.worked(1);
611 callback(files);
612 }
613 }
614
615 /**
616 * @param {!WebInspector.Progress} progress
617 */
618 indexContent(progress) {
619 progress.setTotalWork(1);
620 var requestId = this._manager.registerProgress(progress);
621 InspectorFrontendHost.indexPath(requestId, this._embedderPath);
622 }
95 }; 623 };
96 624
97 /** 625 WebInspector.IsolatedFileSystem.ImageExtensions =
98 * @param {!DOMError} error 626 new Set(['jpeg', 'jpg', 'svg', 'gif', 'webp', 'png', 'ico', 'tiff', 'tif', ' bmp']);
99 * @return {string} 627
100 */ 628
101 WebInspector.IsolatedFileSystem.errorMessage = function(error)
102 {
103 return WebInspector.UIString("File system error: %s", error.message);
104 };
105
106 WebInspector.IsolatedFileSystem.prototype = {
107 /**
108 * @param {string} path
109 * @return {!Promise<?{modificationTime: !Date, size: number}>}
110 */
111 getMetadata: function(path)
112 {
113 var fulfill;
114 var promise = new Promise(f => fulfill = f);
115 this._domFileSystem.root.getFile(path, null, fileEntryLoaded, errorHandl er);
116 return promise;
117
118 /**
119 * @param {!FileEntry} entry
120 */
121 function fileEntryLoaded(entry)
122 {
123 entry.getMetadata(fulfill, errorHandler);
124 }
125
126 /**
127 * @param {!FileError} error
128 */
129 function errorHandler(error)
130 {
131 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(erro r);
132 console.error(errorMessage + " when getting file metadata '" + path) ;
133 fulfill(null);
134 }
135 },
136
137 /**
138 * @return {!Array<string>}
139 */
140 filePaths: function()
141 {
142 return this._filePaths.valuesArray();
143 },
144
145 /**
146 * @return {!Array<string>}
147 */
148 gitFolders: function()
149 {
150 return this._gitFolders.valuesArray();
151 },
152
153 /**
154 * @return {string}
155 */
156 path: function()
157 {
158 return this._path;
159 },
160
161 /**
162 * @return {string}
163 */
164 embedderPath: function()
165 {
166 return this._embedderPath;
167 },
168
169 /**
170 * @param {?Object} projectObject
171 */
172 _initializeProject: function(projectObject)
173 {
174 this._projectObject = projectObject;
175
176 var projectExcludes = this.projectProperty("excludes");
177 if (Array.isArray(projectExcludes)) {
178 for (var folder of /** @type {!Array<*>} */ (projectExcludes)) {
179 if (typeof folder === "string")
180 this._nonConfigurableExcludedFolders.add(folder);
181 }
182 }
183 },
184
185 /**
186 * @param {string} key
187 * @return {*}
188 */
189 projectProperty: function(key)
190 {
191 return this._projectObject ? this._projectObject[key] : null;
192 },
193
194 /**
195 * @return {!Promise}
196 */
197 _initializeFilePaths: function()
198 {
199 var fulfill;
200 var promise = new Promise(x => fulfill = x);
201 var pendingRequests = 1;
202 var boundInnerCallback = innerCallback.bind(this);
203 this._requestEntries("", boundInnerCallback);
204 return promise;
205
206 /**
207 * @param {!Array.<!FileEntry>} entries
208 * @this {WebInspector.IsolatedFileSystem}
209 */
210 function innerCallback(entries)
211 {
212 for (var i = 0; i < entries.length; ++i) {
213 var entry = entries[i];
214 if (!entry.isDirectory) {
215 if (this._isFileExcluded(entry.fullPath))
216 continue;
217 this._filePaths.add(entry.fullPath.substr(1));
218 } else {
219 if (entry.fullPath.endsWith("/.git")) {
220 var lastSlash = entry.fullPath.lastIndexOf("/");
221 var parentFolder = entry.fullPath.substring(1, lastSlash );
222 this._gitFolders.add(parentFolder);
223 }
224 if (this._isFileExcluded(entry.fullPath + "/"))
225 continue;
226 ++pendingRequests;
227 this._requestEntries(entry.fullPath, boundInnerCallback);
228 }
229 }
230 if ((--pendingRequests === 0))
231 fulfill();
232 }
233 },
234
235 /**
236 * @param {string} path
237 * @param {?string} name
238 * @param {function(?string)} callback
239 */
240 createFile: function(path, name, callback)
241 {
242 var newFileIndex = 1;
243 if (!name)
244 name = "NewFile";
245 var nameCandidate;
246
247 this._domFileSystem.root.getDirectory(path, null, dirEntryLoaded.bind(th is), errorHandler.bind(this));
248
249 /**
250 * @param {!DirectoryEntry} dirEntry
251 * @this {WebInspector.IsolatedFileSystem}
252 */
253 function dirEntryLoaded(dirEntry)
254 {
255 var nameCandidate = name;
256 if (newFileIndex > 1)
257 nameCandidate += newFileIndex;
258 ++newFileIndex;
259 dirEntry.getFile(nameCandidate, { create: true, exclusive: true }, f ileCreated, fileCreationError.bind(this));
260
261 function fileCreated(entry)
262 {
263 callback(entry.fullPath.substr(1));
264 }
265
266 /**
267 * @this {WebInspector.IsolatedFileSystem}
268 */
269 function fileCreationError(error)
270 {
271 if (error.name === "InvalidModificationError") {
272 dirEntryLoaded.call(this, dirEntry);
273 return;
274 }
275
276 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage( error);
277 console.error(errorMessage + " when testing if file exists '" + (this._path + "/" + path + "/" + nameCandidate) + "'");
278 callback(null);
279 }
280 }
281
282 /**
283 * @this {WebInspector.IsolatedFileSystem}
284 */
285 function errorHandler(error)
286 {
287 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(erro r);
288 var filePath = this._path + "/" + path;
289 if (nameCandidate)
290 filePath += "/" + nameCandidate;
291 console.error(errorMessage + " when getting content for file '" + (f ilePath) + "'");
292 callback(null);
293 }
294 },
295
296 /**
297 * @param {string} path
298 */
299 deleteFile: function(path)
300 {
301 this._domFileSystem.root.getFile(path, null, fileEntryLoaded.bind(this), errorHandler.bind(this));
302
303 /**
304 * @param {!FileEntry} fileEntry
305 * @this {WebInspector.IsolatedFileSystem}
306 */
307 function fileEntryLoaded(fileEntry)
308 {
309 fileEntry.remove(fileEntryRemoved, errorHandler.bind(this));
310 }
311
312 function fileEntryRemoved()
313 {
314 }
315
316 /**
317 * @param {!FileError} error
318 * @this {WebInspector.IsolatedFileSystem}
319 * @suppress {checkTypes}
320 * TODO(jsbell): Update externs replacing FileError with DOMException. h ttps://crbug.com/496901
321 */
322 function errorHandler(error)
323 {
324 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(erro r);
325 console.error(errorMessage + " when deleting file '" + (this._path + "/" + path) + "'");
326 }
327 },
328
329 /**
330 * @param {string} path
331 * @return {!Promise<?string>}
332 */
333 requestFileContentPromise: function(path)
334 {
335 var fulfill;
336 var promise = new Promise(x => fulfill = x);
337 this.requestFileContent(path, fulfill);
338 return promise;
339 },
340
341 /**
342 * @param {string} path
343 * @param {function(?string)} callback
344 */
345 requestFileContent: function(path, callback)
346 {
347 this._domFileSystem.root.getFile(path, null, fileEntryLoaded.bind(this), errorHandler.bind(this));
348
349 /**
350 * @param {!FileEntry} entry
351 * @this {WebInspector.IsolatedFileSystem}
352 */
353 function fileEntryLoaded(entry)
354 {
355 entry.file(fileLoaded, errorHandler.bind(this));
356 }
357
358 /**
359 * @param {!Blob} file
360 */
361 function fileLoaded(file)
362 {
363 var reader = new FileReader();
364 reader.onloadend = readerLoadEnd;
365 if (WebInspector.IsolatedFileSystem.ImageExtensions.has(WebInspector .ParsedURL.extractExtension(path)))
366 reader.readAsDataURL(file);
367 else
368 reader.readAsText(file);
369 }
370
371 /**
372 * @this {!FileReader}
373 */
374 function readerLoadEnd()
375 {
376 /** @type {?string} */
377 var string = null;
378 try {
379 string = /** @type {string} */ (this.result);
380 } catch (e) {
381 console.error("Can't read file: " + path + ": " + e);
382 }
383 callback(string);
384 }
385
386 /**
387 * @this {WebInspector.IsolatedFileSystem}
388 */
389 function errorHandler(error)
390 {
391 if (error.name === "NotFoundError") {
392 callback(null);
393 return;
394 }
395
396 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(erro r);
397 console.error(errorMessage + " when getting content for file '" + (t his._path + "/" + path) + "'");
398 callback(null);
399 }
400 },
401
402 /**
403 * @param {string} path
404 * @param {string} content
405 * @param {function()} callback
406 */
407 setFileContent: function(path, content, callback)
408 {
409 WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Action.Fil eSavedInWorkspace);
410 this._domFileSystem.root.getFile(path, { create: true }, fileEntryLoaded .bind(this), errorHandler.bind(this));
411
412 /**
413 * @param {!FileEntry} entry
414 * @this {WebInspector.IsolatedFileSystem}
415 */
416 function fileEntryLoaded(entry)
417 {
418 entry.createWriter(fileWriterCreated.bind(this), errorHandler.bind(t his));
419 }
420
421 /**
422 * @param {!FileWriter} fileWriter
423 * @this {WebInspector.IsolatedFileSystem}
424 */
425 function fileWriterCreated(fileWriter)
426 {
427 fileWriter.onerror = errorHandler.bind(this);
428 fileWriter.onwriteend = fileWritten;
429 var blob = new Blob([content], { type: "text/plain" });
430 fileWriter.write(blob);
431
432 function fileWritten()
433 {
434 fileWriter.onwriteend = callback;
435 fileWriter.truncate(blob.size);
436 }
437 }
438
439 /**
440 * @this {WebInspector.IsolatedFileSystem}
441 */
442 function errorHandler(error)
443 {
444 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(erro r);
445 console.error(errorMessage + " when setting content for file '" + (t his._path + "/" + path) + "'");
446 callback();
447 }
448 },
449
450 /**
451 * @param {string} path
452 * @param {string} newName
453 * @param {function(boolean, string=)} callback
454 */
455 renameFile: function(path, newName, callback)
456 {
457 newName = newName ? newName.trim() : newName;
458 if (!newName || newName.indexOf("/") !== -1) {
459 callback(false);
460 return;
461 }
462 var fileEntry;
463 var dirEntry;
464
465 this._domFileSystem.root.getFile(path, null, fileEntryLoaded.bind(this), errorHandler.bind(this));
466
467 /**
468 * @param {!FileEntry} entry
469 * @this {WebInspector.IsolatedFileSystem}
470 */
471 function fileEntryLoaded(entry)
472 {
473 if (entry.name === newName) {
474 callback(false);
475 return;
476 }
477
478 fileEntry = entry;
479 fileEntry.getParent(dirEntryLoaded.bind(this), errorHandler.bind(thi s));
480 }
481
482 /**
483 * @param {!Entry} entry
484 * @this {WebInspector.IsolatedFileSystem}
485 */
486 function dirEntryLoaded(entry)
487 {
488 dirEntry = entry;
489 dirEntry.getFile(newName, null, newFileEntryLoaded, newFileEntryLoad ErrorHandler.bind(this));
490 }
491
492 /**
493 * @param {!FileEntry} entry
494 */
495 function newFileEntryLoaded(entry)
496 {
497 callback(false);
498 }
499
500 /**
501 * @this {WebInspector.IsolatedFileSystem}
502 */
503 function newFileEntryLoadErrorHandler(error)
504 {
505 if (error.name !== "NotFoundError") {
506 callback(false);
507 return;
508 }
509 fileEntry.moveTo(dirEntry, newName, fileRenamed, errorHandler.bind(t his));
510 }
511
512 /**
513 * @param {!FileEntry} entry
514 */
515 function fileRenamed(entry)
516 {
517 callback(true, entry.name);
518 }
519
520 /**
521 * @this {WebInspector.IsolatedFileSystem}
522 */
523 function errorHandler(error)
524 {
525 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(erro r);
526 console.error(errorMessage + " when renaming file '" + (this._path + "/" + path) + "' to '" + newName + "'");
527 callback(false);
528 }
529 },
530
531 /**
532 * @param {!DirectoryEntry} dirEntry
533 * @param {function(!Array.<!FileEntry>)} callback
534 */
535 _readDirectory: function(dirEntry, callback)
536 {
537 var dirReader = dirEntry.createReader();
538 var entries = [];
539
540 function innerCallback(results)
541 {
542 if (!results.length) {
543 callback(entries.sort());
544 } else {
545 entries = entries.concat(toArray(results));
546 dirReader.readEntries(innerCallback, errorHandler);
547 }
548 }
549
550 function toArray(list)
551 {
552 return Array.prototype.slice.call(list || [], 0);
553 }
554
555 dirReader.readEntries(innerCallback, errorHandler);
556
557 function errorHandler(error)
558 {
559 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(erro r);
560 console.error(errorMessage + " when reading directory '" + dirEntry. fullPath + "'");
561 callback([]);
562 }
563 },
564
565 /**
566 * @param {string} path
567 * @param {function(!Array.<!FileEntry>)} callback
568 */
569 _requestEntries: function(path, callback)
570 {
571 this._domFileSystem.root.getDirectory(path, null, innerCallback.bind(thi s), errorHandler);
572
573 /**
574 * @param {!DirectoryEntry} dirEntry
575 * @this {WebInspector.IsolatedFileSystem}
576 */
577 function innerCallback(dirEntry)
578 {
579 this._readDirectory(dirEntry, callback);
580 }
581
582 function errorHandler(error)
583 {
584 var errorMessage = WebInspector.IsolatedFileSystem.errorMessage(erro r);
585 console.error(errorMessage + " when requesting entry '" + path + "'" );
586 callback([]);
587 }
588 },
589
590 _saveExcludedFolders: function()
591 {
592 var settingValue = this._excludedFoldersSetting.get();
593 settingValue[this._path] = this._excludedFolders.valuesArray();
594 this._excludedFoldersSetting.set(settingValue);
595 },
596
597 /**
598 * @param {string} path
599 */
600 addExcludedFolder: function(path)
601 {
602 this._excludedFolders.add(path);
603 this._saveExcludedFolders();
604 this._manager.dispatchEventToListeners(WebInspector.IsolatedFileSystemMa nager.Events.ExcludedFolderAdded, path);
605 },
606
607 /**
608 * @param {string} path
609 */
610 removeExcludedFolder: function(path)
611 {
612 this._excludedFolders.delete(path);
613 this._saveExcludedFolders();
614 this._manager.dispatchEventToListeners(WebInspector.IsolatedFileSystemMa nager.Events.ExcludedFolderRemoved, path);
615 },
616
617 fileSystemRemoved: function()
618 {
619 var settingValue = this._excludedFoldersSetting.get();
620 delete settingValue[this._path];
621 this._excludedFoldersSetting.set(settingValue);
622 },
623
624 /**
625 * @param {string} folderPath
626 * @return {boolean}
627 */
628 _isFileExcluded: function(folderPath)
629 {
630 if (this._nonConfigurableExcludedFolders.has(folderPath) || this._exclud edFolders.has(folderPath))
631 return true;
632 var regex = this._manager.workspaceFolderExcludePatternSetting().asRegEx p();
633 return !!(regex && regex.test(folderPath));
634 },
635
636 /**
637 * @return {!Set<string>}
638 */
639 excludedFolders: function()
640 {
641 return this._excludedFolders;
642 },
643
644 /**
645 * @return {!Set<string>}
646 */
647 nonConfigurableExcludedFolders: function()
648 {
649 return this._nonConfigurableExcludedFolders;
650 },
651
652 /**
653 * @param {string} query
654 * @param {!WebInspector.Progress} progress
655 * @param {function(!Array.<string>)} callback
656 */
657 searchInPath: function(query, progress, callback)
658 {
659 var requestId = this._manager.registerCallback(innerCallback);
660 InspectorFrontendHost.searchInPath(requestId, this._embedderPath, query) ;
661
662 /**
663 * @param {!Array.<string>} files
664 */
665 function innerCallback(files)
666 {
667 files = files.map(embedderPath => WebInspector.ParsedURL.platformPat hToURL(embedderPath));
668 progress.worked(1);
669 callback(files);
670 }
671 },
672
673 /**
674 * @param {!WebInspector.Progress} progress
675 */
676 indexContent: function(progress)
677 {
678 progress.setTotalWork(1);
679 var requestId = this._manager.registerProgress(progress);
680 InspectorFrontendHost.indexPath(requestId, this._embedderPath);
681 }
682 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698