OLD | NEW |
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 }; | |
OLD | NEW |