Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 /** | |
| 6 * @constructor | |
| 7 * @extends {WebInspector.Object} | |
| 8 * @param {!WebInspector.Workspace} workspace | |
| 9 * @param {!WebInspector.BreakpointManager} breakpointManager | |
| 10 * @param {!WebInspector.FileSystemMapping} fileSystemMapping | |
| 11 */ | |
| 12 WebInspector.Persistence = function(workspace, breakpointManager, fileSystemMapp ing) | |
| 13 { | |
| 14 WebInspector.Object.call(this); | |
| 15 this._workspace = workspace; | |
| 16 this._breakpointManager = breakpointManager; | |
| 17 this._fileSystemMapping = fileSystemMapping; | |
| 18 /** @type {!Set<!WebInspector.PersistenceBinding>} */ | |
| 19 this._bindings = new Set(); | |
| 20 this._eventListeners = [ | |
| 21 workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeAdd ed, this._onUISourceCodeAdded, this), | |
| 22 workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeRem oved, this._onUISourceCodeRemoved, this), | |
| 23 workspace.addEventListener(WebInspector.Workspace.Events.ProjectRemoved, this._onProjectRemoved, this), | |
| 24 this._fileSystemMapping.addEventListener(WebInspector.FileSystemMapping. Events.FileMappingAdded, this._remap, this), | |
| 25 this._fileSystemMapping.addEventListener(WebInspector.FileSystemMapping. Events.FileMappingRemoved, this._remap, this) | |
| 26 ]; | |
| 27 this._remap(); | |
| 28 } | |
| 29 | |
| 30 WebInspector.Persistence._binding = Symbol("Persistence.Binding"); | |
| 31 WebInspector.Persistence._muteCommit = Symbol("Persistence.MuteCommit"); | |
| 32 | |
| 33 WebInspector.Persistence._NodePrefix = "(function (exports, require, module, __f ilename, __dirname) { "; | |
| 34 WebInspector.Persistence._NodeSuffix = "\n});" | |
| 35 WebInspector.Persistence._NodeShebang = "#!/usr/bin/env node\n"; | |
| 36 | |
| 37 WebInspector.Persistence.Events = { | |
| 38 BindingCreated: Symbol("BindingCreated"), | |
| 39 BindingRemoved: Symbol("BindingRemoved") | |
| 40 } | |
| 41 | |
| 42 WebInspector.Persistence.prototype = { | |
| 43 _remap: function() | |
| 44 { | |
| 45 for (var binding of this._bindings.valuesArray()) | |
| 46 this._unbind(binding.network); | |
| 47 var networkProjects = this._workspace.projectsForType(WebInspector.proje ctTypes.Network); | |
| 48 for (var networkProject of networkProjects) { | |
| 49 for (var uiSourceCode of networkProject.uiSourceCodes()) | |
| 50 this._bind(uiSourceCode); | |
| 51 } | |
| 52 }, | |
| 53 | |
| 54 /** | |
| 55 * @param {!WebInspector.Event} event | |
| 56 */ | |
| 57 _onUISourceCodeAdded: function(event) | |
| 58 { | |
| 59 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */(event.data) ; | |
| 60 this._bind(uiSourceCode); | |
| 61 }, | |
| 62 | |
| 63 /** | |
| 64 * @param {!WebInspector.Event} event | |
| 65 */ | |
| 66 _onUISourceCodeRemoved: function(event) | |
| 67 { | |
| 68 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */(event.data) ; | |
| 69 this._unbind(uiSourceCode); | |
| 70 }, | |
| 71 | |
| 72 /** | |
| 73 * @param {!WebInspector.Event} event | |
| 74 */ | |
| 75 _onProjectRemoved: function(event) | |
| 76 { | |
| 77 var project = /** @type {!WebInspector.Project} */(event.data); | |
| 78 for (var uiSourceCode of project.uiSourceCodes()) | |
| 79 this._unbind(uiSourceCode); | |
| 80 }, | |
| 81 | |
| 82 /** | |
| 83 * @param {!WebInspector.UISourceCode} uiSourceCode | |
| 84 * @return {?WebInspector.PersistenceBinding} | |
| 85 */ | |
| 86 _createBinding: function(uiSourceCode) | |
| 87 { | |
| 88 if (uiSourceCode.project().type() === WebInspector.projectTypes.FileSyst em) { | |
| 89 var fileSystemPath = WebInspector.FileSystemWorkspaceBinding.fileSys temPath(uiSourceCode.project().id()); | |
| 90 var networkURL = this._fileSystemMapping.networkURLForFileSystemURL( fileSystemPath, uiSourceCode.url()); | |
| 91 var networkSourceCode = networkURL ? this._workspace.uiSourceCodeFor URL(networkURL) : null; | |
| 92 return networkSourceCode ? new WebInspector.PersistenceBinding(netwo rkSourceCode, uiSourceCode) : null; | |
| 93 } | |
| 94 if (uiSourceCode.project().type() === WebInspector.projectTypes.Network) { | |
| 95 var file = this._fileSystemMapping.fileForURL(uiSourceCode.url()); | |
| 96 var projectId = file ? WebInspector.FileSystemWorkspaceBinding.proje ctId(file.fileSystemPath) : null; | |
| 97 var fileSourceCode = file && projectId ? this._workspace.uiSourceCod e(projectId, file.fileURL) : null; | |
| 98 return fileSourceCode ? new WebInspector.PersistenceBinding(uiSource Code, fileSourceCode) : null; | |
| 99 } | |
| 100 return null; | |
| 101 }, | |
| 102 | |
| 103 /** | |
| 104 * @param {!WebInspector.UISourceCode} uiSourceCode | |
| 105 */ | |
| 106 _bind: function(uiSourceCode) | |
| 107 { | |
| 108 console.assert(!uiSourceCode[WebInspector.Persistence._binding], "Cannot bind already bound UISourceCode!"); | |
| 109 var binding = this._createBinding(uiSourceCode); | |
| 110 if (!binding) | |
| 111 return; | |
| 112 if (binding.network.isDirty() || binding.fileSystem.isDirty()) { | |
| 113 WebInspector.console.log(WebInspector.UIString("Failed to map %s. Sa ve your changes and reload page.", binding.network.name())); | |
|
dgozman
2016/09/23 23:03:21
"%s can not be persisted to file system due to uns
lushnikov
2016/09/24 00:30:50
Done.
| |
| 114 return; | |
| 115 } | |
| 116 this._bindings.add(binding); | |
| 117 binding.network[WebInspector.Persistence._binding] = binding; | |
| 118 binding.fileSystem[WebInspector.Persistence._binding] = binding; | |
| 119 | |
| 120 binding.fileSystem.forceLoadOnCheckContent(); | |
| 121 | |
| 122 binding.network.addEventListener(WebInspector.UISourceCode.Events.Workin gCopyCommitted, this._onWorkingCopyCommitted, this); | |
| 123 binding.fileSystem.addEventListener(WebInspector.UISourceCode.Events.Wor kingCopyCommitted, this._onWorkingCopyCommitted, this); | |
| 124 binding.fileSystem.addEventListener(WebInspector.UISourceCode.Events.Tit leChanged, this._onFileSystemUISourceCodeRenamed, this); | |
| 125 | |
| 126 this._moveBreakpoints(binding.fileSystem, binding.network); | |
| 127 this.dispatchEventToListeners(WebInspector.Persistence.Events.BindingCre ated, binding); | |
| 128 }, | |
| 129 | |
| 130 /** | |
| 131 * @param {!WebInspector.UISourceCode} uiSourceCode | |
| 132 */ | |
| 133 _unbind: function(uiSourceCode) | |
| 134 { | |
| 135 var binding = uiSourceCode[WebInspector.Persistence._binding]; | |
| 136 if (!binding) | |
| 137 return; | |
| 138 this._bindings.delete(binding); | |
| 139 binding.network[WebInspector.Persistence._binding] = null; | |
| 140 binding.fileSystem[WebInspector.Persistence._binding] = null; | |
| 141 | |
| 142 binding.network.removeEventListener(WebInspector.UISourceCode.Events.Wor kingCopyCommitted, this._onWorkingCopyCommitted, this); | |
| 143 binding.fileSystem.removeEventListener(WebInspector.UISourceCode.Events. WorkingCopyCommitted, this._onWorkingCopyCommitted, this); | |
| 144 binding.fileSystem.removeEventListener(WebInspector.UISourceCode.Events. TitleChanged, this._onFileSystemUISourceCodeRenamed, this); | |
| 145 | |
| 146 this._copyBreakpoints(binding.network, binding.fileSystem); | |
| 147 this.dispatchEventToListeners(WebInspector.Persistence.Events.BindingRem oved, binding); | |
| 148 }, | |
| 149 | |
| 150 /** | |
| 151 * @param {!WebInspector.Event} event | |
| 152 */ | |
| 153 _onFileSystemUISourceCodeRenamed: function(event) | |
| 154 { | |
| 155 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */(event.targe t); | |
| 156 var binding = uiSourceCode[WebInspector.Persistence._binding]; | |
| 157 this._unbind(binding.network); | |
| 158 this._bind(binding.network); | |
| 159 }, | |
| 160 | |
| 161 /** | |
| 162 * @param {!WebInspector.Event} event | |
| 163 */ | |
| 164 _onWorkingCopyCommitted: function(event) | |
| 165 { | |
| 166 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */(event.targe t); | |
| 167 var binding = uiSourceCode[WebInspector.Persistence._binding]; | |
| 168 if (!binding || binding[WebInspector.Persistence._muteCommit]) | |
| 169 return; | |
| 170 var newContent = /** @type {string} */(event.data.content); | |
| 171 var other = binding.network === uiSourceCode ? binding.fileSystem : bind ing.network; | |
| 172 if (Runtime.queryParam("v8only")) { | |
| 173 other.requestContent().then(currentContent => this._syncNodeJSConten t(binding, other, currentContent, newContent)); | |
| 174 return; | |
| 175 } | |
| 176 binding[WebInspector.Persistence._muteCommit] = true; | |
| 177 other.addRevision(newContent); | |
| 178 binding[WebInspector.Persistence._muteCommit] = false; | |
| 179 this._contentSyncedForTest(); | |
| 180 }, | |
| 181 | |
| 182 /** | |
| 183 * @param {!WebInspector.PersistenceBinding} binding | |
| 184 * @param {!WebInspector.UISourceCode} uiSourceCode | |
| 185 * @param {string} currentContent | |
| 186 * @param {string} newContent | |
| 187 */ | |
| 188 _syncNodeJSContent: function(binding, uiSourceCode, currentContent, newConte nt) | |
| 189 { | |
| 190 if (uiSourceCode === binding.fileSystem) { | |
| 191 if (newContent.startsWith(WebInspector.Persistence._NodePrefix) && n ewContent.endsWith(WebInspector.Persistence._NodeSuffix)) | |
| 192 newContent = newContent.substring(WebInspector.Persistence._Node Prefix.length, newContent.length - WebInspector.Persistence._NodeSuffix.length); | |
| 193 if (currentContent.startsWith(WebInspector.Persistence._NodeShebang) ) | |
| 194 newContent = WebInspector.Persistence._NodeShebang + newContent; | |
| 195 } else { | |
| 196 if (newContent.startsWith(WebInspector.Persistence._NodeShebang)) | |
| 197 newContent = newContent.substring(WebInspector.Persistence._Node Shebang.length); | |
| 198 if (currentContent.startsWith(WebInspector.Persistence._NodePrefix) && currentContent.endsWith(WebInspector.Persistence._NodeSuffix)) | |
| 199 newContent = WebInspector.Persistence._NodePrefix + newContent + WebInspector.Persistence._NodeSuffix; | |
| 200 } | |
| 201 binding[WebInspector.Persistence._muteCommit] = true; | |
| 202 uiSourceCode.addRevision(newContent); | |
| 203 binding[WebInspector.Persistence._muteCommit] = false; | |
| 204 this._contentSyncedForTest(); | |
| 205 }, | |
| 206 | |
| 207 _contentSyncedForTest: function() { }, | |
| 208 | |
| 209 /** | |
| 210 * @param {!WebInspector.UISourceCode} from | |
| 211 * @param {!WebInspector.UISourceCode} to | |
| 212 */ | |
| 213 _moveBreakpoints: function(from, to) | |
| 214 { | |
| 215 var breakpoints = this._breakpointManager.breakpointsForUISourceCode(fro m); | |
| 216 for (var breakpoint of breakpoints) { | |
| 217 breakpoint.remove(); | |
| 218 this._breakpointManager.setBreakpoint(to, breakpoint.lineNumber(), b reakpoint.columnNumber(), breakpoint.condition(), breakpoint.enabled()); | |
| 219 } | |
| 220 }, | |
| 221 | |
| 222 /** | |
| 223 * @param {!WebInspector.UISourceCode} from | |
| 224 * @param {!WebInspector.UISourceCode} to | |
| 225 */ | |
| 226 _copyBreakpoints: function(from, to) | |
| 227 { | |
| 228 var breakpoints = this._breakpointManager.breakpointsForUISourceCode(fro m); | |
| 229 for (var breakpoint of breakpoints) | |
| 230 this._breakpointManager.setBreakpoint(to, breakpoint.lineNumber(), b reakpoint.columnNumber(), breakpoint.condition(), breakpoint.enabled()); | |
| 231 }, | |
| 232 | |
| 233 /** | |
| 234 * @param {!WebInspector.UISourceCode} uiSourceCode | |
| 235 * @return {boolean} | |
| 236 */ | |
| 237 hasUnsavedCommittedChanges: function(uiSourceCode) | |
| 238 { | |
| 239 if (this._workspace.hasResourceContentTrackingExtensions()) | |
| 240 return false; | |
| 241 if (uiSourceCode.url() && WebInspector.fileManager.isURLSaved(uiSourceCo de.url())) | |
| 242 return false; | |
| 243 if (uiSourceCode.project().canSetFileContent()) | |
| 244 return false; | |
| 245 if (uiSourceCode[WebInspector.Persistence._binding]) | |
| 246 return false; | |
| 247 return !!uiSourceCode.history.length; | |
| 248 }, | |
| 249 | |
| 250 /** | |
| 251 * @param {!WebInspector.UISourceCode} uiSourceCode | |
| 252 * @return {?WebInspector.PersistenceBinding} | |
| 253 */ | |
| 254 binding: function(uiSourceCode) | |
| 255 { | |
| 256 return uiSourceCode[WebInspector.Persistence._binding] || null; | |
| 257 }, | |
| 258 | |
| 259 dispose: function() | |
| 260 { | |
| 261 WebInspector.EventTarget.removeEventListeners(this._eventListeners); | |
| 262 }, | |
| 263 | |
| 264 __proto__: WebInspector.Object.prototype | |
| 265 } | |
| 266 | |
| 267 /** | |
| 268 * @constructor | |
| 269 * @param {!WebInspector.UISourceCode} network | |
| 270 * @param {!WebInspector.UISourceCode} fileSystem | |
| 271 */ | |
| 272 WebInspector.PersistenceBinding = function(network, fileSystem) | |
| 273 { | |
| 274 this.network = network; | |
| 275 this.fileSystem = fileSystem; | |
| 276 } | |
| 277 | |
| 278 /** @type {!WebInspector.Persistence} */ | |
| 279 WebInspector.persistence; | |
| OLD | NEW |