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 |