зеркало из https://github.com/mozilla/gecko-dev.git
merge the last green changeset on m-c to fx-team
This commit is contained in:
Коммит
d210082852
|
@ -6679,14 +6679,6 @@ var gPluginHandler = {
|
|||
return this.CrashSubmit;
|
||||
},
|
||||
|
||||
get crashReportHelpURL() {
|
||||
delete this.crashReportHelpURL;
|
||||
let url = formatURL("app.support.baseURL", true);
|
||||
url += "plugin-crashed";
|
||||
this.crashReportHelpURL = url;
|
||||
return this.crashReportHelpURL;
|
||||
},
|
||||
|
||||
// Map the plugin's name to a filtered version more suitable for user UI.
|
||||
makeNicePluginName : function (aName, aFilename) {
|
||||
if (aName == "Shockwave Flash")
|
||||
|
@ -6825,10 +6817,25 @@ var gPluginHandler = {
|
|||
BrowserOpenAddonsMgr("addons://list/plugin");
|
||||
},
|
||||
|
||||
// Callback for user clicking "submit a report" link
|
||||
submitReport : function(pluginDumpID, browserDumpID) {
|
||||
// The crash reporter wants a DOM element it can append an IFRAME to,
|
||||
// which it uses to submit a form. Let's just give it gBrowser.
|
||||
// When user clicks try, checks if we should also send crash report in bg
|
||||
retryPluginPage: function (browser, plugin, pluginDumpID, browserDumpID) {
|
||||
let doc = plugin.ownerDocument;
|
||||
|
||||
let statusDiv =
|
||||
doc.getAnonymousElementByAttribute(plugin, "class", "submitStatus");
|
||||
let status = statusDiv.getAttribute("status");
|
||||
|
||||
let submitChk =
|
||||
doc.getAnonymousElementByAttribute(plugin, "class", "pleaseSubmitCheckbox");
|
||||
|
||||
// Check status to make sure we haven't submitted already
|
||||
if (status == "please" && submitChk.checked) {
|
||||
this.submitReport(pluginDumpID, browserDumpID);
|
||||
}
|
||||
this.reloadPage(browser);
|
||||
},
|
||||
|
||||
submitReport: function (pluginDumpID, browserDumpID) {
|
||||
this.CrashSubmit.submit(pluginDumpID);
|
||||
if (browserDumpID)
|
||||
this.CrashSubmit.submit(browserDumpID);
|
||||
|
@ -7046,8 +7053,7 @@ var gPluginHandler = {
|
|||
return;
|
||||
|
||||
let submittedReport = aEvent.getData("submittedCrashReport");
|
||||
let doPrompt = true; // XXX followup for .getData("doPrompt");
|
||||
let submitReports = true; // XXX followup for .getData("submitReports");
|
||||
let doPrompt = true; // XXX followup to get via gCrashReporter
|
||||
let pluginName = aEvent.getData("pluginName");
|
||||
let pluginFilename = aEvent.getData("pluginFilename");
|
||||
let pluginDumpID = aEvent.getData("pluginDumpID");
|
||||
|
@ -7065,6 +7071,7 @@ var gPluginHandler = {
|
|||
let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
|
||||
let statusDiv = doc.getAnonymousElementByAttribute(plugin, "class", "submitStatus");
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
let submitReports = gCrashReporter.submitReports;
|
||||
let status;
|
||||
|
||||
// Determine which message to show regarding crash reports.
|
||||
|
@ -7075,18 +7082,21 @@ var gPluginHandler = {
|
|||
status = "noSubmit";
|
||||
}
|
||||
else { // doPrompt
|
||||
// link submit checkbox to gCrashReporter submitReports preference
|
||||
let submitChk = doc.getAnonymousElementByAttribute(
|
||||
plugin, "class", "pleaseSubmitCheckbox");
|
||||
submitChk.checked = submitReports;
|
||||
submitChk.addEventListener("click", function() {
|
||||
gCrashReporter.submitReports = this.checked;
|
||||
}, false);
|
||||
|
||||
status = "please";
|
||||
// XXX can we make the link target actually be blank?
|
||||
let pleaseLink = doc.getAnonymousElementByAttribute(
|
||||
plugin, "class", "pleaseSubmitLink");
|
||||
this.addLinkClickCallback(pleaseLink, "submitReport",
|
||||
pluginDumpID, browserDumpID);
|
||||
}
|
||||
|
||||
// If we don't have a minidumpID, we can't (or didn't) submit anything.
|
||||
// This can happen if the plugin is killed from the task manager.
|
||||
if (!pluginDumpID) {
|
||||
status = "noReport";
|
||||
status = "noReport";
|
||||
}
|
||||
|
||||
statusDiv.setAttribute("status", status);
|
||||
|
@ -7096,10 +7106,23 @@ var gPluginHandler = {
|
|||
let helpIcon = doc.getAnonymousElementByAttribute(plugin, "class", "helpIcon");
|
||||
this.addLinkClickCallback(helpIcon, "openHelpPage");
|
||||
|
||||
// If we're showing the link to manually trigger report submission, we'll
|
||||
// want to be able to update all the instances of the UI for this crash to
|
||||
// show an updated message when a report is submitted.
|
||||
// If we're showing the checkbox to trigger report submission, we'll want
|
||||
// to be able to update all the instances of the UI for this crash when
|
||||
// one instance of the checkbox is modified or the status is updated.
|
||||
if (doPrompt) {
|
||||
let submitReportsPrefObserver = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
observe : function(subject, topic, data) {
|
||||
let submitChk = doc.getAnonymousElementByAttribute(
|
||||
plugin, "class", "pleaseSubmitCheckbox");
|
||||
submitChk.checked = gCrashReporter.submitReports;
|
||||
},
|
||||
handleEvent : function(event) {
|
||||
// Not expected to be called, just here for the closure.
|
||||
}
|
||||
};
|
||||
|
||||
let observer = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
|
@ -7116,16 +7139,21 @@ var gPluginHandler = {
|
|||
handleEvent : function(event) {
|
||||
// Not expected to be called, just here for the closure.
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Use a weak reference, so we don't have to remove it...
|
||||
Services.obs.addObserver(observer, "crash-report-status", true);
|
||||
Services.obs.addObserver(
|
||||
submitReportsPrefObserver, "submit-reports-pref-changed", true);
|
||||
|
||||
// ...alas, now we need something to hold a strong reference to prevent
|
||||
// it from being GC. But I don't want to manually manage the reference's
|
||||
// lifetime (which should be no greater than the page).
|
||||
// Clever solution? Use a closue with an event listener on the document.
|
||||
// Clever solution? Use a closure with an event listener on the document.
|
||||
// When the doc goes away, so do the listener references and the closure.
|
||||
doc.addEventListener("mozCleverClosureHack", observer, false);
|
||||
doc.addEventListener(
|
||||
"mozCleverClosureHack", submitReportsPrefObserver, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -7135,7 +7163,12 @@ var gPluginHandler = {
|
|||
let browser = gBrowser.getBrowserForDocument(doc.defaultView.top.document);
|
||||
|
||||
let link = doc.getAnonymousElementByAttribute(plugin, "class", "reloadLink");
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
this.addLinkClickCallback(
|
||||
link, "retryPluginPage", browser, plugin, pluginDumpID, browserDumpID);
|
||||
#else
|
||||
this.addLinkClickCallback(link, "reloadPage", browser);
|
||||
#endif
|
||||
|
||||
let notificationBox = gBrowser.getNotificationBox(browser);
|
||||
|
||||
|
@ -7201,7 +7234,10 @@ var gPluginHandler = {
|
|||
let link = notification.ownerDocument.createElementNS(XULNS, "label");
|
||||
link.className = "text-link";
|
||||
link.setAttribute("value", gNavigatorBundle.getString("crashedpluginsMessage.learnMore"));
|
||||
link.href = gPluginHandler.crashReportHelpURL;
|
||||
let crashurl = formatURL("app.support.baseURL", true);
|
||||
crashurl += "plugin-crashed-notificationbar";
|
||||
link.href = crashurl;
|
||||
|
||||
let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText");
|
||||
description.appendChild(link);
|
||||
|
||||
|
|
|
@ -973,14 +973,27 @@
|
|||
<toolbar id="inspector-toolbar"
|
||||
nowindowdrag="true"
|
||||
hidden="true">
|
||||
<toolbarbutton id="inspector-inspect-toolbutton"
|
||||
label="&inspectButton.label;"
|
||||
accesskey="&inspectButton.accesskey;"
|
||||
command="Inspector:Inspect"/>
|
||||
<toolbarseparator />
|
||||
<hbox id="inspector-tools">
|
||||
<!-- registered tools go here -->
|
||||
</hbox>
|
||||
<vbox flex="1">
|
||||
<resizer id="inspector-top-resizer" flex="1"
|
||||
class="inspector-resizer"
|
||||
dir="top" disabled="true"
|
||||
element="inspector-tree-box"/>
|
||||
<hbox>
|
||||
<toolbarbutton id="inspector-inspect-toolbutton"
|
||||
label="&inspectButton.label;"
|
||||
accesskey="&inspectButton.accesskey;"
|
||||
command="Inspector:Inspect"/>
|
||||
<toolbarseparator/>
|
||||
<hbox id="inspector-tools">
|
||||
<!-- registered tools go here -->
|
||||
</hbox>
|
||||
<spacer flex="1"/>
|
||||
<resizer id="inspector-end-resizer"
|
||||
class="inspector-resizer"
|
||||
dir="top" disabled="true"
|
||||
element="inspector-tree-box"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</toolbar>
|
||||
<toolbar id="addon-bar"
|
||||
toolbarname="&addonBarCmd.label;" accesskey="&addonBarCmd.accesskey;"
|
||||
|
|
|
@ -247,6 +247,12 @@ function runTest(testNum) {
|
|||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
|
||||
ok(true, "Starting test #" + testNum);
|
||||
|
||||
var inspectItems = [];
|
||||
if (SpecialPowers.getBoolPref("devtools.inspector.enabled")) {
|
||||
inspectItems = ["---", null,
|
||||
"context-inspect", true];
|
||||
}
|
||||
|
||||
switch (testNum) {
|
||||
case 1:
|
||||
// Invoke context menu for next test.
|
||||
|
@ -268,9 +274,8 @@ function runTest(testNum) {
|
|||
"context-selectall", true,
|
||||
"---", null,
|
||||
"context-viewsource", true,
|
||||
"context-viewinfo", true,
|
||||
"---", null,
|
||||
"context-inspect", true]);
|
||||
"context-viewinfo", true
|
||||
].concat(inspectItems));
|
||||
closeContextMenu();
|
||||
openContextMenuFor(link); // Invoke context menu for next test.
|
||||
break;
|
||||
|
@ -283,18 +288,15 @@ function runTest(testNum) {
|
|||
"context-bookmarklink", true,
|
||||
"context-savelink", true,
|
||||
"context-sendlink", true,
|
||||
"context-copylink", true,
|
||||
"---", null,
|
||||
"context-inspect", true]);
|
||||
"context-copylink", true
|
||||
].concat(inspectItems));
|
||||
closeContextMenu();
|
||||
openContextMenuFor(mailto); // Invoke context menu for next test.
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// Context menu for text mailto-link
|
||||
checkContextMenu(["context-copyemail", true,
|
||||
"---", null,
|
||||
"context-inspect", true]);
|
||||
checkContextMenu(["context-copyemail", true].concat(inspectItems));
|
||||
closeContextMenu();
|
||||
openContextMenuFor(input); // Invoke context menu for next test.
|
||||
break;
|
||||
|
@ -310,9 +312,8 @@ function runTest(testNum) {
|
|||
"---", null,
|
||||
"context-selectall", false,
|
||||
"---", null,
|
||||
"spell-check-enabled", true,
|
||||
"---", null,
|
||||
"context-inspect", true]);
|
||||
"spell-check-enabled", true
|
||||
].concat(inspectItems));
|
||||
closeContextMenu();
|
||||
openContextMenuFor(img); // Invoke context menu for next test.
|
||||
break;
|
||||
|
@ -326,9 +327,8 @@ function runTest(testNum) {
|
|||
"context-saveimage", true,
|
||||
"context-sendimage", true,
|
||||
"context-setDesktopBackground", true,
|
||||
"context-viewimageinfo", true,
|
||||
"---", null,
|
||||
"context-inspect", true]);
|
||||
"context-viewimageinfo", true
|
||||
].concat(inspectItems));
|
||||
closeContextMenu();
|
||||
openContextMenuFor(canvas); // Invoke context menu for next test.
|
||||
break;
|
||||
|
@ -338,9 +338,8 @@ function runTest(testNum) {
|
|||
checkContextMenu(["context-viewimage", true,
|
||||
"context-saveimage", true,
|
||||
"context-bookmarkpage", true,
|
||||
"context-selectall", true,
|
||||
"---", null,
|
||||
"context-inspect", true]);
|
||||
"context-selectall", true
|
||||
].concat(inspectItems));
|
||||
closeContextMenu();
|
||||
openContextMenuFor(video_ok); // Invoke context menu for next test.
|
||||
break;
|
||||
|
@ -358,9 +357,8 @@ function runTest(testNum) {
|
|||
"---", null,
|
||||
"context-savevideo", true,
|
||||
"context-video-saveimage", true,
|
||||
"context-sendvideo", true,
|
||||
"---", null,
|
||||
"context-inspect", true]);
|
||||
"context-sendvideo", true
|
||||
].concat(inspectItems));
|
||||
closeContextMenu();
|
||||
openContextMenuFor(video_bad); // Invoke context menu for next test.
|
||||
break;
|
||||
|
@ -378,9 +376,8 @@ function runTest(testNum) {
|
|||
"---", null,
|
||||
"context-savevideo", true,
|
||||
"context-video-saveimage", false,
|
||||
"context-sendvideo", true,
|
||||
"---", null,
|
||||
"context-inspect", true]);
|
||||
"context-sendvideo", true
|
||||
].concat(inspectItems));
|
||||
closeContextMenu();
|
||||
openContextMenuFor(video_bad2); // Invoke context menu for next test.
|
||||
break;
|
||||
|
@ -398,9 +395,8 @@ function runTest(testNum) {
|
|||
"---", null,
|
||||
"context-savevideo", false,
|
||||
"context-video-saveimage", false,
|
||||
"context-sendvideo", false,
|
||||
"---", null,
|
||||
"context-inspect", true]);
|
||||
"context-sendvideo", false
|
||||
].concat(inspectItems));
|
||||
closeContextMenu();
|
||||
openContextMenuFor(iframe); // Invoke context menu for next test.
|
||||
break;
|
||||
|
@ -434,9 +430,8 @@ function runTest(testNum) {
|
|||
"context-viewframeinfo", true], null,
|
||||
"---", null,
|
||||
"context-viewsource", true,
|
||||
"context-viewinfo", true,
|
||||
"---", null,
|
||||
"context-inspect", true]);
|
||||
"context-viewinfo", true
|
||||
].concat(inspectItems));
|
||||
closeContextMenu();
|
||||
openContextMenuFor(textarea, false, true); // Invoke context menu for next test, but wait for the spellcheck.
|
||||
break;
|
||||
|
@ -460,8 +455,7 @@ function runTest(testNum) {
|
|||
["spell-check-dictionary-en-US", true,
|
||||
"---", null,
|
||||
"spell-add-dictionaries", true], null,
|
||||
"---", null,
|
||||
"context-inspect", true]);
|
||||
].concat(inspectItems));
|
||||
|
||||
closeContextMenu();
|
||||
openContextMenuFor(contenteditable); // Invoke context menu for next test.
|
||||
|
@ -485,9 +479,8 @@ function runTest(testNum) {
|
|||
"spell-dictionaries", true,
|
||||
["spell-check-dictionary-en-US", true,
|
||||
"---", null,
|
||||
"spell-add-dictionaries", true], null,
|
||||
"---", null,
|
||||
"context-inspect", true]);
|
||||
"spell-add-dictionaries", true], null
|
||||
].concat(inspectItems));
|
||||
|
||||
closeContextMenu();
|
||||
openContextMenuFor(inputspell); // Invoke context menu for next test.
|
||||
|
@ -511,9 +504,8 @@ function runTest(testNum) {
|
|||
"spell-dictionaries", true,
|
||||
["spell-check-dictionary-en-US", true,
|
||||
"---", null,
|
||||
"spell-add-dictionaries", true], null,
|
||||
"---", null,
|
||||
"context-inspect", true]);
|
||||
"spell-add-dictionaries", true], null
|
||||
].concat(inspectItems));
|
||||
|
||||
closeContextMenu();
|
||||
openContextMenuFor(link); // Invoke context menu for next test.
|
||||
|
@ -560,9 +552,8 @@ function runTest(testNum) {
|
|||
"context-selectall", true,
|
||||
"---", null,
|
||||
"context-viewsource", true,
|
||||
"context-viewinfo", true,
|
||||
"---", null,
|
||||
"context-inspect", true]);
|
||||
"context-viewinfo", true
|
||||
].concat(inspectItems));
|
||||
|
||||
invokeItemAction("0");
|
||||
closeContextMenu();
|
||||
|
@ -585,9 +576,8 @@ function runTest(testNum) {
|
|||
"context-selectall", true,
|
||||
"---", null,
|
||||
"context-viewsource", true,
|
||||
"context-viewinfo", true,
|
||||
"---", null,
|
||||
"context-inspect", true]);
|
||||
"context-viewinfo", true
|
||||
].concat(inspectItems));
|
||||
|
||||
subwindow.close();
|
||||
SimpleTest.finish();
|
||||
|
|
|
@ -177,6 +177,9 @@ SessionStartup.prototype = {
|
|||
Services.obs.addObserver(this, "domwindowopened", true);
|
||||
|
||||
Services.obs.addObserver(this, "sessionstore-windows-restored", true);
|
||||
|
||||
if (this._sessionType != Ci.nsISessionStartup.NO_SESSION)
|
||||
Services.obs.addObserver(this, "browser:purge-session-history", true);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -197,6 +200,8 @@ SessionStartup.prototype = {
|
|||
// no reason for initializing at this point (cf. bug 409115)
|
||||
Services.obs.removeObserver(this, "final-ui-startup");
|
||||
Services.obs.removeObserver(this, "quit-application");
|
||||
if (this._sessionType != Ci.nsISessionStartup.NO_SESSION)
|
||||
Services.obs.removeObserver(this, "browser:purge-session-history");
|
||||
break;
|
||||
case "domwindowopened":
|
||||
var window = aSubject;
|
||||
|
@ -210,6 +215,10 @@ SessionStartup.prototype = {
|
|||
Services.obs.removeObserver(this, "sessionstore-windows-restored");
|
||||
// free _initialState after nsSessionStore is done with it
|
||||
this._initialState = null;
|
||||
break;
|
||||
case "browser:purge-session-history":
|
||||
Services.obs.removeObserver(this, "browser:purge-session-history");
|
||||
// reset all state on sanitization
|
||||
this._sessionType = Ci.nsISessionStartup.NO_SESSION;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -2481,7 +2481,19 @@ SessionStoreService.prototype = {
|
|||
if (ix != -1 && total[ix] && total[ix].sizemode == "minimized")
|
||||
ix = -1;
|
||||
|
||||
return { windows: total, selectedWindow: ix + 1, _closedWindows: lastClosedWindowsCopy };
|
||||
let session = {
|
||||
state: this._loadState == STATE_RUNNING ? STATE_RUNNING_STR : STATE_STOPPED_STR,
|
||||
lastUpdate: Date.now(),
|
||||
startTime: this._sessionStartTime,
|
||||
recentCrashes: this._recentCrashes
|
||||
};
|
||||
|
||||
return {
|
||||
windows: total,
|
||||
selectedWindow: ix + 1,
|
||||
_closedWindows: lastClosedWindowsCopy,
|
||||
session: session
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -2565,7 +2577,7 @@ SessionStoreService.prototype = {
|
|||
this._closedWindows = root._closedWindows;
|
||||
|
||||
var winData;
|
||||
if (!root.selectedWindow) {
|
||||
if (!root.selectedWindow || root.selectedWindow > root.windows.length) {
|
||||
root.selectedWindow = 0;
|
||||
} else {
|
||||
// put the selected window at the beginning of the array to ensure that
|
||||
|
@ -3263,31 +3275,48 @@ SessionStoreService.prototype = {
|
|||
if (!node)
|
||||
continue;
|
||||
|
||||
let eventType;
|
||||
let value = aData[key];
|
||||
if (typeof value == "string" && node.type != "file") {
|
||||
if (node.value == value)
|
||||
continue; // don't dispatch an input event for no change
|
||||
|
||||
node.value = value;
|
||||
|
||||
let event = aDocument.createEvent("UIEvents");
|
||||
event.initUIEvent("input", true, true, aDocument.defaultView, 0);
|
||||
node.dispatchEvent(event);
|
||||
eventType = "input";
|
||||
}
|
||||
else if (typeof value == "boolean")
|
||||
else if (typeof value == "boolean") {
|
||||
if (node.checked == value)
|
||||
continue; // don't dispatch a change event for no change
|
||||
|
||||
node.checked = value;
|
||||
else if (typeof value == "number")
|
||||
eventType = "change";
|
||||
}
|
||||
else if (typeof value == "number") {
|
||||
try {
|
||||
node.selectedIndex = value;
|
||||
eventType = "change";
|
||||
} catch (ex) { /* throws for invalid indices */ }
|
||||
else if (value && value.fileList && value.type == "file" && node.type == "file")
|
||||
}
|
||||
else if (value && value.fileList && value.type == "file" && node.type == "file") {
|
||||
node.mozSetFileNameArray(value.fileList, value.fileList.length);
|
||||
eventType = "input";
|
||||
}
|
||||
else if (value && typeof value.indexOf == "function" && node.options) {
|
||||
Array.forEach(node.options, function(aOpt, aIx) {
|
||||
aOpt.selected = value.indexOf(aIx) > -1;
|
||||
|
||||
// Only fire the event here if this wasn't selected by default
|
||||
if (!aOpt.defaultSelected)
|
||||
eventType = "change";
|
||||
});
|
||||
}
|
||||
// NB: dispatching "change" events might have unintended side-effects
|
||||
|
||||
// Fire events for this node if applicable
|
||||
if (eventType) {
|
||||
let event = aDocument.createEvent("UIEvents");
|
||||
event.initUIEvent(eventType, true, true, aDocument.defaultView, 0);
|
||||
node.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3521,14 +3550,6 @@ SessionStoreService.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
oState.session = {
|
||||
state: this._loadState == STATE_RUNNING ? STATE_RUNNING_STR : STATE_STOPPED_STR,
|
||||
lastUpdate: Date.now(),
|
||||
startTime: this._sessionStartTime
|
||||
};
|
||||
if (this._recentCrashes)
|
||||
oState.session.recentCrashes = this._recentCrashes;
|
||||
|
||||
// Persist the last session if we deferred restoring it
|
||||
if (this._lastSessionState)
|
||||
oState.lastSessionState = this._lastSessionState;
|
||||
|
|
|
@ -50,6 +50,8 @@ include $(topsrcdir)/config/rules.mk
|
|||
|
||||
_BROWSER_TEST_FILES = \
|
||||
head.js \
|
||||
browser_form_restore_events.js \
|
||||
browser_form_restore_events_sample.html \
|
||||
browser_248970_a.js \
|
||||
browser_248970_b.js \
|
||||
browser_248970_b_sample.html \
|
||||
|
@ -98,8 +100,6 @@ _BROWSER_TEST_FILES = \
|
|||
browser_465223.js \
|
||||
browser_466937.js \
|
||||
browser_466937_sample.html \
|
||||
browser_476161.js \
|
||||
browser_476161_sample.html \
|
||||
browser_477657.js \
|
||||
browser_480148.js \
|
||||
browser_480893.js \
|
||||
|
@ -152,7 +152,9 @@ _BROWSER_TEST_FILES = \
|
|||
browser_645428.js \
|
||||
browser_659591.js \
|
||||
browser_662812.js \
|
||||
browser_665702-state_session.js \
|
||||
browser_682507.js \
|
||||
browser_694378.js \
|
||||
$(NULL)
|
||||
|
||||
ifneq ($(OS_ARCH),Darwin)
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Test for bug 476161</title>
|
||||
|
||||
<script>
|
||||
|
||||
document.addEventListener("input", function(aEvent) {
|
||||
var inputEl = aEvent.originalTarget;
|
||||
var changedEl = document.getElementById("changed");
|
||||
|
||||
changedEl.textContent += " " + inputEl.id;
|
||||
}, false);
|
||||
|
||||
</script>
|
||||
|
||||
<h3>Text fields with changed text</h3>
|
||||
<input type="text" id="modify1">
|
||||
<input type="text" id="modify2" value="preset value">
|
||||
|
||||
<h3>Text fields with unchanged text</h3>
|
||||
<input type="text" id="unchanged1">
|
||||
<input type="text" id="unchanged2" value="preset value">
|
||||
|
||||
<h3>Changed field IDs</h3>
|
||||
<div id="changed"></div>
|
|
@ -0,0 +1,24 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function compareArray(a, b) {
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (a[i] !== b[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function test() {
|
||||
let currentState = JSON.parse(ss.getBrowserState());
|
||||
ok(currentState.session, "session data returned by getBrowserState");
|
||||
|
||||
let keys = Object.keys(currentState.session);
|
||||
let expectedKeys = ["state", "lastUpdate", "startTime", "recentCrashes"];
|
||||
ok(compareArray(keys.sort(), expectedKeys.sort()),
|
||||
"session object from getBrowserState has correct keys");
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test Summary:
|
||||
// 1. call ss.setWindowState with a broken state
|
||||
// 1a. ensure that it doesn't throw.
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let brokenState = {
|
||||
windows: [
|
||||
{ tabs: [{ entries: [{ url: "about:mozilla" }] }] }
|
||||
//{ tabs: [{ entries: [{ url: "about:robots" }] }] },
|
||||
],
|
||||
selectedWindow: 2
|
||||
};
|
||||
let brokenStateString = JSON.stringify(brokenState);
|
||||
|
||||
let gotError = false;
|
||||
try {
|
||||
ss.setWindowState(window, brokenStateString, true);
|
||||
}
|
||||
catch (ex) {
|
||||
gotError = true;
|
||||
info(ex);
|
||||
}
|
||||
|
||||
ok(!gotError, "ss.setWindowState did not throw an error");
|
||||
|
||||
// Make sure that we reset the state. Use a full state just in case things get crazy.
|
||||
let blankState = { windows: [{ tabs: [{ entries: [{ url: "about:blank" }] }]}]};
|
||||
waitForBrowserState(blankState, finish);
|
||||
}
|
||||
|
|
@ -35,33 +35,64 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
/** Test for Bug 476161 **/
|
||||
|
||||
/** Originally a test for Bug 476161, but then expanded to include all input types in bug 640136 **/
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
|
||||
let file = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Components.interfaces.nsIProperties)
|
||||
.get("TmpD", Components.interfaces.nsIFile);
|
||||
|
||||
let testURL = "http://mochi.test:8888/browser/" +
|
||||
"browser/components/sessionstore/test/browser/browser_476161_sample.html";
|
||||
"browser/components/sessionstore/test/browser/browser_form_restore_events_sample.html";
|
||||
let tab = gBrowser.addTab(testURL);
|
||||
tab.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
let doc = tab.linkedBrowser.contentDocument;
|
||||
|
||||
doc.getElementById("modify1").value += Math.random();
|
||||
doc.getElementById("modify2").value += " " + Date.now();
|
||||
|
||||
|
||||
// text fields
|
||||
doc.getElementById("modify01").value += Math.random();
|
||||
doc.getElementById("modify02").value += " " + Date.now();
|
||||
|
||||
// textareas
|
||||
doc.getElementById("modify03").value += Math.random();
|
||||
doc.getElementById("modify04").value += " " + Date.now();
|
||||
|
||||
// file
|
||||
doc.getElementById("modify05").value = file.path;
|
||||
|
||||
// select
|
||||
doc.getElementById("modify06").selectedIndex = 1;
|
||||
var multipleChange = doc.getElementById("modify07");
|
||||
Array.forEach(multipleChange.options, function(option) option.selected = true);
|
||||
|
||||
// checkbox
|
||||
doc.getElementById("modify08").checked = true;
|
||||
doc.getElementById("modify09").checked = false;
|
||||
|
||||
// radio
|
||||
// select one then another in the same group - only last one should get event on restore
|
||||
doc.getElementById("modify10").checked = true;
|
||||
doc.getElementById("modify11").checked = true;
|
||||
|
||||
|
||||
let tab2 = gBrowser.duplicateTab(tab);
|
||||
tab2.linkedBrowser.addEventListener("load", function(aEvent) {
|
||||
tab2.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
let doc = tab2.linkedBrowser.contentDocument;
|
||||
let changed = doc.getElementById("changed").textContent.trim().split();
|
||||
|
||||
is(changed.sort().join(" "), "modify1 modify2",
|
||||
"input events were only dispatched for modified text fields");
|
||||
|
||||
let inputFired = doc.getElementById("inputFired").textContent.trim().split();
|
||||
let changeFired = doc.getElementById("changeFired").textContent.trim().split();
|
||||
|
||||
is(inputFired.sort().join(" "), "modify01 modify02 modify03 modify04 modify05",
|
||||
"input events were only dispatched for modified input, textarea fields");
|
||||
|
||||
is(changeFired.sort().join(" "), "modify06 unchanged06 modify07 modify08 modify09 modify11",
|
||||
"change events were only dispatched for modified select, checkbox, radio fields");
|
||||
|
||||
// clean up
|
||||
gBrowser.removeTab(tab2);
|
||||
gBrowser.removeTab(tab);
|
||||
|
||||
|
||||
finish();
|
||||
}, true);
|
||||
}, true);
|
|
@ -0,0 +1,98 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Test for form restore events (originally bug 476161)</title>
|
||||
|
||||
<script>
|
||||
|
||||
document.addEventListener("input", function(aEvent) {
|
||||
var inputEl = aEvent.originalTarget;
|
||||
var changedEl = document.getElementById("inputFired");
|
||||
changedEl.textContent += " " + inputEl.id;
|
||||
}, false);
|
||||
|
||||
document.addEventListener("change", function(aEvent) {
|
||||
var inputEl = aEvent.originalTarget;
|
||||
var changedEl = document.getElementById("changeFired");
|
||||
changedEl.textContent += " " + inputEl.id;
|
||||
}, false);
|
||||
|
||||
</script>
|
||||
|
||||
<!-- input events -->
|
||||
<h3>Text fields with changed text</h3>
|
||||
<input type="text" id="modify1">
|
||||
<input type="text" id="modify2" value="preset value">
|
||||
<input type="text" id="modify01">
|
||||
<input type="text" id="modify02" value="preset value">
|
||||
|
||||
<h3>Text fields with unchanged text</h3>
|
||||
<input type="text" id="unchanged1">
|
||||
<input type="text" id="unchanged2" value="preset value">
|
||||
<input type="text" id="unchanged01">
|
||||
<input type="text" id="unchanged02" value="preset value">
|
||||
|
||||
<h3>Textarea with changed text</h3>
|
||||
<textarea id="modify03"></textarea>
|
||||
<textarea id="modify04">preset value</textarea>
|
||||
|
||||
<h3>Textarea with unchanged text</h3>
|
||||
<textarea id="unchanged03"></textarea>
|
||||
<textarea id="unchanged04">preset value</textarea>
|
||||
|
||||
<h3>file field with changed value</h3>
|
||||
<input type="file" id="modify05">
|
||||
|
||||
<h3>file field with unchanged value</h3>
|
||||
<input type="file" id="unchanged05">
|
||||
|
||||
<!-- change events -->
|
||||
|
||||
<h3>Select menu with changed selection</h3>
|
||||
<select id="modify06">
|
||||
<option value="one">one</option>
|
||||
<option value="two">two</option>
|
||||
<option value="three">three</option>
|
||||
</select>
|
||||
|
||||
<h3>Select menu with unchanged selection (change event still fires)</h3>
|
||||
<select id="unchanged06">
|
||||
<option value="one">one</option>
|
||||
<option value="two" selected>two</option>
|
||||
<option value="three">three</option>
|
||||
</select>
|
||||
|
||||
<h3>Multiple Select menu with changed selection</h3>
|
||||
<select id="modify07" multiple>
|
||||
<option value="one">one</option>
|
||||
<option value="two" selected>two</option>
|
||||
<option value="three">three</option>
|
||||
</select>
|
||||
|
||||
<h3>Select menu with unchanged selection</h3>
|
||||
<select id="unchanged07" multiple>
|
||||
<option value="one">one</option>
|
||||
<option value="two" selected>two</option>
|
||||
<option value="three" selected>three</option>
|
||||
</select>
|
||||
|
||||
<h3>checkbox with changed value</h3>
|
||||
<input type="checkbox" id="modify08">
|
||||
<input type="checkbox" id="modify09" checked>
|
||||
|
||||
<h3>checkbox with unchanged value</h3>
|
||||
<input type="checkbox" id="unchanged08">
|
||||
<input type="checkbox" id="unchanged09" checked>
|
||||
|
||||
<h3>radio with changed value</h3>
|
||||
<input type="radio" id="modify10" name="group">Radio 1</input>
|
||||
<input type="radio" id="modify11" name="group">Radio 2</input>
|
||||
<input type="radio" id="modify12" name="group" checked>Radio 3</input>
|
||||
|
||||
<h3>radio with unchanged value</h3>
|
||||
<input type="radio" id="unchanged10" name="group2">Radio 4</input>
|
||||
<input type="radio" id="unchanged11" name="group2">Radio 5</input>
|
||||
<input type="radio" id="unchanged12" name="group2" checked>Radio 6</input>
|
||||
|
||||
<h3>Changed field IDs</h3>
|
||||
<div id="changed"></div>
|
||||
<div id="inputFired"></div>
|
||||
<div id="changeFired"></div>
|
|
@ -230,7 +230,14 @@ TreePanel.prototype = {
|
|||
treeBox.minHeight = 10;
|
||||
treeBox.flex = 1;
|
||||
toolbarParent.insertBefore(treeBox, toolbar);
|
||||
this.createResizer();
|
||||
|
||||
let resizerTop =
|
||||
this.IUI.browser.ownerDocument.getElementById("inspector-top-resizer");
|
||||
let resizerEnd =
|
||||
this.IUI.browser.ownerDocument.getElementById("inspector-end-resizer");
|
||||
resizerTop.removeAttribute("disabled");
|
||||
resizerEnd.removeAttribute("disabled");
|
||||
|
||||
treeBox.appendChild(this.treeIFrame);
|
||||
|
||||
let boundLoadedInitializeTreePanel = function loadedInitializeTreePanel()
|
||||
|
@ -251,28 +258,19 @@ TreePanel.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Lame resizer on the toolbar.
|
||||
*/
|
||||
createResizer: function TP_createResizer()
|
||||
{
|
||||
let resizer = this.document.createElement("resizer");
|
||||
resizer.id = "inspector-horizontal-splitter";
|
||||
resizer.setAttribute("dir", "top");
|
||||
resizer.flex = 1;
|
||||
resizer.setAttribute("element", "inspector-tree-box");
|
||||
resizer.height = 24;
|
||||
this.IUI.toolbar.appendChild(resizer);
|
||||
this.resizer = resizer;
|
||||
},
|
||||
|
||||
/**
|
||||
* Close the TreePanel.
|
||||
*/
|
||||
close: function TP_close()
|
||||
{
|
||||
if (this.openInDock) {
|
||||
this.IUI.toolbar.removeChild(this.resizer);
|
||||
let resizerTop =
|
||||
this.IUI.browser.ownerDocument.getElementById("inspector-top-resizer");
|
||||
let resizerEnd =
|
||||
this.IUI.browser.ownerDocument.getElementById("inspector-end-resizer");
|
||||
resizerTop.setAttribute("disabled", "true");
|
||||
resizerEnd.setAttribute("disabled", "true");
|
||||
|
||||
let treeBox = this.container;
|
||||
let treeBoxParent = treeBox.parentNode;
|
||||
treeBoxParent.removeChild(treeBox);
|
||||
|
@ -679,8 +677,6 @@ TreePanel.prototype = {
|
|||
|
||||
domplateUtils.setDOM(null);
|
||||
|
||||
delete this.resizer;
|
||||
|
||||
if (this.DOMHelpers) {
|
||||
this.DOMHelpers.destroy();
|
||||
delete this.DOMHelpers;
|
||||
|
|
|
@ -681,17 +681,17 @@ SelectorView.prototype = {
|
|||
text: function SelectorView_text(aElement) {
|
||||
let result = this.selectorInfo.selector.text;
|
||||
if (this.selectorInfo.elementStyle) {
|
||||
if (this.tree.styleInspector.IUI) {
|
||||
if (this.selectorInfo.sourceElement == this.tree.styleInspector.IUI.selection)
|
||||
{
|
||||
result = "this";
|
||||
} else {
|
||||
result = CssLogic.getShortName(this.selectorInfo.sourceElement);
|
||||
}
|
||||
let source = this.selectorInfo.sourceElement;
|
||||
let IUI = this.tree.styleInspector.IUI;
|
||||
if (IUI && IUI.selection == source) {
|
||||
result = "this";
|
||||
} else {
|
||||
result = CssLogic.getShortName(source);
|
||||
}
|
||||
|
||||
aElement.parentNode.querySelector(".rule-link > a").
|
||||
addEventListener("click", function(aEvent) {
|
||||
this.tree.styleInspector.selectFromPath(this.selectorInfo.sourceElement);
|
||||
this.tree.styleInspector.selectFromPath(source);
|
||||
aEvent.preventDefault();
|
||||
}.bind(this), false);
|
||||
result += ".style";
|
||||
|
|
|
@ -606,10 +606,12 @@ CssLogic.prototype = {
|
|||
|
||||
/**
|
||||
* Check if the highlighted element or it's parents have matched selectors.
|
||||
* If aCallback is provided then the domRules for the element are passed to
|
||||
* the callback function.
|
||||
*
|
||||
* @param {function} [aCallback] Simple callback method
|
||||
* @param {function} [aCallback] Simple callback method. If aCallback is
|
||||
* provided then the domRules for each element in the loop are passed to
|
||||
* the callback function. When the element has .style properties, the callback
|
||||
* receives {style: element.style}. If the callback returns true then the
|
||||
* element has matched rules, otherwise not.
|
||||
* @return {Boolean} true if the current element or it's parents have
|
||||
* matching CssSelector objects, false otherwise
|
||||
*/
|
||||
|
@ -628,11 +630,22 @@ CssLogic.prototype = {
|
|||
continue;
|
||||
}
|
||||
|
||||
// Check if the are DOM rules that we can consider as matched rules
|
||||
// (depending on the callback).
|
||||
if (domRules.Count() && (!aCallback || aCallback(domRules))) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if the element has any element.style properties that we can
|
||||
// consider as "matched" (depending on the callback).
|
||||
if (element.style.length > 0 &&
|
||||
(!aCallback || aCallback({style: element.style}))) {
|
||||
matched = true;
|
||||
}
|
||||
|
||||
if (matched) {
|
||||
break;
|
||||
}
|
||||
} while ((element = element.parentNode) &&
|
||||
element.nodeType === Ci.nsIDOMNode.ELEMENT_NODE);
|
||||
|
||||
|
@ -1499,6 +1512,11 @@ CssPropertyInfo.prototype = {
|
|||
{
|
||||
if (this._hasMatchedSelectors === null) {
|
||||
this._hasMatchedSelectors = this._cssLogic.hasMatchedSelectors(function(aDomRules) {
|
||||
if (!aDomRules.Count) {
|
||||
// For element.style.
|
||||
return !!aDomRules.style.getPropertyValue(this.property);
|
||||
}
|
||||
|
||||
for (let i = 0; i < aDomRules.Count(); i++) {
|
||||
let domRule = aDomRules.GetElementAt(i);
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ _BROWSER_TEST_FILES = \
|
|||
browser_bug683672.js \
|
||||
browser_styleinspector_bug_672746_default_styles.js \
|
||||
browser_styleinspector_bug_672744_search_filter.js \
|
||||
browser_bug_692400_element_style.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests for selector text errors.
|
||||
|
||||
let doc;
|
||||
let stylePanel;
|
||||
|
||||
function createDocument()
|
||||
{
|
||||
doc.body.innerHTML = "<div style='color:blue;'></div>";
|
||||
|
||||
doc.title = "Style Inspector Selector Text Test";
|
||||
ok(window.StyleInspector, "StyleInspector exists");
|
||||
stylePanel = new StyleInspector(window);
|
||||
|
||||
|
||||
stylePanel.createPanel(false, function() {
|
||||
Services.obs.addObserver(SI_checkText, "StyleInspector-populated", false);
|
||||
|
||||
let span = doc.querySelector("div");
|
||||
ok(span, "captain, we have the test div");
|
||||
stylePanel.open(span);
|
||||
});
|
||||
}
|
||||
|
||||
function SI_checkText()
|
||||
{
|
||||
Services.obs.removeObserver(SI_checkText, "StyleInspector-populated", false);
|
||||
|
||||
let propertyView = null;
|
||||
stylePanel.cssHtmlTree.propertyViews.some(function(aView) {
|
||||
if (aView.name == "color") {
|
||||
propertyView = aView;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
ok(propertyView, "found PropertyView for color");
|
||||
|
||||
is(propertyView.hasMatchedSelectors, true, "hasMatchedSelectors is true");
|
||||
|
||||
propertyView.matchedExpanded = true;
|
||||
propertyView.refreshMatchedSelectors();
|
||||
|
||||
let td = propertyView.matchedSelectorTable.querySelector("td.rule-text");
|
||||
ok(td, "found the first table row");
|
||||
|
||||
let selector = propertyView.matchedSelectorViews[0];
|
||||
ok(selector, "found the first matched selector view");
|
||||
|
||||
try {
|
||||
is(td.textContent.trim(), selector.humanReadableText(td).trim(),
|
||||
"selector text is correct");
|
||||
} catch (ex) {
|
||||
info("EXCEPTION: " + ex);
|
||||
ok(false, "getting the selector text should not raise an exception");
|
||||
}
|
||||
|
||||
Services.obs.addObserver(finishUp, "StyleInspector-closed", false);
|
||||
stylePanel.close();
|
||||
}
|
||||
|
||||
function finishUp()
|
||||
{
|
||||
Services.obs.removeObserver(finishUp, "StyleInspector-closed", false);
|
||||
doc = stylePanel = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
|
||||
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
|
||||
doc = content.document;
|
||||
waitForFocus(createDocument, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,selector text test, bug 692400";
|
||||
}
|
|
@ -164,7 +164,7 @@ function styleInspectorClosedByHide()
|
|||
{
|
||||
Services.obs.removeObserver(styleInspectorClosedByHide, "StyleInspector-closed", false);
|
||||
is(stylePanels[0].state, "open", "instance stylePanels[0] is still open");
|
||||
is(stylePanels[1].state, "closed", "instance stylePanels[1] is hidden");
|
||||
isnot(stylePanels[1].state, "open", "instance stylePanels[1] is not open");
|
||||
is(stylePanels[2].state, "open", "instance stylePanels[2] is still open");
|
||||
|
||||
info("closing web console");
|
||||
|
|
|
@ -38,82 +38,21 @@
|
|||
|
||||
let EXPORTED_SYMBOLS = [ "GcliCommands" ];
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
Components.utils.import("resource:///modules/gcli.jsm");
|
||||
Components.utils.import("resource:///modules/HUDService.jsm");
|
||||
|
||||
let bundleName = "chrome://browser/locale/devtools/gclicommands.properties";
|
||||
let stringBundle = Services.strings.createBundle(bundleName);
|
||||
|
||||
let gcli = gcli._internal.require("gcli/index");
|
||||
let canon = gcli._internal.require("gcli/canon");
|
||||
|
||||
|
||||
let document;
|
||||
|
||||
/**
|
||||
* The exported API
|
||||
*/
|
||||
let GcliCommands = {
|
||||
/**
|
||||
* Allow HUDService to inform us of the document against which we work
|
||||
*/
|
||||
setDocument: function GcliCommands_setDocument(aDocument) {
|
||||
document = aDocument;
|
||||
},
|
||||
|
||||
/**
|
||||
* Undo the effects of GcliCommands.setDocument()
|
||||
*/
|
||||
unsetDocument: function GcliCommands_unsetDocument() {
|
||||
document = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Lookup a string in the GCLI string bundle
|
||||
* @param aName The name to lookup
|
||||
* @return The looked up name
|
||||
*/
|
||||
function lookup(aName)
|
||||
{
|
||||
try {
|
||||
return stringBundle.GetStringFromName(aName);
|
||||
} catch (ex) {
|
||||
throw new Error("Failure in lookup('" + aName + "')");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Lookup a string in the GCLI string bundle
|
||||
* @param aName The name to lookup
|
||||
* @param aSwaps An array of swaps. See stringBundle.formatStringFromName
|
||||
* @return The looked up name
|
||||
*/
|
||||
function lookupFormat(aName, aSwaps)
|
||||
{
|
||||
try {
|
||||
return stringBundle.formatStringFromName(aName, aSwaps, aSwaps.length);
|
||||
} catch (ex) {
|
||||
Services.console.logStringMessage("Failure in lookupFormat('" + aName + "')");
|
||||
throw new Error("Failure in lookupFormat('" + aName + "')");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 'echo' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "echo",
|
||||
description: lookup("echoDesc"),
|
||||
description: gcli.lookup("echoDesc"),
|
||||
params: [
|
||||
{
|
||||
name: "message",
|
||||
type: "string",
|
||||
description: lookup("echoMessageDesc")
|
||||
description: gcli.lookup("echoMessageDesc")
|
||||
}
|
||||
],
|
||||
returnType: "string",
|
||||
|
@ -123,17 +62,19 @@ gcli.addCommand({
|
|||
});
|
||||
|
||||
|
||||
let canon = gcli._internal.require("gcli/canon");
|
||||
|
||||
/**
|
||||
* 'help' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "help",
|
||||
returnType: "html",
|
||||
description: lookup("helpDesc"),
|
||||
description: gcli.lookup("helpDesc"),
|
||||
exec: function Command_help(args, context) {
|
||||
let output = [];
|
||||
|
||||
output.push("<strong>" + lookup("helpAvailable") + ":</strong><br/>");
|
||||
output.push("<strong>" + gcli.lookup("helpAvailable") + ":</strong><br/>");
|
||||
|
||||
let commandNames = canon.getCommandNames();
|
||||
commandNames.sort();
|
||||
|
@ -160,8 +101,8 @@ gcli.addCommand({
|
|||
*/
|
||||
gcli.addCommand({
|
||||
name: "console",
|
||||
description: lookup("consoleDesc"),
|
||||
manual: lookup("consoleManual")
|
||||
description: gcli.lookup("consoleDesc"),
|
||||
manual: gcli.lookup("consoleManual")
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -169,10 +110,32 @@ gcli.addCommand({
|
|||
*/
|
||||
gcli.addCommand({
|
||||
name: "console clear",
|
||||
description: lookup("consoleclearDesc"),
|
||||
description: gcli.lookup("consoleclearDesc"),
|
||||
exec: function(args, context) {
|
||||
let hud = HUDService.getHudReferenceById(context.environment.hudId);
|
||||
hud.gcliterm.clearOutput();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 'inspect' command
|
||||
*/
|
||||
gcli.addCommand({
|
||||
name: "inspect",
|
||||
description: gcli.lookup("inspectDesc"),
|
||||
manual: gcli.lookup("inspectManual"),
|
||||
params: [
|
||||
{
|
||||
name: "node",
|
||||
type: "node",
|
||||
description: gcli.lookup("inspectNodeDesc"),
|
||||
manual: gcli.lookup("inspectNodeManual")
|
||||
}
|
||||
],
|
||||
exec: function Command_inspect(args, context) {
|
||||
let hud = HUDService.getHudReferenceById(context.environment.hudId);
|
||||
let InspectorUI = hud.gcliterm.document.defaultView.InspectorUI;
|
||||
InspectorUI.openInspectorUI(args.node);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -79,12 +79,6 @@ XPCOMUtils.defineLazyGetter(this, "gcli", function () {
|
|||
return obj.gcli;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "GcliCommands", function () {
|
||||
var obj = {};
|
||||
Cu.import("resource:///modules/GcliCommands.jsm", obj);
|
||||
return obj.GcliCommands;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "StyleInspector", function () {
|
||||
var obj = {};
|
||||
Cu.import("resource:///modules/devtools/StyleInspector.jsm", obj);
|
||||
|
@ -133,6 +127,23 @@ function LogFactory(aMessagePrefix)
|
|||
return log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the various Command JSMs.
|
||||
* Should be called when the console first opens.
|
||||
*
|
||||
* @return an object containing the EXPORTED_SYMBOLS from all the command
|
||||
* modules. In general there is no reason when JSMs need to export symbols
|
||||
* except when they need the host environment to inform them of things like the
|
||||
* current window/document/etc.
|
||||
*/
|
||||
function loadCommands() {
|
||||
let commandExports = {};
|
||||
|
||||
Cu.import("resource:///modules/GcliCommands.jsm", commandExports);
|
||||
|
||||
return commandExports;
|
||||
}
|
||||
|
||||
let log = LogFactory("*** HUDService:");
|
||||
|
||||
const HUD_STRINGS_URI = "chrome://global/locale/headsUpDisplay.properties";
|
||||
|
@ -6882,6 +6893,11 @@ catch (ex) {
|
|||
// GcliTerm
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Some commands need customization - this is how we get at them.
|
||||
*/
|
||||
let commandExports = undefined;
|
||||
|
||||
/**
|
||||
* GcliTerm
|
||||
*
|
||||
|
@ -6932,7 +6948,10 @@ function GcliTerm(aContentWindow, aHudId, aDocument, aConsole, aHintNode)
|
|||
|
||||
gcli._internal.commandOutputManager.addListener(this.onCommandOutput, this);
|
||||
gcli._internal.createView(this.opts);
|
||||
GcliCommands.setDocument(aContentWindow.document);
|
||||
|
||||
if (!commandExports) {
|
||||
commandExports = loadCommands();
|
||||
}
|
||||
}
|
||||
|
||||
GcliTerm.prototype = {
|
||||
|
@ -6957,7 +6976,6 @@ GcliTerm.prototype = {
|
|||
*/
|
||||
destroy: function Gcli_destroy()
|
||||
{
|
||||
GcliCommands.unsetDocument();
|
||||
gcli._internal.removeView(this.opts);
|
||||
gcli._internal.commandOutputManager.removeListener(this.onCommandOutput, this);
|
||||
|
||||
|
|
|
@ -630,11 +630,52 @@ var require = define.globalDomain.require.bind(define.globalDomain);
|
|||
* http://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
var mozl10n = {};
|
||||
|
||||
(function(aMozl10n) {
|
||||
var temp = {};
|
||||
Components.utils.import("resource://gre/modules/Services.jsm", temp);
|
||||
var stringBundle = temp.Services.strings.createBundle(
|
||||
"chrome://browser/locale/devtools/gclicommands.properties");
|
||||
|
||||
/**
|
||||
* Lookup a string in the GCLI string bundle
|
||||
* @param name The name to lookup
|
||||
* @return The looked up name
|
||||
*/
|
||||
aMozl10n.lookup = function(name) {
|
||||
try {
|
||||
return stringBundle.GetStringFromName(name);
|
||||
}
|
||||
catch (ex) {
|
||||
throw new Error("Failure in lookup('" + name + "')");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Lookup a string in the GCLI string bundle
|
||||
* @param name The name to lookup
|
||||
* @param swaps An array of swaps. See stringBundle.formatStringFromName
|
||||
* @return The looked up name
|
||||
*/
|
||||
aMozl10n.lookupFormat = function(name, swaps) {
|
||||
try {
|
||||
return stringBundle.formatStringFromName(name, swaps, swaps.length);
|
||||
}
|
||||
catch (ex) {
|
||||
throw new Error("Failure in lookupFormat('" + name + "')");
|
||||
}
|
||||
};
|
||||
|
||||
})(mozl10n);
|
||||
|
||||
define('gcli/index', ['require', 'exports', 'module' , 'gcli/canon', 'gcli/types/basic', 'gcli/types/javascript', 'gcli/types/node', 'gcli/cli', 'gcli/ui/inputter', 'gcli/ui/arg_fetch', 'gcli/ui/menu', 'gcli/ui/focus'], function(require, exports, module) {
|
||||
|
||||
// The API for use by command authors
|
||||
exports.addCommand = require('gcli/canon').addCommand;
|
||||
exports.removeCommand = require('gcli/canon').removeCommand;
|
||||
exports.lookup = mozl10n.lookup;
|
||||
exports.lookupFormat = mozl10n.lookupFormat;
|
||||
|
||||
// Internal startup process. Not exported
|
||||
require('gcli/types/basic').startup();
|
||||
|
@ -3437,9 +3478,10 @@ exports.JavascriptType = JavascriptType;
|
|||
* http://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
define('gcli/types/node', ['require', 'exports', 'module' , 'gcli/l10n', 'gcli/types'], function(require, exports, module) {
|
||||
define('gcli/types/node', ['require', 'exports', 'module' , 'gcli/host', 'gcli/l10n', 'gcli/types'], function(require, exports, module) {
|
||||
|
||||
|
||||
var host = require('gcli/host');
|
||||
var l10n = require('gcli/l10n');
|
||||
var types = require('gcli/types');
|
||||
var Type = require('gcli/types').Type;
|
||||
|
@ -3521,13 +3563,13 @@ NodeType.prototype.parse = function(arg) {
|
|||
var node = nodes.item(0);
|
||||
node.__gcliQuery = arg.text;
|
||||
|
||||
flashNode(node, 'green');
|
||||
host.flashNode(node, 'green');
|
||||
|
||||
return new Conversion(node, arg, Status.VALID, '');
|
||||
}
|
||||
|
||||
Array.prototype.forEach.call(nodes, function(n) {
|
||||
flashNode(n, 'red');
|
||||
host.flashNode(n, 'red');
|
||||
});
|
||||
|
||||
return new Conversion(null, arg, Status.ERROR,
|
||||
|
@ -3537,11 +3579,21 @@ NodeType.prototype.parse = function(arg) {
|
|||
NodeType.prototype.name = 'node';
|
||||
|
||||
|
||||
});
|
||||
/*
|
||||
* Copyright 2009-2011 Mozilla Foundation and contributors
|
||||
* Licensed under the New BSD license. See LICENSE.txt or:
|
||||
* http://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
define('gcli/host', ['require', 'exports', 'module' ], function(require, exports, module) {
|
||||
|
||||
|
||||
/**
|
||||
* Helper to turn a node background it's complementary color for 1 second.
|
||||
* There is likely a better way to do this, but this will do for now.
|
||||
*/
|
||||
function flashNode(node, color) {
|
||||
exports.flashNode = function(node, color) {
|
||||
if (!node.__gcliHighlighting) {
|
||||
node.__gcliHighlighting = true;
|
||||
var original = node.style.background;
|
||||
|
@ -3551,7 +3603,7 @@ function flashNode(node, color) {
|
|||
delete node.__gcliHighlighting;
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
});
|
||||
|
@ -4197,16 +4249,17 @@ Requisition.prototype._onCommandAssignmentChange = function(ev) {
|
|||
/**
|
||||
* Assignments have an order, so we need to store them in an array.
|
||||
* But we also need named access ...
|
||||
* @return The found assignment, or undefined, if no match was found
|
||||
*/
|
||||
Requisition.prototype.getAssignment = function(nameOrNumber) {
|
||||
var name = (typeof nameOrNumber === 'string') ?
|
||||
nameOrNumber :
|
||||
Object.keys(this._assignments)[nameOrNumber];
|
||||
return this._assignments[name];
|
||||
return this._assignments[name] || undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* Where parameter name == assignment names - they are the same.
|
||||
* Where parameter name == assignment names - they are the same
|
||||
*/
|
||||
Requisition.prototype.getParameterNames = function() {
|
||||
return Object.keys(this._assignments);
|
||||
|
@ -5041,210 +5094,8 @@ ExecutionContext.prototype.createPromise = function() {
|
|||
|
||||
define('gcli/promise', ['require', 'exports', 'module' ], function(require, exports, module) {
|
||||
|
||||
|
||||
/**
|
||||
* Create an unfulfilled promise
|
||||
* @constructor
|
||||
*/
|
||||
function Promise() {
|
||||
this._status = Promise.PENDING;
|
||||
this._value = undefined;
|
||||
this._onSuccessHandlers = [];
|
||||
this._onErrorHandlers = [];
|
||||
|
||||
// Debugging help
|
||||
this._id = Promise._nextId++;
|
||||
Promise._outstanding[this._id] = this;
|
||||
};
|
||||
|
||||
/**
|
||||
* We give promises and ID so we can track which are outstanding
|
||||
*/
|
||||
Promise._nextId = 0;
|
||||
|
||||
/**
|
||||
* Outstanding promises. Handy list for debugging only.
|
||||
*/
|
||||
Promise._outstanding = [];
|
||||
|
||||
/**
|
||||
* Recently resolved promises. Also for debugging only.
|
||||
*/
|
||||
Promise._recent = [];
|
||||
|
||||
/**
|
||||
* A promise can be in one of 2 states.
|
||||
* The ERROR and SUCCESS states are terminal, the PENDING state is the only
|
||||
* start state.
|
||||
*/
|
||||
Promise.ERROR = -1;
|
||||
Promise.PENDING = 0;
|
||||
Promise.SUCCESS = 1;
|
||||
|
||||
/**
|
||||
* Yeay for RTTI.
|
||||
*/
|
||||
Promise.prototype.isPromise = true;
|
||||
|
||||
/**
|
||||
* Have we either been resolve()ed or reject()ed?
|
||||
*/
|
||||
Promise.prototype.isComplete = function() {
|
||||
return this._status != Promise.PENDING;
|
||||
};
|
||||
|
||||
/**
|
||||
* Have we resolve()ed?
|
||||
*/
|
||||
Promise.prototype.isResolved = function() {
|
||||
return this._status == Promise.SUCCESS;
|
||||
};
|
||||
|
||||
/**
|
||||
* Have we reject()ed?
|
||||
*/
|
||||
Promise.prototype.isRejected = function() {
|
||||
return this._status == Promise.ERROR;
|
||||
};
|
||||
|
||||
/**
|
||||
* Take the specified action of fulfillment of a promise, and (optionally)
|
||||
* a different action on promise rejection.
|
||||
*/
|
||||
Promise.prototype.then = function(onSuccess, onError) {
|
||||
if (typeof onSuccess === 'function') {
|
||||
if (this._status === Promise.SUCCESS) {
|
||||
onSuccess.call(null, this._value);
|
||||
} else if (this._status === Promise.PENDING) {
|
||||
this._onSuccessHandlers.push(onSuccess);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof onError === 'function') {
|
||||
if (this._status === Promise.ERROR) {
|
||||
onError.call(null, this._value);
|
||||
} else if (this._status === Promise.PENDING) {
|
||||
this._onErrorHandlers.push(onError);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Like then() except that rather than returning <tt>this</tt> we return
|
||||
* a promise which resolves when the original promise resolves.
|
||||
*/
|
||||
Promise.prototype.chainPromise = function(onSuccess) {
|
||||
var chain = new Promise();
|
||||
chain._chainedFrom = this;
|
||||
this.then(function(data) {
|
||||
try {
|
||||
chain.resolve(onSuccess(data));
|
||||
} catch (ex) {
|
||||
chain.reject(ex);
|
||||
}
|
||||
}, function(ex) {
|
||||
chain.reject(ex);
|
||||
});
|
||||
return chain;
|
||||
};
|
||||
|
||||
/**
|
||||
* Supply the fulfillment of a promise
|
||||
*/
|
||||
Promise.prototype.resolve = function(data) {
|
||||
return this._complete(this._onSuccessHandlers, Promise.SUCCESS, data, 'resolve');
|
||||
};
|
||||
|
||||
/**
|
||||
* Renege on a promise
|
||||
*/
|
||||
Promise.prototype.reject = function(data) {
|
||||
return this._complete(this._onErrorHandlers, Promise.ERROR, data, 'reject');
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal method to be called on resolve() or reject().
|
||||
* @private
|
||||
*/
|
||||
Promise.prototype._complete = function(list, status, data, name) {
|
||||
// Complain if we've already been completed
|
||||
if (this._status != Promise.PENDING) {
|
||||
console.group('Promise already closed');
|
||||
console.error('Attempted ' + name + '() with ', data);
|
||||
console.error('Previous status = ', this._status,
|
||||
', previous value = ', this._value);
|
||||
console.trace();
|
||||
|
||||
console.groupEnd();
|
||||
return this;
|
||||
}
|
||||
|
||||
this._status = status;
|
||||
this._value = data;
|
||||
|
||||
// Call all the handlers, and then delete them
|
||||
list.forEach(function(handler) {
|
||||
handler.call(null, this._value);
|
||||
}, this);
|
||||
delete this._onSuccessHandlers;
|
||||
delete this._onErrorHandlers;
|
||||
|
||||
// Remove the given {promise} from the _outstanding list, and add it to the
|
||||
// _recent list, pruning more than 20 recent promises from that list.
|
||||
delete Promise._outstanding[this._id];
|
||||
Promise._recent.push(this);
|
||||
while (Promise._recent.length > 20) {
|
||||
Promise._recent.shift();
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes an array of promises and returns a promise that that is fulfilled once
|
||||
* all the promises in the array are fulfilled
|
||||
* @param promiseList The array of promises
|
||||
* @return the promise that is fulfilled when all the array is fulfilled
|
||||
*/
|
||||
Promise.group = function(promiseList) {
|
||||
if (!(promiseList instanceof Array)) {
|
||||
promiseList = Array.prototype.slice.call(arguments);
|
||||
}
|
||||
|
||||
// If the original array has nothing in it, return now to avoid waiting
|
||||
if (promiseList.length === 0) {
|
||||
return new Promise().resolve([]);
|
||||
}
|
||||
|
||||
var groupPromise = new Promise();
|
||||
var results = [];
|
||||
var fulfilled = 0;
|
||||
|
||||
var onSuccessFactory = function(index) {
|
||||
return function(data) {
|
||||
results[index] = data;
|
||||
fulfilled++;
|
||||
// If the group has already failed, silently drop extra results
|
||||
if (groupPromise._status !== Promise.ERROR) {
|
||||
if (fulfilled === promiseList.length) {
|
||||
groupPromise.resolve(results);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
promiseList.forEach(function(promise, index) {
|
||||
var onSuccess = onSuccessFactory(index);
|
||||
var onError = groupPromise.reject.bind(groupPromise);
|
||||
promise.then(onSuccess, onError);
|
||||
});
|
||||
|
||||
return groupPromise;
|
||||
};
|
||||
|
||||
exports.Promise = Promise;
|
||||
Components.utils.import("resource:///modules/devtools/Promise.jsm");
|
||||
exports.Promise = Promise;
|
||||
|
||||
});
|
||||
/*
|
||||
|
|
|
@ -145,8 +145,9 @@ _BROWSER_TEST_FILES = \
|
|||
browser_webconsole_bug_659907_console_dir.js \
|
||||
browser_webconsole_bug_678816.js \
|
||||
browser_webconsole_bug_664131_console_group.js \
|
||||
browser_gcli_require.js \
|
||||
browser_gcli_inspect.js \
|
||||
browser_gcli_integrate.js \
|
||||
browser_gcli_require.js \
|
||||
browser_gcli_web.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
@ -218,6 +219,7 @@ _BROWSER_TEST_PAGES = \
|
|||
test-bug-646025-console-file-location.html \
|
||||
test-bug-678816-content.js \
|
||||
test-file-location.js \
|
||||
browser_gcli_inspect.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>GCLI inspect command test</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- This is a list of 0 h1 elements -->
|
||||
|
||||
<!-- This is a list of 1 div elements -->
|
||||
<div>Hello, I'm a div</div>
|
||||
|
||||
<!-- This is a list of 2 span elements -->
|
||||
<span>Hello, I'm a span</span>
|
||||
<span>And me</span>
|
||||
|
||||
<!-- This is a collection of various things that match only once -->
|
||||
<p class="someclass">.someclass</p>
|
||||
<p id="someid">#someid</p>
|
||||
<button disabled>button[disabled]</button>
|
||||
<p><strong>p>strong</strong></p>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,93 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// For more information on GCLI see:
|
||||
// - https://github.com/mozilla/gcli/blob/master/docs/index.md
|
||||
// - https://wiki.mozilla.org/DevTools/Features/GCLI
|
||||
|
||||
// Tests that the inspect command works as it should
|
||||
|
||||
Components.utils.import("resource:///modules/gcli.jsm");
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
gcliterm = undefined;
|
||||
requisition = undefined;
|
||||
|
||||
Services.prefs.clearUserPref("devtools.gcli.enable");
|
||||
});
|
||||
|
||||
function test() {
|
||||
Services.prefs.setBoolPref("devtools.gcli.enable", true);
|
||||
addTab("http://example.com/browser/browser/devtools/webconsole/test/browser/browser_gcli_inspect.html");
|
||||
browser.addEventListener("DOMContentLoaded", onLoad, false);
|
||||
}
|
||||
|
||||
let gcliterm;
|
||||
let requisition;
|
||||
|
||||
function onLoad() {
|
||||
browser.removeEventListener("DOMContentLoaded", onLoad, false);
|
||||
|
||||
try {
|
||||
openConsole();
|
||||
|
||||
let hud = HUDService.getHudByWindow(content);
|
||||
gcliterm = hud.gcliterm;
|
||||
requisition = gcliterm.opts.requisition;
|
||||
|
||||
testSetup();
|
||||
testCreateCommands();
|
||||
}
|
||||
catch (ex) {
|
||||
ok(false, "Caught exception: " + ex)
|
||||
gcli._internal.console.error("Test Failure", ex);
|
||||
}
|
||||
finally {
|
||||
closeConsole();
|
||||
finishTest();
|
||||
}
|
||||
}
|
||||
|
||||
function testSetup() {
|
||||
ok(gcliterm, "We have a GCLI term");
|
||||
ok(requisition, "We have a Requisition");
|
||||
}
|
||||
|
||||
function testCreateCommands() {
|
||||
type("inspec");
|
||||
is(gcliterm.completeNode.textContent, " inspect", "Completion for \"inspec\"");
|
||||
is(requisition.getStatus().toString(), "ERROR", "inspec is ERROR");
|
||||
|
||||
type("inspect");
|
||||
is(requisition.getStatus().toString(), "ERROR", "inspect is ERROR");
|
||||
|
||||
type("inspect h1");
|
||||
is(requisition.getStatus().toString(), "ERROR", "inspect h1 is ERROR");
|
||||
|
||||
type("inspect span");
|
||||
is(requisition.getStatus().toString(), "ERROR", "inspect span is ERROR");
|
||||
|
||||
type("inspect div");
|
||||
is(requisition.getStatus().toString(), "VALID", "inspect div is VALID");
|
||||
|
||||
type("inspect .someclass");
|
||||
is(requisition.getStatus().toString(), "VALID", "inspect .someclass is VALID");
|
||||
|
||||
type("inspect #someid");
|
||||
is(requisition.getStatus().toString(), "VALID", "inspect #someid is VALID");
|
||||
|
||||
type("inspect button[disabled]");
|
||||
is(requisition.getStatus().toString(), "VALID", "inspect button[disabled] is VALID");
|
||||
|
||||
type("inspect p>strong");
|
||||
is(requisition.getStatus().toString(), "VALID", "inspect p>strong is VALID");
|
||||
|
||||
type("inspect :root");
|
||||
is(requisition.getStatus().toString(), "VALID", "inspect :root is VALID");
|
||||
}
|
||||
|
||||
function type(command) {
|
||||
gcliterm.inputNode.value = command.slice(0, -1);
|
||||
gcliterm.inputNode.focus();
|
||||
EventUtils.synthesizeKey(command.slice(-1), {});
|
||||
}
|
|
@ -54,7 +54,7 @@ var Node = Components.interfaces.nsIDOMNode;
|
|||
* http://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
define('gclitest/index', ['require', 'exports', 'module' , 'gcli/index', 'test/examiner', 'gclitest/testTokenize', 'gclitest/testSplit', 'gclitest/testCli', 'gclitest/testHistory', 'gclitest/testRequire'], function(require, exports, module) {
|
||||
define('gclitest/suite', ['require', 'exports', 'module' , 'gcli/index', 'test/examiner', 'gclitest/testTokenize', 'gclitest/testSplit', 'gclitest/testCli', 'gclitest/testHistory', 'gclitest/testRequire'], function(require, exports, module) {
|
||||
|
||||
// We need to make sure GCLI is initialized before we begin testing it
|
||||
require('gcli/index');
|
||||
|
@ -65,7 +65,6 @@ define('gclitest/index', ['require', 'exports', 'module' , 'gcli/index', 'test/e
|
|||
examiner.addSuite('gclitest/testSplit', require('gclitest/testSplit'));
|
||||
examiner.addSuite('gclitest/testCli', require('gclitest/testCli'));
|
||||
examiner.addSuite('gclitest/testHistory', require('gclitest/testHistory'));
|
||||
|
||||
examiner.addSuite('gclitest/testRequire', require('gclitest/testRequire'));
|
||||
|
||||
examiner.run();
|
||||
|
@ -1373,7 +1372,7 @@ define('gclitest/requirable', ['require', 'exports', 'module' ], function(requir
|
|||
});
|
||||
|
||||
function undefine() {
|
||||
delete define.modules['gclitest/index'];
|
||||
delete define.modules['gclitest/suite'];
|
||||
delete define.modules['test/examiner'];
|
||||
delete define.modules['gclitest/testTokenize'];
|
||||
delete define.modules['test/assert'];
|
||||
|
@ -1384,7 +1383,7 @@ function undefine() {
|
|||
delete define.modules['gclitest/testRequire'];
|
||||
delete define.modules['gclitest/requirable'];
|
||||
|
||||
delete define.globalDomain.modules['gclitest/index'];
|
||||
delete define.globalDomain.modules['gclitest/suite'];
|
||||
delete define.globalDomain.modules['test/examiner'];
|
||||
delete define.globalDomain.modules['gclitest/testTokenize'];
|
||||
delete define.globalDomain.modules['test/assert'];
|
||||
|
|
|
@ -35,3 +35,25 @@ consoleManual=Filter, clear and close the web console
|
|||
# LOCALIZATION NOTE (consoleclearDesc) A very short string used to describe the
|
||||
# function of the 'console clear' command.
|
||||
consoleclearDesc=Clear the console
|
||||
|
||||
# LOCALIZATION NOTE (inspectDesc) A very short description of the 'inspect'
|
||||
# command. See inspectManual for a fuller description of what it does. This
|
||||
# string is designed to be shown in a menu alongside the command name, which
|
||||
# is why it should be as short as possible.
|
||||
inspectDesc=Inspect a node
|
||||
|
||||
# LOCALIZATION NOTE (inspectManual) A fuller description of the 'inspect'
|
||||
# command, displayed when the user asks for help on what it does.
|
||||
inspectManual=Investigate the dimensions and properties of an element using \
|
||||
a CSS selector to open the DOM highlighter
|
||||
|
||||
# LOCALIZATION NOTE (inspectNodeDesc) A very short string to describe the
|
||||
# 'node' parameter to the 'inspect' command, which is displayed in a dialog
|
||||
# when the user is using this command.
|
||||
inspectNodeDesc=CSS selector
|
||||
|
||||
# LOCALIZATION NOTE (inspectNodeManual) A fuller description of the 'node'
|
||||
# parameter to the 'inspect' command, displayed when the user asks for help
|
||||
# on what it does.
|
||||
inspectNodeManual=A CSS selector for use with Document.querySelector which \
|
||||
identifies a single element
|
||||
|
|
|
@ -1954,7 +1954,7 @@ panel[dimmed="true"] {
|
|||
|
||||
#inspector-toolbar {
|
||||
-moz-appearance: none;
|
||||
padding: 4px 3px;
|
||||
padding: 0 3px 4px;
|
||||
border-top: 1px solid hsla(210, 8%, 5%, .65);
|
||||
box-shadow: 0 1px 0 0 hsla(210, 16%, 76%, .2) inset;
|
||||
background-image: -moz-linear-gradient(top, hsl(210,11%,36%), hsl(210,11%,18%));
|
||||
|
@ -1998,15 +1998,35 @@ panel[dimmed="true"] {
|
|||
background-color: hsla(210,8%,5%,.2) !important;
|
||||
}
|
||||
|
||||
/*
|
||||
* need a "bumpy" background image for this!
|
||||
*/
|
||||
#inspector-horizontal-splitter {
|
||||
background: none !important;
|
||||
/* Highlighter - toolbar resizers */
|
||||
|
||||
.inspector-resizer {
|
||||
-moz-appearance: none;
|
||||
cursor: n-resize;
|
||||
}
|
||||
|
||||
.inspector-resizer[disabled] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#inspector-top-resizer {
|
||||
background: none;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
#inspector-end-resizer {
|
||||
width: 12px;
|
||||
height: 8px;
|
||||
background-image: -moz-linear-gradient(top, black 1px, rgba(255,255,255,0.2) 1px);
|
||||
background-size: 10px 2px;
|
||||
background-clip: padding-box;
|
||||
background-repeat: repeat-y;
|
||||
border-width: 1px 1px 0;
|
||||
border-style: solid;
|
||||
border-color: rgba(255, 255, 255, 0.05);
|
||||
margin: 7px 7px 8px;
|
||||
}
|
||||
|
||||
/* Highlighter - Node Infobar */
|
||||
|
||||
/* Highlighter - Node Infobar - text */
|
||||
|
|
|
@ -2549,7 +2549,7 @@ panel[dimmed="true"] {
|
|||
|
||||
#inspector-toolbar {
|
||||
-moz-appearance: none;
|
||||
padding: 4px 3px;
|
||||
padding: 0 3px 4px;
|
||||
border-top: 1px solid hsla(210, 8%, 5%, .65);
|
||||
box-shadow: 0 1px 0 0 hsla(210, 16%, 76%, .2) inset;
|
||||
background-image: -moz-linear-gradient(top, hsl(210,11%,36%), hsl(210,11%,18%));
|
||||
|
@ -2593,15 +2593,35 @@ panel[dimmed="true"] {
|
|||
background-color: hsla(210,8%,5%,.2);
|
||||
}
|
||||
|
||||
/*
|
||||
* need a "bumpy" background image for this!
|
||||
*/
|
||||
#inspector-horizontal-splitter {
|
||||
background: none !important;
|
||||
/* Highlighter - toolbar resizers */
|
||||
|
||||
.inspector-resizer {
|
||||
-moz-appearance: none;
|
||||
cursor: n-resize;
|
||||
}
|
||||
|
||||
.inspector-resizer[disabled] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#inspector-top-resizer {
|
||||
background: none;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
#inspector-end-resizer {
|
||||
width: 12px;
|
||||
height: 8px;
|
||||
background-image: -moz-linear-gradient(top, black 1px, rgba(255,255,255,0.2) 1px);
|
||||
background-size: 10px 2px;
|
||||
background-clip: padding-box;
|
||||
background-repeat: repeat-y;
|
||||
border-width: 1px 1px 0;
|
||||
border-style: solid;
|
||||
border-color: rgba(255, 255, 255, 0.05);
|
||||
margin: 7px 7px 8px;
|
||||
}
|
||||
|
||||
/* Highlighter - Node Infobar */
|
||||
|
||||
/* Highlighter - Node Infobar - text */
|
||||
|
|
|
@ -2647,7 +2647,7 @@ panel[dimmed="true"] {
|
|||
|
||||
#inspector-toolbar {
|
||||
-moz-appearance: none;
|
||||
padding: 4px 3px;
|
||||
padding: 0 3px 4px;
|
||||
border-top: 1px solid hsla(211,68%,6%,.65) !important;
|
||||
box-shadow: 0 1px 0 hsla(209,29%,72%,.25) inset;
|
||||
background-image: -moz-linear-gradient(top, hsl(209,18%,34%), hsl(210,24%,16%));
|
||||
|
@ -2691,15 +2691,35 @@ panel[dimmed="true"] {
|
|||
background-color: hsla(211,68%,6%,.2);
|
||||
}
|
||||
|
||||
/*
|
||||
* need a "bumpy" background image for this!
|
||||
*/
|
||||
#inspector-horizontal-splitter {
|
||||
background: none !important;
|
||||
/* Highlighter - toolbar resizers */
|
||||
|
||||
.inspector-resizer {
|
||||
-moz-appearance: none;
|
||||
cursor: n-resize;
|
||||
}
|
||||
|
||||
.inspector-resizer[disabled] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#inspector-top-resizer {
|
||||
background: none;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
#inspector-end-resizer {
|
||||
width: 12px;
|
||||
height: 8px;
|
||||
background-image: -moz-linear-gradient(top, black 1px, rgba(255,255,255,0.2) 1px);
|
||||
background-size: 10px 2px;
|
||||
background-clip: padding-box;
|
||||
background-repeat: repeat-y;
|
||||
border-width: 1px 1px 0;
|
||||
border-style: solid;
|
||||
border-color: rgba(255, 255, 255, 0.05);
|
||||
margin: 7px 7px 8px;
|
||||
}
|
||||
|
||||
/* Highlighter - Node Infobar */
|
||||
|
||||
/* Highlighter - Node Infobar - text */
|
||||
|
|
|
@ -201,6 +201,9 @@ ConsoleAPI.prototype = {
|
|||
}
|
||||
let args = Array.prototype.slice.call(aArguments);
|
||||
let format = args.shift();
|
||||
if (typeof format != "string") {
|
||||
return aArguments;
|
||||
}
|
||||
// Format specification regular expression.
|
||||
let pattern = /%(\d*).?(\d*)[a-zA-Z]/g;
|
||||
let processed = format.replace(pattern, function CA_PA_substitute(spec) {
|
||||
|
|
|
@ -220,10 +220,15 @@ function observeConsoleTest() {
|
|||
expect("log", "2, a, %l", 3);
|
||||
win.console.log("%d, %s, %l", 2, "a", 3);
|
||||
|
||||
// bug #692550 handle null and undefined
|
||||
// Bug #692550 handle null and undefined.
|
||||
expect("log", "null, undefined");
|
||||
win.console.log("%s, %s", null, undefined);
|
||||
|
||||
// Bug #696288 handle object as first argument.
|
||||
let obj = { a: 1 };
|
||||
expect("log", obj, "a");
|
||||
win.console.log(obj, "a");
|
||||
|
||||
expect("dir", win.toString());
|
||||
win.console.dir(win);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -38,7 +38,8 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "mozilla/dom/CrashReporterChild.h"
|
||||
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "nsXULAppAPI.h"
|
||||
|
@ -1551,7 +1552,21 @@ nsresult GetSubmitReports(bool* aSubmitReports)
|
|||
|
||||
nsresult SetSubmitReports(bool aSubmitReports)
|
||||
{
|
||||
return PrefSubmitReports(&aSubmitReports, true);
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIObserverService> obsServ =
|
||||
mozilla::services::GetObserverService();
|
||||
if (!obsServ) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = PrefSubmitReports(&aSubmitReports, true);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
obsServ->NotifyObservers(nsnull, "submit-reports-pref-changed", nsnull);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// The "pending" dir is Crash Reports/pending, from which minidumps
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
<!ENTITY reloadPlugin.pre "">
|
||||
<!ENTITY reloadPlugin.middle "Reload the page">
|
||||
<!ENTITY reloadPlugin.post " to try again.">
|
||||
<!-- LOCALIZATION NOTE (report.please): This and the other report.* strings should be as short as possible, ideally 2-3 words. -->
|
||||
<!ENTITY report.please "Send crash report">
|
||||
<!-- LOCALIZATION NOTE: report.* strings should be as short as possible, ideally 2-3 words. -->
|
||||
<!ENTITY report.checkbox "…and send crash report">
|
||||
<!ENTITY report.submitting "Sending report…">
|
||||
<!ENTITY report.submitted "Crash report sent.">
|
||||
<!ENTITY report.disabled "Crash reporting disabled.">
|
||||
|
|
|
@ -68,15 +68,17 @@
|
|||
</html:div>
|
||||
<html:div class="msg msgManagePlugins"><html:a class="managePluginsLink" href="">&managePlugins;</html:a></html:div>
|
||||
<html:div class="submitStatus">
|
||||
<!-- links set at runtime -->
|
||||
<html:div class="msg msgPleaseSubmit"><html:a class="pleaseSubmitLink" href="">&report.please;</html:a></html:div>
|
||||
<!-- link href set at runtime -->
|
||||
<html:div class="msg msgReload">&reloadPlugin.pre;<html:a class="reloadLink" href="">&reloadPlugin.middle;</html:a>&reloadPlugin.post;</html:div>
|
||||
<html:div class="msg msgSubmitPlease">
|
||||
<html:input id="pleaseSubmitCheckbox" type="checkbox" class="pleaseSubmitCheckbox" />
|
||||
<html:label for="pleaseSubmitCheckbox">&report.checkbox;</html:label>
|
||||
</html:div>
|
||||
<html:div class="msg msgSubmitting">&report.submitting;<html:span class="throbber"> </html:span></html:div>
|
||||
<html:div class="msg msgSubmitted">&report.submitted;</html:div>
|
||||
<html:div class="msg msgNotSubmitted">&report.disabled;</html:div>
|
||||
<html:div class="msg msgSubmitFailed">&report.failed;</html:div>
|
||||
<html:div class="msg msgNoCrashReport">&report.unavailable;</html:div>
|
||||
<!-- link href set at runtime -->
|
||||
<html:div class="msg msgReload">&reloadPlugin.pre;<html:a class="reloadLink" href="">&reloadPlugin.middle;</html:a>&reloadPlugin.post;</html:div>
|
||||
</html:div>
|
||||
<xul:spacer flex="1"/>
|
||||
<html:div class="msg msgBottomLinks">
|
||||
|
|
|
@ -55,19 +55,14 @@ html|applet:not([height]), html|applet[height=""] {
|
|||
}
|
||||
|
||||
.submitStatus[status="noReport"] .msgNoCrashReport,
|
||||
.submitStatus[status="please"] .msgPleaseSubmit,
|
||||
.submitStatus[status="noSubmit"] .msgNotSubmitted,
|
||||
.submitStatus[status="submitting"] .msgSubmitting,
|
||||
.submitStatus[status="success"] .msgSubmitted,
|
||||
.submitStatus[status="failed"] .msgSubmitFailed,
|
||||
.submitStatus[status]:not([status="please"]) .msgReload {
|
||||
.submitStatus[status="please"] .msgSubmitPlease,
|
||||
.submitStatus .msgReload {
|
||||
display: block;
|
||||
}
|
||||
.submitStatus[status="please"] .msgReload {
|
||||
/* Take up space when invisible, so stuff doesn't shift upon reveal. */
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.helpIcon {
|
||||
cursor: pointer;
|
||||
|
|
Загрузка…
Ссылка в новой задаче