Created
November 28, 2012 20:52
-
-
Save mihaisucan/4164400 to your computer and use it in GitHub Desktop.
bug-792062
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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