OLD | NEW |
| (Empty) |
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 /** | |
32 * @constructor | |
33 * @param {!WebInspector.IsolatedFileSystemManager} isolatedFileSystemManager | |
34 * @param {!WebInspector.Workspace} workspace | |
35 */ | |
36 WebInspector.FileSystemWorkspaceBinding = function(isolatedFileSystemManager, wo
rkspace) | |
37 { | |
38 this._isolatedFileSystemManager = isolatedFileSystemManager; | |
39 this._workspace = workspace; | |
40 this._isolatedFileSystemManager.addEventListener(WebInspector.IsolatedFileSy
stemManager.Events.FileSystemAdded, this._fileSystemAdded, this); | |
41 this._isolatedFileSystemManager.addEventListener(WebInspector.IsolatedFileSy
stemManager.Events.FileSystemRemoved, this._fileSystemRemoved, this); | |
42 /** @type {!StringMap.<!WebInspector.FileSystemWorkspaceBinding.FileSystem>}
*/ | |
43 this._boundFileSystems = new StringMap(); | |
44 | |
45 /** @type {!Object.<number, function(!Array.<string>)>} */ | |
46 this._callbacks = {}; | |
47 /** @type {!Object.<number, !WebInspector.Progress>} */ | |
48 this._progresses = {}; | |
49 | |
50 InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Event
s.IndexingTotalWorkCalculated, this._onIndexingTotalWorkCalculated, this); | |
51 InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Event
s.IndexingWorked, this._onIndexingWorked, this); | |
52 InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Event
s.IndexingDone, this._onIndexingDone, this); | |
53 InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Event
s.SearchCompleted, this._onSearchCompleted, this); | |
54 } | |
55 | |
56 WebInspector.FileSystemWorkspaceBinding._scriptExtensions = ["js", "java", "coff
ee", "ts", "dart"].keySet(); | |
57 WebInspector.FileSystemWorkspaceBinding._styleSheetExtensions = ["css", "scss",
"sass", "less"].keySet(); | |
58 WebInspector.FileSystemWorkspaceBinding._documentExtensions = ["htm", "html", "a
sp", "aspx", "phtml", "jsp"].keySet(); | |
59 | |
60 WebInspector.FileSystemWorkspaceBinding._lastRequestId = 0; | |
61 | |
62 /** | |
63 * @param {string} fileSystemPath | |
64 * @return {string} | |
65 */ | |
66 WebInspector.FileSystemWorkspaceBinding.projectId = function(fileSystemPath) | |
67 { | |
68 return "filesystem:" + fileSystemPath; | |
69 } | |
70 | |
71 WebInspector.FileSystemWorkspaceBinding.prototype = { | |
72 /** | |
73 * @param {!WebInspector.Event} event | |
74 */ | |
75 _fileSystemAdded: function(event) | |
76 { | |
77 var fileSystem = /** @type {!WebInspector.IsolatedFileSystem} */ (event.
data); | |
78 var boundFileSystem = new WebInspector.FileSystemWorkspaceBinding.FileSy
stem(this, fileSystem, this._workspace); | |
79 this._boundFileSystems.put(fileSystem.normalizedPath(), boundFileSystem)
; | |
80 }, | |
81 | |
82 /** | |
83 * @param {!WebInspector.Event} event | |
84 */ | |
85 _fileSystemRemoved: function(event) | |
86 { | |
87 var fileSystem = /** @type {!WebInspector.IsolatedFileSystem} */ (event.
data); | |
88 var boundFileSystem = this._boundFileSystems.get(fileSystem.normalizedPa
th()); | |
89 boundFileSystem.dispose(); | |
90 this._boundFileSystems.remove(fileSystem.normalizedPath()); | |
91 }, | |
92 | |
93 /** | |
94 * @param {string} projectId | |
95 * @return {string} | |
96 */ | |
97 fileSystemPath: function(projectId) | |
98 { | |
99 var fileSystemPath = projectId.substr("filesystem:".length); | |
100 var normalizedPath = WebInspector.IsolatedFileSystem.normalizePath(fileS
ystemPath); | |
101 var boundFileSystem = this._boundFileSystems.get(normalizedPath); | |
102 return projectId.substr("filesystem:".length); | |
103 }, | |
104 | |
105 /** | |
106 * @return {number} | |
107 */ | |
108 _nextId: function() | |
109 { | |
110 return ++WebInspector.FileSystemWorkspaceBinding._lastRequestId; | |
111 }, | |
112 | |
113 /** | |
114 * @param {function(!Array.<string>)} callback | |
115 * @return {number} | |
116 */ | |
117 registerCallback: function(callback) | |
118 { | |
119 var requestId = this._nextId(); | |
120 this._callbacks[requestId] = callback; | |
121 return requestId; | |
122 }, | |
123 | |
124 /** | |
125 * @param {!WebInspector.Progress} progress | |
126 * @return {number} | |
127 */ | |
128 registerProgress: function(progress) | |
129 { | |
130 var requestId = this._nextId(); | |
131 this._progresses[requestId] = progress; | |
132 return requestId; | |
133 }, | |
134 | |
135 /** | |
136 * @param {!WebInspector.Event} event | |
137 */ | |
138 _onIndexingTotalWorkCalculated: function(event) | |
139 { | |
140 var requestId = /** @type {number} */ (event.data["requestId"]); | |
141 var fileSystemPath = /** @type {string} */ (event.data["fileSystemPath"]
); | |
142 var totalWork = /** @type {number} */ (event.data["totalWork"]); | |
143 | |
144 var progress = this._progresses[requestId]; | |
145 if (!progress) | |
146 return; | |
147 progress.setTotalWork(totalWork); | |
148 }, | |
149 | |
150 /** | |
151 * @param {!WebInspector.Event} event | |
152 */ | |
153 _onIndexingWorked: function(event) | |
154 { | |
155 var requestId = /** @type {number} */ (event.data["requestId"]); | |
156 var fileSystemPath = /** @type {string} */ (event.data["fileSystemPath"]
); | |
157 var worked = /** @type {number} */ (event.data["worked"]); | |
158 | |
159 var progress = this._progresses[requestId]; | |
160 if (!progress) | |
161 return; | |
162 progress.worked(worked); | |
163 }, | |
164 | |
165 /** | |
166 * @param {!WebInspector.Event} event | |
167 */ | |
168 _onIndexingDone: function(event) | |
169 { | |
170 var requestId = /** @type {number} */ (event.data["requestId"]); | |
171 var fileSystemPath = /** @type {string} */ (event.data["fileSystemPath"]
); | |
172 | |
173 var progress = this._progresses[requestId]; | |
174 if (!progress) | |
175 return; | |
176 progress.done(); | |
177 delete this._progresses[requestId]; | |
178 }, | |
179 | |
180 /** | |
181 * @param {!WebInspector.Event} event | |
182 */ | |
183 _onSearchCompleted: function(event) | |
184 { | |
185 var requestId = /** @type {number} */ (event.data["requestId"]); | |
186 var fileSystemPath = /** @type {string} */ (event.data["fileSystemPath"]
); | |
187 var files = /** @type {!Array.<string>} */ (event.data["files"]); | |
188 | |
189 var callback = this._callbacks[requestId]; | |
190 if (!callback) | |
191 return; | |
192 callback.call(null, files); | |
193 delete this._callbacks[requestId]; | |
194 }, | |
195 } | |
196 | |
197 /** | |
198 * @constructor | |
199 * @implements {WebInspector.ProjectDelegate} | |
200 * @param {!WebInspector.IsolatedFileSystem} isolatedFileSystem | |
201 * @param {!WebInspector.Workspace} workspace | |
202 * @param {!WebInspector.FileSystemWorkspaceBinding} fileSystemWorkspaceBinding | |
203 */ | |
204 WebInspector.FileSystemWorkspaceBinding.FileSystem = function(fileSystemWorkspac
eBinding, isolatedFileSystem, workspace) | |
205 { | |
206 this._fileSystemWorkspaceBinding = fileSystemWorkspaceBinding; | |
207 this._fileSystem = isolatedFileSystem; | |
208 this._fileSystemURL = "file://" + this._fileSystem.normalizedPath() + "/"; | |
209 this._workspace = workspace; | |
210 | |
211 this._projectId = WebInspector.FileSystemWorkspaceBinding.projectId(this._fi
leSystem.path()); | |
212 console.assert(!this._workspace.project(this._projectId)); | |
213 this._projectStore = this._workspace.addProject(this._projectId, this); | |
214 this.populate(); | |
215 } | |
216 | |
217 WebInspector.FileSystemWorkspaceBinding.FileSystem.prototype = { | |
218 /** | |
219 * @return {string} | |
220 */ | |
221 type: function() | |
222 { | |
223 return WebInspector.projectTypes.FileSystem; | |
224 }, | |
225 | |
226 /** | |
227 * @return {string} | |
228 */ | |
229 fileSystemPath: function() | |
230 { | |
231 return this._fileSystem.path(); | |
232 }, | |
233 | |
234 /** | |
235 * @return {string} | |
236 */ | |
237 displayName: function() | |
238 { | |
239 var normalizedPath = this._fileSystem.normalizedPath(); | |
240 return normalizedPath.substr(normalizedPath.lastIndexOf("/") + 1); | |
241 }, | |
242 | |
243 /** | |
244 * @param {string} path | |
245 * @return {string} | |
246 */ | |
247 _filePathForPath: function(path) | |
248 { | |
249 return "/" + path; | |
250 }, | |
251 | |
252 /** | |
253 * @param {string} path | |
254 * @param {function(?string)} callback | |
255 */ | |
256 requestFileContent: function(path, callback) | |
257 { | |
258 var filePath = this._filePathForPath(path); | |
259 this._fileSystem.requestFileContent(filePath, callback); | |
260 }, | |
261 | |
262 /** | |
263 * @param {string} path | |
264 * @param {function(?Date, ?number)} callback | |
265 */ | |
266 requestMetadata: function(path, callback) | |
267 { | |
268 var filePath = this._filePathForPath(path); | |
269 this._fileSystem.requestMetadata(filePath, callback); | |
270 }, | |
271 | |
272 /** | |
273 * @return {boolean} | |
274 */ | |
275 canSetFileContent: function() | |
276 { | |
277 return true; | |
278 }, | |
279 | |
280 /** | |
281 * @param {string} path | |
282 * @param {string} newContent | |
283 * @param {function(?string)} callback | |
284 */ | |
285 setFileContent: function(path, newContent, callback) | |
286 { | |
287 var filePath = this._filePathForPath(path); | |
288 this._fileSystem.setFileContent(filePath, newContent, callback.bind(this
, "")); | |
289 }, | |
290 | |
291 /** | |
292 * @return {boolean} | |
293 */ | |
294 canRename: function() | |
295 { | |
296 return true; | |
297 }, | |
298 | |
299 /** | |
300 * @param {string} path | |
301 * @param {string} newName | |
302 * @param {function(boolean, string=, string=, string=, !WebInspector.Resour
ceType=)} callback | |
303 */ | |
304 rename: function(path, newName, callback) | |
305 { | |
306 var filePath = this._filePathForPath(path); | |
307 this._fileSystem.renameFile(filePath, newName, innerCallback.bind(this))
; | |
308 | |
309 /** | |
310 * @param {boolean} success | |
311 * @param {string=} newName | |
312 * @this {WebInspector.FileSystemWorkspaceBinding.FileSystem} | |
313 */ | |
314 function innerCallback(success, newName) | |
315 { | |
316 if (!success) { | |
317 callback(false, newName); | |
318 return; | |
319 } | |
320 var validNewName = /** @type {string} */ (newName); | |
321 console.assert(validNewName); | |
322 var slash = filePath.lastIndexOf("/"); | |
323 var parentPath = filePath.substring(0, slash); | |
324 filePath = parentPath + "/" + validNewName; | |
325 filePath = filePath.substr(1); | |
326 var newURL = this._workspace.urlForPath(this._fileSystem.path(), fil
ePath); | |
327 var extension = this._extensionForPath(validNewName); | |
328 var newOriginURL = this._fileSystemURL + filePath | |
329 var newContentType = this._contentTypeForExtension(extension); | |
330 callback(true, validNewName, newURL, newOriginURL, newContentType); | |
331 } | |
332 }, | |
333 | |
334 /** | |
335 * @param {string} path | |
336 * @param {string} query | |
337 * @param {boolean} caseSensitive | |
338 * @param {boolean} isRegex | |
339 * @param {function(!Array.<!WebInspector.ContentProvider.SearchMatch>)} cal
lback | |
340 */ | |
341 searchInFileContent: function(path, query, caseSensitive, isRegex, callback) | |
342 { | |
343 var filePath = this._filePathForPath(path); | |
344 this._fileSystem.requestFileContent(filePath, contentCallback); | |
345 | |
346 /** | |
347 * @param {?string} content | |
348 */ | |
349 function contentCallback(content) | |
350 { | |
351 var result = []; | |
352 if (content !== null) | |
353 result = WebInspector.ContentProvider.performSearchInContent(con
tent, query, caseSensitive, isRegex); | |
354 callback(result); | |
355 } | |
356 }, | |
357 | |
358 /** | |
359 * @param {!WebInspector.ProjectSearchConfig} searchConfig | |
360 * @param {!Array.<string>} filesMathingFileQuery | |
361 * @param {!WebInspector.Progress} progress | |
362 * @param {function(!Array.<string>)} callback | |
363 */ | |
364 findFilesMatchingSearchRequest: function(searchConfig, filesMathingFileQuery
, progress, callback) | |
365 { | |
366 var result = filesMathingFileQuery; | |
367 var queriesToRun = searchConfig.queries().slice(); | |
368 if (!queriesToRun.length) | |
369 queriesToRun.push(""); | |
370 progress.setTotalWork(queriesToRun.length); | |
371 searchNextQuery.call(this); | |
372 | |
373 /** | |
374 * @this {WebInspector.FileSystemWorkspaceBinding.FileSystem} | |
375 */ | |
376 function searchNextQuery() | |
377 { | |
378 if (!queriesToRun.length) { | |
379 progress.done(); | |
380 callback(result); | |
381 return; | |
382 } | |
383 var query = queriesToRun.shift(); | |
384 this._searchInPath(searchConfig.isRegex() ? "" : query, progress, in
nerCallback.bind(this)); | |
385 } | |
386 | |
387 /** | |
388 * @param {!Array.<string>} files | |
389 * @this {WebInspector.FileSystemWorkspaceBinding.FileSystem} | |
390 */ | |
391 function innerCallback(files) | |
392 { | |
393 files = files.sort(); | |
394 progress.worked(1); | |
395 result = result.intersectOrdered(files, String.naturalOrderComparato
r); | |
396 searchNextQuery.call(this); | |
397 } | |
398 }, | |
399 | |
400 /** | |
401 * @param {string} query | |
402 * @param {!WebInspector.Progress} progress | |
403 * @param {function(!Array.<string>)} callback | |
404 */ | |
405 _searchInPath: function(query, progress, callback) | |
406 { | |
407 var requestId = this._fileSystemWorkspaceBinding.registerCallback(innerC
allback.bind(this)); | |
408 InspectorFrontendHost.searchInPath(requestId, this._fileSystem.path(), q
uery); | |
409 | |
410 /** | |
411 * @param {!Array.<string>} files | |
412 * @this {WebInspector.FileSystemWorkspaceBinding.FileSystem} | |
413 */ | |
414 function innerCallback(files) | |
415 { | |
416 /** | |
417 * @param {string} fullPath | |
418 * @this {WebInspector.FileSystemWorkspaceBinding.FileSystem} | |
419 */ | |
420 function trimAndNormalizeFileSystemPath(fullPath) | |
421 { | |
422 var trimmedPath = fullPath.substr(this._fileSystem.path().length
+ 1); | |
423 if (WebInspector.isWin()) | |
424 trimmedPath = trimmedPath.replace(/\\/g, "/"); | |
425 return trimmedPath; | |
426 } | |
427 | |
428 files = files.map(trimAndNormalizeFileSystemPath.bind(this)); | |
429 progress.worked(1); | |
430 callback(files); | |
431 } | |
432 }, | |
433 | |
434 /** | |
435 * @param {!WebInspector.Progress} progress | |
436 */ | |
437 indexContent: function(progress) | |
438 { | |
439 progress.setTotalWork(1); | |
440 var requestId = this._fileSystemWorkspaceBinding.registerProgress(progre
ss); | |
441 progress.addEventListener(WebInspector.Progress.Events.Canceled, this._i
ndexingCanceled.bind(this, requestId)); | |
442 InspectorFrontendHost.indexPath(requestId, this._fileSystem.path()); | |
443 }, | |
444 | |
445 /** | |
446 * @param {number} requestId | |
447 */ | |
448 _indexingCanceled: function(requestId) | |
449 { | |
450 InspectorFrontendHost.stopIndexing(requestId); | |
451 }, | |
452 | |
453 /** | |
454 * @param {string} path | |
455 * @return {string} | |
456 */ | |
457 _extensionForPath: function(path) | |
458 { | |
459 var extensionIndex = path.lastIndexOf("."); | |
460 if (extensionIndex === -1) | |
461 return ""; | |
462 return path.substring(extensionIndex + 1).toLowerCase(); | |
463 }, | |
464 | |
465 /** | |
466 * @param {string} extension | |
467 * @return {!WebInspector.ResourceType} | |
468 */ | |
469 _contentTypeForExtension: function(extension) | |
470 { | |
471 if (WebInspector.FileSystemWorkspaceBinding._scriptExtensions[extension]
) | |
472 return WebInspector.resourceTypes.Script; | |
473 if (WebInspector.FileSystemWorkspaceBinding._styleSheetExtensions[extens
ion]) | |
474 return WebInspector.resourceTypes.Stylesheet; | |
475 if (WebInspector.FileSystemWorkspaceBinding._documentExtensions[extensio
n]) | |
476 return WebInspector.resourceTypes.Document; | |
477 return WebInspector.resourceTypes.Other; | |
478 }, | |
479 | |
480 populate: function() | |
481 { | |
482 this._fileSystem.requestFilesRecursive("", this._addFile.bind(this)); | |
483 }, | |
484 | |
485 /** | |
486 * @param {string} path | |
487 * @param {function()=} callback | |
488 */ | |
489 refresh: function(path, callback) | |
490 { | |
491 this._fileSystem.requestFilesRecursive(path, this._addFile.bind(this), c
allback); | |
492 }, | |
493 | |
494 /** | |
495 * @param {string} path | |
496 */ | |
497 excludeFolder: function(path) | |
498 { | |
499 this._fileSystemWorkspaceBinding._isolatedFileSystemManager.mapping().ad
dExcludedFolder(this._fileSystem.path(), path); | |
500 }, | |
501 | |
502 /** | |
503 * @param {string} path | |
504 * @param {?string} name | |
505 * @param {string} content | |
506 * @param {function(?string)} callback | |
507 */ | |
508 createFile: function(path, name, content, callback) | |
509 { | |
510 this._fileSystem.createFile(path, name, innerCallback.bind(this)); | |
511 var createFilePath; | |
512 | |
513 /** | |
514 * @param {?string} filePath | |
515 * @this {WebInspector.FileSystemWorkspaceBinding.FileSystem} | |
516 */ | |
517 function innerCallback(filePath) | |
518 { | |
519 if (!filePath) { | |
520 callback(null); | |
521 return; | |
522 } | |
523 createFilePath = filePath; | |
524 if (!content) { | |
525 contentSet.call(this); | |
526 return; | |
527 } | |
528 this._fileSystem.setFileContent(filePath, content, contentSet.bind(t
his)); | |
529 } | |
530 | |
531 /** | |
532 * @this {WebInspector.FileSystemWorkspaceBinding.FileSystem} | |
533 */ | |
534 function contentSet() | |
535 { | |
536 this._addFile(createFilePath); | |
537 callback(createFilePath); | |
538 } | |
539 }, | |
540 | |
541 /** | |
542 * @param {string} path | |
543 */ | |
544 deleteFile: function(path) | |
545 { | |
546 this._fileSystem.deleteFile(path); | |
547 this._removeFile(path); | |
548 }, | |
549 | |
550 remove: function() | |
551 { | |
552 this._fileSystemWorkspaceBinding._isolatedFileSystemManager.removeFileSy
stem(this._fileSystem.path()); | |
553 }, | |
554 | |
555 /** | |
556 * @param {string} filePath | |
557 */ | |
558 _addFile: function(filePath) | |
559 { | |
560 if (!filePath) | |
561 console.assert(false); | |
562 | |
563 var slash = filePath.lastIndexOf("/"); | |
564 var parentPath = filePath.substring(0, slash); | |
565 var name = filePath.substring(slash + 1); | |
566 | |
567 var url = this._workspace.urlForPath(this._fileSystem.path(), filePath); | |
568 var extension = this._extensionForPath(name); | |
569 var contentType = this._contentTypeForExtension(extension); | |
570 | |
571 var fileDescriptor = new WebInspector.FileDescriptor(parentPath, name, t
his._fileSystemURL + filePath, url, contentType); | |
572 this._projectStore.addFile(fileDescriptor); | |
573 }, | |
574 | |
575 /** | |
576 * @param {string} path | |
577 */ | |
578 _removeFile: function(path) | |
579 { | |
580 this._projectStore.removeFile(path); | |
581 }, | |
582 | |
583 dispose: function() | |
584 { | |
585 this._workspace.removeProject(this._projectId); | |
586 } | |
587 } | |
588 | |
589 /** | |
590 * @type {!WebInspector.FileSystemWorkspaceBinding} | |
591 */ | |
592 WebInspector.fileSystemWorkspaceBinding; | |
OLD | NEW |