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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/bindings/FileSystemWorkspaceBinding.js

Issue 2515583002: DevTools: move FileSystemWorkspaceBinding under persistence/ (Closed)
Patch Set: rebaseline 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
(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 * @unrestricted
33 */
34 Bindings.FileSystemWorkspaceBinding = class {
35 /**
36 * @param {!Workspace.IsolatedFileSystemManager} isolatedFileSystemManager
37 * @param {!Workspace.Workspace} workspace
38 */
39 constructor(isolatedFileSystemManager, workspace) {
40 this._isolatedFileSystemManager = isolatedFileSystemManager;
41 this._workspace = workspace;
42 this._eventListeners = [
43 this._isolatedFileSystemManager.addEventListener(
44 Workspace.IsolatedFileSystemManager.Events.FileSystemAdded, this._onFi leSystemAdded, this),
45 this._isolatedFileSystemManager.addEventListener(
46 Workspace.IsolatedFileSystemManager.Events.FileSystemRemoved, this._on FileSystemRemoved, this),
47 this._isolatedFileSystemManager.addEventListener(
48 Workspace.IsolatedFileSystemManager.Events.FileSystemFilesChanged, thi s._fileSystemFilesChanged, this)
49 ];
50 /** @type {!Map.<string, !Bindings.FileSystemWorkspaceBinding.FileSystem>} * /
51 this._boundFileSystems = new Map();
52 this._isolatedFileSystemManager.waitForFileSystems().then(this._onFileSystem sLoaded.bind(this));
53 }
54
55 /**
56 * @param {string} fileSystemPath
57 * @return {string}
58 */
59 static projectId(fileSystemPath) {
60 return fileSystemPath;
61 }
62
63 /**
64 * @param {!Workspace.UISourceCode} uiSourceCode
65 * @return {!Array<string>}
66 */
67 static relativePath(uiSourceCode) {
68 var baseURL =
69 /** @type {!Bindings.FileSystemWorkspaceBinding.FileSystem}*/ (uiSourceC ode.project())._fileSystemBaseURL;
70 return uiSourceCode.url().substring(baseURL.length).split('/');
71 }
72
73 /**
74 * @param {!Workspace.Project} project
75 * @param {string} relativePath
76 * @return {string}
77 */
78 static completeURL(project, relativePath) {
79 var fsProject = /** @type {!Bindings.FileSystemWorkspaceBinding.FileSystem}* / (project);
80 return fsProject._fileSystemBaseURL + relativePath;
81 }
82
83 /**
84 * @param {string} extension
85 * @return {!Common.ResourceType}
86 */
87 static _contentTypeForExtension(extension) {
88 if (Bindings.FileSystemWorkspaceBinding._styleSheetExtensions.has(extension) )
89 return Common.resourceTypes.Stylesheet;
90 if (Bindings.FileSystemWorkspaceBinding._documentExtensions.has(extension))
91 return Common.resourceTypes.Document;
92 if (Bindings.FileSystemWorkspaceBinding._imageExtensions.has(extension))
93 return Common.resourceTypes.Image;
94 if (Bindings.FileSystemWorkspaceBinding._scriptExtensions.has(extension))
95 return Common.resourceTypes.Script;
96 return Common.resourceTypes.Other;
97 }
98
99 /**
100 * @param {string} projectId
101 * @return {string}
102 */
103 static fileSystemPath(projectId) {
104 return projectId;
105 }
106
107 /**
108 * @return {!Workspace.IsolatedFileSystemManager}
109 */
110 fileSystemManager() {
111 return this._isolatedFileSystemManager;
112 }
113
114 /**
115 * @param {!Array<!Workspace.IsolatedFileSystem>} fileSystems
116 */
117 _onFileSystemsLoaded(fileSystems) {
118 for (var fileSystem of fileSystems)
119 this._addFileSystem(fileSystem);
120 }
121
122 /**
123 * @param {!Common.Event} event
124 */
125 _onFileSystemAdded(event) {
126 var fileSystem = /** @type {!Workspace.IsolatedFileSystem} */ (event.data);
127 this._addFileSystem(fileSystem);
128 }
129
130 /**
131 * @param {!Workspace.IsolatedFileSystem} fileSystem
132 */
133 _addFileSystem(fileSystem) {
134 var boundFileSystem = new Bindings.FileSystemWorkspaceBinding.FileSystem(thi s, fileSystem, this._workspace);
135 this._boundFileSystems.set(fileSystem.path(), boundFileSystem);
136 }
137
138 /**
139 * @param {!Common.Event} event
140 */
141 _onFileSystemRemoved(event) {
142 var fileSystem = /** @type {!Workspace.IsolatedFileSystem} */ (event.data);
143 var boundFileSystem = this._boundFileSystems.get(fileSystem.path());
144 boundFileSystem.dispose();
145 this._boundFileSystems.remove(fileSystem.path());
146 }
147
148 /**
149 * @param {!Common.Event} event
150 */
151 _fileSystemFilesChanged(event) {
152 var paths = /** @type {!Array<string>} */ (event.data);
153 for (var path of paths) {
154 for (var key of this._boundFileSystems.keys()) {
155 if (!path.startsWith(key))
156 continue;
157 this._boundFileSystems.get(key)._fileChanged(path);
158 }
159 }
160 }
161
162 dispose() {
163 Common.EventTarget.removeEventListeners(this._eventListeners);
164 for (var fileSystem of this._boundFileSystems.values()) {
165 fileSystem.dispose();
166 this._boundFileSystems.remove(fileSystem._fileSystem.path());
167 }
168 }
169 };
170
171 Bindings.FileSystemWorkspaceBinding._styleSheetExtensions = new Set(['css', 'scs s', 'sass', 'less']);
172 Bindings.FileSystemWorkspaceBinding._documentExtensions = new Set(['htm', 'html' , 'asp', 'aspx', 'phtml', 'jsp']);
173 Bindings.FileSystemWorkspaceBinding._scriptExtensions = new Set([
174 'asp', 'aspx', 'c', 'cc', 'cljs', 'coffee', 'cpp', 'cs', 'dart', 'java', 'js',
175 'jsp', 'jsx', 'h', 'm', 'mm', 'py', 'sh', 'ts', 'tsx', 'ls'
176 ]);
177
178 Bindings.FileSystemWorkspaceBinding._imageExtensions = Workspace.IsolatedFileSys tem.ImageExtensions;
179
180
181 /**
182 * @implements {Workspace.Project}
183 * @unrestricted
184 */
185 Bindings.FileSystemWorkspaceBinding.FileSystem = class extends Workspace.Project Store {
186 /**
187 * @param {!Bindings.FileSystemWorkspaceBinding} fileSystemWorkspaceBinding
188 * @param {!Workspace.IsolatedFileSystem} isolatedFileSystem
189 * @param {!Workspace.Workspace} workspace
190 */
191 constructor(fileSystemWorkspaceBinding, isolatedFileSystem, workspace) {
192 var fileSystemPath = isolatedFileSystem.path();
193 var id = Bindings.FileSystemWorkspaceBinding.projectId(fileSystemPath);
194 console.assert(!workspace.project(id));
195 var displayName = fileSystemPath.substr(fileSystemPath.lastIndexOf('/') + 1) ;
196
197 super(workspace, id, Workspace.projectTypes.FileSystem, displayName);
198
199 this._fileSystem = isolatedFileSystem;
200 this._fileSystemBaseURL = this._fileSystem.path() + '/';
201 this._fileSystemWorkspaceBinding = fileSystemWorkspaceBinding;
202 this._fileSystemPath = fileSystemPath;
203
204 workspace.addProject(this);
205 this.populate();
206 }
207
208 /**
209 * @return {string}
210 */
211 fileSystemPath() {
212 return this._fileSystemPath;
213 }
214
215 /**
216 * @return {!Array<string>}
217 */
218 gitFolders() {
219 return this._fileSystem.gitFolders().map(folder => this._fileSystemPath + '/ ' + folder);
220 }
221
222 /**
223 * @param {!Workspace.UISourceCode} uiSourceCode
224 * @return {string}
225 */
226 _filePathForUISourceCode(uiSourceCode) {
227 return uiSourceCode.url().substring(this._fileSystemPath.length);
228 }
229
230 /**
231 * @override
232 * @param {!Workspace.UISourceCode} uiSourceCode
233 * @return {!Promise<?Workspace.UISourceCodeMetadata>}
234 */
235 requestMetadata(uiSourceCode) {
236 if (uiSourceCode[Bindings.FileSystemWorkspaceBinding._metadata])
237 return uiSourceCode[Bindings.FileSystemWorkspaceBinding._metadata];
238 var relativePath = this._filePathForUISourceCode(uiSourceCode);
239 var promise = this._fileSystem.getMetadata(relativePath).then(onMetadata);
240 uiSourceCode[Bindings.FileSystemWorkspaceBinding._metadata] = promise;
241 return promise;
242
243 /**
244 * @param {?{modificationTime: !Date, size: number}} metadata
245 * @return {?Workspace.UISourceCodeMetadata}
246 */
247 function onMetadata(metadata) {
248 if (!metadata)
249 return null;
250 return new Workspace.UISourceCodeMetadata(metadata.modificationTime, metad ata.size);
251 }
252 }
253
254 /**
255 * @override
256 * @param {!Workspace.UISourceCode} uiSourceCode
257 * @param {function(?string)} callback
258 */
259 requestFileContent(uiSourceCode, callback) {
260 var filePath = this._filePathForUISourceCode(uiSourceCode);
261 var isImage = Bindings.FileSystemWorkspaceBinding._imageExtensions.has(Commo n.ParsedURL.extractExtension(filePath));
262
263 this._fileSystem.requestFileContent(filePath, isImage ? base64CallbackWrappe r : callback);
264
265 /**
266 * @param {?string} result
267 */
268 function base64CallbackWrapper(result) {
269 if (!result) {
270 callback(result);
271 return;
272 }
273 var index = result.indexOf(',');
274 callback(result.substring(index + 1));
275 }
276 }
277
278 /**
279 * @override
280 * @return {boolean}
281 */
282 canSetFileContent() {
283 return true;
284 }
285
286 /**
287 * @override
288 * @param {!Workspace.UISourceCode} uiSourceCode
289 * @param {string} newContent
290 * @param {function(?string)} callback
291 */
292 setFileContent(uiSourceCode, newContent, callback) {
293 var filePath = this._filePathForUISourceCode(uiSourceCode);
294 this._fileSystem.setFileContent(filePath, newContent, callback.bind(this, '' ));
295 }
296
297 /**
298 * @override
299 * @return {boolean}
300 */
301 canRename() {
302 return true;
303 }
304
305 /**
306 * @override
307 * @param {!Workspace.UISourceCode} uiSourceCode
308 * @param {string} newName
309 * @param {function(boolean, string=, string=, !Common.ResourceType=)} callbac k
310 */
311 rename(uiSourceCode, newName, callback) {
312 if (newName === uiSourceCode.name()) {
313 callback(true, uiSourceCode.name(), uiSourceCode.url(), uiSourceCode.conte ntType());
314 return;
315 }
316
317 var filePath = this._filePathForUISourceCode(uiSourceCode);
318 this._fileSystem.renameFile(filePath, newName, innerCallback.bind(this));
319
320 /**
321 * @param {boolean} success
322 * @param {string=} newName
323 * @this {Bindings.FileSystemWorkspaceBinding.FileSystem}
324 */
325 function innerCallback(success, newName) {
326 if (!success || !newName) {
327 callback(false, newName);
328 return;
329 }
330 console.assert(newName);
331 var slash = filePath.lastIndexOf('/');
332 var parentPath = filePath.substring(0, slash);
333 filePath = parentPath + '/' + newName;
334 filePath = filePath.substr(1);
335 var extension = this._extensionForPath(newName);
336 var newURL = this._fileSystemBaseURL + filePath;
337 var newContentType = Bindings.FileSystemWorkspaceBinding._contentTypeForEx tension(extension);
338 this.renameUISourceCode(uiSourceCode, newName);
339 callback(true, newName, newURL, newContentType);
340 }
341 }
342
343 /**
344 * @override
345 * @param {!Workspace.UISourceCode} uiSourceCode
346 * @param {string} query
347 * @param {boolean} caseSensitive
348 * @param {boolean} isRegex
349 * @param {function(!Array.<!Common.ContentProvider.SearchMatch>)} callback
350 */
351 searchInFileContent(uiSourceCode, query, caseSensitive, isRegex, callback) {
352 var filePath = this._filePathForUISourceCode(uiSourceCode);
353 this._fileSystem.requestFileContent(filePath, contentCallback);
354
355 /**
356 * @param {?string} content
357 */
358 function contentCallback(content) {
359 var result = [];
360 if (content !== null)
361 result = Common.ContentProvider.performSearchInContent(content, query, c aseSensitive, isRegex);
362 callback(result);
363 }
364 }
365
366 /**
367 * @override
368 * @param {!Workspace.ProjectSearchConfig} searchConfig
369 * @param {!Array.<string>} filesMathingFileQuery
370 * @param {!Common.Progress} progress
371 * @param {function(!Array.<string>)} callback
372 */
373 findFilesMatchingSearchRequest(searchConfig, filesMathingFileQuery, progress, callback) {
374 var result = filesMathingFileQuery;
375 var queriesToRun = searchConfig.queries().slice();
376 if (!queriesToRun.length)
377 queriesToRun.push('');
378 progress.setTotalWork(queriesToRun.length);
379 searchNextQuery.call(this);
380
381 /**
382 * @this {Bindings.FileSystemWorkspaceBinding.FileSystem}
383 */
384 function searchNextQuery() {
385 if (!queriesToRun.length) {
386 progress.done();
387 callback(result);
388 return;
389 }
390 var query = queriesToRun.shift();
391 this._fileSystem.searchInPath(searchConfig.isRegex() ? '' : query, progres s, innerCallback.bind(this));
392 }
393
394 /**
395 * @param {!Array.<string>} files
396 * @this {Bindings.FileSystemWorkspaceBinding.FileSystem}
397 */
398 function innerCallback(files) {
399 files = files.sort();
400 progress.worked(1);
401 result = result.intersectOrdered(files, String.naturalOrderComparator);
402 searchNextQuery.call(this);
403 }
404 }
405
406 /**
407 * @override
408 * @param {!Common.Progress} progress
409 */
410 indexContent(progress) {
411 this._fileSystem.indexContent(progress);
412 }
413
414 /**
415 * @param {string} path
416 * @return {string}
417 */
418 _extensionForPath(path) {
419 var extensionIndex = path.lastIndexOf('.');
420 if (extensionIndex === -1)
421 return '';
422 return path.substring(extensionIndex + 1).toLowerCase();
423 }
424
425 populate() {
426 var chunkSize = 1000;
427 var filePaths = this._fileSystem.filePaths();
428 reportFileChunk.call(this, 0);
429
430 /**
431 * @param {number} from
432 * @this {Bindings.FileSystemWorkspaceBinding.FileSystem}
433 */
434 function reportFileChunk(from) {
435 var to = Math.min(from + chunkSize, filePaths.length);
436 for (var i = from; i < to; ++i)
437 this._addFile(filePaths[i]);
438 if (to < filePaths.length)
439 setTimeout(reportFileChunk.bind(this, to), 100);
440 }
441 }
442
443 /**
444 * @override
445 * @param {string} url
446 */
447 excludeFolder(url) {
448 var relativeFolder = url.substring(this._fileSystemBaseURL.length);
449 if (!relativeFolder.startsWith('/'))
450 relativeFolder = '/' + relativeFolder;
451 if (!relativeFolder.endsWith('/'))
452 relativeFolder += '/';
453 this._fileSystem.addExcludedFolder(relativeFolder);
454
455 var uiSourceCodes = this.uiSourceCodes().slice();
456 for (var i = 0; i < uiSourceCodes.length; ++i) {
457 var uiSourceCode = uiSourceCodes[i];
458 if (uiSourceCode.url().startsWith(url))
459 this.removeUISourceCode(uiSourceCode.url());
460 }
461 }
462
463 /**
464 * @override
465 * @param {string} path
466 * @param {?string} name
467 * @param {string} content
468 * @param {function(?Workspace.UISourceCode)} callback
469 */
470 createFile(path, name, content, callback) {
471 this._fileSystem.createFile(path, name, innerCallback.bind(this));
472 var createFilePath;
473
474 /**
475 * @param {?string} filePath
476 * @this {Bindings.FileSystemWorkspaceBinding.FileSystem}
477 */
478 function innerCallback(filePath) {
479 if (!filePath) {
480 callback(null);
481 return;
482 }
483 createFilePath = filePath;
484 if (!content) {
485 contentSet.call(this);
486 return;
487 }
488 this._fileSystem.setFileContent(filePath, content, contentSet.bind(this));
489 }
490
491 /**
492 * @this {Bindings.FileSystemWorkspaceBinding.FileSystem}
493 */
494 function contentSet() {
495 callback(this._addFile(createFilePath));
496 }
497 }
498
499 /**
500 * @override
501 * @param {string} path
502 */
503 deleteFile(path) {
504 this._fileSystem.deleteFile(path);
505 this.removeUISourceCode(path);
506 }
507
508 /**
509 * @override
510 */
511 remove() {
512 this._fileSystemWorkspaceBinding._isolatedFileSystemManager.removeFileSystem (this._fileSystem);
513 }
514
515 /**
516 * @param {string} filePath
517 * @return {!Workspace.UISourceCode}
518 */
519 _addFile(filePath) {
520 var extension = this._extensionForPath(filePath);
521 var contentType = Bindings.FileSystemWorkspaceBinding._contentTypeForExtensi on(extension);
522
523 var uiSourceCode = this.createUISourceCode(this._fileSystemBaseURL + filePat h, contentType);
524 this.addUISourceCode(uiSourceCode);
525 return uiSourceCode;
526 }
527
528 /**
529 * @param {string} path
530 */
531 _fileChanged(path) {
532 var uiSourceCode = this.uiSourceCodeForURL(path);
533 if (!uiSourceCode) {
534 var contentType = Bindings.FileSystemWorkspaceBinding._contentTypeForExten sion(this._extensionForPath(path));
535 this.addUISourceCode(this.createUISourceCode(path, contentType));
536 return;
537 }
538 uiSourceCode[Bindings.FileSystemWorkspaceBinding._metadata] = null;
539 uiSourceCode.checkContentUpdated();
540 }
541
542 dispose() {
543 this.removeProject();
544 }
545 };
546
547 Bindings.FileSystemWorkspaceBinding._metadata = Symbol('FileSystemWorkspaceBindi ng.Metadata');
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/devtools/BUILD.gn ('k') | third_party/WebKit/Source/devtools/front_end/bindings/module.json » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698