Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(364)

Side by Side Diff: Source/devtools/front_end/sdk/UISourceCode.js

Issue 471433004: DevTools: Split out the "workspace" and "bindings" modules from "sdk" (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Remove marker interfaces and WI.SourceMapping Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/devtools/front_end/sdk/TempFile.js ('k') | Source/devtools/front_end/sdk/Workspace.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2011 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 /**
33 * @constructor
34 * @extends {WebInspector.Object}
35 * @implements {WebInspector.ContentProvider}
36 * @param {!WebInspector.Project} project
37 * @param {string} parentPath
38 * @param {string} name
39 * @param {string} originURL
40 * @param {string} url
41 * @param {!WebInspector.ResourceType} contentType
42 */
43 WebInspector.UISourceCode = function(project, parentPath, name, originURL, url, contentType)
44 {
45 this._project = project;
46 this._parentPath = parentPath;
47 this._name = name;
48 this._originURL = originURL;
49 this._url = url;
50 this._contentType = contentType;
51 /** @type {!Array.<function(?string)>} */
52 this._requestContentCallbacks = [];
53 /** @type {!Array.<!WebInspector.PresentationConsoleMessage>} */
54 this._consoleMessages = [];
55
56 /** @type {!Array.<!WebInspector.Revision>} */
57 this.history = [];
58 }
59
60 WebInspector.UISourceCode.Events = {
61 WorkingCopyChanged: "WorkingCopyChanged",
62 WorkingCopyCommitted: "WorkingCopyCommitted",
63 TitleChanged: "TitleChanged",
64 SavedStateUpdated: "SavedStateUpdated",
65 ConsoleMessageAdded: "ConsoleMessageAdded",
66 ConsoleMessageRemoved: "ConsoleMessageRemoved",
67 ConsoleMessagesCleared: "ConsoleMessagesCleared",
68 SourceMappingChanged: "SourceMappingChanged",
69 }
70
71 WebInspector.UISourceCode.prototype = {
72 /**
73 * @return {string}
74 */
75 get url()
76 {
77 return this._url;
78 },
79
80 /**
81 * @return {string}
82 */
83 name: function()
84 {
85 return this._name;
86 },
87
88 /**
89 * @return {string}
90 */
91 parentPath: function()
92 {
93 return this._parentPath;
94 },
95
96 /**
97 * @return {string}
98 */
99 path: function()
100 {
101 return this._parentPath ? this._parentPath + "/" + this._name : this._na me;
102 },
103
104 /**
105 * @return {string}
106 */
107 fullDisplayName: function()
108 {
109 return this._project.displayName() + "/" + (this._parentPath ? this._par entPath + "/" : "") + this.displayName(true);
110 },
111
112 /**
113 * @param {boolean=} skipTrim
114 * @return {string}
115 */
116 displayName: function(skipTrim)
117 {
118 var displayName = this.name() || WebInspector.UIString("(index)");
119 return skipTrim ? displayName : displayName.trimEnd(100);
120 },
121
122 /**
123 * @return {string}
124 */
125 uri: function()
126 {
127 var path = this.path();
128 if (!this._project.id())
129 return path;
130 if (!path)
131 return this._project.id();
132 return this._project.id() + "/" + path;
133 },
134
135 /**
136 * @return {string}
137 */
138 originURL: function()
139 {
140 return this._originURL;
141 },
142
143 /**
144 * @return {boolean}
145 */
146 canRename: function()
147 {
148 return this._project.canRename();
149 },
150
151 /**
152 * @param {string} newName
153 * @param {function(boolean)} callback
154 */
155 rename: function(newName, callback)
156 {
157 this._project.rename(this, newName, innerCallback.bind(this));
158
159 /**
160 * @param {boolean} success
161 * @param {string=} newName
162 * @param {string=} newURL
163 * @param {string=} newOriginURL
164 * @param {!WebInspector.ResourceType=} newContentType
165 * @this {WebInspector.UISourceCode}
166 */
167 function innerCallback(success, newName, newURL, newOriginURL, newConten tType)
168 {
169 if (success)
170 this._updateName(/** @type {string} */ (newName), /** @type {str ing} */ (newURL), /** @type {string} */ (newOriginURL), /** @type {!WebInspector .ResourceType} */ (newContentType));
171 callback(success);
172 }
173 },
174
175 remove: function()
176 {
177 this._project.deleteFile(this.path());
178 },
179
180 /**
181 * @param {string} name
182 * @param {string} url
183 * @param {string} originURL
184 * @param {!WebInspector.ResourceType=} contentType
185 */
186 _updateName: function(name, url, originURL, contentType)
187 {
188 var oldURI = this.uri();
189 this._name = name;
190 if (url)
191 this._url = url;
192 if (originURL)
193 this._originURL = originURL;
194 if (contentType)
195 this._contentType = contentType;
196 this.dispatchEventToListeners(WebInspector.UISourceCode.Events.TitleChan ged, oldURI);
197 },
198
199 /**
200 * @return {string}
201 */
202 contentURL: function()
203 {
204 return this.originURL();
205 },
206
207 /**
208 * @return {!WebInspector.ResourceType}
209 */
210 contentType: function()
211 {
212 return this._contentType;
213 },
214
215 /**
216 * @return {!WebInspector.Project}
217 */
218 project: function()
219 {
220 return this._project;
221 },
222
223 /**
224 * @param {function(?Date, ?number)} callback
225 */
226 requestMetadata: function(callback)
227 {
228 this._project.requestMetadata(this, callback);
229 },
230
231 /**
232 * @param {function(?string)} callback
233 */
234 requestContent: function(callback)
235 {
236 if (this._content || this._contentLoaded) {
237 callback(this._content);
238 return;
239 }
240 this._requestContentCallbacks.push(callback);
241 if (this._requestContentCallbacks.length === 1)
242 this._project.requestFileContent(this, this._fireContentAvailable.bi nd(this));
243 },
244
245 /**
246 * @param {function()} callback
247 */
248 _pushCheckContentUpdatedCallback: function(callback)
249 {
250 if (!this._checkContentUpdatedCallbacks)
251 this._checkContentUpdatedCallbacks = [];
252 this._checkContentUpdatedCallbacks.push(callback);
253 },
254
255 _terminateContentCheck: function()
256 {
257 delete this._checkingContent;
258 if (this._checkContentUpdatedCallbacks) {
259 this._checkContentUpdatedCallbacks.forEach(function(callback) { call back(); });
260 delete this._checkContentUpdatedCallbacks;
261 }
262 },
263
264 /**
265 * @param {function()=} callback
266 */
267 checkContentUpdated: function(callback)
268 {
269 callback = callback || function() {};
270 if (!this._project.canSetFileContent()) {
271 callback();
272 return;
273 }
274 this._pushCheckContentUpdatedCallback(callback);
275
276 if (this._checkingContent) {
277 return;
278 }
279 this._checkingContent = true;
280 this._project.requestFileContent(this, contentLoaded.bind(this));
281
282 /**
283 * @param {?string} updatedContent
284 * @this {WebInspector.UISourceCode}
285 */
286 function contentLoaded(updatedContent)
287 {
288 if (updatedContent === null) {
289 var workingCopy = this.workingCopy();
290 this._commitContent("", false);
291 this.setWorkingCopy(workingCopy);
292 this._terminateContentCheck();
293 return;
294 }
295 if (typeof this._lastAcceptedContent === "string" && this._lastAccep tedContent === updatedContent) {
296 this._terminateContentCheck();
297 return;
298 }
299 if (this._content === updatedContent) {
300 delete this._lastAcceptedContent;
301 this._terminateContentCheck();
302 return;
303 }
304
305 if (!this.isDirty()) {
306 this._commitContent(updatedContent, false);
307 this._terminateContentCheck();
308 return;
309 }
310
311 var shouldUpdate = window.confirm(WebInspector.UIString("This file w as changed externally. Would you like to reload it?"));
312 if (shouldUpdate)
313 this._commitContent(updatedContent, false);
314 else
315 this._lastAcceptedContent = updatedContent;
316 this._terminateContentCheck();
317 }
318 },
319
320 /**
321 * @param {function(?string)} callback
322 */
323 requestOriginalContent: function(callback)
324 {
325 this._project.requestFileContent(this, callback);
326 },
327
328 /**
329 * @param {string} content
330 * @param {boolean} shouldSetContentInProject
331 */
332 _commitContent: function(content, shouldSetContentInProject)
333 {
334 delete this._lastAcceptedContent;
335 this._content = content;
336 this._contentLoaded = true;
337
338 var lastRevision = this.history.length ? this.history[this.history.lengt h - 1] : null;
339 if (!lastRevision || lastRevision._content !== this._content) {
340 var revision = new WebInspector.Revision(this, this._content, new Da te());
341 this.history.push(revision);
342 }
343
344 this._innerResetWorkingCopy();
345 this._hasCommittedChanges = true;
346 this.dispatchEventToListeners(WebInspector.UISourceCode.Events.WorkingCo pyCommitted);
347 if (this._url && WebInspector.fileManager.isURLSaved(this._url))
348 this._saveURLWithFileManager(false, this._content);
349 if (shouldSetContentInProject)
350 this._project.setFileContent(this, this._content, function() { });
351 },
352
353 /**
354 * @param {boolean} forceSaveAs
355 * @param {?string} content
356 */
357 _saveURLWithFileManager: function(forceSaveAs, content)
358 {
359 WebInspector.fileManager.save(this._url, /** @type {string} */ (content) , forceSaveAs, callback.bind(this));
360 WebInspector.fileManager.close(this._url);
361
362 /**
363 * @param {boolean} accepted
364 * @this {WebInspector.UISourceCode}
365 */
366 function callback(accepted)
367 {
368 if (!accepted)
369 return;
370 this._savedWithFileManager = true;
371 this.dispatchEventToListeners(WebInspector.UISourceCode.Events.Saved StateUpdated);
372 }
373 },
374
375 /**
376 * @param {boolean} forceSaveAs
377 */
378 save: function(forceSaveAs)
379 {
380 if (this.project().type() === WebInspector.projectTypes.FileSystem || th is.project().type() === WebInspector.projectTypes.Snippets) {
381 this.commitWorkingCopy();
382 return;
383 }
384 if (this.isDirty()) {
385 this._saveURLWithFileManager(forceSaveAs, this.workingCopy());
386 this.commitWorkingCopy();
387 return;
388 }
389 this.requestContent(this._saveURLWithFileManager.bind(this, forceSaveAs) );
390 },
391
392 /**
393 * @return {boolean}
394 */
395 hasUnsavedCommittedChanges: function()
396 {
397 if (this._savedWithFileManager || this.project().canSetFileContent() || this._project.isServiceProject())
398 return false;
399 if (this._project.workspace().hasResourceContentTrackingExtensions())
400 return false;
401 return !!this._hasCommittedChanges;
402 },
403
404 /**
405 * @param {string} content
406 */
407 addRevision: function(content)
408 {
409 this._commitContent(content, true);
410 },
411
412 revertToOriginal: function()
413 {
414 /**
415 * @this {WebInspector.UISourceCode}
416 * @param {?string} content
417 */
418 function callback(content)
419 {
420 if (typeof content !== "string")
421 return;
422
423 this.addRevision(content);
424 }
425
426 this.requestOriginalContent(callback.bind(this));
427 },
428
429 /**
430 * @param {function(!WebInspector.UISourceCode)} callback
431 */
432 revertAndClearHistory: function(callback)
433 {
434 /**
435 * @this {WebInspector.UISourceCode}
436 * @param {?string} content
437 */
438 function revert(content)
439 {
440 if (typeof content !== "string")
441 return;
442
443 this.addRevision(content);
444 this.history = [];
445 callback(this);
446 }
447
448 this.requestOriginalContent(revert.bind(this));
449 },
450
451 /**
452 * @return {string}
453 */
454 workingCopy: function()
455 {
456 if (this._workingCopyGetter) {
457 this._workingCopy = this._workingCopyGetter();
458 delete this._workingCopyGetter;
459 }
460 if (this.isDirty())
461 return this._workingCopy;
462 return this._content;
463 },
464
465 resetWorkingCopy: function()
466 {
467 this._innerResetWorkingCopy();
468 this.dispatchEventToListeners(WebInspector.UISourceCode.Events.WorkingCo pyChanged);
469 },
470
471 _innerResetWorkingCopy: function()
472 {
473 delete this._workingCopy;
474 delete this._workingCopyGetter;
475 },
476
477 /**
478 * @param {string} newWorkingCopy
479 */
480 setWorkingCopy: function(newWorkingCopy)
481 {
482 this._workingCopy = newWorkingCopy;
483 delete this._workingCopyGetter;
484 this.dispatchEventToListeners(WebInspector.UISourceCode.Events.WorkingCo pyChanged);
485 },
486
487 setWorkingCopyGetter: function(workingCopyGetter)
488 {
489 this._workingCopyGetter = workingCopyGetter;
490 this.dispatchEventToListeners(WebInspector.UISourceCode.Events.WorkingCo pyChanged);
491 },
492
493 removeWorkingCopyGetter: function()
494 {
495 if (!this._workingCopyGetter)
496 return;
497 this._workingCopy = this._workingCopyGetter();
498 delete this._workingCopyGetter;
499 },
500
501 commitWorkingCopy: function()
502 {
503 if (this.isDirty())
504 this._commitContent(this.workingCopy(), true);
505 },
506
507 /**
508 * @return {boolean}
509 */
510 isDirty: function()
511 {
512 return typeof this._workingCopy !== "undefined" || typeof this._workingC opyGetter !== "undefined";
513 },
514
515 /**
516 * @return {string}
517 */
518 highlighterType: function()
519 {
520 var lastIndexOfDot = this._name.lastIndexOf(".");
521 var extension = lastIndexOfDot !== -1 ? this._name.substr(lastIndexOfDot + 1) : "";
522 var indexOfQuestionMark = extension.indexOf("?");
523 if (indexOfQuestionMark !== -1)
524 extension = extension.substr(0, indexOfQuestionMark);
525 var mimeType = WebInspector.ResourceType.mimeTypesForExtensions[extensio n.toLowerCase()];
526 return mimeType || this.contentType().canonicalMimeType();
527 },
528
529 /**
530 * @return {?string}
531 */
532 content: function()
533 {
534 return this._content;
535 },
536
537 /**
538 * @param {string} query
539 * @param {boolean} caseSensitive
540 * @param {boolean} isRegex
541 * @param {function(!Array.<!WebInspector.ContentProvider.SearchMatch>)} cal lback
542 */
543 searchInContent: function(query, caseSensitive, isRegex, callback)
544 {
545 var content = this.content();
546 if (content) {
547 var provider = new WebInspector.StaticContentProvider(this.contentTy pe(), content);
548 provider.searchInContent(query, caseSensitive, isRegex, callback);
549 return;
550 }
551
552 this._project.searchInFileContent(this, query, caseSensitive, isRegex, c allback);
553 },
554
555 /**
556 * @param {?string} content
557 */
558 _fireContentAvailable: function(content)
559 {
560 this._contentLoaded = true;
561 this._content = content;
562
563 var callbacks = this._requestContentCallbacks.slice();
564 this._requestContentCallbacks = [];
565 for (var i = 0; i < callbacks.length; ++i)
566 callbacks[i](content);
567 },
568
569 /**
570 * @return {boolean}
571 */
572 contentLoaded: function()
573 {
574 return this._contentLoaded;
575 },
576
577 /**
578 * @return {!Array.<!WebInspector.PresentationConsoleMessage>}
579 */
580 consoleMessages: function()
581 {
582 return this._consoleMessages;
583 },
584
585 /**
586 * @param {!WebInspector.PresentationConsoleMessage} message
587 */
588 consoleMessageAdded: function(message)
589 {
590 this._consoleMessages.push(message);
591 this.dispatchEventToListeners(WebInspector.UISourceCode.Events.ConsoleMe ssageAdded, message);
592 },
593
594 /**
595 * @param {!WebInspector.PresentationConsoleMessage} message
596 */
597 consoleMessageRemoved: function(message)
598 {
599 this._consoleMessages.remove(message);
600 this.dispatchEventToListeners(WebInspector.UISourceCode.Events.ConsoleMe ssageRemoved, message);
601 },
602
603 consoleMessagesCleared: function()
604 {
605 this._consoleMessages = [];
606 this.dispatchEventToListeners(WebInspector.UISourceCode.Events.ConsoleMe ssagesCleared);
607 },
608
609 /**
610 * @param {number} lineNumber
611 * @param {number=} columnNumber
612 * @return {!WebInspector.UILocation}
613 */
614 uiLocation: function(lineNumber, columnNumber)
615 {
616 if (typeof columnNumber === "undefined")
617 columnNumber = 0;
618 return new WebInspector.UILocation(this, lineNumber, columnNumber);
619 },
620
621 __proto__: WebInspector.Object.prototype
622 }
623
624 /**
625 * @constructor
626 * @param {!WebInspector.UISourceCode} uiSourceCode
627 * @param {number} lineNumber
628 * @param {number} columnNumber
629 */
630 WebInspector.UILocation = function(uiSourceCode, lineNumber, columnNumber)
631 {
632 this.uiSourceCode = uiSourceCode;
633 this.lineNumber = lineNumber;
634 this.columnNumber = columnNumber;
635 }
636
637 WebInspector.UILocation.prototype = {
638 /**
639 * @return {string}
640 */
641 linkText: function()
642 {
643 var linkText = this.uiSourceCode.displayName();
644 if (typeof this.lineNumber === "number")
645 linkText += ":" + (this.lineNumber + 1);
646 return linkText;
647 },
648
649 /**
650 * @return {string}
651 */
652 id: function()
653 {
654 return this.uiSourceCode.uri() + ":" + this.lineNumber + ":" + this.colu mnNumber;
655 },
656 }
657
658 /**
659 * @interface
660 */
661 WebInspector.RawLocation = function()
662 {
663 }
664
665 /**
666 * @constructor
667 * @param {!WebInspector.RawLocation} rawLocation
668 * @param {function(!WebInspector.UILocation):(boolean|undefined)} updateDelegat e
669 */
670 WebInspector.LiveLocation = function(rawLocation, updateDelegate)
671 {
672 this._rawLocation = rawLocation;
673 this._updateDelegate = updateDelegate;
674 }
675
676 WebInspector.LiveLocation.prototype = {
677 update: function()
678 {
679 var uiLocation = this.uiLocation();
680 if (!uiLocation)
681 return;
682 if (this._updateDelegate(uiLocation))
683 this.dispose();
684 },
685
686 /**
687 * @return {!WebInspector.RawLocation}
688 */
689 rawLocation: function()
690 {
691 return this._rawLocation;
692 },
693
694 /**
695 * @return {!WebInspector.UILocation}
696 */
697 uiLocation: function()
698 {
699 throw "Not implemented";
700 },
701
702 dispose: function()
703 {
704 // Overridden by subclasses.
705 }
706 }
707
708 /**
709 * @constructor
710 * @implements {WebInspector.ContentProvider}
711 * @param {!WebInspector.UISourceCode} uiSourceCode
712 * @param {?string|undefined} content
713 * @param {!Date} timestamp
714 */
715 WebInspector.Revision = function(uiSourceCode, content, timestamp)
716 {
717 this._uiSourceCode = uiSourceCode;
718 this._content = content;
719 this._timestamp = timestamp;
720 }
721
722 WebInspector.Revision.prototype = {
723 /**
724 * @return {!WebInspector.UISourceCode}
725 */
726 get uiSourceCode()
727 {
728 return this._uiSourceCode;
729 },
730
731 /**
732 * @return {!Date}
733 */
734 get timestamp()
735 {
736 return this._timestamp;
737 },
738
739 /**
740 * @return {?string}
741 */
742 get content()
743 {
744 return this._content || null;
745 },
746
747 revertToThis: function()
748 {
749 /**
750 * @param {string} content
751 * @this {WebInspector.Revision}
752 */
753 function revert(content)
754 {
755 if (this._uiSourceCode._content !== content)
756 this._uiSourceCode.addRevision(content);
757 }
758 this.requestContent(revert.bind(this));
759 },
760
761 /**
762 * @return {string}
763 */
764 contentURL: function()
765 {
766 return this._uiSourceCode.originURL();
767 },
768
769 /**
770 * @return {!WebInspector.ResourceType}
771 */
772 contentType: function()
773 {
774 return this._uiSourceCode.contentType();
775 },
776
777 /**
778 * @param {function(string)} callback
779 */
780 requestContent: function(callback)
781 {
782 callback(this._content || "");
783 },
784
785 /**
786 * @param {string} query
787 * @param {boolean} caseSensitive
788 * @param {boolean} isRegex
789 * @param {function(!Array.<!WebInspector.ContentProvider.SearchMatch>)} cal lback
790 */
791 searchInContent: function(query, caseSensitive, isRegex, callback)
792 {
793 callback([]);
794 }
795 }
OLDNEW
« no previous file with comments | « Source/devtools/front_end/sdk/TempFile.js ('k') | Source/devtools/front_end/sdk/Workspace.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698