merge m-c to fx-team
authorTim Taubert <tim.taubert@gmx.de>
Wed, 21 Dec 2011 10:38:31 +0100
changeset 83181 cd921d073b226cfa86ce6cb7c91307929ebf45c0
parent 83175 4e4878620bb576ecc2e445e6cfba8ba540047b79 (current diff)
parent 83180 a98e349f29f7f8f2ac0ec6d6b36b89eb9b7905a2 (diff)
child 83182 d6b976e83811207066453e1de9b9d6f2abae0228
child 83551 6587497e7e9651a03597d49f5015fb3dc492bcc3
push id4288
push userbmo@edmorley.co.uk
push dateWed, 21 Dec 2011 12:16:44 +0000
treeherdermozilla-inbound@ed488640454a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone12.0a1
first release with
nightly win32
cd921d073b22 / 12.0a1 / 20111221031226 / files
nightly win64
cd921d073b22 / 12.0a1 / 20111221031226 / files
nightly linux32
nightly linux64
nightly mac
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly win32
nightly win64
merge m-c to fx-team
browser/devtools/webconsole/test/browser_webconsole_bug_583816_tab_focus.js
--- a/browser/devtools/scratchpad/scratchpad.js
+++ b/browser/devtools/scratchpad/scratchpad.js
@@ -19,16 +19,17 @@
  * Portions created by the Initial Developer are Copyright (C) 2011
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Rob Campbell <robcee@mozilla.com> (original author)
  *   Erik Vold <erikvvold@gmail.com>
  *   David Dahl <ddahl@mozilla.com>
  *   Mihai Sucan <mihai.sucan@gmail.com>
