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("%s can not be persis
ted to file system due to unsaved changes.", binding.network.name())); |
| 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 |