• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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