Merge m-c to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2013-08-05 12:03:22 +02:00
commit d17ceba6e3
417 changed files with 10670 additions and 5938 deletions

View File

@ -195,7 +195,6 @@
@BINPATH@/components/dom_indexeddb.xpt
@BINPATH@/components/dom_offline.xpt
@BINPATH@/components/dom_payment.xpt
@BINPATH@/components/dom_push.xpt
@BINPATH@/components/dom_json.xpt
@BINPATH@/components/dom_browserelement.xpt
@BINPATH@/components/dom_messages.xpt

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1374187152000">
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1375219877000">
<emItems>
<emItem blockID="i350" id="sqlmoz@facebook.com">
<versionRange minVersion="0" maxVersion="*" severity="3">
@ -135,6 +135,10 @@
<versionRange minVersion="0" maxVersion="*" severity="1">
</versionRange>
</emItem>
<emItem blockID="i429" id="{B40794A0-7477-4335-95C5-8CB9BBC5C4A5}">
<versionRange minVersion="0" maxVersion="*" severity="3">
</versionRange>
</emItem>
<emItem blockID="i11" id="yslow@yahoo-inc.com">
<versionRange minVersion="2.0.5" maxVersion="2.0.5">
<targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">

View File

@ -335,6 +335,9 @@ pref("browser.download.manager.quitBehavior", 0);
pref("browser.download.manager.scanWhenDone", true);
pref("browser.download.manager.resumeOnWakeDelay", 10000);
// Enables the asynchronous Downloads API in the Downloads Panel.
pref("browser.download.useJSTransfer", false);
// This allows disabling the Downloads Panel in favor of the old interface.
pref("browser.download.useToolkitUI", false);

View File

@ -96,7 +96,7 @@
<command id="Tools:DevToolbar" oncommand="DeveloperToolbar.toggle();" disabled="true" hidden="true"/>
<command id="Tools:DevToolbarFocus" oncommand="DeveloperToolbar.focusToggle();" disabled="true"/>
<command id="Tools:ChromeDebugger" oncommand="BrowserDebuggerProcess.init();" disabled="true" hidden="true"/>
<command id="Tools:BrowserConsole" oncommand="HUDConsoleUI.toggleBrowserConsole();"/>
<command id="Tools:BrowserConsole" oncommand="HUDService.toggleBrowserConsole();"/>
<command id="Tools:Scratchpad" oncommand="Scratchpad.openScratchpad();" disabled="true" hidden="true"/>
<command id="Tools:ResponsiveUI" oncommand="ResponsiveUI.toggle();" disabled="true" hidden="true"/>
<command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
@ -176,7 +176,8 @@
<broadcaster id="devtoolsMenuBroadcaster_DevToolbox"
label="&devToolboxMenuItem.label;"
type="checkbox" autocheck="false"
command="Tools:DevToolbox"/>
command="Tools:DevToolbox"
key="key_devToolboxMenuItem"/>
<broadcaster id="devtoolsMenuBroadcaster_DevToolbar"
label="&devToolbarMenu.label;"
type="checkbox" autocheck="false"
@ -261,6 +262,7 @@
<key id="key_openDownloads" key="&downloads.commandkey;" command="Tools:Downloads" modifiers="accel"/>
#endif
<key id="key_openAddons" key="&addons.commandkey;" command="Tools:Addons" modifiers="accel,shift"/>
<key id="key_devToolboxMenuItemF12" keycode="&devToolsCmd.keycode;" keytext="&devToolsCmd.keytext;" command="Tools:DevToolbox"/>
<key id="key_browserConsole" key="&browserConsoleCmd.commandkey;" command="Tools:BrowserConsole" modifiers="accel,shift"/>
<key id="key_devToolbar" keycode="&devToolbar.keycode;" modifiers="shift"
keytext="&devToolbar.keytext;" command="Tools:DevToolbarFocus"/>
@ -271,6 +273,16 @@
modifiers="accel,shift"
#endif
/>
<key id="key_devToolboxMenuItem" keycode="&devToolboxMenuItem.keycode;"
keytext="&devToolboxMenuItem.keytext;" command="Tools:DevToolbox" key="&devToolboxMenuItem.keytext;"
#ifdef XP_MACOSX
modifiers="accel,alt"
#else
modifiers="accel,shift"
#endif
/>
<key id="key_scratchpad" keycode="&scratchpad.keycode;" modifiers="shift"
keytext="&scratchpad.keytext;" command="Tools:Scratchpad"/>
<key id="openFileKb" key="&openFileCmd.commandkey;" command="Browser:OpenFile" modifiers="accel"/>

View File

@ -1106,7 +1106,15 @@ var gBrowserInit = {
// If the user manually opens the download manager before the timeout, the
// downloads will start right away, and getting the service again won't hurt.
setTimeout(function() {
Services.downloads;
let DownloadsCommon =
Cu.import("resource:///modules/DownloadsCommon.jsm", {}).DownloadsCommon;
if (DownloadsCommon.useJSTransfer) {
// Open the data link without initalizing nsIDownloadManager.
DownloadsCommon.initializeAllDataLinks();
} else {
// Initalizing nsIDownloadManager will trigger the data link.
Services.downloads;
}
let DownloadTaskbarProgress =
Cu.import("resource://gre/modules/DownloadTaskbarProgress.jsm", {}).DownloadTaskbarProgress;
DownloadTaskbarProgress.onBrowserWindowLoad(window);
@ -7153,8 +7161,13 @@ XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
XPCOMUtils.defineLazyModuleGetter(this, "gDevToolsBrowser",
"resource:///modules/devtools/gDevTools.jsm");
XPCOMUtils.defineLazyGetter(this, "HUDConsoleUI", function () {
return Cu.import("resource:///modules/HUDService.jsm", {}).HUDService.consoleUI;
Object.defineProperty(this, "HUDService", {
get: function HUDService_getter() {
let devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
return devtools.require("devtools/webconsole/hudservice");
},
configurable: true,
enumerable: true
});
// Prompt user to restart the browser in safe mode

View File

@ -1052,16 +1052,24 @@
<hbox style="width: 100%;" pack="center"> <!-- Inner hbox needed due to bug 579776. -->
<vbox id="full-screen-warning-message" align="center">
<description id="full-screen-domain-text"/>
<description class="full-screen-description" value="&fullscreenExitHint.value;"/>
<description class="full-screen-description" value="&fullscreenExitHint2.value;"/>
<vbox id="full-screen-approval-pane" align="center">
<description class="full-screen-description" value="&fullscreenApproval.value;"/>
<hbox>
#ifdef XP_UNIX
<button label="&fullscreenExitButton.label;"
oncommand="FullScreen.setFullscreenAllowed(false);"
class="full-screen-approval-button"/>
<button label="&fullscreenAllowButton.label;"
oncommand="FullScreen.setFullscreenAllowed(true);"
class="full-screen-approval-button"/>
#else
<button label="&fullscreenAllowButton.label;"
oncommand="FullScreen.setFullscreenAllowed(true);"
class="full-screen-approval-button"/>
<button label="&fullscreenExitButton.label;"
oncommand="FullScreen.setFullscreenAllowed(false);"
class="full-screen-approval-button"/>
#endif
</hbox>
<checkbox id="full-screen-remember-decision"/>
</vbox>

View File

@ -9,6 +9,11 @@
%tabBrowserDTD;
]>
# MAKE_E10S_WORK surrounds code needed to have the front-end try to be smart
# about using non-remote browsers for loading certain URIs when remote tabs
# (browser.tabs.remote) are enabled.
#define MAKE_E10S_WORK 1
<bindings id="tabBrowserBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
@ -1300,6 +1305,73 @@
]]></body>
</method>
#ifdef MAKE_E10S_WORK
<method name="_updateBrowserRemoteness">
<parameter name="aBrowser"/>
<parameter name="aRemote"/>
<body>
<![CDATA[
let isRemote = aBrowser.getAttribute("remote") == "true";
if (isRemote == aRemote)
return;
// Unhook our progress listener.
let tab = this._getTabForBrowser(aBrowser);
let index = tab._tPos;
let filter = this.mTabFilters[index];
aBrowser.webProgress.removeProgressListener(filter);
// Change the "remote" attribute.
let parent = aBrowser.parentNode;
parent.removeChild(aBrowser);
aBrowser.setAttribute("remote", aRemote ? "true" : "false");
parent.appendChild(aBrowser);
// Restore the progress listener.
aBrowser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL);
if (aRemote)
tab.setAttribute("remote", "true");
else
tab.removeAttribute("remote");
]]>
</body>
</method>
<!--
Returns true if we want to load the content for this URL in a
remote process. Eventually this should just check whether aURL
is unprivileged. Right now, though, we would like to load
some unprivileged URLs (like about:neterror) in the main
process since they interact with chrome code through
BrowserOnClick.
-->
<method name="_shouldBrowserBeRemote">
<parameter name="aURL"/>
<body>
<![CDATA[
if (!gMultiProcessBrowser)
return false;
// loadURI in browser.xml treats null as about:blank
if (!aURL)
aURL = "about:blank";
if (aURL.startsWith("about:") &&
aURL.toLowerCase() != "about:home" &&
aURL.toLowerCase() != "about:blank") {
return false;
}
if (aURL.startsWith("chrome:"))
return false;
return true;
]]>
</body>
</method>
#endif
<method name="addTab">
<parameter name="aURI"/>
<parameter name="aReferrerURI"/>
@ -1344,6 +1416,8 @@
t.setAttribute("crop", "end");
t.setAttribute("onerror", "this.removeAttribute('image');");
if (remote)
t.setAttribute("remote", "true");
t.className = "tabbrowser-tab";
this.tabContainer._unlockTabSizing();
@ -1379,10 +1453,13 @@
b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu"));
b.setAttribute("tooltip", this.getAttribute("contenttooltip"));
if (Services.prefs.getPrefType("browser.tabs.remote") == Services.prefs.PREF_BOOL &&
Services.prefs.getBoolPref("browser.tabs.remote")) {
#ifdef MAKE_E10S_WORK
let remote = this._shouldBrowserBeRemote(aURI);
#else
let remote = gMultiProcessBrowser;
#endif
if (remote)
b.setAttribute("remote", "true");
}
if (window.gShowPageResizers && document.getElementById("addon-bar").collapsed &&
window.windowState == window.STATE_NORMAL) {
@ -2554,7 +2631,17 @@
<parameter name="aCharset"/>
<body>
<![CDATA[
#ifdef MAKE_E10S_WORK
this._updateBrowserRemoteness(this.mCurrentBrowser, this._shouldBrowserBeRemote(aURI));
try {
#endif
return this.mCurrentBrowser.loadURI(aURI, aReferrerURI, aCharset);
#ifdef MAKE_E10S_WORK
} catch (e) {
let url = this.mCurrentBrowser.currentURI.spec;
this._updateBrowserRemoteness(this.mCurrentBrowser, this._shouldBrowserBeRemote(url));
}
#endif
]]>
</body>
</method>
@ -2568,7 +2655,17 @@
<parameter name="aPostData"/>
<body>
<![CDATA[
#ifdef MAKE_E10S_WORK
this._updateBrowserRemoteness(this.mCurrentBrowser, this._shouldBrowserBeRemote(aURI));
try {
#endif
return this.mCurrentBrowser.loadURIWithFlags(aURI, aFlags, aReferrerURI, aCharset, aPostData);
#ifdef MAKE_E10S_WORK
} catch (e) {
let url = this.mCurrentBrowser.currentURI.spec;
this._updateBrowserRemoteness(this.mCurrentBrowser, this._shouldBrowserBeRemote(url));
}
#endif
]]>
</body>
</method>
@ -2818,6 +2915,7 @@
browserStack.removeChild(this.mCurrentBrowser);
this.mCurrentBrowser.setAttribute("remote", true);
browserStack.appendChild(this.mCurrentBrowser);
this.tabContainer.firstChild.setAttribute("remote", "true");
}
this.mCurrentTab = this.tabContainer.firstChild;

View File

@ -51,8 +51,12 @@ XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Downloads",
"resource://gre/modules/Downloads.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
"resource://gre/modules/DownloadUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm")
XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
"resource://gre/modules/PrivateBrowsingUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
@ -582,6 +586,20 @@ XPCOMUtils.defineLazyGetter(DownloadsCommon, "isWinVistaOrHigher", function () {
return parseFloat(sysInfo.getProperty("version")) >= 6;
});
/**
* Returns true if we should hook the panel to the JavaScript API for downloads
* instead of the nsIDownloadManager back-end. In order for the logic to work
* properly, this value never changes during the execution of the application,
* even if the underlying preference value has changed. A restart is required
* for the change to take effect.
*/
XPCOMUtils.defineLazyGetter(DownloadsCommon, "useJSTransfer", function () {
try {
return Services.prefs.getBoolPref("browser.download.useJSTransfer");
} catch (ex) { }
return false;
});
////////////////////////////////////////////////////////////////////////////////
//// DownloadsData
@ -617,6 +635,11 @@ function DownloadsDataCtor(aPrivate) {
// Array of view objects that should be notified when the available download
// data changes.
this._views = [];
if (DownloadsCommon.useJSTransfer) {
// Maps Download objects to DownloadDataItem objects.
this._downloadToDataItemMap = new Map();
}
}
DownloadsDataCtor.prototype = {
@ -632,8 +655,15 @@ DownloadsDataCtor.prototype = {
initializeDataLink: function DD_initializeDataLink(aDownloadManagerService)
{
// Start receiving real-time events.
aDownloadManagerService.addPrivacyAwareListener(this);
Services.obs.addObserver(this, "download-manager-remove-download-guid", false);
if (DownloadsCommon.useJSTransfer) {
let promiseList = this._isPrivate ? Downloads.getPrivateDownloadList()
: Downloads.getPublicDownloadList();
promiseList.then(list => list.addView(this)).then(null, Cu.reportError);
} else {
aDownloadManagerService.addPrivacyAwareListener(this);
Services.obs.addObserver(this, "download-manager-remove-download-guid",
false);
}
},
/**
@ -641,6 +671,11 @@ DownloadsDataCtor.prototype = {
*/
terminateDataLink: function DD_terminateDataLink()
{
if (DownloadsCommon.useJSTransfer) {
Cu.reportError("terminateDataLink not applicable with useJSTransfer");
return;
}
this._terminateDataAccess();
// Stop receiving real-time events.
@ -648,6 +683,84 @@ DownloadsDataCtor.prototype = {
Services.downloads.removeListener(this);
},
//////////////////////////////////////////////////////////////////////////////
//// Integration with the asynchronous Downloads back-end
onDownloadAdded: function (aDownload)
{
let dataItem = new DownloadsDataItem(aDownload);
this._downloadToDataItemMap.set(aDownload, dataItem);
this.dataItems[dataItem.downloadGuid] = dataItem;
for (let view of this._views) {
view.onDataItemAdded(dataItem, true);
}
this._updateDataItemState(dataItem);
},
onDownloadChanged: function (aDownload)
{
let dataItem = this._downloadToDataItemMap.get(aDownload);
if (!dataItem) {
Cu.reportError("Download doesn't exist.");
return;
}
this._updateDataItemState(dataItem);
},
onDownloadRemoved: function (aDownload)
{
let dataItem = this._downloadToDataItemMap.get(aDownload);
if (!dataItem) {
Cu.reportError("Download doesn't exist.");
return;
}
this._downloadToDataItemMap.remove(aDownload);
this.dataItems[dataItem.downloadGuid] = null;
for (let view of this._views) {
view.onDataItemRemoved(dataItem);
}
},
/**
* Updates the given data item and sends related notifications.
*/
_updateDataItemState: function (aDataItem)
{
let wasInProgress = aDataItem.inProgress;
let wasDone = aDataItem.done;
aDataItem.updateFromJSDownload();
if (wasInProgress && !aDataItem.inProgress) {
aDataItem.endTime = Date.now();
}
for (let view of this._views) {
try {
view.getViewItem(aDataItem).onStateChange({});
} catch (ex) {
Cu.reportError(ex);
}
}
if (!aDataItem.newDownloadNotified) {
aDataItem.newDownloadNotified = true;
this._notifyDownloadEvent("start");
}
if (!wasDone && aDataItem.done) {
this._notifyDownloadEvent("finish");
}
for (let view of this._views) {
view.getViewItem(aDataItem).onProgressChange();
}
},
//////////////////////////////////////////////////////////////////////////////
//// Registration of views
@ -1160,11 +1273,14 @@ XPCOMUtils.defineLazyGetter(this, "DownloadsData", function() {
*
* @param aSource
* Object containing the data with which the item should be initialized.
* This should implement either nsIDownload or mozIStorageRow.
* This should implement either nsIDownload or mozIStorageRow. If the
* JavaScript API for downloads is enabled, this is a Download object.
*/
function DownloadsDataItem(aSource)
{
if (aSource instanceof Ci.nsIDownload) {
if (DownloadsCommon.useJSTransfer) {
this._initFromJSDownload(aSource);
} else if (aSource instanceof Ci.nsIDownload) {
this._initFromDownload(aSource);
} else {
this._initFromDataRow(aSource);
@ -1172,6 +1288,66 @@ function DownloadsDataItem(aSource)
}
DownloadsDataItem.prototype = {
/**
* The JavaScript API does not need identifiers for Download objects, so they
* are generated sequentially for the corresponding DownloadDataItem.
*/
get _autoIncrementId() ++DownloadsDataItem.prototype.__lastId,
__lastId: 0,
/**
* Initializes this object from the JavaScript API for downloads.
*
* The endTime property is initialized to the current date and time.
*
* @param aDownload
* The Download object with the current state.
*/
_initFromJSDownload: function (aDownload)
{
this._download = aDownload;
this.downloadGuid = "id:" + this._autoIncrementId;
this.file = aDownload.target.path;
this.target = OS.Path.basename(aDownload.target.path);
this.uri = aDownload.source.url;
this.endTime = Date.now();
this.updateFromJSDownload();
},
/**
* Updates this object from the JavaScript API for downloads.
*/
updateFromJSDownload: function ()
{
// Collapse state using the correct priority.
if (this._download.succeeded) {
this.state = nsIDM.DOWNLOAD_FINISHED;
} else if (this._download.error &&
this._download.error.becauseBlockedByParentalControls) {
this.state = nsIDM.DOWNLOAD_BLOCKED_PARENTAL;
} else if (this._download.error) {
this.state = nsIDM.DOWNLOAD_FAILED;
} else if (this._download.canceled && this._download.hasPartialData) {
this.state = nsIDM.DOWNLOAD_PAUSED;
} else if (this._download.canceled) {
this.state = nsIDM.DOWNLOAD_CANCELED;
} else if (this._download.stopped) {
this.state = nsIDM.DOWNLOAD_NOTSTARTED;
} else {
this.state = nsIDM.DOWNLOAD_DOWNLOADING;
}
this.referrer = this._download.source.referrer;
this.startTime = this._download.startTime;
this.currBytes = this._download.currentBytes;
this.maxBytes = this._download.totalBytes;
this.resumable = this._download.hasPartialData;
this.speed = 0;
this.percentComplete = this._download.progress;
},
/**
* Initializes this object from a download object of the Download Manager.
*
@ -1408,6 +1584,11 @@ DownloadsDataItem.prototype = {
* @throws if the file cannot be opened.
*/
openLocalFile: function DDI_openLocalFile(aOwnerWindow) {
if (DownloadsCommon.useJSTransfer) {
this._download.launch().then(null, Cu.reportError);
return;
}
this.getDownload(function(aDownload) {
DownloadsCommon.openDownloadedFile(this.localFile,
aDownload.MIMEInfo,
@ -1427,6 +1608,15 @@ DownloadsDataItem.prototype = {
* @throws if the download is not resumable or if has already done.
*/
togglePauseResume: function DDI_togglePauseResume() {
if (DownloadsCommon.useJSTransfer) {
if (this._download.stopped) {
this._download.start();
} else {
this._download.cancel();
}
return;
}
if (!this.inProgress || !this.resumable)
throw new Error("The given download cannot be paused or resumed");
@ -1445,8 +1635,13 @@ DownloadsDataItem.prototype = {
* @throws if we cannot.
*/
retry: function DDI_retry() {
if (DownloadsCommon.useJSTransfer) {
this._download.start();
return;
}
if (!this.canRetry)
throw new Error("Cannot rerty this download");
throw new Error("Cannot retry this download");
this.getDownload(function(aDownload) {
aDownload.retry();
@ -1473,6 +1668,12 @@ DownloadsDataItem.prototype = {
* @throws if the download is already done.
*/
cancel: function() {
if (DownloadsCommon.useJSTransfer) {
this._download.cancel();
this._download.removePartialData().then(null, Cu.reportError);
return;
}
if (!this.inProgress)
throw new Error("Cannot cancel this download");
@ -1486,6 +1687,16 @@ DownloadsDataItem.prototype = {
* Remove the download.
*/
remove: function DDI_remove() {
if (DownloadsCommon.useJSTransfer) {
let promiseList = this._download.source.isPrivate
? Downloads.getPrivateDownloadList()
: Downloads.getPublicDownloadList();
promiseList.then(list => list.remove(this._download))
.then(() => this._download.finalize(true))
.then(null, Cu.reportError);
return;
}
this.getDownload(function (aDownload) {
if (this.inProgress) {
aDownload.cancel();

View File

@ -86,10 +86,6 @@ DownloadsStartup.prototype = {
{
switch (aTopic) {
case "profile-after-change":
kObservedTopics.forEach(
function (topic) Services.obs.addObserver(this, topic, true),
this);
// Override Toolkit's nsIDownloadManagerUI implementation with our own.
// This must be done at application startup and not in the manifest to
// ensure that our implementation overrides the original one.
@ -104,15 +100,21 @@ DownloadsStartup.prototype = {
// when nsIDownloadManager will not be available anymore (bug 851471).
let useJSTransfer = false;
try {
// For performance reasons, we don't want to load the DownloadsCommon
// module during startup, so we read the preference value directly.
useJSTransfer =
Services.prefs.getBoolPref("browser.download.useJSTransfer");
} catch (ex) {
// This is a hidden preference that does not exist by default.
}
} catch (ex) { }
if (useJSTransfer) {
Components.manager.QueryInterface(Ci.nsIComponentRegistrar)
.registerFactory(kTransferCid, "",
kTransferContractId, null);
} else {
// The other notifications are handled internally by the JavaScript
// API for downloads, no need to observe when that API is enabled.
for (let topic of kObservedTopics) {
Services.obs.addObserver(this, topic, true);
}
}
break;

View File

@ -112,8 +112,6 @@ let gDocShellCapabilities = (function () {
};
})();
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ScratchpadManager",
"resource:///modules/devtools/scratchpad-manager.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DocumentUtils",
@ -349,16 +347,6 @@ let SessionStoreInternal = {
// See bug 516755.
_disabledForMultiProcess: false,
// The original "sessionstore.resume_session_once" preference value before it
// was modified by saveState. saveState will set the
// "sessionstore.resume_session_once" to true when the
// the "sessionstore.resume_from_crash" preference is false (crash recovery
// is disabled) so that pinned tabs will be restored in the case of a
// crash. This variable is used to restore the original value so the
// previous session is not always restored when
// "sessionstore.resume_from_crash" is true.
_resume_session_once_on_shutdown: null,
/**
* A promise fulfilled once initialization is complete.
*/
@ -1057,15 +1045,6 @@ let SessionStoreInternal = {
// browser is about to exit anyway.
Services.obs.removeObserver(this, "browser:purge-session-history");
}
else if (this._resume_session_once_on_shutdown != null) {
// if the sessionstore.resume_session_once preference was changed by
// saveState because crash recovery is disabled then restore the
// preference back to the value it was prior to that. This will prevent
// SessionStore from always restoring the session when crash recovery is
// disabled.
this._prefBranch.setBoolPref("sessionstore.resume_session_once",
this._resume_session_once_on_shutdown);
}
if (aData != "restart") {
// Throw away the previous session on shutdown
@ -1214,12 +1193,6 @@ let SessionStoreInternal = {
break;
case "sessionstore.resume_from_crash":
this._resume_from_crash = this._prefBranch.getBoolPref("sessionstore.resume_from_crash");
// restore original resume_session_once preference if set in saveState
if (this._resume_session_once_on_shutdown != null) {
this._prefBranch.setBoolPref("sessionstore.resume_session_once",
this._resume_session_once_on_shutdown);
this._resume_session_once_on_shutdown = null;
}
// either create the file with crash recovery information or remove it
// (when _loadState is not STATE_RUNNING, that file is used for session resuming instead)
if (!this._resume_from_crash)
@ -3841,19 +3814,6 @@ let SessionStoreInternal = {
}
#endif
if (pinnedOnly) {
// Save original resume_session_once preference for when quiting browser,
// otherwise session will be restored next time browser starts and we
// only want it to be restored in the case of a crash.
if (this._resume_session_once_on_shutdown == null) {
this._resume_session_once_on_shutdown =
this._prefBranch.getBoolPref("sessionstore.resume_session_once");
this._prefBranch.setBoolPref("sessionstore.resume_session_once", true);
// flush the preference file so preference will be saved in case of a crash
Services.prefs.savePrefFile(null);
}
}
// Persist the last session if we deferred restoring it
if (this._lastSessionState)
oState.lastSessionState = this._lastSessionState;

View File

@ -19,14 +19,12 @@ Cu.import("resource://gre/modules/osfile.jsm");
Cu.import("resource://gre/modules/devtools/gcli.jsm");
Cu.import("resource:///modules/devtools/shared/event-emitter.js");
var require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
let Telemetry = require("devtools/shared/telemetry");
let devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
let Telemetry = devtools.require("devtools/shared/telemetry");
let telemetry = new Telemetry();
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
"resource:///modules/devtools/gDevTools.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "devtools",
"resource://gre/modules/devtools/Loader.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AppCacheUtils",
"resource:///modules/devtools/AppCacheUtils.jsm");
@ -799,8 +797,13 @@ XPCOMUtils.defineLazyModuleGetter(this, "AppCacheUtils",
/* CmdConsole -------------------------------------------------------------- */
(function(module) {
XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
"resource:///modules/HUDService.jsm");
Object.defineProperty(this, "HUDService", {
get: function() {
return devtools.require("devtools/webconsole/hudservice");
},
configurable: true,
enumerable: true
});
/**
* 'console' command

View File

@ -3,8 +3,6 @@
// Tests that the calllog commands works as they should
let HUDService = (Cu.import("resource:///modules/HUDService.jsm", {})).HUDService;
const TEST_URI = "data:text/html;charset=utf-8,gcli-calllog";
let tests = {};
@ -55,7 +53,7 @@ tests.testCallLogExec = function(options) {
subject.QueryInterface(Ci.nsISupportsString);
let hud = HUDService.getHudReferenceById(subject.data);
ok(hud.hudId in HUDService.hudReferences, "console open");
ok(hud, "console open");
helpers.audit(options, [
{

View File

@ -3,8 +3,6 @@
// Tests that the calllog commands works as they should
let HUDService = (Cu.import("resource:///modules/HUDService.jsm", {})).HUDService;
const TEST_URI = "data:text/html;charset=utf-8,cmd-calllog-chrome";
let tests = {};
@ -56,7 +54,7 @@ tests.testCallLogExec = function(options) {
subject.QueryInterface(Ci.nsISupportsString);
let hud = HUDService.getHudReferenceById(subject.data);
ok(hud.hudId in HUDService.hudReferences, "console open");
ok(hud, "console open");
helpers.audit(options, [
{

View File

@ -3,8 +3,6 @@
// Test various GCLI commands
let HUDService = (Cu.import("resource:///modules/HUDService.jsm", {})).HUDService;
const TEST_URI = "data:text/html;charset=utf-8,gcli-commands";
let tests = {};
@ -24,41 +22,46 @@ tests.testConsole = function(options) {
subject.QueryInterface(Ci.nsISupportsString);
hud = HUDService.getHudReferenceById(subject.data);
ok(hud.hudId in HUDService.hudReferences, "console open");
ok(hud, "console open");
hud.jsterm.execute("pprint(window)", onExecute);
}
Services.obs.addObserver(onWebConsoleOpen, "web-console-created", false);
let onExecute = function() {
function onExecute () {
let labels = hud.outputNode.querySelectorAll(".webconsole-msg-output");
ok(labels.length > 0, "output for pprint(window)");
hud.jsterm.once("messages-cleared", onClear);
helpers.audit(options, [
{
setup: "console clear",
exec: {
output: ""
},
post: function() {
let labels = hud.outputNode.querySelectorAll(".webconsole-msg-output");
// Bug 845827 - The GCLI "console clear" command doesn't always work
// is(labels.length, 0, "no output in console");
}
},
}
]);
}
function onClear() {
let labels = hud.outputNode.querySelectorAll(".webconsole-msg-output");
is(labels.length, 0, "no output in console");
helpers.audit(options, [
{
setup: "console close",
exec: {
output: ""
},
post: function() {
ok(!(hud.hudId in HUDService.hudReferences), "console closed");
ok(!HUDService.getHudReferenceById(hud.hudId), "console closed");
}
}
]).then(function() {
deferred.resolve();
});
};
}
helpers.audit(options, [
{

View File

@ -506,11 +506,12 @@ gcli.addCommand({
const blackBoxed = [];
for (let source of toBlackBox) {
let { url } = source;
activeThread.source(source)[cmd.clientMethod](function ({ error }) {
if (error) {
blackBoxed.push(lookup("ErrorDesc") + " " + source.url);
blackBoxed.push(lookup("ErrorDesc") + " " + url);
} else {
blackBoxed.push(source.url);
blackBoxed.push(url);
}
if (toBlackBox.length === blackBoxed.length) {

View File

@ -29,8 +29,17 @@ Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Parser",
"resource:///modules/devtools/Parser.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetworkHelper",
"resource://gre/modules/devtools/NetworkHelper.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "devtools",
"resource://gre/modules/devtools/Loader.jsm");
Object.defineProperty(this, "NetworkHelper", {
get: function() {
return devtools.require("devtools/toolkit/webconsole/network-helper");
},
configurable: true,
enumerable: true
});
/**
* Object defining the debugger controller components.
@ -438,6 +447,7 @@ StackFrames.prototype = {
currentEvaluation: null,
currentException: null,
currentReturnedValue: null,
_dontSwitchSources: false,
/**
* Connect to the current thread client.
@ -594,12 +604,24 @@ StackFrames.prototype = {
// Make sure the debugger view panes are visible.
DebuggerView.showInstrumentsPane();
this._refillFrames();
},
/**
* Fill the StackFrames view with the frames we have in the cache, compressing
* frames which have black boxed sources into single frames.
*/
_refillFrames: function() {
// Make sure all the previous stackframes are removed before re-adding them.
DebuggerView.StackFrames.empty();
let previousBlackBoxed = null;
for (let frame of this.activeThread.cachedFrames) {
let { depth, where: { url, line }, isBlackBoxed } = frame;
let { depth, where: { url, line }, source } = frame;
let isBlackBoxed = source
? this.activeThread.source(source).isBlackBoxed
: false;
let frameLocation = NetworkHelper.convertToUnicode(unescape(url));
let frameTitle = StackFrameUtils.getFrameTitle(frame);
@ -612,8 +634,10 @@ StackFrames.prototype = {
previousBlackBoxed = null;
}
DebuggerView.StackFrames.addFrame(frameTitle, frameLocation, line, depth, isBlackBoxed);
DebuggerView.StackFrames.addFrame(
frameTitle, frameLocation, line, depth, isBlackBoxed);
}
if (this.currentFrame == null) {
DebuggerView.StackFrames.selectedDepth = 0;
}
@ -644,10 +668,9 @@ StackFrames.prototype = {
*/
_onBlackBoxChange: function() {
if (this.activeThread.state == "paused") {
// We have to clear out the existing frames and refetch them to get their
// updated black boxed status.
this.activeThread._clearFrames();
this.activeThread.fillFrames(CALL_STACK_PAGE_SIZE);
this._dontSwitchSources = true;
this.currentFrame = null;
this._refillFrames();
}
},
@ -672,8 +695,10 @@ StackFrames.prototype = {
*
* @param number aDepth
* The depth of the frame in the stack.
* @param boolean aDontSwitchSources
* Flag on whether or not we want to switch the selected source.
*/
selectFrame: function(aDepth) {
selectFrame: function(aDepth, aDontSwitchSources) {
// Make sure the frame at the specified depth exists first.
let frame = this.activeThread.cachedFrames[this.currentFrame = aDepth];
if (!frame) {
@ -686,8 +711,11 @@ StackFrames.prototype = {
return;
}
let noSwitch = this._dontSwitchSources;
this._dontSwitchSources = false;
// Move the editor's caret to the proper url and line.
DebuggerView.updateEditor(url, line);
DebuggerView.updateEditor(url, line, { noSwitch: noSwitch });
// Highlight the breakpoint at the specified url and line if it exists.
DebuggerView.Sources.highlightBreakpoint(url, line);
// Don't display the watch expressions textbox inputs in the pane.

View File

@ -193,18 +193,34 @@
modifiers="accel alt"
command="prevSourceCommand"/>
<key id="resumeKey"
keycode="&debuggerUI.stepping.resume;"
keycode="&debuggerUI.stepping.resume1;"
command="resumeCommand"/>
<key id="resumeKey2"
keycode="&debuggerUI.stepping.resume2;"
modifiers="accel"
command="resumeCommand"/>
<key id="stepOverKey"
keycode="&debuggerUI.stepping.stepOver;"
keycode="&debuggerUI.stepping.stepOver1;"
command="stepOverCommand"/>
<key id="stepOverKey2"
keycode="&debuggerUI.stepping.stepOver2;"
modifiers="accel"
command="stepOverCommand"/>
<key id="stepInKey"
keycode="&debuggerUI.stepping.stepIn;"
keycode="&debuggerUI.stepping.stepIn1;"
command="stepInCommand"/>
<key id="stepInKey2"
keycode="&debuggerUI.stepping.stepIn2;"
modifiers="accel"
command="stepInCommand"/>
<key id="stepOutKey"
keycode="&debuggerUI.stepping.stepOut;"
keycode="&debuggerUI.stepping.stepOut1;"
modifiers="shift"
command="stepOutCommand"/>
<key id="stepOutKey2"
keycode="&debuggerUI.stepping.stepOut2;"
modifiers="accel shift"
command="stepOutCommand"/>
<key id="fileSearchKey"
key="&debuggerUI.searchFile.key;"
modifiers="accel"

View File

@ -17,6 +17,8 @@ MOCHITEST_BROWSER_TESTS = \
browser_dbg_blackboxing-03.js \
browser_dbg_blackboxing-04.js \
browser_dbg_blackboxing-05.js \
browser_dbg_blackboxing-06.js \
browser_dbg_blackboxing-07.js \
browser_dbg_clean-exit.js \
browser_dbg_cmd.js \
browser_dbg_cmd_blackbox.js \

View File

@ -57,17 +57,15 @@ function testBlackBoxSource() {
const { activeThread } = gDebugger.DebuggerController;
activeThread.addOneTimeListener("blackboxchange", function (event, sourceClient) {
activeThread.addOneTimeListener("framesadded", function () {
ok(sourceClient.isBlackBoxed, "The source should be black boxed now");
ok(sourceClient.isBlackBoxed, "The source should be black boxed now");
const frames = gDebugger.DebuggerView.StackFrames.widget._list;
is(frames.querySelectorAll(".dbg-stackframe").length, 3,
"Should only get 3 frames");
is(frames.querySelectorAll(".dbg-stackframe-black-boxed").length, 1,
"And one of them is the combined black boxed frames");
const frames = gDebugger.DebuggerView.StackFrames.widget._list;
is(frames.querySelectorAll(".dbg-stackframe").length, 3,
"Should only get 3 frames");
is(frames.querySelectorAll(".dbg-stackframe-black-boxed").length, 1,
"And one of them is the combined black boxed frames");
closeDebuggerAndFinish();
});
closeDebuggerAndFinish();
});
checkbox.click();

View File

@ -41,7 +41,7 @@ function testSourceEditorShown() {
function blackBoxSource() {
const { activeThread } = gDebugger.DebuggerController;
activeThread.addOneTimeListener("blackboxchange", testBlackBoxMessageShown);
getBlackBoxCheckbox().click();
getAnyBlackBoxCheckbox().click();
}
function testBlackBoxMessageShown() {
@ -65,7 +65,7 @@ function testSourceEditorShownAgain() {
closeDebuggerAndFinish();
}
function getBlackBoxCheckbox() {
function getAnyBlackBoxCheckbox() {
return gDebugger.document.querySelector(
".side-menu-widget-item .side-menu-widget-item-checkbox");
}

View File

@ -0,0 +1,70 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that clicking the black box checkbox doesn't select that source.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_blackboxing.html";
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
resumed = true;
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
once(gDebugger, "Debugger:SourceShown", testBlackBox);
});
}
function testBlackBox() {
const sources = gDebugger.DebuggerView.Sources;
const selectedUrl = sources.selectedItem.attachment.source.url;
const checkbox = getDifferentBlackBoxCheckbox(selectedUrl);
ok(checkbox, "We should be able to grab a checkbox");
const { activeThread } = gDebugger.DebuggerController;
activeThread.addOneTimeListener("blackboxchange", function () {
is(selectedUrl,
sources.selectedItem.attachment.source.url,
"The same source should be selected");
closeDebuggerAndFinish();
});
checkbox.click();
}
function getDifferentBlackBoxCheckbox(url) {
return gDebugger.document.querySelector(
".side-menu-widget-item:not([tooltiptext=\""
+ url + "\"]) .side-menu-widget-item-checkbox");
}
function once(target, event, callback) {
target.addEventListener(event, function _listener(...args) {
target.removeEventListener(event, _listener, false);
callback.apply(null, args);
}, false);
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
});

View File

@ -0,0 +1,86 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that clicking the black box checkbox when paused doesn't re-select the
* currently paused frame's source.
*/
const TAB_URL = EXAMPLE_URL + "browser_dbg_blackboxing.html";
var gPane = null;
var gTab = null;
var gDebuggee = null;
var gDebugger = null;
function test()
{
let scriptShown = false;
let framesAdded = false;
let resumed = false;
let testStarted = false;
debug_tab_pane(TAB_URL, function(aTab, aDebuggee, aPane) {
resumed = true;
gTab = aTab;
gDebuggee = aDebuggee;
gPane = aPane;
gDebugger = gPane.panelWin;
once(gDebugger, "Debugger:SourceShown", runTest);
});
}
function runTest() {
const { activeThread } = gDebugger.DebuggerController;
activeThread.addOneTimeListener("paused", function () {
const sources = gDebugger.DebuggerView.Sources;
const selectedUrl = sources.selectedItem.attachment.source.url;
once(gDebugger, "Debugger:SourceShown", function () {
const newSelectedUrl = sources.selectedItem.attachment.source.url;
isnot(selectedUrl, newSelectedUrl,
"Should not have the same url selected");
activeThread.addOneTimeListener("blackboxchange", function () {
isnot(sources.selectedItem.attachment.source.url,
selectedUrl,
"The selected source did not change");
closeDebuggerAndFinish();
});
getBlackBoxCheckbox(newSelectedUrl).click();
});
getDifferentSource(selectedUrl).click();
});
gDebuggee.runTest();
}
function getDifferentSource(url) {
return gDebugger.document.querySelector(
".side-menu-widget-item:not([tooltiptext=\""
+ url + "\"])");
}
function getBlackBoxCheckbox(url) {
return gDebugger.document.querySelector(
".side-menu-widget-item[tooltiptext=\""
+ url + "\"] .side-menu-widget-item-checkbox");
}
function once(target, event, callback) {
target.addEventListener(event, function _listener(...args) {
target.removeEventListener(event, _listener, false);
callback.apply(null, args);
}, false);
}
registerCleanupFunction(function() {
removeTab(gTab);
gPane = null;
gTab = null;
gDebuggee = null;
gDebugger = null;
});

View File

@ -20,7 +20,7 @@ let gClient;
let gThreadClient;
let gTab;
function cmd(typed, expectedNumEvents=1) {
function cmd(typed, expectedNumEvents=1, output=null) {
const deferred = promise.defer();
let timesFired = 0;
@ -31,10 +31,16 @@ function cmd(typed, expectedNumEvents=1) {
}
});
helpers.audit(gOptions, [{
let audit = {
setup: typed,
exec: {}
}]);
};
if (output) {
audit.output = output;
}
helpers.audit(gOptions, [audit]);
return deferred.promise;
}
@ -93,7 +99,8 @@ function testUnBlackBoxSource() {
}
function testBlackBoxGlob() {
return cmd("dbg blackbox --glob *blackboxing_t*.js", 2)
return cmd("dbg blackbox --glob *blackboxing_t*.js", 2,
[/blackboxing_three\.js/g, /blackboxing_two\.js/g])
.then(function () {
ok(getBlackBoxCheckbox(BLACKBOXME_URL).checked,
"blackboxme should not be black boxed because it doesn't match the glob");

View File

@ -19,6 +19,7 @@ var ProfilerController = devtools.require("devtools/profiler/controller");
const FORBIDDEN_IDS = new Set(["toolbox", ""]);
const MAX_ORDINAL = 99;
/**
* DevTools is a class that represents a set of developer tools, it holds a
* set of tools and keeps track of open toolboxes in the browser.
@ -345,15 +346,24 @@ let gDevToolsBrowser = {
selectToolCommand: function(gBrowser, toolId) {
let target = devtools.TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
let tools = gDevTools.getToolDefinitionMap();
let toolDefinition = tools.get(toolId);
if (toolbox && toolbox.currentToolId == toolId) {
if (toolbox.hostType == devtools.Toolbox.HostType.WINDOW) {
toolbox.fireCustomKey(toolId);
if (toolDefinition.preventClosingOnKey || toolbox.hostType == devtools.Toolbox.HostType.WINDOW) {
toolbox.raise();
} else {
toolbox.destroy();
}
} else {
gDevTools.showToolbox(target, toolId);
gDevTools.showToolbox(target, toolId).then(() => {
let target = devtools.TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
toolbox.fireCustomKey(toolId);
});
}
},
@ -374,6 +384,11 @@ let gDevToolsBrowser = {
gDevToolsBrowser._trackedBrowserWindows.add(win);
gDevToolsBrowser._addAllToolsToMenu(win.document);
if (this._isFirebugInstalled()) {
let broadcaster = win.document.getElementById("devtoolsMenuBroadcaster_DevToolbox");
broadcaster.removeAttribute("key");
}
let tabContainer = win.document.getElementById("tabbrowser-tabs")
tabContainer.addEventListener("TabSelect",
gDevToolsBrowser._updateMenuCheckbox, false);
@ -392,6 +407,7 @@ let gDevToolsBrowser = {
*/
attachKeybindingsToBrowser: function DT_attachKeybindingsToBrowser(doc, keys) {
let devtoolsKeyset = doc.getElementById("devtoolsKeyset");
if (!devtoolsKeyset) {
devtoolsKeyset = doc.createElement("keyset");
devtoolsKeyset.setAttribute("id", "devtoolsKeyset");
@ -401,6 +417,17 @@ let gDevToolsBrowser = {
mainKeyset.parentNode.insertBefore(devtoolsKeyset, mainKeyset);
},
/**
* Detect the presence of a Firebug.
*
* @return promise
*/
_isFirebugInstalled: function DT_isFirebugInstalled() {
let bootstrappedAddons = Services.prefs.getCharPref("extensions.bootstrappedAddons");
return bootstrappedAddons.indexOf("firebug@software.joehewitt.com") != -1;
},
/**
* Add the menuitem for a tool to all open browser windows.
*
@ -725,6 +752,7 @@ let gDevToolsBrowser = {
Services.obs.removeObserver(gDevToolsBrowser.destroy, "quit-application");
},
}
this.gDevToolsBrowser = gDevToolsBrowser;
gDevTools.on("tool-registered", function(ev, toolId) {

View File

@ -30,6 +30,7 @@ MOCHITEST_BROWSER_FILES = \
browser_toolbox_options_disablejs_iframe.html \
browser_toolbox_highlight.js \
browser_toolbox_raise.js \
browser_keybindings.js \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,119 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that the keybindings for opening and closing the inspector work as expected
// Can probably make this a shared test that tests all of the tools global keybindings
function test()
{
waitForExplicitFinish();
let doc;
let node;
let inspector;
let keysetMap = { };
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
doc = content.document;
waitForFocus(setupKeyBindingsTest, content);
}, true);
content.location = "data:text/html,<html><head><title>Test for the " +
"highlighter keybindings</title></head><body>" +
"<h1>Keybindings!</h1></body></html>";
function buildDevtoolsKeysetMap(keyset) {
[].forEach.call(keyset.querySelectorAll("key"), function(key) {
if (!key.getAttribute("key")) {
return;
}
let modifiers = key.getAttribute("modifiers");
keysetMap[key.id.split("_")[1]] = {
key: key.getAttribute("key"),
modifiers: modifiers,
modifierOpt: {
shiftKey: modifiers.match("shift"),
ctrlKey: modifiers.match("ctrl"),
altKey: modifiers.match("alt"),
metaKey: modifiers.match("meta"),
accelKey: modifiers.match("accel")
},
synthesizeKey: function() {
EventUtils.synthesizeKey(this.key, this.modifierOpt);
}
}
});
}
function setupKeyBindingsTest()
{
for (let win of gDevToolsBrowser._trackedBrowserWindows) {
buildDevtoolsKeysetMap(win.document.getElementById("devtoolsKeyset"));
}
gDevTools.once("toolbox-ready", (e, toolbox) => {
inspectorShouldBeOpenAndHighlighting(toolbox.getCurrentPanel(), toolbox)
});
keysetMap.inspector.synthesizeKey();
}
function inspectorShouldBeOpenAndHighlighting(aInspector, aToolbox)
{
is (aToolbox.currentToolId, "inspector", "Correct tool has been loaded");
is (aInspector.highlighter.locked, true, "Highlighter should be locked");
aInspector.highlighter.once("unlocked", () => {
is (aInspector.highlighter.locked, false, "Highlighter should be unlocked");
keysetMap.inspector.synthesizeKey();
is (aInspector.highlighter.locked, true, "Highlighter should be locked");
keysetMap.inspector.synthesizeKey();
is (aInspector.highlighter.locked, false, "Highlighter should be unlocked");
keysetMap.inspector.synthesizeKey();
is (aInspector.highlighter.locked, true, "Highlighter should be locked");
aToolbox.once("webconsole-ready", (e, panel) => {
webconsoleShouldBeSelected(aToolbox, panel);
});
keysetMap.webconsole.synthesizeKey();
});
}
function webconsoleShouldBeSelected(aToolbox, panel)
{
is (aToolbox.currentToolId, "webconsole");
aToolbox.once("jsdebugger-ready", (e, panel) => {
jsdebuggerShouldBeSelected(aToolbox, panel);
});
keysetMap.jsdebugger.synthesizeKey();
}
function jsdebuggerShouldBeSelected(aToolbox, panel)
{
is (aToolbox.currentToolId, "jsdebugger");
aToolbox.once("netmonitor-ready", (e, panel) => {
netmonitorShouldBeSelected(aToolbox, panel);
});
keysetMap.netmonitor.synthesizeKey();
}
function netmonitorShouldBeSelected(aToolbox, panel)
{
is (aToolbox.currentToolId, "netmonitor");
finishUp();
}
function finishUp() {
doc = node = inspector = keysetMap = null;
gBrowser.removeCurrentTab();
finish();
}
}

View File

@ -264,13 +264,30 @@ Toolbox.prototype = {
key.setAttribute("modifiers", toolDefinition.modifiers);
key.setAttribute("oncommand", "void(0);"); // needed. See bug 371900
key.addEventListener("command", function(toolId) {
this.selectTool(toolId);
this.selectTool(toolId).then(() => {
this.fireCustomKey(toolId);
});
}.bind(this, id), true);
doc.getElementById("toolbox-keyset").appendChild(key);
}
}
},
/**
* Handle any custom key events. Returns true if there was a custom key binding run
* @param {string} toolId
* Which tool to run the command on (skip if not current)
*/
fireCustomKey: function TBOX_fireCustomKey(toolId) {
let tools = gDevTools.getToolDefinitionMap();
let activeToolDefinition = tools.get(toolId);
if (activeToolDefinition.onkey && this.currentToolId === toolId) {
activeToolDefinition.onkey(this.getCurrentPanel());
}
},
/**
* Build the buttons for changing hosts. Called every time
* the host changes.

View File

@ -129,8 +129,6 @@ Highlighter.prototype = {
this.transitionDisabler = null;
this.pageEventsMuter = null;
this.unlockAndFocus();
this.selection.on("new-node", this.highlight);
this.selection.on("new-node", this.updateInfobar);
this.selection.on("pseudoclass", this.updateInfobar);

View File

@ -137,10 +137,6 @@ InspectorPanel.prototype = {
// All the components are initialized. Let's select a node.
this._selection.setNodeFront(defaultSelection);
if (this.highlighter) {
this.highlighter.unlock();
}
this.markup.expandNode(this.selection.nodeFront);
this.emit("ready");

View File

@ -4,13 +4,10 @@
"use strict";
const {Cu} = require("chrome");
const EventEmitter = require("devtools/shared/event-emitter");
const promise = require("sdk/core/promise");
loader.lazyGetter(this, "AutocompletePopup", () => {
return Cu.import("resource:///modules/devtools/AutocompletePopup.jsm", {}).AutocompletePopup;
});
loader.lazyGetter(this, "AutocompletePopup", () => require("devtools/shared/autocomplete-popup").AutocompletePopup);
// Maximum number of selector suggestions shown in the panel.
const MAX_SUGGESTIONS = 15;

View File

@ -29,6 +29,7 @@ function test()
function runObjectInspectionTest(inspector)
{
inspector.highlighter.once("locked", performTestComparison);
inspector.highlighter.unlock();
inspector.selection.setNode(objectNode, "");
}

View File

@ -50,6 +50,7 @@ function test()
function runTests(inspector)
{
inspector.highlighter.unlock();
executeSoon(function() {
inspector.highlighter.once("highlighting", isTheIframeSelected);
moveMouseOver(iframeNode, 1, 1);

View File

@ -51,6 +51,7 @@ function moveMouseOver(aElement)
function runIframeTests()
{
getActiveInspector().highlighter.unlock();
getActiveInspector().selection.once("new-node", performTestComparisons1);
moveMouseOver(div1)
}

View File

@ -35,6 +35,7 @@ function inspectNode(aInspector)
inspector.highlighter.once("locked", performScrollingTest);
executeSoon(function() {
inspector.highlighter.unlock();
inspector.selection.setNode(div, "");
});
}

View File

@ -12,8 +12,7 @@ browser.jar:
content/browser/devtools/netmonitor-controller.js (netmonitor/netmonitor-controller.js)
content/browser/devtools/netmonitor-view.js (netmonitor/netmonitor-view.js)
content/browser/devtools/NetworkPanel.xhtml (webconsole/NetworkPanel.xhtml)
content/browser/devtools/webconsole.js (webconsole/webconsole.js)
* content/browser/devtools/webconsole.xul (webconsole/webconsole.xul)
content/browser/devtools/webconsole.xul (webconsole/webconsole.xul)
* content/browser/devtools/scratchpad.xul (scratchpad/scratchpad.xul)
content/browser/devtools/scratchpad.js (scratchpad/scratchpad.js)
content/browser/devtools/splitview.css (shared/splitview.css)

View File

@ -19,10 +19,12 @@ Object.defineProperty(exports, "TargetFactory", {
loader.lazyGetter(this, "osString", () => Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS);
let events = require("sdk/system/events");
// Panels
loader.lazyGetter(this, "OptionsPanel", function() require("devtools/framework/toolbox-options").OptionsPanel);
loader.lazyGetter(this, "InspectorPanel", function() require("devtools/inspector/inspector-panel").InspectorPanel);
loader.lazyImporter(this, "WebConsolePanel", "resource:///modules/WebConsolePanel.jsm");
loader.lazyGetter(this, "WebConsolePanel", function() require("devtools/webconsole/panel").WebConsolePanel);
loader.lazyImporter(this, "DebuggerPanel", "resource:///modules/devtools/DebuggerPanel.jsm");
loader.lazyImporter(this, "StyleEditorPanel", "resource:///modules/devtools/StyleEditorPanel.jsm");
loader.lazyGetter(this, "ProfilerPanel", function() require("devtools/profiler/panel"));
@ -95,6 +97,13 @@ Tools.inspector = {
label: l10n("inspector.label", inspectorStrings),
tooltip: l10n("inspector.tooltip", inspectorStrings),
preventClosingOnKey: true,
onkey: function(panel) {
if (panel.highlighter) {
panel.highlighter.toggleLockState();
}
},
isTargetSupported: function(target) {
return !target.isRemote;
},
@ -221,6 +230,8 @@ var unloadObserver = {
};
Services.obs.addObserver(unloadObserver, "sdk:loader:destroy", false);
events.emit("devtools-loaded", {});
/**
* Lookup l10n string from a string bundle.
*

View File

@ -21,9 +21,7 @@ Cu.import("resource:///modules/devtools/LayoutHelpers.jsm");
Cu.import("resource://gre/modules/devtools/Templater.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "AutocompletePopup", function() {
return Cu.import("resource:///modules/devtools/AutocompletePopup.jsm", {}).AutocompletePopup;
});
loader.lazyGetter(this, "AutocompletePopup", () => require("devtools/shared/autocomplete-popup").AutocompletePopup);
/**
* Vocabulary for the purposes of this file:
@ -161,6 +159,14 @@ MarkupView.prototype = {
}
switch(aEvent.keyCode) {
case Ci.nsIDOMKeyEvent.DOM_VK_H:
let node = this._selectedContainer.node;
if (node.hidden) {
this.walker.unhideNode(node).then(() => this.nodeChanged(node));
} else {
this.walker.hideNode(node).then(() => this.nodeChanged(node));
}
break;
case Ci.nsIDOMKeyEvent.DOM_VK_DELETE:
case Ci.nsIDOMKeyEvent.DOM_VK_BACK_SPACE:
this.deleteNode(this._selectedContainer.node);
@ -523,7 +529,7 @@ MarkupView.prototype = {
*/
nodeChanged: function MT_nodeChanged(aNode)
{
if (aNode === this._inspector.selection) {
if (aNode === this._inspector.selection.nodeFront) {
this._inspector.change("markupview");
}
},

View File

@ -19,8 +19,16 @@ Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetworkHelper",
"resource://gre/modules/devtools/NetworkHelper.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "devtools",
"resource://gre/modules/devtools/Loader.jsm");
Object.defineProperty(this, "NetworkHelper", {
get: function() {
return devtools.require("devtools/toolkit/webconsole/network-helper");
},
configurable: true,
enumerable: true
});
XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
"@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper");

View File

@ -19,9 +19,6 @@ let TargetFactory = temp.devtools.TargetFactory;
Cu.import("resource://gre/modules/devtools/dbg-server.jsm", temp);
let DebuggerServer = temp.DebuggerServer;
Cu.import("resource:///modules/HUDService.jsm", temp);
let HUDService = temp.HUDService;
// Import the GCLI test helper
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);

View File

@ -2,10 +2,6 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let tempScope = {};
Cu.import("resource:///modules/HUDService.jsm", tempScope);
let HUDService = tempScope.HUDService;
function test()
{
waitForExplicitFinish();
@ -43,7 +39,7 @@ function test()
Services.obs.
addObserver(onWebConsoleOpen, "web-console-created", false);
HUDService.consoleUI.toggleHUD();
HUDService.toggleWebConsole();
});
});
}, true);

View File

@ -25,9 +25,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "gcli",
XPCOMUtils.defineLazyModuleGetter(this, "CmdCommands",
"resource:///modules/devtools/BuiltinCommands.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ConsoleServiceListener",
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
@ -55,6 +52,14 @@ let Telemetry = devtools.require("devtools/shared/telemetry");
const converters = require("gcli/converters");
Object.defineProperty(this, "ConsoleServiceListener", {
get: function() {
return devtools.require("devtools/toolkit/webconsole/utils").ConsoleServiceListener;
},
configurable: true,
enumerable: true
});
/**
* A collection of utilities to help working with commands
*/
@ -400,6 +405,10 @@ DeveloperToolbar.prototype._onload = function DT_onload(aFocus)
tabbrowser.addEventListener("beforeunload", this, true);
this._initErrorsCount(tabbrowser.selectedTab);
this._devtoolsUnloaded = this._devtoolsUnloaded.bind(this);
this._devtoolsLoaded = this._devtoolsLoaded.bind(this);
Services.obs.addObserver(this._devtoolsUnloaded, "devtools-unloaded", false);
Services.obs.addObserver(this._devtoolsLoaded, "devtools-loaded", false);
this._element.hidden = false;
@ -427,6 +436,26 @@ DeveloperToolbar.prototype._onload = function DT_onload(aFocus)
}
};
/**
* The devtools-unloaded event handler.
* @private
*/
DeveloperToolbar.prototype._devtoolsUnloaded = function DT__devtoolsUnloaded()
{
let tabbrowser = this._chromeWindow.getBrowser();
Array.prototype.forEach.call(tabbrowser.tabs, this._stopErrorsCount, this);
};
/**
* The devtools-loaded event handler.
* @private
*/
DeveloperToolbar.prototype._devtoolsLoaded = function DT__devtoolsLoaded()
{
let tabbrowser = this._chromeWindow.getBrowser();
this._initErrorsCount(tabbrowser.selectedTab);
};
/**
* Initialize the listeners needed for tracking the number of errors for a given
* tab.
@ -523,6 +552,8 @@ DeveloperToolbar.prototype.destroy = function DT_destroy()
tabbrowser.removeEventListener("load", this, true);
tabbrowser.removeEventListener("beforeunload", this, true);
Services.obs.removeObserver(this._devtoolsUnloaded, "devtools-unloaded");
Services.obs.removeObserver(this._devtoolsLoaded, "devtools-loaded");
Array.prototype.forEach.call(tabbrowser.tabs, this._stopErrorsCount, this);
this.display.focusManager.removeMonitoredElement(this.outputPanel._frame);

View File

@ -3,20 +3,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const Cu = Components.utils;
const Ci = Components.interfaces;
"use strict";
// The XUL and XHTML namespace.
const {Cc, Ci, Cu} = require("chrome");
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "gDevTools", function() {
return Cu.import("resource:///modules/devtools/gDevTools.jsm", {}).gDevTools;
});
this.EXPORTED_SYMBOLS = ["AutocompletePopup"];
loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm");
loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
/**
* Autocomplete popup UI implementation.
@ -38,7 +31,6 @@ this.EXPORTED_SYMBOLS = ["AutocompletePopup"];
* - onClick {String} The click event handler for the richlistbox.
* - onKeypress {String} The keypress event handler for the richlistitems.
*/
this.AutocompletePopup =
function AutocompletePopup(aDocument, aOptions = {})
{
this._document = aDocument;
@ -117,6 +109,7 @@ function AutocompletePopup(aDocument, aOptions = {})
this._list.addEventListener("keypress", this.onKeypress, false);
}
}
exports.AutocompletePopup = AutocompletePopup;
AutocompletePopup.prototype = {
_document: null,
@ -268,22 +261,28 @@ AutocompletePopup.prototype = {
*/
_updateSize: function AP__updateSize()
{
// We need the dispatch to allow the content to reflow. Attempting to
// update the richlistbox size too early does not work.
Services.tm.currentThread.dispatch({ run: () => {
if (!this._panel) {
return;
}
this._list.width = this._panel.clientWidth + this._scrollbarWidth;
// Height change is required, otherwise the panel is drawn at an offset
// the first time.
this._list.height = this._list.clientHeight;
// This brings the panel back at right position.
this._list.top = 0;
// Changing panel height might make the selected item out of view, so
// bring it back to view.
this._list.ensureIndexIsVisible(this._list.selectedIndex);
}}, 0);
if (!this._panel) {
return;
}
// Flush the layout so that we get the latest height.
this._panel.boxObject.height;
let height = {};
this._list.scrollBoxObject.getScrolledSize({}, height);
// Change the width of the popup only if the scrollbar is visible.
if (height.value > this._panel.clientHeight) {
this._list.width = this._panel.clientWidth + this._scrollbarWidth;
}
// Height change is required, otherwise the panel is drawn at an offset
// the first time.
this._list.height = this._list.clientHeight;
// This brings the panel back at right position.
this._list.top = 0;
// Move the panel to -1,-1 to realign the popup with its anchor node when
// decreasing the panel height.
this._panel.moveTo(-1, -1);
// Changing panel height might make the selected item out of view, so
// bring it back to view.
this._list.ensureIndexIsVisible(this._list.selectedIndex);
},
/**

View File

@ -7,8 +7,6 @@ function test() {
const TEST_URI = "http://example.com/browser/browser/devtools/shared/test/" +
"browser_toolbar_webconsole_errors_count.html";
let HUDService = Cu.import("resource:///modules/HUDService.jsm",
{}).HUDService;
let gDevTools = Cu.import("resource:///modules/devtools/gDevTools.jsm",
{}).gDevTools;

View File

@ -14,8 +14,16 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
Cu.import("resource:///modules/devtools/shared/event-emitter.js");
XPCOMUtils.defineLazyModuleGetter(this, "NetworkHelper",
"resource://gre/modules/devtools/NetworkHelper.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "devtools",
"resource://gre/modules/devtools/Loader.jsm");
Object.defineProperty(this, "NetworkHelper", {
get: function() {
return devtools.require("devtools/toolkit/webconsole/network-helper");
},
configurable: true,
enumerable: true
});
this.EXPORTED_SYMBOLS = ["SideMenuWidget"];
@ -629,7 +637,12 @@ SideMenuItem.prototype = {
checkbox.removeAttribute("checked");
}
checkbox.addEventListener("command", function () {
// Stop the toggling of the checkbox from selecting the list item.
checkbox.addEventListener("mousedown", function (event) {
event.stopPropagation();
}, false);
checkbox.addEventListener("command", function (event) {
ViewHelpers.dispatchEvent(checkbox, "check", {
checked: checkbox.checked,
});

View File

@ -23,11 +23,24 @@ Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
Cu.import("resource:///modules/devtools/shared/event-emitter.js");
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js").Promise;
XPCOMUtils.defineLazyModuleGetter(this, "NetworkHelper",
"resource://gre/modules/devtools/NetworkHelper.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "devtools",
"resource://gre/modules/devtools/Loader.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
Object.defineProperty(this, "WebConsoleUtils", {
get: function() {
return devtools.require("devtools/toolkit/webconsole/utils").Utils;
},
configurable: true,
enumerable: true
});
Object.defineProperty(this, "NetworkHelper", {
get: function() {
return devtools.require("devtools/toolkit/webconsole/network-helper");
},
configurable: true,
enumerable: true
});
this.EXPORTED_SYMBOLS = ["VariablesView"];

View File

@ -12,7 +12,17 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js").Promise;
Cu.import("resource:///modules/devtools/VariablesView.jsm");
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "devtools",
"resource://gre/modules/devtools/Loader.jsm");
Object.defineProperty(this, "WebConsoleUtils", {
get: function() {
return devtools.require("devtools/toolkit/webconsole/utils").Utils;
},
configurable: true,
enumerable: true
});
XPCOMUtils.defineLazyGetter(this, "VARIABLES_SORTING_ENABLED", () =>
Services.prefs.getBoolPref("devtools.debugger.ui.variables-sorting-enabled")

View File

@ -149,7 +149,7 @@ StyleEditorUI.prototype = {
*/
_onStyleSheetsCleared: function() {
// remember selected sheet and line number for next load
if (this.selectedEditor) {
if (this.selectedEditor && this.selectedEditor.sourceEditor) {
let href = this.selectedEditor.styleSheet.href;
let {line, col} = this.selectedEditor.sourceEditor.getCaretPosition();
this.selectStyleSheet(href, line, col);

View File

@ -1891,6 +1891,4 @@ XPCOMUtils.defineLazyGetter(this, "domUtils", function() {
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
});
XPCOMUtils.defineLazyGetter(this, "AutocompletePopup", function() {
return Cu.import("resource:///modules/devtools/AutocompletePopup.jsm", {}).AutocompletePopup;
});
loader.lazyGetter(this, "AutocompletePopup", () => require("devtools/shared/autocomplete-popup").AutocompletePopup);

View File

@ -12,4 +12,4 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
libs::
$(NSINSTALL) $(srcdir)/*.js $(FINAL_TARGET)/modules/devtools/framework
$(NSINSTALL) $(srcdir)/*.js $(FINAL_TARGET)/modules/devtools/webconsole

View File

@ -0,0 +1,311 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const Heritage = require("sdk/core/heritage");
const XHTML_NS = "http://www.w3.org/1999/xhtml";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
// Constants for compatibility with the Web Console output implementation before
// bug 778766.
// TODO: remove these once bug 778766 is fixed.
const COMPAT = {
// The various categories of messages.
CATEGORIES: {
NETWORK: 0,
CSS: 1,
JS: 2,
WEBDEV: 3,
INPUT: 4,
OUTPUT: 5,
SECURITY: 6,
},
// The possible message severities.
SEVERITIES: {
ERROR: 0,
WARNING: 1,
INFO: 2,
LOG: 3,
},
};
/**
* The ConsoleOutput object is used to manage output of messages in the Web
* Console.
*
* @constructor
* @param object owner
* The console output owner. This usually the WebConsoleFrame instance.
* Any other object can be used, as long as it has the following
* properties and methods:
* - window
* - document
* - outputMessage(category, methodOrNode[, methodArguments])
* TODO: this is needed temporarily, until bug 778766 is fixed.
*/
function ConsoleOutput(owner)
{
this.owner = owner;
this._onFlushOutputMessage = this._onFlushOutputMessage.bind(this);
}
ConsoleOutput.prototype = {
/**
* The document that holds the output.
* @type DOMDocument
*/
get document() this.owner.document,
/**
* The DOM window that holds the output.
* @type Window
*/
get window() this.owner.window,
/**
* Add a message to output.
*
* @param object ...args
* Any number of Message objects.
* @return this
*/
addMessage: function(...args)
{
for (let msg of args) {
msg.init(this);
this.owner.outputMessage(msg._categoryCompat, this._onFlushOutputMessage,
[msg]);
}
return this;
},
/**
* Message renderer used for compatibility with the current Web Console output
* implementation. This method is invoked for every message object that is
* flushed to output. The message object is initialized and rendered, then it
* is displayed.
*
* TODO: remove this method once bug 778766 is fixed.
*
* @private
* @param object message
* The message object to render.
* @return DOMElement
* The message DOM element that can be added to the console output.
*/
_onFlushOutputMessage: function(message)
{
return message.render().element;
},
/**
* Destroy this ConsoleOutput instance.
*/
destroy: function()
{
this.owner = null;
},
}; // ConsoleOutput.prototype
/**
* Message objects container.
* @type object
*/
let Messages = {};
/**
* The BaseMessage object is used for all types of messages. Every kind of
* message should use this object as its base.
*
* @constructor
*/
Messages.BaseMessage = function()
{
this.widgets = new Set();
};
Messages.BaseMessage.prototype = {
/**
* Reference to the ConsoleOutput owner.
*
* @type object|null
* This is |null| if the message is not yet initialized.
*/
output: null,
/**
* Reference to the parent message object, if this message is in a group or if
* it is otherwise owned by another message.
*
* @type object|null
*/
parent: null,
/**
* Message DOM element.
*
* @type DOMElement|null
* This is |null| if the message is not yet rendered.
*/
element: null,
/**
* Tells if this message is visible or not.
* @type boolean
*/
get visible() {
return this.element && this.element.parentNode;
},
/**
* Holds the text-only representation of the message.
* @type string
*/
textContent: "",
/**
* Set of widgets included in this message.
* @type Set
*/
widgets: null,
// Properties that allow compatibility with the current Web Console output
// implementation.
_elementClassCompat: "",
_categoryCompat: null,
_severityCompat: null,
/**
* Initialize the message.
*
* @param object output
* The ConsoleOutput owner.
* @param object [parent=null]
* Optional: a different message object that owns this instance.
* @return this
*/
init: function(output, parent=null)
{
this.output = output;
this.parent = parent;
return this;
},
/**
* Render the message. After this method is invoked the |element| property
* will point to the DOM element of this message.
* @return this
*/
render: function()
{
if (!this.element) {
this.element = this._renderCompat();
}
return this;
},
/**
* Prepare the message container for the Web Console, such that it is
* compatible with the current implementation.
* TODO: remove this once bug 778766.
*/
_renderCompat: function()
{
let doc = this.output.document;
let container = doc.createElementNS(XUL_NS, "richlistitem");
container.setAttribute("id", "console-msg-" + gSequenceId());
container.setAttribute("class", "hud-msg-node " + this._elementClassCompat);
container.category = this._categoryCompat;
container.severity = this._severityCompat;
container.clipboardText = this.textContent;
container.timestamp = this.timestamp;
container._messageObject = this;
let body = doc.createElementNS(XUL_NS, "description");
body.flex = 1;
body.classList.add("webconsole-msg-body");
container.appendChild(body);
return container;
},
}; // Messages.BaseMessage.prototype
/**
* The NavigationMarker is used to show a page load event.
*
* @constructor
* @extends Messages.BaseMessage
* @param string url
* The URL to display.
* @param number timestamp
* The message date and time, milliseconds elapsed since 1 January 1970
* 00:00:00 UTC.
*/
Messages.NavigationMarker = function(url, timestamp)
{
Messages.BaseMessage.apply(this, arguments);
this._url = url;
this.textContent = "------ " + url;
this.timestamp = timestamp;
};
Messages.NavigationMarker.prototype = Heritage.extend(Messages.BaseMessage.prototype,
{
/**
* Message timestamp.
*
* @type number
* Milliseconds elapsed since 1 January 1970 00:00:00 UTC.
*/
timestamp: 0,
// Class names in order: category, severity then the class for the filter.
_elementClassCompat: "webconsole-msg-network webconsole-msg-info hud-networkinfo",
_categoryCompat: COMPAT.CATEGORIES.NETWORK,
_severityCompat: COMPAT.SEVERITIES.LOG,
/**
* Prepare the DOM element for this message.
* @return this
*/
render: function()
{
if (this.element) {
return this;
}
let url = this._url;
let pos = url.indexOf("?");
if (pos > -1) {
url = url.substr(0, pos);
}
let doc = this.output.document;
let urlnode = doc.createElementNS(XHTML_NS, "span");
urlnode.className = "url";
urlnode.textContent = url;
// Add the text in the xul:description.webconsole-msg-body element.
let render = Messages.BaseMessage.prototype.render.bind(this);
render().element.firstChild.appendChild(urlnode);
this.element.classList.add("navigation-marker");
this.element.url = this._url;
return this;
},
}); // Messages.NavigationMarker.prototype
function gSequenceId()
{
return gSequenceId.n++;
}
gSequenceId.n = 0;
exports.ConsoleOutput = ConsoleOutput;
exports.Messages = Messages;

View File

@ -6,37 +6,19 @@
"use strict";
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const {Cc, Ci, Cu} = require("chrome");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
let WebConsoleUtils = require("devtools/toolkit/webconsole/utils").Utils;
let Heritage = require("sdk/core/heritage");
XPCOMUtils.defineLazyModuleGetter(this, "gDevTools",
"resource:///modules/devtools/gDevTools.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "devtools",
"resource://gre/modules/devtools/Loader.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer",
"resource://gre/modules/devtools/dbg-server.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerClient",
"resource://gre/modules/devtools/dbg-client.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "promise",
"resource://gre/modules/commonjs/sdk/core/promise.js", "Promise");
XPCOMUtils.defineLazyModuleGetter(this, "Heritage",
"resource:///modules/devtools/ViewHelpers.jsm");
let Telemetry = devtools.require("devtools/shared/telemetry");
loader.lazyGetter(this, "promise", () => require("sdk/core/promise"));
loader.lazyGetter(this, "Telemetry", () => require("devtools/shared/telemetry"));
loader.lazyGetter(this, "WebConsoleFrame", () => require("devtools/webconsole/webconsole").WebConsoleFrame);
loader.lazyImporter(this, "gDevTools", "resource:///modules/devtools/gDevTools.jsm");
loader.lazyImporter(this, "devtools", "resource://gre/modules/devtools/Loader.jsm");
loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm");
loader.lazyImporter(this, "DebuggerServer", "resource://gre/modules/devtools/dbg-server.jsm");
loader.lazyImporter(this, "DebuggerClient", "resource://gre/modules/devtools/dbg-client.jsm");
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
let l10n = new WebConsoleUtils.l10n(STRINGS_URI);
@ -46,32 +28,36 @@ const BROWSER_CONSOLE_WINDOW_FEATURES = "chrome,titlebar,toolbar,centerscreen,re
// The preference prefix for all of the Browser Console filters.
const BROWSER_CONSOLE_FILTER_PREFS_PREFIX = "devtools.browserconsole.filter.";
this.EXPORTED_SYMBOLS = ["HUDService"];
///////////////////////////////////////////////////////////////////////////
//// The HUD service
function HUD_SERVICE()
{
this.hudReferences = {};
this.consoles = new Map();
this.lastFinishedRequest = { callback: null };
}
HUD_SERVICE.prototype =
{
/**
* Keeps a reference for each HeadsUpDisplay that is created
* @type object
*/
hudReferences: null,
_browserConsoleID: null,
_browserConsoleDefer: null,
/**
* getter for UI commands to be used by the frontend
*
* @returns object
* Keeps a reference for each Web Console / Browser Console that is created.
* @type Map
*/
get consoleUI() {
return HeadsUpDisplayUICommands;
},
consoles: null,
/**
* Assign a function to this property to listen for every request that
* completes. Used by unit tests. The callback takes one argument: the HTTP
* activity object as received from the remote Web Console.
*
* @type object
* Includes a property named |callback|. Assign the function to the
* |callback| property of this object.
*/
lastFinishedRequest: null,
/**
* Firefox-specific current tab getter
@ -100,14 +86,14 @@ HUD_SERVICE.prototype =
function HS_openWebConsole(aTarget, aIframeWindow, aChromeWindow)
{
let hud = new WebConsole(aTarget, aIframeWindow, aChromeWindow);
this.hudReferences[hud.hudId] = hud;
this.consoles.set(hud.hudId, hud);
return hud.init();
},
/**
* Open a Browser Console for the given target.
*
* @see devtools/framework/Target.jsm for details about targets.
* @see devtools/framework/target.js for details about targets.
*
* @param object aTarget
* The target that the browser console will connect to.
@ -122,19 +108,19 @@ HUD_SERVICE.prototype =
function HS_openBrowserConsole(aTarget, aIframeWindow, aChromeWindow)
{
let hud = new BrowserConsole(aTarget, aIframeWindow, aChromeWindow);
this.hudReferences[hud.hudId] = hud;
this.consoles.set(hud.hudId, hud);
return hud.init();
},
/**
* Returns the HeadsUpDisplay object associated to a content window.
* Returns the Web Console object associated to a content window.
*
* @param nsIDOMWindow aContentWindow
* @returns object
*/
getHudByWindow: function HS_getHudByWindow(aContentWindow)
{
for each (let hud in this.hudReferences) {
for (let [hudId, hud] of this.consoles) {
let target = hud.target;
if (target && target.tab && target.window === aContentWindow) {
return hud;
@ -144,37 +130,152 @@ HUD_SERVICE.prototype =
},
/**
* Returns the hudId that is corresponding to the hud activated for the
* passed aContentWindow. If there is no matching hudId null is returned.
*
* @param nsIDOMWindow aContentWindow
* @returns string or null
*/
getHudIdByWindow: function HS_getHudIdByWindow(aContentWindow)
{
let hud = this.getHudByWindow(aContentWindow);
return hud ? hud.hudId : null;
},
/**
* Returns the hudReference for a given id.
* Returns the console instance for a given id.
*
* @param string aId
* @returns Object
*/
getHudReferenceById: function HS_getHudReferenceById(aId)
{
return aId in this.hudReferences ? this.hudReferences[aId] : null;
return this.consoles.get(aId);
},
/**
* Assign a function to this property to listen for every request that
* completes. Used by unit tests. The callback takes one argument: the HTTP
* activity object as received from the remote Web Console.
* Toggle the Web Console for the current tab.
*
* @type function
* @return object
* A promise for either the opening of the toolbox that holds the Web
* Console, or a Promise for the closing of the toolbox.
*/
lastFinishedRequestCallback: null,
toggleWebConsole: function HS_toggleWebConsole()
{
let window = this.currentContext();
let target = devtools.TargetFactory.forTab(window.gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
return toolbox && toolbox.currentToolId == "webconsole" ?
toolbox.destroy() :
gDevTools.showToolbox(target, "webconsole");
},
/**
* Find if there is a Web Console open for the current tab and return the
* instance.
* @return object|null
* The WebConsole object or null if the active tab has no open Web
* Console.
*/
getOpenWebConsole: function HS_getOpenWebConsole()
{
let tab = this.currentContext().gBrowser.selectedTab;
if (!tab || !devtools.TargetFactory.isKnownTab(tab)) {
return null;
}
let target = devtools.TargetFactory.forTab(tab);
let toolbox = gDevTools.getToolbox(target);
let panel = toolbox ? toolbox.getPanel("webconsole") : null;
return panel ? panel.hud : null;
},
/**
* Toggle the Browser Console.
*/
toggleBrowserConsole: function HS_toggleBrowserConsole()
{
if (this._browserConsoleID) {
let hud = this.getHudReferenceById(this._browserConsoleID);
return hud.destroy();
}
if (this._browserConsoleDefer) {
return this._browserConsoleDefer.promise;
}
this._browserConsoleDefer = promise.defer();
function connect()
{
let deferred = promise.defer();
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
let client = new DebuggerClient(DebuggerServer.connectPipe());
client.connect(() =>
client.listTabs((aResponse) => {
// Add Global Process debugging...
let globals = JSON.parse(JSON.stringify(aResponse));
delete globals.tabs;
delete globals.selected;
// ...only if there are appropriate actors (a 'from' property will
// always be there).
if (Object.keys(globals).length > 1) {
deferred.resolve({ form: globals, client: client, chrome: true });
} else {
deferred.reject("Global console not found!");
}
}));
return deferred.promise;
}
let target;
function getTarget(aConnection)
{
let options = {
form: aConnection.form,
client: aConnection.client,
chrome: true,
};
return devtools.TargetFactory.forRemoteTab(options);
}
function openWindow(aTarget)
{
target = aTarget;
let deferred = promise.defer();
let win = Services.ww.openWindow(null, devtools.Tools.webConsole.url, "_blank",
BROWSER_CONSOLE_WINDOW_FEATURES, null);
win.addEventListener("DOMContentLoaded", function onLoad() {
win.removeEventListener("DOMContentLoaded", onLoad);
// Set the correct Browser Console title.
let root = win.document.documentElement;
root.setAttribute("title", root.getAttribute("browserConsoleTitle"));
deferred.resolve(win);
});
return deferred.promise;
}
connect().then(getTarget).then(openWindow).then((aWindow) =>
this.openBrowserConsole(target, aWindow, aWindow)
.then((aBrowserConsole) => {
this._browserConsoleID = aBrowserConsole.hudId;
this._browserConsoleDefer.resolve(aBrowserConsole);
this._browserConsoleDefer = null;
}));
return this._browserConsoleDefer.promise;
},
/**
* Get the Browser Console instance, if open.
*
* @return object|null
* A BrowserConsole instance or null if the Browser Console is not
* open.
*/
getBrowserConsole: function HS_getBrowserConsole()
{
return this.getHudReferenceById(this._browserConsoleID);
},
};
@ -209,7 +310,7 @@ function WebConsole(aTarget, aIframeWindow, aChromeWindow)
this.browserWindow = HUDService.currentContext();
}
this.ui = new this.iframeWindow.WebConsoleFrame(this);
this.ui = new WebConsoleFrame(this);
}
WebConsole.prototype = {
@ -223,12 +324,13 @@ WebConsole.prototype = {
_destroyer: null,
/**
* Getter for HUDService.lastFinishedRequestCallback.
* Getter for a function to to listen for every request that completes. Used
* by unit tests. The callback takes one argument: the HTTP activity object as
* received from the remote Web Console.
*
* @see HUDService.lastFinishedRequestCallback
* @type function
*/
get lastFinishedRequestCallback() HUDService.lastFinishedRequestCallback,
get lastFinishedRequestCallback() HUDService.lastFinishedRequest.callback,
/**
* Getter for the xul:popupset that holds any popups we open.
@ -471,7 +573,7 @@ WebConsole.prototype = {
return this._destroyer.promise;
}
delete HUDService.hudReferences[this.hudId];
HUDService.consoles.delete(this.hudId);
this._destroyer = promise.defer();
@ -592,7 +694,7 @@ BrowserConsole.prototype = Heritage.extend(WebConsole.prototype,
let chromeWindow = this.chromeWindow;
this.$destroy().then(() =>
this.target.client.close(() => {
HeadsUpDisplayUICommands._browserConsoleID = null;
HUDService._browserConsoleID = null;
chromeWindow.close();
this._bc_destroyer.resolve(null);
}));
@ -601,144 +703,16 @@ BrowserConsole.prototype = Heritage.extend(WebConsole.prototype,
},
});
//////////////////////////////////////////////////////////////////////////
// HeadsUpDisplayUICommands
//////////////////////////////////////////////////////////////////////////
var HeadsUpDisplayUICommands = {
_browserConsoleID: null,
_browserConsoleDefer: null,
/**
* Toggle the Web Console for the current tab.
*
* @return object
* A promise for either the opening of the toolbox that holds the Web
* Console, or a promise for the closing of the toolbox.
*/
toggleHUD: function UIC_toggleHUD()
{
let window = HUDService.currentContext();
let target = devtools.TargetFactory.forTab(window.gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
return toolbox && toolbox.currentToolId == "webconsole" ?
toolbox.destroy() :
gDevTools.showToolbox(target, "webconsole");
},
/**
* Find if there is a Web Console open for the current tab and return the
* instance.
* @return object|null
* The WebConsole object or null if the active tab has no open Web
* Console.
*/
getOpenHUD: function UIC_getOpenHUD()
{
let tab = HUDService.currentContext().gBrowser.selectedTab;
if (!tab || !devtools.TargetFactory.isKnownTab(tab)) {
return null;
}
let target = devtools.TargetFactory.forTab(tab);
let toolbox = gDevTools.getToolbox(target);
let panel = toolbox ? toolbox.getPanel("webconsole") : null;
return panel ? panel.hud : null;
},
/**
* Toggle the Browser Console.
*/
toggleBrowserConsole: function UIC_toggleBrowserConsole()
{
if (this._browserConsoleID) {
let hud = HUDService.getHudReferenceById(this._browserConsoleID);
return hud.destroy();
}
if (this._browserConsoleDefer) {
return this._browserConsoleDefer.promise;
}
this._browserConsoleDefer = promise.defer();
function connect()
{
let deferred = promise.defer();
if (!DebuggerServer.initialized) {
DebuggerServer.init();
DebuggerServer.addBrowserActors();
}
let client = new DebuggerClient(DebuggerServer.connectPipe());
client.connect(() =>
client.listTabs((aResponse) => {
// Add Global Process debugging...
let globals = JSON.parse(JSON.stringify(aResponse));
delete globals.tabs;
delete globals.selected;
// ...only if there are appropriate actors (a 'from' property will
// always be there).
if (Object.keys(globals).length > 1) {
deferred.resolve({ form: globals, client: client, chrome: true });
} else {
deferred.reject("Global console not found!");
}
}));
return deferred.promise;
}
let target;
function getTarget(aConnection)
{
let options = {
form: aConnection.form,
client: aConnection.client,
chrome: true,
};
return devtools.TargetFactory.forRemoteTab(options);
}
function openWindow(aTarget)
{
target = aTarget;
let deferred = promise.defer();
let win = Services.ww.openWindow(null, devtools.Tools.webConsole.url, "_blank",
BROWSER_CONSOLE_WINDOW_FEATURES, null);
win.addEventListener("DOMContentLoaded", function onLoad() {
win.removeEventListener("DOMContentLoaded", onLoad);
// Set the correct Browser Console title.
let root = win.document.documentElement;
root.setAttribute("title", root.getAttribute("browserConsoleTitle"));
deferred.resolve(win);
});
return deferred.promise;
}
connect().then(getTarget).then(openWindow).then((aWindow) =>
HUDService.openBrowserConsole(target, aWindow, aWindow)
.then((aBrowserConsole) => {
this._browserConsoleID = aBrowserConsole.hudId;
this._browserConsoleDefer.resolve(aBrowserConsole);
this._browserConsoleDefer = null;
}));
return this._browserConsoleDefer.promise;
},
get browserConsole() {
return HUDService.getHudReferenceById(this._browserConsoleID);
},
};
const HUDService = new HUD_SERVICE();
(() => {
let methods = ["openWebConsole", "openBrowserConsole", "toggleWebConsole",
"toggleBrowserConsole", "getOpenWebConsole",
"getBrowserConsole", "getHudByWindow", "getHudReferenceById"];
for (let method of methods) {
exports[method] = HUDService[method].bind(HUDService);
}
exports.consoles = HUDService.consoles;
exports.lastFinishedRequest = HUDService.lastFinishedRequest;
})();

View File

@ -5,10 +5,3 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
TEST_DIRS += ['test']
EXTRA_JS_MODULES += [
'HUDService.jsm',
'NetworkPanel.jsm',
'WebConsolePanel.jsm',
]

View File

@ -6,28 +6,17 @@
"use strict";
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const {Cc, Ci, Cu} = require("chrome");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
loader.lazyGetter(this, "NetworkHelper", () => require("devtools/toolkit/webconsole/network-helper"));
loader.lazyImporter(this, "NetUtil", "resource://gre/modules/NetUtil.jsm");
loader.lazyServiceGetter(this, "mimeService", "@mozilla.org/mime;1", "nsIMIMEService");
XPCOMUtils.defineLazyServiceGetter(this, "mimeService", "@mozilla.org/mime;1",
"nsIMIMEService");
XPCOMUtils.defineLazyModuleGetter(this, "NetworkHelper",
"resource://gre/modules/devtools/NetworkHelper.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
let WebConsoleUtils = require("devtools/toolkit/webconsole/utils").Utils;
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
let l10n = new WebConsoleUtils.l10n(STRINGS_URI);
this.EXPORTED_SYMBOLS = ["NetworkPanel"];
/**
* Creates a new NetworkPanel.
@ -41,7 +30,6 @@ this.EXPORTED_SYMBOLS = ["NetworkPanel"];
* The parent WebConsoleFrame object that owns this network panel
* instance.
*/
this.NetworkPanel =
function NetworkPanel(aParent, aHttpActivity, aWebConsoleFrame)
{
let doc = aParent.ownerDocument;
@ -108,6 +96,7 @@ function NetworkPanel(aParent, aHttpActivity, aWebConsoleFrame)
aParent.appendChild(this.panel);
}
exports.NetworkPanel = NetworkPanel;
NetworkPanel.prototype =
{

View File

@ -4,29 +4,22 @@
"use strict";
this.EXPORTED_SYMBOLS = [ "WebConsolePanel" ];
const {Cc, Ci, Cu} = require("chrome");
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "promise",
"resource://gre/modules/commonjs/sdk/core/promise.js", "Promise");
XPCOMUtils.defineLazyModuleGetter(this, "HUDService",
"resource:///modules/HUDService.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
"resource:///modules/devtools/shared/event-emitter.js");
loader.lazyGetter(this, "promise", () => require("sdk/core/promise"));
loader.lazyGetter(this, "HUDService", () => require("devtools/webconsole/hudservice"));
loader.lazyGetter(this, "EventEmitter", () => require("devtools/shared/event-emitter"));
/**
* A DevToolPanel that controls the Web Console.
*/
function WebConsolePanel(iframeWindow, toolbox) {
function WebConsolePanel(iframeWindow, toolbox)
{
this._frameWindow = iframeWindow;
this._toolbox = toolbox;
EventEmitter.decorate(this);
}
exports.WebConsolePanel = WebConsolePanel;
WebConsolePanel.prototype = {
hud: null,

View File

@ -17,7 +17,6 @@ MOCHITEST_BROWSER_FILES = \
browser_webconsole_basic_net_logging.js \
browser_webconsole_bug_579412_input_focus.js \
browser_webconsole_bug_580001_closing_after_completion.js \
browser_webconsole_bug_580400_groups.js \
browser_webconsole_bug_588730_text_node_insertion.js \
browser_webconsole_bug_601667_filter_buttons.js \
browser_webconsole_bug_597136_external_script_errors.js \
@ -145,6 +144,7 @@ MOCHITEST_BROWSER_FILES = \
browser_console_variables_view_while_debugging_and_inspecting.js \
browser_webconsole_bug_686937_autocomplete_JSTerm_helpers.js \
browser_webconsole_cached_autocomplete.js \
browser_console_navigation_marker.js \
head.js \
$(NULL)

View File

@ -10,6 +10,9 @@ function test()
{
const TEST_URI = "data:text/html;charset=utf8,<title>bug871156</title>\n" +
"<p>hello world";
let firstTab = gBrowser.selectedTab;
Services.prefs.setBoolPref("browser.tabs.animate", false);
addTab(TEST_URI);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
@ -20,47 +23,61 @@ function test()
{
ok(hud, "Web Console opened");
let tabClosed = false, toolboxDestroyed = false;
let tabClosed = promise.defer();
let toolboxDestroyed = promise.defer();
let tabSelected = promise.defer();
let pageWindow = firstTab.linkedBrowser.contentWindow;
let toolbox = gDevTools.getToolbox(hud.target);
gBrowser.tabContainer.addEventListener("TabClose", function onTabClose() {
gBrowser.tabContainer.removeEventListener("TabClose", onTabClose);
info("tab closed");
tabClosed.resolve(null);
});
ok(true, "tab closed");
tabClosed = true;
if (toolboxDestroyed) {
testBrowserConsole();
gBrowser.tabContainer.addEventListener("TabSelect", function onTabSelect() {
gBrowser.tabContainer.removeEventListener("TabSelect", onTabSelect);
if (gBrowser.selectedTab == firstTab) {
info("tab selected");
tabSelected.resolve(null);
}
});
let toolbox = gDevTools.getToolbox(hud.target);
toolbox.once("destroyed", () => {
ok(true, "toolbox destroyed");
toolboxDestroyed = true;
if (tabClosed) {
testBrowserConsole();
}
info("toolbox destroyed");
toolboxDestroyed.resolve(null);
});
EventUtils.synthesizeKey("w", { accelKey: true }, hud.iframeWindow);
promise.all([tabClosed.promise, toolboxDestroyed.promise, tabSelected.promise ]).then(() => {
info("promise.all resolved");
waitForFocus(testBrowserConsole, pageWindow, true);
});
// Get out of the web console initialization.
executeSoon(() => {
EventUtils.synthesizeKey("w", { accelKey: true });
});
}
function testBrowserConsole()
{
info("test the Browser Console");
HUDConsoleUI.toggleBrowserConsole().then((hud) => {
HUDService.toggleBrowserConsole().then((hud) => {
ok(hud, "Browser Console opened");
Services.obs.addObserver(function onDestroy() {
Services.obs.removeObserver(onDestroy, "web-console-destroyed");
ok(true, "the Browser Console closed");
executeSoon(finishTest);
Services.prefs.clearUserPref("browser.tabs.animate");
waitForFocus(finish, content, true);
}, "web-console-destroyed", false);
EventUtils.synthesizeKey("w", { accelKey: true }, hud.iframeWindow);
waitForFocus(() => {
EventUtils.synthesizeKey("w", { accelKey: true }, hud.iframeWindow);
}, hud.iframeWindow);
});
}
}

View File

@ -9,16 +9,21 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/te
function test()
{
let oldFunction = HUDConsoleUI.toggleBrowserConsole;
let functionExecuted = false;
HUDConsoleUI.toggleBrowserConsole = () => functionExecuted = true;
Services.obs.addObserver(function observer(aSubject) {
Services.obs.removeObserver(observer, "web-console-created");
aSubject.QueryInterface(Ci.nsISupportsString);
let hud = HUDService.getBrowserConsole();
ok(hud, "browser console is open");
is(aSubject.data, hud.hudId, "notification hudId is correct");
executeSoon(() => consoleOpened(hud));
}, "web-console-created", false);
let hud = HUDService.getBrowserConsole();
ok(!hud, "browser console is not open");
info("wait for the browser console to open with ctrl-shift-j");
EventUtils.synthesizeKey("j", { accelKey: true, shiftKey: true }, content);
ok(functionExecuted,
"toggleBrowserConsole() was executed by the Ctrl-Shift-J key shortcut");
HUDConsoleUI.toggleBrowserConsole = oldFunction;
HUDConsoleUI.toggleBrowserConsole().then(consoleOpened);
}
function consoleOpened(hud)

View File

@ -24,7 +24,7 @@ function test()
{
ok(hud, "web console opened");
webconsole = hud;
HUDConsoleUI.toggleBrowserConsole().then(browserConsoleOpened);
HUDService.toggleBrowserConsole().then(browserConsoleOpened);
}
function browserConsoleOpened(hud)

View File

@ -13,7 +13,7 @@ function test()
let console = Cu.import("resource://gre/modules/devtools/Console.jsm", {}).console;
console.log("bug861338-log-cached");
HUDConsoleUI.toggleBrowserConsole().then(consoleOpened);
HUDService.toggleBrowserConsole().then(consoleOpened);
let hud = null;
function consoleOpened(aHud)

View File

@ -15,7 +15,7 @@ function test()
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
info("open the browser console");
HUDConsoleUI.toggleBrowserConsole().then(onBrowserConsoleOpen);
HUDService.toggleBrowserConsole().then(onBrowserConsoleOpen);
}, true);
function onBrowserConsoleOpen(aHud)

View File

@ -16,7 +16,7 @@ function test()
addTab(TEST_URI);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
HUDConsoleUI.toggleBrowserConsole().then(browserConsoleOpened);
HUDService.toggleBrowserConsole().then(browserConsoleOpened);
}, true);
function browserConsoleOpened(aHud)

View File

@ -45,7 +45,7 @@ function consoleOpened(hud)
function onWebConsoleClose()
{
info("web console closed");
HUDConsoleUI.toggleBrowserConsole().then(onBrowserConsoleOpen);
HUDService.toggleBrowserConsole().then(onBrowserConsoleOpen);
}
function onBrowserConsoleOpen(hud)

View File

@ -85,7 +85,7 @@ function consoleOpened(hud)
function onWebConsoleClose()
{
info("web console closed");
HUDConsoleUI.toggleBrowserConsole().then(onBrowserConsoleOpen);
HUDService.toggleBrowserConsole().then(onBrowserConsoleOpen);
}
function onBrowserConsoleOpen(hud)

View File

@ -54,16 +54,19 @@ function test()
"filter input is focused");
if (Services.appinfo.OS == "Darwin") {
ok(hud.ui.getFilterState("network"), "network category is enabled");
EventUtils.synthesizeKey("t", { ctrlKey: true });
ok(!hud.ui.getFilterState("network"), "accesskey for Network works");
EventUtils.synthesizeKey("t", { ctrlKey: true });
ok(hud.ui.getFilterState("network"), "accesskey for Network works (again)");
}
else {
EventUtils.synthesizeKey("N", { altKey: true });
let net = hud.ui.document.querySelector("toolbarbutton[category=net]");
is(hud.ui.document.activeElement, net,
"accesskey for Network category focuses the Net button");
}
let net = hud.ui.document.querySelector("toolbarbutton[category=net]");
is(hud.ui.document.activeElement, net,
"accesskey for Network category focuses the Net button");
finishTest();
}
}

View File

@ -0,0 +1,81 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Check that the navigation marker shows on page reload - bug 793996.
function test()
{
const PREF = "devtools.webconsole.persistlog";
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
let hud = null;
let Messages = require("devtools/webconsole/console-output").Messages;
Services.prefs.setBoolPref(PREF, true);
registerCleanupFunction(() => Services.prefs.clearUserPref(PREF));
addTab(TEST_URI);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
openConsole(null, consoleOpened);
}, true);
function consoleOpened(aHud)
{
hud = aHud;
ok(hud, "Web Console opened");
hud.jsterm.clearOutput();
content.console.log("foobarz1");
waitForMessages({
webconsole: hud,
messages: [{
text: "foobarz1",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
}],
}).then(onConsoleMessage);
}
function onConsoleMessage()
{
browser.addEventListener("load", onReload, true);
content.location.reload();
}
function onReload()
{
browser.removeEventListener("load", onReload, true);
content.console.log("foobarz2");
waitForMessages({
webconsole: hud,
messages: [{
name: "page reload",
text: "test-console.html",
category: CATEGORY_NETWORK,
severity: SEVERITY_LOG,
},
{
text: "foobarz2",
category: CATEGORY_WEBDEV,
severity: SEVERITY_LOG,
},
{
name: "navigation marker",
text: "test-console.html",
type: Messages.NavigationMarker,
}],
}).then(onConsoleMessageAfterReload);
}
function onConsoleMessageAfterReload()
{
isnot(hud.outputNode.textContent.indexOf("foobarz1"), -1,
"foobarz1 is still in the output");
finishTest();
}
}

View File

@ -51,7 +51,7 @@ function consoleOpened(hud)
function onWebConsoleClose()
{
info("web console closed");
HUDConsoleUI.toggleBrowserConsole().then(onBrowserConsoleOpen);
HUDService.toggleBrowserConsole().then(onBrowserConsoleOpen);
}
function onBrowserConsoleOpen(hud)

View File

@ -128,7 +128,7 @@ function test()
info("testBrowserConsole()");
closeConsole(privateTab, () => {
info("web console closed");
privateWindow.HUDConsoleUI.toggleBrowserConsole().then(onBrowserConsoleOpen);
privateWindow.HUDService.toggleBrowserConsole().then(onBrowserConsoleOpen);
});
}
@ -167,10 +167,10 @@ function test()
checkNoPrivateMessages();
info("close the browser console");
privateWindow.HUDConsoleUI.toggleBrowserConsole().then(() => {
privateWindow.HUDService.toggleBrowserConsole().then(() => {
info("reopen the browser console");
executeSoon(() =>
HUDConsoleUI.toggleBrowserConsole().then(onBrowserConsoleReopen));
HUDService.toggleBrowserConsole().then(onBrowserConsoleReopen));
});
});
privateWindow.BrowserTryToCloseWindow();

View File

@ -1,78 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Tests that console groups behave properly.
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console.html";
function test() {
addTab(TEST_URI);
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
openConsole(null, testGroups);
}, true);
}
function testGroups(HUD) {
let jsterm = HUD.jsterm;
let outputNode = HUD.outputNode;
jsterm.clearOutput();
// We test for one group by testing for zero "new" groups. The
// "webconsole-new-group" class creates a divider. Thus one group is
// indicated by zero new groups, two groups are indicated by one new group,
// and so on.
let waitForSecondMessage = {
name: "second console message",
validatorFn: function()
{
return outputNode.querySelectorAll(".webconsole-msg-output").length == 2;
},
successFn: function()
{
let timestamp1 = Date.now();
if (timestamp1 - timestamp0 < 5000) {
is(outputNode.querySelectorAll(".webconsole-new-group").length, 0,
"no group dividers exist after the second console message");
}
for (let i = 0; i < outputNode.itemCount; i++) {
outputNode.getItemAtIndex(i).timestamp = 0; // a "far past" value
}
jsterm.execute("2");
waitForSuccess(waitForThirdMessage);
},
failureFn: finishTest,
};
let waitForThirdMessage = {
name: "one group divider exists after the third console message",
validatorFn: function()
{
return outputNode.querySelectorAll(".webconsole-new-group").length == 1;
},
successFn: finishTest,
failureFn: finishTest,
};
let timestamp0 = Date.now();
jsterm.execute("0");
waitForSuccess({
name: "no group dividers exist after the first console message",
validatorFn: function()
{
return outputNode.querySelectorAll(".webconsole-new-group").length == 0;
},
successFn: function()
{
jsterm.execute("1");
waitForSuccess(waitForSecondMessage);
},
failureFn: finishTest,
});
}

View File

@ -6,45 +6,44 @@
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-585956-console-trace.html";
function test() {
addTab(TEST_URI);
addTab("data:text/html;charset=utf8,<p>hello");
browser.addEventListener("load", tabLoaded, true);
}
function tabLoaded() {
browser.removeEventListener("load", tabLoaded, true);
function tabLoaded() {
browser.removeEventListener("load", tabLoaded, true);
openConsole(null, function(hud) {
content.location.reload();
openConsole(null, function(hud) {
content.location = TEST_URI;
waitForSuccess({
name: "stacktrace message",
validatorFn: function()
{
return hud.outputNode.querySelector(".hud-log");
},
successFn: performChecks,
failureFn: finishTest,
waitForMessages({
webconsole: hud,
messages: [{
name: "console.trace output",
consoleTrace: {
file: "test-bug-585956-console-trace.html",
fn: "window.foobar585956c",
},
}],
}).then(performChecks);
});
});
}
function performChecks() {
// The expected stack trace object.
let stacktrace = [
{ filename: TEST_URI, lineNumber: 9, functionName: "window.foobar585956c", language: 2 },
{ filename: TEST_URI, lineNumber: 14, functionName: "foobar585956b", language: 2 },
{ filename: TEST_URI, lineNumber: 18, functionName: "foobar585956a", language: 2 },
{ filename: TEST_URI, lineNumber: 21, functionName: null, language: 2 }
];
let hudId = HUDService.getHudIdByWindow(content);
let HUD = HUDService.hudReferences[hudId];
let node = HUD.outputNode.querySelector(".hud-log");
ok(node, "found trace log node");
ok(node._stacktrace, "found stacktrace object");
is(node._stacktrace.toSource(), stacktrace.toSource(), "stacktrace is correct");
isnot(node.textContent.indexOf("bug-585956"), -1, "found file name");
finishTest();
}
function performChecks(results) {
let node = [...results[0].matched][0];
// The expected stack trace object.
let stacktrace = [
{ filename: TEST_URI, lineNumber: 9, functionName: "window.foobar585956c", language: 2 },
{ filename: TEST_URI, lineNumber: 14, functionName: "foobar585956b", language: 2 },
{ filename: TEST_URI, lineNumber: 18, functionName: "foobar585956a", language: 2 },
{ filename: TEST_URI, lineNumber: 21, functionName: null, language: 2 }
];
ok(node, "found trace log node");
ok(node._stacktrace, "found stacktrace object");
is(node._stacktrace.toSource(), stacktrace.toSource(), "stacktrace is correct");
isnot(node.textContent.indexOf("bug-585956"), -1, "found file name");
finishTest();
}
}

View File

@ -25,33 +25,34 @@ function tabLoaded(aEvent) {
function tabReloaded(aEvent) {
gBrowser.selectedBrowser.removeEventListener(aEvent.type, tabReloaded, true);
let hudId = HUDService.getHudIdByWindow(content);
let HUD = HUDService.hudReferences[hudId];
let HUD = HUDService.getHudByWindow(content);
ok(HUD, "Web Console is open");
waitForSuccess({
name: "error message displayed",
validatorFn: function() {
return HUD.outputNode.textContent.indexOf("fooBug597756_error") > -1;
},
successFn: function() {
if (newTabIsOpen) {
finishTest();
return;
}
closeConsole(gBrowser.selectedTab, function() {
gBrowser.removeCurrentTab();
waitForMessages({
webconsole: HUD,
messages: [{
name: "error message displayed",
text: "fooBug597756_error",
category: CATEGORY_JS,
severity: SEVERITY_ERROR,
}],
}).then(() => {
if (newTabIsOpen) {
finishTest();
return;
}
let newTab = gBrowser.addTab();
gBrowser.selectedTab = newTab;
closeConsole(gBrowser.selectedTab, () => {
gBrowser.removeCurrentTab();
newTabIsOpen = true;
gBrowser.selectedBrowser.addEventListener("load", tabLoaded, true);
expectUncaughtException();
content.location = TEST_URI;
});
},
failureFn: finishTest,
let newTab = gBrowser.addTab();
gBrowser.selectedTab = newTab;
newTabIsOpen = true;
gBrowser.selectedBrowser.addEventListener("load", tabLoaded, true);
expectUncaughtException();
content.location = TEST_URI;
});
});
}

View File

@ -53,7 +53,7 @@ function performTest(aRequest, aConsole)
executeSoon(finishTest);
});
HUDService.lastFinishedRequestCallback = null;
HUDService.lastFinishedRequest.callback = null;
}
function test()
@ -63,7 +63,7 @@ function test()
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
openConsole(null, () => {
HUDService.lastFinishedRequestCallback = performTest;
HUDService.lastFinishedRequest.callback = performTest;
browser.addEventListener("load", function onReload() {
browser.removeEventListener("load", onReload, true);

View File

@ -13,7 +13,7 @@ const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/te
function performTest(lastFinishedRequest, aConsole)
{
ok(lastFinishedRequest, "charset test page was loaded and logged");
HUDService.lastFinishedRequestCallback = null;
HUDService.lastFinishedRequest.callback = null;
executeSoon(() => {
aConsole.webConsoleClient.getResponseContent(lastFinishedRequest.actor,
@ -27,7 +27,7 @@ function performTest(lastFinishedRequest, aConsole)
isnot(body.indexOf("<p>" + chars + "</p>"), -1,
"found the chinese simplified string");
HUDService.lastFinishedRequestCallback = null;
HUDService.lastFinishedRequest.callback = null;
executeSoon(finishTest);
});
});
@ -45,7 +45,7 @@ function test()
ok(hud.ui._saveRequestAndResponseBodies,
"The saveRequestAndResponseBodies property was successfully set.");
HUDService.lastFinishedRequestCallback = performTest;
HUDService.lastFinishedRequest.callback = performTest;
content.location = TEST_URI;
});
});

View File

@ -10,44 +10,9 @@
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-601177-log-levels.html";
function performTest()
{
let hudId = HUDService.getHudIdByWindow(content);
let HUD = HUDService.hudReferences[hudId];
findEntry(HUD, "hud-networkinfo", "test-bug-601177-log-levels.html",
"found test-bug-601177-log-levels.html");
findEntry(HUD, "hud-networkinfo", "test-bug-601177-log-levels.js",
"found test-bug-601177-log-levels.js");
findEntry(HUD, "hud-networkinfo", "test-image.png", "found test-image.png");
findEntry(HUD, "hud-network", "foobar-known-to-fail.png",
"found foobar-known-to-fail.png");
findEntry(HUD, "hud-exception", "foobarBug601177exception",
"found exception");
findEntry(HUD, "hud-jswarn", "undefinedPropertyBug601177",
"found strict warning");
findEntry(HUD, "hud-jswarn", "foobarBug601177strictError",
"found strict error");
executeSoon(finishTest);
}
function findEntry(aHUD, aClass, aString, aMessage)
{
return testLogEntry(aHUD.outputNode, aString, aMessage, false, false,
aClass);
}
function test()
{
Services.prefs.setBoolPref("javascript.options.strict", true);
registerCleanupFunction(function() {
Services.prefs.clearUserPref("javascript.options.strict");
});
@ -56,27 +21,55 @@ function test()
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
openConsole(null, function(hud) {
browser.addEventListener("load", function onLoad2() {
browser.removeEventListener("load", onLoad2, true);
waitForSuccess({
name: "all messages displayed",
validatorFn: function()
{
return hud.outputNode.itemCount >= 7;
},
successFn: performTest,
failureFn: function() {
info("itemCount: " + hud.outputNode.itemCount);
finishTest();
},
});
}, true);
expectUncaughtException();
content.location = TEST_URI;
});
openConsole(null, consoleOpened);
}, true);
}
function consoleOpened(hud)
{
expectUncaughtException();
content.location = TEST_URI;
info("waiting for messages");
waitForMessages({
webconsole: hud,
messages: [
{
text: "test-bug-601177-log-levels.html",
category: CATEGORY_NETWORK,
severity: SEVERITY_LOG,
},
{
text: "test-bug-601177-log-levels.js",
category: CATEGORY_NETWORK,
severity: SEVERITY_LOG,
},
{
text: "test-image.png",
category: CATEGORY_NETWORK,
severity: SEVERITY_LOG,
},
{
text: "foobar-known-to-fail.png",
category: CATEGORY_NETWORK,
severity: SEVERITY_ERROR,
},
{
text: "foobarBug601177exception",
category: CATEGORY_JS,
severity: SEVERITY_ERROR,
},
{
text: "undefinedPropertyBug601177",
category: CATEGORY_JS,
severity: SEVERITY_WARNING,
},
{
text: "foobarBug601177strictError",
category: CATEGORY_JS,
severity: SEVERITY_WARNING,
},
],
}).then(finishTest);
}
}

View File

@ -43,8 +43,7 @@ function startTest()
{
// Find the relevant elements in the Web Console of tab 2.
let win2 = tabs[runCount*2 + 1].linkedBrowser.contentWindow;
let hudId2 = HUDService.getHudIdByWindow(win2);
huds[1] = HUDService.hudReferences[hudId2];
huds[1] = HUDService.getHudByWindow(win2);
info("startTest: iframe2 root height " + huds[1].ui.rootElement.clientHeight);
if (runCount == 0) {
@ -101,8 +100,7 @@ function testpopup2b(aEvent) {
waitForFocus(function() {
// Find the relevant elements in the Web Console of tab 1.
let win1 = tabs[runCount*2].linkedBrowser.contentWindow;
let hudId1 = HUDService.getHudIdByWindow(win1);
huds[0] = HUDService.hudReferences[hudId1];
huds[0] = HUDService.getHudByWindow(win1);
info("iframe1 root height " + huds[0].ui.rootElement.clientHeight);

View File

@ -3,68 +3,29 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Tests that network log messages bring up the network panel.
// Tests that we report JS exceptions in event handlers coming from
// network requests, like onreadystate for XHR. See bug 618078.
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-bug-618078-network-exceptions.html";
let testEnded = false;
let TestObserver = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
observe: function test_observe(aSubject)
{
if (testEnded || !(aSubject instanceof Ci.nsIScriptError)) {
return;
}
is(aSubject.category, "content javascript", "error category");
testEnded = true;
if (aSubject.category == "content javascript") {
executeSoon(checkOutput);
}
else {
executeSoon(finishTest);
}
}
};
function checkOutput()
{
waitForSuccess({
name: "exception message",
validatorFn: function()
{
return hud.outputNode.textContent.indexOf("bug618078exception") > -1;
},
successFn: finishTest,
failureFn: finishTest,
});
}
function testEnd()
{
Services.console.unregisterListener(TestObserver);
}
function test()
{
addTab("data:text/html;charset=utf-8,Web Console test for bug 618078");
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
openConsole(null, function(hud) {
expectUncaughtException();
content.location = TEST_URI;
openConsole(null, function(aHud) {
hud = aHud;
Services.console.registerListener(TestObserver);
registerCleanupFunction(testEnd);
executeSoon(function() {
expectUncaughtException();
content.location = TEST_URI;
});
waitForMessages({
webconsole: hud,
messages: [{
text: "bug618078exception",
category: CATEGORY_JS,
severity: SEVERITY_ERROR,
}],
}).then(finishTest);
});
}, true);
}

View File

@ -25,12 +25,11 @@ function test() {
}, true);
}
function performTest() {
let hudId = HUDService.getHudIdByWindow(content);
let HUD = HUDService.hudReferences[hudId];
function performTest(results) {
let HUD = HUDService.getHudByWindow(content);
let networkMessage = HUD.outputNode.querySelector(".webconsole-msg-network");
ok(networkMessage, "found network message");
let networkMessage = [...results[0].matched][0];
ok(networkMessage, "network message element");
let networkLink = networkMessage.querySelector(".webconsole-msg-link");
ok(networkLink, "found network message link");
@ -46,7 +45,7 @@ function performTest() {
popupsShown++;
executeSoon(function() {
let popups = popupset.querySelectorAll("panel[hudId=" + hudId + "]");
let popups = popupset.querySelectorAll("panel[hudId=" + HUD.hudId + "]");
is(popups.length, 1, "found one popup");
document.addEventListener("popuphidden", onpopuphidden, false);
@ -67,7 +66,7 @@ function performTest() {
hiddenPopups++;
executeSoon(function() {
let popups = popupset.querySelectorAll("panel[hudId=" + hudId + "]");
let popups = popupset.querySelectorAll("panel[hudId=" + HUD.hudId + "]");
is(popups.length, 0, "no popups found");
executeSoon(finishTest);

View File

@ -25,7 +25,7 @@ function consoleOpened(hud)
ok(hud.ui._saveRequestAndResponseBodies,
"The saveRequestAndResponseBodies property was successfully set.");
HUDService.lastFinishedRequestCallback = requestDoneCallback;
HUDService.lastFinishedRequest.callback = requestDoneCallback;
waitForSuccess(waitForResponses);
content.location = TEST_URI;
});
@ -44,7 +44,7 @@ function consoleOpened(hud)
function getHeaders()
{
HUDService.lastFinishedRequestCallback = null;
HUDService.lastFinishedRequest.callback = null;
ok("301" in lastFinishedRequests, "request 1: 301 Moved Permanently");
ok("404" in lastFinishedRequests, "request 2: 404 Not found");

View File

@ -14,11 +14,8 @@ function test() {
}
function consoleOpened(HUD) {
let tmp = {};
Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tmp);
let WCU = tmp.WebConsoleUtils;
let JSPropertyProvider = tmp.JSPropertyProvider;
tmp = null;
let tools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
let JSPropertyProvider = tools.require("devtools/toolkit/webconsole/utils").JSPropertyProvider;
let jsterm = HUD.jsterm;
let win = content.wrappedJSObject;

View File

@ -28,7 +28,7 @@ function test()
openConsole(null, function(aHud) {
hud = aHud;
HUDService.lastFinishedRequestCallback = function(aRequest) {
HUDService.lastFinishedRequest.callback = function(aRequest) {
lastRequest = aRequest;
if (requestCallback) {
requestCallback();
@ -124,12 +124,20 @@ function testFormSubmission()
// There should be 3 network requests pointing to the HTML file.
waitForMessages({
webconsole: hud,
messages: [{
text: "test-network-request.html",
category: CATEGORY_NETWORK,
severity: SEVERITY_LOG,
count: 3,
}],
messages: [
{
text: "test-network-request.html",
category: CATEGORY_NETWORK,
severity: SEVERITY_LOG,
count: 3,
},
{
text: "test-data.json",
category: CATEGORY_NETWORK,
severity: SEVERITY_LOG,
count: 2,
},
],
}).then(testLiveFilteringOnSearchStrings);
};
@ -170,7 +178,7 @@ function testLiveFilteringOnSearchStrings() {
is(countMessageNodes(), 0, "the log nodes are hidden when searching for " +
"the string \"foo\"bar'baz\"boo'\"");
HUDService.lastFinishedRequestCallback = null;
HUDService.lastFinishedRequest.callback = null;
lastRequest = null;
requestCallback = null;
finishTest();

View File

@ -22,11 +22,6 @@ function consoleOpened(aHud) {
let popup = jsterm.autocompletePopup;
let completeNode = jsterm.completeNode;
let tmp = {};
Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tmp);
let WCU = tmp.WebConsoleUtils;
tmp = null;
ok(!popup.isOpen, "popup is not open");
popup._panel.addEventListener("popupshown", function onShown() {

View File

@ -84,46 +84,29 @@ function performWebConsoleTests(hud)
outputNode = hud.outputNode;
jsterm.clearOutput();
jsterm.execute("$0");
jsterm.execute("$0", onNodeOutput);
waitForSuccess({
name: "$0 output",
validatorFn: function()
{
return outputNode.querySelector(".webconsole-msg-output");
},
successFn: function()
{
let node = outputNode.querySelector(".webconsole-msg-output");
isnot(node.textContent.indexOf("[object HTMLHeadingElement"), -1,
"correct output for $0");
function onNodeOutput()
{
let node = outputNode.querySelector(".webconsole-msg-output");
isnot(node.textContent.indexOf("[object HTMLHeadingElement"), -1,
"correct output for $0");
jsterm.clearOutput();
jsterm.execute("$0.textContent = 'bug653531'");
waitForSuccess(waitForNodeUpdate);
},
failureFn: finishUp,
});
jsterm.clearOutput();
jsterm.execute("$0.textContent = 'bug653531'", onNodeUpdate);
}
let waitForNodeUpdate = {
name: "$0.textContent update",
validatorFn: function()
{
return outputNode.querySelector(".webconsole-msg-output");
},
successFn: function()
{
let node = outputNode.querySelector(".webconsole-msg-output");
isnot(node.textContent.indexOf("bug653531"), -1,
"correct output for $0.textContent");
let inspector = gDevTools.getToolbox(target).getPanel("inspector");
is(inspector.selection.node.textContent, "bug653531",
"node successfully updated");
function onNodeUpdate()
{
let node = outputNode.querySelector(".webconsole-msg-output");
isnot(node.textContent.indexOf("bug653531"), -1,
"correct output for $0.textContent");
let inspector = gDevTools.getToolbox(target).getPanel("inspector");
is(inspector.selection.node.textContent, "bug653531",
"node successfully updated");
executeSoon(finishUp);
},
failureFn: finishUp,
};
executeSoon(finishUp);
}
}
function finishUp() {

View File

@ -59,8 +59,7 @@ function testTimerIndependenceInTabs(hud) {
}
function testTimerIndependenceInSameTab() {
let hudId = HUDService.getHudIdByWindow(content);
let hud = HUDService.hudReferences[hudId];
let hud = HUDService.getHudByWindow(content);
outputNode = hud.outputNode;
waitForSuccess({
@ -87,8 +86,7 @@ function testTimerIndependenceInSameTab() {
}
function testTimerIndependenceInSameTabAgain() {
let hudId = HUDService.getHudIdByWindow(content);
let hud = HUDService.hudReferences[hudId];
let hud = HUDService.getHudByWindow(content);
outputNode = hud.outputNode;
executeSoon(function() {

View File

@ -32,7 +32,7 @@ function test()
openConsole(null, function(aHud) {
hud = aHud;
HUDService.lastFinishedRequestCallback = requestCallbackWrapper;
HUDService.lastFinishedRequest.callback = requestCallbackWrapper;
executeSoon(testPageLoad);
});
@ -204,7 +204,7 @@ function testNetworkPanel()
// All tests are done. Shutdown.
networkPanel.panel.hidePopup();
lastRequest = null;
HUDService.lastFinishedRequestCallback = null;
HUDService.lastFinishedRequest.callback = null;
executeSoon(finishTest);
}, true);
}

View File

@ -14,14 +14,14 @@ function test() {
function webConsoleCreated(aID)
{
Services.obs.removeObserver(observer, "web-console-created");
ok(HUDService.hudReferences[aID], "We have a hud reference");
ok(HUDService.getHudReferenceById(aID), "We have a hud reference");
content.wrappedJSObject.console.log("adding a log message");
}
function webConsoleDestroyed(aID)
{
Services.obs.removeObserver(observer, "web-console-destroyed");
ok(!HUDService.hudReferences[aID], "We do not have a hud reference");
ok(!HUDService.getHudReferenceById(aID), "We do not have a hud reference");
executeSoon(finishTest);
}
@ -43,10 +43,10 @@ let observer = {
switch(aTopic) {
case "web-console-created":
webConsoleCreated(aSubject);
webConsoleCreated(aSubject.data);
break;
case "web-console-destroyed":
webConsoleDestroyed(aSubject);
webConsoleDestroyed(aSubject.data);
break;
case "web-console-message-created":
webConsoleMessage(aSubject, aData);

View File

@ -15,11 +15,8 @@ function test() {
function testPropertyProvider() {
browser.removeEventListener("load", testPropertyProvider, true);
let tmp = {};
Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tmp);
let JSPropertyProvider = tmp.JSPropertyProvider;
tmp = null;
let tools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
let JSPropertyProvider = tools.require("devtools/toolkit/webconsole/utils").JSPropertyProvider;
let completion = JSPropertyProvider(content, "thisIsNotDefined");
is (completion.matches.length, 0, "no match for 'thisIsNotDefined");

View File

@ -3,18 +3,19 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
let tempScope = {};
Cu.import("resource:///modules/HUDService.jsm", tempScope);
let HUDService = tempScope.HUDService;
Cu.import("resource://gre/modules/devtools/WebConsoleUtils.jsm", tempScope);
let WebConsoleUtils = tempScope.WebConsoleUtils;
Cu.import("resource:///modules/devtools/gDevTools.jsm", tempScope);
let gDevTools = tempScope.gDevTools;
Cu.import("resource://gre/modules/devtools/Loader.jsm", tempScope);
let TargetFactory = tempScope.devtools.TargetFactory;
Components.utils.import("resource://gre/modules/devtools/Console.jsm", tempScope);
let console = tempScope.console;
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
let WebConsoleUtils, gDevTools, TargetFactory, console, promise, require;
(() => {
gDevTools = Cu.import("resource:///modules/devtools/gDevTools.jsm", {}).gDevTools;
console = Cu.import("resource://gre/modules/devtools/Console.jsm", {}).console;
promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
let tools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
let utils = tools.require("devtools/toolkit/webconsole/utils");
TargetFactory = tools.TargetFactory;
WebConsoleUtils = utils.Utils;
require = tools.require;
})();
// promise._reportErrors = true; // please never leave me.
let gPendingOutputTest = 0;
@ -243,7 +244,7 @@ function dumpConsoles()
{
if (gPendingOutputTest) {
console.log("dumpConsoles start");
for each (let hud in HUDService.hudReferences) {
for (let hud of HUDService.consoles) {
if (!hud.outputNode) {
console.debug("no output content for", hud.hudId);
continue;
@ -289,14 +290,12 @@ function finishTest()
dumpConsoles();
if (HUDConsoleUI.browserConsole) {
let hud = HUDConsoleUI.browserConsole;
if (hud.jsterm) {
hud.jsterm.clearOutput(true);
let browserConsole = HUDService.getBrowserConsole();
if (browserConsole) {
if (browserConsole.jsterm) {
browserConsole.jsterm.clearOutput(true);
}
HUDConsoleUI.toggleBrowserConsole().then(finishTest);
HUDService.toggleBrowserConsole().then(finishTest);
return;
}
@ -319,8 +318,8 @@ function tearDown()
{
dumpConsoles();
if (HUDConsoleUI.browserConsole) {
HUDConsoleUI.toggleBrowserConsole();
if (HUDService.getBrowserConsole()) {
HUDService.toggleBrowserConsole();
}
let target = TargetFactory.forTab(gBrowser.selectedTab);
@ -886,6 +885,9 @@ function getMessageElementText(aElement)
* message.
* - longString: boolean, set to |true} to match long strings in the
* message.
* - type: match messages that are instances of the given object. For
* example, you can point to Messages.NavigationMarker to match any
* such message.
* - objects: boolean, set to |true| if you expect inspectable
* objects in the message.
* - source: object that can hold one property: url. This is used to
@ -1065,8 +1067,25 @@ function waitForMessages(aOptions)
return false;
}
if (aRule.type) {
// The rule tries to match the newer types of messages, based on their
// object constructor.
if (!aElement._messageObject ||
!(aElement._messageObject instanceof aRule.type)) {
return false;
}
}
else if (aElement._messageObject) {
// If the message element holds a reference to its object, it means this
// is a newer message type. All of the older waitForMessages() rules do
// not expect this kind of messages. We return false here.
// TODO: we keep this behavior until bug 778766 is fixed. After that we
// will not require |type| to match newer types of messages.
return false;
}
let partialMatch = !!(aRule.consoleTrace || aRule.consoleTime ||
aRule.consoleTimeEnd);
aRule.consoleTimeEnd || aRule.type);
if (aRule.category && aElement.category != aRule.category) {
if (partialMatch) {

View File

@ -6,45 +6,29 @@
"use strict";
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const {Cc, Ci, Cu} = require("chrome");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
let WebConsoleUtils = require("devtools/toolkit/webconsole/utils").Utils;
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
"@mozilla.org/widget/clipboardhelper;1",
"nsIClipboardHelper");
XPCOMUtils.defineLazyModuleGetter(this, "GripClient",
"resource://gre/modules/devtools/dbg-client.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NetworkPanel",
"resource:///modules/NetworkPanel.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AutocompletePopup",
"resource:///modules/devtools/AutocompletePopup.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "WebConsoleUtils",
"resource://gre/modules/devtools/WebConsoleUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "promise",
"resource://gre/modules/commonjs/sdk/core/promise.js", "Promise");
XPCOMUtils.defineLazyModuleGetter(this, "VariablesView",
"resource:///modules/devtools/VariablesView.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "VariablesViewController",
"resource:///modules/devtools/VariablesViewController.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
"resource:///modules/devtools/shared/event-emitter.js");
XPCOMUtils.defineLazyModuleGetter(this, "devtools",
"resource://gre/modules/devtools/Loader.jsm");
loader.lazyServiceGetter(this, "clipboardHelper",
"@mozilla.org/widget/clipboardhelper;1",
"nsIClipboardHelper");
loader.lazyImporter(this, "Services", "resource://gre/modules/Services.jsm");
loader.lazyGetter(this, "promise", () => require("sdk/core/promise"));
loader.lazyGetter(this, "EventEmitter", () => require("devtools/shared/event-emitter"));
loader.lazyGetter(this, "AutocompletePopup",
() => require("devtools/shared/autocomplete-popup").AutocompletePopup);
loader.lazyGetter(this, "ToolSidebar",
() => require("devtools/framework/sidebar").ToolSidebar);
loader.lazyGetter(this, "NetworkPanel",
() => require("devtools/webconsole/network-panel").NetworkPanel);
loader.lazyGetter(this, "ConsoleOutput",
() => require("devtools/webconsole/console-output").ConsoleOutput);
loader.lazyGetter(this, "Messages",
() => require("devtools/webconsole/console-output").Messages);
loader.lazyImporter(this, "GripClient", "resource://gre/modules/devtools/dbg-client.jsm");
loader.lazyImporter(this, "VariablesView", "resource:///modules/devtools/VariablesView.jsm");
loader.lazyImporter(this, "VariablesViewController", "resource:///modules/devtools/VariablesViewController.jsm");
const STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
let l10n = new WebConsoleUtils.l10n(STRINGS_URI);
@ -191,6 +175,7 @@ const PREF_PERSISTLOG = "devtools.webconsole.persistlog";
* The WebConsoleFrame is responsible for the actual Web Console UI
* implementation.
*
* @constructor
* @param object aWebConsoleOwner
* The WebConsole owner object.
*/
@ -198,6 +183,7 @@ function WebConsoleFrame(aWebConsoleOwner)
{
this.owner = aWebConsoleOwner;
this.hudId = this.owner.hudId;
this.window = this.owner.iframeWindow;
this._repeatNodes = {};
this._outputQueue = [];
@ -205,6 +191,8 @@ function WebConsoleFrame(aWebConsoleOwner)
this._networkRequests = {};
this.filterPrefs = {};
this.output = new ConsoleOutput(this);
this._toggleFilter = this._toggleFilter.bind(this);
this._flushMessageQueue = this._flushMessageQueue.bind(this);
@ -213,11 +201,12 @@ function WebConsoleFrame(aWebConsoleOwner)
EventEmitter.decorate(this);
}
exports.WebConsoleFrame = WebConsoleFrame;
WebConsoleFrame.prototype = {
/**
* The WebConsole instance that owns this frame.
* @see HUDService.jsm::WebConsole
* @see hudservice.js::WebConsole
* @type object
*/
owner: null,
@ -341,6 +330,12 @@ WebConsoleFrame.prototype = {
*/
outputNode: null,
/**
* The ConsoleOutput instance that manages all output.
* @type object
*/
output: null,
/**
* The input element that allows the user to filter messages by string.
* @type nsIDOMElement
@ -471,9 +466,6 @@ WebConsoleFrame.prototype = {
*/
_initUI: function WCF__initUI()
{
// Remember that this script is loaded in the webconsole.xul context:
// |window| is the iframe global.
this.window = window;
this.document = this.window.document;
this.rootElement = this.document.documentElement;
@ -483,6 +475,8 @@ WebConsoleFrame.prototype = {
this._commandController = new CommandController(this);
this.window.controllers.insertControllerAt(0, this._commandController);
this._contextMenuHandler = new ConsoleContextMenu(this);
let doc = this.document;
this.filterBox = doc.querySelector(".hud-filter-box");
@ -626,6 +620,12 @@ WebConsoleFrame.prototype = {
let jslog = this.document.querySelector("menuitem[prefKey=jslog]");
jslog.hidden = true;
}
if (Services.appinfo.OS == "Darwin") {
let net = this.document.querySelector("toolbarbutton[category=net]");
let accesskey = net.getAttribute("accesskeyMacOSX");
net.setAttribute("accesskey", accesskey);
}
},
/**
@ -842,8 +842,6 @@ WebConsoleFrame.prototype = {
node.classList.add("hud-filtered-by-type");
}
}
this.regroupOutput();
},
/**
@ -870,8 +868,6 @@ WebConsoleFrame.prototype = {
node.classList.add("hud-filtered-by-string");
}
}
this.regroupOutput();
},
/**
@ -1762,6 +1758,35 @@ WebConsoleFrame.prototype = {
}
},
/**
* Handler for the tabNavigated notification.
*
* @param string aEvent
* Event name.
* @param object aPacket
* Notification packet received from the server.
*/
handleTabNavigated: function WCF_handleTabNavigated(aEvent, aPacket)
{
if (aEvent == "will-navigate") {
if (this.persistLog) {
let marker = new Messages.NavigationMarker(aPacket.url, Date.now());
this.output.addMessage(marker);
}
else {
this.jsterm.clearOutput();
}
}
if (aPacket.url) {
this.onLocationChange(aPacket.url, aPacket.title);
}
if (aEvent == "navigate" && !aPacket.nativeConsoleAPI) {
this.logWarningAboutReplacedAPI();
}
},
/**
* Output a message node. This filters a node appropriately, then sends it to
* the output, regrouping and pruning output as necessary.
@ -1875,11 +1900,6 @@ WebConsoleFrame.prototype = {
this._pruneCategoriesQueue = {};
}
// Regroup messages at the end of the queue.
if (!this._outputQueue.length) {
this.regroupOutput();
}
let isInputOutput = lastVisibleNode &&
(lastVisibleNode.classList.contains("webconsole-msg-input") ||
lastVisibleNode.classList.contains("webconsole-msg-output"));
@ -2148,29 +2168,6 @@ WebConsoleFrame.prototype = {
}
},
/**
* Splits the given console messages into groups based on their timestamps.
*/
regroupOutput: function WCF_regroupOutput()
{
// Go through the nodes and adjust the placement of "webconsole-new-group"
// classes.
let nodes = this.outputNode.querySelectorAll(".hud-msg-node" +
":not(.hud-filtered-by-string):not(.hud-filtered-by-type)");
let lastTimestamp;
for (let i = 0, n = nodes.length; i < n; i++) {
let thisTimestamp = nodes[i].timestamp;
if (lastTimestamp != null &&
thisTimestamp >= lastTimestamp + NEW_GROUP_DELAY) {
nodes[i].classList.add("webconsole-new-group");
}
else {
nodes[i].classList.remove("webconsole-new-group");
}
lastTimestamp = thisTimestamp;
}
},
/**
* Given a category and message body, creates a DOM node to represent an
* incoming message. The timestamp is automatically added.
@ -2634,7 +2631,6 @@ WebConsoleFrame.prototype = {
// Gather up the selected items and concatenate their clipboard text.
let strings = [];
let newGroup = false;
let children = this.outputNode.children;
@ -2644,21 +2640,10 @@ WebConsoleFrame.prototype = {
continue;
}
// Add dashes between groups so that group boundaries show up in the
// copied output.
if (i > 0 && item.classList.contains("webconsole-new-group")) {
newGroup = true;
}
// Ensure the selected item hasn't been filtered by type or string.
if (!item.classList.contains("hud-filtered-by-type") &&
!item.classList.contains("hud-filtered-by-string")) {
let timestampString = l10n.timestampString(item.timestamp);
if (newGroup) {
strings.push("--");
newGroup = false;
}
if (aOptions.linkOnly) {
strings.push(item.url);
}
@ -2753,6 +2738,13 @@ WebConsoleFrame.prototype = {
this.jsterm.destroy();
this.jsterm = null;
}
this.output.destroy();
this.output = null;
if (this._contextMenuHandler) {
this._contextMenuHandler.destroy();
this._contextMenuHandler = null;
}
this._commandController = null;
@ -3288,7 +3280,6 @@ JSTerm.prototype = {
_createSidebar: function JST__createSidebar()
{
let tabbox = this.hud.document.querySelector("#webconsole-sidebar");
let ToolSidebar = devtools.require("devtools/framework/sidebar").ToolSidebar;
this.sidebar = new ToolSidebar(tabbox, this, "webconsole");
this.sidebar.show();
},
@ -4990,17 +4981,7 @@ WebConsoleConnectionProxy.prototype = {
return;
}
if (aEvent == "will-navigate" && !this.owner.persistLog) {
this.owner.jsterm.clearOutput();
}
if (aPacket.url) {
this.owner.onLocationChange(aPacket.url, aPacket.title);
}
if (aEvent == "navigate" && !aPacket.nativeConsoleAPI) {
this.owner.logWarningAboutReplacedAPI();
}
this.owner.handleTabNavigated(aEvent, aPacket);
},
/**
@ -5063,40 +5044,35 @@ function gSequenceId()
gSequenceId.n = 0;
function goUpdateConsoleCommands() {
goUpdateCommand("consoleCmd_openURL");
goUpdateCommand("consoleCmd_copyURL");
}
///////////////////////////////////////////////////////////////////////////////
// Context Menu
///////////////////////////////////////////////////////////////////////////////
const CONTEXTMENU_ID = "output-contextmenu";
/*
* ConsoleContextMenu: This handle to show/hide a context menu item.
* ConsoleContextMenu this used to handle the visibility of context menu items.
*
* @constructor
* @param object aOwner
* The WebConsoleFrame instance that owns this object.
*/
let ConsoleContextMenu = {
function ConsoleContextMenu(aOwner)
{
this.owner = aOwner;
this.popup = this.owner.document.getElementById("output-contextmenu");
this.build = this.build.bind(this);
this.popup.addEventListener("popupshowing", this.build);
}
ConsoleContextMenu.prototype = {
/*
* Handle to show/hide context menu item.
*
* @param nsIDOMEvent aEvent
*/
build: function CCM_build(aEvent)
{
let popup = aEvent.target;
if (popup.id !== CONTEXTMENU_ID) {
return;
}
let view = document.querySelector(".hud-output-node");
let view = this.owner.outputNode;
let metadata = this.getSelectionMetadata(view);
for (let i = 0, l = popup.childNodes.length; i < l; ++i) {
let element = popup.childNodes[i];
for (let element of this.popup.children) {
element.hidden = this.shouldHideMenuItem(element, metadata);
}
},
@ -5173,4 +5149,15 @@ let ConsoleContextMenu = {
return shouldHide;
},
/**
* Destroy the ConsoleContextMenu object instance.
*/
destroy: function CCM_destroy()
{
this.popup.removeEventListener("popupshowing", this.build);
this.popup = null;
this.owner = null;
},
};

View File

@ -22,7 +22,12 @@
width="900" height="350"
persist="screenX screenY width height sizemode">
<script type="text/javascript" src="chrome://global/content/globalOverlay.js"/>
<script type="text/javascript" src="webconsole.js"/>
<script type="text/javascript"><![CDATA[
function goUpdateConsoleCommands() {
goUpdateCommand("consoleCmd_openURL");
goUpdateCommand("consoleCmd_copyURL");
}
// ]]></script>
<commandset id="editMenuCommands"/>
@ -57,8 +62,7 @@
<keyset id="editMenuKeys"/>
<popupset id="mainPopupSet">
<menupopup id="output-contextmenu"
onpopupshowing="ConsoleContextMenu.build(event);">
<menupopup id="output-contextmenu">
<menuitem id="saveBodiesContextMenu" type="checkbox" label="&saveBodies.label;"
accesskey="&saveBodies.accesskey;"/>
<menuitem id="menu_openURL" label="&openURL.label;"
@ -78,11 +82,8 @@
<toolbarbutton label="&btnPageNet.label;" type="menu-button"
category="net" class="devtools-toolbarbutton webconsole-filter-button"
tooltiptext="&btnPageNet.tooltip;"
#ifdef XP_MACOSX
accesskey="&btnPageNet.accesskeyMacOSX;"
#else
accesskeyMacOSX="&btnPageNet.accesskeyMacOSX;"
accesskey="&btnPageNet.accesskey;"
#endif
tabindex="3">
<menupopup>
<menuitem label="&btnConsoleErrors;" type="checkbox" autocheck="false"

View File

@ -190,7 +190,6 @@
@BINPATH@/components/dom_canvas.xpt
@BINPATH@/components/dom_contacts.xpt
@BINPATH@/components/dom_alarm.xpt
@BINPATH@/components/dom_push.xpt
@BINPATH@/components/dom_core.xpt
@BINPATH@/components/dom_css.xpt
@BINPATH@/components/dom_devicestorage.xpt

File diff suppressed because it is too large Load Diff

View File

@ -109,9 +109,8 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY fullScreenExit.accesskey "F">
<!ENTITY fullscreenAllowButton.label "Allow">
<!ENTITY fullscreenExitButton.label "Deny">
<!ENTITY fullscreenApproval.value "Allow fullscreen?">
<!ENTITY fullscreenExitHint.value "Press ESC at any time to exit fullscreen.">
<!ENTITY fullscreenExitHint2.value "Press ESC at any time to exit.">
<!ENTITY leaveDOMFullScreen.label "Exit Full Screen">
<!ENTITY leaveDOMFullScreen.accesskey "u">
@ -207,6 +206,9 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY webDeveloperMenu.label "Web Developer">
<!ENTITY webDeveloperMenu.accesskey "W">
<!ENTITY devToolsCmd.keycode "VK_F12">
<!ENTITY devToolsCmd.keytext "F12">
<!ENTITY devtoolsConnect.label "Connect…">
<!ENTITY devtoolsConnect.accesskey "e">
@ -252,6 +254,8 @@ These should match what Safari and other Apple applications use on OS X Lion. --
<!ENTITY devToolbar.keytext "F2">
<!ENTITY devToolboxMenuItem.label "Toggle Tools">
<!ENTITY devToolboxMenuItem.accesskey "T">
<!ENTITY devToolboxMenuItem.keycode "I">
<!ENTITY devToolboxMenuItem.keytext "I">
<!ENTITY devToolbarToolsButton.tooltip "Toggle developer tools">
<!ENTITY devToolbarOtherToolsButton.label "More Tools">

View File

@ -134,7 +134,11 @@
<!-- LOCALIZATION NOTE (debuggerUI.stepping): These are the keycodes that
- control the stepping commands in the debugger (continue, step over,
- step in and step out). -->
<!ENTITY debuggerUI.stepping.resume "VK_F6">
<!ENTITY debuggerUI.stepping.stepOver "VK_F7">
<!ENTITY debuggerUI.stepping.stepIn "VK_F8">
<!ENTITY debuggerUI.stepping.stepOut "VK_F8">
<!ENTITY debuggerUI.stepping.resume1 "VK_F8">
<!ENTITY debuggerUI.stepping.resume2 "VK_SLASH">
<!ENTITY debuggerUI.stepping.stepOver1 "VK_F10">
<!ENTITY debuggerUI.stepping.stepOver2 "VK_QUOTE">
<!ENTITY debuggerUI.stepping.stepIn1 "VK_F11">
<!ENTITY debuggerUI.stepping.stepIn2 "VK_SEMICOLON">
<!ENTITY debuggerUI.stepping.stepOut1 "VK_F11">
<!ENTITY debuggerUI.stepping.stepOut2 "VK_SEMICOLON">

View File

@ -35,7 +35,7 @@ nodeMenu.tooltiptext=Node operations
# LOCALIZATION NOTE (inspector.*)
# Used for the menuitem in the tool menu
inspector.label=Inspector
inspector.commandkey=I
inspector.commandkey=C
inspector.accesskey=I
# LOCALIZATION NOTE (markupView.more.*)

View File

@ -39,7 +39,7 @@ var Appbar = {
if (this.activeTileset && ('isBound' in this.activeTileset)) {
this.activeTileset.clearSelection();
}
this.clearContextualActions();
this._clearContextualActions();
this.activeTileset = null;
break;
@ -174,8 +174,6 @@ var Appbar = {
if (aVerbs.length) {
Elements.contextappbar.show();
} else {
Elements.contextappbar.hide();
}
// Look up all of the buttons for the verbs that should be visible.
@ -227,7 +225,7 @@ var Appbar = {
});
},
clearContextualActions: function() {
_clearContextualActions: function() {
this.showContextualActions([]);
},

View File

@ -73,5 +73,10 @@
</body>
</method>
</implementation>
<handlers>
<!-- Work around for bug 835175 -->
<handler event="click">false;</handler>
</handlers>
</binding>
</bindings>

View File

@ -99,5 +99,10 @@
document.getAnonymousElementByAttribute(this, "class", "flyoutpanel-contents");
]]></field>
</implementation>
<handlers>
<!-- Work around for bug 835175 -->
<handler event="click">false;</handler>
</handlers>
</binding>
</bindings>

View File

@ -181,7 +181,8 @@
<vbox id="page">
<vbox id="tray" class="tray-toolbar" observes="bcast_windowState" >
<!-- Tabs -->
<hbox id="tabs-container" observes="bcast_windowState">
<!-- onclick handler to work around bug 837242 -->
<hbox id="tabs-container" observes="bcast_windowState" onclick="void(0);">
<box id="tabs" flex="1"
observes="bcast_preciseInput"
onselect="BrowserUI.selectTabAndDismiss(this);"
@ -242,7 +243,8 @@
<box id="horizontal-scroller" class="scroller" orient="horizontal" left="0" bottom="0"/>
<!-- Content touch selection overlay -->
<box class="selection-overlay-hidden" id="content-selection-overlay"/>
<!-- onclick addresses dom bug 835175 -->
<box onclick="false" class="selection-overlay-hidden" id="content-selection-overlay"/>
</stack>
</vbox>
@ -736,9 +738,11 @@
</flyoutpanel>
<!-- Chrome touch selection overlay -->
<box class="selection-overlay-hidden" id="chrome-selection-overlay"/>
<!-- onclick addresses dom bug 835175 -->
<box onclick="false" class="selection-overlay-hidden" id="chrome-selection-overlay"/>
<box onclick="event.stopPropagation();" id="context-container" class="menu-container" hidden="true">
<!-- onclick is dom bug 835175 -->
<vbox id="context-popup" class="menu-popup">
<richlistbox id="context-commands" bindingType="contextmenu" flex="1">
<!-- priority="low" items are hidden by default when a context is being displayed

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html [
<!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
%htmlDTD;
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
%brandDTD;
<!ENTITY % aboutAddonsDTD SYSTEM "chrome://browser/locale/aboutAddons.dtd">
%aboutAddonsDTD;
]>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title> &aboutAddons.title; </title>
<link rel="stylesheet" href="chrome://browser/skin/aboutAddons.css" type="text/css"/>
</head>
<body>
<div id="fox">
<div id="floatingTextBox">
<div id="aboutAddonsTextTitle">
&aboutAddons.messageTitle;
</div>
<div id="aboutAddonsTextBody">
&aboutAddons.message;
&aboutAddons.goBackToStart;
<a href="about:start">&aboutAddons.startPageLinkTitle;</a>
</div>
</div>
</div>
</body>
</html>

View File

@ -10,6 +10,7 @@ chrome.jar:
content/aboutRights.xhtml (content/pages/aboutRights.xhtml)
content/blockedSite.xhtml (content/pages/blockedSite.xhtml)
content/netError.xhtml (content/pages/netError.xhtml)
content/aboutAddons.xhtml (content/pages/aboutAddons.xhtml)
content/bindings/bindings.xml (content/bindings/bindings.xml)
content/bindings/tabs.xml (content/bindings/tabs.xml)
@ -101,3 +102,4 @@ chrome.jar:
% override chrome://global/content/config.xul chrome://browser/content/config.xul
% override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
% override chrome://mozapps/content/extensions/extensions.xul chrome://browser/content/aboutAddons.xhtml

View File

@ -16,9 +16,6 @@ include $(DEPTH)/config/autoconf.mk
# browser_context_menu_tests_01.html \
# browser_context_menu_tests_02.html \
# browser_context_menu_tests_03.html \
# Bug 897175
# browser_findbar.js \
# browser_findbar.html \
MOCHITEST_METRO_FILES = \
head.js \
@ -28,6 +25,8 @@ MOCHITEST_METRO_FILES = \
browser_circular_progress_indicator.js \
browser_context_ui.js \
browser_downloads.js \
browser_findbar.js \
browser_findbar.html \
browser_history.js \
browser_onscreen_keyboard.js \
browser_onscreen_keyboard.html \

Some files were not shown because too many files have changed in this diff Show More