mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-21 17:59:34 +00:00
Bug 747820 - Style editor breaks with non-latin encoding. r=msucan f=cedricv
This commit is contained in:
parent
02685b8e7c
commit
994d41bdd1
@ -758,6 +758,87 @@ 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.
|
||||||
|
* @return string
|
||||||
|
* The CSS string, in unicode.
|
||||||
|
*/
|
||||||
|
_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// step 4 (2 of 2): charset of referring document.
|
||||||
|
if (sheet.ownerNode && 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);
|
||||||
|
|
||||||
|
try {
|
||||||
|
converter.charset = aCharset;
|
||||||
|
return converter.ConvertToUnicode(aString);
|
||||||
|
} catch(e) {
|
||||||
|
return aString;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load source from a file or file-like resource.
|
* Load source from a file or file-like resource.
|
||||||
*
|
*
|
||||||
@ -790,6 +871,7 @@ StyleEditor.prototype = {
|
|||||||
{
|
{
|
||||||
let channel = Services.io.newChannel(aHref, null, null);
|
let channel = Services.io.newChannel(aHref, null, null);
|
||||||
let chunks = [];
|
let chunks = [];
|
||||||
|
let channelCharset = "";
|
||||||
let streamListener = { // nsIStreamListener inherits nsIRequestObserver
|
let streamListener = { // nsIStreamListener inherits nsIRequestObserver
|
||||||
onStartRequest: function (aRequest, aContext, aStatusCode) {
|
onStartRequest: function (aRequest, aContext, aStatusCode) {
|
||||||
if (!Components.isSuccessCode(aStatusCode)) {
|
if (!Components.isSuccessCode(aStatusCode)) {
|
||||||
@ -797,6 +879,10 @@ StyleEditor.prototype = {
|
|||||||
}
|
}
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
onDataAvailable: function (aRequest, aContext, aStream, aOffset, aCount) {
|
onDataAvailable: function (aRequest, aContext, aStream, aOffset, aCount) {
|
||||||
|
let channel = aRequest.QueryInterface(Ci.nsIChannel);
|
||||||
|
if (!channelCharset) {
|
||||||
|
channelCharset = channel.contentCharset;
|
||||||
|
}
|
||||||
chunks.push(NetUtil.readInputStreamToString(aStream, aCount));
|
chunks.push(NetUtil.readInputStreamToString(aStream, aCount));
|
||||||
},
|
},
|
||||||
onStopRequest: function (aRequest, aContext, aStatusCode) {
|
onStopRequest: function (aRequest, aContext, aStatusCode) {
|
||||||
@ -804,7 +890,7 @@ StyleEditor.prototype = {
|
|||||||
return this._signalError(LOAD_ERROR);
|
return this._signalError(LOAD_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._onSourceLoad(chunks.join(""));
|
this._onSourceLoad(chunks.join(""), channelCharset);
|
||||||
}.bind(this)
|
}.bind(this)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -816,9 +902,14 @@ StyleEditor.prototype = {
|
|||||||
* Called when source has been loaded.
|
* Called when source has been loaded.
|
||||||
*
|
*
|
||||||
* @param string aSourceText
|
* @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._restoreExpando();
|
||||||
this._state.text = prettifyCSS(aSourceText);
|
this._state.text = prettifyCSS(aSourceText);
|
||||||
this._loaded = true;
|
this._loaded = true;
|
||||||
|
@ -71,6 +71,10 @@ function testEditorAdded(aChrome, aEditor)
|
|||||||
|
|
||||||
function testFirstStyleSheetEditor(aChrome, aEditor)
|
function testFirstStyleSheetEditor(aChrome, aEditor)
|
||||||
{
|
{
|
||||||
|
// Note: the html <link> contains charset="UTF-8".
|
||||||
|
ok(aEditor._state.text.indexOf("\u263a") >= 0,
|
||||||
|
"stylesheet is unicode-aware.");
|
||||||
|
|
||||||
//testing TESTCASE's simple.css stylesheet
|
//testing TESTCASE's simple.css stylesheet
|
||||||
is(aEditor.styleSheetIndex, 0,
|
is(aEditor.styleSheetIndex, 0,
|
||||||
"first stylesheet is at index 0");
|
"first stylesheet is at index 0");
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/* vim: set ts=2 et sw=2 tw=80: */
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
/* ☺ */
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>simple testcase</title>
|
<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">
|
<style type="text/css">
|
||||||
body {
|
body {
|
||||||
background: white;
|
background: white;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user