Home | History | Annotate | Download | only in sdk
      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  * @implements {WebInspector.ProjectDelegate}
     34  * @param {!WebInspector.Workspace} workspace
     35  * @param {string} id
     36  * @param {!WebInspector.projectTypes} type
     37  */
     38 WebInspector.ContentProviderBasedProjectDelegate = function(workspace, id, type)
     39 {
     40     this._type = type;
     41     /** @type {!Object.<string, !WebInspector.ContentProvider>} */
     42     this._contentProviders = {};
     43     this._workspace = workspace;
     44     this._id = id;
     45     this._projectStore = workspace.addProject(id, this);
     46 }
     47 
     48 WebInspector.ContentProviderBasedProjectDelegate.prototype = {
     49     /**
     50      * @return {string}
     51      */
     52     type: function()
     53     {
     54         return this._type;
     55     },
     56 
     57     /**
     58      * @return {string}
     59      */
     60     displayName: function()
     61     {
     62         // Overriddden by subclasses
     63         return "";
     64     },
     65 
     66     /**
     67      * @param {string} path
     68      * @param {function(?Date, ?number)} callback
     69      */
     70     requestMetadata: function(path, callback)
     71     {
     72         callback(null, null);
     73     },
     74 
     75     /**
     76      * @param {string} path
     77      * @param {function(?string)} callback
     78      */
     79     requestFileContent: function(path, callback)
     80     {
     81         var contentProvider = this._contentProviders[path];
     82         contentProvider.requestContent(callback);
     83 
     84         /**
     85          * @param {?string} content
     86          * @param {boolean} encoded
     87          * @param {string} mimeType
     88          */
     89         function innerCallback(content, encoded, mimeType)
     90         {
     91             callback(content);
     92         }
     93     },
     94 
     95     /**
     96      * @return {boolean}
     97      */
     98     canSetFileContent: function()
     99     {
    100         return false;
    101     },
    102 
    103     /**
    104      * @param {string} path
    105      * @param {string} newContent
    106      * @param {function(?string)} callback
    107      */
    108     setFileContent: function(path, newContent, callback)
    109     {
    110         callback(null);
    111     },
    112 
    113     /**
    114      * @return {boolean}
    115      */
    116     canRename: function()
    117     {
    118         return false;
    119     },
    120 
    121     /**
    122      * @param {string} path
    123      * @param {string} newName
    124      * @param {function(boolean, string=, string=, string=, !WebInspector.ResourceType=)} callback
    125      */
    126     rename: function(path, newName, callback)
    127     {
    128         this.performRename(path, newName, innerCallback.bind(this));
    129 
    130         /**
    131          * @param {boolean} success
    132          * @param {string=} newName
    133          * @this {WebInspector.ContentProviderBasedProjectDelegate}
    134          */
    135         function innerCallback(success, newName)
    136         {
    137             if (success)
    138                 this._updateName(path, /** @type {string} */ (newName));
    139             callback(success, newName);
    140         }
    141     },
    142 
    143     /**
    144      * @param {string} path
    145      */
    146     refresh: function(path)
    147     {
    148     },
    149 
    150     /**
    151      * @param {string} path
    152      */
    153     excludeFolder: function(path)
    154     {
    155     },
    156 
    157     /**
    158      * @param {string} path
    159      * @param {?string} name
    160      * @param {string} content
    161      * @param {function(?string)} callback
    162      */
    163     createFile: function(path, name, content, callback)
    164     {
    165     },
    166 
    167     /**
    168      * @param {string} path
    169      */
    170     deleteFile: function(path)
    171     {
    172     },
    173 
    174     remove: function()
    175     {
    176     },
    177 
    178     /**
    179      * @param {string} path
    180      * @param {string} newName
    181      * @param {function(boolean, string=)} callback
    182      */
    183     performRename: function(path, newName, callback)
    184     {
    185         callback(false);
    186     },
    187 
    188     /**
    189      * @param {string} path
    190      * @param {string} newName
    191      */
    192     _updateName: function(path, newName)
    193     {
    194         var oldPath = path;
    195         var copyOfPath = path.split("/");
    196         copyOfPath[copyOfPath.length - 1] = newName;
    197         var newPath = copyOfPath.join("/");
    198         this._contentProviders[newPath] = this._contentProviders[oldPath];
    199         delete this._contentProviders[oldPath];
    200     },
    201 
    202     /**
    203      * @param {string} path
    204      * @param {string} query
    205      * @param {boolean} caseSensitive
    206      * @param {boolean} isRegex
    207      * @param {function(!Array.<!WebInspector.ContentProvider.SearchMatch>)} callback
    208      */
    209     searchInFileContent: function(path, query, caseSensitive, isRegex, callback)
    210     {
    211         var contentProvider = this._contentProviders[path];
    212         contentProvider.searchInContent(query, caseSensitive, isRegex, callback);
    213     },
    214 
    215     /**
    216      * @param {!WebInspector.ProjectSearchConfig} searchConfig
    217      * @param {!WebInspector.Progress} progress
    218      * @param {function(!Array.<string>)} callback
    219      */
    220     findFilesMatchingSearchRequest: function(searchConfig, progress, callback)
    221     {
    222         var result = [];
    223         var paths = Object.keys(this._contentProviders);
    224         var totalCount = paths.length;
    225         if (totalCount === 0) {
    226             // searchInContent should call back later.
    227             setTimeout(doneCallback, 0);
    228             return;
    229         }
    230 
    231         paths = paths.filter(searchConfig.filePathMatchesFileQuery.bind(searchConfig));
    232         var barrier = new CallbackBarrier();
    233         progress.setTotalWork(paths.length);
    234         for (var i = 0; i < paths.length; ++i)
    235             searchInContent.call(this, paths[i], barrier.createCallback(searchInContentCallback.bind(null, paths[i])));
    236         barrier.callWhenDone(doneCallback);
    237 
    238         /**
    239          * @param {string} path
    240          * @param {function(boolean)} callback
    241          * @this {WebInspector.ContentProviderBasedProjectDelegate}
    242          */
    243         function searchInContent(path, callback)
    244         {
    245             var queriesToRun = searchConfig.queries().slice();
    246             searchNextQuery.call(this);
    247 
    248             /**
    249              * @this {WebInspector.ContentProviderBasedProjectDelegate}
    250              */
    251             function searchNextQuery()
    252             {
    253                 if (!queriesToRun.length) {
    254                     callback(true);
    255                     return;
    256                 }
    257                 var query = queriesToRun.shift();
    258                 this._contentProviders[path].searchInContent(query, !searchConfig.ignoreCase(), searchConfig.isRegex(), contentCallback.bind(this));
    259             }
    260 
    261             /**
    262              * @param {!Array.<!WebInspector.ContentProvider.SearchMatch>} searchMatches
    263              * @this {WebInspector.ContentProviderBasedProjectDelegate}
    264              */
    265             function contentCallback(searchMatches)
    266             {
    267                 if (!searchMatches.length) {
    268                     callback(false);
    269                     return;
    270                 }
    271                 searchNextQuery.call(this);
    272             }
    273         }
    274 
    275         /**
    276          * @param {string} path
    277          * @param {boolean} matches
    278          */
    279         function searchInContentCallback(path, matches)
    280         {
    281             if (matches)
    282                 result.push(path);
    283             progress.worked(1);
    284         }
    285 
    286         function doneCallback()
    287         {
    288             callback(result);
    289             progress.done();
    290         }
    291     },
    292 
    293     /**
    294      * @param {!WebInspector.Progress} progress
    295      */
    296     indexContent: function(progress)
    297     {
    298         setTimeout(progress.done.bind(progress), 0);
    299     },
    300 
    301     /**
    302      * @param {string} parentPath
    303      * @param {string} name
    304      * @param {string} url
    305      * @param {!WebInspector.ContentProvider} contentProvider
    306      * @return {string}
    307      */
    308     addContentProvider: function(parentPath, name, url, contentProvider)
    309     {
    310         var path = parentPath ? parentPath + "/" + name : name;
    311         if (this._contentProviders[path])
    312             return path;
    313         var fileDescriptor = new WebInspector.FileDescriptor(parentPath, name, url, url, contentProvider.contentType());
    314         this._contentProviders[path] = contentProvider;
    315         this._projectStore.addFile(fileDescriptor);
    316         return path;
    317     },
    318 
    319     /**
    320      * @param {string} path
    321      */
    322     removeFile: function(path)
    323     {
    324         delete this._contentProviders[path];
    325         this._projectStore.removeFile(path);
    326     },
    327 
    328     /**
    329      * @return {!Object.<string, !WebInspector.ContentProvider>}
    330      */
    331     contentProviders: function()
    332     {
    333         return this._contentProviders;
    334     },
    335 
    336     reset: function()
    337     {
    338         this._contentProviders = {};
    339         this._workspace.removeProject(this._id);
    340         this._projectStore = this._workspace.addProject(this._id, this);
    341     }
    342 }
    343