| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| 11 * copyright notice, this list of conditions and the following disclaimer | 11 * copyright notice, this list of conditions and the following disclaimer |
| 12 * in the documentation and/or other materials provided with the | 12 * in the documentation and/or other materials provided with the |
| 13 * distribution. | 13 * distribution. |
| 14 * * Neither the name of Google Inc. nor the names of its | 14 * * Neither the name of Google Inc. nor the names of its |
| 15 * contributors may be used to endorse or promote products derived from | 15 * contributors may be used to endorse or promote products derived from |
| 16 * this software without specific prior written permission. | 16 * this software without specific prior written permission. |
| 17 * | 17 * |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | |
| 31 /** | 30 /** |
| 32 * @constructor | 31 * @unrestricted |
| 33 * @param {!WebInspector.CSSModel} cssModel | |
| 34 * @param {!WebInspector.Workspace} workspace | |
| 35 * @param {!WebInspector.NetworkMapping} networkMapping | |
| 36 */ | 32 */ |
| 37 WebInspector.StylesSourceMapping = function(cssModel, workspace, networkMapping) | 33 WebInspector.StylesSourceMapping = class { |
| 38 { | 34 /** |
| 35 * @param {!WebInspector.CSSModel} cssModel |
| 36 * @param {!WebInspector.Workspace} workspace |
| 37 * @param {!WebInspector.NetworkMapping} networkMapping |
| 38 */ |
| 39 constructor(cssModel, workspace, networkMapping) { |
| 39 this._cssModel = cssModel; | 40 this._cssModel = cssModel; |
| 40 this._workspace = workspace; | 41 this._workspace = workspace; |
| 41 this._networkMapping = networkMapping; | 42 this._networkMapping = networkMapping; |
| 42 | 43 |
| 43 /** @type {!Map<string, !Map<string, !Map<string, !WebInspector.CSSStyleShee
tHeader>>>} */ | 44 /** @type {!Map<string, !Map<string, !Map<string, !WebInspector.CSSStyleShee
tHeader>>>} */ |
| 44 this._urlToHeadersByFrameId = new Map(); | 45 this._urlToHeadersByFrameId = new Map(); |
| 45 /** @type {!Map.<!WebInspector.UISourceCode, !WebInspector.StyleFile>} */ | 46 /** @type {!Map.<!WebInspector.UISourceCode, !WebInspector.StyleFile>} */ |
| 46 this._styleFiles = new Map(); | 47 this._styleFiles = new Map(); |
| 47 | 48 |
| 48 this._eventListeners = [ | 49 this._eventListeners = [ |
| 49 this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectRe
moved, this._projectRemoved, this), | 50 this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectRemo
ved, this._projectRemoved, this), |
| 50 this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceC
odeAdded, this._uiSourceCodeAddedToWorkspace, this), | 51 this._workspace.addEventListener( |
| 51 this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceC
odeRemoved, this._uiSourceCodeRemoved, this), | 52 WebInspector.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdd
edToWorkspace, this), |
| 52 this._cssModel.addEventListener(WebInspector.CSSModel.Events.StyleSheetA
dded, this._styleSheetAdded, this), | 53 this._workspace.addEventListener( |
| 53 this._cssModel.addEventListener(WebInspector.CSSModel.Events.StyleSheetR
emoved, this._styleSheetRemoved, this), | 54 WebInspector.Workspace.Events.UISourceCodeRemoved, this._uiSourceCodeR
emoved, this), |
| 54 this._cssModel.addEventListener(WebInspector.CSSModel.Events.StyleSheetC
hanged, this._styleSheetChanged, this), | 55 this._cssModel.addEventListener(WebInspector.CSSModel.Events.StyleSheetAdd
ed, this._styleSheetAdded, this), |
| 55 WebInspector.ResourceTreeModel.fromTarget(cssModel.target()).addEventLis
tener( | 56 this._cssModel.addEventListener(WebInspector.CSSModel.Events.StyleSheetRem
oved, this._styleSheetRemoved, this), |
| 56 WebInspector.ResourceTreeModel.Events.MainFrameNavigated, this._unbi
ndAllUISourceCodes, this) | 57 this._cssModel.addEventListener(WebInspector.CSSModel.Events.StyleSheetCha
nged, this._styleSheetChanged, this), |
| 58 WebInspector.ResourceTreeModel.fromTarget(cssModel.target()) |
| 59 .addEventListener( |
| 60 WebInspector.ResourceTreeModel.Events.MainFrameNavigated, this._un
bindAllUISourceCodes, this) |
| 57 ]; | 61 ]; |
| 58 }; | 62 } |
| 59 | 63 |
| 60 WebInspector.StylesSourceMapping.ChangeUpdateTimeoutMs = 200; | 64 /** |
| 61 | 65 * @param {!WebInspector.CSSLocation} rawLocation |
| 62 WebInspector.StylesSourceMapping.prototype = { | 66 * @return {?WebInspector.UILocation} |
| 63 /** | 67 */ |
| 64 * @param {!WebInspector.CSSLocation} rawLocation | 68 rawLocationToUILocation(rawLocation) { |
| 65 * @return {?WebInspector.UILocation} | 69 var uiSourceCode = this._networkMapping.uiSourceCodeForStyleURL(rawLocation.
url, rawLocation.header()); |
| 66 */ | 70 if (!uiSourceCode) |
| 67 rawLocationToUILocation: function(rawLocation) | 71 return null; |
| 68 { | 72 var lineNumber = rawLocation.lineNumber; |
| 69 var uiSourceCode = this._networkMapping.uiSourceCodeForStyleURL(rawLocat
ion.url, rawLocation.header()); | 73 var columnNumber = rawLocation.columnNumber; |
| 70 if (!uiSourceCode) | 74 var header = this._cssModel.styleSheetHeaderForId(rawLocation.styleSheetId); |
| 71 return null; | 75 if (header && header.isInline && header.hasSourceURL) { |
| 72 var lineNumber = rawLocation.lineNumber; | 76 lineNumber -= header.lineNumberInSource(0); |
| 73 var columnNumber = rawLocation.columnNumber; | 77 columnNumber -= header.columnNumberInSource(lineNumber, 0); |
| 74 var header = this._cssModel.styleSheetHeaderForId(rawLocation.styleSheet
Id); | 78 } |
| 75 if (header && header.isInline && header.hasSourceURL) { | 79 return uiSourceCode.uiLocation(lineNumber, columnNumber); |
| 76 lineNumber -= header.lineNumberInSource(0); | 80 } |
| 77 columnNumber -= header.columnNumberInSource(lineNumber, 0); | 81 |
| 78 } | 82 /** |
| 79 return uiSourceCode.uiLocation(lineNumber, columnNumber); | 83 * @param {!WebInspector.Event} event |
| 80 }, | 84 */ |
| 81 | 85 _styleSheetAdded(event) { |
| 82 /** | 86 var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.data); |
| 83 * @param {!WebInspector.Event} event | 87 var url = header.resourceURL(); |
| 84 */ | 88 if (!url) |
| 85 _styleSheetAdded: function(event) | 89 return; |
| 86 { | 90 |
| 87 var header = /** @type {!WebInspector.CSSStyleSheetHeader} */(event.data
); | 91 var map = this._urlToHeadersByFrameId.get(url); |
| 88 var url = header.resourceURL(); | 92 if (!map) { |
| 89 if (!url) | 93 map = /** @type {!Map.<string, !Map.<string, !WebInspector.CSSStyleSheetHe
ader>>} */ (new Map()); |
| 90 return; | 94 this._urlToHeadersByFrameId.set(url, map); |
| 91 | 95 } |
| 92 var map = this._urlToHeadersByFrameId.get(url); | 96 var headersById = map.get(header.frameId); |
| 93 if (!map) { | 97 if (!headersById) { |
| 94 map = /** @type {!Map.<string, !Map.<string, !WebInspector.CSSStyleS
heetHeader>>} */ (new Map()); | 98 headersById = /** @type {!Map.<string, !WebInspector.CSSStyleSheetHeader>}
*/ (new Map()); |
| 95 this._urlToHeadersByFrameId.set(url, map); | 99 map.set(header.frameId, headersById); |
| 96 } | 100 } |
| 97 var headersById = map.get(header.frameId); | 101 headersById.set(header.id, header); |
| 98 if (!headersById) { | 102 var uiSourceCode = this._networkMapping.uiSourceCodeForStyleURL(url, header)
; |
| 99 headersById = /** @type {!Map.<string, !WebInspector.CSSStyleSheetHe
ader>} */ (new Map()); | 103 if (uiSourceCode) |
| 100 map.set(header.frameId, headersById); | 104 this._bindUISourceCode(uiSourceCode, header); |
| 101 } | 105 } |
| 102 headersById.set(header.id, header); | 106 |
| 107 /** |
| 108 * @param {!WebInspector.Event} event |
| 109 */ |
| 110 _styleSheetRemoved(event) { |
| 111 var header = /** @type {!WebInspector.CSSStyleSheetHeader} */ (event.data); |
| 112 var url = header.resourceURL(); |
| 113 if (!url) |
| 114 return; |
| 115 |
| 116 var map = this._urlToHeadersByFrameId.get(url); |
| 117 console.assert(map); |
| 118 var headersById = map.get(header.frameId); |
| 119 console.assert(headersById); |
| 120 headersById.delete(header.id); |
| 121 |
| 122 if (!headersById.size) { |
| 123 map.delete(header.frameId); |
| 124 if (!map.size) { |
| 125 this._urlToHeadersByFrameId.delete(url); |
| 103 var uiSourceCode = this._networkMapping.uiSourceCodeForStyleURL(url, hea
der); | 126 var uiSourceCode = this._networkMapping.uiSourceCodeForStyleURL(url, hea
der); |
| 104 if (uiSourceCode) | 127 if (uiSourceCode) |
| 105 this._bindUISourceCode(uiSourceCode, header); | 128 this._unbindUISourceCode(uiSourceCode); |
| 106 }, | 129 } |
| 130 } |
| 131 } |
| 132 |
| 133 /** |
| 134 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 135 */ |
| 136 _unbindUISourceCode(uiSourceCode) { |
| 137 var styleFile = this._styleFiles.get(uiSourceCode); |
| 138 if (!styleFile) |
| 139 return; |
| 140 styleFile.dispose(); |
| 141 this._styleFiles.delete(uiSourceCode); |
| 142 } |
| 143 |
| 144 /** |
| 145 * @param {!WebInspector.Event} event |
| 146 */ |
| 147 _unbindAllUISourceCodes(event) { |
| 148 if (event.data.target() !== this._cssModel.target()) |
| 149 return; |
| 150 for (var styleFile of this._styleFiles.values()) |
| 151 styleFile.dispose(); |
| 152 this._styleFiles.clear(); |
| 153 this._urlToHeadersByFrameId = new Map(); |
| 154 } |
| 155 |
| 156 /** |
| 157 * @param {!WebInspector.Event} event |
| 158 */ |
| 159 _uiSourceCodeAddedToWorkspace(event) { |
| 160 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data); |
| 161 if (!this._urlToHeadersByFrameId.has(uiSourceCode.url())) |
| 162 return; |
| 163 this._bindUISourceCode( |
| 164 uiSourceCode, this._urlToHeadersByFrameId.get(uiSourceCode.url()).values
Array()[0].valuesArray()[0]); |
| 165 } |
| 166 |
| 167 /** |
| 168 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 169 * @param {!WebInspector.CSSStyleSheetHeader} header |
| 170 */ |
| 171 _bindUISourceCode(uiSourceCode, header) { |
| 172 if (this._styleFiles.get(uiSourceCode) || (header.isInline && !header.hasSou
rceURL)) |
| 173 return; |
| 174 this._styleFiles.set(uiSourceCode, new WebInspector.StyleFile(uiSourceCode,
this)); |
| 175 WebInspector.cssWorkspaceBinding.updateLocations(header); |
| 176 } |
| 177 |
| 178 /** |
| 179 * @param {!WebInspector.Event} event |
| 180 */ |
| 181 _projectRemoved(event) { |
| 182 var project = /** @type {!WebInspector.Project} */ (event.data); |
| 183 var uiSourceCodes = project.uiSourceCodes(); |
| 184 for (var i = 0; i < uiSourceCodes.length; ++i) |
| 185 this._unbindUISourceCode(uiSourceCodes[i]); |
| 186 } |
| 187 |
| 188 /** |
| 189 * @param {!WebInspector.Event} event |
| 190 */ |
| 191 _uiSourceCodeRemoved(event) { |
| 192 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data); |
| 193 this._unbindUISourceCode(uiSourceCode); |
| 194 } |
| 195 |
| 196 /** |
| 197 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 198 * @param {string} content |
| 199 * @param {boolean} majorChange |
| 200 * @return {!Promise<?string>} |
| 201 */ |
| 202 _setStyleContent(uiSourceCode, content, majorChange) { |
| 203 var styleSheetIds = this._cssModel.styleSheetIdsForURL(uiSourceCode.url()); |
| 204 if (!styleSheetIds.length) |
| 205 return Promise.resolve(/** @type {?string} */ ('No stylesheet found: ' + u
iSourceCode.url())); |
| 206 |
| 207 this._isSettingContent = true; |
| 107 | 208 |
| 108 /** | 209 /** |
| 109 * @param {!WebInspector.Event} event | 210 * @param {?string} error |
| 211 * @this {WebInspector.StylesSourceMapping} |
| 212 * @return {?string} |
| 110 */ | 213 */ |
| 111 _styleSheetRemoved: function(event) | 214 function callback(error) { |
| 112 { | 215 delete this._isSettingContent; |
| 113 var header = /** @type {!WebInspector.CSSStyleSheetHeader} */(event.data
); | 216 return error || null; |
| 114 var url = header.resourceURL(); | 217 } |
| 115 if (!url) | 218 |
| 116 return; | 219 var promises = []; |
| 117 | 220 for (var i = 0; i < styleSheetIds.length; ++i) |
| 118 var map = this._urlToHeadersByFrameId.get(url); | 221 promises.push(this._cssModel.setStyleSheetText(styleSheetIds[i], content,
majorChange)); |
| 119 console.assert(map); | 222 |
| 120 var headersById = map.get(header.frameId); | 223 return Promise.all(promises).spread(callback.bind(this)); |
| 121 console.assert(headersById); | 224 } |
| 122 headersById.delete(header.id); | 225 |
| 123 | 226 /** |
| 124 if (!headersById.size) { | 227 * @param {!WebInspector.Event} event |
| 125 map.delete(header.frameId); | 228 */ |
| 126 if (!map.size) { | 229 _styleSheetChanged(event) { |
| 127 this._urlToHeadersByFrameId.delete(url); | 230 if (this._isSettingContent) |
| 128 var uiSourceCode = this._networkMapping.uiSourceCodeForStyleURL(
url, header); | 231 return; |
| 129 if (uiSourceCode) | 232 |
| 130 this._unbindUISourceCode(uiSourceCode); | 233 this._updateStyleSheetTextSoon(event.data.styleSheetId); |
| 131 } | 234 } |
| 132 } | 235 |
| 133 }, | 236 /** |
| 237 * @param {!CSSAgent.StyleSheetId} styleSheetId |
| 238 */ |
| 239 _updateStyleSheetTextSoon(styleSheetId) { |
| 240 if (this._updateStyleSheetTextTimer) |
| 241 clearTimeout(this._updateStyleSheetTextTimer); |
| 242 |
| 243 this._updateStyleSheetTextTimer = setTimeout( |
| 244 this._updateStyleSheetText.bind(this, styleSheetId), WebInspector.Styles
SourceMapping.ChangeUpdateTimeoutMs); |
| 245 } |
| 246 |
| 247 /** |
| 248 * @param {!CSSAgent.StyleSheetId} styleSheetId |
| 249 */ |
| 250 _updateStyleSheetText(styleSheetId) { |
| 251 if (this._updateStyleSheetTextTimer) { |
| 252 clearTimeout(this._updateStyleSheetTextTimer); |
| 253 delete this._updateStyleSheetTextTimer; |
| 254 } |
| 255 |
| 256 var header = this._cssModel.styleSheetHeaderForId(styleSheetId); |
| 257 if (!header) |
| 258 return; |
| 259 var styleSheetURL = header.resourceURL(); |
| 260 if (!styleSheetURL) |
| 261 return; |
| 262 var uiSourceCode = this._networkMapping.uiSourceCodeForStyleURL(styleSheetUR
L, header); |
| 263 if (!uiSourceCode) |
| 264 return; |
| 265 header.requestContent().then(callback.bind(this, uiSourceCode)); |
| 134 | 266 |
| 135 /** | 267 /** |
| 136 * @param {!WebInspector.UISourceCode} uiSourceCode | 268 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 269 * @param {?string} content |
| 270 * @this {WebInspector.StylesSourceMapping} |
| 137 */ | 271 */ |
| 138 _unbindUISourceCode: function(uiSourceCode) | 272 function callback(uiSourceCode, content) { |
| 139 { | 273 var styleFile = this._styleFiles.get(uiSourceCode); |
| 140 var styleFile = this._styleFiles.get(uiSourceCode); | 274 if (styleFile) |
| 141 if (!styleFile) | 275 styleFile.addRevision(content || ''); |
| 142 return; | 276 } |
| 143 styleFile.dispose(); | 277 } |
| 144 this._styleFiles.delete(uiSourceCode); | 278 |
| 145 }, | 279 dispose() { |
| 146 | 280 WebInspector.EventTarget.removeEventListeners(this._eventListeners); |
| 147 /** | 281 } |
| 148 * @param {!WebInspector.Event} event | |
| 149 */ | |
| 150 _unbindAllUISourceCodes: function(event) | |
| 151 { | |
| 152 if (event.data.target() !== this._cssModel.target()) | |
| 153 return; | |
| 154 for (var styleFile of this._styleFiles.values()) | |
| 155 styleFile.dispose(); | |
| 156 this._styleFiles.clear(); | |
| 157 this._urlToHeadersByFrameId = new Map(); | |
| 158 }, | |
| 159 | |
| 160 /** | |
| 161 * @param {!WebInspector.Event} event | |
| 162 */ | |
| 163 _uiSourceCodeAddedToWorkspace: function(event) | |
| 164 { | |
| 165 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data
); | |
| 166 if (!this._urlToHeadersByFrameId.has(uiSourceCode.url())) | |
| 167 return; | |
| 168 this._bindUISourceCode(uiSourceCode, this._urlToHeadersByFrameId.get(uiS
ourceCode.url()).valuesArray()[0].valuesArray()[0]); | |
| 169 }, | |
| 170 | |
| 171 /** | |
| 172 * @param {!WebInspector.UISourceCode} uiSourceCode | |
| 173 * @param {!WebInspector.CSSStyleSheetHeader} header | |
| 174 */ | |
| 175 _bindUISourceCode: function(uiSourceCode, header) | |
| 176 { | |
| 177 if (this._styleFiles.get(uiSourceCode) || (header.isInline && !header.ha
sSourceURL)) | |
| 178 return; | |
| 179 this._styleFiles.set(uiSourceCode, new WebInspector.StyleFile(uiSourceCo
de, this)); | |
| 180 WebInspector.cssWorkspaceBinding.updateLocations(header); | |
| 181 }, | |
| 182 | |
| 183 /** | |
| 184 * @param {!WebInspector.Event} event | |
| 185 */ | |
| 186 _projectRemoved: function(event) | |
| 187 { | |
| 188 var project = /** @type {!WebInspector.Project} */ (event.data); | |
| 189 var uiSourceCodes = project.uiSourceCodes(); | |
| 190 for (var i = 0; i < uiSourceCodes.length; ++i) | |
| 191 this._unbindUISourceCode(uiSourceCodes[i]); | |
| 192 }, | |
| 193 | |
| 194 /** | |
| 195 * @param {!WebInspector.Event} event | |
| 196 */ | |
| 197 _uiSourceCodeRemoved: function(event) | |
| 198 { | |
| 199 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data
); | |
| 200 this._unbindUISourceCode(uiSourceCode); | |
| 201 }, | |
| 202 | |
| 203 /** | |
| 204 * @param {!WebInspector.UISourceCode} uiSourceCode | |
| 205 * @param {string} content | |
| 206 * @param {boolean} majorChange | |
| 207 * @return {!Promise<?string>} | |
| 208 */ | |
| 209 _setStyleContent: function(uiSourceCode, content, majorChange) | |
| 210 { | |
| 211 var styleSheetIds = this._cssModel.styleSheetIdsForURL(uiSourceCode.url(
)); | |
| 212 if (!styleSheetIds.length) | |
| 213 return Promise.resolve(/** @type {?string} */("No stylesheet found:
" + uiSourceCode.url())); | |
| 214 | |
| 215 this._isSettingContent = true; | |
| 216 | |
| 217 /** | |
| 218 * @param {?string} error | |
| 219 * @this {WebInspector.StylesSourceMapping} | |
| 220 * @return {?string} | |
| 221 */ | |
| 222 function callback(error) | |
| 223 { | |
| 224 delete this._isSettingContent; | |
| 225 return error || null; | |
| 226 } | |
| 227 | |
| 228 var promises = []; | |
| 229 for (var i = 0; i < styleSheetIds.length; ++i) | |
| 230 promises.push(this._cssModel.setStyleSheetText(styleSheetIds[i], con
tent, majorChange)); | |
| 231 | |
| 232 return Promise.all(promises).spread(callback.bind(this)); | |
| 233 }, | |
| 234 | |
| 235 /** | |
| 236 * @param {!WebInspector.Event} event | |
| 237 */ | |
| 238 _styleSheetChanged: function(event) | |
| 239 { | |
| 240 if (this._isSettingContent) | |
| 241 return; | |
| 242 | |
| 243 this._updateStyleSheetTextSoon(event.data.styleSheetId); | |
| 244 }, | |
| 245 | |
| 246 /** | |
| 247 * @param {!CSSAgent.StyleSheetId} styleSheetId | |
| 248 */ | |
| 249 _updateStyleSheetTextSoon: function(styleSheetId) | |
| 250 { | |
| 251 if (this._updateStyleSheetTextTimer) | |
| 252 clearTimeout(this._updateStyleSheetTextTimer); | |
| 253 | |
| 254 this._updateStyleSheetTextTimer = setTimeout(this._updateStyleSheetText.
bind(this, styleSheetId), WebInspector.StylesSourceMapping.ChangeUpdateTimeoutMs
); | |
| 255 }, | |
| 256 | |
| 257 /** | |
| 258 * @param {!CSSAgent.StyleSheetId} styleSheetId | |
| 259 */ | |
| 260 _updateStyleSheetText: function(styleSheetId) | |
| 261 { | |
| 262 if (this._updateStyleSheetTextTimer) { | |
| 263 clearTimeout(this._updateStyleSheetTextTimer); | |
| 264 delete this._updateStyleSheetTextTimer; | |
| 265 } | |
| 266 | |
| 267 var header = this._cssModel.styleSheetHeaderForId(styleSheetId); | |
| 268 if (!header) | |
| 269 return; | |
| 270 var styleSheetURL = header.resourceURL(); | |
| 271 if (!styleSheetURL) | |
| 272 return; | |
| 273 var uiSourceCode = this._networkMapping.uiSourceCodeForStyleURL(styleShe
etURL, header); | |
| 274 if (!uiSourceCode) | |
| 275 return; | |
| 276 header.requestContent().then(callback.bind(this, uiSourceCode)); | |
| 277 | |
| 278 /** | |
| 279 * @param {!WebInspector.UISourceCode} uiSourceCode | |
| 280 * @param {?string} content | |
| 281 * @this {WebInspector.StylesSourceMapping} | |
| 282 */ | |
| 283 function callback(uiSourceCode, content) | |
| 284 { | |
| 285 var styleFile = this._styleFiles.get(uiSourceCode); | |
| 286 if (styleFile) | |
| 287 styleFile.addRevision(content || ""); | |
| 288 } | |
| 289 }, | |
| 290 | |
| 291 dispose: function() | |
| 292 { | |
| 293 WebInspector.EventTarget.removeEventListeners(this._eventListeners); | |
| 294 } | |
| 295 }; | 282 }; |
| 296 | 283 |
| 284 WebInspector.StylesSourceMapping.ChangeUpdateTimeoutMs = 200; |
| 285 |
| 297 /** | 286 /** |
| 298 * @constructor | 287 * @unrestricted |
| 299 * @param {!WebInspector.UISourceCode} uiSourceCode | |
| 300 * @param {!WebInspector.StylesSourceMapping} mapping | |
| 301 */ | 288 */ |
| 302 WebInspector.StyleFile = function(uiSourceCode, mapping) | 289 WebInspector.StyleFile = class { |
| 303 { | 290 /** |
| 291 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 292 * @param {!WebInspector.StylesSourceMapping} mapping |
| 293 */ |
| 294 constructor(uiSourceCode, mapping) { |
| 304 this._uiSourceCode = uiSourceCode; | 295 this._uiSourceCode = uiSourceCode; |
| 305 this._mapping = mapping; | 296 this._mapping = mapping; |
| 306 this._eventListeners = [ | 297 this._eventListeners = [ |
| 307 this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.Wor
kingCopyChanged, this._workingCopyChanged, this), | 298 this._uiSourceCode.addEventListener( |
| 308 this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.Wor
kingCopyCommitted, this._workingCopyCommitted, this) | 299 WebInspector.UISourceCode.Events.WorkingCopyChanged, this._workingCopy
Changed, this), |
| 300 this._uiSourceCode.addEventListener( |
| 301 WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._workingCo
pyCommitted, this) |
| 309 ]; | 302 ]; |
| 310 this._commitThrottler = new WebInspector.Throttler(WebInspector.StyleFile.up
dateTimeout); | 303 this._commitThrottler = new WebInspector.Throttler(WebInspector.StyleFile.up
dateTimeout); |
| 311 this._terminated = false; | 304 this._terminated = false; |
| 305 } |
| 306 |
| 307 /** |
| 308 * @param {!WebInspector.Event} event |
| 309 */ |
| 310 _workingCopyCommitted(event) { |
| 311 if (this._isAddingRevision) |
| 312 return; |
| 313 |
| 314 this._isMajorChangePending = true; |
| 315 this._commitThrottler.schedule(this._commitIncrementalEdit.bind(this), true)
; |
| 316 } |
| 317 |
| 318 /** |
| 319 * @param {!WebInspector.Event} event |
| 320 */ |
| 321 _workingCopyChanged(event) { |
| 322 if (this._isAddingRevision) |
| 323 return; |
| 324 |
| 325 this._commitThrottler.schedule(this._commitIncrementalEdit.bind(this), false
); |
| 326 } |
| 327 |
| 328 _commitIncrementalEdit() { |
| 329 if (this._terminated) |
| 330 return; |
| 331 var promise = |
| 332 this._mapping._setStyleContent(this._uiSourceCode, this._uiSourceCode.wo
rkingCopy(), this._isMajorChangePending) |
| 333 .then(this._styleContentSet.bind(this)); |
| 334 this._isMajorChangePending = false; |
| 335 return promise; |
| 336 } |
| 337 |
| 338 /** |
| 339 * @param {?string} error |
| 340 */ |
| 341 _styleContentSet(error) { |
| 342 if (error) |
| 343 console.error(error); |
| 344 } |
| 345 |
| 346 /** |
| 347 * @param {string} content |
| 348 */ |
| 349 addRevision(content) { |
| 350 this._isAddingRevision = true; |
| 351 this._uiSourceCode.addRevision(content); |
| 352 delete this._isAddingRevision; |
| 353 } |
| 354 |
| 355 dispose() { |
| 356 if (this._terminated) |
| 357 return; |
| 358 this._terminated = true; |
| 359 WebInspector.EventTarget.removeEventListeners(this._eventListeners); |
| 360 } |
| 312 }; | 361 }; |
| 313 | 362 |
| 314 WebInspector.StyleFile.updateTimeout = 200; | 363 WebInspector.StyleFile.updateTimeout = 200; |
| 315 | |
| 316 WebInspector.StyleFile.prototype = { | |
| 317 /** | |
| 318 * @param {!WebInspector.Event} event | |
| 319 */ | |
| 320 _workingCopyCommitted: function(event) | |
| 321 { | |
| 322 if (this._isAddingRevision) | |
| 323 return; | |
| 324 | |
| 325 this._isMajorChangePending = true; | |
| 326 this._commitThrottler.schedule(this._commitIncrementalEdit.bind(this), t
rue); | |
| 327 }, | |
| 328 | |
| 329 /** | |
| 330 * @param {!WebInspector.Event} event | |
| 331 */ | |
| 332 _workingCopyChanged: function(event) | |
| 333 { | |
| 334 if (this._isAddingRevision) | |
| 335 return; | |
| 336 | |
| 337 this._commitThrottler.schedule(this._commitIncrementalEdit.bind(this), f
alse); | |
| 338 }, | |
| 339 | |
| 340 _commitIncrementalEdit: function() | |
| 341 { | |
| 342 if (this._terminated) | |
| 343 return; | |
| 344 var promise = this._mapping._setStyleContent(this._uiSourceCode, this._u
iSourceCode.workingCopy(), this._isMajorChangePending) | |
| 345 .then(this._styleContentSet.bind(this)); | |
| 346 this._isMajorChangePending = false; | |
| 347 return promise; | |
| 348 }, | |
| 349 | |
| 350 /** | |
| 351 * @param {?string} error | |
| 352 */ | |
| 353 _styleContentSet: function(error) | |
| 354 { | |
| 355 if (error) | |
| 356 console.error(error); | |
| 357 }, | |
| 358 | |
| 359 /** | |
| 360 * @param {string} content | |
| 361 */ | |
| 362 addRevision: function(content) | |
| 363 { | |
| 364 this._isAddingRevision = true; | |
| 365 this._uiSourceCode.addRevision(content); | |
| 366 delete this._isAddingRevision; | |
| 367 }, | |
| 368 | |
| 369 dispose: function() | |
| 370 { | |
| 371 if (this._terminated) | |
| 372 return; | |
| 373 this._terminated = true; | |
| 374 WebInspector.EventTarget.removeEventListeners(this._eventListeners); | |
| 375 } | |
| 376 }; | |
| OLD | NEW |