Skip to content

Instantly share code, notes, and snippets.

@mihaisucan
Created November 28, 2012 20:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mihaisucan/4164400 to your computer and use it in GitHub Desktop.
Save mihaisucan/4164400 to your computer and use it in GitHub Desktop.
bug-792062
diff --git a/browser/devtools/webconsole/webconsole.js b/browser/devtools/webconsole/webconsole.js
index 973c06a..a3eeacb 100644
--- a/browser/devtools/webconsole/webconsole.js
+++ b/browser/devtools/webconsole/webconsole.js
@@ -3983,7 +3983,7 @@ function WebConsoleConnectionProxy(aWebConsole, aTarget)
this._onNetworkEvent = this._onNetworkEvent.bind(this);
this._onNetworkEventUpdate = this._onNetworkEventUpdate.bind(this);
this._onFileActivity = this._onFileActivity.bind(this);
- this._onLocationChange = this._onLocationChange.bind(this);
+ this._onTabNavigated = this._onTabNavigated.bind(this);
}
WebConsoleConnectionProxy.prototype = {
@@ -3996,6 +3996,12 @@ WebConsoleConnectionProxy.prototype = {
owner: null,
/**
+ * The target that the console connects to.
+ * @type RemoteTarget
+ */
+ target: null,
+
+ /**
* The DebuggerClient object.
*
* @see DebuggerClient
@@ -4012,6 +4018,12 @@ WebConsoleConnectionProxy.prototype = {
webConsoleClient: null,
/**
+ * The TabClient instance we use.
+ * @type object
+ */
+ tabClient: null,
+
+ /**
* Tells if the connection is established.
* @type boolean
*/
@@ -4026,6 +4038,14 @@ WebConsoleConnectionProxy.prototype = {
_consoleActor: null,
/**
+ * The TabActor ID.
+ *
+ * @private
+ * @type string
+ */
+ _tabActor: null,
+
+ /**
* Tells if the window.console object of the remote web page is the native
* object or not.
* @private
@@ -4069,7 +4089,7 @@ WebConsoleConnectionProxy.prototype = {
client.addListener("networkEvent", this._onNetworkEvent);
client.addListener("networkEventUpdate", this._onNetworkEventUpdate);
client.addListener("fileActivity", this._onFileActivity);
- client.addListener("locationChange", this._onLocationChange);
+ client.addListener("tabNavigated", this._onTabNavigated);
if (this.target.isRemote) {
this._consoleActor = this.target.form.consoleActor;
@@ -4078,7 +4098,7 @@ WebConsoleConnectionProxy.prototype = {
}
let listeners = ["PageError", "ConsoleAPI", "NetworkActivity",
- "FileActivity", "LocationChange"];
+ "FileActivity"];
this.client.attachConsole(this._consoleActor, listeners,
this._onAttachConsole.bind(this, aCallback));
return;
@@ -4102,16 +4122,43 @@ WebConsoleConnectionProxy.prototype = {
let selectedTab = aResponse.tabs[aResponse.selected];
if (selectedTab) {
this._consoleActor = selectedTab.consoleActor;
+ this._tabActor = selectedTab.actor;
this.owner.onLocationChange(selectedTab.url, selectedTab.title);
}
else {
this._consoleActor = aResponse.consoleActor;
+ this._tabActor = aResponse.actor;
}
this.owner._resetConnectionTimeout();
+ this.client.attachTab(this._tabActor,
+ this._onAttachTab.bind(this, aCallback));
+ },
+
+ /**
+ * The "attachTab" response handler.
+ *
+ * @private
+ * @param function [aCallback]
+ * Optional function to invoke once the connection is established.
+ * @param object aResponse
+ * The JSON response object received from the server.
+ * @param object aTabClient
+ * The TabClient instance for the attached tab.
+ */
+ _onAttachTab: function WCCP__onAttachTab(aCallback, aResponse, aTabClient)
+ {
+ if (aResponse.error) {
+ Cu.reportError("attachTab failed: " + aResponse.error + " " +
+ aResponse.message);
+ return;
+ }
+
+ this.tabClient = aTabClient;
+
let listeners = ["PageError", "ConsoleAPI", "NetworkActivity",
- "FileActivity", "LocationChange"];
+ "FileActivity"];
this.client.attachConsole(this._consoleActor, listeners,
this._onAttachConsole.bind(this, aCallback));
},
@@ -4260,7 +4307,7 @@ WebConsoleConnectionProxy.prototype = {
},
/**
- * The "locationChange" message type handler. We redirect any message to
+ * The "tabNavigated" message type handler. We redirect any message to
* the UI for displaying.
*
* @private
@@ -4269,13 +4316,15 @@ WebConsoleConnectionProxy.prototype = {
* @param object aPacket
* The message received from the server.
*/
- _onLocationChange: function WCCP__onLocationChange(aType, aPacket)
+ _onTabNavigated: function WCCP__onTabNavigated(aType, aPacket)
{
- if (!this.owner || aPacket.from != this._consoleActor) {
+ if (!this.owner || aPacket.from != this._tabActor) {
return;
}
- this.owner.onLocationChange(aPacket.uri, aPacket.title);
+ //dump("WCCP__onTabNavigated state " + aPacket.state + " url " + aPacket.url + " title " + aPacket.title + " nativeConsoleAPI " + aPacket.nativeConsoleAPI + "\n");
+
+ this.owner.onLocationChange(aPacket.url, aPacket.title);
if (aPacket.state == "stop" && !aPacket.nativeConsoleAPI) {
this.owner.logWarningAboutReplacedAPI();
}
@@ -4329,7 +4378,7 @@ WebConsoleConnectionProxy.prototype = {
this.client.removeListener("networkEvent", this._onNetworkEvent);
this.client.removeListener("networkEventUpdate", this._onNetworkEventUpdate);
this.client.removeListener("fileActivity", this._onFileActivity);
- this.client.removeListener("locationChange", this._onLocationChange);
+ this.client.removeListener("tabNavigated", this._onTabNavigated);
try {
if (!this.target.isRemote) {
@@ -4344,6 +4393,8 @@ WebConsoleConnectionProxy.prototype = {
this.client = null;
this.webConsoleClient = null;
+ this.tabClient = null;
+ this.target = null;
this.connected = false;
this.owner = null;
},
diff --git a/toolkit/devtools/debugger/dbg-client.jsm b/toolkit/devtools/debugger/dbg-client.jsm
index a2b8e30..44d3d78 100644
--- a/toolkit/devtools/debugger/dbg-client.jsm
+++ b/toolkit/devtools/debugger/dbg-client.jsm
@@ -480,9 +480,10 @@ DebuggerClient.prototype = {
this._threadClients[aPacket.from]._onThreadState(aPacket);
}
// On navigation the server resumes, so the client must resume as well.
- // We achive that by generating a fake resumption packet that triggers
+ // We achieve that by generating a fake resumption packet that triggers
// the client's thread state change listeners.
- if (aPacket.type == UnsolicitedNotifications.tabNavigated &&
+ if (this.activeThread &&
+ aPacket.type == UnsolicitedNotifications.tabNavigated &&
aPacket.from in this._tabClients) {
let resumption = { from: this.activeThread._actor, type: "resumed" };
this.activeThread._onThreadState(resumption);
diff --git a/toolkit/devtools/debugger/server/dbg-browser-actors.js b/toolkit/devtools/debugger/server/dbg-browser-actors.js
index 811eff7..160f31a 100644
--- a/toolkit/devtools/debugger/server/dbg-browser-actors.js
+++ b/toolkit/devtools/debugger/server/dbg-browser-actors.js
@@ -338,12 +338,12 @@ BrowserTabActor.prototype = {
// A constant prefix that will be used to form the actor ID by the server.
actorPrefix: "tab",
- grip: function BTA_grip() {
- dbg_assert(!this.exited,
- "grip() shouldn't be called on exited browser actor.");
- dbg_assert(this.actorID,
- "tab should have an actorID.");
-
+ /**
+ * Getter for the tab title.
+ * @return string
+ * Tab title.
+ */
+ get tabTitle() {
let title = this.browser.contentTitle;
// If contentTitle is empty (e.g. on a not-yet-restored tab), but there is a
// tabbrowser (i.e. desktop Firefox, but not Fennec), we can use the label
@@ -352,9 +352,18 @@ BrowserTabActor.prototype = {
title = this._tabbrowser
._getTabForContentWindow(this.browser.contentWindow).label;
}
+ return title;
+ },
+
+ grip: function BTA_grip() {
+ dbg_assert(!this.exited,
+ "grip() shouldn't be called on exited browser actor.");
+ dbg_assert(this.actorID,
+ "tab should have an actorID.");
+
let response = {
actor: this.actorID,
- title: title,
+ title: this.tabTitle,
url: this.browser.currentURI.spec
};
@@ -375,10 +384,6 @@ BrowserTabActor.prototype = {
*/
disconnect: function BTA_disconnect() {
this._detach();
-
- if (this._progressListener) {
- this._progressListener.destroy();
- }
this._extraActors = null;
},
@@ -396,9 +401,6 @@ BrowserTabActor.prototype = {
type: "tabDetached" });
}
- if (this._progressListener) {
- this._progressListener.destroy();
- }
this._browser = null;
this._tabbrowser = null;
},
@@ -464,6 +466,10 @@ BrowserTabActor.prototype = {
return;
}
+ if (this._progressListener) {
+ this._progressListener.destroy();
+ }
+
this.browser.removeEventListener("DOMWindowCreated", this._onWindowCreated, true);
this.browser.removeEventListener("pageshow", this._onWindowCreated, true);
@@ -499,10 +505,6 @@ BrowserTabActor.prototype = {
this._detach();
- if (this._progressListener) {
- this._progressListener.destroy();
- }
-
return { type: "detached" };
},
@@ -556,11 +558,6 @@ BrowserTabActor.prototype = {
if (this.threadActor.dbg) {
this.threadActor.dbg.enabled = true;
}
- if (this._progressListener) {
- delete this._progressListener._needsTabNavigated;
- }
- this.conn.send({ from: this.actorID, type: "tabNavigated",
- url: this.browser.contentDocument.URL });
}
}
@@ -570,7 +567,26 @@ BrowserTabActor.prototype = {
this.threadActor.findGlobals();
}
}
- }
+ },
+
+ /**
+ * Tells if the window.console object is native or overwritten by script in
+ * the page.
+ *
+ * @param nsIDOMWindow aWindow
+ * The window object you want to check.
+ * @return boolean
+ * True if the window.console object is native, or false otherwise.
+ */
+ hasNativeConsoleAPI: function BTA_hasNativeConsoleAPI(aWindow) {
+ let isNative = false;
+ try {
+ let console = aWindow.wrappedJSObject.console;
+ isNative = "__mozillaConsole__" in console;
+ }
+ catch (ex) { }
+ return isNative;
+ },
};
/**
@@ -606,33 +622,45 @@ DebuggerProgressListener.prototype = {
let isWindow = aFlag & Ci.nsIWebProgressListener.STATE_IS_WINDOW;
// Skip non-interesting states.
- if (isStart && isDocument && isRequest && isNetwork) {
+ if (!isWindow || !isNetwork ||
+ aProgress.DOMWindow != this._tabActor.browser.contentWindow) {
+ return;
+ }
+
+ if (isStart && aRequest instanceof Ci.nsIChannel) {
// If the request is about to happen in a new window, we are not concerned
// about the request.
- if (aProgress.DOMWindow != this._tabActor.browser.contentWindow) {
- return;
- }
- // If the debuggee is not paused, then proceed normally.
- if (this._tabActor.threadActor.state != "paused") {
- return;
+ // Proceed normally only if the debuggee is not paused.
+ if (this._tabActor.threadActor.state == "paused") {
+ aRequest.suspend();
+ this._tabActor.threadActor.onResume();
+ this._tabActor.threadActor.dbg.enabled = false;
+ this._tabActor._pendingNavigation = aRequest;
}
- aRequest.suspend();
- this._tabActor.threadActor.onResume();
- this._tabActor.threadActor.dbg.enabled = false;
- this._tabActor._pendingNavigation = aRequest;
- this._needsTabNavigated = true;
- } else if (isStop && isWindow && isNetwork && this._needsTabNavigated) {
- delete this._needsTabNavigated;
- this._tabActor.threadActor.dbg.enabled = true;
this._tabActor.conn.send({
from: this._tabActor.actorID,
type: "tabNavigated",
- url: this._tabActor.browser.contentDocument.URL
+ url: aRequest.URI.spec,
+ title: "",
+ nativeConsoleAPI: true,
+ state: "start",
});
+ } else if (isStop) {
+ if (this._tabActor.threadActor.state == "running") {
+ this._tabActor.threadActor.dbg.enabled = true;
+ }
- this.destroy();
+ let window = this._tabActor.browser.contentWindow;
+ this._tabActor.conn.send({
+ from: this._tabActor.actorID,
+ type: "tabNavigated",
+ url: this._tabActor.browser.contentDocument.URL,
+ title: this._tabActor.tabTitle,
+ nativeConsoleAPI: this._tabActor.hasNativeConsoleAPI(window),
+ state: "stop",
+ });
}
},
@@ -641,7 +669,11 @@ DebuggerProgressListener.prototype = {
*/
destroy: function DPL_destroy() {
if (this._tabActor._tabbrowser.removeProgressListener) {
- this._tabActor._tabbrowser.removeProgressListener(this);
+ try {
+ this._tabActor._tabbrowser.removeProgressListener(this);
+ } catch (ex) {
+ // This can throw during browser shutdown.
+ }
}
this._tabActor._progressListener = null;
this._tabActor = null;
diff --git a/toolkit/devtools/debugger/server/dbg-server.js b/toolkit/devtools/debugger/server/dbg-server.js
index 13984a5..d5a5e0a 100644
--- a/toolkit/devtools/debugger/server/dbg-server.js
+++ b/toolkit/devtools/debugger/server/dbg-server.js
@@ -543,7 +543,8 @@ DebuggerServerConnection.prototype = {
removeActorPool: function DSC_removeActorPool(aActorPool) {
let index = this._extraPools.lastIndexOf(aActorPool);
if (index > -1) {
- this._extraPools.splice(index, 1);
+ let pool = this._extraPools.splice(index, 1);
+ pool.map(function(p) { p.cleanup(); });
}
},
diff --git a/toolkit/devtools/webconsole/dbg-webconsole-actors.js b/toolkit/devtools/webconsole/dbg-webconsole-actors.js
index e37e692..1fa5863 100644
--- a/toolkit/devtools/webconsole/dbg-webconsole-actors.js
+++ b/toolkit/devtools/webconsole/dbg-webconsole-actors.js
@@ -155,30 +155,14 @@ WebConsoleActor.prototype =
actorPrefix: "console",
+ hasNativeConsoleAPI: BrowserTabActor.prototype.hasNativeConsoleAPI,
+
grip: function WCA_grip()
{
return { actor: this.actorID };
},
/**
- * Tells if the window.console object is native or overwritten by script in
- * the page.
- *
- * @return boolean
- * True if the window.console object is native, or false otherwise.
- */
- hasNativeConsoleAPI: function WCA_hasNativeConsoleAPI()
- {
- let isNative = false;
- try {
- let consoleObject = WebConsoleUtils.unwrap(this.window).console;
- isNative = "__mozillaConsole__" in consoleObject;
- }
- catch (ex) { }
- return isNative;
- },
-
- /**
* Destroy the current WebConsoleActor instance.
*/
disconnect: function WCA_disconnect()
@@ -336,20 +320,11 @@ WebConsoleActor.prototype =
MONITOR_FILE_ACTIVITY);
startedListeners.push(listener);
break;
- case "LocationChange":
- if (!this.consoleProgressListener) {
- this.consoleProgressListener =
- new ConsoleProgressListener(this.window, this);
- }
- this.consoleProgressListener.startMonitor(this.consoleProgressListener.
- MONITOR_LOCATION_CHANGE);
- startedListeners.push(listener);
- break;
}
}
return {
startedListeners: startedListeners,
- nativeConsoleAPI: this.hasNativeConsoleAPI(),
+ nativeConsoleAPI: this.hasNativeConsoleAPI(this.window),
};
},
@@ -370,7 +345,7 @@ WebConsoleActor.prototype =
// listeners.
let toDetach = aRequest.listeners ||
["PageError", "ConsoleAPI", "NetworkActivity",
- "FileActivity", "LocationChange"];
+ "FileActivity"];
while (toDetach.length > 0) {
let listener = toDetach.shift();
@@ -403,13 +378,6 @@ WebConsoleActor.prototype =
}
stoppedListeners.push(listener);
break;
- case "LocationChange":
- if (this.consoleProgressListener) {
- this.consoleProgressListener.stopMonitor(this.consoleProgressListener.
- MONITOR_LOCATION_CHANGE);
- }
- stoppedListeners.push(listener);
- break;
}
}
@@ -737,34 +705,6 @@ WebConsoleActor.prototype =
this.conn.send(packet);
},
- /**
- * Handler for location changes. This method sends the new browser location
- * to the remote Web Console client.
- *
- * @see ConsoleProgressListener
- * @param string aState
- * Tells the location change state:
- * - "start" means a load has begun.
- * - "stop" means load completed.
- * @param string aURI
- * The new browser URI.
- * @param string aTitle
- * The new page title URI.
- */
- onLocationChange: function WCA_onLocationChange(aState, aURI, aTitle)
- {
- // TODO: Bug 792062 - Make the tabNavigated notification reusable by the Web Console
- let packet = {
- from: this.actorID,
- type: "locationChange",
- uri: aURI,
- title: aTitle,
- state: aState,
- nativeConsoleAPI: this.hasNativeConsoleAPI(),
- };
- this.conn.send(packet);
- },
-
//////////////////
// End of event handlers for various listeners.
//////////////////
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment