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