Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1545)

Unified Diff: Source/devtools/front_end/sdk/CSSWorkspaceBinding.js

Issue 297923002: DevTools: Decouple CSS model from UI entities (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Address comments Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
}
}

Powered by Google App Engine
This is Rietveld 408576698