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