+ *   Kenny Heaton <kennyheaton@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -578,16 +579,17 @@ var Scratchpad = {
     let self = this;
     NetUtil.asyncFetch(channel, function(aInputStream, aStatus) {
       let content = null;
 
       if (Components.isSuccessCode(aStatus)) {
         content = NetUtil.readInputStreamToString(aInputStream,
                                                   aInputStream.available());
         self.setText(content);
+        self.editor.resetUndo();
       }
       else if (!aSilentError) {
         window.alert(self.strings.GetStringFromName("openFile.failed"));
       }
 
       if (aCallback) {
         aCallback.call(self, aStatus, content);
       }
--- a/browser/devtools/scratchpad/test/Makefile.in
+++ b/browser/devtools/scratchpad/test/Makefile.in
@@ -55,11 +55,12 @@ include $(topsrcdir)/config/rules.mk
 		browser_scratchpad_bug_660560_tab.js \
 		browser_scratchpad_open.js \
 		browser_scratchpad_restore.js \
 		browser_scratchpad_bug_679467_falsy.js \
 		browser_scratchpad_bug_699130_edit_ui_updates.js \
 		browser_scratchpad_bug_669612_unsaved.js \
 		head.js \
 		browser_scratchpad_bug_653427_confirm_close.js \
+		browser_scratchpad_bug684546_reset_undo.js \
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_bug684546_reset_undo.js
@@ -0,0 +1,155 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+Cu.import("resource://gre/modules/NetUtil.jsm");
+Cu.import("resource://gre/modules/FileUtils.jsm");
+
+// Reference to the Scratchpad chrome window object.
+let gScratchpadWindow;
+
+// Reference to the Scratchpad object.
+let gScratchpad;
+
+// Reference to the temporary nsIFile we will work with.
+let gFileA;
+let gFileB;
+
+// The temporary file content.
+let gFileAContent = "// File A ** Hello World!";
+let gFileBContent = "// File B ** Goodbye All";
+
+// Help track if one or both files are saved
+let gFirstFileSaved = false;
+
+function test()
+{
+  waitForExplicitFinish();
+
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function browserLoad() {
+    gBrowser.selectedBrowser.removeEventListener("load", browserLoad, true);
+    openScratchpad(runTests);
+  }, true);
+
+  content.location = "data:text/html,<p>test that undo get's reset after file load in Scratchpad";
+}
+
+function runTests()
+{
+  gScratchpad = gScratchpadWindow.Scratchpad;
+
+  // Create a temporary file.
+  gFileA = FileUtils.getFile("TmpD", ["fileAForBug684546.tmp"]);
+  gFileA.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+
+  gFileB = FileUtils.getFile("TmpD", ["fileBForBug684546.tmp"]);
+  gFileB.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
+
+  // Write the temporary file.
+  let foutA = Cc["@mozilla.org/network/file-output-stream;1"].
+             createInstance(Ci.nsIFileOutputStream);
+  foutA.init(gFileA.QueryInterface(Ci.nsILocalFile), 0x02 | 0x08 | 0x20,
+            0644, foutA.DEFER_OPEN);
+
+  let foutB = Cc["@mozilla.org/network/file-output-stream;1"].
+             createInstance(Ci.nsIFileOutputStream);
+  foutB.init(gFileB.QueryInterface(Ci.nsILocalFile), 0x02 | 0x08 | 0x20,
+            0644, foutB.DEFER_OPEN);
+
+  let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
+                  createInstance(Ci.nsIScriptableUnicodeConverter);
+  converter.charset = "UTF-8";
+  let fileContentStreamA = converter.convertToInputStream(gFileAContent);
+  let fileContentStreamB = converter.convertToInputStream(gFileBContent);
+
+  NetUtil.asyncCopy(fileContentStreamA, foutA, tempFileSaved);
+  NetUtil.asyncCopy(fileContentStreamB, foutB, tempFileSaved);
+}
+
+function tempFileSaved(aStatus)
+{
+  let success = Components.isSuccessCode(aStatus);
+
+  ok(success, "a temporary file was saved successfully");
+
+  if (!success)
+  {
+    finish();
+    return;
+  }
+
+  if (gFirstFileSaved && success)
+  {
+    ok((gFirstFileSaved && success), "Both files loaded");
+    // Import the file A into Scratchpad.
+    gScratchpad.importFromFile(gFileA.QueryInterface(Ci.nsILocalFile),  true,
+                              fileAImported);
+  }
+  gFirstFileSaved = success;
+}
+
+function fileAImported(aStatus, aFileContent)
+{
+  ok(Components.isSuccessCode(aStatus),
+     "the temporary file A was imported successfully with Scratchpad");
+
+  is(aFileContent, gFileAContent, "received data is correct");
+
+  is(gScratchpad.getText(), gFileAContent, "the editor content is correct");
+
+  gScratchpad.setText("new text", gScratchpad.getText().length);
+
+  is(gScratchpad.getText(), gFileAContent + "new text", "text updated correctly");
+  gScratchpad.undo();
+  is(gScratchpad.getText(), gFileAContent, "undo works");
+  gScratchpad.redo();
+  is(gScratchpad.getText(), gFileAContent + "new text", "redo works");
+
+  // Import the file B into Scratchpad.
+  gScratchpad.importFromFile(gFileB.QueryInterface(Ci.nsILocalFile),  true,
+                            fileBImported);
+}
+
+function fileBImported(aStatus, aFileContent)
+{
+  ok(Components.isSuccessCode(aStatus),
+     "the temporary file B was imported successfully with Scratchpad");
+
+  is(aFileContent, gFileBContent, "received data is correct");
+
+  is(gScratchpad.getText(), gFileBContent, "the editor content is correct");
+
+  ok(!gScratchpad.editor.canUndo(), "editor cannot undo after load");
+
+  gScratchpad.undo();
+  is(gScratchpad.getText(), gFileBContent,
+      "the editor content is still correct after undo");
+
+  gScratchpad.setText("new text", gScratchpad.getText().length);
+  is(gScratchpad.getText(), gFileBContent + "new text", "text updated correctly");
+
+  gScratchpad.undo();
+  is(gScratchpad.getText(), gFileBContent, "undo works");
+  ok(!gScratchpad.editor.canUndo(), "editor cannot undo after load (again)");
+
+  gScratchpad.redo();
+  is(gScratchpad.getText(), gFileBContent + "new text", "redo works");
+
+  // Done!
+  finish();
+}
+
+registerCleanupFunction(function() {
+  if (gFileA && gFileA.exists())
+  {
+    gFileA.remove(false);
+    gFileA = null;
+  }
+  if (gFileB && gFileB.exists())
+  {
+    gFileB.remove(false);
+    gFileB = null;
+  }
+  gScratchpad = null;
+});
--- a/browser/devtools/sourceeditor/source-editor-orion.jsm
+++ b/browser/devtools/sourceeditor/source-editor-orion.jsm
@@ -16,16 +16,17 @@
  *
  * The Initial Developer of the Original Code is
  * The Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2011
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Mihai Sucan <mihai.sucan@gmail.com> (original author)
+ *   Kenny Heaton <kennyheaton@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -549,16 +550,24 @@ SourceEditor.prototype = {
    *         True if there are changes that can be repeated, false otherwise.
    */
   canRedo: function SE_canRedo()
   {
     return this._undoStack.canRedo();
   },
 
   /**
+   * Reset the Undo stack
+   */
+  resetUndo: function SE_resetUndo()
+  {
+    this._undoStack.reset();
+  },
+
+  /**
    * Start a compound change in the editor. Compound changes are grouped into
    * only one change that you can undo later, after you invoke
    * endCompoundChange().
    */
   startCompoundChange: function SE_startCompoundChange()
   {
     this._undoStack.startCompoundChange();
   },
--- a/browser/devtools/sourceeditor/source-editor-textarea.jsm
+++ b/browser/devtools/sourceeditor/source-editor-textarea.jsm
@@ -16,16 +16,17 @@
  *
  * The Initial Developer of the Original Code is
  * The Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2011
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Mihai Sucan <mihai.sucan@gmail.com> (original author)
+ *   Kenny Heaton <kennyheaton@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -143,18 +144,17 @@ SourceEditor.prototype = {
 
     // Mimic the mode change.
     this.setMode(aConfig.mode || SourceEditor.DEFAULTS.MODE);
 
     this._editor.transactionManager.maxTransactionCount =
       aConfig.undoLimit || SourceEditor.DEFAULTS.UNDO_LIMIT;
 
     // Make sure that the transactions stack is clean.
-    this._editor.transactionManager.clear();
-    this._editor.resetModificationCount();
+    this.resetUndo();
 
     // Add the edit action listener so we can fire the SourceEditor TextChanged
     // events.
     this._editActionListener = new EditActionListener(this);
     this._editor.addEditActionListener(this._editActionListener);
 
     this._lineDelimiter = win.navigator.platform.indexOf("Win") > -1 ?
                           "\r\n" : "\n";
@@ -402,16 +402,25 @@ SourceEditor.prototype = {
   {
     let isEnabled = {};
     let canRedo = {};
     this._editor.canRedo(isEnabled, canRedo);
     return canRedo.value;
   },
 
   /**
+   * Reset the Undo stack
+   */
+  resetUndo: function SE_resetUndo()
+  {
+    this._editor.transactionManager.clear();
+    this._editor.resetModificationCount();
+  },
+
+  /**
    * Start a compound change in the editor. Compound changes are grouped into
    * only one change that you can undo later, after you invoke
    * endCompoundChange().
    */
   startCompoundChange: function SE_startCompoundChange()
   {
     this._editor.beginTransaction();
   },
--- a/browser/devtools/sourceeditor/test/Makefile.in
+++ b/browser/devtools/sourceeditor/test/Makefile.in
@@ -45,14 +45,15 @@ include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES = \
 		browser_sourceeditor_initialization.js \
 		browser_bug684862_paste_html.js \
 		browser_bug687573_vscroll.js \
 		browser_bug687568_pagescroll.js \
 		browser_bug687580_drag_and_drop.js \
+		browser_bug684546_reset_undo.js \
 		browser_bug695035_middle_click_paste.js \
 		browser_bug687160_line_api.js \
 		head.js \
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/devtools/sourceeditor/test/browser_bug684546_reset_undo.js
@@ -0,0 +1,70 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+Cu.import("resource:///modules/source-editor.jsm");
+
+let testWin;
+let editor;
+
+function test()
+{
+  waitForExplicitFinish();
+
+  const windowUrl = "data:application/vnd.mozilla.xul+xml,<?xml version='1.0'?>" +
+    "<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
+    " title='test for bug 684546 - reset undo' width='300' height='500'>" +
+    "<box flex='1'/></window>";
+  const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
+
+  testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null);
+  testWin.addEventListener("load", function onWindowLoad() {
+    testWin.removeEventListener("load", onWindowLoad, false);
+    waitForFocus(initEditor, testWin);
+  }, false);
+}
+
+function initEditor()
+{
+  let box = testWin.document.querySelector("box");
+
+  editor = new SourceEditor();
+  editor.init(box, {}, editorLoaded);
+}
+
+function editorLoaded()
+{
+  editor.setText("First");
+  editor.setText("Second", 5);
+  is(editor.getText(), "FirstSecond", "text set correctly.");
+  editor.undo();
+  is(editor.getText(), "First", "undo works.");
+  editor.redo();
+  is(editor.getText(), "FirstSecond", "redo works.");
+  editor.resetUndo();
+  ok(!editor.canUndo(), "canUndo() is correct");
+  ok(!editor.canRedo(), "canRedo() is correct");
+  editor.undo();
+  is(editor.getText(), "FirstSecond", "reset undo works correctly");
+  editor.setText("Third", 11);
+  is(editor.getText(), "FirstSecondThird", "text set correctly");
+  editor.undo();
+  is(editor.getText(), "FirstSecond", "undo works after reset");
+  editor.redo();
+  is(editor.getText(), "FirstSecondThird", "redo works after reset");
+  editor.resetUndo();
+  ok(!editor.canUndo(), "canUndo() is correct (again)");
+  ok(!editor.canRedo(), "canRedo() is correct (again)");
+  editor.undo();
+  is(editor.getText(), "FirstSecondThird", "reset undo still works correctly");
+
+  finish();
+}
+
+registerCleanupFunction(function() {
+  editor.destroy();
+  testWin.close();
+  testWin = editor = null;
+});
--- a/browser/devtools/tilt/Tilt.jsm
+++ b/browser/devtools/tilt/Tilt.jsm
@@ -133,16 +133,17 @@ Tilt.prototype = {
     if (!this.visualizers[aId]) {
       return;
     }
 
     this.visualizers[aId].removeOverlay();
     this.visualizers[aId].cleanup();
     this.visualizers[aId] = null;
 
+    this.chromeWindow.gBrowser.selectedBrowser.contentWindow.focus();
     Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.DESTROYED, null);
   },
 
   /**
    * Handles any supplementary post-initialization work, done immediately
    * after a TILT_NOTIFICATIONS.INITIALIZED notification.
    */
   _whenInitialized: function T__whenInitialized()
--- a/browser/devtools/tilt/TiltVisualizer.jsm
+++ b/browser/devtools/tilt/TiltVisualizer.jsm
@@ -60,21 +60,21 @@ const INVISIBLE_ELEMENTS = {
 
 const STACK_THICKNESS = 15;
 const WIREFRAME_COLOR = [0, 0, 0, 0.25];
 const INITIAL_TRANSITION_DURATION = 100;
 const INITIAL_Z_TRANSLATION = 400;
 
 const MOUSE_CLICK_THRESHOLD = 10;
 const ARCBALL_SENSITIVITY = 0.3;
-const ARCBALL_ZOOM_STEP = 0.1;
 const ARCBALL_ROTATION_STEP = 0.15;
 const ARCBALL_TRANSLATION_STEP = 35;
-const ARCBALL_SCROLL_MIN = -3000;
-const ARCBALL_SCROLL_MAX = 500;
+const ARCBALL_ZOOM_STEP = 0.1;
+const ARCBALL_ZOOM_MIN = -3000;
+const ARCBALL_ZOOM_MAX = 500;
 
 const TILT_CRAFTER = "resource:///modules/devtools/TiltWorkerCrafter.js";
 const TILT_PICKER = "resource:///modules/devtools/TiltWorkerPicker.js";
 
 Cu.import("resource:///modules/devtools/TiltGL.jsm");
 Cu.import("resource:///modules/devtools/TiltMath.jsm");
 Cu.import("resource:///modules/devtools/TiltUtils.jsm");
 Cu.import("resource:///modules/devtools/TiltVisualizerStyle.jsm");
@@ -101,17 +101,17 @@ function TiltVisualizer(aProperties)
   /**
    * The canvas element used for rendering the visualization.
    */
   this.canvas = TiltUtils.DOM.initCanvas(aProperties.parentNode, {
     focusable: true,
     append: true
   });
 
-  /*
+  /**
    * Visualization logic and drawing loop.
    */
   this.presenter = new TiltVisualizer.Presenter(this.canvas,
     aProperties.contentWindow,
     aProperties.requestAnimationFrame,
     aProperties.inspectorUI,
     aProperties.onError || null,
     aProperties.onLoad || null);
@@ -180,16 +180,17 @@ TiltVisualizer.prototype = {
  */
 TiltVisualizer.Presenter = function TV_Presenter(
   aCanvas, aContentWindow, aRequestAnimationFrame, aInspectorUI,
   onError, onLoad)
 {
   this.canvas = aCanvas;
   this.contentWindow = aContentWindow;
   this.inspectorUI = aInspectorUI;
+  this.tiltUI = aInspectorUI.chromeWin.Tilt;
 
   /**
    * Create the renderer, containing useful functions for easy drawing.
    */
   this.renderer = new TiltGL.Renderer(aCanvas, onError, onLoad);
 
   /**
    * A custom shader used for drawing the visualization mesh.
@@ -967,17 +968,17 @@ TiltVisualizer.Controller.prototype = {
   /**
    * Called when the mouse wheel is used.
    */
   onMozScroll: function TVC_onMozScroll(e)
   {
     e.preventDefault();
     e.stopPropagation();
 
-    this.arcball.mouseScroll(e.detail);
+    this.arcball.zoom(e.detail);
   },
 
   /**
    * Called when a key is pressed.
    */
   onKeyDown: function TVC_onKeyDown(e)
   {
     let code = e.keyCode || e.which;
@@ -995,16 +996,20 @@ TiltVisualizer.Controller.prototype = {
   onKeyUp: function TVC_onKeyUp(e)
   {
     let code = e.keyCode || e.which;
 
     if (code >= e.DOM_VK_LEFT && code <= e.DOM_VK_DOWN) {
       e.preventDefault();
       e.stopPropagation();
     }
+    if (code === e.DOM_VK_ESCAPE) {
+      this.presenter.tiltUI.destroy(this.presenter.tiltUI.currentWindowId);
+      return;
+    }
     this.arcball.keyUp(code);
   },
 
   /**
    * Called when the content window of the current browser is resized.
    */
   onResize: function TVC_onResize(e)
   {
@@ -1070,22 +1075,17 @@ TiltVisualizer.Arcball = function TV_Arc
 {
   /**
    * Values retaining the current horizontal and vertical mouse coordinates.
    */
   this._mousePress = vec3.create();
   this._mouseRelease = vec3.create();
   this._mouseMove = vec3.create();
   this._mouseLerp = vec3.create();
-
-  /**
-   * Other mouse flags: current pressed mouse button and the scroll amount.
-   */
   this._mouseButton = -1;
-  this._scrollValue = 0;
 
   /**
    * Object retaining the current pressed key codes.
    */
   this._keyCode = {};
 
   /**
    * The vectors representing the mouse coordinates mapped on the arcball
@@ -1104,16 +1104,17 @@ TiltVisualizer.Arcball = function TV_Arc
   this._currentRot = quat4.create(aInitialRot);
 
   /**
    * The current camera translation coordinates.
    */
   this._lastTrans = vec3.create();
   this._deltaTrans = vec3.create();
   this._currentTrans = vec3.create(aInitialTrans);
+  this._zoomAmount = 0;
 
   /**
    * Additional rotation and translation vectors.
    */
   this._addKeyRot = vec3.create();
   this._addKeyTrans = vec3.create();
   this._deltaKeyRot = quat4.create();
   this._deltaKeyTrans = vec3.create();
@@ -1212,21 +1213,21 @@ TiltVisualizer.Arcball.prototype = {
       currentTrans[0] = lastTrans[0] + deltaTrans[0];
       currentTrans[1] = lastTrans[1] + deltaTrans[1];
     } else {
       // save the current panning to stack translations
       lastTrans[0] = currentTrans[0];
       lastTrans[1] = currentTrans[1];
     }
 
-    let scrollValue = this._scrollValue;
+    let zoomAmount = this._zoomAmount;
     let keyCode = this._keyCode;
 
     // mouse wheel handles zooming
-    deltaTrans[2] = (scrollValue - currentTrans[2]) * ARCBALL_ZOOM_STEP;
+    deltaTrans[2] = (zoomAmount - currentTrans[2]) * ARCBALL_ZOOM_STEP;
     currentTrans[2] += deltaTrans[2];
 
     let addKeyRot = this._addKeyRot;
     let addKeyTrans = this._addKeyTrans;
     let deltaKeyRot = this._deltaKeyRot;
     let deltaKeyTrans = this._deltaKeyTrans;
 
     // handle additional rotation and translation by the keyboard
@@ -1249,16 +1250,29 @@ TiltVisualizer.Arcball.prototype = {
       addKeyTrans[0] += ARCBALL_SENSITIVITY * ARCBALL_TRANSLATION_STEP;
     }
     if (keyCode[Ci.nsIDOMKeyEvent.DOM_VK_UP]) {
       addKeyTrans[1] -= ARCBALL_SENSITIVITY * ARCBALL_TRANSLATION_STEP;
     }
     if (keyCode[Ci.nsIDOMKeyEvent.DOM_VK_DOWN]) {
       addKeyTrans[1] += ARCBALL_SENSITIVITY * ARCBALL_TRANSLATION_STEP;
     }
+    if (keyCode[Ci.nsIDOMKeyEvent.DOM_VK_I] ||
+        keyCode[Ci.nsIDOMKeyEvent.DOM_VK_ADD] ||
+        keyCode[Ci.nsIDOMKeyEvent.DOM_VK_EQUALS]) {
+      this.zoom(-ARCBALL_TRANSLATION_STEP);
+    }
+    if (keyCode[Ci.nsIDOMKeyEvent.DOM_VK_O] ||
+        keyCode[Ci.nsIDOMKeyEvent.DOM_VK_SUBTRACT]) {
+      this.zoom(ARCBALL_TRANSLATION_STEP);
+    }
+    if (keyCode[Ci.nsIDOMKeyEvent.DOM_VK_R] ||
+        keyCode[Ci.nsIDOMKeyEvent.DOM_VK_0]) {
+      this._zoomAmount = 0;
+    }
 
     // update the delta key rotations and translations
     deltaKeyRot[0] +=
       (addKeyRot[0] - deltaKeyRot[0]) * ARCBALL_SENSITIVITY;
     deltaKeyRot[1] +=
       (addKeyRot[1] - deltaKeyRot[1]) * ARCBALL_SENSITIVITY;
 
     deltaKeyTrans[0] +=
@@ -1359,26 +1373,27 @@ TiltVisualizer.Arcball.prototype = {
    */
   mouseOut: function TVA_mouseOut()
   {
     // if the mouse leaves the parent bounds, stop the animation
     this._mouseButton = -1;
   },
 
   /**
-   * Function handling the mouseScroll event.
-   * Call this when the mouse wheel was scrolled.
+   * Function handling the arcball zoom amount.
+   * Call this, for example, when the mouse wheel was scrolled or zoom keys
+   * were pressed.
    *
-   * @param {Number} aScroll
-   *                 the mouse wheel direction and speed
+   * @param {Number} aZoom
+   *                 the zoom direction and speed
    */
-  mouseScroll: function TVA_mouseScroll(aScroll)
+  zoom: function TVA_zoom(aZoom)
   {
-    this._scrollValue = TiltMath.clamp(this._scrollValue - aScroll,
-      ARCBALL_SCROLL_MIN, ARCBALL_SCROLL_MAX);
+    this._zoomAmount = TiltMath.clamp(this._zoomAmount - aZoom,
+      ARCBALL_ZOOM_MIN, ARCBALL_ZOOM_MAX);
   },
 
   /**
    * Function handling the keyDown event.
    * Call this when a key was pressed.
    *
    * @param {Number} aCode
    *                 the code corresponding to the key pressed
--- a/browser/devtools/tilt/test/Makefile.in
+++ b/browser/devtools/tilt/test/Makefile.in
@@ -45,16 +45,17 @@ include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES = \
 	head.js \
 	browser_tilt_01_lazy_getter.js \
 	browser_tilt_02_notifications.js \
 	browser_tilt_03_tab_switch.js \
 	browser_tilt_04_initialization.js \
+	browser_tilt_05_destruction-esc.js \
 	browser_tilt_05_destruction.js \
 	browser_tilt_arcball.js \
 	browser_tilt_gl01.js \
 	browser_tilt_gl02.js \
 	browser_tilt_gl03.js \
 	browser_tilt_gl04.js \
 	browser_tilt_gl05.js \
 	browser_tilt_gl06.js \
--- a/browser/devtools/tilt/test/browser_tilt_04_initialization.js
+++ b/browser/devtools/tilt/test/browser_tilt_04_initialization.js
@@ -15,39 +15,48 @@ function test() {
     info("Skipping initialization test because WebGL isn't supported.");
     return;
   }
 
   waitForExplicitFinish();
 
   createTab(function() {
     let id = TiltUtils.getWindowId(gBrowser.selectedBrowser.contentWindow);
+    let initialActiveElement;
 
     is(id, Tilt.currentWindowId,
       "The unique window identifiers should match for the same window.");
 
     createTilt({
       onInspectorOpen: function() {
+        initialActiveElement = document.activeElement;
+
         is(Tilt.visualizers[id], null,
           "A instance of the visualizer shouldn't be initialized yet.");
 
         is(typeof TiltVisualizer.Prefs.enabled, "boolean",
           "The 'enabled' pref should have been loaded by now.");
         is(typeof TiltVisualizer.Prefs.forceEnabled, "boolean",
           "The 'force-enabled' pref should have been loaded by now.");
       },
-      onTiltOpen: function()
+      onTiltOpen: function(instance)
       {
+        is(document.activeElement, instance.presenter.canvas,
+          "The visualizer canvas should be focused on initialization.");
+
         ok(Tilt.visualizers[id] instanceof TiltVisualizer,
           "A new instance of the visualizer wasn't created properly.");
         ok(Tilt.visualizers[id].isInitialized(),
           "The new instance of the visualizer wasn't initialized properly.");
       },
       onTiltClose: function()
       {
+        is(document.activeElement, initialActiveElement,
+          "The focus wasn't correctly given back to the initial element.");
+
         is(Tilt.visualizers[id], null,
           "The current instance of the visualizer wasn't destroyed properly.");
       },
       onEnd: function()
       {
         gBrowser.removeCurrentTab();
         finish();
       }
new file mode 100644
--- /dev/null
+++ b/browser/devtools/tilt/test/browser_tilt_05_destruction-esc.js
@@ -0,0 +1,41 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/*global ok, is, info, waitForExplicitFinish, finish, gBrowser */
+/*global isTiltEnabled, isWebGLSupported, createTab, createTilt */
+/*global Services, EventUtils, Tilt, TiltUtils, InspectorUI, TILT_DESTROYED */
+"use strict";
+
+function test() {
+  if (!isTiltEnabled()) {
+    info("Skipping destruction test because Tilt isn't enabled.");
+    return;
+  }
+  if (!isWebGLSupported()) {
+    info("Skipping destruction test because WebGL isn't supported.");
+    return;
+  }
+
+  waitForExplicitFinish();
+
+  createTab(function() {
+    createTilt({
+      onTiltOpen: function()
+      {
+        Services.obs.addObserver(cleanup, TILT_DESTROYED, false);
+        EventUtils.sendKey("ESCAPE");
+      }
+    });
+  });
+}
+
+function cleanup() {
+  let id = TiltUtils.getWindowId(gBrowser.selectedBrowser.contentWindow);
+
+  is(Tilt.visualizers[id], null,
+    "The current instance of the visualizer wasn't destroyed properly.");
+
+  Services.obs.removeObserver(cleanup, TILT_DESTROYED);
+  gBrowser.removeCurrentTab();
+  finish();
+}
--- a/browser/devtools/tilt/test/browser_tilt_arcball.js
+++ b/browser/devtools/tilt/test/browser_tilt_arcball.js
@@ -1,12 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /*global ok, is, isApproxVec, vec3, quat4, TiltVisualizer */
+/*global Cc, Ci, Cu */
 "use strict";
 
 function cloneUpdate(update) {
   return {
     rotation: quat4.create(update.rotation),
     translation: vec3.create(update.translation)
   };
 }
@@ -194,23 +195,23 @@ function test() {
       -0.17157875001430511, 0.04261413961648941,
       -0.08445467799901962, -0.9806182980537415],
       translation: [0, 0, -6.125794887542725] },
     { rotation: [
       -0.17158031463623047, 0.04261442646384239,
       -0.08445550501346588, -0.980617880821228],
       translation: [0, 0, -6.5132155418396] }];
 
-  arcball3.mouseScroll(10);
+  arcball3.zoom(10);
   for (let i3 = 0; i3 < 10; i3++) {
     stack3.push(cloneUpdate(arcball3.update()));
   }
 
   ok(isExpectedUpdate(stack3, expect3),
-    "Mouse scroll events didn't create the expected transformation results.");
+    "Mouse zoom events didn't create the expected transformation results.");
 
   let stack4 = [];
   let expect4 = [
     { rotation: [
       -0.17158135771751404, 0.04261462762951851,
       -0.08445606380701065, -0.9806176424026489],
       translation: [0, 0, -6.861894130706787] },
     { rotation: [
@@ -245,24 +246,24 @@ function test() {
       -0.17158377170562744, 0.04261511191725731,
       -0.08445732295513153, -0.980617105960846],
       translation: [0, 0, -8.649148941040039] },
     { rotation: [
       -0.17158380150794983, 0.04261511191725731,
       -0.08445733785629272, -0.980617105960846],
       translation: [0, 0, -8.784234046936035] }];
 
-  arcball3.keyDown(65);
-  arcball3.keyDown(68);
-  arcball3.keyDown(87);
-  arcball3.keyDown(83);
-  arcball3.keyDown(37);
-  arcball3.keyDown(39);
-  arcball3.keyDown(38);
-  arcball3.keyDown(40);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_A);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_D);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_W);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_S);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_LEFT);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_RIGHT);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_UP);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_DOWN);
   for (let i4 = 0; i4 < 10; i4++) {
     stack4.push(cloneUpdate(arcball3.update()));
   }
 
   ok(isExpectedUpdate(stack4, expect4),
     "Key down events didn't create the expected transformation results.");
 
   let stack5 = [];
@@ -303,31 +304,196 @@ function test() {
       -0.17158392071723938, 0.0426151417195797,
       -0.0844573974609375, -0.980617105960846],
       translation: [0, 0, -9.528986930847168] },
     { rotation: [
       -0.17158392071723938, 0.0426151417195797,
       -0.0844573974609375, -0.980617105960846],
       translation: [0, 0, -9.576087951660156] }];
 
