Merge fx-team to m-c.

This commit is contained in:
Ryan VanderMeulen 2014-06-03 14:41:54 -04:00
commit 9305d5716f
24 changed files with 510 additions and 56 deletions

View File

@ -85,7 +85,13 @@ add_task(function*() {
ok(otherTB.querySelector("#sync-button"), "Sync button is on other toolbar, too."); ok(otherTB.querySelector("#sync-button"), "Sync button is on other toolbar, too.");
let wasInformedCorrectlyOfAreaDisappearing = false; let wasInformedCorrectlyOfAreaDisappearing = false;
let windowClosed = null; //XXXgijs So we could be using promiseWindowClosed here. However, after
// repeated random oranges, I'm instead relying on onWindowClosed below to
// fire appropriately - it is linked to an unload event as well, and so
// reusing it prevents a potential race between unload handlers where the
// one from promiseWindowClosed could fire before the onWindowClosed
// (and therefore onAreaNodeRegistered) one, causing the test to fail.
let windowCloseDeferred = Promise.defer();
listener = { listener = {
onAreaNodeUnregistered: function(aArea, aNode, aReason) { onAreaNodeUnregistered: function(aArea, aNode, aReason) {
if (aArea == TOOLBARID) { if (aArea == TOOLBARID) {
@ -96,8 +102,7 @@ add_task(function*() {
}, },
onWindowClosed: function(aWindow) { onWindowClosed: function(aWindow) {
if (aWindow == otherWin) { if (aWindow == otherWin) {
info("Got window closed notification for correct window."); windowCloseDeferred.resolve(aWindow);
windowClosed = aWindow;
} else { } else {
info("Other window was closed!"); info("Other window was closed!");
info("Other window title: " + (aWindow.document && aWindow.document.title)); info("Other window title: " + (aWindow.document && aWindow.document.title));
@ -106,7 +111,8 @@ add_task(function*() {
}, },
}; };
CustomizableUI.addListener(listener); CustomizableUI.addListener(listener);
yield promiseWindowClosed(otherWin); otherWin.close();
let windowClosed = yield windowCloseDeferred.promise;
is(windowClosed, otherWin, "Window should have sent onWindowClosed notification."); is(windowClosed, otherWin, "Window should have sent onWindowClosed notification.");
ok(wasInformedCorrectlyOfAreaDisappearing, "Should be told about window closing."); ok(wasInformedCorrectlyOfAreaDisappearing, "Should be told about window closing.");

View File

@ -249,8 +249,13 @@ function openAndLoadWindow(aOptions, aWaitForDelayedStartup=false) {
} }
function promiseWindowClosed(win) { function promiseWindowClosed(win) {
let deferred = Promise.defer();
win.addEventListener("unload", function onunload() {
win.removeEventListener("unload", onunload);
deferred.resolve();
});
win.close(); win.close();
return waitForCondition(() => win.closed); return deferred.promise;
} }
function promisePanelShown(win) { function promisePanelShown(win) {

View File

@ -203,6 +203,11 @@ var gPermissionManager = {
{ {
if (aTopic == "perm-changed") { if (aTopic == "perm-changed") {
var permission = aSubject.QueryInterface(Components.interfaces.nsIPermission); var permission = aSubject.QueryInterface(Components.interfaces.nsIPermission);
// Ignore unrelated permission types.
if (permission.type != this._type)
return;
if (aData == "added") { if (aData == "added") {
this._addPermissionToList(permission); this._addPermissionToList(permission);
++this._view._rowCount; ++this._view._rowCount;

View File

@ -8,6 +8,7 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
this.EXPORTED_SYMBOLS = [ "BingTranslation" ]; this.EXPORTED_SYMBOLS = [ "BingTranslation" ];
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Log.jsm"); Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://gre/modules/Task.jsm");
@ -327,14 +328,16 @@ let BingTokenManager = {
let params = [ let params = [
"grant_type=client_credentials", "grant_type=client_credentials",
"scope=" + encodeURIComponent("http://api.microsofttranslator.com"), "scope=" + encodeURIComponent("http://api.microsofttranslator.com"),
"client_id=", "client_id=" +
"client_secret=" getAuthTokenParam("%BING_API_CLIENTID%", "browser.translation.bing.clientIdOverride"),
"client_secret=" +
getAuthTokenParam("%BING_API_KEY%", "browser.translation.bing.apiKeyOverride")
]; ];
let deferred = Promise.defer(); let deferred = Promise.defer();
this._pendingRequest = deferred.promise; this._pendingRequest = deferred.promise;
request.post(params.join("&"), function(err) { request.post(params.join("&"), function(err) {
this._pendingRequest = null; BingTokenManager._pendingRequest = null;
if (err) { if (err) {
deferred.reject(err); deferred.reject(err);
@ -367,3 +370,16 @@ function escapeXML(aStr) {
.replace("<", "&lt;", "g") .replace("<", "&lt;", "g")
.replace(">", "&gt;", "g"); .replace(">", "&gt;", "g");
} }
/**
* Fetch an auth token (clientID or client secret), which may be overridden by
* a pref if it's set.
*/
function getAuthTokenParam(key, prefName) {
let val;
try {
val = Services.prefs.getCharPref(prefName);
} catch(ex) {}
return encodeURIComponent(Services.urlFormatter.formatURL(val || key));
}

View File

@ -42,10 +42,10 @@
</xul:hbox> </xul:hbox>
<!-- translating --> <!-- translating -->
<xul:hbox class="translating-box" pack="center"> <xul:vbox class="translating-box" pack="center">
<xul:label class="translate-infobar-element" <xul:label class="translate-infobar-element"
value="&translation.translatingContent.label;"/> value="&translation.translatingContent.label;"/>
</xul:hbox> </xul:vbox>
<!-- translated --> <!-- translated -->
<xul:hbox class="translated-box" align="center"> <xul:hbox class="translated-box" align="center">
@ -58,11 +58,13 @@
</xul:menulist> </xul:menulist>
<xul:label class="translate-infobar-element" <xul:label class="translate-infobar-element"
value="&translation.translatedTo.label;"/> value="&translation.translatedTo.label;"/>
<xul:menulist anonid="toLanguage" <xul:menulist class="translate-infobar-element"
anonid="toLanguage"
oncommand="document.getBindingParent(this).translate()"> oncommand="document.getBindingParent(this).translate()">
<xul:menupopup/> <xul:menupopup/>
</xul:menulist> </xul:menulist>
<xul:label value="&translation.translatedToSuffix.label;"/> <xul:label class="translate-infobar-element"
value="&translation.translatedToSuffix.label;"/>
<xul:button anonid="showOriginal" <xul:button anonid="showOriginal"
class="translate-infobar-element" class="translate-infobar-element"
label="&translation.showOriginal.button;" label="&translation.showOriginal.button;"

View File

@ -113,6 +113,8 @@ skip-if = os == 'win' # bug 1005274
[browser_dbg_break-on-dom-06.js] [browser_dbg_break-on-dom-06.js]
[browser_dbg_break-on-dom-07.js] [browser_dbg_break-on-dom-07.js]
[browser_dbg_break-on-dom-08.js] [browser_dbg_break-on-dom-08.js]
[browser_dbg_break-on-dom-event.js]
skip-if = os == "mac" || e10s # Bug 895426
[browser_dbg_breakpoints-actual-location.js] [browser_dbg_breakpoints-actual-location.js]
[browser_dbg_breakpoints-break-on-last-line-of-script-on-reload.js] [browser_dbg_breakpoints-break-on-last-line-of-script-on-reload.js]
[browser_dbg_breakpoints-button-01.js] [browser_dbg_breakpoints-button-01.js]
@ -124,6 +126,7 @@ skip-if = os == 'win' # bug 1005274
[browser_dbg_breakpoints-highlight.js] [browser_dbg_breakpoints-highlight.js]
[browser_dbg_breakpoints-new-script.js] [browser_dbg_breakpoints-new-script.js]
[browser_dbg_breakpoints-pane.js] [browser_dbg_breakpoints-pane.js]
[browser_dbg_chrome-create.js]
[browser_dbg_chrome-debugging.js] [browser_dbg_chrome-debugging.js]
[browser_dbg_clean-exit-window.js] [browser_dbg_clean-exit-window.js]
skip-if = true # Bug 933950 (leaky test) skip-if = true # Bug 933950 (leaky test)
@ -165,6 +168,8 @@ skip-if = true # Bug 933950 (leaky test)
[browser_dbg_navigation.js] [browser_dbg_navigation.js]
[browser_dbg_no-page-sources.js] [browser_dbg_no-page-sources.js]
[browser_dbg_on-pause-highlight.js] [browser_dbg_on-pause-highlight.js]
[browser_dbg_on-pause-raise.js]
skip-if = os == "linux" || e10s # Bug 888811 & bug 891176
[browser_dbg_optimized-out-vars.js] [browser_dbg_optimized-out-vars.js]
[browser_dbg_panel-size.js] [browser_dbg_panel-size.js]
[browser_dbg_parser-01.js] [browser_dbg_parser-01.js]
@ -298,9 +303,3 @@ skip-if = (os == 'mac' || os == 'win') && (debug == false) # Bug 986166
[browser_dbg_variables-view-webidl.js] [browser_dbg_variables-view-webidl.js]
[browser_dbg_watch-expressions-01.js] [browser_dbg_watch-expressions-01.js]
[browser_dbg_watch-expressions-02.js] [browser_dbg_watch-expressions-02.js]
[browser_dbg_chrome-create.js]
skip-if = true # Test doesn't clean up after itself (bug 918507), but also bug 847558 on Linux
[browser_dbg_on-pause-raise.js]
skip-if = os == "linux" || e10s # Bug 888811 & bug 891176
[browser_dbg_break-on-dom-event.js]
skip-if = os == "mac" || e10s # Bug 895426

View File

@ -11,16 +11,16 @@
<!ENTITY color "Text and Background"> <!ENTITY color "Text and Background">
<!ENTITY textColor.label "Text:"> <!ENTITY textColor.label "Text:">
<!ENTITY textColor.accesskey "t"> <!ENTITY textColor.accesskey "T">
<!ENTITY backgroundColor.label "Background:"> <!ENTITY backgroundColor.label "Background:">
<!ENTITY backgroundColor.accesskey "b"> <!ENTITY backgroundColor.accesskey "B">
<!ENTITY useSystemColors.label "Use system colors"> <!ENTITY useSystemColors.label "Use system colors">
<!ENTITY useSystemColors.accesskey "s"> <!ENTITY useSystemColors.accesskey "s">
<!ENTITY underlineLinks.label "Underline links"> <!ENTITY underlineLinks.label "Underline links">
<!ENTITY underlineLinks.accesskey "u"> <!ENTITY underlineLinks.accesskey "U">
<!ENTITY links "Link Colors"> <!ENTITY links "Link Colors">
<!ENTITY linkColor.label "Unvisited Links:"> <!ENTITY linkColor.label "Unvisited Links:">
<!ENTITY linkColor.accesskey "l"> <!ENTITY linkColor.accesskey "L">
<!ENTITY visitedLinkColor.label "Visited Links:"> <!ENTITY visitedLinkColor.label "Visited Links:">
<!ENTITY visitedLinkColor.accesskey "v"> <!ENTITY visitedLinkColor.accesskey "V">

View File

@ -250,7 +250,7 @@ browser.jar:
skin/classic/browser/devtools/itemArrow-rtl.svg (../shared/devtools/images/itemArrow-rtl.svg) skin/classic/browser/devtools/itemArrow-rtl.svg (../shared/devtools/images/itemArrow-rtl.svg)
skin/classic/browser/devtools/itemArrow-ltr.svg (../shared/devtools/images/itemArrow-ltr.svg) skin/classic/browser/devtools/itemArrow-ltr.svg (../shared/devtools/images/itemArrow-ltr.svg)
skin/classic/browser/devtools/noise.png (../shared/devtools/images/noise.png) skin/classic/browser/devtools/noise.png (../shared/devtools/images/noise.png)
skin/classic/browser/devtools/dropmarker.png (../shared/devtools/images/dropmarker.png) skin/classic/browser/devtools/dropmarker.svg (../shared/devtools/images/dropmarker.svg)
skin/classic/browser/devtools/layoutview.css (../shared/devtools/layoutview.css) skin/classic/browser/devtools/layoutview.css (../shared/devtools/layoutview.css)
skin/classic/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png) skin/classic/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png)
skin/classic/browser/devtools/debugger-collapse@2x.png (../shared/devtools/images/debugger-collapse@2x.png) skin/classic/browser/devtools/debugger-collapse@2x.png (../shared/devtools/images/debugger-collapse@2x.png)

View File

@ -368,7 +368,7 @@ browser.jar:
skin/classic/browser/devtools/itemArrow-rtl.svg (../shared/devtools/images/itemArrow-rtl.svg) skin/classic/browser/devtools/itemArrow-rtl.svg (../shared/devtools/images/itemArrow-rtl.svg)
skin/classic/browser/devtools/itemArrow-ltr.svg (../shared/devtools/images/itemArrow-ltr.svg) skin/classic/browser/devtools/itemArrow-ltr.svg (../shared/devtools/images/itemArrow-ltr.svg)
skin/classic/browser/devtools/noise.png (../shared/devtools/images/noise.png) skin/classic/browser/devtools/noise.png (../shared/devtools/images/noise.png)
skin/classic/browser/devtools/dropmarker.png (../shared/devtools/images/dropmarker.png) skin/classic/browser/devtools/dropmarker.svg (../shared/devtools/images/dropmarker.svg)
skin/classic/browser/devtools/layoutview.css (../shared/devtools/layoutview.css) skin/classic/browser/devtools/layoutview.css (../shared/devtools/layoutview.css)
skin/classic/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png) skin/classic/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png)
skin/classic/browser/devtools/debugger-collapse@2x.png (../shared/devtools/images/debugger-collapse@2x.png) skin/classic/browser/devtools/debugger-collapse@2x.png (../shared/devtools/images/debugger-collapse@2x.png)

View File

@ -153,6 +153,11 @@
/* Debugging pane controls */ /* Debugging pane controls */
#debugging-controls .devtools-toolbarbutton > .toolbarbutton-icon {
width: 16px;
height: 16px;
}
#resume { #resume {
list-style-image: url(debugger-play.png); list-style-image: url(debugger-play.png);
-moz-image-region: rect(0px,32px,16px,16px); -moz-image-region: rect(0px,32px,16px,16px);
@ -170,6 +175,25 @@
list-style-image: url(debugger-step-out.png); list-style-image: url(debugger-step-out.png);
} }
@media (min-resolution: 2dppx) {
#resume {
list-style-image: url(debugger-play@2x.png);
-moz-image-region: rect(0px,64px,32px,32px);
}
#step-over {
list-style-image: url(debugger-step-over@2x.png);
}
#step-in {
list-style-image: url(debugger-step-in@2x.png);
}
#step-out {
list-style-image: url(debugger-step-out@2x.png);
}
}
#debugging-controls > toolbarbutton { #debugging-controls > toolbarbutton {
transition: opacity 0.15s ease-in-out; transition: opacity 0.15s ease-in-out;
} }
@ -256,6 +280,12 @@
background-size: 12px; background-size: 12px;
} }
@media (min-resolution: 2dppx) {
.selected .call-item-gutter {
background-image: url("editor-debug-location@2x.png");
}
}
.theme-dark .call-item-gutter { .theme-dark .call-item-gutter {
background-color: #181d20; background-color: #181d20;
color: #5f7387; color: #5f7387;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="8" height="4" viewBox="0 0 8 4" enable-background="new 0 0 8 4">
<polygon points="0,0 4,4 8,0" fill="#B6BABF" />
</svg>

After

Width:  |  Height:  |  Size: 213 B

View File

@ -96,7 +96,7 @@
-moz-appearance: none; -moz-appearance: none;
display: -moz-box; display: -moz-box;
background-color: transparent; background-color: transparent;
list-style-image: url("chrome://browser/skin/devtools/dropmarker.png"); list-style-image: url("chrome://browser/skin/devtools/dropmarker.svg");
-moz-box-align: center; -moz-box-align: center;
border-width: 0; border-width: 0;
min-width: 16px; min-width: 16px;
@ -122,7 +122,7 @@
.devtools-responsiveui-toolbarbutton[type=menu] > .toolbarbutton-menu-dropmarker, .devtools-responsiveui-toolbarbutton[type=menu] > .toolbarbutton-menu-dropmarker,
.devtools-responsiveui-toolbarbutton[type=menu-button] > .toolbarbutton-menubutton-dropmarker { .devtools-responsiveui-toolbarbutton[type=menu-button] > .toolbarbutton-menubutton-dropmarker {
-moz-appearance: none !important; -moz-appearance: none !important;
list-style-image: url("chrome://browser/skin/devtools/dropmarker.png"); list-style-image: url("chrome://browser/skin/devtools/dropmarker.svg");
-moz-box-align: center; -moz-box-align: center;
padding: 0 3px; padding: 0 3px;
} }

View File

@ -136,7 +136,7 @@
.devtools-menulist > .menulist-dropmarker { .devtools-menulist > .menulist-dropmarker {
-moz-appearance: none; -moz-appearance: none;
display: -moz-box; display: -moz-box;
list-style-image: url("chrome://browser/skin/devtools/dropmarker.png"); list-style-image: url("chrome://browser/skin/devtools/dropmarker.svg");
-moz-box-align: center; -moz-box-align: center;
min-width: 16px; min-width: 16px;
} }
@ -168,7 +168,7 @@
.devtools-toolbarbutton[type=menu] > .toolbarbutton-menu-dropmarker, .devtools-toolbarbutton[type=menu] > .toolbarbutton-menu-dropmarker,
.devtools-toolbarbutton[type=menu-button] > .toolbarbutton-menubutton-dropmarker { .devtools-toolbarbutton[type=menu-button] > .toolbarbutton-menubutton-dropmarker {
-moz-appearance: none !important; -moz-appearance: none !important;
list-style-image: url("chrome://browser/skin/devtools/dropmarker.png"); list-style-image: url("chrome://browser/skin/devtools/dropmarker.svg");
-moz-box-align: center; -moz-box-align: center;
padding: 0 3px; padding: 0 3px;
} }

View File

@ -125,6 +125,11 @@ text {
-moz-image-region: rect(0px,16px,16px,0px); -moz-image-region: rect(0px,16px,16px,0px);
} }
#inspector-pane-toggle > .toolbarbutton-icon {
width: 16px;
height: 16px;
}
#inspector-pane-toggle[pane-collapsed] { #inspector-pane-toggle[pane-collapsed] {
list-style-image: url(debugger-expand.png); list-style-image: url(debugger-expand.png);
} }
@ -132,3 +137,18 @@ text {
#inspector-pane-toggle:active { #inspector-pane-toggle:active {
-moz-image-region: rect(0px,32px,16px,16px); -moz-image-region: rect(0px,32px,16px,16px);
} }
@media (min-resolution: 2dppx) {
#inspector-pane-toggle {
list-style-image: url(debugger-collapse@2x.png);
-moz-image-region: rect(0px,32px,32px,0px);
}
#inspector-pane-toggle[pane-collapsed] {
list-style-image: url(debugger-expand@2x.png);
}
#inspector-pane-toggle:active {
-moz-image-region: rect(0px,64px,32px,32px);
}
}

View File

@ -288,7 +288,7 @@ browser.jar:
skin/classic/browser/devtools/itemArrow-rtl.svg (../shared/devtools/images/itemArrow-rtl.svg) skin/classic/browser/devtools/itemArrow-rtl.svg (../shared/devtools/images/itemArrow-rtl.svg)
skin/classic/browser/devtools/itemArrow-ltr.svg (../shared/devtools/images/itemArrow-ltr.svg) skin/classic/browser/devtools/itemArrow-ltr.svg (../shared/devtools/images/itemArrow-ltr.svg)
skin/classic/browser/devtools/noise.png (../shared/devtools/images/noise.png) skin/classic/browser/devtools/noise.png (../shared/devtools/images/noise.png)
skin/classic/browser/devtools/dropmarker.png (../shared/devtools/images/dropmarker.png) skin/classic/browser/devtools/dropmarker.svg (../shared/devtools/images/dropmarker.svg)
skin/classic/browser/devtools/layoutview.css (../shared/devtools/layoutview.css) skin/classic/browser/devtools/layoutview.css (../shared/devtools/layoutview.css)
skin/classic/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png) skin/classic/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png)
skin/classic/browser/devtools/debugger-collapse@2x.png (../shared/devtools/images/debugger-collapse@2x.png) skin/classic/browser/devtools/debugger-collapse@2x.png (../shared/devtools/images/debugger-collapse@2x.png)
@ -688,7 +688,7 @@ browser.jar:
skin/classic/aero/browser/devtools/itemArrow-rtl.svg (../shared/devtools/images/itemArrow-rtl.svg) skin/classic/aero/browser/devtools/itemArrow-rtl.svg (../shared/devtools/images/itemArrow-rtl.svg)
skin/classic/aero/browser/devtools/itemArrow-ltr.svg (../shared/devtools/images/itemArrow-ltr.svg) skin/classic/aero/browser/devtools/itemArrow-ltr.svg (../shared/devtools/images/itemArrow-ltr.svg)
skin/classic/aero/browser/devtools/noise.png (../shared/devtools/images/noise.png) skin/classic/aero/browser/devtools/noise.png (../shared/devtools/images/noise.png)
skin/classic/aero/browser/devtools/dropmarker.png (../shared/devtools/images/dropmarker.png) skin/classic/aero/browser/devtools/dropmarker.svg (../shared/devtools/images/dropmarker.svg)
skin/classic/aero/browser/devtools/layoutview.css (../shared/devtools/layoutview.css) skin/classic/aero/browser/devtools/layoutview.css (../shared/devtools/layoutview.css)
skin/classic/aero/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png) skin/classic/aero/browser/devtools/debugger-collapse.png (../shared/devtools/images/debugger-collapse.png)
skin/classic/aero/browser/devtools/debugger-collapse@2x.png (../shared/devtools/images/debugger-collapse@2x.png) skin/classic/aero/browser/devtools/debugger-collapse@2x.png (../shared/devtools/images/debugger-collapse@2x.png)

View File

@ -227,6 +227,7 @@ public class SQLiteBridge {
cursor.moveToFirst(); cursor.moveToFirst();
String version = cursor.getString(0); String version = cursor.getString(0);
ret = Integer.parseInt(version); ret = Integer.parseInt(version);
cursor.close();
} }
return ret; return ret;
} }

View File

@ -402,7 +402,18 @@ AbstractHealthReporter.prototype = Object.freeze({
// The database needs to be shut down by the end of shutdown // The database needs to be shut down by the end of shutdown
// phase profileBeforeChange. // phase profileBeforeChange.
Metrics.Storage.shutdown.addBlocker("FHR: Flushing storage shutdown", Metrics.Storage.shutdown.addBlocker("FHR: Flushing storage shutdown",
this._promiseShutdown); this._promiseShutdown,
() => ({
shutdownInitiated: this._shutdownInitiated,
initialized: this._initialized,
shutdownRequested: this._shutdownRequested,
initializeHadError: this._initializeHadError,
providerManagerInProgress: this._providerManagerInProgress,
storageInProgress: this._storageInProgress,
hasProviderManager: !!this._providerManager,
hasStorage: !!this._storage,
shutdownComplete: this.shutdownComplete
}));
try { try {
this._storageInProgress = true; this._storageInProgress = true;
@ -571,7 +582,7 @@ AbstractHealthReporter.prototype = Object.freeze({
if (this._initializeHadError) { if (this._initializeHadError) {
this._log.warn("Initialization had error. Shutting down immediately."); this._log.warn("Initialization had error. Shutting down immediately.");
} else { } else {
if (this._providerManagerInProcess) { if (this._providerManagerInProgress) {
this._log.warn("Provider manager is in progress of initializing. " + this._log.warn("Provider manager is in progress of initializing. " +
"Waiting to finish."); "Waiting to finish.");
return; return;

View File

@ -10,6 +10,7 @@ skip-if = e10s # Bug ?????? - intermittent crash of child process reported when
[browser_bug982298.js] [browser_bug982298.js]
[browser_default_image_filename.js] [browser_default_image_filename.js]
skip-if = e10s # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly skip-if = e10s # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly
[browser_f7_caret_browsing.js]
[browser_findbar.js] [browser_findbar.js]
skip-if = e10s # Disabled for e10s: Bug ?????? - seems to be a timing issue with RemoteFinder.jsm messages coming later than the tests expect. skip-if = e10s # Disabled for e10s: Bug ?????? - seems to be a timing issue with RemoteFinder.jsm messages coming later than the tests expect.
[browser_input_file_tooltips.js] [browser_input_file_tooltips.js]

View File

@ -0,0 +1,279 @@
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
let gTab = null;
let gListener = null;
const kURL = "data:text/html;charset=utf-8,Caret browsing is fun.<input id='in'>";
const kPrefShortcutEnabled = "accessibility.browsewithcaret_shortcut.enabled";
const kPrefWarnOnEnable = "accessibility.warn_on_browsewithcaret";
const kPrefCaretBrowsingOn = "accessibility.browsewithcaret";
let oldPrefs = {};
for (let pref of [kPrefShortcutEnabled, kPrefWarnOnEnable, kPrefCaretBrowsingOn]) {
oldPrefs[pref] = Services.prefs.getBoolPref(pref);
}
Services.prefs.setBoolPref(kPrefShortcutEnabled, true);
Services.prefs.setBoolPref(kPrefWarnOnEnable, true);
Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false);
registerCleanupFunction(function() {
if (gTab)
gBrowser.removeTab(gTab);
if (gListener)
Services.wm.removeListener(gListener);
for (let pref of [kPrefShortcutEnabled, kPrefWarnOnEnable, kPrefCaretBrowsingOn]) {
Services.prefs.setBoolPref(pref, oldPrefs[pref]);
}
});
function waitForCondition(aConditionFn, aMaxTries=50, aCheckInterval=100) {
function tryNow() {
tries++;
if (aConditionFn()) {
deferred.resolve();
} else if (tries < aMaxTries) {
tryAgain();
} else {
deferred.reject("Condition timed out: " + aConditionFn.toSource());
}
}
function tryAgain() {
setTimeout(tryNow, aCheckInterval);
}
let deferred = Promise.defer();
let tries = 0;
tryAgain();
return deferred.promise;
}
function promiseWaitForDialogUnload(dialog) {
let deferred = Promise.defer();
dialog.addEventListener("unload", function listener() {
dialog.removeEventListener("unload", listener, false);
deferred.resolve();
}, false);
return deferred.promise;
}
function promiseWaitForFocusEvent(el) {
if (el.ownerDocument.activeElement == el) {
return true;
}
let deferred = Promise.defer();
el.addEventListener("focus", function listener() {
el.removeEventListener("focus", listener, false);
deferred.resolve();
}, false);
return deferred.promise;
}
function promiseTestPageLoad() {
let deferred = Promise.defer();
info("Waiting for test page to load.");
gTab = gBrowser.selectedTab = gBrowser.addTab(kURL);
let browser = gBrowser.selectedBrowser;
browser.addEventListener("load", function listener() {
if (browser.currentURI.spec == "about:blank")
return;
info("Page loaded: " + browser.currentURI.spec);
browser.removeEventListener("load", listener, true);
deferred.resolve();
}, true);
return deferred.promise;
}
function promiseCaretPromptOpened() {
let deferred = Promise.defer();
if (gListener) {
console.trace();
ok(false, "Should not be waiting for another prompt right now.");
return false;
}
info("Waiting for caret prompt to open");
gListener = {
onOpenWindow: function(win) {
let window = win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
window.addEventListener("load", function listener() {
window.removeEventListener("load", listener);
if (window.location.href == "chrome://global/content/commonDialog.xul") {
info("Caret prompt opened, removing listener and focusing");
Services.wm.removeListener(gListener);
gListener = null;
deferred.resolve(window);
}
});
},
onCloseWindow: function() {},
};
Services.wm.addListener(gListener);
return deferred.promise;
}
function hitF7(async = true) {
let f7 = () => EventUtils.sendKey("F7", window.content);
// Need to not stop execution inside this task:
if (async) {
executeSoon(f7);
} else {
f7();
}
}
function syncToggleCaretNoDialog(expected) {
let openedDialog = false;
promiseCaretPromptOpened().then(function(win) {
openedDialog = true;
win.close(); // This will eventually return focus here and allow the test to continue...
});
// Cause the dialog to appear sync, if it still does.
hitF7(false);
if (gListener) {
Services.wm.removeListener(gListener);
gListener = null;
}
let expectedStr = expected ? "on." : "off.";
ok(!openedDialog, "Shouldn't open a dialog to turn caret browsing " + expectedStr);
let prefVal = Services.prefs.getBoolPref(kPrefCaretBrowsingOn);
is(prefVal, expected, "Caret browsing should now be " + expectedStr);
}
add_task(function* checkTogglingCaretBrowsing() {
yield promiseTestPageLoad();
let textEl = window.content.document.getElementById("in");
textEl.focus();
let promiseGotKey = promiseCaretPromptOpened();
hitF7();
let prompt = yield promiseGotKey;
let doc = prompt.document;
is(doc.documentElement.defaultButton, "cancel", "No button should be the default");
ok(!doc.getElementById("checkbox").checked, "Checkbox shouldn't be checked by default.");
let promiseDialogUnloaded = promiseWaitForDialogUnload(prompt);
doc.documentElement.cancelDialog();
yield promiseDialogUnloaded;
yield waitForCondition(() => textEl.ownerDocument.activeElement == textEl);
ok(!Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should still be off after cancelling the dialog.");
promiseGotKey = promiseCaretPromptOpened();
hitF7();
prompt = yield promiseGotKey;
doc = prompt.document;
is(doc.documentElement.defaultButton, "cancel", "No button should be the default");
ok(!doc.getElementById("checkbox").checked, "Checkbox shouldn't be checked by default.");
promiseDialogUnloaded = promiseWaitForDialogUnload(prompt);
doc.documentElement.acceptDialog();
yield promiseDialogUnloaded;
yield waitForCondition(() => textEl.ownerDocument.activeElement == textEl);
ok(Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should be on after accepting the dialog.");
syncToggleCaretNoDialog(false);
promiseGotKey = promiseCaretPromptOpened();
hitF7();
prompt = yield promiseGotKey;
doc = prompt.document;
is(doc.documentElement.defaultButton, "cancel", "No button should be the default");
ok(!doc.getElementById("checkbox").checked, "Checkbox shouldn't be checked by default.");
promiseDialogUnloaded = promiseWaitForDialogUnload(prompt);
doc.documentElement.cancelDialog();
yield promiseDialogUnloaded;
yield waitForCondition(() => textEl.ownerDocument.activeElement == textEl);
ok(!Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should still be off after cancelling the dialog.");
Services.prefs.setBoolPref(kPrefShortcutEnabled, true);
Services.prefs.setBoolPref(kPrefWarnOnEnable, true);
Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false);
gBrowser.removeTab(gTab);
gTab = null;
});
add_task(function* toggleCheckboxNoCaretBrowsing() {
yield promiseTestPageLoad();
let textEl = window.content.document.getElementById("in");
textEl.focus();
let promiseGotKey = promiseCaretPromptOpened();
hitF7();
let prompt = yield promiseGotKey;
let doc = prompt.document;
is(doc.documentElement.defaultButton, "cancel", "No button should be the default");
let checkbox = doc.getElementById("checkbox");
ok(!checkbox.checked, "Checkbox shouldn't be checked by default.");
// Check the box:
checkbox.click();
let promiseDialogUnloaded = promiseWaitForDialogUnload(prompt);
// Say no:
doc.documentElement.getButton("cancel").click();
yield promiseDialogUnloaded;
yield waitForCondition(() => textEl.ownerDocument.activeElement == textEl);
ok(!Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should still be off.");
ok(!Services.prefs.getBoolPref(kPrefShortcutEnabled), "Shortcut should now be disabled.");
syncToggleCaretNoDialog(false);
ok(!Services.prefs.getBoolPref(kPrefShortcutEnabled), "Shortcut should still be disabled.");
Services.prefs.setBoolPref(kPrefShortcutEnabled, true);
Services.prefs.setBoolPref(kPrefWarnOnEnable, true);
Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false);
gBrowser.removeTab(gTab);
gTab = null;
});
add_task(function* toggleCheckboxWantCaretBrowsing() {
yield promiseTestPageLoad();
let textEl = window.content.document.getElementById("in");
textEl.focus();
let promiseGotKey = promiseCaretPromptOpened();
hitF7();
let prompt = yield promiseGotKey;
let doc = prompt.document;
is(doc.documentElement.defaultButton, "cancel", "No button should be the default");
let checkbox = doc.getElementById("checkbox");
ok(!checkbox.checked, "Checkbox shouldn't be checked by default.");
// Check the box:
checkbox.click();
let promiseDialogUnloaded = promiseWaitForDialogUnload(prompt);
// Say yes:
doc.documentElement.acceptDialog();
yield promiseDialogUnloaded;
yield waitForCondition(() => textEl.ownerDocument.activeElement == textEl);
ok(Services.prefs.getBoolPref(kPrefCaretBrowsingOn), "Caret browsing should now be on.");
ok(Services.prefs.getBoolPref(kPrefShortcutEnabled), "Shortcut should still be enabled.");
ok(!Services.prefs.getBoolPref(kPrefWarnOnEnable), "Should no longer warn when enabling.");
syncToggleCaretNoDialog(false);
syncToggleCaretNoDialog(true);
syncToggleCaretNoDialog(false);
Services.prefs.setBoolPref(kPrefShortcutEnabled, true);
Services.prefs.setBoolPref(kPrefWarnOnEnable, true);
Services.prefs.setBoolPref(kPrefCaretBrowsingOn, false);
gBrowser.removeTab(gTab);
gTab = null;
});

View File

@ -1100,7 +1100,11 @@
if (event.defaultPrevented || !event.isTrusted) if (event.defaultPrevented || !event.isTrusted)
return; return;
var isEnabled = this.mPrefs.getBoolPref("accessibility.browsewithcaret_shortcut.enabled"); const kPrefShortcutEnabled = "accessibility.browsewithcaret_shortcut.enabled";
const kPrefWarnOnEnable = "accessibility.warn_on_browsewithcaret";
const kPrefCaretBrowsingOn = "accessibility.browsewithcaret";
var isEnabled = this.mPrefs.getBoolPref(kPrefShortcutEnabled);
if (!isEnabled) if (!isEnabled)
return; return;
@ -1109,12 +1113,12 @@
var warn = true; var warn = true;
try { try {
warn = this.mPrefs.getBoolPref("accessibility.warn_on_browsewithcaret"); warn = this.mPrefs.getBoolPref(kPrefWarnOnEnable);
} catch (ex) { } catch (ex) {
} }
try { try {
browseWithCaretOn = this.mPrefs.getBoolPref("accessibility.browsewithcaret"); browseWithCaretOn = this.mPrefs.getBoolPref(kPrefCaretBrowsingOn);
} catch (ex) { } catch (ex) {
} }
if (warn && !browseWithCaretOn) { if (warn && !browseWithCaretOn) {
@ -1125,14 +1129,22 @@
var buttonPressed = promptService.confirmEx(window, var buttonPressed = promptService.confirmEx(window,
this.mStrBundle.GetStringFromName('browsewithcaret.checkWindowTitle'), this.mStrBundle.GetStringFromName('browsewithcaret.checkWindowTitle'),
this.mStrBundle.GetStringFromName('browsewithcaret.checkLabel'), this.mStrBundle.GetStringFromName('browsewithcaret.checkLabel'),
promptService.STD_YES_NO_BUTTONS, // Make "No" the default:
promptService.STD_YES_NO_BUTTONS | promptService.BUTTON_POS_1_DEFAULT,
null, null, null, this.mStrBundle.GetStringFromName('browsewithcaret.checkMsg'), null, null, null, this.mStrBundle.GetStringFromName('browsewithcaret.checkMsg'),
checkValue); checkValue);
if (buttonPressed != 0) if (buttonPressed != 0) {
if (checkValue.value) {
try {
this.mPrefs.setBoolPref(kPrefShortcutEnabled, false);
} catch (ex) {
}
}
return; return;
}
if (checkValue.value) { if (checkValue.value) {
try { try {
this.mPrefs.setBoolPref("accessibility.warn_on_browsewithcaret", false); this.mPrefs.setBoolPref(kPrefWarnOnEnable, false);
} }
catch (ex) { catch (ex) {
} }
@ -1141,7 +1153,7 @@
// Toggle the pref // Toggle the pref
try { try {
this.mPrefs.setBoolPref("accessibility.browsewithcaret",!browseWithCaretOn); this.mPrefs.setBoolPref(kPrefCaretBrowsingOn, !browseWithCaretOn);
} catch (ex) { } catch (ex) {
} }
]]> ]]>

View File

@ -20,15 +20,18 @@ function setup_crash() {
}); });
Services.obs.notifyObservers(null, TOPIC, null); Services.obs.notifyObservers(null, TOPIC, null);
dump(new Error().stack + "\n");
dump("Waiting for crash\n"); dump("Waiting for crash\n");
} }
function after_crash(mdump, extra) { function after_crash(mdump, extra) {
do_print("after crash: " + extra.AsyncShutdownTimeout); do_print("after crash: " + extra.AsyncShutdownTimeout);
let info = JSON.parse(extra.AsyncShutdownTimeout); let info = JSON.parse(extra.AsyncShutdownTimeout);
do_check_eq(info.phase, "testing-async-shutdown-crash"); Assert.equal(info.phase, "testing-async-shutdown-crash");
do_print("Condition: " + JSON.stringify(info.conditions)); Assert.equal(info.conditions[0].name, "A blocker that is never satisfied");
do_check_true(JSON.stringify(info.conditions).indexOf("A blocker that is never satisfied") != -1); // This test spawns subprocesses by using argument "-e" of xpcshell, so
// this is the filename known to xpcshell.
Assert.equal(info.conditions[0].filename, "-e");
} }
// Test that AsyncShutdown + OS.File reports errors correctly, in a case in which // Test that AsyncShutdown + OS.File reports errors correctly, in a case in which

View File

@ -428,12 +428,22 @@ function Barrier(name) {
" has already begun, it is too late to register" + " has already begun, it is too late to register" +
" completion condition '" + name + "'."); " completion condition '" + name + "'.");
} }
// Determine the filename and line number of the caller.
let leaf = Components.stack;
let frame;
for (frame = leaf; frame != null && frame.filename == leaf.filename; frame = frame.caller) {
// Climb up the stack
}
let set = this._conditions.get(condition); let set = this._conditions.get(condition);
if (!set) { if (!set) {
set = []; set = [];
this._conditions.set(condition, set); this._conditions.set(condition, set);
} }
set.push({name: name, fetchState: fetchState}); set.push({name: name,
fetchState: fetchState,
filename: frame ? frame.filename : "?",
lineNumber: frame ? frame.lineNumber : -1});
}.bind(this), }.bind(this),
/** /**
@ -480,9 +490,12 @@ Barrier.prototype = Object.freeze({
return "Complete"; return "Complete";
} }
let frozen = []; let frozen = [];
for (let {name, isComplete, fetchState} of this._monitors) { for (let {name, isComplete, fetchState, filename, lineNumber} of this._monitors) {
if (!isComplete) { if (!isComplete) {
frozen.push({name: name, state: safeGetState(fetchState)}); frozen.push({name: name,
state: safeGetState(fetchState),
filename: filename,
lineNumber: lineNumber});
} }
} }
return frozen; return frozen;
@ -536,7 +549,7 @@ Barrier.prototype = Object.freeze({
for (let _condition of conditions.keys()) { for (let _condition of conditions.keys()) {
for (let current of conditions.get(_condition)) { for (let current of conditions.get(_condition)) {
let condition = _condition; // Avoid capturing the wrong variable let condition = _condition; // Avoid capturing the wrong variable
let {name, fetchState} = current; let {name, fetchState, filename, lineNumber} = current;
// An indirection on top of condition, used to let clients // An indirection on top of condition, used to let clients
// cancel a blocker through removeBlocker. // cancel a blocker through removeBlocker.
@ -565,7 +578,9 @@ Barrier.prototype = Object.freeze({
let monitor = { let monitor = {
isComplete: false, isComplete: false,
name: name, name: name,
fetchState: fetchState fetchState: fetchState,
filename: filename,
lineNumber: lineNumber
}; };
condition = condition.then(null, function onError(error) { condition = condition.then(null, function onError(error) {
@ -669,12 +684,16 @@ Barrier.prototype = Object.freeze({
// Report the problem as best as we can, then crash. // Report the problem as best as we can, then crash.
let state = this.state; let state = this.state;
let msg = "At least one completion condition failed to complete" + // If you change the following message, please make sure
// that any information on the topic and state appears
// within the first 200 characters of the message. This
// helps automatically sort oranges.
let msg = "AsyncShutdown timeout in " + topic +
" Conditions: " + JSON.stringify(state) +
" At least one completion condition failed to complete" +
" within a reasonable amount of time. Causing a crash to" + " within a reasonable amount of time. Causing a crash to" +
" ensure that we do not leave the user with an unresponsive" + " ensure that we do not leave the user with an unresponsive" +
" process draining resources." + " process draining resources." +
" Conditions: " + JSON.stringify(state) +
" Barrier: " + topic;
err(msg); err(msg);
if (gCrashReporter && gCrashReporter.enabled) { if (gCrashReporter && gCrashReporter.enabled) {
let data = { let data = {
@ -682,13 +701,27 @@ Barrier.prototype = Object.freeze({
conditions: state conditions: state
}; };
gCrashReporter.annotateCrashReport("AsyncShutdownTimeout", gCrashReporter.annotateCrashReport("AsyncShutdownTimeout",
JSON.stringify(data)); JSON.stringify(data));
} else { } else {
warn("No crash reporter available"); warn("No crash reporter available");
} }
let error = new Error(); // To help sorting out bugs, we want to make sure that the
gDebug.abort(error.fileName, error.lineNumber + 1); // call to nsIDebug.abort points to a guilty client, rather
// than to AsyncShutdown itself. We search through all the
// clients until we find one that is guilty and use its
// filename/lineNumber, which have been determined during
// the call to `addBlocker`.
let filename = "?";
let lineNumber = -1;
for (let monitor of this._monitors) {
if (monitor.isComplete) {
continue;
}
filename = monitor.filename;
lineNumber = monitor.lineNumber;
}
gDebug.abort(filename, lineNumber);
}.bind(this), }.bind(this),
function onSatisfied() { function onSatisfied() {
// The promise has been rejected, which means that we have satisfied // The promise has been rejected, which means that we have satisfied
@ -697,7 +730,7 @@ Barrier.prototype = Object.freeze({
promise = promise.then(function() { promise = promise.then(function() {
timeToCrash.reject(); timeToCrash.reject();
}.bind(this)/* No error is possible here*/); }/* No error is possible here*/);
} }
return promise; return promise;

View File

@ -270,7 +270,35 @@ add_task(function* test_phase_removeBlocker() {
}); });
add_task(function() { add_task(function* test_state() {
do_print("Testing information contained in `state`");
let BLOCKER_NAME = "test_state blocker " + Math.random();
// Set up the barrier. Note that we cannot test `barrier.state`
// immediately, as it initially contains "Not started"
let barrier = new AsyncShutdown.Barrier("test_filename");
let deferred = Promise.defer();
let {filename, lineNumber} = Components.stack;
barrier.client.addBlocker(BLOCKER_NAME,
function() {
return deferred.promise;
});
let promiseDone = barrier.wait();
// Now that we have called `wait()`, the state contains interesting things
let state = barrier.state[0];
do_print("State: " + JSON.stringify(barrier.state, null, "\t"));
Assert.equal(state.filename, filename);
Assert.equal(state.lineNumber, lineNumber + 2);
Assert.equal(state.name, BLOCKER_NAME);
deferred.resolve();
yield promiseDone;
});
add_task(function*() {
Services.prefs.clearUserPref("toolkit.asyncshutdown.testing"); Services.prefs.clearUserPref("toolkit.asyncshutdown.testing");
}); });