Home | History | Annotate | Download | only in front_end
      1 /*
      2  * Copyright (C) 2012 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.Object}
     34  */
     35 WebInspector.FileSystemMapping = function()
     36 {
     37     WebInspector.Object.call(this);
     38     this._fileSystemMappingSetting = WebInspector.settings.createSetting("fileSystemMapping", {});
     39     /** @type {!Object.<string, Array.<WebInspector.FileSystemMapping.Entry>>} */
     40     this._fileSystemMappings = {};
     41     this._loadFromSettings();
     42 }
     43 
     44 WebInspector.FileSystemMapping.Events = {
     45     FileMappingAdded: "FileMappingAdded",
     46     FileMappingRemoved: "FileMappingRemoved"
     47 }
     48 
     49 
     50 WebInspector.FileSystemMapping.prototype = {
     51     _loadFromSettings: function()
     52     {
     53         var savedMapping = this._fileSystemMappingSetting.get();
     54         this._fileSystemMappings = {};
     55         for (var fileSystemPath in savedMapping) {
     56             var savedFileSystemMappings = savedMapping[fileSystemPath];
     57 
     58             this._fileSystemMappings[fileSystemPath] = [];
     59             var fileSystemMappings = this._fileSystemMappings[fileSystemPath];
     60 
     61             for (var i = 0; i < savedFileSystemMappings.length; ++i) {
     62                 var savedEntry = savedFileSystemMappings[i];
     63                 var entry = new WebInspector.FileSystemMapping.Entry(savedEntry.fileSystemPath, savedEntry.urlPrefix, savedEntry.pathPrefix);
     64                 fileSystemMappings.push(entry);
     65             }
     66         }
     67         this._rebuildIndexes();
     68     },
     69 
     70     _saveToSettings: function()
     71     {
     72         var savedMapping = this._fileSystemMappings;
     73         this._fileSystemMappingSetting.set(savedMapping);
     74         this._rebuildIndexes();
     75     },
     76 
     77     _rebuildIndexes: function()
     78     {
     79         // We are building an index here to search for the longest url prefix match faster.
     80         this._mappingForURLPrefix = {};
     81         this._urlPrefixes = [];
     82         for (var fileSystemPath in this._fileSystemMappings) {
     83             var fileSystemMapping = this._fileSystemMappings[fileSystemPath];
     84             for (var i = 0; i < fileSystemMapping.length; ++i) {
     85                 var entry = fileSystemMapping[i];
     86                 this._mappingForURLPrefix[entry.urlPrefix] = entry;
     87                 this._urlPrefixes.push(entry.urlPrefix);
     88             }
     89         }
     90         this._urlPrefixes.sort();
     91     },
     92 
     93     /**
     94      * @param {string} fileSystemPath
     95      */
     96     addFileSystem: function(fileSystemPath)
     97     {
     98         if (this._fileSystemMappings[fileSystemPath])
     99             return;
    100 
    101         this._fileSystemMappings[fileSystemPath] = [];
    102         this._saveToSettings();
    103     },
    104 
    105     /**
    106      * @param {string} fileSystemPath
    107      */
    108     removeFileSystem: function(fileSystemPath)
    109     {
    110         if (!this._fileSystemMappings[fileSystemPath])
    111             return;
    112         delete this._fileSystemMappings[fileSystemPath];
    113         this._saveToSettings();
    114     },
    115 
    116     /**
    117      * @param {string} fileSystemPath
    118      * @param {string} urlPrefix
    119      * @param {string} pathPrefix
    120      */
    121     addFileMapping: function(fileSystemPath, urlPrefix, pathPrefix)
    122     {
    123         var entry = new WebInspector.FileSystemMapping.Entry(fileSystemPath, urlPrefix, pathPrefix);
    124         this._fileSystemMappings[fileSystemPath].push(entry);
    125         this._saveToSettings();
    126         this.dispatchEventToListeners(WebInspector.FileSystemMapping.Events.FileMappingAdded, entry);
    127     },
    128 
    129     /**
    130      * @param {string} fileSystemPath
    131      * @param {string} urlPrefix
    132      * @param {string} pathPrefix
    133      */
    134     removeFileMapping: function(fileSystemPath, urlPrefix, pathPrefix)
    135     {
    136         var entry = this._mappingEntryForPathPrefix(fileSystemPath, pathPrefix);
    137         if (!entry)
    138             return;
    139         this._fileSystemMappings[fileSystemPath].remove(entry);
    140         this._saveToSettings();
    141         this.dispatchEventToListeners(WebInspector.FileSystemMapping.Events.FileMappingRemoved, entry);
    142     },
    143 
    144     /**
    145      * @return {Array.<string>}
    146      */
    147     fileSystemPaths: function()
    148     {
    149         return Object.keys(this._fileSystemMappings);
    150     },
    151 
    152     /**
    153      * @param {string} url
    154      * @return {WebInspector.FileSystemMapping.Entry}
    155      */
    156     _mappingEntryForURL: function(url)
    157     {
    158         for (var i = this._urlPrefixes.length - 1; i >= 0; --i) {
    159             var urlPrefix = this._urlPrefixes[i];
    160             if (url.startsWith(urlPrefix))
    161                 return this._mappingForURLPrefix[urlPrefix];
    162         }
    163         return null;
    164     },
    165 
    166     /**
    167      * @param {string} fileSystemPath
    168      * @param {string} filePath
    169      * @return {?WebInspector.FileSystemMapping.Entry}
    170      */
    171     _mappingEntryForPath: function(fileSystemPath, filePath)
    172     {
    173         var entries = this._fileSystemMappings[fileSystemPath];
    174         if (!entries)
    175             return null;
    176 
    177         var entry = null;
    178         for (var i = 0; i < entries.length; ++i) {
    179             var pathPrefix = entries[i].pathPrefix;
    180             // We are looking for the longest pathPrefix match.
    181             if (entry && entry.pathPrefix.length > pathPrefix.length)
    182                 continue;
    183             if (filePath.startsWith(pathPrefix.substr(1)))
    184                 entry = entries[i];
    185         }
    186         return entry;
    187     },
    188 
    189     /**
    190      * @param {string} fileSystemPath
    191      * @param {string} pathPrefix
    192      * @return {WebInspector.FileSystemMapping.Entry}
    193      */
    194     _mappingEntryForPathPrefix: function(fileSystemPath, pathPrefix)
    195     {
    196         var entries = this._fileSystemMappings[fileSystemPath];
    197         for (var i = 0; i < entries.length; ++i) {
    198             if (pathPrefix === entries[i].pathPrefix)
    199                 return entries[i];
    200         }
    201         return null;
    202     },
    203 
    204     /**
    205      * @param {string} fileSystemPath
    206      * @return {Array.<WebInspector.FileSystemMapping.Entry>}
    207      */
    208     mappingEntries: function(fileSystemPath)
    209     {
    210         return this._fileSystemMappings[fileSystemPath].slice();
    211     },
    212 
    213     /**
    214      * @param {string} url
    215      * @return {boolean}
    216      */
    217     hasMappingForURL: function(url)
    218     {
    219         return !!this._mappingEntryForURL(url);
    220     },
    221 
    222     /**
    223      * @param {string} url
    224      * @return {?{fileSystemPath: string, filePath: string}}
    225      */
    226     fileForURL: function(url)
    227     {
    228         var entry = this._mappingEntryForURL(url);
    229         if (!entry)
    230             return null;
    231         var file = {};
    232         file.fileSystemPath = entry.fileSystemPath;
    233         file.filePath = entry.pathPrefix.substr(1) + url.substr(entry.urlPrefix.length);
    234         return file;
    235     },
    236 
    237     /**
    238      * @param {string} fileSystemPath
    239      * @param {string} filePath
    240      * @return {string}
    241      */
    242     urlForPath: function(fileSystemPath, filePath)
    243     {
    244         var entry = this._mappingEntryForPath(fileSystemPath, filePath);
    245         if (!entry)
    246             return "";
    247         return entry.urlPrefix + filePath.substring(entry.pathPrefix.length - 1);
    248     },
    249 
    250     /**
    251      * @param {string} url
    252      */
    253     removeMappingForURL: function(url)
    254     {
    255         var entry = this._mappingEntryForURL(url);
    256         if (!entry)
    257             return;
    258         this._fileSystemMappings[entry.fileSystemPath].remove(entry);
    259         this._saveToSettings();
    260     },
    261 
    262     /**
    263      * @param {string} url
    264      * @param {string} fileSystemPath
    265      * @param {string} filePath
    266      */
    267     addMappingForResource: function(url, fileSystemPath, filePath)
    268     {
    269         var commonPathSuffixLength = 0;
    270         var normalizedFilePath = "/" + filePath;
    271         for (var i = 0; i < normalizedFilePath.length; ++i) {
    272             var filePathCharacter = normalizedFilePath[normalizedFilePath.length - 1 - i];
    273             var urlCharacter = url[url.length - 1 - i];
    274             if (filePathCharacter !== urlCharacter)
    275                 break;
    276             if (filePathCharacter === "/")
    277                 commonPathSuffixLength = i;
    278         }
    279         var pathPrefix = normalizedFilePath.substr(0, normalizedFilePath.length - commonPathSuffixLength);
    280         var urlPrefix = url.substr(0, url.length - commonPathSuffixLength);
    281         this.addFileMapping(fileSystemPath, urlPrefix, pathPrefix);
    282     },
    283 
    284     __proto__: WebInspector.Object.prototype
    285 }
    286 
    287 /**
    288  * @constructor
    289  * @param {string} fileSystemPath
    290  * @param {string} urlPrefix
    291  * @param {string} pathPrefix
    292  */
    293 WebInspector.FileSystemMapping.Entry = function(fileSystemPath, urlPrefix, pathPrefix)
    294 {
    295     this.fileSystemPath = fileSystemPath;
    296     this.urlPrefix = urlPrefix;
    297     this.pathPrefix = pathPrefix;
    298 }
    299