-  arcball3.keyUp(65);
-  arcball3.keyUp(68);
-  arcball3.keyUp(87);
-  arcball3.keyUp(83);
-  arcball3.keyUp(37);
-  arcball3.keyUp(39);
-  arcball3.keyUp(38);
-  arcball3.keyUp(40);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_A);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_D);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_W);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_S);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_LEFT);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_RIGHT);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_UP);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_DOWN);
   for (let i5 = 0; i5 < 10; i5++) {
     stack5.push(cloneUpdate(arcball3.update()));
   }
 
   ok(isExpectedUpdate(stack5, expect5),
     "Key up events didn't create the expected transformation results.");
 
+  let stack6 = [];
+  let expect6 = [
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, -9.618478775024414] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, -6.156630992889404] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 0.4590320587158203] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 9.913128852844238] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 21.921815872192383] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 36.22963333129883] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 52.60667037963867] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 70.84600067138672] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 90.76139831542969] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 112.18525695800781] }];
+
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_I);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_ADD);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_EQUALS);
+  for (let i6 = 0; i6 < 10; i6++) {
+    stack6.push(cloneUpdate(arcball3.update()));
+  }
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_I);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_ADD);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_EQUALS);
+
+  ok(isExpectedUpdate(stack6, expect6),
+    "Key zoom in events didn't create the expected transformation results.");
+
+  let stack7 = [];
+  let expect7 = [
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 134.96673583984375] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 151.97006225585938] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 163.77305603027344] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 170.895751953125] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 173.80618286132812] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 172.92556762695312] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 168.6330108642578] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 161.26971435546875] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 151.1427459716797] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 138.52847290039062] }];
+
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_O);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_SUBTRACT);
+  for (let i7 = 0; i7 < 10; i7++) {
+    stack7.push(cloneUpdate(arcball3.update()));
+  }
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_O);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_SUBTRACT);
+
+  ok(isExpectedUpdate(stack7, expect7),
+    "Key zoom out events didn't create the expected transformation results.");
+
+  let stack8 = [];
+  let expect8 = [
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 123.67562866210938] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 111.30806732177734] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 100.17726135253906] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 90.15953826904297] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 81.14358520507812] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 73.02922821044922] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 65.72630310058594] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 59.15367126464844] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 53.238304138183594] },
+    { rotation: [
+      -0.17158392071723938, 0.0426151417195797,
+      -0.0844573974609375, -0.980617105960846],
+      translation: [0, 0, 47.91447448730469] }];
+
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_R);
+  arcball3.keyDown(Ci.nsIDOMKeyEvent.DOM_VK_0);
+  for (let i8 = 0; i8 < 10; i8++) {
+    stack8.push(cloneUpdate(arcball3.update()));
+  }
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_R);
+  arcball3.keyUp(Ci.nsIDOMKeyEvent.DOM_VK_0);
+
+  ok(isExpectedUpdate(stack8, expect8),
+    "Key zoom reset events didn't create the expected transformation results.");
+
+
   arcball3.resize(123, 456);
   is(arcball3.width, 123,
     "The arcball width wasn't updated correctly.");
   is(arcball3.height, 456,
     "The arcball height wasn't updated correctly.");
   is(arcball3.radius, 123,
     "The arcball radius wasn't implicitly updated correctly.");
 }
