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.
7 * @implements {WebInspector.TargetManager.Observer}
8 * @param {!WebInspector.TargetManager} targetManager
9 * @param {!WebInspector.Workspace} workspace
10 * @param {!WebInspector.NetworkMapping} networkMapping
12 WebInspector
.CSSWorkspaceBinding = function(targetManager
, workspace
, networkMapping
)
14 this._workspace
= workspace
;
15 this._networkMapping
= networkMapping
;
17 /** @type {!Map.<!WebInspector.CSSStyleModel, !WebInspector.CSSWorkspaceBinding.TargetInfo>} */
18 this._modelToTargetInfo
= new Map();
19 targetManager
.observeTargets(this);
21 targetManager
.addModelListener(WebInspector
.ResourceTreeModel
, WebInspector
.ResourceTreeModel
.EventTypes
.MainFrameNavigated
, this._mainFrameCreatedOrNavigated
, this);
24 WebInspector
.CSSWorkspaceBinding
.prototype = {
27 * @param {!WebInspector.Target} target
29 targetAdded: function(target
)
31 var cssModel
= WebInspector
.CSSStyleModel
.fromTarget(target
);
33 this._modelToTargetInfo
.set(cssModel
, new WebInspector
.CSSWorkspaceBinding
.TargetInfo(cssModel
, this._workspace
, this._networkMapping
));
38 * @param {!WebInspector.Target} target
40 targetRemoved: function(target
)
42 var cssModel
= WebInspector
.CSSStyleModel
.fromTarget(target
);
44 this._modelToTargetInfo
.remove(cssModel
)._dispose();
48 * @param {!WebInspector.CSSStyleSheetHeader} header
49 * @param {!WebInspector.CSSSourceMapping} mapping
51 pushSourceMapping: function(header
, mapping
)
53 this._ensureInfoForHeader(header
)._pushSourceMapping(mapping
);
57 * @param {!WebInspector.CSSStyleSheetHeader} header
58 * @return {?WebInspector.CSSWorkspaceBinding.HeaderInfo}
60 _headerInfo: function(header
)
62 var map
= this._modelToTargetInfo
.get(header
.cssModel());
63 return map
._headerInfo(header
.id
) || null;
67 * @param {!WebInspector.CSSStyleSheetHeader} header
68 * @return {!WebInspector.CSSWorkspaceBinding.HeaderInfo}
70 _ensureInfoForHeader: function(header
)
72 var targetInfo
= this._modelToTargetInfo
.get(header
.cssModel());
74 targetInfo
= new WebInspector
.CSSWorkspaceBinding
.TargetInfo(header
.cssModel(), this._workspace
, this._networkMapping
);
75 this._modelToTargetInfo
.set(header
.cssModel(), targetInfo
);
77 return targetInfo
._ensureInfoForHeader(header
);
81 * @param {!WebInspector.Event} event
83 _mainFrameCreatedOrNavigated: function(event
)
85 var target
= /** @type {!WebInspector.ResourceTreeModel} */ (event
.target
).target();
86 var cssModel
= WebInspector
.CSSStyleModel
.fromTarget(target
);
88 this._modelToTargetInfo
.get(cssModel
)._reset();
92 * @param {!WebInspector.CSSStyleSheetHeader} header
94 updateLocations: function(header
)
96 var info
= this._headerInfo(header
);
98 info
._updateLocations();
102 * @param {!WebInspector.CSSLocation} rawLocation
103 * @param {function(!WebInspector.UILocation):(boolean|undefined)} updateDelegate
104 * @return {!WebInspector.CSSWorkspaceBinding.LiveLocation}
106 createLiveLocation: function(rawLocation
, updateDelegate
)
108 var header
= rawLocation
.styleSheetId
? rawLocation
.cssModel().styleSheetHeaderForId(rawLocation
.styleSheetId
) : null;
109 return new WebInspector
.CSSWorkspaceBinding
.LiveLocation(rawLocation
.cssModel(), header
, rawLocation
, this, updateDelegate
);
113 * @param {!WebInspector.CSSWorkspaceBinding.LiveLocation} location
115 _addLiveLocation: function(location
)
117 this._ensureInfoForHeader(location
._header
)._addLocation(location
);
121 * @param {!WebInspector.CSSWorkspaceBinding.LiveLocation} location
123 _removeLiveLocation: function(location
)
125 var info
= this._headerInfo(location
._header
);
127 info
._removeLocation(location
);
131 * @param {!WebInspector.CSSProperty} cssProperty
132 * @param {boolean} forName
133 * @return {?WebInspector.UILocation}
135 propertyUILocation: function(cssProperty
, forName
)
137 var style
= cssProperty
.ownerStyle
;
138 if (!style
|| !style
.parentRule
|| !style
.styleSheetId
)
141 var range
= cssProperty
.range
;
145 var url
= style
.parentRule
.resourceURL();
149 var line
= forName
? range
.startLine
: range
.endLine
;
150 // End of range is exclusive, so subtract 1 from the end offset.
151 var column
= forName
? range
.startColumn
: range
.endColumn
- (cssProperty
.text
&& cssProperty
.text
.endsWith(";") ? 2 : 1);
152 var header
= style
.cssModel().styleSheetHeaderForId(style
.styleSheetId
);
153 var rawLocation
= new WebInspector
.CSSLocation(style
.cssModel(), style
.styleSheetId
, url
, header
.lineNumberInSource(line
), header
.columnNumberInSource(line
, column
));
154 return this.rawLocationToUILocation(rawLocation
);
158 * @param {?WebInspector.CSSLocation} rawLocation
159 * @return {?WebInspector.UILocation}
161 rawLocationToUILocation: function(rawLocation
)
165 var header
= rawLocation
.cssModel().styleSheetHeaderForId(rawLocation
.styleSheetId
);
168 var info
= this._headerInfo(header
);
169 return info
? info
._rawLocationToUILocation(rawLocation
.lineNumber
, rawLocation
.columnNumber
) : null;
175 * @param {!WebInspector.CSSStyleModel} cssModel
176 * @param {!WebInspector.Workspace} workspace
177 * @param {!WebInspector.NetworkMapping} networkMapping
179 WebInspector
.CSSWorkspaceBinding
.TargetInfo = function(cssModel
, workspace
, networkMapping
)
181 this._cssModel
= cssModel
;
182 this._stylesSourceMapping
= new WebInspector
.StylesSourceMapping(cssModel
, workspace
, networkMapping
);
183 this._sassSourceMapping
= new WebInspector
.SASSSourceMapping(cssModel
, workspace
, networkMapping
, WebInspector
.NetworkProject
.forTarget(cssModel
.target()));
185 /** @type {!Map.<string, !WebInspector.CSSWorkspaceBinding.HeaderInfo>} */
186 this._headerInfoById
= new Map();
188 cssModel
.addEventListener(WebInspector
.CSSStyleModel
.Events
.StyleSheetAdded
, this._styleSheetAdded
, this);
189 cssModel
.addEventListener(WebInspector
.CSSStyleModel
.Events
.StyleSheetRemoved
, this._styleSheetRemoved
, this);
192 WebInspector
.CSSWorkspaceBinding
.TargetInfo
.prototype = {
194 * @param {!WebInspector.Event} event
196 _styleSheetAdded: function(event
)
198 var header
= /** @type {!WebInspector.CSSStyleSheetHeader} */ (event
.data
);
199 this._stylesSourceMapping
.addHeader(header
);
200 this._sassSourceMapping
.addHeader(header
);
204 * @param {!WebInspector.Event} event
206 _styleSheetRemoved: function(event
)
208 var header
= /** @type {!WebInspector.CSSStyleSheetHeader} */ (event
.data
);
209 this._stylesSourceMapping
.removeHeader(header
);
210 this._sassSourceMapping
.removeHeader(header
);
211 this._headerInfoById
.remove(header
.id
);
215 * @param {!CSSAgent.StyleSheetId} id
217 _headerInfo: function(id
)
219 return this._headerInfoById
.get(id
);
222 _ensureInfoForHeader: function(header
)
224 var info
= this._headerInfoById
.get(header
.id
);
226 info
= new WebInspector
.CSSWorkspaceBinding
.HeaderInfo(header
);
227 this._headerInfoById
.set(header
.id
, info
);
235 this._cssModel
.removeEventListener(WebInspector
.CSSStyleModel
.Events
.StyleSheetAdded
, this._styleSheetAdded
, this);
236 this._cssModel
.removeEventListener(WebInspector
.CSSStyleModel
.Events
.StyleSheetRemoved
, this._styleSheetRemoved
, this);
241 this._headerInfoById
.clear();
247 * @param {!WebInspector.CSSStyleSheetHeader} header
249 WebInspector
.CSSWorkspaceBinding
.HeaderInfo = function(header
)
251 this._header
= header
;
253 /** @type {!Array.<!WebInspector.CSSSourceMapping>} */
254 this._sourceMappings
= [];
256 /** @type {!Set.<!WebInspector.LiveLocation>} */
257 this._locations
= new Set();
260 WebInspector
.CSSWorkspaceBinding
.HeaderInfo
.prototype = {
262 * @param {!WebInspector.LiveLocation} location
264 _addLocation: function(location
)
266 this._locations
.add(location
);
271 * @param {!WebInspector.LiveLocation} location
273 _removeLocation: function(location
)
275 this._locations
.delete(location
);
278 _updateLocations: function()
280 var items
= this._locations
.valuesArray();
281 for (var i
= 0; i
< items
.length
; ++i
)
286 * @param {number} lineNumber
287 * @param {number=} columnNumber
288 * @return {?WebInspector.UILocation}
290 _rawLocationToUILocation: function(lineNumber
, columnNumber
)
292 var uiLocation
= null;
293 var rawLocation
= new WebInspector
.CSSLocation(this._header
.cssModel(), this._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(rawLocation
);
300 * @param {!WebInspector.CSSSourceMapping} sourceMapping
302 _pushSourceMapping: function(sourceMapping
)
304 this._sourceMappings
.push(sourceMapping
);
305 this._updateLocations();
311 * @extends {WebInspector.LiveLocation}
312 * @param {!WebInspector.CSSStyleModel} cssModel
313 * @param {?WebInspector.CSSStyleSheetHeader} header
314 * @param {!WebInspector.CSSLocation} rawLocation
315 * @param {!WebInspector.CSSWorkspaceBinding} binding
316 * @param {function(!WebInspector.UILocation):(boolean|undefined)} updateDelegate
318 WebInspector
.CSSWorkspaceBinding
.LiveLocation = function(cssModel
, header
, rawLocation
, binding
, updateDelegate
)
320 WebInspector
.LiveLocation
.call(this, updateDelegate
);
321 this._cssModel
= cssModel
;
322 this._rawLocation
= rawLocation
;
323 this._binding
= binding
;
325 this._clearStyleSheet();
327 this._setStyleSheet(header
);
330 WebInspector
.CSSWorkspaceBinding
.LiveLocation
.prototype = {
332 * @param {!WebInspector.Event} event
334 _styleSheetAdded: function(event
)
336 console
.assert(!this._header
);
337 var header
= /** @type {!WebInspector.CSSStyleSheetHeader} */ (event
.data
);
338 if (header
.sourceURL
&& header
.sourceURL
=== this._rawLocation
.url
)
339 this._setStyleSheet(header
);
343 * @param {!WebInspector.Event} event
345 _styleSheetRemoved: function(event
)
347 console
.assert(this._header
);
348 var header
= /** @type {!WebInspector.CSSStyleSheetHeader} */ (event
.data
);
349 if (this._header
!== header
)
351 this._binding
._removeLiveLocation(this);
352 this._clearStyleSheet();
356 * @param {!WebInspector.CSSStyleSheetHeader} header
358 _setStyleSheet: function(header
)
360 this._header
= header
;
361 this._binding
._addLiveLocation(this);
362 this._cssModel
.removeEventListener(WebInspector
.CSSStyleModel
.Events
.StyleSheetAdded
, this._styleSheetAdded
, this);
363 this._cssModel
.addEventListener(WebInspector
.CSSStyleModel
.Events
.StyleSheetRemoved
, this._styleSheetRemoved
, this);
366 _clearStyleSheet: function()
369 this._cssModel
.removeEventListener(WebInspector
.CSSStyleModel
.Events
.StyleSheetRemoved
, this._styleSheetRemoved
, this);
370 this._cssModel
.addEventListener(WebInspector
.CSSStyleModel
.Events
.StyleSheetAdded
, this._styleSheetAdded
, this);
375 * @return {?WebInspector.UILocation}
377 uiLocation: function()
379 var cssLocation
= this._rawLocation
;
381 var headerInfo
= this._binding
._headerInfo(this._header
);
382 return headerInfo
._rawLocationToUILocation(cssLocation
.lineNumber
, cssLocation
.columnNumber
);
384 var uiSourceCode
= this._binding
._networkMapping
.uiSourceCodeForURL(cssLocation
.url
, cssLocation
.target());
387 return uiSourceCode
.uiLocation(cssLocation
.lineNumber
, cssLocation
.columnNumber
);
392 WebInspector
.LiveLocation
.prototype.dispose
.call(this);
394 this._binding
._removeLiveLocation(this);
395 this._cssModel
.removeEventListener(WebInspector
.CSSStyleModel
.Events
.StyleSheetAdded
, this._styleSheetAdded
, this);
396 this._cssModel
.removeEventListener(WebInspector
.CSSStyleModel
.Events
.StyleSheetRemoved
, this._styleSheetRemoved
, this);
399 __proto__
: WebInspector
.LiveLocation
.prototype
405 WebInspector
.CSSSourceMapping = function()
409 WebInspector
.CSSSourceMapping
.prototype = {
411 * @param {!WebInspector.CSSLocation} rawLocation
412 * @return {?WebInspector.UILocation}
414 rawLocationToUILocation: function(rawLocation
) { },
417 * @param {!WebInspector.UISourceCode} uiSourceCode
418 * @param {number} lineNumber
419 * @param {number} columnNumber
420 * @return {?WebInspector.CSSLocation}
422 uiLocationToRawLocation: function(uiSourceCode
, lineNumber
, columnNumber
) { },
427 isIdentity: function() { },
430 * @param {!WebInspector.UISourceCode} uiSourceCode
431 * @param {number} lineNumber
434 uiLineHasMapping: function(uiSourceCode
, lineNumber
) { }
438 * @type {!WebInspector.CSSWorkspaceBinding}
440 WebInspector
.cssWorkspaceBinding
;