зеркало из https://github.com/mozilla/gecko-dev.git
Merge fx-team to m-c.
This commit is contained in:
Коммит
57c88ce89f
|
@ -104,7 +104,12 @@ Selection.prototype = {
|
|||
this.emit("pseudoclass");
|
||||
}
|
||||
if (detached) {
|
||||
this.emit("detached", parentNode ? parentNode.rawNode() : null);
|
||||
let rawNode = null;
|
||||
if (parentNode && parentNode.isLocal_toBeDeprecated()) {
|
||||
rawNode = parentNode.rawNode();
|
||||
}
|
||||
|
||||
this.emit("detached", rawNode, null);
|
||||
this.emit("detached-front", parentNode);
|
||||
}
|
||||
},
|
||||
|
@ -156,7 +161,10 @@ Selection.prototype = {
|
|||
setNodeFront: function(value, reason="unknown") {
|
||||
this.reason = reason;
|
||||
if (value !== this._nodeFront) {
|
||||
let rawValue = value ? value.rawNode() : value;
|
||||
let rawValue = null;
|
||||
if (value && value.isLocal_toBeDeprecated()) {
|
||||
rawValue = value.rawNode();
|
||||
}
|
||||
this.emit("before-new-node", rawValue, reason);
|
||||
this.emit("before-new-node-front", value, reason);
|
||||
let previousNode = this._node;
|
||||
|
@ -208,7 +216,10 @@ Selection.prototype = {
|
|||
|
||||
// As long as there are still tools going around
|
||||
// accessing node.rawNode, this needs to stay.
|
||||
let rawNode = node.rawNode();
|
||||
let rawNode = null;
|
||||
if (node.isLocal_toBeDeprecated()) {
|
||||
rawNode = node.rawNode();
|
||||
}
|
||||
if (rawNode) {
|
||||
try {
|
||||
let doc = this.document;
|
||||
|
|
|
@ -35,6 +35,7 @@ browser.jar:
|
|||
content/browser/devtools/codemirror/xml.js (sourceeditor/codemirror/xml.js)
|
||||
content/browser/devtools/codemirror/css.js (sourceeditor/codemirror/css.js)
|
||||
content/browser/devtools/codemirror/htmlmixed.js (sourceeditor/codemirror/htmlmixed.js)
|
||||
content/browser/devtools/codemirror/clike.js (sourceeditor/codemirror/clike.js)
|
||||
content/browser/devtools/codemirror/activeline.js (sourceeditor/codemirror/activeline.js)
|
||||
content/browser/devtools/codemirror/matchbrackets.js (sourceeditor/codemirror/matchbrackets.js)
|
||||
content/browser/devtools/codemirror/closebrackets.js (sourceeditor/codemirror/closebrackets.js)
|
||||
|
|
|
@ -1570,7 +1570,9 @@ function ElementEditor(aContainer, aNode) {
|
|||
// Create the main editor
|
||||
this.template("element", this);
|
||||
|
||||
this.rawNode = aNode.rawNode();
|
||||
if (aNode.isLocal_toBeDeprecated()) {
|
||||
this.rawNode = aNode.rawNode();
|
||||
}
|
||||
|
||||
// Make the tag name editable (unless this is a remote node or
|
||||
// a document element)
|
||||
|
|
|
@ -38,7 +38,6 @@ const SHADERS_AUTOGROW_ITEMS = 4;
|
|||
const GUTTER_ERROR_PANEL_OFFSET_X = 7; // px
|
||||
const GUTTER_ERROR_PANEL_DELAY = 100; // ms
|
||||
const DEFAULT_EDITOR_CONFIG = {
|
||||
mode: Editor.modes.text,
|
||||
gutters: ["errors"],
|
||||
lineNumbers: true,
|
||||
showAnnotationRuler: true
|
||||
|
@ -389,6 +388,7 @@ let ShadersEditorsView = {
|
|||
// in the ether of a resolved promise's value.
|
||||
let parent = $("#" + type +"-editor");
|
||||
let editor = new Editor(DEFAULT_EDITOR_CONFIG);
|
||||
editor.config.mode = Editor.modes[type];
|
||||
editor.appendTo(parent).then(() => deferred.resolve(editor));
|
||||
|
||||
return deferred.promise;
|
||||
|
|
|
@ -15,6 +15,7 @@ To confirm the functionality run mochitests for the following components:
|
|||
* scratchpad
|
||||
* debugger
|
||||
* styleditor
|
||||
* netmonitor
|
||||
|
||||
The sourceeditor component contains imported CodeMirror tests [3]. Some
|
||||
tests were commented out because we don't use that functionality within
|
||||
|
@ -38,7 +39,10 @@ in the LICENSE file:
|
|||
* comment.js
|
||||
* dialog/dialog.css
|
||||
* dialog/dialog.js
|
||||
* xml.js
|
||||
* css.js
|
||||
* javascript.js
|
||||
* clike.js
|
||||
* matchbrackets.js
|
||||
* closebrackets.js
|
||||
* search/match-highlighter.js
|
||||
|
|
|
@ -0,0 +1,362 @@
|
|||
CodeMirror.defineMode("clike", function(config, parserConfig) {
|
||||
var indentUnit = config.indentUnit,
|
||||
statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
|
||||
dontAlignCalls = parserConfig.dontAlignCalls,
|
||||
keywords = parserConfig.keywords || {},
|
||||
builtin = parserConfig.builtin || {},
|
||||
blockKeywords = parserConfig.blockKeywords || {},
|
||||
atoms = parserConfig.atoms || {},
|
||||
hooks = parserConfig.hooks || {},
|
||||
multiLineStrings = parserConfig.multiLineStrings;
|
||||
var isOperatorChar = /[+\-*&%=<>!?|\/]/;
|
||||
|
||||
var curPunc;
|
||||
|
||||
function tokenBase(stream, state) {
|
||||
var ch = stream.next();
|
||||
if (hooks[ch]) {
|
||||
var result = hooks[ch](stream, state);
|
||||
if (result !== false) return result;
|
||||
}
|
||||
if (ch == '"' || ch == "'") {
|
||||
state.tokenize = tokenString(ch);
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
|
||||
curPunc = ch;
|
||||
return null;
|
||||
}
|
||||
if (/\d/.test(ch)) {
|
||||
stream.eatWhile(/[\w\.]/);
|
||||
return "number";
|
||||
}
|
||||
if (ch == "/") {
|
||||
if (stream.eat("*")) {
|
||||
state.tokenize = tokenComment;
|
||||
return tokenComment(stream, state);
|
||||
}
|
||||
if (stream.eat("/")) {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
}
|
||||
if (isOperatorChar.test(ch)) {
|
||||
stream.eatWhile(isOperatorChar);
|
||||
return "operator";
|
||||
}
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
var cur = stream.current();
|
||||
if (keywords.propertyIsEnumerable(cur)) {
|
||||
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
|
||||
return "keyword";
|
||||
}
|
||||
if (builtin.propertyIsEnumerable(cur)) {
|
||||
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
|
||||
return "builtin";
|
||||
}
|
||||
if (atoms.propertyIsEnumerable(cur)) return "atom";
|
||||
return "variable";
|
||||
}
|
||||
|
||||
function tokenString(quote) {
|
||||
return function(stream, state) {
|
||||
var escaped = false, next, end = false;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == quote && !escaped) {end = true; break;}
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
if (end || !(escaped || multiLineStrings))
|
||||
state.tokenize = null;
|
||||
return "string";
|
||||
};
|
||||
}
|
||||
|
||||
function tokenComment(stream, state) {
|
||||
var maybeEnd = false, ch;
|
||||
while (ch = stream.next()) {
|
||||
if (ch == "/" && maybeEnd) {
|
||||
state.tokenize = null;
|
||||
break;
|
||||
}
|
||||
maybeEnd = (ch == "*");
|
||||
}
|
||||
return "comment";
|
||||
}
|
||||
|
||||
function Context(indented, column, type, align, prev) {
|
||||
this.indented = indented;
|
||||
this.column = column;
|
||||
this.type = type;
|
||||
this.align = align;
|
||||
this.prev = prev;
|
||||
}
|
||||
function pushContext(state, col, type) {
|
||||
var indent = state.indented;
|
||||
if (state.context && state.context.type == "statement")
|
||||
indent = state.context.indented;
|
||||
return state.context = new Context(indent, col, type, null, state.context);
|
||||
}
|
||||
function popContext(state) {
|
||||
var t = state.context.type;
|
||||
if (t == ")" || t == "]" || t == "}")
|
||||
state.indented = state.context.indented;
|
||||
return state.context = state.context.prev;
|
||||
}
|
||||
|
||||
// Interface
|
||||
|
||||
return {
|
||||
startState: function(basecolumn) {
|
||||
return {
|
||||
tokenize: null,
|
||||
context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
|
||||
indented: 0,
|
||||
startOfLine: true
|
||||
};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
var ctx = state.context;
|
||||
if (stream.sol()) {
|
||||
if (ctx.align == null) ctx.align = false;
|
||||
state.indented = stream.indentation();
|
||||
state.startOfLine = true;
|
||||
}
|
||||
if (stream.eatSpace()) return null;
|
||||
curPunc = null;
|
||||
var style = (state.tokenize || tokenBase)(stream, state);
|
||||
if (style == "comment" || style == "meta") return style;
|
||||
if (ctx.align == null) ctx.align = true;
|
||||
|
||||
if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state);
|
||||
else if (curPunc == "{") pushContext(state, stream.column(), "}");
|
||||
else if (curPunc == "[") pushContext(state, stream.column(), "]");
|
||||
else if (curPunc == "(") pushContext(state, stream.column(), ")");
|
||||
else if (curPunc == "}") {
|
||||
while (ctx.type == "statement") ctx = popContext(state);
|
||||
if (ctx.type == "}") ctx = popContext(state);
|
||||
while (ctx.type == "statement") ctx = popContext(state);
|
||||
}
|
||||
else if (curPunc == ctx.type) popContext(state);
|
||||
else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement"))
|
||||
pushContext(state, stream.column(), "statement");
|
||||
state.startOfLine = false;
|
||||
return style;
|
||||
},
|
||||
|
||||
indent: function(state, textAfter) {
|
||||
if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
|
||||
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
|
||||
if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
|
||||
var closing = firstChar == ctx.type;
|
||||
if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
|
||||
else if (ctx.align && (!dontAlignCalls || ctx.type != ")")) return ctx.column + (closing ? 0 : 1);
|
||||
else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;
|
||||
else return ctx.indented + (closing ? 0 : indentUnit);
|
||||
},
|
||||
|
||||
electricChars: "{}",
|
||||
blockCommentStart: "/*",
|
||||
blockCommentEnd: "*/",
|
||||
lineComment: "//",
|
||||
fold: "brace"
|
||||
};
|
||||
});
|
||||
|
||||
(function() {
|
||||
function words(str) {
|
||||
var obj = {}, words = str.split(" ");
|
||||
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
|
||||
return obj;
|
||||
}
|
||||
var cKeywords = "auto if break int case long char register continue return default short do sizeof " +
|
||||
"double static else struct entry switch extern typedef float union for unsigned " +
|
||||
"goto while enum void const signed volatile";
|
||||
|
||||
function cppHook(stream, state) {
|
||||
if (!state.startOfLine) return false;
|
||||
for (;;) {
|
||||
if (stream.skipTo("\\")) {
|
||||
stream.next();
|
||||
if (stream.eol()) {
|
||||
state.tokenize = cppHook;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
stream.skipToEnd();
|
||||
state.tokenize = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "meta";
|
||||
}
|
||||
|
||||
// C#-style strings where "" escapes a quote.
|
||||
function tokenAtString(stream, state) {
|
||||
var next;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == '"' && !stream.eat('"')) {
|
||||
state.tokenize = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "string";
|
||||
}
|
||||
|
||||
function mimes(ms, mode) {
|
||||
for (var i = 0; i < ms.length; ++i) CodeMirror.defineMIME(ms[i], mode);
|
||||
}
|
||||
|
||||
mimes(["text/x-csrc", "text/x-c", "text/x-chdr"], {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords),
|
||||
blockKeywords: words("case do else for if switch while struct"),
|
||||
atoms: words("null"),
|
||||
hooks: {"#": cppHook}
|
||||
});
|
||||
mimes(["text/x-c++src", "text/x-c++hdr"], {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
|
||||
"static_cast typeid catch operator template typename class friend private " +
|
||||
"this using const_cast inline public throw virtual delete mutable protected " +
|
||||
"wchar_t"),
|
||||
blockKeywords: words("catch class do else finally for if struct switch try while"),
|
||||
atoms: words("true false null"),
|
||||
hooks: {"#": cppHook}
|
||||
});
|
||||
CodeMirror.defineMIME("text/x-java", {
|
||||
name: "clike",
|
||||
keywords: words("abstract assert boolean break byte case catch char class const continue default " +
|
||||
"do double else enum extends final finally float for goto if implements import " +
|
||||
"instanceof int interface long native new package private protected public " +
|
||||
"return short static strictfp super switch synchronized this throw throws transient " +
|
||||
"try void volatile while"),
|
||||
blockKeywords: words("catch class do else finally for if switch try while"),
|
||||
atoms: words("true false null"),
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "meta";
|
||||
}
|
||||
}
|
||||
});
|
||||
CodeMirror.defineMIME("text/x-csharp", {
|
||||
name: "clike",
|
||||
keywords: words("abstract as base break case catch checked class const continue" +
|
||||
" default delegate do else enum event explicit extern finally fixed for" +
|
||||
" foreach goto if implicit in interface internal is lock namespace new" +
|
||||
" operator out override params private protected public readonly ref return sealed" +
|
||||
" sizeof stackalloc static struct switch this throw try typeof unchecked" +
|
||||
" unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
|
||||
" global group into join let orderby partial remove select set value var yield"),
|
||||
blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
|
||||
builtin: words("Boolean Byte Char DateTime DateTimeOffset Decimal Double" +
|
||||
" Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32" +
|
||||
" UInt64 bool byte char decimal double short int long object" +
|
||||
" sbyte float string ushort uint ulong"),
|
||||
atoms: words("true false null"),
|
||||
hooks: {
|
||||
"@": function(stream, state) {
|
||||
if (stream.eat('"')) {
|
||||
state.tokenize = tokenAtString;
|
||||
return tokenAtString(stream, state);
|
||||
}
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "meta";
|
||||
}
|
||||
}
|
||||
});
|
||||
CodeMirror.defineMIME("text/x-scala", {
|
||||
name: "clike",
|
||||
keywords: words(
|
||||
|
||||
/* scala */
|
||||
"abstract case catch class def do else extends false final finally for forSome if " +
|
||||
"implicit import lazy match new null object override package private protected return " +
|
||||
"sealed super this throw trait try trye type val var while with yield _ : = => <- <: " +
|
||||
"<% >: # @ " +
|
||||
|
||||
/* package scala */
|
||||
"assert assume require print println printf readLine readBoolean readByte readShort " +
|
||||
"readChar readInt readLong readFloat readDouble " +
|
||||
|
||||
"AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
|
||||
"Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " +
|
||||
"Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
|
||||
"Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
|
||||
"StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: " +
|
||||
|
||||
/* package java.lang */
|
||||
"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
|
||||
"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
|
||||
"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
|
||||
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
|
||||
|
||||
|
||||
),
|
||||
blockKeywords: words("catch class do else finally for forSome if match switch try while"),
|
||||
atoms: words("true false null"),
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "meta";
|
||||
}
|
||||
}
|
||||
});
|
||||
mimes(["x-shader/x-vertex", "x-shader/x-fragment"], {
|
||||
name: "clike",
|
||||
keywords: words("float int bool void " +
|
||||
"vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
|
||||
"mat2 mat3 mat4 " +
|
||||
"sampler1D sampler2D sampler3D samplerCube " +
|
||||
"sampler1DShadow sampler2DShadow" +
|
||||
"const attribute uniform varying " +
|
||||
"break continue discard return " +
|
||||
"for while do if else struct " +
|
||||
"in out inout"),
|
||||
blockKeywords: words("for while do if else struct"),
|
||||
builtin: words("radians degrees sin cos tan asin acos atan " +
|
||||
"pow exp log exp2 sqrt inversesqrt " +
|
||||
"abs sign floor ceil fract mod min max clamp mix step smootstep " +
|
||||
"length distance dot cross normalize ftransform faceforward " +
|
||||
"reflect refract matrixCompMult " +
|
||||
"lessThan lessThanEqual greaterThan greaterThanEqual " +
|
||||
"equal notEqual any all not " +
|
||||
"texture1D texture1DProj texture1DLod texture1DProjLod " +
|
||||
"texture2D texture2DProj texture2DLod texture2DProjLod " +
|
||||
"texture3D texture3DProj texture3DLod texture3DProjLod " +
|
||||
"textureCube textureCubeLod " +
|
||||
"shadow1D shadow2D shadow1DProj shadow2DProj " +
|
||||
"shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod " +
|
||||
"dFdx dFdy fwidth " +
|
||||
"noise1 noise2 noise3 noise4"),
|
||||
atoms: words("true false " +
|
||||
"gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " +
|
||||
"gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " +
|
||||
"gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " +
|
||||
"gl_FogCoord " +
|
||||
"gl_Position gl_PointSize gl_ClipVertex " +
|
||||
"gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " +
|
||||
"gl_TexCoord gl_FogFragCoord " +
|
||||
"gl_FragCoord gl_FrontFacing " +
|
||||
"gl_FragColor gl_FragData gl_FragDepth " +
|
||||
"gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " +
|
||||
"gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " +
|
||||
"gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " +
|
||||
"gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose " +
|
||||
"gl_ProjectionMatrixInverseTranspose " +
|
||||
"gl_ModelViewProjectionMatrixInverseTranspose " +
|
||||
"gl_TextureMatrixInverseTranspose " +
|
||||
"gl_NormalScale gl_DepthRange gl_ClipPlane " +
|
||||
"gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel " +
|
||||
"gl_FrontLightModelProduct gl_BackLightModelProduct " +
|
||||
"gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ " +
|
||||
"gl_FogParameters " +
|
||||
"gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords " +
|
||||
"gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats " +
|
||||
"gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " +
|
||||
"gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " +
|
||||
"gl_MaxDrawBuffers"),
|
||||
hooks: {"#": cppHook}
|
||||
});
|
||||
}());
|
|
@ -46,6 +46,7 @@ const CM_SCRIPTS = [
|
|||
"chrome://browser/content/devtools/codemirror/xml.js",
|
||||
"chrome://browser/content/devtools/codemirror/css.js",
|
||||
"chrome://browser/content/devtools/codemirror/htmlmixed.js",
|
||||
"chrome://browser/content/devtools/codemirror/clike.js",
|
||||
"chrome://browser/content/devtools/codemirror/activeline.js"
|
||||
];
|
||||
|
||||
|
@ -66,8 +67,9 @@ const CM_IFRAME =
|
|||
const CM_MAPPING = [
|
||||
"focus",
|
||||
"hasFocus",
|
||||
"getCursor",
|
||||
"lineCount",
|
||||
"somethingSelected",
|
||||
"getCursor",
|
||||
"setSelection",
|
||||
"getSelection",
|
||||
"replaceSelection",
|
||||
|
@ -76,7 +78,6 @@ const CM_MAPPING = [
|
|||
"clearHistory",
|
||||
"openDialog",
|
||||
"cursorCoords",
|
||||
"lineCount",
|
||||
"refresh"
|
||||
];
|
||||
|
||||
|
@ -91,9 +92,11 @@ const editors = new WeakMap();
|
|||
|
||||
Editor.modes = {
|
||||
text: { name: "text" },
|
||||
js: { name: "javascript" },
|
||||
html: { name: "htmlmixed" },
|
||||
css: { name: "css" }
|
||||
css: { name: "css" },
|
||||
js: { name: "javascript" },
|
||||
vs: { name: "x-shader/x-vertex" },
|
||||
fs: { name: "x-shader/x-fragment" }
|
||||
};
|
||||
|
||||
function ctrl(k) {
|
||||
|
@ -250,63 +253,12 @@ Editor.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Returns true if there's something to undo and false otherwise.
|
||||
* Returns the currently active highlighting mode.
|
||||
* See Editor.modes for the list of all suppoert modes.
|
||||
*/
|
||||
canUndo: function () {
|
||||
getMode: function () {
|
||||
let cm = editors.get(this);
|
||||
return cm.historySize().undo > 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if there's something to redo and false otherwise.
|
||||
*/
|
||||
canRedo: function () {
|
||||
let cm = editors.get(this);
|
||||
return cm.historySize().redo > 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculates and returns one or more {line, ch} objects for
|
||||
* a zero-based index who's value is relative to the start of
|
||||
* the editor's text.
|
||||
*
|
||||
* If only one argument is given, this method returns a single
|
||||
* {line,ch} object. Otherwise it returns an array.
|
||||
*/
|
||||
getPosition: function (...args) {
|
||||
let cm = editors.get(this);
|
||||
let res = args.map((ind) => cm.posFromIndex(ind));
|
||||
return args.length === 1 ? res[0] : res;
|
||||
},
|
||||
|
||||
/**
|
||||
* The reverse of getPosition. Similarly to getPosition this
|
||||
* method returns a single value if only one argument was given
|
||||
* and an array otherwise.
|
||||
*/
|
||||
getOffset: function (...args) {
|
||||
let cm = editors.get(this);
|
||||
let res = args.map((pos) => cm.indexFromPos(pos));
|
||||
return args.length > 1 ? res : res[0];
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns text from the text area. If line argument is provided
|
||||
* the method returns only that line.
|
||||
*/
|
||||
getText: function (line) {
|
||||
let cm = editors.get(this);
|
||||
return line == null ?
|
||||
cm.getValue() : (cm.lineInfo(line) ? cm.lineInfo(line).text : "");
|
||||
},
|
||||
|
||||
/**
|
||||
* Replaces whatever is in the text area with the contents of
|
||||
* the 'value' argument.
|
||||
*/
|
||||
setText: function (value) {
|
||||
let cm = editors.get(this);
|
||||
cm.setValue(value);
|
||||
return cm.getOption("mode");
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -319,20 +271,26 @@ Editor.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Returns the currently active highlighting mode.
|
||||
* See Editor.modes for the list of all suppoert modes.
|
||||
* Returns text from the text area. If line argument is provided
|
||||
* the method returns only that line.
|
||||
*/
|
||||
getMode: function () {
|
||||
getText: function (line) {
|
||||
let cm = editors.get(this);
|
||||
return cm.getOption("mode");
|
||||
|
||||
if (line == null)
|
||||
return cm.getValue();
|
||||
|
||||
let info = cm.lineInfo(line);
|
||||
return info ? cm.lineInfo(line).text : "";
|
||||
},
|
||||
|
||||
/**
|
||||
* True if the editor is in the read-only mode, false otherwise.
|
||||
* Replaces whatever is in the text area with the contents of
|
||||
* the 'value' argument.
|
||||
*/
|
||||
isReadOnly: function () {
|
||||
setText: function (value) {
|
||||
let cm = editors.get(this);
|
||||
return cm.getOption("readOnly");
|
||||
cm.setValue(value);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -374,57 +332,6 @@ Editor.prototype = {
|
|||
this.setCursor(this.getCursor());
|
||||
},
|
||||
|
||||
/**
|
||||
* Marks the contents as clean and returns the current
|
||||
* version number.
|
||||
*/
|
||||
setClean: function () {
|
||||
let cm = editors.get(this);
|
||||
this.version = cm.changeGeneration();
|
||||
return this.version;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if contents of the text area are
|
||||
* clean i.e. no changes were made since the last version.
|
||||
*/
|
||||
isClean: function () {
|
||||
let cm = editors.get(this);
|
||||
return cm.isClean(this.version);
|
||||
},
|
||||
|
||||
/**
|
||||
* Displays a context menu at the point x:y. The first
|
||||
* argument, container, should be a DOM node that contains
|
||||
* a context menu element specified by the ID from
|
||||
* config.contextMenu.
|
||||
*/
|
||||
showContextMenu: function (container, x, y) {
|
||||
if (this.config.contextMenu == null)
|
||||
return;
|
||||
|
||||
let popup = container.getElementById(this.config.contextMenu);
|
||||
popup.openPopupAtScreen(x, y, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* This method opens an in-editor dialog asking for a line to
|
||||
* jump to. Once given, it changes cursor to that line.
|
||||
*/
|
||||
jumpToLine: function () {
|
||||
this.openDialog(CM_JUMP_DIALOG, (line) =>
|
||||
this.setCursor({ line: line - 1, ch: 0 }));
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a {line, ch} object that corresponds to the
|
||||
* left, top coordinates.
|
||||
*/
|
||||
getPositionFromCoords: function (left, top) {
|
||||
let cm = editors.get(this);
|
||||
return cm.coordsChar({ left: left, top: top });
|
||||
},
|
||||
|
||||
/**
|
||||
* Extends the current selection to the position specified
|
||||
* by the provided {line, ch} object.
|
||||
|
@ -437,35 +344,6 @@ Editor.prototype = {
|
|||
cm.setSelection(anchor, head);
|
||||
},
|
||||
|
||||
/**
|
||||
* Extends an instance of the Editor object with additional
|
||||
* functions. Each function will be called with context as
|
||||
* the first argument. Context is a {ed, cm} object where
|
||||
* 'ed' is an instance of the Editor object and 'cm' is an
|
||||
* instance of the CodeMirror object. Example:
|
||||
*
|
||||
* function hello(ctx, name) {
|
||||
* let { cm, ed } = ctx;
|
||||
* cm; // CodeMirror instance
|
||||
* ed; // Editor instance
|
||||
* name; // 'Mozilla'
|
||||
* }
|
||||
*
|
||||
* editor.extend({ hello: hello });
|
||||
* editor.hello('Mozilla');
|
||||
*/
|
||||
extend: function (funcs) {
|
||||
Object.keys(funcs).forEach((name) => {
|
||||
let cm = editors.get(this);
|
||||
let ctx = { ed: this, cm: cm };
|
||||
|
||||
if (name === "initialize")
|
||||
return void funcs[name](ctx);
|
||||
|
||||
this[name] = funcs[name].bind(null, ctx);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the first visible line number in the editor.
|
||||
*/
|
||||
|
@ -641,6 +519,135 @@ Editor.prototype = {
|
|||
cm.removeLineClass(line, "wrap", className);
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculates and returns one or more {line, ch} objects for
|
||||
* a zero-based index who's value is relative to the start of
|
||||
* the editor's text.
|
||||
*
|
||||
* If only one argument is given, this method returns a single
|
||||
* {line,ch} object. Otherwise it returns an array.
|
||||
*/
|
||||
getPosition: function (...args) {
|
||||
let cm = editors.get(this);
|
||||
let res = args.map((ind) => cm.posFromIndex(ind));
|
||||
return args.length === 1 ? res[0] : res;
|
||||
},
|
||||
|
||||
/**
|
||||
* The reverse of getPosition. Similarly to getPosition this
|
||||
* method returns a single value if only one argument was given
|
||||
* and an array otherwise.
|
||||
*/
|
||||
getOffset: function (...args) {
|
||||
let cm = editors.get(this);
|
||||
let res = args.map((pos) => cm.indexFromPos(pos));
|
||||
return args.length > 1 ? res : res[0];
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a {line, ch} object that corresponds to the
|
||||
* left, top coordinates.
|
||||
*/
|
||||
getPositionFromCoords: function (left, top) {
|
||||
let cm = editors.get(this);
|
||||
return cm.coordsChar({ left: left, top: top });
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if there's something to undo and false otherwise.
|
||||
*/
|
||||
canUndo: function () {
|
||||
let cm = editors.get(this);
|
||||
return cm.historySize().undo > 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if there's something to redo and false otherwise.
|
||||
*/
|
||||
canRedo: function () {
|
||||
let cm = editors.get(this);
|
||||
return cm.historySize().redo > 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Marks the contents as clean and returns the current
|
||||
* version number.
|
||||
*/
|
||||
setClean: function () {
|
||||
let cm = editors.get(this);
|
||||
this.version = cm.changeGeneration();
|
||||
return this.version;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if contents of the text area are
|
||||
* clean i.e. no changes were made since the last version.
|
||||
*/
|
||||
isClean: function () {
|
||||
let cm = editors.get(this);
|
||||
return cm.isClean(this.version);
|
||||
},
|
||||
|
||||
/**
|
||||
* True if the editor is in the read-only mode, false otherwise.
|
||||
*/
|
||||
isReadOnly: function () {
|
||||
let cm = editors.get(this);
|
||||
return cm.getOption("readOnly");
|
||||
},
|
||||
|
||||
/**
|
||||
* Displays a context menu at the point x:y. The first
|
||||
* argument, container, should be a DOM node that contains
|
||||
* a context menu element specified by the ID from
|
||||
* config.contextMenu.
|
||||
*/
|
||||
showContextMenu: function (container, x, y) {
|
||||
if (this.config.contextMenu == null)
|
||||
return;
|
||||
|
||||
let popup = container.getElementById(this.config.contextMenu);
|
||||
popup.openPopupAtScreen(x, y, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* This method opens an in-editor dialog asking for a line to
|
||||
* jump to. Once given, it changes cursor to that line.
|
||||
*/
|
||||
jumpToLine: function () {
|
||||
this.openDialog(CM_JUMP_DIALOG, (line) =>
|
||||
this.setCursor({ line: line - 1, ch: 0 }));
|
||||
},
|
||||
|
||||
/**
|
||||
* Extends an instance of the Editor object with additional
|
||||
* functions. Each function will be called with context as
|
||||
* the first argument. Context is a {ed, cm} object where
|
||||
* 'ed' is an instance of the Editor object and 'cm' is an
|
||||
* instance of the CodeMirror object. Example:
|
||||
*
|
||||
* function hello(ctx, name) {
|
||||
* let { cm, ed } = ctx;
|
||||
* cm; // CodeMirror instance
|
||||
* ed; // Editor instance
|
||||
* name; // 'Mozilla'
|
||||
* }
|
||||
*
|
||||
* editor.extend({ hello: hello });
|
||||
* editor.hello('Mozilla');
|
||||
*/
|
||||
extend: function (funcs) {
|
||||
Object.keys(funcs).forEach((name) => {
|
||||
let cm = editors.get(this);
|
||||
let ctx = { ed: this, cm: cm };
|
||||
|
||||
if (name === "initialize")
|
||||
return void funcs[name](ctx);
|
||||
|
||||
this[name] = funcs[name].bind(null, ctx);
|
||||
});
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
this.container = null;
|
||||
this.config = null;
|
||||
|
|
|
@ -1217,9 +1217,11 @@ SelectorView.prototype = {
|
|||
}
|
||||
|
||||
let contentDoc = null;
|
||||
let rawNode = this.tree.viewedElement.rawNode();
|
||||
if (rawNode) {
|
||||
contentDoc = rawNode.ownerDocument;
|
||||
if (this.tree.viewedElement.isLocal_toBeDeprecated()) {
|
||||
let rawNode = this.tree.viewedElement.rawNode();
|
||||
if (rawNode) {
|
||||
contentDoc = rawNode.ownerDocument;
|
||||
}
|
||||
}
|
||||
|
||||
let viewSourceUtils = inspector.viewSourceUtils;
|
||||
|
|
|
@ -223,6 +223,7 @@ skip-if = os == "linux"
|
|||
[browser_webconsole_execution_scope.js]
|
||||
[browser_webconsole_for_of.js]
|
||||
[browser_webconsole_history.js]
|
||||
[browser_webconsole_input_field_focus_on_panel_select.js]
|
||||
[browser_webconsole_js_input_expansion.js]
|
||||
[browser_webconsole_jsterm.js]
|
||||
[browser_webconsole_live_filtering_of_message_types.js]
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* Any copyright is dedicated to the Public Domain
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Test that the JS input field is focused when the user switches back to the
|
||||
// web console from other tools, see bug 891581.
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf8,<p>hello";
|
||||
|
||||
function test()
|
||||
{
|
||||
addTab(TEST_URI);
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
openConsole(null, consoleOpened);
|
||||
}, true);
|
||||
}
|
||||
|
||||
function consoleOpened(hud)
|
||||
{
|
||||
is(hud.jsterm.inputNode.hasAttribute("focused"), true,
|
||||
"inputNode should be focused");
|
||||
|
||||
hud.ui.filterBox.focus();
|
||||
|
||||
is(hud.ui.filterBox.hasAttribute("focused"), true,
|
||||
"filterBox should be focused");
|
||||
|
||||
is(hud.jsterm.inputNode.hasAttribute("focused"), false,
|
||||
"inputNode shouldn't be focused");
|
||||
|
||||
openDebugger().then(debuggerOpened);
|
||||
}
|
||||
|
||||
function debuggerOpened()
|
||||
{
|
||||
openConsole(null, consoleReopened);
|
||||
}
|
||||
|
||||
function consoleReopened(hud)
|
||||
{
|
||||
is(hud.jsterm.inputNode.hasAttribute("focused"), true,
|
||||
"inputNode should be focused");
|
||||
|
||||
finishTest();
|
||||
}
|
|
@ -31,6 +31,7 @@ loader.lazyImporter(this, "ObjectClient", "resource://gre/modules/devtools/dbg-c
|
|||
loader.lazyImporter(this, "VariablesView", "resource:///modules/devtools/VariablesView.jsm");
|
||||
loader.lazyImporter(this, "VariablesViewController", "resource:///modules/devtools/VariablesViewController.jsm");
|
||||
loader.lazyImporter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm");
|
||||
loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
|
||||
|
||||
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
|
||||
let l10n = new WebConsoleUtils.l10n(STRINGS_URI);
|
||||
|
@ -198,6 +199,7 @@ function WebConsoleFrame(aWebConsoleOwner)
|
|||
this.output = new ConsoleOutput(this);
|
||||
|
||||
this._toggleFilter = this._toggleFilter.bind(this);
|
||||
this._onPanelSelected = this._onPanelSelected.bind(this);
|
||||
this._flushMessageQueue = this._flushMessageQueue.bind(this);
|
||||
|
||||
this._outputTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
|
@ -555,6 +557,21 @@ WebConsoleFrame.prototype = {
|
|||
this.jsterm = new JSTerm(this);
|
||||
this.jsterm.init();
|
||||
this.jsterm.inputNode.focus();
|
||||
|
||||
let toolbox = gDevTools.getToolbox(this.owner.target);
|
||||
if (toolbox) {
|
||||
toolbox.on("webconsole-selected", this._onPanelSelected);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the focus to JavaScript input field when the web console tab is
|
||||
* selected.
|
||||
* @private
|
||||
*/
|
||||
_onPanelSelected: function WCF__onPanelSelected()
|
||||
{
|
||||
this.jsterm.inputNode.focus();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -2826,6 +2843,11 @@ WebConsoleFrame.prototype = {
|
|||
|
||||
this._destroyer = promise.defer();
|
||||
|
||||
let toolbox = gDevTools.getToolbox(this.owner.target);
|
||||
if (toolbox) {
|
||||
toolbox.off("webconsole-selected", this._onPanelSelected);
|
||||
}
|
||||
|
||||
this._repeatNodes = {};
|
||||
this._outputQueue = [];
|
||||
this._pruneCategoriesQueue = {};
|
||||
|
|
|
@ -79,23 +79,21 @@
|
|||
}
|
||||
|
||||
.theme-fg-color1,
|
||||
.cm-s-mozilla .cm-variable-2,
|
||||
.cm-s-mozilla .cm-quote { /* green */
|
||||
.cm-s-mozilla .cm-number { /* green */
|
||||
color: #5c9966;
|
||||
}
|
||||
|
||||
.theme-fg-color2,
|
||||
.cm-s-mozilla .cm-attribute,
|
||||
.cm-s-mozilla .cm-builtin,
|
||||
.cm-s-mozilla .cm-variable,
|
||||
.cm-s-mozilla .cm-def,
|
||||
.cm-s-mozilla .cm-variable-3,
|
||||
.cm-s-mozilla .cm-property,
|
||||
.cm-s-mozilla .cm-qualifier { /* blue */
|
||||
color: #3689b2;
|
||||
}
|
||||
|
||||
.theme-fg-color3,
|
||||
.cm-s-mozilla .cm-builtin,
|
||||
.cm-s-mozilla .cm-tag,
|
||||
.cm-s-mozilla .cm-header { /* pink/lavender */
|
||||
color: #a673bf;
|
||||
|
@ -107,18 +105,19 @@
|
|||
|
||||
.theme-fg-color5,
|
||||
.cm-s-mozilla .cm-bracket,
|
||||
.cm-s-mozilla .cm-atom,
|
||||
.cm-s-mozilla .cm-keyword { /* Yellow */
|
||||
color: #a18650;
|
||||
}
|
||||
|
||||
.theme-fg-color6,
|
||||
.cm-s-mozilla .cm-string { /* Orange */
|
||||
.cm-s-mozilla .cm-string,
|
||||
.cm-s-mozilla .cm-string-2 { /* Orange */
|
||||
color: #b26b47;
|
||||
}
|
||||
|
||||
.theme-fg-color7,
|
||||
.cm-s-mozilla .cm-string-2,
|
||||
.cm-s-mozilla .cm-atom,
|
||||
.cm-s-mozilla .cm-quote,
|
||||
.cm-s-mozilla .cm-error { /* Red */
|
||||
color: #bf5656;
|
||||
}
|
||||
|
@ -144,9 +143,10 @@
|
|||
}
|
||||
|
||||
.CodeMirror pre,
|
||||
.cm-s-mozilla .cm-variable-2,
|
||||
.cm-s-mozilla .cm-variable-3,
|
||||
.cm-s-mozilla .cm-operator,
|
||||
.cm-s-mozilla .cm-special,
|
||||
.cm-s-mozilla .cm-number { /* theme-body color */
|
||||
.cm-s-mozilla .cm-special { /* theme-body color */
|
||||
color: #8fa1b2;
|
||||
}
|
||||
|
||||
|
@ -162,10 +162,15 @@
|
|||
background: rgb(176, 176, 176);
|
||||
}
|
||||
|
||||
.CodeMirror-activeline-background { /* selected color with alpha */
|
||||
.cm-s-mozilla .CodeMirror-activeline-background { /* selected color with alpha */
|
||||
background: rgba(185, 215, 253, .15);
|
||||
}
|
||||
|
||||
div.cm-s-mozilla span.CodeMirror-matchingbracket { /* highlight brackets */
|
||||
outline: solid 1px rgba(255, 255, 255, .25);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.cm-s-mozilla .CodeMirror-linenumber { /* line number text */
|
||||
color: #5f7387;
|
||||
}
|
||||
|
|
|
@ -79,23 +79,21 @@
|
|||
}
|
||||
|
||||
.theme-fg-color1,
|
||||
.cm-s-mozilla .cm-variable-2,
|
||||
.cm-s-mozilla .cm-quote { /* green */
|
||||
.cm-s-mozilla .cm-number { /* green */
|
||||
color: hsl(72,100%,27%);
|
||||
}
|
||||
|
||||
.theme-fg-color2,
|
||||
.cm-s-mozilla .cm-attribute,
|
||||
.cm-s-mozilla .cm-builtin,
|
||||
.cm-s-mozilla .cm-variable,
|
||||
.cm-s-mozilla .cm-def,
|
||||
.cm-s-mozilla .cm-variable-3,
|
||||
.cm-s-mozilla .cm-property,
|
||||
.cm-s-mozilla .cm-qualifier { /* blue */
|
||||
color: hsl(208,56%,40%);
|
||||
}
|
||||
|
||||
.theme-fg-color3,
|
||||
.cm-s-mozilla .cm-variable,
|
||||
.cm-s-mozilla .cm-tag,
|
||||
.cm-s-mozilla .cm-header { /* dark blue */
|
||||
color: hsl(208,81%,21%)
|
||||
|
@ -107,18 +105,19 @@
|
|||
|
||||
.theme-fg-color5,
|
||||
.cm-s-mozilla .cm-bracket,
|
||||
.cm-s-mozilla .cm-keyword,
|
||||
.cm-s-mozilla .cm-atom { /* Yellow */
|
||||
.cm-s-mozilla .cm-keyword { /* Yellow */
|
||||
color: #a18650;
|
||||
}
|
||||
|
||||
.theme-fg-color6,
|
||||
.cm-s-mozilla .cm-string { /* Orange */
|
||||
.cm-s-mozilla .cm-string,
|
||||
.cm-s-mozilla .cm-string-2 { /* Orange */
|
||||
color: hsl(24,85%,39%);
|
||||
}
|
||||
|
||||
.theme-fg-color7,
|
||||
.cm-s-mozilla .cm-string-2,
|
||||
.cm-s-mozilla .cm-atom,
|
||||
.cm-s-mozilla .cm-quote,
|
||||
.cm-s-mozilla .cm-error { /* Red */
|
||||
color: #bf5656;
|
||||
}
|
||||
|
@ -144,9 +143,10 @@
|
|||
}
|
||||
|
||||
.CodeMirror pre,
|
||||
.cm-s-mozilla .cm-variable-2,
|
||||
.cm-s-mozilla .cm-variable-3,
|
||||
.cm-s-mozilla .cm-operator,
|
||||
.cm-s-mozilla .cm-special,
|
||||
.cm-s-mozilla .cm-number { /* theme-body color */
|
||||
.cm-s-mozilla .cm-special { /* theme-body color */
|
||||
color: black;
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,7 @@
|
|||
background: rgb(176, 176, 176);
|
||||
}
|
||||
|
||||
.CodeMirror-activeline-background { /* selected color with alpha */
|
||||
.cm-s-mozilla .CodeMirror-activeline-background { /* selected color with alpha */
|
||||
background: rgba(185, 215, 253, .35);
|
||||
}
|
||||
|
||||
|
|
|
@ -1717,6 +1717,10 @@ var NativeWindow = {
|
|||
* the checked state as an argument.
|
||||
*/
|
||||
show: function(aMessage, aValue, aButtons, aTabID, aOptions) {
|
||||
if (aButtons == null) {
|
||||
aButtons = [];
|
||||
}
|
||||
|
||||
aButtons.forEach((function(aButton) {
|
||||
this._callbacks[this._callbacksId] = { cb: aButton.callback, prompt: this._promptId };
|
||||
aButton.callback = this._callbacksId;
|
||||
|
|
|
@ -520,11 +520,11 @@ ImportCertsIntoPermanentStorage(const ScopedCERTCertList &certChain, const SECCe
|
|||
chainNode = CERT_LIST_NEXT(chainNode), i++) {
|
||||
rawArray[i] = &chainNode->cert->derCert;
|
||||
}
|
||||
CERT_ImportCerts(certdb, usage, chainLen,
|
||||
rawArray, nullptr, true, caOnly, nullptr);
|
||||
SECStatus srv = CERT_ImportCerts(certdb, usage, chainLen, rawArray,
|
||||
nullptr, true, caOnly, nullptr);
|
||||
|
||||
PORT_Free(rawArray);
|
||||
return SECSuccess;
|
||||
PORT_Free(rawArray);
|
||||
return srv;
|
||||
}
|
||||
|
||||
|
||||
|
@ -800,7 +800,10 @@ nsNSSCertificateDB::ImportValidCACertsInList(CERTCertList *certList, nsIInterfac
|
|||
continue;
|
||||
}
|
||||
|
||||
ImportCertsIntoPermanentStorage(certChain, certUsageAnyCA, true);
|
||||
rv = ImportCertsIntoPermanentStorage(certChain, certUsageAnyCA, true);
|
||||
if (rv != SECSuccess) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -1209,19 +1209,18 @@ Engine.prototype = {
|
|||
|
||||
fileInStream.init(this._file, MODE_RDONLY, PERMS_FILE, false);
|
||||
|
||||
switch (this._dataType) {
|
||||
case SEARCH_DATA_XML:
|
||||
var domParser = Cc["@mozilla.org/xmlextras/domparser;1"].
|
||||
createInstance(Ci.nsIDOMParser);
|
||||
var doc = domParser.parseFromStream(fileInStream, "UTF-8",
|
||||
this._file.fileSize,
|
||||
"text/xml");
|
||||
if (this._dataType == SEARCH_DATA_XML) {
|
||||
var domParser = Cc["@mozilla.org/xmlextras/domparser;1"].
|
||||
createInstance(Ci.nsIDOMParser);
|
||||
var doc = domParser.parseFromStream(fileInStream, "UTF-8",
|
||||
this._file.fileSize,
|
||||
"text/xml");
|
||||
|
||||
this._data = doc.documentElement;
|
||||
break;
|
||||
default:
|
||||
ERROR("Unsuppored engine _dataType in _initFromFile: \"" + this._dataType + "\"",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
this._data = doc.documentElement;
|
||||
} else {
|
||||
ERROR("Unsuppored engine _dataType in _initFromFile: \"" +
|
||||
this._dataType + "\"",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
fileInStream.close();
|
||||
|
||||
|
@ -1230,14 +1229,41 @@ Engine.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Retrieves the engine data from a URI.
|
||||
* Retrieves the data from the engine's file asynchronously. If the engine's
|
||||
* dataType is XML, the document element is placed in the engine's data field.
|
||||
*
|
||||
* @returns {Promise} A promise, resolved successfully if initializing from
|
||||
* data succeeds, rejected if it fails.
|
||||
*/
|
||||
_initFromURI: function SRCH_ENG_initFromURI() {
|
||||
_asyncInitFromFile: function SRCH_ENG__asyncInitFromFile() {
|
||||
return TaskUtils.spawn(function() {
|
||||
if (!this._file || !(yield OS.File.exists(this._file.path)))
|
||||
FAIL("File must exist before calling initFromFile!", Cr.NS_ERROR_UNEXPECTED);
|
||||
|
||||
if (this._dataType == SEARCH_DATA_XML) {
|
||||
let fileURI = NetUtil.ioService.newFileURI(this._file);
|
||||
yield this._retrieveSearchXMLData(fileURI.spec);
|
||||
} else {
|
||||
ERROR("Unsuppored engine _dataType in _initFromFile: \"" +
|
||||
this._dataType + "\"",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
// Now that the data is loaded, initialize the engine object
|
||||
this._initFromData();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the engine data from a URI. Initializes the engine, flushes to
|
||||
* disk, and notifies the search service once initialization is complete.
|
||||
*/
|
||||
_initFromURIAndLoad: function SRCH_ENG_initFromURIAndLoad() {
|
||||
ENSURE_WARN(this._uri instanceof Ci.nsIURI,
|
||||
"Must have URI when calling _initFromURI!",
|
||||
"Must have URI when calling _initFromURIAndLoad!",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
|
||||
LOG("_initFromURI: Downloading engine from: \"" + this._uri.spec + "\".");
|
||||
LOG("_initFromURIAndLoad: Downloading engine from: \"" + this._uri.spec + "\".");
|
||||
|
||||
var chan = NetUtil.ioService.newChannelFromURI(this._uri);
|
||||
|
||||
|
@ -1251,7 +1277,47 @@ Engine.prototype = {
|
|||
chan.notificationCallbacks = listener;
|
||||
chan.asyncOpen(listener, null);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the engine data from a URI asynchronously and initializes it.
|
||||
*
|
||||
* @returns {Promise} A promise, resolved successfully if retrieveing data
|
||||
* succeeds.
|
||||
*/
|
||||
_asyncInitFromURI: function SRCH_ENG__asyncInitFromURI() {
|
||||
return TaskUtils.spawn(function() {
|
||||
LOG("_asyncInitFromURI: Loading engine from: \"" + this._uri.spec + "\".");
|
||||
yield this._retrieveSearchXMLData(this._uri.spec);
|
||||
// Now that the data is loaded, initialize the engine object
|
||||
this._initFromData();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the engine data for a given URI asynchronously.
|
||||
*
|
||||
* @returns {Promise} A promise, resolved successfully if retrieveing data
|
||||
* succeeds.
|
||||
*/
|
||||
_retrieveSearchXMLData: function SRCH_ENG__retrieveSearchXMLData(aURL) {
|
||||
let deferred = Promise.defer();
|
||||
let request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
|
||||
createInstance(Ci.nsIXMLHttpRequest);
|
||||
request.overrideMimeType("text/xml");
|
||||
request.onload = (aEvent) => {
|
||||
let responseXML = aEvent.target.responseXML;
|
||||
this._data = responseXML.documentElement;
|
||||
deferred.resolve();
|
||||
};
|
||||
request.onerror = function(aEvent) {
|
||||
deferred.resolve();
|
||||
};
|
||||
request.open("GET", aURL, true);
|
||||
request.send();
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
_initFromURISync: function SRCH_ENG_initFromURISync() {
|
||||
ENSURE_WARN(this._uri instanceof Ci.nsIURI,
|
||||
"Must have URI when calling _initFromURISync!",
|
||||
|
@ -1575,7 +1641,6 @@ Engine.prototype = {
|
|||
* Initialize this Engine object from the collected data.
|
||||
*/
|
||||
_initFromData: function SRCH_ENG_initFromData() {
|
||||
|
||||
ENSURE_WARN(this._data, "Can't init an engine with no data!",
|
||||
Cr.NS_ERROR_UNEXPECTED);
|
||||
|
||||
|
@ -2642,6 +2707,26 @@ function executeSoon(func) {
|
|||
Services.tm.mainThread.dispatch(func, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for sync initialization has completed or not.
|
||||
*
|
||||
* @param {aPromise} A promise.
|
||||
*
|
||||
* @returns the value returned by the invoked method.
|
||||
* @throws NS_ERROR_ALREADY_INITIALIZED if sync initialization has completed.
|
||||
*/
|
||||
function checkForSyncCompletion(aPromise) {
|
||||
return aPromise.then(function(aValue) {
|
||||
if (gInitialized) {
|
||||
throw Components.Exception("Synchronous fallback was called and has " +
|
||||
"finished so no need to pursue asynchronous " +
|
||||
"initialization",
|
||||
Cr.NS_ERROR_ALREADY_INITIALIZED);
|
||||
}
|
||||
return aValue;
|
||||
});
|
||||
}
|
||||
|
||||
// nsIBrowserSearchService
|
||||
function SearchService() {
|
||||
// Replace empty LOG function with the useful one if the log pref is set.
|
||||
|
@ -2658,6 +2743,9 @@ SearchService.prototype = {
|
|||
// initialization is complete, only if an error has been encountered so far.
|
||||
_initRV: Cr.NS_OK,
|
||||
|
||||
// The boolean indicates that the initialization has started or not.
|
||||
_initStarted: null,
|
||||
|
||||
// If initialization has not been completed yet, perform synchronous
|
||||
// initialization.
|
||||
// Throws in case of initialization error.
|
||||
|
@ -2687,9 +2775,10 @@ SearchService.prototype = {
|
|||
|
||||
// Synchronous implementation of the initializer.
|
||||
// Used by |_ensureInitialized| as a fallback if initialization is not
|
||||
// complete. In this implementation, it is also used by |init|.
|
||||
// complete.
|
||||
_syncInit: function SRCH_SVC__syncInit() {
|
||||
LOG("_syncInit start");
|
||||
this._initStarted = true;
|
||||
try {
|
||||
this._syncLoadEngines();
|
||||
} catch (ex) {
|
||||
|
@ -2707,6 +2796,30 @@ SearchService.prototype = {
|
|||
LOG("_syncInit end");
|
||||
},
|
||||
|
||||
/**
|
||||
* Asynchronous implementation of the initializer.
|
||||
*
|
||||
* @returns {Promise} A promise, resolved successfully if the initialization
|
||||
* succeeds.
|
||||
*/
|
||||
_asyncInit: function SRCH_SVC__asyncInit() {
|
||||
return TaskUtils.spawn(function() {
|
||||
LOG("_asyncInit start");
|
||||
try {
|
||||
yield checkForSyncCompletion(this._asyncLoadEngines());
|
||||
} catch (ex if ex.result != Cr.NS_ERROR_ALREADY_INITIALIZED) {
|
||||
this._initRV = Cr.NS_ERROR_FAILURE;
|
||||
LOG("_asyncInit: failure loading engines: " + ex);
|
||||
}
|
||||
this._addObservers();
|
||||
gInitialized = true;
|
||||
this._initObservers.resolve(this._initRV);
|
||||
Services.obs.notifyObservers(null, SEARCH_SERVICE_TOPIC, "init-complete");
|
||||
LOG("_asyncInit: Completed _asyncInit");
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
|
||||
_engines: { },
|
||||
__sortedEngines: null,
|
||||
get _sortedEngines() {
|
||||
|
@ -2880,6 +2993,115 @@ SearchService.prototype = {
|
|||
LOG("_loadEngines: done");
|
||||
},
|
||||
|
||||
/**
|
||||
* Loads engines asynchronously.
|
||||
*
|
||||
* @returns {Promise} A promise, resolved successfully if loading data
|
||||
* succeeds.
|
||||
*/
|
||||
_asyncLoadEngines: function SRCH_SVC__asyncLoadEngines() {
|
||||
return TaskUtils.spawn(function() {
|
||||
LOG("_asyncLoadEngines: start");
|
||||
// See if we have a cache file so we don't have to parse a bunch of XML.
|
||||
let cache = {};
|
||||
let cacheEnabled = getBoolPref(BROWSER_SEARCH_PREF + "cache.enabled", true);
|
||||
if (cacheEnabled) {
|
||||
let cacheFilePath = OS.Path.join(OS.Constants.Path.profileDir, "search.json");
|
||||
cache = yield checkForSyncCompletion(this._asyncReadCacheFile(cacheFilePath));
|
||||
}
|
||||
|
||||
// Add all the non-empty directories of NS_APP_SEARCH_DIR_LIST to
|
||||
// loadDirs.
|
||||
let loadDirs = [];
|
||||
let locations = getDir(NS_APP_SEARCH_DIR_LIST, Ci.nsISimpleEnumerator);
|
||||
while (locations.hasMoreElements()) {
|
||||
let dir = locations.getNext().QueryInterface(Ci.nsIFile);
|
||||
let iterator = new OS.File.DirectoryIterator(dir.path,
|
||||
{ winPattern: "*.xml" });
|
||||
try {
|
||||
// Add dir to loadDirs if it contains any files.
|
||||
yield checkForSyncCompletion(iterator.next());
|
||||
loadDirs.push(dir);
|
||||
} catch (ex if ex.result != Cr.NS_ERROR_ALREADY_INITIALIZED) {
|
||||
// Catch for StopIteration exception.
|
||||
} finally {
|
||||
iterator.close();
|
||||
}
|
||||
}
|
||||
|
||||
let loadFromJARs = getBoolPref(BROWSER_SEARCH_PREF + "loadFromJars", false);
|
||||
let chromeURIs = [];
|
||||
let chromeFiles = [];
|
||||
if (loadFromJARs) {
|
||||
Services.obs.notifyObservers(null, SEARCH_SERVICE_TOPIC, "find-jar-engines");
|
||||
[chromeFiles, chromeURIs] =
|
||||
yield checkForSyncCompletion(this._asyncFindJAREngines());
|
||||
}
|
||||
|
||||
let toLoad = chromeFiles.concat(loadDirs);
|
||||
function hasModifiedDir(aList) {
|
||||
return TaskUtils.spawn(function() {
|
||||
let modifiedDir = false;
|
||||
|
||||
for (let dir of aList) {
|
||||
if (!cache.directories || !cache.directories[dir.path]) {
|
||||
modifiedDir = true;
|
||||
break;
|
||||
}
|
||||
|
||||
let info = yield OS.File.stat(dir.path);
|
||||
if (cache.directories[dir.path].lastModifiedTime !=
|
||||
info.lastModificationDate.getTime()) {
|
||||
modifiedDir = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
throw new Task.Result(modifiedDir);
|
||||
});
|
||||
}
|
||||
|
||||
function notInCachePath(aPathToLoad)
|
||||
cachePaths.indexOf(aPathToLoad.path) == -1;
|
||||
|
||||
let buildID = Services.appinfo.platformBuildID;
|
||||
let cachePaths = [path for (path in cache.directories)];
|
||||
|
||||
let rebuildCache = !cache.directories ||
|
||||
cache.version != CACHE_VERSION ||
|
||||
cache.locale != getLocale() ||
|
||||
cache.buildID != buildID ||
|
||||
cachePaths.length != toLoad.length ||
|
||||
toLoad.some(notInCachePath) ||
|
||||
(yield checkForSyncCompletion(hasModifiedDir(toLoad)));
|
||||
|
||||
if (!cacheEnabled || rebuildCache) {
|
||||
LOG("_asyncLoadEngines: Absent or outdated cache. Loading engines from disk.");
|
||||
let engines = [];
|
||||
for (let loadDir of loadDirs) {
|
||||
let enginesFromDir =
|
||||
yield checkForSyncCompletion(this._asyncLoadEnginesFromDir(loadDir));
|
||||
engines = engines.concat(enginesFromDir);
|
||||
}
|
||||
let enginesFromURLs =
|
||||
yield checkForSyncCompletion(this._asyncLoadFromChromeURLs(chromeURIs));
|
||||
engines = engines.concat(enginesFromURLs);
|
||||
|
||||
for (let engine of engines) {
|
||||
this._addEngineToStore(engine);
|
||||
}
|
||||
if (cacheEnabled)
|
||||
this._buildCache();
|
||||
return;
|
||||
}
|
||||
|
||||
LOG("_asyncLoadEngines: loading from cache directories");
|
||||
for each (let dir in cache.directories)
|
||||
this._loadEnginesFromCache(dir);
|
||||
|
||||
LOG("_asyncLoadEngines: done");
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
_readCacheFile: function SRCH_SVC__readCacheFile(aFile) {
|
||||
let stream = Cc["@mozilla.org/network/file-input-stream;1"].
|
||||
createInstance(Ci.nsIFileInputStream);
|
||||
|
@ -2896,6 +3118,28 @@ SearchService.prototype = {
|
|||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Read from a given cache file asynchronously.
|
||||
*
|
||||
* @param aPath the file path.
|
||||
*
|
||||
* @returns {Promise} A promise, resolved successfully if retrieveing data
|
||||
* succeeds.
|
||||
*/
|
||||
_asyncReadCacheFile: function SRCH_SVC__asyncReadCacheFile(aPath) {
|
||||
return TaskUtils.spawn(function() {
|
||||
let json;
|
||||
try {
|
||||
let bytes = yield OS.File.read(aPath);
|
||||
json = JSON.parse(new TextDecoder().decode(bytes));
|
||||
} catch (ex) {
|
||||
LOG("_asyncReadCacheFile: Error reading cache file: " + ex);
|
||||
json = {};
|
||||
}
|
||||
throw new Task.Result(json);
|
||||
});
|
||||
},
|
||||
|
||||
_batchTimer: null,
|
||||
_batchCacheInvalidation: function SRCH_SVC__batchCacheInvalidation() {
|
||||
let callback = {
|
||||
|
@ -3042,15 +3286,64 @@ SearchService.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Loads engines from a given directory asynchronously.
|
||||
*
|
||||
* @param aDir the directory.
|
||||
*
|
||||
* @returns {Promise} A promise, resolved successfully if retrieveing data
|
||||
* succeeds.
|
||||
*/
|
||||
_asyncLoadEnginesFromDir: function SRCH_SVC__asyncLoadEnginesFromDir(aDir) {
|
||||
LOG("_asyncLoadEnginesFromDir: Searching in " + aDir.path + " for search engines.");
|
||||
|
||||
// Check whether aDir is the user profile dir
|
||||
let isInProfile = aDir.equals(getDir(NS_APP_USER_SEARCH_DIR));
|
||||
let iterator = new OS.File.DirectoryIterator(aDir.path);
|
||||
return TaskUtils.spawn(function() {
|
||||
let osfiles = yield iterator.nextBatch();
|
||||
iterator.close();
|
||||
|
||||
let engines = [];
|
||||
for (let osfile of osfiles) {
|
||||
if (osfile.isDir || osfile.isSymLink)
|
||||
continue;
|
||||
|
||||
let fileInfo = yield OS.File.stat(osfile.path);
|
||||
if (fileInfo.size == 0)
|
||||
continue;
|
||||
|
||||
let parts = osfile.path.split(".");
|
||||
if (parts.length <= 1 || (parts.pop()).toLowerCase() != "xml") {
|
||||
// Not an engine
|
||||
continue;
|
||||
}
|
||||
|
||||
let addedEngine = null;
|
||||
try {
|
||||
let file = new FileUtils.File(osfile.path);
|
||||
let isWritable = isInProfile;
|
||||
addedEngine = new Engine(file, SEARCH_DATA_XML, !isWritable);
|
||||
yield checkForSyncCompletion(addedEngine._asyncInitFromFile());
|
||||
} catch (ex if ex.result != Cr.NS_ERROR_ALREADY_INITIALIZED) {
|
||||
LOG("_asyncLoadEnginesFromDir: Failed to load " + file.path + "!\n" + ex);
|
||||
continue;
|
||||
}
|
||||
engines.push(addedEngine);
|
||||
}
|
||||
throw new Task.Result(engines);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
_loadFromChromeURLs: function SRCH_SVC_loadFromChromeURLs(aURLs) {
|
||||
aURLs.forEach(function (url) {
|
||||
try {
|
||||
LOG("_loadFromChromeURLs: loading engine from chrome url: " + url);
|
||||
|
||||
let engine = new Engine(makeURI(url), SEARCH_DATA_XML, true);
|
||||
|
||||
|
||||
engine._initFromURISync();
|
||||
|
||||
|
||||
this._addEngineToStore(engine);
|
||||
} catch (ex) {
|
||||
LOG("_loadFromChromeURLs: failed to load engine: " + ex);
|
||||
|
@ -3058,6 +3351,31 @@ SearchService.prototype = {
|
|||
}, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Loads engines from Chrome URLs asynchronously.
|
||||
*
|
||||
* @param aURLs a list of URLs.
|
||||
*
|
||||
* @returns {Promise} A promise, resolved successfully if loading data
|
||||
* succeeds.
|
||||
*/
|
||||
_asyncLoadFromChromeURLs: function SRCH_SVC__asyncLoadFromChromeURLs(aURLs) {
|
||||
return TaskUtils.spawn(function() {
|
||||
let engines = [];
|
||||
for (let url of aURLs) {
|
||||
try {
|
||||
LOG("_asyncLoadFromChromeURLs: loading engine from chrome url: " + url);
|
||||
let engine = new Engine(NetUtil.newURI(url), SEARCH_DATA_XML, true);
|
||||
yield checkForSyncCompletion(engine._asyncInitFromURI());
|
||||
engines.push(engine);
|
||||
} catch (ex if ex.result != Cr.NS_ERROR_ALREADY_INITIALIZED) {
|
||||
LOG("_asyncLoadFromChromeURLs: failed to load engine: " + ex);
|
||||
}
|
||||
}
|
||||
throw new Task.Result(engines);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
_findJAREngines: function SRCH_SVC_findJAREngines() {
|
||||
LOG("_findJAREngines: looking for engines in JARs")
|
||||
|
||||
|
@ -3119,6 +3437,77 @@ SearchService.prototype = {
|
|||
return [chromeFiles, uris];
|
||||
},
|
||||
|
||||
/**
|
||||
* Loads jar engines asynchronously.
|
||||
*
|
||||
* @returns {Promise} A promise, resolved successfully if finding jar engines
|
||||
* succeeds.
|
||||
*/
|
||||
_asyncFindJAREngines: function SRCH_SVC__asyncFindJAREngines() {
|
||||
return TaskUtils.spawn(function() {
|
||||
LOG("_asyncFindJAREngines: looking for engines in JARs")
|
||||
|
||||
let rootURIPref = "";
|
||||
try {
|
||||
rootURIPref = Services.prefs.getCharPref(BROWSER_SEARCH_PREF + "jarURIs");
|
||||
} catch (ex) {}
|
||||
|
||||
if (!rootURIPref) {
|
||||
LOG("_asyncFindJAREngines: no JAR URIs were specified");
|
||||
throw new Task.Result([[], []]);
|
||||
}
|
||||
|
||||
let rootURIs = rootURIPref.split(",");
|
||||
let uris = [];
|
||||
let chromeFiles = [];
|
||||
|
||||
for (let root of rootURIs) {
|
||||
// Find the underlying JAR file for this chrome package (_loadEngines uses
|
||||
// it to determine whether it needs to invalidate the cache)
|
||||
let chromeFile;
|
||||
try {
|
||||
let chromeURI = gChromeReg.convertChromeURL(makeURI(root));
|
||||
let fileURI = chromeURI; // flat packaging
|
||||
while (fileURI instanceof Ci.nsIJARURI)
|
||||
fileURI = fileURI.JARFile; // JAR packaging
|
||||
fileURI.QueryInterface(Ci.nsIFileURL);
|
||||
chromeFile = fileURI.file;
|
||||
} catch (ex) {
|
||||
LOG("_asyncFindJAREngines: failed to get chromeFile for " + root + ": " + ex);
|
||||
}
|
||||
|
||||
if (!chromeFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
chromeFiles.push(chromeFile);
|
||||
|
||||
// Read list.txt from the chrome package to find the engines we need to
|
||||
// load
|
||||
let listURL = root + "list.txt";
|
||||
let deferred = Promise.defer();
|
||||
let request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
|
||||
createInstance(Ci.nsIXMLHttpRequest);
|
||||
request.onload = function(aEvent) {
|
||||
deferred.resolve(aEvent.target.responseText);
|
||||
};
|
||||
request.onerror = function(aEvent) {
|
||||
LOG("_asyncFindJAREngines: failed to retrieve list.txt from " + listURL);
|
||||
deferred.resolve("");
|
||||
};
|
||||
request.open("GET", NetUtil.newURI(listURL).spec, true);
|
||||
request.send();
|
||||
let list = yield deferred.promise;
|
||||
|
||||
let names = [];
|
||||
names = list.split("\n").filter(function (n) !!n);
|
||||
names.forEach(function (n) uris.push(root + n + ".xml"));
|
||||
}
|
||||
throw new Task.Result([chromeFiles, uris]);
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
_saveSortedEngineList: function SRCH_SVC_saveSortedEngineList() {
|
||||
LOG("SRCH_SVC_saveSortedEngineList: starting");
|
||||
|
||||
|
@ -3262,17 +3651,13 @@ SearchService.prototype = {
|
|||
this._initStarted = true;
|
||||
TaskUtils.spawn(function task() {
|
||||
try {
|
||||
yield engineMetadataService.init();
|
||||
if (gInitialized) {
|
||||
// No need to pursue asynchronous initialization,
|
||||
// synchronous fallback had to be called and has finished.
|
||||
return;
|
||||
}
|
||||
// Complete initialization. In the current implementation,
|
||||
// this is done by calling the synchronous initializer.
|
||||
// Future versions might introduce an actually synchronous
|
||||
// implementation.
|
||||
self._syncInit();
|
||||
yield checkForSyncCompletion(engineMetadataService.init());
|
||||
// Complete initialization by calling asynchronous initializer.
|
||||
yield self._asyncInit();
|
||||
TelemetryStopwatch.finish("SEARCH_SERVICE_INIT_MS");
|
||||
} catch (ex if ex.result == Cr.NS_ERROR_ALREADY_INITIALIZED) {
|
||||
// No need to pursue asynchronous because synchronous fallback was
|
||||
// called and has finished.
|
||||
TelemetryStopwatch.finish("SEARCH_SERVICE_INIT_MS");
|
||||
} catch (ex) {
|
||||
self._initObservers.reject(ex);
|
||||
|
@ -3428,7 +3813,7 @@ SearchService.prototype = {
|
|||
engine._installCallback = null;
|
||||
};
|
||||
}
|
||||
engine._initFromURI();
|
||||
engine._initFromURIAndLoad();
|
||||
} catch (ex) {
|
||||
// Drop the reference to the callback, if set
|
||||
if (engine)
|
||||
|
@ -3855,6 +4240,9 @@ var engineMetadataService = {
|
|||
*/
|
||||
syncInit: function epsSyncInit() {
|
||||
LOG("metadata syncInit start");
|
||||
if (this._initState == engineMetadataService._InitStates.FINISHED_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
switch (this._initState) {
|
||||
case engineMetadataService._InitStates.NOT_STARTED:
|
||||
let jsonFile = new FileUtils.File(this._jsonFile);
|
||||
|
@ -4065,7 +4453,7 @@ var engineUpdateService = {
|
|||
ULOG("updating " + engine.name + " from " + updateURI.spec);
|
||||
testEngine = new Engine(updateURI, dataType, false);
|
||||
testEngine._engineToUpdate = engine;
|
||||
testEngine._initFromURI();
|
||||
testEngine._initFromURIAndLoad();
|
||||
} else
|
||||
ULOG("invalid updateURI");
|
||||
|
||||
|
|
|
@ -315,7 +315,13 @@ SuggestAutoComplete.prototype = {
|
|||
|
||||
this._clearServerErrors();
|
||||
|
||||
var serverResults = JSON.parse(responseText);
|
||||
try {
|
||||
var serverResults = JSON.parse(responseText);
|
||||
} catch(ex) {
|
||||
Components.utils.reportError("Failed to parse JSON from " + this._suggestURI.spec + ": " + ex);
|
||||
return;
|
||||
}
|
||||
|
||||
var searchString = serverResults[0] || "";
|
||||
var results = serverResults[1] || [];
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
|
||||
removeMetadata();
|
||||
removeCacheFile();
|
||||
|
||||
do_load_manifest("data/chrome.manifest");
|
||||
|
||||
let url = "chrome://testsearchplugin/locale/searchplugins/";
|
||||
Services.prefs.setCharPref("browser.search.jarURIs", url);
|
||||
Services.prefs.setBoolPref("browser.search.loadFromJars", true);
|
||||
|
||||
do_check_false(Services.search.isInitialized);
|
||||
|
||||
Services.search.init(function search_initialized(aStatus) {
|
||||
do_check_true(Components.isSuccessCode(aStatus));
|
||||
do_check_true(Services.search.isInitialized);
|
||||
|
||||
// test engines from dir are loaded.
|
||||
let engines = Services.search.getEngines();
|
||||
do_check_true(engines.length > 1);
|
||||
|
||||
// test jar engine is loaded ok.
|
||||
let engine = Services.search.getEngineByName("bug645970");
|
||||
do_check_neq(engine, null);
|
||||
|
||||
Services.prefs.clearUserPref("browser.search.jarURIs");
|
||||
Services.prefs.clearUserPref("browser.search.loadFromJars");
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function run_test() {
|
||||
removeMetadata();
|
||||
removeCacheFile();
|
||||
|
||||
do_load_manifest("data/chrome.manifest");
|
||||
|
||||
let url = "chrome://testsearchplugin/locale/searchplugins/";
|
||||
Services.prefs.setCharPref("browser.search.jarURIs", url);
|
||||
Services.prefs.setBoolPref("browser.search.loadFromJars", true);
|
||||
|
||||
do_check_false(Services.search.isInitialized);
|
||||
|
||||
// test engines from dir are loaded.
|
||||
let engines = Services.search.getEngines();
|
||||
do_check_true(engines.length > 1);
|
||||
|
||||
do_check_true(Services.search.isInitialized);
|
||||
|
||||
// test jar engine is loaded ok.
|
||||
let engine = Services.search.getEngineByName("bug645970");
|
||||
do_check_neq(engine, null);
|
||||
|
||||
Services.prefs.clearUserPref("browser.search.jarURIs");
|
||||
Services.prefs.clearUserPref("browser.search.loadFromJars");
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
|
||||
removeMetadata();
|
||||
removeCacheFile();
|
||||
|
||||
do_load_manifest("data/chrome.manifest");
|
||||
|
||||
let url = "chrome://testsearchplugin/locale/searchplugins/";
|
||||
Services.prefs.setCharPref("browser.search.jarURIs", url);
|
||||
Services.prefs.setBoolPref("browser.search.loadFromJars", true);
|
||||
|
||||
do_check_false(Services.search.isInitialized);
|
||||
let fallback = false;
|
||||
|
||||
Services.search.init(function search_initialized(aStatus) {
|
||||
do_check_true(fallback);
|
||||
do_check_true(Components.isSuccessCode(aStatus));
|
||||
do_check_true(Services.search.isInitialized);
|
||||
|
||||
// test engines from dir are loaded.
|
||||
let engines = Services.search.getEngines();
|
||||
do_check_true(engines.length > 1);
|
||||
|
||||
// test jar engine is loaded ok.
|
||||
let engine = Services.search.getEngineByName("bug645970");
|
||||
do_check_neq(engine, null);
|
||||
|
||||
Services.prefs.clearUserPref("browser.search.jarURIs");
|
||||
Services.prefs.clearUserPref("browser.search.loadFromJars");
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
|
||||
// Execute test for the sync fallback while the async code is being executed.
|
||||
Services.obs.addObserver(function searchServiceObserver(aResult, aTopic, aVerb) {
|
||||
if (aVerb == "find-jar-engines") {
|
||||
Services.obs.removeObserver(searchServiceObserver, aTopic);
|
||||
fallback = true;
|
||||
|
||||
do_check_false(Services.search.isInitialized);
|
||||
|
||||
// test engines from dir are loaded.
|
||||
let engines = Services.search.getEngines();
|
||||
do_check_true(engines.length > 1);
|
||||
|
||||
// test jar engine is loaded ok.
|
||||
let engine = Services.search.getEngineByName("bug645970");
|
||||
do_check_neq(engine, null);
|
||||
|
||||
do_check_true(Services.search.isInitialized);
|
||||
}
|
||||
}, "browser-search-service", false);
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
|
||||
removeMetadata();
|
||||
removeCacheFile();
|
||||
|
||||
do_load_manifest("data/chrome.manifest");
|
||||
|
||||
let url = "chrome://testsearchplugin/locale/searchplugins/";
|
||||
Services.prefs.setCharPref("browser.search.jarURIs", url);
|
||||
Services.prefs.setBoolPref("browser.search.loadFromJars", true);
|
||||
|
||||
do_check_false(Services.search.isInitialized);
|
||||
|
||||
Services.search.init(function search_initialized(aStatus) {
|
||||
do_check_true(Components.isSuccessCode(aStatus));
|
||||
do_check_true(Services.search.isInitialized);
|
||||
|
||||
// test engines from dir are loaded.
|
||||
let engines = Services.search.getEngines();
|
||||
do_check_true(engines.length > 1);
|
||||
|
||||
// test jar engine is loaded ok.
|
||||
let engine = Services.search.getEngineByName("bug645970");
|
||||
do_check_neq(engine, null);
|
||||
|
||||
Services.prefs.clearUserPref("browser.search.jarURIs");
|
||||
Services.prefs.clearUserPref("browser.search.loadFromJars");
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
|
||||
do_check_false(Services.search.isInitialized);
|
||||
|
||||
// test engines from dir are loaded.
|
||||
let engines = Services.search.getEngines();
|
||||
do_check_true(engines.length > 1);
|
||||
|
||||
do_check_true(Services.search.isInitialized);
|
||||
|
||||
// test jar engine is loaded ok.
|
||||
let engine = Services.search.getEngineByName("bug645970");
|
||||
do_check_neq(engine, null);
|
||||
}
|
||||
|
|
@ -27,3 +27,7 @@ support-files =
|
|||
[test_prefSync.js]
|
||||
[test_notifications.js]
|
||||
[test_addEngine_callback.js]
|
||||
[test_async.js]
|
||||
[test_sync.js]
|
||||
[test_sync_fallback.js]
|
||||
[test_sync_delay_fallback.js]
|
||||
|
|
|
@ -386,8 +386,8 @@ struct TelemetryHistogram {
|
|||
uint32_t max;
|
||||
uint32_t bucketCount;
|
||||
uint32_t histogramType;
|
||||
uint16_t id_offset;
|
||||
uint16_t comment_offset;
|
||||
uint32_t id_offset;
|
||||
uint32_t comment_offset;
|
||||
bool extendedStatisticsOK;
|
||||
|
||||
const char *id() const;
|
||||
|
|
|
@ -76,7 +76,7 @@ def write_histogram_table(histograms):
|
|||
|
||||
strtab_name = "gHistogramStringTable"
|
||||
table.writeDefinition(sys.stdout, strtab_name)
|
||||
static_assert("sizeof(%s) <= UINT16_MAX" % strtab_name,
|
||||
static_assert("sizeof(%s) <= UINT32_MAX" % strtab_name,
|
||||
"index overflow")
|
||||
|
||||
# Write out static asserts for histogram data. We'd prefer to perform
|
||||
|
|
|
@ -583,6 +583,17 @@ let NodeFront = protocol.FrontClass(NodeActor, {
|
|||
return ret;
|
||||
},
|
||||
|
||||
/**
|
||||
* Do we use a local target?
|
||||
* Useful to know if a rawNode is available or not.
|
||||
*
|
||||
* This will, one day, be removed. External code should
|
||||
* not need to know if the target is remote or not.
|
||||
*/
|
||||
isLocal_toBeDeprecated: function() {
|
||||
return !!this.conn._transport._serverConnection;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get an nsIDOMNode for the given node front. This only works locally,
|
||||
* and is only intended as a stopgap during the transition to the remote
|
||||
|
|
|
@ -492,7 +492,6 @@ MetroInput::OnPointerPressed(UI::Core::ICoreWindow* aSender,
|
|||
// tracking flags.
|
||||
mContentConsumingTouch = false;
|
||||
mRecognizerWantsEvents = true;
|
||||
mIsFirstTouchMove = true;
|
||||
mCancelable = true;
|
||||
mCanceledIds.Clear();
|
||||
}
|
||||
|
@ -560,24 +559,15 @@ MetroInput::OnPointerMoved(UI::Core::ICoreWindow* aSender,
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
AddPointerMoveDataToRecognizer(aArgs);
|
||||
|
||||
// If the point hasn't moved, filter it out per the spec. Pres shell does
|
||||
// this as well, but we need to know when our first touchmove is going to
|
||||
// get delivered so we can check the result.
|
||||
if (!HasPointMoved(touch, currentPoint.Get())) {
|
||||
// The recognizer needs the intermediate data otherwise it acts flaky
|
||||
AddPointerMoveDataToRecognizer(aArgs);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// If we've accumulated a batch of pointer moves and we're now on a new batch
|
||||
// at a new position send the previous batch. (perf opt)
|
||||
if (!mIsFirstTouchMove && touch->mChanged) {
|
||||
WidgetTouchEvent* touchEvent =
|
||||
new WidgetTouchEvent(true, NS_TOUCH_MOVE, mWidget.Get());
|
||||
InitTouchEventTouchList(touchEvent);
|
||||
DispatchAsyncTouchEvent(touchEvent);
|
||||
}
|
||||
|
||||
touch = CreateDOMTouch(currentPoint.Get());
|
||||
touch->mChanged = true;
|
||||
// replacing old touch point in mTouches map
|
||||
|
@ -585,15 +575,8 @@ MetroInput::OnPointerMoved(UI::Core::ICoreWindow* aSender,
|
|||
|
||||
WidgetTouchEvent* touchEvent =
|
||||
new WidgetTouchEvent(true, NS_TOUCH_MOVE, mWidget.Get());
|
||||
|
||||
// If this is the first touch move of our session, dispatch it now.
|
||||
if (mIsFirstTouchMove) {
|
||||
InitTouchEventTouchList(touchEvent);
|
||||
DispatchAsyncTouchEvent(touchEvent);
|
||||
mIsFirstTouchMove = false;
|
||||
}
|
||||
|
||||
AddPointerMoveDataToRecognizer(aArgs);
|
||||
InitTouchEventTouchList(touchEvent);
|
||||
DispatchAsyncTouchEvent(touchEvent);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -203,7 +203,6 @@ private:
|
|||
// For example, a set of mousemove, mousedown, and mouseup events might
|
||||
// be sent if a tap is detected.
|
||||
bool mContentConsumingTouch;
|
||||
bool mIsFirstTouchMove;
|
||||
bool mCancelable;
|
||||
bool mRecognizerWantsEvents;
|
||||
nsTArray<uint32_t> mCanceledIds;
|
||||
|
|
Загрузка…
Ссылка в новой задаче