Index: Source/devtools/front_end/sdk/CSSWorkspaceBinding.js |
diff --git a/Source/devtools/front_end/sdk/CSSWorkspaceBinding.js b/Source/devtools/front_end/sdk/CSSWorkspaceBinding.js |
index 75574889c97779049f35892d951c8d2dbe8d15b1..f0977917e7c6c0cc9a3936a4b901943763d5f060 100644 |
--- a/Source/devtools/front_end/sdk/CSSWorkspaceBinding.js |
+++ b/Source/devtools/front_end/sdk/CSSWorkspaceBinding.js |
@@ -4,20 +4,127 @@ |
/** |
* @constructor |
+ * @implements {WebInspector.TargetManager.Observer} |
*/ |
WebInspector.CSSWorkspaceBinding = function() |
{ |
+ /** @type {!Map.<!WebInspector.Target, !WebInspector.CSSWorkspaceBinding.TargetInfo>} */ |
+ this._targetToTargetInfo = new Map(); |
+ WebInspector.targetManager.observeTargets(this); |
+ |
+ WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameCreatedOrNavigated, this); |
+ WebInspector.targetManager.addModelListener(WebInspector.CSSStyleModel, WebInspector.CSSStyleModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this); |
} |
WebInspector.CSSWorkspaceBinding.prototype = { |
/** |
+ * @param {!WebInspector.Target} target |
+ */ |
+ targetAdded: function(target) |
+ { |
+ this._targetToTargetInfo.put(target, new WebInspector.CSSWorkspaceBinding.TargetInfo(target)); |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.Target} target |
+ */ |
+ targetRemoved: function(target) |
+ { |
+ this._targetToTargetInfo.remove(target)._dispose(); |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.CSSStyleSheetHeader} header |
+ * @param {!WebInspector.SourceMapping} mapping |
+ */ |
+ pushSourceMapping: function(header, mapping) |
+ { |
+ this._ensureInfoForHeader(header)._pushSourceMapping(mapping); |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.CSSStyleSheetHeader} header |
+ * @return {?WebInspector.CSSWorkspaceBinding.HeaderInfo} |
+ */ |
+ _headerInfo: function(header) |
+ { |
+ var map = this._targetToTargetInfo.get(header.target()); |
+ return map._headerInfo(header.id) || null; |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.CSSStyleSheetHeader} header |
+ * @return {!WebInspector.CSSWorkspaceBinding.HeaderInfo} |
+ */ |
+ _ensureInfoForHeader: function(header) |
+ { |
+ var targetInfo = this._targetToTargetInfo.get(header.target()); |
+ if (!targetInfo) { |
+ targetInfo = new WebInspector.CSSWorkspaceBinding.TargetInfo(header.target()); |
+ this._targetToTargetInfo.put(header.target(), targetInfo); |
+ } |
+ return targetInfo._ensureInfoForHeader(header); |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.Event} event |
+ */ |
+ _mainFrameCreatedOrNavigated: function(event) |
+ { |
+ var target = /** @type {!WebInspector.ResourceTreeModel} */ (event.target).target(); |
+ var info = this._targetToTargetInfo.remove(target); |
+ if (info) |
+ info._dispose(); |
+ this._targetToTargetInfo.put(target, new WebInspector.CSSWorkspaceBinding.TargetInfo(target)); |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.Event} event |
+ */ |
+ _styleSheetRemoved: function(event) |
+ { |
+ var target = /** @type {!WebInspector.CSSStyleModel} */ (event.target).target(); |
+ var info = this._targetToTargetInfo.get(target); |
+ info._styleSheetRemoved(/** @type {!WebInspector.CSSStyleSheetHeader} */ (event.data).id); |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.CSSStyleSheetHeader} header |
+ */ |
+ updateLocations: function(header) |
+ { |
+ var info = this._headerInfo(header); |
+ if (info) |
+ info._updateLocations(); |
+ }, |
+ |
+ /** |
* @param {!WebInspector.CSSLocation} rawLocation |
* @param {function(!WebInspector.UILocation):(boolean|undefined)} updateDelegate |
- * @return {!WebInspector.CSSStyleModel.LiveLocation} |
+ * @return {!WebInspector.CSSWorkspaceBinding.LiveLocation} |
*/ |
createLiveLocation: function(rawLocation, updateDelegate) |
{ |
- return /** @type {!WebInspector.CSSStyleModel.LiveLocation} */ (rawLocation.createLiveLocation(updateDelegate)); |
+ var header = rawLocation.styleSheetId ? rawLocation.target().cssModel.styleSheetHeaderForId(rawLocation.styleSheetId) : null; |
+ return new WebInspector.CSSWorkspaceBinding.LiveLocation(rawLocation.target().cssModel, header, rawLocation, updateDelegate); |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.CSSWorkspaceBinding.LiveLocation} location |
+ */ |
+ _addLiveLocation: function(location) |
+ { |
+ this._ensureInfoForHeader(location._header)._addLocation(location); |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.CSSWorkspaceBinding.LiveLocation} location |
+ */ |
+ _removeLiveLocation: function(location) |
+ { |
+ var info = this._headerInfo(location._header); |
+ if (info) |
+ info._removeLocation(location); |
}, |
/** |
@@ -52,7 +159,270 @@ WebInspector.CSSWorkspaceBinding.prototype = { |
*/ |
rawLocationToUILocation: function(rawLocation) |
{ |
- return rawLocation ? rawLocation.target().cssModel.rawLocationToUILocation(rawLocation) : null; |
+ if (!rawLocation) |
+ return null; |
+ var cssModel = rawLocation.target().cssModel; |
+ var frameIdToSheetIds = cssModel.styleSheetIdsByFrameIdForURL(rawLocation.url); |
+ if (!Object.values(frameIdToSheetIds).length) |
+ return null; |
+ var styleSheetIds = []; |
+ for (var frameId in frameIdToSheetIds) |
+ styleSheetIds = styleSheetIds.concat(frameIdToSheetIds[frameId]); |
+ var uiLocation; |
+ for (var i = 0; !uiLocation && i < styleSheetIds.length; ++i) { |
+ var header = cssModel.styleSheetHeaderForId(styleSheetIds[i]); |
+ if (!header) |
+ continue; |
+ var info = this._headerInfo(header); |
+ if (info) |
+ uiLocation = info._rawLocationToUILocation(rawLocation.lineNumber, rawLocation.columnNumber); |
+ } |
+ return uiLocation || null; |
+ } |
+} |
+ |
+/** |
+ * @constructor |
+ * @param {!WebInspector.Target} target |
+ */ |
+WebInspector.CSSWorkspaceBinding.TargetInfo = function(target) |
+{ |
+ this._target = target; |
+ |
+ /** @type {!StringMap.<!WebInspector.CSSWorkspaceBinding.HeaderInfo>} */ |
+ this._headerInfoById = new StringMap(); |
+ |
+ this._mapping = new WebInspector.CSSStyleSheetMapping(target.cssModel, WebInspector.workspace, WebInspector.networkWorkspaceBinding); |
+} |
+ |
+WebInspector.CSSWorkspaceBinding.TargetInfo.prototype = { |
+ /** |
+ * @param {!CSSAgent.StyleSheetId} id |
+ */ |
+ _styleSheetRemoved: function(id) |
+ { |
+ this._headerInfoById.remove(id); |
+ }, |
+ |
+ /** |
+ * @param {!CSSAgent.StyleSheetId} id |
+ */ |
+ _headerInfo: function(id) |
+ { |
+ return this._headerInfoById.get(id); |
+ }, |
+ |
+ _ensureInfoForHeader: function(header) |
+ { |
+ var info = this._headerInfoById.get(header.id); |
+ if (!info) { |
+ info = new WebInspector.CSSWorkspaceBinding.HeaderInfo(header); |
+ this._headerInfoById.put(header.id, info); |
+ } |
+ return info; |
+ }, |
+ |
+ _dispose: function() |
+ { |
+ this._mapping._dispose(); |
+ } |
+} |
+ |
+/** |
+ * @constructor |
+ * @param {!WebInspector.CSSStyleSheetHeader} header |
+ */ |
+WebInspector.CSSWorkspaceBinding.HeaderInfo = function(header) |
+{ |
+ this._header = header; |
+ |
+ /** @type {!Array.<!WebInspector.SourceMapping>} */ |
+ this._sourceMappings = []; |
+ |
+ /** @type {!Set.<!WebInspector.LiveLocation>} */ |
+ this._locations = new Set(); |
+} |
+ |
+WebInspector.CSSWorkspaceBinding.HeaderInfo.prototype = { |
+ /** |
+ * @param {!WebInspector.LiveLocation} location |
+ */ |
+ _addLocation: function(location) |
+ { |
+ this._locations.add(location); |
+ location.update(); |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.LiveLocation} location |
+ */ |
+ _removeLocation: function(location) |
+ { |
+ this._locations.remove(location); |
+ }, |
+ |
+ _updateLocations: function() |
+ { |
+ var items = this._locations.values(); |
+ for (var i = 0; i < items.length; ++i) |
+ items[i].update(); |
+ }, |
+ |
+ /** |
+ * @param {number} lineNumber |
+ * @param {number=} columnNumber |
+ * @return {?WebInspector.UILocation} |
+ */ |
+ _rawLocationToUILocation: function(lineNumber, columnNumber) |
+ { |
+ var uiLocation = null; |
+ var rawLocation = new WebInspector.CSSLocation(this._header.target(), this._header.id, this._header.resourceURL(), lineNumber, columnNumber); |
+ for (var i = this._sourceMappings.length - 1; !uiLocation && i >= 0; --i) |
+ uiLocation = this._sourceMappings[i].rawLocationToUILocation(rawLocation); |
+ return uiLocation; |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.SourceMapping} sourceMapping |
+ */ |
+ _pushSourceMapping: function(sourceMapping) |
+ { |
+ this._sourceMappings.push(sourceMapping); |
+ this._updateLocations(); |
+ } |
+} |
+ |
+/** |
+ * @constructor |
+ * @extends {WebInspector.LiveLocation} |
+ * @param {!WebInspector.CSSStyleModel} cssModel |
+ * @param {?WebInspector.CSSStyleSheetHeader} header |
+ * @param {!WebInspector.CSSLocation} rawLocation |
+ * @param {function(!WebInspector.UILocation):(boolean|undefined)} updateDelegate |
+ */ |
+WebInspector.CSSWorkspaceBinding.LiveLocation = function(cssModel, header, rawLocation, updateDelegate) |
+{ |
+ WebInspector.LiveLocation.call(this, rawLocation, updateDelegate); |
+ this._cssModel = cssModel; |
+ if (!header) |
+ this._clearStyleSheet(); |
+ else |
+ this._setStyleSheet(header); |
+} |
+ |
+WebInspector.CSSWorkspaceBinding.LiveLocation.prototype = { |
+ /** |
+ * @param {!WebInspector.Event} event |
+ */ |
+ _styleSheetAdded: function(event) |
+ { |
+ console.assert(!this._header); |
+ var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.data); |
+ if (header.sourceURL && header.sourceURL === this.rawLocation().url) |
+ this._setStyleSheet(header); |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.Event} event |
+ */ |
+ _styleSheetRemoved: function(event) |
+ { |
+ console.assert(this._header); |
+ var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.data); |
+ if (this._header !== header) |
+ return; |
+ WebInspector.cssWorkspaceBinding._removeLiveLocation(this); |
+ this._clearStyleSheet(); |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.CSSStyleSheetHeader} header |
+ */ |
+ _setStyleSheet: function(header) |
+ { |
+ this._header = header; |
+ WebInspector.cssWorkspaceBinding._addLiveLocation(this); |
+ this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, this._styleSheetAdded, this); |
+ this._cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this); |
+ }, |
+ |
+ _clearStyleSheet: function() |
+ { |
+ delete this._header; |
+ this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this); |
+ this._cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, this._styleSheetAdded, this); |
+ }, |
+ |
+ /** |
+ * @return {?WebInspector.UILocation} |
+ */ |
+ uiLocation: function() |
+ { |
+ var cssLocation = /** @type WebInspector.CSSLocation */ (this.rawLocation()); |
+ if (this._header) { |
+ var headerInfo = WebInspector.cssWorkspaceBinding._headerInfo(this._header); |
+ return headerInfo._rawLocationToUILocation(cssLocation.lineNumber, cssLocation.columnNumber); |
+ } |
+ var uiSourceCode = WebInspector.workspace.uiSourceCodeForURL(cssLocation.url); |
+ if (!uiSourceCode) |
+ return null; |
+ return uiSourceCode.uiLocation(cssLocation.lineNumber, cssLocation.columnNumber); |
+ }, |
+ |
+ dispose: function() |
+ { |
+ WebInspector.LiveLocation.prototype.dispose.call(this); |
+ if (this._header) |
+ WebInspector.cssWorkspaceBinding._removeLiveLocation(this); |
+ this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, this._styleSheetAdded, this); |
+ this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this); |
+ }, |
+ |
+ __proto__: WebInspector.LiveLocation.prototype |
+} |
+ |
+/** |
+ * @constructor |
+ * @param {!WebInspector.CSSStyleModel} cssModel |
+ * @param {!WebInspector.Workspace} workspace |
+ * @param {!WebInspector.NetworkWorkspaceBinding} networkWorkspaceBinding |
+ */ |
+WebInspector.CSSStyleSheetMapping = function(cssModel, workspace, networkWorkspaceBinding) |
vsevik
2014/07/22 16:37:59
This is essentially the same object as WebInspecto
|
+{ |
+ this._cssModel = cssModel; |
+ this._workspace = workspace; |
+ this._stylesSourceMapping = new WebInspector.StylesSourceMapping(cssModel, workspace); |
+ this._sassSourceMapping = new WebInspector.SASSSourceMapping(cssModel, workspace, networkWorkspaceBinding); |
+ |
+ cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, this._styleSheetAdded, this); |
+ cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this); |
+} |
+ |
+WebInspector.CSSStyleSheetMapping.prototype = { |
+ /** |
+ * @param {!WebInspector.Event} event |
+ */ |
+ _styleSheetAdded: function(event) |
+ { |
+ var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.data); |
+ this._stylesSourceMapping.addHeader(header); |
+ this._sassSourceMapping.addHeader(header); |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.Event} event |
+ */ |
+ _styleSheetRemoved: function(event) |
+ { |
+ var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.data); |
+ this._stylesSourceMapping.removeHeader(header); |
+ this._sassSourceMapping.removeHeader(header); |
+ }, |
+ |
+ _dispose: function() |
+ { |
+ this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetAdded, this._styleSheetAdded, this); |
+ this._cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this); |
} |
} |