--- a/browser/devtools/tilt/test/browser_tilt_visualizer.js
+++ b/browser/devtools/tilt/test/browser_tilt_visualizer.js
@@ -17,16 +17,17 @@ function test() {
 
   let webGLError = false;
   let webGLLoad = false;
 
   let visualizer = new TiltVisualizer({
     parentNode: gBrowser.selectedBrowser.parentNode,
     contentWindow: gBrowser.selectedBrowser.contentWindow,
     requestAnimationFrame: window.mozRequestAnimationFrame,
+    inspectorUI: window.InspectorUI,
 
     onError: function onWebGLError()
     {
       webGLError = true;
     },
 
     onLoad: function onWebGLLoad()
     {
--- a/browser/devtools/tilt/test/head.js
+++ b/browser/devtools/tilt/test/head.js
@@ -45,19 +45,17 @@ const TILT_ENABLED = Services.prefs.getB
 const INSP_ENABLED = Services.prefs.getBoolPref("devtools.inspector.enabled");
 
 
 function isTiltEnabled() {
   return TILT_ENABLED && INSP_ENABLED;
 }
 
 function isWebGLSupported() {
-  return TiltGL.isWebGLSupported() &&
-         TiltGL.create3DContext(
-           document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"));
+  return TiltGL.isWebGLSupported() && TiltGL.create3DContext(createCanvas());
 }
 
 function isApprox(num1, num2) {
   return Math.abs(num1 - num2) < EPSILON;
 }
 
 function isApproxVec(vec1, vec2) {
   if (vec1.length !== vec2.length) {
@@ -68,19 +66,17 @@ function isApproxVec(vec1, vec2) {
       return false;
     }
   }
   return true;
 }
 
 
 function createCanvas() {
-  return gBrowser.parentNode
-                 .ownerDocument
-                 .createElementNS("http://www.w3.org/1999/xhtml", "canvas");
+  return document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
 }
 
 
 function createTab(callback, location) {
   let tab = gBrowser.selectedTab = gBrowser.addTab();
 
   gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
     gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
@@ -108,17 +104,17 @@ function createTilt(callbacks, close) {
     });
   }
 
   function onTiltOpen() {
     Services.obs.removeObserver(onTiltOpen, TILT_INITIALIZED);
 
     executeSoon(function() {
       if ("function" === typeof callbacks.onTiltOpen) {
-        callbacks.onTiltOpen();
+        callbacks.onTiltOpen(Tilt.visualizers[Tilt.currentWindowId]);
       }
       if (close) {
         Services.obs.addObserver(onTiltClose, TILT_DESTROYED, false);
         Tilt.destroy(Tilt.currentWindowId);
       }
     });
   }
 
--- a/browser/devtools/webconsole/HUDService.jsm
+++ b/browser/devtools/webconsole/HUDService.jsm
@@ -5258,16 +5258,20 @@ JSTerm.prototype = {
 
       case Ci.nsIDOMKeyEvent.DOM_VK_TAB:
         // Generate a completion and accept the first proposed value.
         if (this.complete(this.COMPLETE_HINT_ONLY) &&
             this.lastCompletion &&
             this.acceptProposedCompletion()) {
           aEvent.preventDefault();
         }
+        else {
+          this.updateCompleteNode(HUDService.getStr("Autocomplete.blank"));
+          aEvent.preventDefault();
+        }
         break;
 
       default:
         break;
     }
   },
 
   /**
--- a/browser/devtools/webconsole/test/Makefile.in
+++ b/browser/devtools/webconsole/test/Makefile.in
@@ -83,17 +83,17 @@ include $(topsrcdir)/config/rules.mk
 	browser_webconsole_property_provider.js \
 	browser_webconsole_registries.js \
 	browser_webconsole_bug_587617_output_copy.js \
 	browser_webconsole_bug_585237_line_limit.js \
 	browser_webconsole_bug_581231_close_button.js \
 	browser_webconsole_bug_582201_duplicate_errors.js \
 	browser_webconsole_bug_580454_timestamp_l10n.js \
 	browser_webconsole_netlogging.js \
-	browser_webconsole_bug_583816_tab_focus.js \
+	browser_webconsole_bug_583816_No_input_and_Tab_key_pressed.js \
 	browser_webconsole_bug_594477_clickable_output.js \
 	browser_webconsole_bug_589162_css_filter.js \
 	browser_webconsole_bug_597103_deactivateHUDForContext_unfocused_window.js \
 	browser_webconsole_bug_595350_multiple_windows_and_tabs.js \
 	browser_webconsole_bug_594497_history_arrow_keys.js \
 	browser_webconsole_bug_588342_document_focus.js \
 	browser_webconsole_bug_595934_message_categories.js \
 	browser_webconsole_bug_601352_scroll.js \
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_bug_583816_No_input_and_Tab_key_pressed.js
@@ -0,0 +1,70 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Web Console test suite.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mihai Sucan <mihai.sucan@gmail.com>
+ *   Jignesh Kakadiya <jigneshhk1992@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * 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";
+
+function test() {
+  addTab(TEST_URI);
+  browser.addEventListener("DOMContentLoaded", testCompletion, false);
+}
+
+function testCompletion() {
+  browser.removeEventListener("DOMContentLoaded", testCompletion, false);
+
+  openConsole();
+
+  var jsterm = HUDService.getHudByWindow(content).jsterm;
+  var input = jsterm.inputNode;
+
+  jsterm.setInputValue("");
+  EventUtils.synthesizeKey("VK_TAB", {});
+  is(jsterm.completeNode.value, "<- no result", "<- no result - matched");
+  is(input.value, "", "inputnode is empty - matched")
+  is(input.getAttribute("focused"), "true", "input is still focused");
+
+  //Any thing which is not in property autocompleter
+  jsterm.setInputValue("window.Bug583816");
+  EventUtils.synthesizeKey("VK_TAB", {});
+  is(jsterm.completeNode.value, "                <- no result", "completenode content - matched");
+  is(input.value, "window.Bug583816", "inputnode content - matched");
+  is(input.getAttribute("focused"), "true", "input is still focused");
+
+  jsterm = input = null;
+  finishTest();
+}
deleted file mode 100644
--- a/browser/devtools/webconsole/test/browser_webconsole_bug_583816_tab_focus.js
+++ /dev/null
@@ -1,61 +0,0 @@
-/* vim:set ts=2 sw=2 sts=2 et: */
-/* ***** BEGIN LICENSE BLOCK *****
- * Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- *
- * Contributor(s):
- *  Mihai Șucan <mihai.sucan@gmail.com>
- *
- * ***** END LICENSE BLOCK ***** */
-
-const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test//test-console.html";
-
-let HUD, inputNode;
-
-function tabLoad(aEvent) {
-  browser.removeEventListener(aEvent.type, arguments.callee, true);
-
-  waitForFocus(function() {
-    openConsole();
-
-    HUD = HUDService.getHudByWindow(content);
-
-    inputNode = HUD.jsterm.inputNode;
-
-    inputNode.focus();
-    executeSoon(function() {
-      is(inputNode.getAttribute("focused"), "true", "inputNode is focused");
-      HUD.jsterm.setInputValue("doc");
-      inputNode.addEventListener("keyup", firstTab, false);
-      EventUtils.synthesizeKey("VK_TAB", {});
-    });
-  }, content);
-}
-
-function firstTab(aEvent) {
-  this.removeEventListener(aEvent.type, arguments.callee, false);
-
-  is(inputNode.getAttribute("focused"), "true", "inputNode is still focused");
-  isnot(this.value, "doc", "input autocompleted");
-
-  HUD.jsterm.setInputValue("foobarbaz" + Date.now());
-
-  EventUtils.synthesizeKey("VK_TAB", {});
-
-  executeSoon(secondTab);
-}
-
-function secondTab() {
-  isnot(inputNode.getAttribute("focused"), "true",
-          "inputNode is no longer focused");
-
-  HUD = inputNode = null;
-  HUDService.deactivateHUDForContext(gBrowser.selectedTab);
-  executeSoon(finish);
-}
-
-function test() {
-  addTab(TEST_URI);
-  browser.addEventListener("load", tabLoad, true);
-}
-
--- a/browser/locales/en-US/chrome/browser/devtools/webconsole.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/webconsole.properties
@@ -166,9 +166,14 @@ stacktrace.outputMessage=Stack trace fro
 # %S=name of timer
 timerStarted=%S: timer started
 
 # LOCALIZATION NOTE (timeEnd):
 # This string is used to display the result of the console.timeEnd() call.
 # %1$S=name of timer, %2$S=number of milliseconds
 timeEnd=%1$S: %2$Sms
 
+# LOCALIZATION NOTE (Autocomplete.blank):
+# This string is used when inputnode string containing anchor doesn't
+# doesn't matches to any property in the content.
+Autocomplete.blank=  <- no result
+
 maxTimersExceeded=The maximum allowed number of timers in this page was exceeded.