| Index: third_party/WebKit/Source/devtools/front_end/bindings/StylesSourceMapping.js
|
| diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/StylesSourceMapping.js b/third_party/WebKit/Source/devtools/front_end/bindings/StylesSourceMapping.js
|
| index b9760d6e79d42aca4047733c32a893b1286d2b6a..20489acf243b1136a869a75e1dd5b4efc599cb3e 100644
|
| --- a/third_party/WebKit/Source/devtools/front_end/bindings/StylesSourceMapping.js
|
| +++ b/third_party/WebKit/Source/devtools/front_end/bindings/StylesSourceMapping.js
|
| @@ -40,21 +40,19 @@ Bindings.StylesSourceMapping = class {
|
| this._cssModel = cssModel;
|
| this._workspace = workspace;
|
|
|
| - /** @type {!Map<string, !Map<string, !Map<string, !SDK.CSSStyleSheetHeader>>>} */
|
| - this._urlToHeadersByFrameId = new Map();
|
| + var target = this._cssModel.target();
|
| + var projectId = 'styles:' + target.id();
|
| + this._project = new Bindings.ContentProviderBasedProject(
|
| + this._workspace, projectId, Workspace.projectTypes.Network, '', false /* isServiceProject */);
|
| + Bindings.NetworkProject.connectProjectToTarget(this._project, target);
|
| +
|
| /** @type {!Map.<!Workspace.UISourceCode, !Bindings.StyleFile>} */
|
| this._styleFiles = new Map();
|
|
|
| this._eventListeners = [
|
| - this._workspace.addEventListener(Workspace.Workspace.Events.ProjectRemoved, this._projectRemoved, this),
|
| - this._workspace.addEventListener(
|
| - Workspace.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAddedToWorkspace, this),
|
| - this._workspace.addEventListener(Workspace.Workspace.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this),
|
| this._cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetAdded, this._styleSheetAdded, this),
|
| this._cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetRemoved, this._styleSheetRemoved, this),
|
| - this._cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetChanged, this._styleSheetChanged, this),
|
| - SDK.ResourceTreeModel.fromTarget(cssModel.target())
|
| - .addEventListener(SDK.ResourceTreeModel.Events.MainFrameNavigated, this._unbindAllUISourceCodes, this)
|
| + this._cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetChanged, this._styleSheetChanged, this)
|
| ];
|
| }
|
|
|
| @@ -66,7 +64,7 @@ Bindings.StylesSourceMapping = class {
|
| var header = rawLocation.header();
|
| if (!header)
|
| return null;
|
| - var uiSourceCode = Bindings.NetworkProject.uiSourceCodeForStyleURL(this._workspace, rawLocation.url, header);
|
| + var uiSourceCode = this._project.uiSourceCodeForURL(header.contentURL());
|
| if (!uiSourceCode)
|
| return null;
|
| var lineNumber = rawLocation.lineNumber;
|
| @@ -83,24 +81,28 @@ Bindings.StylesSourceMapping = class {
|
| */
|
| _styleSheetAdded(event) {
|
| var header = /** @type {!SDK.CSSStyleSheetHeader} */ (event.data);
|
| + if (header.isInline && !header.hasSourceURL && header.origin !== 'inspector')
|
| + return;
|
| +
|
| var url = header.resourceURL();
|
| if (!url)
|
| return;
|
|
|
| - var map = this._urlToHeadersByFrameId.get(url);
|
| - if (!map) {
|
| - map = /** @type {!Map.<string, !Map.<string, !SDK.CSSStyleSheetHeader>>} */ (new Map());
|
| - this._urlToHeadersByFrameId.set(url, map);
|
| + var frame = SDK.ResourceTreeFrame.fromStyleSheet(header);
|
| + var uiSourceCode = this._project.uiSourceCodeForURL(header.contentURL());
|
| + if (!uiSourceCode) {
|
| + var originalContentProvider = header.originalContentProvider();
|
| + uiSourceCode = this._project.createUISourceCode(url, originalContentProvider.contentType());
|
| + var metadata = frame ? Bindings.resourceMetadata(frame.resourceForURL(url)) : null;
|
| + this._project.addUISourceCodeWithProvider(uiSourceCode, originalContentProvider, metadata);
|
| + this._styleFiles.set(uiSourceCode, new Bindings.StyleFile(this._cssModel, uiSourceCode));
|
| + Bindings.NetworkProject.useExplicitMimeType(uiSourceCode);
|
| }
|
| - var headersById = map.get(header.frameId);
|
| - if (!headersById) {
|
| - headersById = /** @type {!Map.<string, !SDK.CSSStyleSheetHeader>} */ (new Map());
|
| - map.set(header.frameId, headersById);
|
| - }
|
| - headersById.set(header.id, header);
|
| - var uiSourceCode = Bindings.NetworkProject.uiSourceCodeForStyleURL(this._workspace, url, header);
|
| - if (uiSourceCode)
|
| - this._bindUISourceCode(uiSourceCode, header);
|
| + var styleFile = this._styleFiles.get(uiSourceCode);
|
| + styleFile.addHeader(header);
|
| + if (frame)
|
| + Bindings.NetworkProject.connectFrameToUISourceCode(uiSourceCode, frame);
|
| + Bindings.cssWorkspaceBinding.updateLocations(header);
|
| }
|
|
|
| /**
|
| @@ -108,251 +110,185 @@ Bindings.StylesSourceMapping = class {
|
| */
|
| _styleSheetRemoved(event) {
|
| var header = /** @type {!SDK.CSSStyleSheetHeader} */ (event.data);
|
| - var url = header.resourceURL();
|
| - if (!url)
|
| + var uiSourceCode = this._project.uiSourceCodeForURL(header.contentURL());
|
| + if (!uiSourceCode)
|
| return;
|
| -
|
| - var map = this._urlToHeadersByFrameId.get(url);
|
| - console.assert(map);
|
| - var headersById = map.get(header.frameId);
|
| - console.assert(headersById);
|
| - headersById.delete(header.id);
|
| -
|
| - if (!headersById.size) {
|
| - map.delete(header.frameId);
|
| - if (!map.size) {
|
| - this._urlToHeadersByFrameId.delete(url);
|
| - var uiSourceCode = Bindings.NetworkProject.uiSourceCodeForStyleURL(this._workspace, url, header);
|
| - if (uiSourceCode)
|
| - this._unbindUISourceCode(uiSourceCode);
|
| - }
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * @param {!Workspace.UISourceCode} uiSourceCode
|
| - */
|
| - _unbindUISourceCode(uiSourceCode) {
|
| var styleFile = this._styleFiles.get(uiSourceCode);
|
| - if (!styleFile)
|
| + styleFile.removeHeader(header);
|
| + if (styleFile.hasHeaders())
|
| return;
|
| styleFile.dispose();
|
| this._styleFiles.delete(uiSourceCode);
|
| + this._project.removeFile(uiSourceCode.url());
|
| }
|
|
|
| /**
|
| * @param {!Common.Event} event
|
| */
|
| - _unbindAllUISourceCodes(event) {
|
| - if (event.data.target() !== this._cssModel.target())
|
| + _styleSheetChanged(event) {
|
| + var styleSheetId = /** @type {!Protocol.CSS.StyleSheetId} */ (event.data.styleSheetId);
|
| + var header = this._cssModel.styleSheetHeaderForId(styleSheetId);
|
| + if (!header)
|
| + return;
|
| + var uiSourceCode = this._project.uiSourceCodeForURL(header.contentURL());
|
| + if (!uiSourceCode)
|
| return;
|
| + var styleFile = this._styleFiles.get(uiSourceCode);
|
| + if (styleFile)
|
| + styleFile.styleSheetChanged(header);
|
| + }
|
| +
|
| + dispose() {
|
| for (var styleFile of this._styleFiles.values())
|
| styleFile.dispose();
|
| this._styleFiles.clear();
|
| - this._urlToHeadersByFrameId = new Map();
|
| + this._project.removeProject();
|
| + Common.EventTarget.removeEventListeners(this._eventListeners);
|
| }
|
| +};
|
|
|
| +/**
|
| + * @unrestricted
|
| + */
|
| +Bindings.StyleFile = class {
|
| /**
|
| - * @param {!Common.Event} event
|
| + * @param {!SDK.CSSModel} cssModel
|
| + * @param {!Workspace.UISourceCode} uiSourceCode
|
| */
|
| - _uiSourceCodeAddedToWorkspace(event) {
|
| - var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
|
| - if (!this._urlToHeadersByFrameId.has(uiSourceCode.url()))
|
| - return;
|
| - this._bindUISourceCode(
|
| - uiSourceCode, this._urlToHeadersByFrameId.get(uiSourceCode.url()).valuesArray()[0].valuesArray()[0]);
|
| + constructor(cssModel, uiSourceCode) {
|
| + this._cssModel = cssModel;
|
| + this._uiSourceCode = uiSourceCode;
|
| + /** @type {!Set<!SDK.CSSStyleSheetHeader>} */
|
| + this._headers = new Set();
|
| + this._eventListeners = [
|
| + this._uiSourceCode.addEventListener(
|
| + Workspace.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this),
|
| + this._uiSourceCode.addEventListener(
|
| + Workspace.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this)
|
| + ];
|
| + this._commitThrottler = new Common.Throttler(Bindings.StyleFile.updateTimeout);
|
| + this._terminated = false;
|
| }
|
|
|
| /**
|
| - * @param {!Workspace.UISourceCode} uiSourceCode
|
| * @param {!SDK.CSSStyleSheetHeader} header
|
| */
|
| - _bindUISourceCode(uiSourceCode, header) {
|
| - if (this._styleFiles.get(uiSourceCode) || (header.isInline && !header.hasSourceURL))
|
| - return;
|
| - this._styleFiles.set(uiSourceCode, new Bindings.StyleFile(uiSourceCode, this));
|
| - Bindings.cssWorkspaceBinding.updateLocations(header);
|
| + addHeader(header) {
|
| + this._headers.add(header);
|
| }
|
|
|
| /**
|
| - * @param {!Common.Event} event
|
| + * @param {!SDK.CSSStyleSheetHeader} header
|
| */
|
| - _projectRemoved(event) {
|
| - var project = /** @type {!Workspace.Project} */ (event.data);
|
| - var uiSourceCodes = project.uiSourceCodes();
|
| - for (var i = 0; i < uiSourceCodes.length; ++i)
|
| - this._unbindUISourceCode(uiSourceCodes[i]);
|
| + removeHeader(header) {
|
| + this._headers.delete(header);
|
| }
|
|
|
| /**
|
| - * @param {!Common.Event} event
|
| + * @return {boolean}
|
| */
|
| - _uiSourceCodeRemoved(event) {
|
| - var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (event.data);
|
| - this._unbindUISourceCode(uiSourceCode);
|
| + hasHeaders() {
|
| + return !!this._headers.size;
|
| }
|
|
|
| /**
|
| - * @param {!Workspace.UISourceCode} uiSourceCode
|
| - * @param {string} content
|
| - * @param {boolean} majorChange
|
| - * @return {!Promise<?string>}
|
| + * @param {!SDK.CSSStyleSheetHeader} header
|
| */
|
| - _setStyleContent(uiSourceCode, content, majorChange) {
|
| - var styleSheetIds = this._cssModel.styleSheetIdsForURL(uiSourceCode.url());
|
| - if (!styleSheetIds.length)
|
| - return Promise.resolve(/** @type {?string} */ ('No stylesheet found: ' + uiSourceCode.url()));
|
| -
|
| - this._isSettingContent = true;
|
| -
|
| - /**
|
| - * @param {?string} error
|
| - * @this {Bindings.StylesSourceMapping}
|
| - * @return {?string}
|
| - */
|
| - function callback(error) {
|
| - delete this._isSettingContent;
|
| - return error || null;
|
| - }
|
| -
|
| - var promises = [];
|
| - for (var i = 0; i < styleSheetIds.length; ++i)
|
| - promises.push(this._cssModel.setStyleSheetText(styleSheetIds[i], content, majorChange));
|
| + styleSheetChanged(header) {
|
| + if (this._isSettingStyleSheetContents)
|
| + return;
|
|
|
| - return Promise.all(promises).spread(callback.bind(this));
|
| + this._commitThrottler.schedule(this._syncStyleSheetChange.bind(this, header), false);
|
| }
|
|
|
| /**
|
| * @param {!Common.Event} event
|
| */
|
| - _styleSheetChanged(event) {
|
| - if (this._isSettingContent)
|
| + _workingCopyCommitted(event) {
|
| + if (this._isAddingRevision)
|
| return;
|
|
|
| - this._updateStyleSheetTextSoon(event.data.styleSheetId);
|
| + this._isMajorChangePending = true;
|
| + this._commitThrottler.schedule(this._syncUISourceCodeChange.bind(this), true);
|
| }
|
|
|
| /**
|
| - * @param {!Protocol.CSS.StyleSheetId} styleSheetId
|
| + * @param {!Common.Event} event
|
| */
|
| - _updateStyleSheetTextSoon(styleSheetId) {
|
| - if (this._updateStyleSheetTextTimer)
|
| - clearTimeout(this._updateStyleSheetTextTimer);
|
| + _workingCopyChanged(event) {
|
| + if (this._isAddingRevision)
|
| + return;
|
|
|
| - this._updateStyleSheetTextTimer = setTimeout(
|
| - this._updateStyleSheetText.bind(this, styleSheetId), Bindings.StylesSourceMapping.ChangeUpdateTimeoutMs);
|
| + this._commitThrottler.schedule(this._syncUISourceCodeChange.bind(this), false);
|
| }
|
|
|
| /**
|
| - * @param {!Protocol.CSS.StyleSheetId} styleSheetId
|
| + * @param {!SDK.CSSStyleSheetHeader} header
|
| + * @return {!Promise}
|
| */
|
| - _updateStyleSheetText(styleSheetId) {
|
| - if (this._updateStyleSheetTextTimer) {
|
| - clearTimeout(this._updateStyleSheetTextTimer);
|
| - delete this._updateStyleSheetTextTimer;
|
| - }
|
| + _syncStyleSheetChange(header) {
|
| + if (this._terminated || !this._headers.has(header))
|
| + return Promise.resolve();
|
|
|
| - var header = this._cssModel.styleSheetHeaderForId(styleSheetId);
|
| - if (!header)
|
| - return;
|
| - var styleSheetURL = header.resourceURL();
|
| - if (!styleSheetURL)
|
| - return;
|
| - var uiSourceCode = Bindings.NetworkProject.uiSourceCodeForStyleURL(this._workspace, styleSheetURL, header);
|
| - if (!uiSourceCode)
|
| - return;
|
| - header.requestContent().then(callback.bind(this, uiSourceCode));
|
| + return header.requestContent().then(onHeaderContent.bind(this));
|
|
|
| /**
|
| - * @param {!Workspace.UISourceCode} uiSourceCode
|
| * @param {?string} content
|
| - * @this {Bindings.StylesSourceMapping}
|
| + * @return {!Promise}
|
| + * @this {Bindings.StyleFile}
|
| */
|
| - function callback(uiSourceCode, content) {
|
| - var styleFile = this._styleFiles.get(uiSourceCode);
|
| - if (typeof content === 'string' && styleFile)
|
| - styleFile.addRevision(content);
|
| - this._styleFileSyncedForTest();
|
| + function onHeaderContent(content) {
|
| + if (this._terminated || content === null) {
|
| + this._styleFileSyncedForTest();
|
| + return Promise.resolve();
|
| + }
|
| + this._isAddingRevision = true;
|
| + this._uiSourceCode.addRevision(content);
|
| + delete this._isAddingRevision;
|
| + return this._setStyleSheetContents(content, header, true);
|
| }
|
| }
|
|
|
| - _styleFileSyncedForTest() {
|
| - }
|
| -
|
| - dispose() {
|
| - Common.EventTarget.removeEventListeners(this._eventListeners);
|
| - }
|
| -};
|
| -
|
| -Bindings.StylesSourceMapping.ChangeUpdateTimeoutMs = 200;
|
| -
|
| -/**
|
| - * @unrestricted
|
| - */
|
| -Bindings.StyleFile = class {
|
| /**
|
| - * @param {!Workspace.UISourceCode} uiSourceCode
|
| - * @param {!Bindings.StylesSourceMapping} mapping
|
| + * @return {!Promise}
|
| */
|
| - constructor(uiSourceCode, mapping) {
|
| - this._uiSourceCode = uiSourceCode;
|
| - this._mapping = mapping;
|
| - this._eventListeners = [
|
| - this._uiSourceCode.addEventListener(
|
| - Workspace.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this),
|
| - this._uiSourceCode.addEventListener(
|
| - Workspace.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this)
|
| - ];
|
| - this._commitThrottler = new Common.Throttler(Bindings.StyleFile.updateTimeout);
|
| - this._terminated = false;
|
| - }
|
| -
|
| - /**
|
| - * @param {!Common.Event} event
|
| - */
|
| - _workingCopyCommitted(event) {
|
| - if (this._isAddingRevision)
|
| - return;
|
| -
|
| - this._isMajorChangePending = true;
|
| - this._commitThrottler.schedule(this._commitIncrementalEdit.bind(this), true);
|
| - }
|
| -
|
| - /**
|
| - * @param {!Common.Event} event
|
| - */
|
| - _workingCopyChanged(event) {
|
| - if (this._isAddingRevision)
|
| - return;
|
| -
|
| - this._commitThrottler.schedule(this._commitIncrementalEdit.bind(this), false);
|
| - }
|
| -
|
| - _commitIncrementalEdit() {
|
| + _syncUISourceCodeChange() {
|
| if (this._terminated)
|
| - return;
|
| - var promise =
|
| - this._mapping._setStyleContent(this._uiSourceCode, this._uiSourceCode.workingCopy(), this._isMajorChangePending)
|
| - .then(this._styleContentSet.bind(this));
|
| + return Promise.resolve();
|
| + var promise = this._setStyleSheetContents(this._uiSourceCode.workingCopy(), null, this._isMajorChangePending);
|
| this._isMajorChangePending = false;
|
| return promise;
|
| }
|
|
|
| /**
|
| - * @param {?string} error
|
| + * @param {string} content
|
| + * @param {?SDK.CSSStyleSheetHeader} skipStyleSheet
|
| + * @param {boolean} majorChange
|
| + * @return {!Promise}
|
| */
|
| - _styleContentSet(error) {
|
| - if (error)
|
| - console.error(error);
|
| + _setStyleSheetContents(content, skipStyleSheet, majorChange) {
|
| + this._isSettingStyleSheetContents = true;
|
| + var promises = [];
|
| + for (var header of this._headers) {
|
| + if (header === skipStyleSheet)
|
| + continue;
|
| + promises.push(this._cssModel.setStyleSheetText(header.id, content, majorChange));
|
| + }
|
| +
|
| + return Promise.all(promises).then(onStyleSheetContentsUpdated.bind(this));
|
| +
|
| + /**
|
| + * @param {!Array<?Protocol.Error>} errors
|
| + * @this {Bindings.StyleFile}
|
| + */
|
| + function onStyleSheetContentsUpdated(errors) {
|
| + delete this._isSettingStyleSheetContents;
|
| + errors.filter(error => !!error).forEach(console.error);
|
| + this._styleFileSyncedForTest();
|
| + }
|
| }
|
|
|
| - /**
|
| - * @param {string} content
|
| - */
|
| - addRevision(content) {
|
| - this._isAddingRevision = true;
|
| - this._uiSourceCode.addRevision(content);
|
| - delete this._isAddingRevision;
|
| + _styleFileSyncedForTest() {
|
| }
|
|
|
| dispose() {
|
|
|