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 * @extends {WebInspector.DialogDelegate} 34 * @param {string} fileSystemPath 35 */ 36WebInspector.EditFileSystemDialog = function(fileSystemPath) 37{ 38 WebInspector.DialogDelegate.call(this); 39 this._fileSystemPath = fileSystemPath; 40 41 this.element = document.createElement("div"); 42 this.element.className = "edit-file-system-dialog"; 43 44 var header = this.element.createChild("div", "header"); 45 var headerText = header.createChild("span"); 46 headerText.textContent = "Edit file system"; 47 48 var closeButton = header.createChild("div", "close-button-gray done-button"); 49 closeButton.addEventListener("click", this._onDoneClick.bind(this), false); 50 51 var contents = this.element.createChild("div", "contents"); 52 53 WebInspector.isolatedFileSystemManager.mapping().addEventListener(WebInspector.FileSystemMapping.Events.FileMappingAdded, this._fileMappingAdded, this); 54 WebInspector.isolatedFileSystemManager.mapping().addEventListener(WebInspector.FileSystemMapping.Events.FileMappingRemoved, this._fileMappingRemoved, this); 55 WebInspector.isolatedFileSystemManager.mapping().addEventListener(WebInspector.FileSystemMapping.Events.ExcludedFolderAdded, this._excludedFolderAdded, this); 56 WebInspector.isolatedFileSystemManager.mapping().addEventListener(WebInspector.FileSystemMapping.Events.ExcludedFolderRemoved, this._excludedFolderRemoved, this); 57 58 var blockHeader = contents.createChild("div", "block-header"); 59 blockHeader.textContent = "Mappings"; 60 this._fileMappingsSection = contents.createChild("div", "file-mappings-section"); 61 this._fileMappingsListContainer = this._fileMappingsSection.createChild("div", "settings-list-container"); 62 var entries = WebInspector.isolatedFileSystemManager.mapping().mappingEntries(this._fileSystemPath); 63 64 this._fileMappingsList = new WebInspector.EditableSettingsList(["url", "path"], this._fileMappingValuesProvider.bind(this), this._fileMappingValidate.bind(this), this._fileMappingEdit.bind(this)); 65 this._fileMappingsList.addEventListener(WebInspector.SettingsList.Events.Removed, this._fileMappingRemovedfromList.bind(this)); 66 67 this._fileMappingsList.element.classList.add("file-mappings-list"); 68 this._fileMappingsListContainer.appendChild(this._fileMappingsList.element); 69 70 this._entries = {}; 71 for (var i = 0; i < entries.length; ++i) 72 this._addMappingRow(entries[i]); 73 74 blockHeader = contents.createChild("div", "block-header"); 75 blockHeader.textContent = "Excluded folders"; 76 this._excludedFolderListSection = contents.createChild("div", "excluded-folders-section"); 77 this._excludedFolderListContainer = this._excludedFolderListSection.createChild("div", "settings-list-container"); 78 var excludedFolderEntries = WebInspector.isolatedFileSystemManager.mapping().excludedFolders(fileSystemPath); 79 80 this._excludedFolderList = new WebInspector.EditableSettingsList(["path"], this._excludedFolderValueProvider.bind(this), this._excludedFolderValidate.bind(this), this._excludedFolderEdit.bind(this)); 81 this._excludedFolderList.addEventListener(WebInspector.SettingsList.Events.Removed, this._excludedFolderRemovedfromList.bind(this)); 82 this._excludedFolderList.element.classList.add("excluded-folders-list"); 83 this._excludedFolderListContainer.appendChild(this._excludedFolderList.element); 84 this._excludedFolderEntries = new StringMap(); 85 for (var i = 0; i < excludedFolderEntries.length; ++i) 86 this._addExcludedFolderRow(excludedFolderEntries[i]); 87 88 this.element.tabIndex = 0; 89} 90 91WebInspector.EditFileSystemDialog.show = function(element, fileSystemPath) 92{ 93 WebInspector.Dialog.show(element, new WebInspector.EditFileSystemDialog(fileSystemPath)); 94 var glassPane = document.getElementById("glass-pane"); 95 glassPane.classList.add("settings-glass-pane"); 96} 97 98WebInspector.EditFileSystemDialog.prototype = { 99 /** 100 * @param {!Element} element 101 */ 102 show: function(element) 103 { 104 element.appendChild(this.element); 105 this.element.classList.add("dialog-contents"); 106 element.classList.add("settings-dialog"); 107 element.classList.add("settings-tab"); 108 this._dialogElement = element; 109 }, 110 111 _resize: function() 112 { 113 if (!this._dialogElement) 114 return; 115 116 const width = 540; 117 const minHeight = 150; 118 var maxHeight = document.body.offsetHeight - 10; 119 maxHeight = Math.max(minHeight, maxHeight); 120 this._dialogElement.style.maxHeight = maxHeight + "px"; 121 this._dialogElement.style.width = width + "px"; 122 }, 123 124 /** 125 * @param {!Element} element 126 * @param {!Element} relativeToElement 127 */ 128 position: function(element, relativeToElement) 129 { 130 this._resize(); 131 }, 132 133 willHide: function(event) 134 { 135 }, 136 137 _fileMappingAdded: function(event) 138 { 139 var entry = /** @type {!WebInspector.FileSystemMapping.Entry} */ (event.data); 140 this._addMappingRow(entry); 141 }, 142 143 _fileMappingRemoved: function(event) 144 { 145 var entry = /** @type {!WebInspector.FileSystemMapping.Entry} */ (event.data); 146 if (this._fileSystemPath !== entry.fileSystemPath) 147 return; 148 delete this._entries[entry.urlPrefix]; 149 if (this._fileMappingsList.itemForId(entry.urlPrefix)) 150 this._fileMappingsList.removeItem(entry.urlPrefix); 151 this._resize(); 152 }, 153 154 _fileMappingValuesProvider: function(itemId, columnId) 155 { 156 if (!itemId) 157 return ""; 158 var entry = this._entries[itemId]; 159 switch (columnId) { 160 case "url": 161 return entry.urlPrefix; 162 case "path": 163 return entry.pathPrefix; 164 default: 165 console.assert("Should not be reached."); 166 } 167 return ""; 168 }, 169 170 /** 171 * @param {?string} itemId 172 * @param {!Object} data 173 */ 174 _fileMappingValidate: function(itemId, data) 175 { 176 var oldPathPrefix = itemId ? this._entries[itemId].pathPrefix : null; 177 return this._validateMapping(data["url"], itemId, data["path"], oldPathPrefix); 178 }, 179 180 /** 181 * @param {?string} itemId 182 * @param {!Object} data 183 */ 184 _fileMappingEdit: function(itemId, data) 185 { 186 if (itemId) { 187 var urlPrefix = itemId; 188 var pathPrefix = this._entries[itemId].pathPrefix; 189 var fileSystemPath = this._entries[itemId].fileSystemPath; 190 WebInspector.isolatedFileSystemManager.mapping().removeFileMapping(fileSystemPath, urlPrefix, pathPrefix); 191 } 192 this._addFileMapping(data["url"], data["path"]); 193 }, 194 195 /** 196 * @param {string} urlPrefix 197 * @param {?string} allowedURLPrefix 198 * @param {string} path 199 * @param {?string} allowedPathPrefix 200 */ 201 _validateMapping: function(urlPrefix, allowedURLPrefix, path, allowedPathPrefix) 202 { 203 var columns = []; 204 if (!this._checkURLPrefix(urlPrefix, allowedURLPrefix)) 205 columns.push("url"); 206 if (!this._checkPathPrefix(path, allowedPathPrefix)) 207 columns.push("path"); 208 return columns; 209 }, 210 211 /** 212 * @param {!WebInspector.Event} event 213 */ 214 _fileMappingRemovedfromList: function(event) 215 { 216 var urlPrefix = /** @type{?string} */ (event.data); 217 if (!urlPrefix) 218 return; 219 220 var entry = this._entries[urlPrefix]; 221 WebInspector.isolatedFileSystemManager.mapping().removeFileMapping(entry.fileSystemPath, entry.urlPrefix, entry.pathPrefix); 222 }, 223 224 /** 225 * @param {string} urlPrefix 226 * @param {string} pathPrefix 227 * @return {boolean} 228 */ 229 _addFileMapping: function(urlPrefix, pathPrefix) 230 { 231 var normalizedURLPrefix = this._normalizePrefix(urlPrefix); 232 var normalizedPathPrefix = this._normalizePrefix(pathPrefix); 233 WebInspector.isolatedFileSystemManager.mapping().addFileMapping(this._fileSystemPath, normalizedURLPrefix, normalizedPathPrefix); 234 this._fileMappingsList.selectItem(normalizedURLPrefix); 235 return true; 236 }, 237 238 /** 239 * @param {string} prefix 240 * @return {string} 241 */ 242 _normalizePrefix: function(prefix) 243 { 244 if (!prefix) 245 return ""; 246 return prefix + (prefix[prefix.length - 1] === "/" ? "" : "/"); 247 }, 248 249 _addMappingRow: function(entry) 250 { 251 var fileSystemPath = entry.fileSystemPath; 252 var urlPrefix = entry.urlPrefix; 253 if (!this._fileSystemPath || this._fileSystemPath !== fileSystemPath) 254 return; 255 256 this._entries[urlPrefix] = entry; 257 var fileMappingListItem = this._fileMappingsList.addItem(urlPrefix, null); 258 this._resize(); 259 }, 260 261 _excludedFolderAdded: function(event) 262 { 263 var entry = /** @type {!WebInspector.FileSystemMapping.ExcludedFolderEntry} */ (event.data); 264 this._addExcludedFolderRow(entry); 265 }, 266 267 _excludedFolderRemoved: function(event) 268 { 269 var entry = /** @type {!WebInspector.FileSystemMapping.ExcludedFolderEntry} */ (event.data); 270 var fileSystemPath = entry.fileSystemPath; 271 if (!fileSystemPath || this._fileSystemPath !== fileSystemPath) 272 return; 273 delete this._excludedFolderEntries[entry.path]; 274 if (this._excludedFolderList.itemForId(entry.path)) 275 this._excludedFolderList.removeItem(entry.path); 276 }, 277 278 _excludedFolderValueProvider: function(itemId, columnId) 279 { 280 return itemId; 281 }, 282 283 /** 284 * @param {?string} itemId 285 * @param {!Object} data 286 */ 287 _excludedFolderValidate: function(itemId, data) 288 { 289 var fileSystemPath = this._fileSystemPath; 290 var columns = []; 291 if (!this._validateExcludedFolder(data["path"], itemId)) 292 columns.push("path"); 293 return columns; 294 }, 295 296 /** 297 * @param {string} path 298 * @param {?string} allowedPath 299 * @return {boolean} 300 */ 301 _validateExcludedFolder: function(path, allowedPath) 302 { 303 return !!path && (path === allowedPath || !this._excludedFolderEntries.contains(path)); 304 }, 305 306 /** 307 * @param {?string} itemId 308 * @param {!Object} data 309 */ 310 _excludedFolderEdit: function(itemId, data) 311 { 312 var fileSystemPath = this._fileSystemPath; 313 if (itemId) 314 WebInspector.isolatedFileSystemManager.mapping().removeExcludedFolder(fileSystemPath, itemId); 315 var excludedFolderPath = data["path"]; 316 WebInspector.isolatedFileSystemManager.mapping().addExcludedFolder(fileSystemPath, excludedFolderPath); 317 }, 318 319 /** 320 * @param {!WebInspector.Event} event 321 */ 322 _excludedFolderRemovedfromList: function(event) 323 { 324 var itemId = /** @type{?string} */ (event.data); 325 if (!itemId) 326 return; 327 WebInspector.isolatedFileSystemManager.mapping().removeExcludedFolder(this._fileSystemPath, itemId); 328 }, 329 330 /** 331 * @param {!WebInspector.FileSystemMapping.ExcludedFolderEntry} entry 332 */ 333 _addExcludedFolderRow: function(entry) 334 { 335 var fileSystemPath = entry.fileSystemPath; 336 if (!fileSystemPath || this._fileSystemPath !== fileSystemPath) 337 return; 338 var path = entry.path; 339 this._excludedFolderEntries.put(path, entry); 340 this._excludedFolderList.addItem(path, null); 341 }, 342 343 /** 344 * @param {string} value 345 * @param {?string} allowedPrefix 346 * @return {boolean} 347 */ 348 _checkURLPrefix: function(value, allowedPrefix) 349 { 350 var prefix = this._normalizePrefix(value); 351 return !!prefix && (prefix === allowedPrefix || !this._entries[prefix]); 352 }, 353 354 /** 355 * @param {string} value 356 * @param {?string} allowedPrefix 357 * @return {boolean} 358 */ 359 _checkPathPrefix: function(value, allowedPrefix) 360 { 361 var prefix = this._normalizePrefix(value); 362 if (!prefix) 363 return false; 364 if (prefix === allowedPrefix) 365 return true; 366 for (var urlPrefix in this._entries) { 367 var entry = this._entries[urlPrefix]; 368 if (urlPrefix && entry.pathPrefix === prefix) 369 return false; 370 } 371 return true; 372 }, 373 374 focus: function() 375 { 376 WebInspector.setCurrentFocusElement(this.element); 377 }, 378 379 _onDoneClick: function() 380 { 381 WebInspector.Dialog.hide(); 382 }, 383 384 onEnter: function() 385 { 386 }, 387 388 __proto__: WebInspector.DialogDelegate.prototype 389} 390