Merge mozilla-central to mozilla-inbound
authorEd Morley <bmo@edmorley.co.uk>
Tue, 10 Jan 2012 23:56:12 +0000
changeset 85418 6f4760bd3de0aa23a1bf726bbdbb03f37d1beea6
parent 85417 37ede8ee0d0ec8a7556245d1a76af133757a8ebb (current diff)
parent 85332 1962ca549264ba02a27d1c50c13fb969411bf1c3 (diff)
child 85419 f2df780ad0476887699181cdfcd7b76ab0c05bf2
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone12.0a1
Merge mozilla-central to mozilla-inbound
browser/app/profile/firefox.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1044,17 +1044,17 @@ pref("devtools.scratchpad.enabled", true
 
 // Enable the Style Editor.
 pref("devtools.styleeditor.enabled", true);
 
 // Enable tools for Chrome development.
 pref("devtools.chrome.enabled", false);
 
 // Disable the GCLI enhanced command line.
-pref("devtools.gcli.enable", false);
+pref("devtools.gcli.enable", true);
 
 // The last Web Console height. This is initially 0 which means that the Web
 // Console will use the default height next time it shows.
 // Change to -1 if you do not want the Web Console to remember its last height.
 pref("devtools.hud.height", 0);
 
 // Remember the Web Console position. Possible values:
 //   above - above the web page,
--- a/browser/devtools/webconsole/GcliCommands.jsm
+++ b/browser/devtools/webconsole/GcliCommands.jsm
@@ -80,16 +80,28 @@ gcli.addCommand({
   exec: function(args, context) {
     let hud = HUDService.getHudReferenceById(context.environment.hudId);
     hud.gcliterm.clearOutput();
   }
 });
 
 
 /**
+ * 'console close' command
+ */
+gcli.addCommand({
+  name: "console close",
+  description: gcli.lookup("consolecloseDesc"),
+  exec: function(args, context) {
+    let tab = HUDService.getHudReferenceById(context.environment.hudId).tab;
+    HUDService.deactivateHUDForContext(tab);
+  }
+});
+
+/**
  * 'inspect' command
  */
 gcli.addCommand({
   name: "inspect",
   description: gcli.lookup("inspectDesc"),
   manual: gcli.lookup("inspectManual"),
   params: [
     {
--- a/browser/devtools/webconsole/HUDService.jsm
+++ b/browser/devtools/webconsole/HUDService.jsm
@@ -3656,17 +3656,17 @@ HeadsUpDisplay.prototype = {
     this.createConsoleMenu(this.consoleWrap);
 
     this.filterPrefs = HUDService.getDefaultFilterPrefs(this.hudId);
 
     let consoleFilterToolbar = this.makeFilterToolbar();
     consoleFilterToolbar.setAttribute("id", "viewGroup");
     this.consoleFilterToolbar = consoleFilterToolbar;
 
-    this.hintNode = this.makeXULNode("div");
+    this.hintNode = this.makeXULNode("vbox");
     this.hintNode.setAttribute("class", "gcliterm-hint-node");
 
     let hintParentNode = this.makeXULNode("vbox");
     hintParentNode.setAttribute("flex", "0");
     hintParentNode.setAttribute("class", "gcliterm-hint-parent");
     hintParentNode.setAttribute("pack", "end");
     hintParentNode.appendChild(this.hintNode);
     hintParentNode.hidden = true;
@@ -6830,17 +6830,17 @@ GcliTerm.prototype = {
     this.element = this.document.createElement("vbox");
     this.element.setAttribute("class", "gcliterm-input-container");
     this.element.setAttribute("flex", "0");
 
     this.inputStack = this.document.createElement("stack");
     this.inputStack.setAttribute("class", "gcliterm-stack-node");
     this.element.appendChild(this.inputStack);
 
-    this.completeNode = this.document.createElement("div");
+    this.completeNode = this.document.createElementNS(HTML_NS, "div");
     this.completeNode.setAttribute("class", "gcliterm-complete-node");
     this.completeNode.setAttribute("aria-live", "polite");
     this.inputStack.appendChild(this.completeNode);
 
     this.inputNode = this.document.createElement("textbox");
     this.inputNode.setAttribute("class", "gcliterm-input-node");
     this.inputNode.setAttribute("rows", "1");
     this.inputStack.appendChild(this.inputNode);
@@ -6862,26 +6862,26 @@ GcliTerm.prototype = {
     if (aEvent.output.output == null) {
       return;
     }
 
     let output = aEvent.output.output;
     if (aEvent.output.command.returnType == "html" && typeof output == "string") {
       output = this.document.createRange().createContextualFragment(
           '<div xmlns="' + HTML_NS + '" xmlns:xul="' + XUL_NS + '">' +
-          output + '</div>').firstChild;
+          output + '</div>');
     }
 
     // See https://github.com/mozilla/domtemplate/blob/master/README.md
     // for docs on the template() function
     let element = this.document.createRange().createContextualFragment(
-      '<richlistitem xmlns="' + XUL_NS + '" clipboardText="${clipboardText}"' +
-      '    timestamp="${timestamp}" id="${id}" class="hud-msg-node">' +
-      '  <label class="webconsole-timestamp" value="${timestampString}"/>' +
-      '  <vbox class="webconsole-msg-icon-container" style="${iconContainerStyle}">' +
+      '<richlistitem xmlns="' + XUL_NS + '" _clipboardText="${clipboardText}"' +
+      '    _timestamp="${timestamp}" _id="${id}" class="hud-msg-node">' +
+      '  <label class="webconsole-timestamp" _value="${timestampString}"/>' +
+      '  <vbox class="webconsole-msg-icon-container" _style="${iconContainerStyle}">' +
       '    <image class="webconsole-msg-icon"/>' +
       '    <spacer flex="1"/>' +
       '  </vbox>' +
       '  <hbox flex="1" class="gcliterm-msg-body">${output}</hbox>' +
       '  <hbox align="start"><label value="1" class="webconsole-msg-repeat"/></hbox>' +
       '</richlistitem>').firstChild;
 
     let hud = HUDService.getHudReferenceById(this.hudId);
--- a/browser/devtools/webconsole/gcli.jsm
+++ b/browser/devtools/webconsole/gcli.jsm
@@ -3024,16 +3024,22 @@ JavascriptType.prototype.parse = functio
   // should be completed.
   var beginning = this._findCompletionBeginning(typed);
 
   // There was an error analyzing the string.
   if (beginning.err) {
     return new Conversion(typed, arg, Status.ERROR, beginning.err);
   }
 
+  // If the current state is ParseState.COMPLEX, then we can't do completion.
+  // so bail out now
+  if (beginning.state === ParseState.COMPLEX) {
+    return new Conversion(typed, arg);
+  }
+
   // If the current state is not ParseState.NORMAL, then we are inside of a
   // string which means that no completion is possible.
   if (beginning.state !== ParseState.NORMAL) {
     return new Conversion(typed, arg, Status.INCOMPLETE, '');
   }
 
   var completionPart = typed.substring(beginning.startPos);
   var properties = completionPart.split('.');
@@ -3063,17 +3069,17 @@ JavascriptType.prototype.parse = functio
 
       try {
         scope = scope[prop];
       }
       catch (ex) {
         // It would be nice to be able to report this error in some way but
         // as it can happen just when someone types '{sessionStorage.', it
         // almost doesn't really count as an error, so we ignore it
-        return new Conversion(typed, arg, Status.INCOMPLETE, '');
+        return new Conversion(typed, arg, Status.VALID, '');
       }
     }
   }
   else {
     matchProp = properties[0].trimLeft();
   }
 
   // If the reason we just stopped adjusting the scope was a non-simple string,
@@ -3241,30 +3247,54 @@ function isVendorPrefixed(name) {
          name.indexOf('webkit') === 0 ||
          name.indexOf('ms') === 0;
 }
 
 /**
  * Constants used in return value of _findCompletionBeginning()
  */
 var ParseState = {
+  /**
+   * We have simple input like window.foo, without any punctuation that makes
+   * completion prediction be confusing or wrong
+   */
   NORMAL: 0,
+
+  /**
+   * The cursor is in some Javascript that makes completion hard to predict,
+   * like console.log(
+   */
+  COMPLEX: 1,
+
+  /**
+   * The cursor is inside single quotes (')
+   */
   QUOTE: 2,
+
+  /**
+   * The cursor is inside single quotes (")
+   */
   DQUOTE: 3
 };
 
 var OPEN_BODY = '{[('.split('');
 var CLOSE_BODY = '}])'.split('');
 var OPEN_CLOSE_BODY = {
   '{': '}',
   '[': ']',
   '(': ')'
 };
 
 /**
+ * How we distinguish between simple and complex JS input. We attempt
+ * completion against simple JS.
+ */
+var simpleChars = /[a-zA-Z0-9.]/;
+
+/**
  * Analyzes a given string to find the last statement that is interesting for
  * later completion.
  * @param text A string to analyze
  * @return If there was an error in the string detected, then a object like
  *   { err: 'ErrorMesssage' }
  * is returned, otherwise a object like
  *   {
  *     state: ParseState.NORMAL|ParseState.QUOTE|ParseState.DQUOTE,
@@ -3272,18 +3302,23 @@ var OPEN_CLOSE_BODY = {
  *   }
  */
 JavascriptType.prototype._findCompletionBeginning = function(text) {
   var bodyStack = [];
 
   var state = ParseState.NORMAL;
   var start = 0;
   var c;
+  var complex = false;
+
   for (var i = 0; i < text.length; i++) {
     c = text[i];
+    if (!simpleChars.test(c)) {
+      complex = true;
+    }
 
     switch (state) {
       // Normal JS state.
       case ParseState.NORMAL:
         if (c === '"') {
           state = ParseState.DQUOTE;
         }
         else if (c === '\'') {
@@ -3339,16 +3374,20 @@ JavascriptType.prototype._findCompletion
         }
         else if (c === '\'') {
           state = ParseState.NORMAL;
         }
         break;
     }
   }
 
+  if (state === ParseState.NORMAL && complex) {
+    state = ParseState.COMPLEX;
+  }
+
   return {
     state: state,
     startPos: start
   };
 };
 
 /**
  * Return true if the passed object is either an iterator or a generator, and
@@ -4333,17 +4372,16 @@ Requisition.prototype.toCanonicalString 
     // named parameters in place of positional params. Both can wait.
     if (assignment.getValue() !== assignment.param.defaultValue) {
       line.push(' ');
       line.push(type.stringify(assignment.getValue()));
     }
   }, this);
 
   // Canonically, if we've opened with a { then we should have a } to close
-  var command = this.commandAssignment.getValue();
   if (cmd === '{') {
     if (this.getAssignment(0).getArg().suffix.indexOf('}') === -1) {
       line.push(' }');
     }
   }
 
   return line.join('');
 };
@@ -5286,19 +5324,16 @@ define('gcli/ui/domtemplate', ['require'
   exports.template = obj.template;
 
 });
 define("text!gcli/commands/help.css", [], void 0);
 define("text!gcli/commands/help_intro.html", [], "\n" +
   "<h2>${l10n.introHeader}</h2>\n" +
   "\n" +
   "<p>\n" +
-  "  <a target=\"_blank\" href=\"https://developer.mozilla.org/AppLinks/WebConsoleHelp?locale=${lang}\">\n" +
-  "    ${l10n.introBody}\n" +
-  "  </a>\n" +
   "</p>\n" +
   "");
 
 define("text!gcli/commands/help_list.html", [], "\n" +
   "<h3>${getHeading()}</h3>\n" +
   "\n" +
   "<table>\n" +
   "  <tr foreach=\"command in ${getMatchingCommands()}\"\n" +
@@ -5369,34 +5404,34 @@ function Console(options) {
 
   // Create a FocusManager for the various parts to register with
   this.focusManager = new FocusManager({ document: options.chromeDocument });
   this.focusManager.onFocus.add(this.gcliTerm.show, this.gcliTerm);
   this.focusManager.onBlur.add(this.gcliTerm.hide, this.gcliTerm);
   this.focusManager.addMonitoredElement(this.gcliTerm.hintNode, 'gcliTerm');
 
   this.inputter = new Inputter({
-    document: options.contentDocument,
+    document: options.chromeDocument,
     requisition: options.requisition,
     inputElement: options.inputElement,
     completeElement: options.completeElement,
     completionPrompt: '',
     backgroundElement: options.backgroundElement,
     focusManager: this.focusManager
   });
 
   this.menu = new CommandMenu({
-    document: options.contentDocument,
+    document: options.chromeDocument,
     requisition: options.requisition,
     menuClass: 'gcliterm-menu'
   });
   this.hintElement.appendChild(this.menu.element);
 
   this.argFetcher = new ArgFetcher({
-    document: options.contentDocument,
+    document: options.chromeDocument,
     requisition: options.requisition,
     argFetcherClass: 'gcliterm-argfetcher'
   });
   this.hintElement.appendChild(this.argFetcher.element);
 
   this.chromeWindow = options.chromeDocument.defaultView;
   this.resizer = this.resizer.bind(this);
   this.chromeWindow.addEventListener('resize', this.resizer, false);
@@ -5464,16 +5499,67 @@ Console.prototype.resizer = function() {
     }
     else {
       this.argFetcher.setMaxHeight(parentHeight);
 
       this.hintElement.style.overflowY = null;
       this.hintElement.style.borderBottomColor = 'white';
     }
   }
+
+  // We also try to make the max-width of any GCLI elements so they don't
+  // extend outside the scroll area.
+  var doc = this.hintElement.ownerDocument;
+
+  var outputNode = this.hintElement.parentNode.parentNode.children[1];
+  var outputs = outputNode.getElementsByClassName('gcliterm-msg-body');
+  var listItems = outputNode.getElementsByClassName('hud-msg-node');
+
+  // This is an top-side estimate. We could try to calculate it, maybe using
+  // something along these lines http://www.alexandre-gomes.com/?p=115 However
+  // experience has shown this to be hard to get to work reliably
+  // Also we don't need to be precise. If we use a number that is too big then
+  // the only down-side is too great a right margin
+  var scrollbarWidth = 20;
+
+  if (listItems.length > 0) {
+    var parentWidth = outputNode.getBoundingClientRect().width - scrollbarWidth;
+    var otherWidth;
+    var body;
+
+    for (var i = 0; i < listItems.length; ++i) {
+      var listItem = listItems[i];
+      // a.k.a 'var otherWidth = 132'
+      otherWidth = 0;
+      body = null;
+
+      for (var j = 0; j < listItem.children.length; j++) {
+        var child = listItem.children[j];
+
+        if (child.classList.contains('gcliterm-msg-body')) {
+          body = child.children[0];
+        }
+        else {
+          otherWidth += child.getBoundingClientRect().width;
+        }
+
+        var styles = doc.defaultView.getComputedStyle(child, null);
+        otherWidth += parseInt(styles.borderLeftWidth, 10) +
+                      parseInt(styles.borderRightWidth, 10) +
+                      parseInt(styles.paddingLeft, 10) +
+                      parseInt(styles.paddingRight, 10) +
+                      parseInt(styles.marginLeft, 10) +
+                      parseInt(styles.marginRight, 10);
+      }
+
+      if (body) {
+        body.style.width = (parentWidth - otherWidth) + 'px';
+      }
+    }
+  }
 };
 
 exports.Console = Console;
 
 });
 /*
  * Copyright 2009-2011 Mozilla Foundation and contributors
  * Licensed under the New BSD license. See LICENSE.txt or:
@@ -6034,17 +6120,17 @@ Completer.prototype.update = function(in
   //
   // <span class="gcli-prompt">${completionPrompt}</span>
   // ${appendMarkupStatus()}
   // ${prefix}
   // <span class="gcli-in-ontab">${contents}</span>
   // <span class="gcli-in-closebrace" if="${unclosedJs}">}<span>
 
   var document = this.element.ownerDocument;
-  var prompt = document.createElement('span');
+  var prompt = dom.createElement(document, 'span');
   prompt.classList.add('gcli-prompt');
   prompt.appendChild(document.createTextNode(this.completionPrompt + ' '));
   this.element.appendChild(prompt);
 
   if (input.typed.length > 0) {
     var scores = this.requisition.getInputStatusMarkup(input.cursor.start);
     this.appendMarkupStatus(this.element, scores, input);
   }
@@ -6066,31 +6152,31 @@ Completer.prototype.update = function(in
       prefix = ' \u00a0';         // aka &nbsp;
       contents = '\u21E5 ' + tab; // aka &rarr; the right arrow
     }
 
     if (prefix != null) {
       this.element.appendChild(document.createTextNode(prefix));
     }
 
-    var suffix = document.createElement('span');
+    var suffix = dom.createElement(document, 'span');
     suffix.classList.add('gcli-in-ontab');
     suffix.appendChild(document.createTextNode(contents));
     this.element.appendChild(suffix);
   }
 
   // Add a grey '}' to the end of the command line when we've opened
   // with a { but haven't closed it
   var command = this.requisition.commandAssignment.getValue();
   var unclosedJs = command && command.name === '{' &&
           this.requisition.getAssignment(0).getArg().suffix.indexOf('}') === -1;
   if (unclosedJs) {
-    var close = document.createElement('span');
+    var close = dom.createElement(document, 'span');
     close.classList.add('gcli-in-closebrace');
-    close.appendChild(document.createTextNode('}'));
+    close.appendChild(document.createTextNode(' }'));
     this.element.appendChild(close);
   }
 };
 
 /**
  * Mark-up an array of Status values with spans
  */
 Completer.prototype.appendMarkupStatus = function(element, scores, input) {
@@ -6106,17 +6192,17 @@ Completer.prototype.appendMarkupStatus =
 
   while (true) {
     if (lastStatus !== scores[i]) {
       var state = scores[i];
       if (!state) {
         console.error('No state at i=' + i + '. scores.len=' + scores.length);
         state = Status.VALID;
       }
-      span = document.createElement('span');
+      span = dom.createElement(document, 'span');
       span.classList.add('gcli-in-' + state.toString().toLowerCase());
       lastStatus = scores[i];
     }
     var char = input.typed[i];
     if (char === ' ') {
       char = '\u00a0';
     }
     contents += char;
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_579412_input_focus.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_579412_input_focus.js
@@ -37,17 +37,22 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests that the input field is focused when the console is opened.
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testInputFocus, false);
 }
 
 function testInputFocus() {
   browser.removeEventListener("DOMContentLoaded", testInputFocus, false);
 
   openConsole();
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_580001_closing_after_completion.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_580001_closing_after_completion.js
@@ -38,17 +38,22 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests to ensure that errors don't appear when the console is closed while a
 // completion is being performed.
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testClosingAfterCompletion,
                            false);
 }
 
 function testClosingAfterCompletion() {
   browser.removeEventListener("DOMContentLoaded",
                               testClosingAfterCompletion, false);
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_580400_groups.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_580400_groups.js
@@ -37,17 +37,22 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests that console groups behave properly.
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testGroups, false);
 }
 
 function testGroups() {
   browser.removeEventListener("DOMContentLoaded", testGroups, false);
 
   openConsole();
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_582201_duplicate_errors.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_582201_duplicate_errors.js
@@ -38,17 +38,22 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests that exceptions thrown by content don't show up twice in the Web
 // Console.
 
 const TEST_DUPLICATE_ERROR_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-duplicate-error.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   expectUncaughtException();
   addTab(TEST_DUPLICATE_ERROR_URI);
   browser.addEventListener("DOMContentLoaded", testDuplicateErrors, false);
 }
 
 function testDuplicateErrors() {
   browser.removeEventListener("DOMContentLoaded", testDuplicateErrors,
                               false);
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_583816_No_input_and_Tab_key_pressed.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_583816_No_input_and_Tab_key_pressed.js
@@ -34,17 +34,22 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//browser/test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testCompletion, false);
 }
 
 function testCompletion() {
   browser.removeEventListener("DOMContentLoaded", testCompletion, false);
 
   openConsole();
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js
@@ -33,17 +33,22 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 const TEST_URI = "data:text/html,<p>bug 585991 - autocomplete popup keyboard usage test";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("load", tabLoaded, true);
 }
 
 function tabLoaded() {
   browser.removeEventListener("load", tabLoaded, true);
   openConsole();
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_585991_autocomplete_popup.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_585991_autocomplete_popup.js
@@ -33,17 +33,22 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 const TEST_URI = "data:text/html,<p>bug 585991 - autocomplete popup test";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("load", tabLoaded, true);
 }
 
 function tabLoaded() {
   browser.removeEventListener("load", tabLoaded, true);
   openConsole();
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_586388_select_all.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_586388_select_all.js
@@ -5,17 +5,22 @@
  *
  * Contributor(s):
  *  Patrick Walton <pcwalton@mozilla.com>
  *
  * ***** END LICENSE BLOCK ***** */
 
 const TEST_URI = "http://example.com/";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded",
                            testSelectionWhenMovingBetweenBoxes, false);
 }
 
 function testSelectionWhenMovingBetweenBoxes() {
   browser.removeEventListener("DOMContentLoaded",
                               testSelectionWhenMovingBetweenBoxes, false);
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_587617_output_copy.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_587617_output_copy.js
@@ -5,17 +5,22 @@
  * Contributor(s):
  *  Mihai Șucan <mihai.sucan@gmail.com>
  *  Patrick Walton <pcwalton@mozilla.com>
  *
  * ***** END LICENSE BLOCK ***** */
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("load", tabLoaded, true);
 }
 
 function tabLoaded() {
   browser.removeEventListener("load", tabLoaded, true);
   openConsole();
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_588342_document_focus.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_588342_document_focus.js
@@ -6,18 +6,22 @@
  * Contributor(s):
  *  Mihai Șucan <mihai.sucan@gmail.com>
  *
  * ***** END LICENSE BLOCK ***** */
 
 const TEST_URI = "data:text/html,Web Console test for bug 588342";
 let fm, notificationBox, input;
 
-function test()
-{
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
+function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
   addTab(TEST_URI);
   browser.addEventListener("load", tabLoad, true);
 }
 
 function tabLoad(aEvent) {
   browser.removeEventListener(aEvent.type, arguments.callee, true);
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_588967_input_expansion.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_588967_input_expansion.js
@@ -33,17 +33,22 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testInputExpansion, false);
 }
 
 function testInputExpansion() {
   browser.removeEventListener("DOMContentLoaded", testInputExpansion, false);
 
   openConsole();
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_592442_closing_brackets.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_592442_closing_brackets.js
@@ -8,17 +8,22 @@
  *  Patrick Walton <pcwalton@mozilla.com>
  *  Mihai Șucan <mihai.sucan@gmail.com>
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests that, when the user types an extraneous closing bracket, no error
 // appears.
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab("data:text/html,test for bug 592442");
   browser.addEventListener("load", testExtraneousClosingBrackets, true);
 }
 
 function testExtraneousClosingBrackets(aEvent) {
   browser.removeEventListener(aEvent.type, arguments.callee, true);
 
   openConsole();
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_594477_clickable_output.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_594477_clickable_output.js
@@ -149,13 +149,18 @@ function propertyPanelHidden(aEvent) {
 
   executeSoon(function() {
     document.removeEventListener("popupshown", propertyPanelShowFailure, false);
     outputItem = null;
     finishTest();
   });
 }
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("load", tabLoad1, true);
 }
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_594497_history_arrow_keys.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_594497_history_arrow_keys.js
@@ -150,13 +150,18 @@ function performTests() {
 
   ok(!inputNode.value,
      "VK_DOWN: inputNode.value is empty");
 
   inputNode = values = null;
   executeSoon(finishTest);
 }
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab("data:text/html,Web Console test for bug 594497 and bug 619598");
   browser.addEventListener("load", tabLoad, true);
 }
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_595934_message_categories.js
@@ -167,16 +167,17 @@ function testNext() {
     content.location = testLocation;
   }
   else {
     executeSoon(finish);
   }
 }
 
 function testEnd() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
   Services.console.unregisterListener(TestObserver);
   output.removeEventListener("DOMNodeInserted", onDOMNodeInserted, false);
   output = jsterm = null;
   finishTest();
 }
 
 function onDOMNodeInserted(aEvent) {
   let textContent = output.textContent;
@@ -186,14 +187,15 @@ function onDOMNodeInserted(aEvent) {
   }
 
   if (foundCategory) {
     executeSoon(testNext);
   }
 }
 
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   registerCleanupFunction(testEnd);
 
   addTab("data:text/html,Web Console test for bug 595934 - message categories coverage.");
   browser.addEventListener("load", tabLoad, true);
 }
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_598357_jsterm_output.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_598357_jsterm_output.js
@@ -220,13 +220,18 @@ function testEnd() {
       ok(false, "the property panel failed to show for inputValues[" + i + "]");
     }
   }
 
   eventHandlers = popupshown = null;
   executeSoon(finishTest);
 }
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("load", tabLoad, true);
 }
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_601352_scroll.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_601352_scroll.js
@@ -52,13 +52,18 @@ function tabLoad(aEvent) {
 
     ok(top >= 0 && Math.floor(bottom) <= height + 1,
        "last message is visible");
 
     finishTest();
   });
 }
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab("data:text/html,Web Console test for bug 601352");
   browser.addEventListener("load", tabLoad, true);
 }
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_611795.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_611795.js
@@ -27,22 +27,27 @@ function onContentLoaded()
   let msg = "The console output is repeated 10 times";
   let node = outputNode.querySelector(".webconsole-msg-console");
   is(node.childNodes[3].firstChild.getAttribute("value"), 10, msg);
 
   jsterm.clearOutput();
   finishTest();
 }
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 /**
  * Unit test for bug 611795:
  * Repeated CSS messages get collapsed into one.
  */
 function test()
 {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("load", function() {
     browser.removeEventListener("load", arguments.callee, true);
 
     openConsole();
     browser.addEventListener("load", onContentLoaded, true);
     content.location.reload();
   }, true);
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_613280_jsterm_copy.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_613280_jsterm_copy.js
@@ -3,17 +3,22 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  *
  * Contributor(s):
  *   Mihai Șucan <mihai.sucan@gmail.com>
  */
 
 const TEST_URI = "data:text/html,Web Console test for bug 613280";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("load", tabLoaded, true);
 }
 
 function tabLoaded() {
   browser.removeEventListener("load", tabLoaded, true);
   openConsole();
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_614793_jsterm_scroll.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_614793_jsterm_scroll.js
@@ -31,13 +31,18 @@ function tabLoad(aEvent) {
   oldScrollTop = boxObject.scrollTop;
   outputNode.scrollBoxObject.ensureElementIsVisible(outputNode.lastChild);
 
   is(boxObject.scrollTop, oldScrollTop, "scroll location is the same");
 
   finishTest();
 }
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab("data:text/html,Web Console test for bug 614793: jsterm result scroll");
   browser.addEventListener("load", tabLoad, true);
 }
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_618311_close_panels.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_618311_close_panels.js
@@ -33,17 +33,22 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("load", function() {
     browser.removeEventListener("load", arguments.callee, true);
 
     openConsole();
     content.location.reload();
     browser.addEventListener("load", tabLoaded, true);
   }, true);
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_618311_private_browsing.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_618311_private_browsing.js
@@ -36,17 +36,22 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
 let pb = Cc["@mozilla.org/privatebrowsing;1"].
          getService(Ci.nsIPrivateBrowsingService);
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab("data:text/html,Web Console test for bug 618311 (private browsing)");
 
   browser.addEventListener("load", function() {
     browser.removeEventListener("load", arguments.callee, true);
 
     registerCleanupFunction(function() {
       pb.privateBrowsingEnabled = false;
       pb = null;
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_621644_jsterm_dollar.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_621644_jsterm_dollar.js
@@ -37,12 +37,17 @@ function tabLoad(aEvent) {
                      querySelector(".webconsole-msg-output:last-child");
     ok(outputItem.textContent.indexOf("621644") > -1,
        "jsterm output is correct for $$()");
 
     executeSoon(finishTest);
   }, content);
 }
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("load", tabLoad, true);
 }
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_626484_output_copy_order.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_626484_output_copy_order.js
@@ -1,13 +1,18 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 let itemsSet, HUD;
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab("data:text/html,Web Console test for bug 626484");
   browser.addEventListener("load", tabLoaded, true);
 }
 
 function tabLoaded(aEvent) {
   browser.removeEventListener(aEvent.type, arguments.callee, true);
   openConsole();
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_632275_getters_document_width.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_632275_getters_document_width.js
@@ -1,14 +1,19 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-bug-632275-getters.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("load", tabLoaded, true);
 }
 
 function tabLoaded() {
   browser.removeEventListener("load", tabLoaded, true);
   openConsole();
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_632347_iterators_generators.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_632347_iterators_generators.js
@@ -33,17 +33,22 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-bug-632347-iterators-generators.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("load", tabLoaded, true);
 }
 
 function tabLoaded() {
   browser.removeEventListener("load", tabLoaded, true);
   openConsole();
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_642615_autocomplete.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_642615_autocomplete.js
@@ -71,12 +71,17 @@ function tabLoad(aEvent) {
         goDoCommand("cmd_paste");
       },
       finish);
   }, false);
 
   EventUtils.synthesizeKey("u", {});
 }
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("load", tabLoad, true);
 }
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_644419_log_limits.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_644419_log_limits.js
@@ -7,17 +7,22 @@
 // Tests that the Web Console limits the number of lines displayed according to
 // the limit set for each category.
 
 const TEST_URI = "http://example.com/browser/browser/devtools/" +
                  "webconsole/test/test-bug-644419-log-limits.html";
 
 var gOldPref, gHudId;
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab("data:text/html,Web Console test for bug 644419: Console should " +
          "have user-settable log limits for each message category");
   browser.addEventListener("load", onLoad, true);
 }
 
 function onLoad(aEvent) {
   browser.removeEventListener(aEvent.type, arguments.callee, true);
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_651501_document_body_autocomplete.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_651501_document_body_autocomplete.js
@@ -3,17 +3,22 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // Tests that document.body autocompletes in the web console.
 
 Cu.import("resource:///modules/PropertyPanel.jsm");
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab("data:text/html,Web Console autocompletion bug in document.body");
   browser.addEventListener("load", onLoad, true);
 }
 
 var gHUD;
 
 function onLoad(aEvent) {
   browser.removeEventListener(aEvent.type, arguments.callee, true);
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_653531_highlighter_console_helper.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_653531_highlighter_console_helper.js
@@ -128,18 +128,23 @@ function performTestComparisons(evt)
 }
 
 function finishUp() {
   InspectorUI.closeInspectorUI();
   gBrowser.removeCurrentTab();
   finish();
 }
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test()
 {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   waitForExplicitFinish();
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", function() {
     gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
     doc = content.document;
     waitForFocus(createDocument, content);
   }, true);
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_658368_time_methods.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_658368_time_methods.js
@@ -1,17 +1,22 @@
 /* vim:set ts=2 sw=2 sts=2 et: */
 /*
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // Tests that the Console API implements the time() and timeEnd() methods.
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab("http://example.com/browser/browser/devtools/webconsole/" +
          "test/test-bug-658368-time-methods.html");
   openConsole();
   browser.addEventListener("load", onLoad, true);
 }
 
 function onLoad(aEvent) {
   browser.removeEventListener(aEvent.type, onLoad, true);
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_660806_history_nav.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_660806_history_nav.js
@@ -1,15 +1,20 @@
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const TEST_URI = "data:text/html,<p>bug 660806 - history navigation must not show the autocomplete popup";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("load", tabLoaded, true);
 }
 
 function tabLoaded()
 {
   browser.removeEventListener("load", tabLoaded, true);
   openConsole();
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_664131_console_group.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_664131_console_group.js
@@ -2,17 +2,22 @@
 /*
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // Tests that console.group/groupEnd works as intended.
 const GROUP_INDENT = 12;
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab("data:text/html,Web Console test for bug 664131: Expand console " +
          "object with group methods");
   browser.addEventListener("load", onLoad, true);
 }
 
 function onLoad(aEvent) {
   browser.removeEventListener(aEvent.type, arguments.callee, true);
 
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_704295.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_704295.js
@@ -35,17 +35,22 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests for bug 704295
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testCompletion, false);
 }
 
 function testCompletion() {
   browser.removeEventListener("DOMContentLoaded", testCompletion, false);
 
   openConsole();
--- a/browser/devtools/webconsole/test/browser_webconsole_chrome.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_chrome.js
@@ -37,17 +37,22 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests that code completion works properly.
 
 const TEST_URI = "chrome://browser/content/browser.xul";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testChrome, false);
 }
 
 function testChrome() {
   browser.removeEventListener("DOMContentLoaded", testChrome, false);
 
   openConsole();
--- a/browser/devtools/webconsole/test/browser_webconsole_completion.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_completion.js
@@ -37,17 +37,22 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests that code completion works properly.
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testCompletion, false);
 }
 
 function testCompletion() {
   browser.removeEventListener("DOMContentLoaded", testCompletion, false);
 
   openConsole();
--- a/browser/devtools/webconsole/test/browser_webconsole_console_logging_api.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_console_logging_api.js
@@ -37,17 +37,22 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests that the basic console.log()-style APIs and filtering work.
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", onLoad, false);
 }
 
 function onLoad() {
   browser.removeEventListener("DOMContentLoaded", onLoad, false);
 
   openConsole();
--- a/browser/devtools/webconsole/test/browser_webconsole_consoleonpage.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_consoleonpage.js
@@ -6,18 +6,23 @@
  * Contributor(s):
  *  Julian Viereck <jviereck@mozilla.com>
  *  Mihai Șucan <mihai.sucan@gmail.com>
  *
  * ***** END LICENSE BLOCK ***** */
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-own-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test()
 {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("load", function() {
     browser.removeEventListener("load", arguments.callee, true);
     testOpenWebConsole();
   }, true);
 }
 
 function testOpenWebConsole()
--- a/browser/devtools/webconsole/test/browser_webconsole_copying_multiple_messages_inserts_newlines_in_between.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_copying_multiple_messages_inserts_newlines_in_between.js
@@ -7,18 +7,23 @@
  *  Patrick Walton <pcwalton@mozilla.com>
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests that copying multiple messages inserts newlines in between.
 
 const TEST_URI = "data:text/html,Web Console test for bug 586142";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test()
 {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", onLoad, false);
 }
 
 function onLoad() {
   browser.removeEventListener("DOMContentLoaded", onLoad,
                                                false);
   executeSoon(testNewlines);
--- a/browser/devtools/webconsole/test/browser_webconsole_execution_scope.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_execution_scope.js
@@ -37,17 +37,22 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests that commands run by the user are executed in content space.
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testExecutionScope, false);
 }
 
 function testExecutionScope() {
   browser.removeEventListener("DOMContentLoaded", testExecutionScope,
                               false);
 
--- a/browser/devtools/webconsole/test/browser_webconsole_history.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_history.js
@@ -41,17 +41,22 @@
 // Tests the console history feature accessed via the up and down arrow keys.
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
 // Constants used for defining the direction of JSTerm input history navigation.
 const HISTORY_BACK = -1;
 const HISTORY_FORWARD = 1;
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testHistory, false);
 }
 
 function testHistory() {
   browser.removeEventListener("DOMContentLoaded", testHistory, false);
 
   openConsole();
--- a/browser/devtools/webconsole/test/browser_webconsole_hud_getters.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_hud_getters.js
@@ -38,17 +38,22 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests that the HUD can be accessed via the HUD references in the HUD
 // service.
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testHUDGetters, false);
 }
 
 function testHUDGetters() {
   browser.removeEventListener("DOMContentLoaded", testHUDGetters, false);
 
   openConsole();
--- a/browser/devtools/webconsole/test/browser_webconsole_js_input_and_output_styling.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_js_input_and_output_styling.js
@@ -38,17 +38,22 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests that the correct CSS styles are applied to the lines of console
 // output.
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testJSInputAndOutputStyling,
                            false);
 }
 
 function testJSInputAndOutputStyling() {
   browser.removeEventListener("DOMContentLoaded",
                               testJSInputAndOutputStyling, false);
--- a/browser/devtools/webconsole/test/browser_webconsole_js_input_expansion.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_js_input_expansion.js
@@ -37,17 +37,22 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests that the input box expands as the user types long lines.
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testJSInputExpansion, false);
 }
 
 function testJSInputExpansion() {
   browser.removeEventListener("DOMContentLoaded", testJSInputExpansion,
                               false);
 
--- a/browser/devtools/webconsole/test/browser_webconsole_jsterm.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_jsterm.js
@@ -38,17 +38,22 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
 let jsterm;
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testJSTerm, false);
 }
 
 function checkResult(msg, desc, lines) {
   let labels = jsterm.outputNode.querySelectorAll(".webconsole-msg-output");
   is(labels.length, lines, "correct number of results shown for " + desc);
   is(labels[lines-1].textContent.trim(), msg, "correct message shown for " +
--- a/browser/devtools/webconsole/test/browser_webconsole_null_and_undefined_output.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_null_and_undefined_output.js
@@ -38,17 +38,22 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Test that JavaScript expressions that evaluate to null or undefined produce
 // meaningful output.
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testNullAndUndefinedOutput,
                            false);
 }
 
 function testNullAndUndefinedOutput() {
   browser.removeEventListener("DOMContentLoaded",
                               testNullAndUndefinedOutput, false);
--- a/browser/devtools/webconsole/test/browser_webconsole_output_order.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_output_order.js
@@ -38,17 +38,22 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests that any output created from calls to the console API comes after the
 // echoed JavaScript.
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testOutputOrder, false);
 }
 
 function testOutputOrder() {
   browser.removeEventListener("DOMContentLoaded", testOutputOrder, false);
 
   openConsole();
--- a/browser/devtools/webconsole/test/browser_webconsole_property_panel.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_property_panel.js
@@ -38,17 +38,22 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests the functionality of the "property panel", which allows JavaScript
 // objects and DOM nodes to be inspected.
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testPropertyPanel, false);
 }
 
 function testPropertyPanel() {
   browser.removeEventListener("DOMContentLoaded", testPropertyPanel, false);
 
   openConsole();
--- a/browser/devtools/webconsole/test/browser_webconsole_property_provider.js
+++ b/browser/devtools/webconsole/test/browser_webconsole_property_provider.js
@@ -38,17 +38,22 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 // Tests the property provider, which is part of the code completion
 // infrastructure.
 
 const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
 
+registerCleanupFunction(function() {
+  Services.prefs.clearUserPref("devtools.gcli.enable");
+});
+
 function test() {
+  Services.prefs.setBoolPref("devtools.gcli.enable", false);
   addTab(TEST_URI);
   browser.addEventListener("DOMContentLoaded", testPropertyProvider, false);
 }
 
 function testPropertyProvider() {
   browser.removeEventListener("DOMContentLoaded", testPropertyProvider,
                               false);
 
--- a/browser/locales/en-US/chrome/browser/devtools/gcli.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/gcli.properties
@@ -108,17 +108,17 @@ helpManual=Provide help either on a spec
 # parameter to the 'help' command. See helpSearchManual for a fuller
 # description of what it does. This string is designed to be shown in a dialog
 # with restricted space, which is why it should be as short as possible.
 helpSearchDesc=Search string
 
 # LOCALIZATION NOTE (helpSearchManual): A fuller description of the 'search'
 # parameter to the 'help' command. Displayed when the user asks for help on
 # what it does.
-helpSearchManual=A search string to use in narrowing down the list of commands that are displayed to the user. Any part of the string can match, regular expressions are not supported.
+helpSearchManual=A search string to use in narrowing down the list of commands that are displayed to the user. Any part of the command name can match, regular expressions are not supported.
 
 # LOCALIZATION NOTE (helpManSynopsis): A heading shown at the top of a help
 # page for a command in the console It labels a summary of the parameters to
 # the command
 helpManSynopsis=Synopsis
 
 # LOCALIZATION NOTE (helpManDescription): A heading shown in a help page for a
 # command in the console. This heading precedes the top level description.
--- a/browser/locales/en-US/chrome/browser/devtools/gclicommands.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/gclicommands.properties
@@ -50,8 +50,13 @@ inspectManual=Investigate the dimensions
 # 'node' parameter to the 'inspect' command, which is displayed in a dialog
 # when the user is using this command.
 inspectNodeDesc=CSS selector
 
 # LOCALIZATION NOTE (inspectNodeManual) A fuller description of the 'node'
 # parameter to the 'inspect' command, displayed when the user asks for help
 # on what it does.
 inspectNodeManual=A CSS selector for use with Document.querySelector which identifies a single element
+
+# LOCALIZATION NOTE (consolecloseDesc) A very short description of the
+# 'console close' command. This string is designed to be shown in a menu
+# alongside the command name, which is why it should be as short as possible.
+consolecloseDesc=Close the console
--- a/browser/themes/gnomestripe/devtools/webconsole.css
+++ b/browser/themes/gnomestripe/devtools/webconsole.css
@@ -62,21 +62,17 @@
 }
 
 /* General output styles */
 
 .webconsole-timestamp {
   color: GrayText;
   margin-top: 0;
   margin-bottom: 0;
-}
-
-.hud-msg-node {
-  list-style-image: url(chrome://browser/skin/devtools/webconsole.png);
-  -moz-image-region: rect(0, 1px, 0, 0);
+  font: 12px "DejaVu Sans Mono", monospace;
 }
 
 .webconsole-msg-icon {
   margin: 3px 4px;
   width: 8px;
   height: 8px;
 }
 
@@ -86,16 +82,19 @@
 }
 
 .webconsole-msg-body {
   margin-top: 0;
   margin-bottom: 3px;
   -moz-margin-start: 3px;
   -moz-margin-end: 6px;
   white-space: pre-wrap;
+  list-style-image: url(chrome://browser/skin/devtools/webconsole.png);
+  -moz-image-region: rect(0, 1px, 0, 0);
+  font: 12px "DejaVu Sans Mono", monospace;
 }
 
 .webconsole-msg-body-piece {
   margin: 0;
 }
 
 .webconsole-msg-url {
   margin: 0 6px;
@@ -128,17 +127,16 @@
   text-align: end;
 }
 
 .hud-msg-node[selected="true"] > .webconsole-timestamp,
 .hud-msg-node[selected="true"] > .webconsole-location {
   color: inherit;
 }
 
-.hud-output-node,
 .jsterm-input-node,
 .jsterm-complete-node {
   font: 12px "DejaVu Sans Mono", monospace;
 }
 
 .hud-output-node {
   -moz-appearance: none;
   border-bottom: 1px solid ThreeDShadow;
--- a/browser/themes/pinstripe/devtools/webconsole.css
+++ b/browser/themes/pinstripe/devtools/webconsole.css
@@ -65,21 +65,17 @@
 }
 
 /* General output styles */
 
 .webconsole-timestamp {
   color: GrayText;
   margin-top: 0;
   margin-bottom: 0;
-}
-
-.hud-msg-node {
-  list-style-image: url(chrome://browser/skin/devtools/webconsole.png);
-  -moz-image-region: rect(0, 1px, 0, 0);
+  font: 11px Menlo, Monaco, monospace;
 }
 
 .webconsole-msg-icon {
   margin: 3px 4px;
   width: 8px;
   height: 8px;
 }
 
@@ -89,16 +85,19 @@
 }
 
 .webconsole-msg-body {
   margin-top: 0;
   margin-bottom: 3px;
   -moz-margin-start: 3px;
   -moz-margin-end: 6px;
   white-space: pre-wrap;
+  list-style-image: url(chrome://browser/skin/devtools/webconsole.png);
+  -moz-image-region: rect(0, 1px, 0, 0);
+  font: 11px Menlo, Monaco, monospace;
 }
 
 .webconsole-msg-body-piece {
   margin: 0;
 }
 
 .webconsole-msg-url {
   margin: 0 6px;
@@ -131,17 +130,16 @@
   text-align: end;
 }
 
 .hud-msg-node[selected="true"] > .webconsole-timestamp,
 .hud-msg-node[selected="true"] > .webconsole-location {
   color: inherit;
 }
 
-.hud-output-node,
 .jsterm-input-node,
 .jsterm-complete-node {
   font: 11px Menlo, Monaco, monospace;
 }
 
 .hud-output-node {
   -moz-appearance: none;
   border-bottom: 1px solid ThreeDShadow;
--- a/browser/themes/winstripe/devtools/webconsole.css
+++ b/browser/themes/winstripe/devtools/webconsole.css
@@ -61,21 +61,17 @@
 }
 
 /* General output styles */
 
 .webconsole-timestamp {
   color: GrayText;
   margin-top: 0;
   margin-bottom: 0;
-}
-
-.hud-msg-node {
-  list-style-image: url(chrome://browser/skin/devtools/webconsole.png);
-  -moz-image-region: rect(0, 1px, 0, 0);
+  font: 12px Consolas, Lucida Console, monospace;
 }
 
 .webconsole-msg-icon {
   margin: 3px 4px;
   width: 8px;
   height: 8px;
 }
 
@@ -85,16 +81,19 @@
 }
 
 .webconsole-msg-body {
   margin-top: 0;
   margin-bottom: 3px;
   -moz-margin-start: 3px;
   -moz-margin-end: 6px;
   white-space: pre-wrap;
+  list-style-image: url(chrome://browser/skin/devtools/webconsole.png);
+  -moz-image-region: rect(0, 1px, 0, 0);
+  font: 12px Consolas, Lucida Console, monospace;
 }
 
 .webconsole-msg-body-piece {
   margin: 0;
 }
 
 .webconsole-msg-url {
   margin: 0 6px;
@@ -127,17 +126,16 @@
   text-align: end;
 }
 
 .hud-msg-node[selected="true"] > .webconsole-timestamp,
 .hud-msg-node[selected="true"] > .webconsole-location {
   color: inherit;
 }
 
-.hud-output-node,
 .jsterm-input-node,
 .jsterm-complete-node {
   font: 12px Consolas, Lucida Console, monospace;
 }
 
 .hud-output-node {
   -moz-appearance: none;
   border-bottom: 1px solid ThreeDShadow;
--- a/mobile/android/locales/Makefile.in
+++ b/mobile/android/locales/Makefile.in
@@ -43,16 +43,17 @@ VPATH     = @srcdir@
 relativesrcdir = mobile/android/locales
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/config.mk
 
 SUBMAKEFILES += \
         $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/Makefile \
         $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales/Makefile \
+        $(DEPTH)/mobile/locales/Makefile \
         $(NULL)
 
 PREF_JS_EXPORTS = $(firstword $(wildcard $(LOCALE_SRCDIR)/mobile-l10n.js) \
                        @srcdir@/en-US/mobile-l10n.js )
 
 include $(topsrcdir)/config/rules.mk
 
 include $(topsrcdir)/toolkit/locales/l10n.mk
--- a/mobile/android/makefiles.sh
+++ b/mobile/android/makefiles.sh
@@ -39,16 +39,17 @@ add_makefiles "
 netwerk/locales/Makefile
 dom/locales/Makefile
 toolkit/locales/Makefile
 security/manager/locales/Makefile
 mobile/android/app/Makefile
 mobile/android/app/profile/extensions/Makefile
 mobile/android/base/Makefile
 mobile/android/base/locales/Makefile
+mobile/locales/Makefile
 $MOZ_BRANDING_DIRECTORY/Makefile
 $MOZ_BRANDING_DIRECTORY/locales/Makefile
 mobile/android/chrome/Makefile
 mobile/android/chrome/tests/Makefile
 mobile/android/components/Makefile
 mobile/android/components/build/Makefile
 mobile/android/modules/Makefile
 mobile/android/installer/Makefile
--- a/mobile/xul/locales/Makefile.in
+++ b/mobile/xul/locales/Makefile.in
@@ -51,16 +51,17 @@ endif
 vpath crashreporter%.ini $(LOCALE_SRCDIR)/crashreporter
 ifdef LOCALE_MERGEDIR
 vpath crashreporter%.ini @srcdir@/en-US/crashreporter
 endif
 
 SUBMAKEFILES += \
         $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/Makefile \
         $(DEPTH)/$(MOZ_BRANDING_DIRECTORY)/locales/Makefile \
+        $(DEPTH)/mobile/locales/Makefile \
         $(NULL)
 
 MOZ_LANGPACK_EID=langpack-$(AB_CD)@firefox-mobile.mozilla.org
 PREF_JS_EXPORTS = $(firstword $(wildcard $(LOCALE_SRCDIR)/mobile-l10n.js) \
                        @srcdir@/en-US/mobile-l10n.js )
 
 # Shouldn't := DEB_BUILD_ARCH despite the $(shell ) as deb isn't everywhere
 DEB_BUILD_ARCH = $(shell dpkg-architecture -qDEB_BUILD_ARCH)
--- a/mobile/xul/makefiles.sh
+++ b/mobile/xul/makefiles.sh
@@ -42,16 +42,17 @@ mobile/xul/app/profile/extensions/Makefi
 $MOZ_BRANDING_DIRECTORY/content/Makefile
 $MOZ_BRANDING_DIRECTORY/locales/Makefile
 mobile/xul/chrome/Makefile
 mobile/xul/components/Makefile
 mobile/xul/components/build/Makefile
 mobile/xul/modules/Makefile
 mobile/xul/installer/Makefile
 mobile/xul/locales/Makefile
+mobile/locales/Makefile
 mobile/xul/Makefile
 mobile/xul/themes/core/Makefile
 "
 
 if [ "$ENABLE_TESTS" ]; then
   add_makefiles "
     mobile/xul/chrome/tests/Makefile
   "