initial import
[vuplus_webkit] / Source / WebCore / inspector / front-end / CSSStyleModel.js
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
29  */
30
31 /**
32  * @constructor
33  * @extends {WebInspector.Object}
34  */
35 WebInspector.CSSStyleModel = function()
36 {
37     new WebInspector.CSSStyleModelResourceBinding(this);
38 }
39
40 WebInspector.CSSStyleModel.parseRuleArrayPayload = function(ruleArray)
41 {
42     var result = [];
43     for (var i = 0; i < ruleArray.length; ++i)
44         result.push(WebInspector.CSSRule.parsePayload(ruleArray[i]));
45     return result;
46 }
47
48 WebInspector.CSSStyleModel.Events = {
49     StyleSheetChanged: 0
50 }
51
52 WebInspector.CSSStyleModel.prototype = {
53     getStylesAsync: function(nodeId, forcedPseudoClasses, userCallback)
54     {
55         function callback(userCallback, error, payload)
56         {
57             if (error) {
58                 if (userCallback)
59                     userCallback(null);
60                 return;
61             }
62
63             var result = {};
64             if ("inlineStyle" in payload)
65                 result.inlineStyle = WebInspector.CSSStyleDeclaration.parsePayload(payload.inlineStyle);
66
67             result.computedStyle = WebInspector.CSSStyleDeclaration.parsePayload(payload.computedStyle);
68             result.matchedCSSRules = WebInspector.CSSStyleModel.parseRuleArrayPayload(payload.matchedCSSRules);
69
70             result.styleAttributes = {};
71             var payloadStyleAttributes = payload.styleAttributes;
72             for (var i = 0; i < payloadStyleAttributes.length; ++i) {
73                 var name = payloadStyleAttributes[i].name;
74                 result.styleAttributes[name] = WebInspector.CSSStyleDeclaration.parsePayload(payloadStyleAttributes[i].style);
75             }
76
77             result.pseudoElements = [];
78             for (var i = 0; i < payload.pseudoElements.length; ++i) {
79                 var entryPayload = payload.pseudoElements[i];
80                 result.pseudoElements.push({ pseudoId: entryPayload.pseudoId, rules: WebInspector.CSSStyleModel.parseRuleArrayPayload(entryPayload.rules) });
81             }
82
83             result.inherited = [];
84             for (var i = 0; i < payload.inherited.length; ++i) {
85                 var entryPayload = payload.inherited[i];
86                 var entry = {};
87                 if ("inlineStyle" in entryPayload)
88                     entry.inlineStyle = WebInspector.CSSStyleDeclaration.parsePayload(entryPayload.inlineStyle);
89                 if ("matchedCSSRules" in entryPayload)
90                     entry.matchedCSSRules = WebInspector.CSSStyleModel.parseRuleArrayPayload(entryPayload.matchedCSSRules);
91                 result.inherited.push(entry);
92             }
93
94             if (userCallback)
95                 userCallback(result);
96         }
97
98         CSSAgent.getStylesForNode(nodeId, forcedPseudoClasses || [], callback.bind(null, userCallback));
99     },
100
101     getComputedStyleAsync: function(nodeId, userCallback)
102     {
103         function callback(userCallback, error, stylePayload)
104         {
105             if (error)
106                 userCallback(null);
107             else
108                 userCallback(WebInspector.CSSStyleDeclaration.parsePayload(stylePayload));
109         }
110
111         CSSAgent.getComputedStyleForNode(nodeId, callback.bind(null, userCallback));
112     },
113
114     getInlineStyleAsync: function(nodeId, userCallback)
115     {
116         function callback(userCallback, error, stylePayload)
117         {
118             if (error)
119                 userCallback(null);
120             else
121                 userCallback(WebInspector.CSSStyleDeclaration.parsePayload(stylePayload));
122         }
123
124         CSSAgent.getInlineStyleForNode(nodeId, callback.bind(null, userCallback));
125     },
126
127     setRuleSelector: function(ruleId, nodeId, newSelector, successCallback, failureCallback)
128     {
129         function checkAffectsCallback(nodeId, successCallback, rulePayload, selectedNodeIds)
130         {
131             if (!selectedNodeIds)
132                 return;
133             var doesAffectSelectedNode = (selectedNodeIds.indexOf(nodeId) >= 0);
134             var rule = WebInspector.CSSRule.parsePayload(rulePayload);
135             successCallback(rule, doesAffectSelectedNode);
136             this._fireStyleSheetChanged(rule.id.styleSheetId, true);
137         }
138
139         function callback(nodeId, successCallback, failureCallback, error, newSelector, rulePayload)
140         {
141             // FIXME: looks like rulePayload is always null.
142             if (error)
143                 failureCallback();
144             else {
145                 var documentElementId = this._documentElementId(nodeId);
146                 if (documentElementId)
147                     WebInspector.domAgent.querySelectorAll(documentElementId, newSelector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload));
148                 else
149                     failureCallback();
150             }
151         }
152
153         CSSAgent.setRuleSelector(ruleId, newSelector, callback.bind(this, nodeId, successCallback, failureCallback, newSelector));
154     },
155
156     addRule: function(nodeId, selector, successCallback, failureCallback)
157     {
158         function checkAffectsCallback(nodeId, successCallback, rulePayload, selectedNodeIds)
159         {
160             if (!selectedNodeIds)
161                 return;
162
163             var doesAffectSelectedNode = (selectedNodeIds.indexOf(nodeId) >= 0);
164             var rule = WebInspector.CSSRule.parsePayload(rulePayload);
165             successCallback(rule, doesAffectSelectedNode);
166             this._fireStyleSheetChanged(rule.id.styleSheetId, true);
167         }
168
169         function callback(successCallback, failureCallback, selector, error, rulePayload)
170         {
171             if (error) {
172                 // Invalid syntax for a selector
173                 failureCallback();
174             } else {
175                 var documentElementId = this._documentElementId(nodeId);
176                 if (documentElementId)
177                     WebInspector.domAgent.querySelectorAll(documentElementId, selector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload));
178                 else
179                     failureCallback();
180             }
181         }
182
183         CSSAgent.addRule(nodeId, selector, callback.bind(this, successCallback, failureCallback, selector));
184     },
185
186     _documentElementId: function(nodeId)
187     {
188         var node = WebInspector.domAgent.nodeForId(nodeId);
189         if (!node)
190             return null;
191         return node.ownerDocumentElement().id;
192     },
193
194     _fireStyleSheetChanged: function(styleSheetId, majorChange, callback)
195     {
196         callback = callback || function() {};
197
198         if (!majorChange || !styleSheetId || !this.hasEventListeners(WebInspector.CSSStyleModel.Events.StyleSheetChanged)) {
199             callback();
200             return;
201         }
202
203         function mycallback(error, content)
204         {
205             if (!error)
206                 this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.StyleSheetChanged, { styleSheetId: styleSheetId, content: content, majorChange: majorChange });
207             callback();
208         }
209
210         CSSAgent.getStyleSheetText(styleSheetId, mycallback.bind(this));
211     },
212
213     setStyleSheetText: function(styleSheetId, newText, majorChange, userCallback)
214     {
215         function callback(error)
216         {
217              if (!error)
218                  this._fireStyleSheetChanged(styleSheetId, majorChange, userCallback ? userCallback.bind(this, error) : null);
219         }
220         CSSAgent.setStyleSheetText(styleSheetId, newText, callback.bind(this));
221     }
222 }
223
224 WebInspector.CSSStyleModel.prototype.__proto__ = WebInspector.Object.prototype;
225
226 /**
227  * @constructor
228  * @param {*} payload
229  */
230 WebInspector.CSSStyleDeclaration = function(payload)
231 {
232     this.id = payload.styleId;
233     this.width = payload.width;
234     this.height = payload.height;
235     this.range = payload.range;
236     this._shorthandValues = WebInspector.CSSStyleDeclaration.buildShorthandValueMap(payload.shorthandEntries);
237     this._livePropertyMap = {}; // LIVE properties (source-based or style-based) : { name -> CSSProperty }
238     this._allProperties = []; // ALL properties: [ CSSProperty ]
239     this._longhandProperties = {}; // shorthandName -> [ CSSProperty ]
240     this.__disabledProperties = {}; // DISABLED properties: { index -> CSSProperty }
241     var payloadPropertyCount = payload.cssProperties.length;
242
243     var propertyIndex = 0;
244     for (var i = 0; i < payloadPropertyCount; ++i) {
245         var property = new WebInspector.CSSProperty.parsePayload(this, i, payload.cssProperties[i]);
246         this._allProperties.push(property);
247         if (property.disabled)
248             this.__disabledProperties[i] = property;
249         if (!property.active && !property.styleBased)
250             continue;
251         var name = property.name;
252         this[propertyIndex] = name;
253         this._livePropertyMap[name] = property;
254
255         // Index longhand properties.
256         if (property.shorthand) { // only for parsed
257             var longhands = this._longhandProperties[property.shorthand];
258             if (!longhands) {
259                 longhands = [];
260                 this._longhandProperties[property.shorthand] = longhands;
261             }
262             longhands.push(property);
263         }
264         ++propertyIndex;
265     }
266     this.length = propertyIndex;
267     if ("cssText" in payload)
268         this.cssText = payload.cssText;
269 }
270
271 WebInspector.CSSStyleDeclaration.buildShorthandValueMap = function(shorthandEntries)
272 {
273     var result = {};
274     for (var i = 0; i < shorthandEntries.length; ++i)
275         result[shorthandEntries[i].name] = shorthandEntries[i].value;
276     return result;
277 }
278
279 WebInspector.CSSStyleDeclaration.parsePayload = function(payload)
280 {
281     return new WebInspector.CSSStyleDeclaration(payload);
282 }
283
284 WebInspector.CSSStyleDeclaration.prototype = {
285     get allProperties()
286     {
287         return this._allProperties;
288     },
289
290     getLiveProperty: function(name)
291     {
292         return this._livePropertyMap[name];
293     },
294
295     getPropertyValue: function(name)
296     {
297         var property = this._livePropertyMap[name];
298         return property ? property.value : "";
299     },
300
301     getPropertyPriority: function(name)
302     {
303         var property = this._livePropertyMap[name];
304         return property ? property.priority : "";
305     },
306
307     getPropertyShorthand: function(name)
308     {
309         var property = this._livePropertyMap[name];
310         return property ? property.shorthand : "";
311     },
312
313     isPropertyImplicit: function(name)
314     {
315         var property = this._livePropertyMap[name];
316         return property ? property.implicit : "";
317     },
318
319     styleTextWithShorthands: function()
320     {
321         var cssText = "";
322         var foundProperties = {};
323         for (var i = 0; i < this.length; ++i) {
324             var individualProperty = this[i];
325             var shorthandProperty = this.getPropertyShorthand(individualProperty);
326             var propertyName = (shorthandProperty || individualProperty);
327
328             if (propertyName in foundProperties)
329                 continue;
330
331             if (shorthandProperty) {
332                 var value = this.getShorthandValue(shorthandProperty);
333                 var priority = this.getShorthandPriority(shorthandProperty);
334             } else {
335                 var value = this.getPropertyValue(individualProperty);
336                 var priority = this.getPropertyPriority(individualProperty);
337             }
338
339             foundProperties[propertyName] = true;
340
341             cssText += propertyName + ": " + value;
342             if (priority)
343                 cssText += " !" + priority;
344             cssText += "; ";
345         }
346
347         return cssText;
348     },
349
350     getLonghandProperties: function(name)
351     {
352         return this._longhandProperties[name] || [];
353     },
354
355     getShorthandValue: function(shorthandProperty)
356     {
357         var property = this.getLiveProperty(shorthandProperty);
358         return property ? property.value : this._shorthandValues[shorthandProperty];
359     },
360
361     getShorthandPriority: function(shorthandProperty)
362     {
363         var priority = this.getPropertyPriority(shorthandProperty);
364         if (priority)
365             return priority;
366
367         var longhands = this._longhandProperties[shorthandProperty];
368         return longhands ? this.getPropertyPriority(longhands[0]) : null;
369     },
370
371     propertyAt: function(index)
372     {
373         return (index < this.allProperties.length) ? this.allProperties[index] : null;
374     },
375
376     pastLastSourcePropertyIndex: function()
377     {
378         for (var i = this.allProperties.length - 1; i >= 0; --i) {
379             var property = this.allProperties[i];
380             if (property.active || property.disabled)
381                 return i + 1;
382         }
383         return 0;
384     },
385
386     newBlankProperty: function()
387     {
388         return new WebInspector.CSSProperty(this, this.pastLastSourcePropertyIndex(), "", "", "", "active", true, false, false, "");
389     },
390
391     insertPropertyAt: function(index, name, value, userCallback)
392     {
393         function callback(userCallback, error, payload)
394         {
395             if (!userCallback)
396                 return;
397
398             if (error) {
399                 console.error(JSON.stringify(error));
400                 userCallback(null);
401             } else {
402                 userCallback(WebInspector.CSSStyleDeclaration.parsePayload(payload));
403                 WebInspector.cssModel._fireStyleSheetChanged(this.id.styleSheetId, true);
404             }
405         }
406
407         CSSAgent.setPropertyText(this.id, index, name + ": " + value + ";", false, callback.bind(null, userCallback));
408     },
409
410     appendProperty: function(name, value, userCallback)
411     {
412         this.insertPropertyAt(this.allProperties.length, name, value, userCallback);
413     }
414 }
415
416 /**
417  * @constructor
418  */
419 WebInspector.CSSRule = function(payload)
420 {
421     this.id = payload.ruleId;
422     this.selectorText = payload.selectorText;
423     this.sourceLine = payload.sourceLine;
424     this.sourceURL = payload.sourceURL;
425     this.origin = payload.origin;
426     this.style = WebInspector.CSSStyleDeclaration.parsePayload(payload.style);
427     this.style.parentRule = this;
428     this.selectorRange = payload.selectorRange;
429 }
430
431 WebInspector.CSSRule.parsePayload = function(payload)
432 {
433     return new WebInspector.CSSRule(payload);
434 }
435
436 WebInspector.CSSRule.prototype = {
437     get isUserAgent()
438     {
439         return this.origin === "user-agent";
440     },
441
442     get isUser()
443     {
444         return this.origin === "user";
445     },
446
447     get isViaInspector()
448     {
449         return this.origin === "inspector";
450     },
451
452     get isRegular()
453     {
454         return this.origin === "";
455     }
456 }
457
458 /**
459  * @constructor
460  */
461 WebInspector.CSSProperty = function(ownerStyle, index, name, value, priority, status, parsedOk, implicit, shorthand, text)
462 {
463     this.ownerStyle = ownerStyle;
464     this.index = index;
465     this.name = name;
466     this.value = value;
467     this.priority = priority;
468     this.status = status;
469     this.parsedOk = parsedOk;
470     this.implicit = implicit;
471     this.shorthand = shorthand;
472     this.text = text;
473 }
474
475 WebInspector.CSSProperty.parsePayload = function(ownerStyle, index, payload)
476 {
477     // The following default field values are used in the payload:
478     // priority: ""
479     // parsedOk: true
480     // implicit: false
481     // status: "style"
482     // shorthandName: ""
483     var result = new WebInspector.CSSProperty(
484         ownerStyle, index, payload.name, payload.value, payload.priority || "", payload.status || "style", ("parsedOk" in payload) ? payload.parsedOk : true, !!payload.implicit, payload.shorthandName || "", payload.text);
485     return result;
486 }
487
488 WebInspector.CSSProperty.prototype = {
489     get propertyText()
490     {
491         if (this.text !== undefined)
492             return this.text;
493
494         if (this.name === "")
495             return "";
496         return this.name + ": " + this.value + (this.priority ? " !" + this.priority : "") + ";";
497     },
498
499     get isLive()
500     {
501         return this.active || this.styleBased;
502     },
503
504     get active()
505     {
506         return this.status === "active";
507     },
508
509     get styleBased()
510     {
511         return this.status === "style";
512     },
513
514     get inactive()
515     {
516         return this.status === "inactive";
517     },
518
519     get disabled()
520     {
521         return this.status === "disabled";
522     },
523
524     // Replaces "propertyName: propertyValue [!important];" in the stylesheet by an arbitrary propertyText.
525     setText: function(propertyText, majorChange, userCallback)
526     {
527         function enabledCallback(style)
528         {
529             if (style)
530                 WebInspector.cssModel._fireStyleSheetChanged(style.id.styleSheetId, majorChange, userCallback ? userCallback.bind(null, style) : null);
531             else if (userCallback)
532                 userCallback(style);
533         }
534
535         function callback(error, stylePayload)
536         {
537             if (!error) {
538                 this.text = propertyText;
539                 var style = WebInspector.CSSStyleDeclaration.parsePayload(stylePayload);
540                 var newProperty = style.allProperties[this.index];
541
542                 if (newProperty && this.disabled && !propertyText.match(/^\s*$/)) {
543                     newProperty.setDisabled(false, enabledCallback);
544                     return;
545                 }
546
547                 WebInspector.cssModel._fireStyleSheetChanged(style.id.styleSheetId, majorChange, userCallback ? userCallback.bind(null, style) : null);
548             } else {
549                 if (userCallback)
550                     userCallback(null);
551             }
552         }
553
554         if (!this.ownerStyle)
555             throw "No ownerStyle for property";
556
557         // An index past all the properties adds a new property to the style.
558         CSSAgent.setPropertyText(this.ownerStyle.id, this.index, propertyText, this.index < this.ownerStyle.pastLastSourcePropertyIndex(), callback.bind(this));
559     },
560
561     setValue: function(newValue, majorChange, userCallback)
562     {
563         var text = this.name + ": " + newValue + (this.priority ? " !" + this.priority : "") + ";"
564         this.setText(text, majorChange, userCallback);
565     },
566
567     setDisabled: function(disabled, userCallback)
568     {
569         if (!this.ownerStyle && userCallback)
570             userCallback(null);
571         if (disabled === this.disabled && userCallback)
572             userCallback(this.ownerStyle);
573
574         function callback(error, stylePayload)
575         {
576             if (error) {
577                 if (userCallback)
578                     userCallback(null);
579                 return;
580             }
581             if (userCallback) {
582                 var style = WebInspector.CSSStyleDeclaration.parsePayload(stylePayload);
583                 userCallback(style);
584             }
585             WebInspector.cssModel._fireStyleSheetChanged(this.ownerStyle.id.styleSheetId, false);
586         }
587
588         CSSAgent.toggleProperty(this.ownerStyle.id, this.index, disabled, callback.bind(this));
589     }
590 }
591
592 /**
593  * @constructor
594  */
595 WebInspector.CSSStyleSheet = function(payload)
596 {
597     this.id = payload.styleSheetId;
598     this.rules = [];
599     this.styles = {};
600     for (var i = 0; i < payload.rules.length; ++i) {
601         var rule = WebInspector.CSSRule.parsePayload(payload.rules[i]);
602         this.rules.push(rule);
603         if (rule.style)
604             this.styles[rule.style.id] = rule.style;
605     }
606     if ("text" in payload)
607         this._text = payload.text;
608 }
609
610 WebInspector.CSSStyleSheet.createForId = function(styleSheetId, userCallback)
611 {
612     function callback(error, styleSheetPayload)
613     {
614         if (error)
615             userCallback(null);
616         else
617             userCallback(new WebInspector.CSSStyleSheet(styleSheetPayload));
618     }
619     CSSAgent.getStyleSheet(styleSheetId, callback.bind(this));
620 }
621
622 WebInspector.CSSStyleSheet.prototype = {
623     getText: function()
624     {
625         return this._text;
626     },
627
628     setText: function(newText, majorChange, userCallback)
629     {
630         function callback(error)
631         {
632              if (userCallback)
633                  userCallback(error);
634              if (!error)
635                  WebInspector.cssModel._fireStyleSheetChanged(this.id, majorChange);
636         }
637
638         CSSAgent.setStyleSheetText(this.id, newText, callback.bind(this));
639     }
640 }
641
642 /**
643  * @constructor
644  * @implements {WebInspector.ResourceDomainModelBinding}
645  */
646 WebInspector.CSSStyleModelResourceBinding = function(cssModel)
647 {
648     this._cssModel = cssModel;
649     this._urlToStyleSheetId = {};
650     this._styleSheetIdToURL = {};
651     this._cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetChanged, this);
652     WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, this._inspectedURLChanged, this);
653     WebInspector.Resource.registerDomainModelBinding(WebInspector.Resource.Type.Stylesheet, this);
654 }
655
656 WebInspector.CSSStyleModelResourceBinding.prototype = {
657     setContent: function(resource, content, majorChange, userCallback)
658     {
659         if (this._urlToStyleSheetId[resource.url]) {
660             this._innerSetContent(resource.url, content, majorChange, userCallback);
661             return;
662         }
663         this._loadStyleSheetHeaders(this._innerSetContent.bind(this, resource.url, content, majorChange, userCallback));
664     },
665
666     _inspectedURLChanged: function(event)
667     {
668         // Main frame navigation - clear history.
669         this._urlToStyleSheetId = {};
670         this._styleSheetIdToURL = {};
671     },
672
673     _innerSetContent: function(url, content, majorChange, userCallback, error)
674     {
675         if (error) {
676             userCallback(error);
677             return;
678         }
679
680         var styleSheetId = this._urlToStyleSheetId[url];
681         if (!styleSheetId) {
682             if (userCallback)
683                 userCallback("No stylesheet found: " + url);
684             return;
685         }
686         this._cssModel.setStyleSheetText(styleSheetId, content, majorChange, userCallback);
687     },
688
689     _loadStyleSheetHeaders: function(callback)
690     {
691         function didGetAllStyleSheets(error, infos)
692         {
693             if (error) {
694                 callback(error);
695                 return;
696             }
697
698             for (var i = 0; i < infos.length; ++i) {
699                 var info = infos[i];
700                 this._urlToStyleSheetId[info.sourceURL] = info.styleSheetId;
701                 this._styleSheetIdToURL[info.styleSheetId] = info.sourceURL;
702             }
703             callback();
704         }
705         CSSAgent.getAllStyleSheets(didGetAllStyleSheets.bind(this));
706     },
707
708     _styleSheetChanged: function(event)
709     {
710         var styleSheetId = event.data.styleSheetId;
711         function setContent()
712         {
713             var url = this._styleSheetIdToURL[styleSheetId];
714             if (!url)
715                 return;
716
717             var resource = WebInspector.resourceForURL(url);
718             if (!resource)
719                 return;
720
721             var majorChange = event.data.majorChange;
722             if (majorChange)
723                 resource.addRevision(event.data.content);
724         }
725
726         if (!this._styleSheetIdToURL[styleSheetId]) {
727             this._loadStyleSheetHeaders(setContent.bind(this));
728             return;
729         }
730         setContent.call(this);
731     }
732 }
733
734 WebInspector.CSSStyleModelResourceBinding.prototype.__proto__ = WebInspector.ResourceDomainModelBinding.prototype;