/
unicode-style-editor.diff
172 lines (166 loc) · 6.38 KB
/
unicode-style-editor.diff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# HG changeset patch
# Parent c80d0e010be310c2770e6668a89ee5cce1e97f3d
# User Thaddee Tyl <thaddee.tyl@gmail.com>
Bug 747820 — Style editor breaks with non-latin encoding.
diff --git a/browser/devtools/styleeditor/StyleEditor.jsm b/browser/devtools/styleeditor/StyleEditor.jsm
--- a/browser/devtools/styleeditor/StyleEditor.jsm
+++ b/browser/devtools/styleeditor/StyleEditor.jsm
@@ -759,6 +759,81 @@ StyleEditor.prototype = {
},
/**
+ * Decode a CSS source string to unicode according to the character set rules
+ * defined in <http://www.w3.org/TR/CSS2/syndata.html#charset>.
+ *
+ * @param string aString
+ * Source of a CSS stylesheet, loaded from file or cache.
+ * @param string aChannelCharset
+ * Charset of the source string if set by the HTTP channel.
+ */
+ _decodeCSSCharset: function SE__decodeCSSCharset(aString, aChannelCharset)
+ {
+ // StyleSheet's charset can be specified from multiple sources
+
+ if (aChannelCharset.length > 0) {
+ // step 1 of syndata.html: charset given in HTTP header.
+ return this._convertToUnicode(aString, aChannelCharset);
+ }
+
+ let sheet = this.styleSheet;
+ if (sheet) {
+ // Do we have a @charset rule in the stylesheet?
+ // step 2 of syndata.html (without the BOM check).
+ if (sheet.cssRules) {
+ let rules = sheet.cssRules;
+ if (rules.length
+ && rules.item(0).type == Ci.nsIDOMCSSRule.CHARSET_RULE) {
+ return this._convertToUnicode(aString, rules.item(0).encoding);
+ }
+ }
+
+ if (sheet.ownerNode) {
+ // step 3: see <link charset="…">
+ let linkCharset = sheet.ownerNode.getAttribute("charset");
+ if (linkCharset != null) {
+ return this._convertToUnicode(aString, linkCharset);
+ }
+ }
+
+ // step 4 (1 of 2): charset of referring stylesheet.
+ let parentSheet = sheet.parentStyleSheet;
+ if (parentSheet && parentSheet.cssRules &&
+ parentSheet.cssRules[0].type == Ci.nsIDOMCSSRule.CHARSET_RULE) {
+ return this._convertToUnicode(aString, parentSheet.cssRules[0].encoding);
+ }
+
+ if (sheet.ownerNode) {
+ // step 4 (2 of 2): charset of referring document.
+ if (sheet.ownerNode.ownerDocument.characterSet) {
+ return this._convertToUnicode(aString, sheet.ownerNode.ownerDocument.characterSet);
+ }
+ }
+ }
+
+ // step 5: default to utf-8.
+ return this._convertToUnicode(aString, "UTF-8");
+ },
+
+ /**
+ * Convert a given string, encoded in a given character set, to unicode.
+ * @param string aString
+ * A string.
+ * @param string aCharset
+ * A character set.
+ * @return string
+ * A unicode string.
+ */
+ _convertToUnicode: function SE__convertToUnicode(aString, aCharset) {
+ // Decoding primitives.
+ let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
+ .createInstance(Ci.nsIScriptableUnicodeConverter);
+
+ converter.charset = aCharset;
+ return converter.ConvertToUnicode(aString);
+ },
+
+ /**
* Load source from a file or file-like resource.
*
* @param string aHref
@@ -790,6 +865,7 @@ StyleEditor.prototype = {
{
let channel = Services.io.newChannel(aHref, null, null);
let chunks = [];
+ let channelCharset = "";
let streamListener = { // nsIStreamListener inherits nsIRequestObserver
onStartRequest: function (aRequest, aContext, aStatusCode) {
if (!Components.isSuccessCode(aStatusCode)) {
@@ -797,6 +873,10 @@ StyleEditor.prototype = {
}
}.bind(this),
onDataAvailable: function (aRequest, aContext, aStream, aOffset, aCount) {
+ let channel = aRequest.QueryInterface(Ci.nsIChannel);
+ if (!channelCharset) {
+ channelCharset = channel.contentCharset;
+ }
chunks.push(NetUtil.readInputStreamToString(aStream, aCount));
},
onStopRequest: function (aRequest, aContext, aStatusCode) {
@@ -804,7 +884,7 @@ StyleEditor.prototype = {
return this._signalError(LOAD_ERROR);
}
- this._onSourceLoad(chunks.join(""));
+ this._onSourceLoad(chunks.join(""), channelCharset);
}.bind(this)
};
@@ -816,9 +896,14 @@ StyleEditor.prototype = {
* Called when source has been loaded.
*
* @param string aSourceText
+ * @param string aCharset
+ * Optional. The character set to use. The default is to detect the
+ * character set following the standard (see
+ * <http://www.w3.org/TR/CSS2/syndata.html#charset>).
*/
- _onSourceLoad: function SE__onSourceLoad(aSourceText)
+ _onSourceLoad: function SE__onSourceLoad(aSourceText, aCharset)
{
+ aSourceText = this._decodeCSSCharset(aSourceText, aCharset || "");
this._restoreExpando();
this._state.text = prettifyCSS(aSourceText);
this._loaded = true;
diff --git a/browser/devtools/styleeditor/test/browser_styleeditor_init.js b/browser/devtools/styleeditor/test/browser_styleeditor_init.js
--- a/browser/devtools/styleeditor/test/browser_styleeditor_init.js
+++ b/browser/devtools/styleeditor/test/browser_styleeditor_init.js
@@ -71,6 +71,11 @@ function testEditorAdded(aChrome, aEdito
function testFirstStyleSheetEditor(aChrome, aEditor)
{
+ // Note: the html <link> contains charset="UTF-8".
+ let text = aEditor._state.text;
+ ok(text.indexOf("☺") >= 0,
+ "stylesheet is unicode-aware.");
+
//testing TESTCASE's simple.css stylesheet
is(aEditor.styleSheetIndex, 0,
"first stylesheet is at index 0");
diff --git a/browser/devtools/styleeditor/test/simple.css b/browser/devtools/styleeditor/test/simple.css
--- a/browser/devtools/styleeditor/test/simple.css
+++ b/browser/devtools/styleeditor/test/simple.css
@@ -1,6 +1,7 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
+/* ☺ */
body {
margin: 0;
diff --git a/browser/devtools/styleeditor/test/simple.html b/browser/devtools/styleeditor/test/simple.html
--- a/browser/devtools/styleeditor/test/simple.html
+++ b/browser/devtools/styleeditor/test/simple.html
@@ -2,7 +2,7 @@
<html>
<head>
<title>simple testcase</title>
- <link rel="stylesheet" type="text/css" media="screen" href="simple.css"/>
+ <link rel="stylesheet" charset="UTF-8" type="text/css" media="screen" href="simple.css"/>
<style type="text/css">
body {
background: white;