| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 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 * @implements {WebInspector.TargetManager.Observer} | |
| 8 */ | |
| 9 WebInspector.CSSWorkspaceBinding = function() | |
| 10 { | |
| 11 /** @type {!Map.<!WebInspector.Target, !WebInspector.CSSWorkspaceBinding.Tar
getInfo>} */ | |
| 12 this._targetToTargetInfo = new Map(); | |
| 13 WebInspector.targetManager.observeTargets(this); | |
| 14 | |
| 15 WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel,
WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameCre
atedOrNavigated, this); | |
| 16 } | |
| 17 | |
| 18 WebInspector.CSSWorkspaceBinding.prototype = { | |
| 19 /** | |
| 20 * @param {!WebInspector.Target} target | |
| 21 */ | |
| 22 targetAdded: function(target) | |
| 23 { | |
| 24 this._targetToTargetInfo.put(target, new WebInspector.CSSWorkspaceBindin
g.TargetInfo(target, WebInspector.workspace, WebInspector.networkWorkspaceBindin
g)); | |
| 25 }, | |
| 26 | |
| 27 /** | |
| 28 * @param {!WebInspector.Target} target | |
| 29 */ | |
| 30 targetRemoved: function(target) | |
| 31 { | |
| 32 this._targetToTargetInfo.remove(target)._dispose(); | |
| 33 }, | |
| 34 | |
| 35 /** | |
| 36 * @param {!WebInspector.CSSStyleSheetHeader} header | |
| 37 * @param {!WebInspector.SourceMapping} mapping | |
| 38 */ | |
| 39 pushSourceMapping: function(header, mapping) | |
| 40 { | |
| 41 this._ensureInfoForHeader(header)._pushSourceMapping(mapping); | |
| 42 }, | |
| 43 | |
| 44 /** | |
| 45 * @param {!WebInspector.CSSStyleSheetHeader} header | |
| 46 * @return {?WebInspector.CSSWorkspaceBinding.HeaderInfo} | |
| 47 */ | |
| 48 _headerInfo: function(header) | |
| 49 { | |
| 50 var map = this._targetToTargetInfo.get(header.target()); | |
| 51 return map._headerInfo(header.id) || null; | |
| 52 }, | |
| 53 | |
| 54 /** | |
| 55 * @param {!WebInspector.CSSStyleSheetHeader} header | |
| 56 * @return {!WebInspector.CSSWorkspaceBinding.HeaderInfo} | |
| 57 */ | |
| 58 _ensureInfoForHeader: function(header) | |
| 59 { | |
| 60 var targetInfo = this._targetToTargetInfo.get(header.target()); | |
| 61 if (!targetInfo) { | |
| 62 targetInfo = new WebInspector.CSSWorkspaceBinding.TargetInfo(header.
target(), WebInspector.workspace, WebInspector.networkWorkspaceBinding); | |
| 63 this._targetToTargetInfo.put(header.target(), targetInfo); | |
| 64 } | |
| 65 return targetInfo._ensureInfoForHeader(header); | |
| 66 }, | |
| 67 | |
| 68 /** | |
| 69 * @param {!WebInspector.Event} event | |
| 70 */ | |
| 71 _mainFrameCreatedOrNavigated: function(event) | |
| 72 { | |
| 73 var target = /** @type {!WebInspector.ResourceTreeModel} */ (event.targe
t).target(); | |
| 74 this._targetToTargetInfo.get(target)._reset(); | |
| 75 }, | |
| 76 | |
| 77 /** | |
| 78 * @param {!WebInspector.CSSStyleSheetHeader} header | |
| 79 */ | |
| 80 updateLocations: function(header) | |
| 81 { | |
| 82 var info = this._headerInfo(header); | |
| 83 if (info) | |
| 84 info._updateLocations(); | |
| 85 }, | |
| 86 | |
| 87 /** | |
| 88 * @param {!WebInspector.CSSLocation} rawLocation | |
| 89 * @param {function(!WebInspector.UILocation):(boolean|undefined)} updateDel
egate | |
| 90 * @return {!WebInspector.CSSWorkspaceBinding.LiveLocation} | |
| 91 */ | |
| 92 createLiveLocation: function(rawLocation, updateDelegate) | |
| 93 { | |
| 94 var header = rawLocation.styleSheetId ? rawLocation.target().cssModel.st
yleSheetHeaderForId(rawLocation.styleSheetId) : null; | |
| 95 return new WebInspector.CSSWorkspaceBinding.LiveLocation(rawLocation.tar
get().cssModel, header, rawLocation, updateDelegate); | |
| 96 }, | |
| 97 | |
| 98 /** | |
| 99 * @param {!WebInspector.CSSWorkspaceBinding.LiveLocation} location | |
| 100 */ | |
| 101 _addLiveLocation: function(location) | |
| 102 { | |
| 103 this._ensureInfoForHeader(location._header)._addLocation(location); | |
| 104 }, | |
| 105 | |
| 106 /** | |
| 107 * @param {!WebInspector.CSSWorkspaceBinding.LiveLocation} location | |
| 108 */ | |
| 109 _removeLiveLocation: function(location) | |
| 110 { | |
| 111 var info = this._headerInfo(location._header); | |
| 112 if (info) | |
| 113 info._removeLocation(location); | |
| 114 }, | |
| 115 | |
| 116 /** | |
| 117 * @param {!WebInspector.CSSProperty} cssProperty | |
| 118 * @param {boolean} forName | |
| 119 * @return {?WebInspector.UILocation} | |
| 120 */ | |
| 121 propertyUILocation: function(cssProperty, forName) | |
| 122 { | |
| 123 var style = cssProperty.ownerStyle; | |
| 124 if (!style || !style.parentRule || !style.styleSheetId) | |
| 125 return null; | |
| 126 | |
| 127 var range = cssProperty.range; | |
| 128 if (!range) | |
| 129 return null; | |
| 130 | |
| 131 var url = style.parentRule.resourceURL(); | |
| 132 if (!url) | |
| 133 return null; | |
| 134 | |
| 135 var line = forName ? range.startLine : range.endLine; | |
| 136 // End of range is exclusive, so subtract 1 from the end offset. | |
| 137 var column = forName ? range.startColumn : range.endColumn - (cssPropert
y.text && cssProperty.text.endsWith(";") ? 2 : 1); | |
| 138 var rawLocation = new WebInspector.CSSLocation(style.target(), style.sty
leSheetId, url, line, column); | |
| 139 return this.rawLocationToUILocation(rawLocation); | |
| 140 }, | |
| 141 | |
| 142 /** | |
| 143 * @param {?WebInspector.CSSLocation} rawLocation | |
| 144 * @return {?WebInspector.UILocation} | |
| 145 */ | |
| 146 rawLocationToUILocation: function(rawLocation) | |
| 147 { | |
| 148 if (!rawLocation) | |
| 149 return null; | |
| 150 var cssModel = rawLocation.target().cssModel; | |
| 151 var frameIdToSheetIds = cssModel.styleSheetIdsByFrameIdForURL(rawLocatio
n.url); | |
| 152 if (!Object.values(frameIdToSheetIds).length) | |
| 153 return null; | |
| 154 var styleSheetIds = []; | |
| 155 for (var frameId in frameIdToSheetIds) | |
| 156 styleSheetIds = styleSheetIds.concat(frameIdToSheetIds[frameId]); | |
| 157 var uiLocation; | |
| 158 for (var i = 0; !uiLocation && i < styleSheetIds.length; ++i) { | |
| 159 var header = cssModel.styleSheetHeaderForId(styleSheetIds[i]); | |
| 160 if (!header) | |
| 161 continue; | |
| 162 var info = this._headerInfo(header); | |
| 163 if (info) | |
| 164 uiLocation = info._rawLocationToUILocation(rawLocation.lineNumbe
r, rawLocation.columnNumber); | |
| 165 } | |
| 166 return uiLocation || null; | |
| 167 } | |
| 168 } | |
| 169 | |
| 170 /** | |
| 171 * @constructor | |
| 172 * @param {!WebInspector.Target} target | |
| 173 * @param {!WebInspector.Workspace} workspace | |
| 174 * @param {!WebInspector.NetworkWorkspaceBinding} networkWorkspaceBinding | |
| 175 */ | |
| 176 WebInspector.CSSWorkspaceBinding.TargetInfo = function(target, workspace, networ
kWorkspaceBinding) | |
| 177 { | |
| 178 this._target = target; | |
| 179 this._workspace = workspace; | |
| 180 | |
| 181 var cssModel = target.cssModel; | |
| 182 this._stylesSourceMapping = new WebInspector.StylesSourceMapping(cssModel, w
orkspace); | |
| 183 this._sassSourceMapping = new WebInspector.SASSSourceMapping(cssModel, works
pace, networkWorkspaceBinding); | |
| 184 | |
| 185 /** @type {!StringMap.<!WebInspector.CSSWorkspaceBinding.HeaderInfo>} */ | |
| 186 this._headerInfoById = new StringMap(); | |
| 187 | |
| 188 cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded,
this._styleSheetAdded, this); | |
| 189 cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetRemove
d, this._styleSheetRemoved, this); | |
| 190 } | |
| 191 | |
| 192 WebInspector.CSSWorkspaceBinding.TargetInfo.prototype = { | |
| 193 /** | |
| 194 * @param {!WebInspector.Event} event | |
| 195 */ | |
| 196 _styleSheetAdded: function(event) | |
| 197 { | |
| 198 var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.dat
a); | |
| 199 this._stylesSourceMapping.addHeader(header); | |
| 200 this._sassSourceMapping.addHeader(header); | |
| 201 }, | |
| 202 | |
| 203 /** | |
| 204 * @param {!WebInspector.Event} event | |
| 205 */ | |
| 206 _styleSheetRemoved: function(event) | |
| 207 { | |
| 208 var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.dat
a); | |
| 209 this._stylesSourceMapping.removeHeader(header); | |
| 210 this._sassSourceMapping.removeHeader(header); | |
| 211 this._headerInfoById.remove(header.id); | |
| 212 }, | |
| 213 | |
| 214 /** | |
| 215 * @param {!CSSAgent.StyleSheetId} id | |
| 216 */ | |
| 217 _headerInfo: function(id) | |
| 218 { | |
| 219 return this._headerInfoById.get(id); | |
| 220 }, | |
| 221 | |
| 222 _ensureInfoForHeader: function(header) | |
| 223 { | |
| 224 var info = this._headerInfoById.get(header.id); | |
| 225 if (!info) { | |
| 226 info = new WebInspector.CSSWorkspaceBinding.HeaderInfo(header); | |
| 227 this._headerInfoById.put(header.id, info); | |
| 228 } | |
| 229 return info; | |
| 230 }, | |
| 231 | |
| 232 _dispose: function() | |
| 233 { | |
| 234 this._reset(); | |
| 235 this._target.cssModel.removeEventListener(WebInspector.CSSStyleModel.Eve
nts.StyleSheetAdded, this._styleSheetAdded, this); | |
| 236 this._target.cssModel.removeEventListener(WebInspector.CSSStyleModel.Eve
nts.StyleSheetRemoved, this._styleSheetRemoved, this); | |
| 237 }, | |
| 238 | |
| 239 _reset: function() | |
| 240 { | |
| 241 this._headerInfoById.clear(); | |
| 242 } | |
| 243 } | |
| 244 | |
| 245 /** | |
| 246 * @constructor | |
| 247 * @param {!WebInspector.CSSStyleSheetHeader} header | |
| 248 */ | |
| 249 WebInspector.CSSWorkspaceBinding.HeaderInfo = function(header) | |
| 250 { | |
| 251 this._header = header; | |
| 252 | |
| 253 /** @type {!Array.<!WebInspector.SourceMapping>} */ | |
| 254 this._sourceMappings = []; | |
| 255 | |
| 256 /** @type {!Set.<!WebInspector.LiveLocation>} */ | |
| 257 this._locations = new Set(); | |
| 258 } | |
| 259 | |
| 260 WebInspector.CSSWorkspaceBinding.HeaderInfo.prototype = { | |
| 261 /** | |
| 262 * @param {!WebInspector.LiveLocation} location | |
| 263 */ | |
| 264 _addLocation: function(location) | |
| 265 { | |
| 266 this._locations.add(location); | |
| 267 location.update(); | |
| 268 }, | |
| 269 | |
| 270 /** | |
| 271 * @param {!WebInspector.LiveLocation} location | |
| 272 */ | |
| 273 _removeLocation: function(location) | |
| 274 { | |
| 275 this._locations.remove(location); | |
| 276 }, | |
| 277 | |
| 278 _updateLocations: function() | |
| 279 { | |
| 280 var items = this._locations.values(); | |
| 281 for (var i = 0; i < items.length; ++i) | |
| 282 items[i].update(); | |
| 283 }, | |
| 284 | |
| 285 /** | |
| 286 * @param {number} lineNumber | |
| 287 * @param {number=} columnNumber | |
| 288 * @return {?WebInspector.UILocation} | |
| 289 */ | |
| 290 _rawLocationToUILocation: function(lineNumber, columnNumber) | |
| 291 { | |
| 292 var uiLocation = null; | |
| 293 var rawLocation = new WebInspector.CSSLocation(this._header.target(), th
is._header.id, this._header.resourceURL(), lineNumber, columnNumber); | |
| 294 for (var i = this._sourceMappings.length - 1; !uiLocation && i >= 0; --i
) | |
| 295 uiLocation = this._sourceMappings[i].rawLocationToUILocation(rawLoca
tion); | |
| 296 return uiLocation; | |
| 297 }, | |
| 298 | |
| 299 /** | |
| 300 * @param {!WebInspector.SourceMapping} sourceMapping | |
| 301 */ | |
| 302 _pushSourceMapping: function(sourceMapping) | |
| 303 { | |
| 304 this._sourceMappings.push(sourceMapping); | |
| 305 this._updateLocations(); | |
| 306 } | |
| 307 } | |
| 308 | |
| 309 /** | |
| 310 * @constructor | |
| 311 * @extends {WebInspector.LiveLocation} | |
| 312 * @param {!WebInspector.CSSStyleModel} cssModel | |
| 313 * @param {?WebInspector.CSSStyleSheetHeader} header | |
| 314 * @param {!WebInspector.CSSLocation} rawLocation | |
| 315 * @param {function(!WebInspector.UILocation):(boolean|undefined)} updateDelegat
e | |
| 316 */ | |
| 317 WebInspector.CSSWorkspaceBinding.LiveLocation = function(cssModel, header, rawLo
cation, updateDelegate) | |
| 318 { | |
| 319 WebInspector.LiveLocation.call(this, rawLocation, updateDelegate); | |
| 320 this._cssModel = cssModel; | |
| 321 if (!header) | |
| 322 this._clearStyleSheet(); | |
| 323 else | |
| 324 this._setStyleSheet(header); | |
| 325 } | |
| 326 | |
| 327 WebInspector.CSSWorkspaceBinding.LiveLocation.prototype = { | |
| 328 /** | |
| 329 * @param {!WebInspector.Event} event | |
| 330 */ | |
| 331 _styleSheetAdded: function(event) | |
| 332 { | |
| 333 console.assert(!this._header); | |
| 334 var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.dat
a); | |
| 335 if (header.sourceURL && header.sourceURL === this.rawLocation().url) | |
| 336 this._setStyleSheet(header); | |
| 337 }, | |
| 338 | |
| 339 /** | |
| 340 * @param {!WebInspector.Event} event | |
| 341 */ | |
| 342 _styleSheetRemoved: function(event) | |
| 343 { | |
| 344 console.assert(this._header); | |
| 345 var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.dat
a); | |
| 346 if (this._header !== header) | |
| 347 return; | |
| 348 WebInspector.cssWorkspaceBinding._removeLiveLocation(this); | |
| 349 this._clearStyleSheet(); | |
| 350 }, | |
| 351 | |
| 352 /** | |
| 353 * @param {!WebInspector.CSSStyleSheetHeader} header | |
| 354 */ | |
| 355 _setStyleSheet: function(header) | |
| 356 { | |
| 357 this._header = header; | |
| 358 WebInspector.cssWorkspaceBinding._addLiveLocation(this); | |
| 359 this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.Sty
leSheetAdded, this._styleSheetAdded, this); | |
| 360 this._cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleS
heetRemoved, this._styleSheetRemoved, this); | |
| 361 }, | |
| 362 | |
| 363 _clearStyleSheet: function() | |
| 364 { | |
| 365 delete this._header; | |
| 366 this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.Sty
leSheetRemoved, this._styleSheetRemoved, this); | |
| 367 this._cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleS
heetAdded, this._styleSheetAdded, this); | |
| 368 }, | |
| 369 | |
| 370 /** | |
| 371 * @return {?WebInspector.UILocation} | |
| 372 */ | |
| 373 uiLocation: function() | |
| 374 { | |
| 375 var cssLocation = /** @type WebInspector.CSSLocation */ (this.rawLocatio
n()); | |
| 376 if (this._header) { | |
| 377 var headerInfo = WebInspector.cssWorkspaceBinding._headerInfo(this._
header); | |
| 378 return headerInfo._rawLocationToUILocation(cssLocation.lineNumber, c
ssLocation.columnNumber); | |
| 379 } | |
| 380 var uiSourceCode = WebInspector.workspace.uiSourceCodeForURL(cssLocation
.url); | |
| 381 if (!uiSourceCode) | |
| 382 return null; | |
| 383 return uiSourceCode.uiLocation(cssLocation.lineNumber, cssLocation.colum
nNumber); | |
| 384 }, | |
| 385 | |
| 386 dispose: function() | |
| 387 { | |
| 388 WebInspector.LiveLocation.prototype.dispose.call(this); | |
| 389 if (this._header) | |
| 390 WebInspector.cssWorkspaceBinding._removeLiveLocation(this); | |
| 391 this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.Sty
leSheetAdded, this._styleSheetAdded, this); | |
| 392 this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.Sty
leSheetRemoved, this._styleSheetRemoved, this); | |
| 393 }, | |
| 394 | |
| 395 __proto__: WebInspector.LiveLocation.prototype | |
| 396 } | |
| 397 | |
| 398 /** | |
| 399 * @type {!WebInspector.CSSWorkspaceBinding} | |
| 400 */ | |
| 401 WebInspector.cssWorkspaceBinding; | |
| OLD | NEW |