Unreviewed, rolling out r143100.
[WebKit-https.git] / Source / WebCore / inspector / front-end / Workspace.js
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  */
34 WebInspector.WorkspaceController = function(workspace)
35 {
36     this._workspace = workspace;
37     WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, this._inspectedURLChanged, this);
38 }
39
40 WebInspector.WorkspaceController.prototype = {
41     /**
42      * @param {WebInspector.Event} event
43      */
44     _inspectedURLChanged: function(event)
45     {
46         WebInspector.Revision.filterOutStaleRevisions();
47     }
48 }
49
50 /**
51  * @constructor
52  * @param {string} path
53  * @param {string} originURL
54  * @param {string} url
55  * @param {WebInspector.ResourceType} contentType
56  * @param {boolean} isEditable
57  * @param {boolean=} isContentScript
58  */
59 WebInspector.FileDescriptor = function(path, originURL, url, contentType, isEditable, isContentScript)
60 {
61     this.path = path;
62     this.originURL = originURL;
63     this.url = url;
64     this.contentType = contentType;
65     this.isEditable = isEditable;
66     this.isContentScript = isContentScript || false;
67 }
68
69 /**
70  * @interface
71  */
72 WebInspector.ProjectDelegate = function() { }
73
74 WebInspector.ProjectDelegate.Events = {
75     FileAdded: "FileAdded",
76     FileRemoved: "FileRemoved",
77     Reset: "Reset",
78 }
79
80 WebInspector.ProjectDelegate.prototype = {
81     /**
82      * @return {string}
83      */
84     id: function() { },
85
86     /**
87      * @return {string}
88      */
89     type: function() { },
90
91     /**
92      * @return {string}
93      */
94     displayName: function() { }, 
95
96     /**
97      * @param {string} path
98      * @param {function(?string,boolean,string)} callback
99      */
100     requestFileContent: function(path, callback) { },
101
102     /**
103      * @param {string} path
104      * @param {string} newContent
105      * @param {function(?string)} callback
106      */
107     setFileContent: function(path, newContent, callback) { },
108
109     /**
110      * @param {string} path
111      * @param {string} query
112      * @param {boolean} caseSensitive
113      * @param {boolean} isRegex
114      * @param {function(Array.<WebInspector.ContentProvider.SearchMatch>)} callback
115      */
116     searchInFileContent: function(path, query, caseSensitive, isRegex, callback) { },
117
118     /**
119      * @param {string} eventType
120      * @param {function(WebInspector.Event)} listener
121      * @param {Object=} thisObject
122      */
123     addEventListener: function(eventType, listener, thisObject) { },
124
125     /**
126      * @param {string} eventType
127      * @param {function(WebInspector.Event)} listener
128      * @param {Object=} thisObject
129      */
130     removeEventListener: function(eventType, listener, thisObject) { }
131 }
132
133 /**
134  * @type {?WebInspector.WorkspaceController}
135  */
136 WebInspector.workspaceController = null;
137
138 /**
139  * @param {WebInspector.Workspace} workspace
140  * @param {WebInspector.ProjectDelegate} projectDelegate
141  * @constructor
142  */
143 WebInspector.Project = function(workspace, projectDelegate)
144 {
145     /** @type {Object.<string, WebInspector.UISourceCode>} */
146     this._uiSourceCodes = {};
147     this._workspace = workspace;
148     this._projectDelegate = projectDelegate;
149     this._projectDelegate.addEventListener(WebInspector.ProjectDelegate.Events.FileAdded, this._fileAdded, this);
150     this._projectDelegate.addEventListener(WebInspector.ProjectDelegate.Events.FileRemoved, this._fileRemoved, this);
151     this._projectDelegate.addEventListener(WebInspector.ProjectDelegate.Events.Reset, this._reset, this);
152 }
153
154 WebInspector.Project.prototype = {
155     /**
156      * @return {string}
157      */
158     id: function()
159     {
160         return this._projectDelegate.id();
161     },
162
163     /**
164      * @return {string}
165      */
166     type: function()
167     {
168         return this._projectDelegate.type(); 
169     },
170
171     /**
172      * @return {string}
173      */
174     displayName: function() 
175     {
176         return this._projectDelegate.displayName(); 
177     },
178
179     /**
180      * @return {boolean}
181      */
182     isServiceProject: function()
183     {
184         return this._projectDelegate.type() === WebInspector.projectTypes.Debugger || this._projectDelegate.type() === WebInspector.projectTypes.LiveEdit;
185     },
186
187     _fileAdded: function(event)
188     {
189         var fileDescriptor = /** @type {WebInspector.FileDescriptor} */ (event.data);
190         var uiSourceCode = this.uiSourceCodeForURI(fileDescriptor.path);
191         if (uiSourceCode) {
192             // FIXME: Implement
193             return;
194         }
195         uiSourceCode = new WebInspector.UISourceCode(this, fileDescriptor.path, fileDescriptor.originURL, fileDescriptor.url, fileDescriptor.contentType, fileDescriptor.isEditable); 
196         uiSourceCode.isContentScript = fileDescriptor.isContentScript;
197         this._uiSourceCodes[uiSourceCode.path()] = uiSourceCode;
198         this._workspace.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, uiSourceCode);
199     },
200
201     _fileRemoved: function(event)
202     {
203         var path = /** @type {string} */ (event.data);
204         var uiSourceCode = this.uiSourceCodeForURI(path);
205         if (!uiSourceCode)
206             return;
207         delete this._uiSourceCodes[uiSourceCode.path()];
208         this._workspace.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeRemoved, uiSourceCode);
209     },
210
211     _reset: function()
212     {
213         this._workspace.dispatchEventToListeners(WebInspector.Workspace.Events.ProjectWillReset, this);
214         this._uiSourceCodes = {};
215     },
216
217     /**
218      * @param {string} path
219      * @return {?WebInspector.UISourceCode}
220      */
221     uiSourceCode: function(path)
222     {
223         return this._uiSourceCodes[path] || null;
224     },
225
226     /**
227      * @param {string} originURL
228      * @return {?WebInspector.UISourceCode}
229      */
230     uiSourceCodeForOriginURL: function(originURL)
231     {
232         for (var path in this._uiSourceCodes) {
233             var uiSourceCode = this._uiSourceCodes[path];
234             if (uiSourceCode.originURL() === originURL)
235                 return uiSourceCode;
236         }
237         return null;
238     },
239
240     /**
241      * @param {string} uri
242      * @return {?WebInspector.UISourceCode}
243      */
244     uiSourceCodeForURI: function(uri)
245     {
246         return this.uiSourceCode(uri);
247     },
248
249     /**
250      * @return {Array.<WebInspector.UISourceCode>}
251      */
252     uiSourceCodes: function()
253     {
254         return Object.values(this._uiSourceCodes);
255     },
256
257     /**
258      * @param {WebInspector.UISourceCode} uiSourceCode
259      * @param {function(?string,boolean,string)} callback
260      */
261     requestFileContent: function(uiSourceCode, callback)
262     {
263         this._projectDelegate.requestFileContent(uiSourceCode.path(), callback);
264     },
265
266     /**
267      * @param {WebInspector.UISourceCode} uiSourceCode
268      * @param {string} newContent
269      * @param {function(?string)} callback
270      */
271     setFileContent: function(uiSourceCode, newContent, callback)
272     {
273         this._projectDelegate.setFileContent(uiSourceCode.path(), newContent, callback);
274         this._workspace.dispatchEventToListeners(WebInspector.Workspace.Events.UISourceCodeContentCommitted, { uiSourceCode: uiSourceCode, content: newContent });
275     },
276
277     /**
278      * @param {WebInspector.UISourceCode} uiSourceCode
279      * @param {string} query
280      * @param {boolean} caseSensitive
281      * @param {boolean} isRegex
282      * @param {function(Array.<WebInspector.ContentProvider.SearchMatch>)} callback
283      */
284     searchInFileContent: function(uiSourceCode, query, caseSensitive, isRegex, callback)
285     {
286         this._projectDelegate.searchInFileContent(uiSourceCode.path(), query, caseSensitive, isRegex, callback);
287     },
288
289     dispose: function()
290     {
291         this._projectDelegate.reset();
292     }
293 }
294
295 WebInspector.projectTypes = {
296     Debugger: "debugger",
297     LiveEdit: "liveedit",
298     Compiler: "compiler",
299     Network: "network",
300     Snippets: "snippets",
301     FileSystem: "filesystem"
302 }
303
304 /**
305  * @constructor
306  * @implements {WebInspector.UISourceCodeProvider}
307  * @extends {WebInspector.Object}
308  */
309 WebInspector.Workspace = function()
310 {
311     /** @type {!Object.<string, WebInspector.Project>} */
312     this._projects = {};
313 }
314
315 WebInspector.Workspace.Events = {
316     UISourceCodeContentCommitted: "UISourceCodeContentCommitted",
317     ProjectWillReset: "ProjectWillReset"
318 }
319
320 WebInspector.Workspace.prototype = {
321     /**
322      * @param {string} projectId
323      * @param {string} path
324      * @return {?WebInspector.UISourceCode}
325      */
326     uiSourceCode: function(projectId, path)
327     {
328         var project = this._projects[projectId];
329         return project ? project.uiSourceCode(path) : null;
330     },
331
332     /**
333      * @param {string} originURL
334      * @return {?WebInspector.UISourceCode}
335      */
336     uiSourceCodeForOriginURL: function(originURL)
337     {
338         var networkProjects = this.projectsForType(WebInspector.projectTypes.Network)
339         for (var i = 0; i < networkProjects.length; ++i) {
340             var project = networkProjects[i];
341             var uiSourceCode = project.uiSourceCodeForOriginURL(originURL);
342             if (uiSourceCode)
343                 return uiSourceCode;
344         }
345         return null;
346     },
347
348     /**
349      * @param {string} uri
350      * @return {?WebInspector.UISourceCode}
351      */
352     uiSourceCodeForURI: function(uri)
353     {
354         for (var projectId in this._projects) {
355             var project = this._projects[projectId];
356             var uiSourceCode = project.uiSourceCodeForURI(uri);
357             if (uiSourceCode)
358                 return uiSourceCode;
359         }
360         return null;
361     },
362
363     /**
364      * @param {string} type
365      * @return {Array.<WebInspector.UISourceCode>}
366      */
367     uiSourceCodesForProjectType: function(type)
368     {
369         var result = [];
370         for (var projectName in this._projects) {
371             var project = this._projects[projectName];
372             if (project.type() === type)
373                 result = result.concat(project.uiSourceCodes());
374         }
375         return result;
376     },
377
378     /**
379      * @param {WebInspector.ProjectDelegate} projectDelegate
380      * @return {WebInspector.Project}
381      */
382     addProject: function(projectDelegate)
383     {
384         var projectId = projectDelegate.id();
385         this._projects[projectId] = new WebInspector.Project(this, projectDelegate);
386         return this._projects[projectId];
387     },
388
389     /**
390      * @param {string} projectId
391      */
392     removeProject: function(projectId)
393     {
394         var project = this._projects[projectId];
395         if (!project)
396             return;
397         project.dispose();
398         delete this._projects[projectId];
399     },
400
401     /**
402      * @param {string} projectId
403      * @return {WebInspector.Project}
404      */
405     project: function(projectId)
406     {
407         return this._projects[projectId];
408     },
409
410     /**
411      * @return {Array.<WebInspector.Project>}
412      */
413     projects: function()
414     {
415         return Object.values(this._projects);
416     },
417
418     /**
419      * @param {string} type
420      * @return {Array.<WebInspector.Project>}
421      */
422     projectsForType: function(type)
423     {
424         function filterByType(project)
425         {
426             return project.type() === type;
427         }
428         return this.projects().filter(filterByType);
429     },
430
431     /**
432      * @return {Array.<WebInspector.UISourceCode>}
433      */
434     uiSourceCodes: function()
435     {
436         var result = [];
437         for (var projectId in this._projects) {
438             var project = this._projects[projectId];
439             result = result.concat(project.uiSourceCodes());
440         }
441         return result;
442     },
443
444     /**
445      * @return {?WebInspector.Project}
446      */
447     projectForUISourceCode: function(uiSourceCode)
448     {
449         for (var projectId in this._projects) {
450             var project = this._projects[projectId];
451             if (project.uiSourceCodeForURI(uiSourceCode.uri()))
452                 return project;
453         }
454         return null;
455     },
456
457     __proto__: WebInspector.Object.prototype
458 }
459
460 /**
461  * @type {?WebInspector.Workspace}
462  */
463 WebInspector.workspace = null;