merge fx-team to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-08-29 15:13:15 +02:00
commit d9df5fe009
18 changed files with 184 additions and 10 deletions

View File

@ -1277,6 +1277,12 @@ var gBrowserInit = {
Services.telemetry.getHistogramById("MASTER_PASSWORD_ENABLED").add(mpEnabled); Services.telemetry.getHistogramById("MASTER_PASSWORD_ENABLED").add(mpEnabled);
} }
}, 5000); }, 5000);
// Telemetry for tracking protection.
let tpEnabled = gPrefService
.getBoolPref("privacy.trackingprotection.enabled");
Services.telemetry.getHistogramById("TRACKING_PROTECTION_ENABLED")
.add(tpEnabled);
}); });
this.delayedStartupFinished = true; this.delayedStartupFinished = true;
@ -6494,6 +6500,10 @@ var gIdentityHandler = {
nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT | nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT |
nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT)) { nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT)) {
this.showBadContentDoorhanger(state); this.showBadContentDoorhanger(state);
} else {
// We didn't show the shield
Services.telemetry.getHistogramById("TRACKING_PROTECTION_SHIELD")
.add(0);
} }
}, },
@ -6515,6 +6525,19 @@ var gIdentityHandler = {
// default // default
let iconState = "bad-content-blocked-notification-icon"; let iconState = "bad-content-blocked-notification-icon";
// Telemetry for whether the shield was due to tracking protection or not
let histogram = Services.telemetry.getHistogramById
("TRACKING_PROTECTION_SHIELD");
if (state & Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT) {
histogram.add(1);
} else if (state &
Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT) {
histogram.add(2);
} else {
// The shield is due to mixed content, just keep a count so we can
// normalize later.
histogram.add(3);
}
if (state & if (state &
(Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT | (Ci.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT |
Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT)) { Ci.nsIWebProgressListener.STATE_LOADED_TRACKING_CONTENT)) {

View File

@ -1819,6 +1819,10 @@
// places this host on the tracking protection white list. // places this host on the tracking protection white list.
Services.perms.add(normalizedUrl, Services.perms.add(normalizedUrl,
"trackingprotection", Services.perms.ALLOW_ACTION); "trackingprotection", Services.perms.ALLOW_ACTION);
// Telemetry for disable protection
let histogram = Services.telemetry.getHistogramById(
"TRACKING_PROTECTION_EVENTS");
histogram.add(1);
BrowserReload(); BrowserReload();
]]></body> ]]></body>
</method> </method>
@ -1829,6 +1833,10 @@
// from the tracking protection white list (any list actually). // from the tracking protection white list (any list actually).
Services.perms.remove(gBrowser.selectedBrowser.currentURI.host, Services.perms.remove(gBrowser.selectedBrowser.currentURI.host,
"trackingprotection"); "trackingprotection");
// Telemetry for enable protection
let histogram = Services.telemetry.getHistogramById(
"TRACKING_PROTECTION_EVENTS");
histogram.add(2);
BrowserReload(); BrowserReload();
]]></body> ]]></body>
</method> </method>

View File

@ -13,6 +13,8 @@ Cu.import("resource:///modules/loop/LoopContacts.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "hookWindowCloseForPanelClose", XPCOMUtils.defineLazyModuleGetter(this, "hookWindowCloseForPanelClose",
"resource://gre/modules/MozSocialAPI.jsm"); "resource://gre/modules/MozSocialAPI.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
"resource://gre/modules/PluralForm.jsm");
XPCOMUtils.defineLazyGetter(this, "appInfo", function() { XPCOMUtils.defineLazyGetter(this, "appInfo", function() {
return Cc["@mozilla.org/xre/app-info;1"] return Cc["@mozilla.org/xre/app-info;1"]
.getService(Ci.nsIXULAppInfo) .getService(Ci.nsIXULAppInfo)
@ -150,6 +152,23 @@ function injectLoopAPI(targetWindow) {
} }
}, },
/**
* Returns the correct form of a semi-colon separated string
* based on the value of the `num` argument and the current locale.
*
* @param {Integer} num The number used to find the plural form.
* @param {String} str The semi-colon separated string of word forms.
* @returns {String} The correct word form based on the value of the number
* and the current locale.
*/
getPluralForm: {
enumerable: true,
writable: true,
value: function(num, str) {
return PluralForm.get(num, str);
}
},
/** /**
* Call to ensure that any necessary registrations for the Loop Service * Call to ensure that any necessary registrations for the Loop Service
* have taken place. * have taken place.

View File

@ -13,11 +13,16 @@
var gLanguage = ''; var gLanguage = '';
// fetch an l10n objects // fetch an l10n objects
function getL10nData(key) { function getL10nData(key, num) {
var response = gL10nDetails.getStrings(key); var response = gL10nDetails.getStrings(key);
var data = JSON.parse(response); var data = JSON.parse(response);
if (!data) if (!data)
console.warn('[l10n] #' + key + ' missing for [' + gLanguage + ']'); console.warn('[l10n] #' + key + ' missing for [' + gLanguage + ']');
if (num !== undefined) {
for (var prop in data) {
data[prop] = gL10nDetails.getPluralForm(num, data[prop]);
}
}
return data; return data;
} }
@ -33,7 +38,11 @@
// translate a string // translate a string
function translateString(key, args, fallback) { function translateString(key, args, fallback) {
var data = getL10nData(key); if (args && args.num) {
var num = args && args.num;
delete args.num;
}
var data = getL10nData(key, num);
if (!data && fallback) if (!data && fallback)
data = {textContent: fallback}; data = {textContent: fallback};
if (!data) if (!data)

View File

@ -550,7 +550,8 @@ loop.shared.views = (function(_, OT, l10n) {
FeedbackLayout({title: l10n.get("feedback_thank_you_heading")}, FeedbackLayout({title: l10n.get("feedback_thank_you_heading")},
React.DOM.p({className: "info thank-you"}, React.DOM.p({className: "info thank-you"},
l10n.get("feedback_window_will_close_in", { l10n.get("feedback_window_will_close_in", {
countdown: this.state.countdown countdown: this.state.countdown,
num: this.state.countdown
})) }))
) )
); );

View File

@ -550,7 +550,8 @@ loop.shared.views = (function(_, OT, l10n) {
<FeedbackLayout title={l10n.get("feedback_thank_you_heading")}> <FeedbackLayout title={l10n.get("feedback_thank_you_heading")}>
<p className="info thank-you">{ <p className="info thank-you">{
l10n.get("feedback_window_will_close_in", { l10n.get("feedback_window_will_close_in", {
countdown: this.state.countdown countdown: this.state.countdown,
num: this.state.countdown
})}</p> })}</p>
</FeedbackLayout> </FeedbackLayout>
); );

View File

@ -12,3 +12,4 @@ skip-if = !debug
[browser_mozLoop_prefs.js] [browser_mozLoop_prefs.js]
[browser_mozLoop_doNotDisturb.js] [browser_mozLoop_doNotDisturb.js]
skip-if = buildapp == 'mulet' skip-if = buildapp == 'mulet'
[browser_mozLoop_pluralStrings.js]

View File

@ -0,0 +1,19 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* This is an integration test from navigator.mozLoop through to the end
* effects - rather than just testing MozLoopAPI alone.
*/
add_task(loadLoopPanel);
add_task(function* test_mozLoop_pluralStrings() {
Assert.ok(gMozLoopAPI, "mozLoop should exist");
var strings = JSON.parse(gMozLoopAPI.getStrings("feedback_window_will_close_in"));
Assert.equal(gMozLoopAPI.getPluralForm(0, strings.textContent),
"This window will close in {{countdown}} seconds");
Assert.equal(gMozLoopAPI.getPluralForm(1, strings.textContent),
"This window will close in {{countdown}} second");
});

View File

@ -65,6 +65,8 @@ function AutocompletePopup(aDocument, aOptions = {})
if (!aOptions.onKeypress) { if (!aOptions.onKeypress) {
this._panel.setAttribute("ignorekeys", "true"); this._panel.setAttribute("ignorekeys", "true");
} }
// Stop this appearing as an alert to accessibility.
this._panel.setAttribute("role", "presentation");
let mainPopupSet = this._document.getElementById("mainPopupSet"); let mainPopupSet = this._document.getElementById("mainPopupSet");
if (mainPopupSet) { if (mainPopupSet) {
@ -106,6 +108,7 @@ function AutocompletePopup(aDocument, aOptions = {})
if (this.onKeypress) { if (this.onKeypress) {
this._list.addEventListener("keypress", this.onKeypress, false); this._list.addEventListener("keypress", this.onKeypress, false);
} }
this._itemIdCounter = 0;
} }
exports.AutocompletePopup = AutocompletePopup; exports.AutocompletePopup = AutocompletePopup;
@ -148,6 +151,8 @@ AutocompletePopup.prototype = {
*/ */
hidePopup: function AP_hidePopup() hidePopup: function AP_hidePopup()
{ {
// Return accessibility focus to the input.
this._document.activeElement.removeAttribute("aria-activedescendant");
this._panel.hidePopup(); this._panel.hidePopup();
}, },
@ -295,6 +300,23 @@ AutocompletePopup.prototype = {
this._list.ensureIndexIsVisible(this._list.selectedIndex); this._list.ensureIndexIsVisible(this._list.selectedIndex);
}, },
/**
* Update accessibility appropriately when the selected item is changed.
*
* @private
*/
_updateAriaActiveDescendant: function AP__updateAriaActiveDescendant()
{
if (!this._list.selectedItem) {
// Return accessibility focus to the input.
this._document.activeElement.removeAttribute("aria-activedescendant");
return;
}
// Focus this for accessibility so users know about the selected item.
this._document.activeElement.setAttribute("aria-activedescendant",
this._list.selectedItem.id);
},
/** /**
* Clear all the items from the autocomplete list. * Clear all the items from the autocomplete list.
*/ */
@ -340,6 +362,7 @@ AutocompletePopup.prototype = {
if (this.isOpen && this._list.ensureIndexIsVisible) { if (this.isOpen && this._list.ensureIndexIsVisible) {
this._list.ensureIndexIsVisible(this._list.selectedIndex); this._list.ensureIndexIsVisible(this._list.selectedIndex);
} }
this._updateAriaActiveDescendant();
}, },
/** /**
@ -362,6 +385,7 @@ AutocompletePopup.prototype = {
if (this.isOpen) { if (this.isOpen) {
this._list.ensureIndexIsVisible(this._list.selectedIndex); this._list.ensureIndexIsVisible(this._list.selectedIndex);
} }
this._updateAriaActiveDescendant();
}, },
/** /**
@ -383,6 +407,8 @@ AutocompletePopup.prototype = {
appendItem: function AP_appendItem(aItem) appendItem: function AP_appendItem(aItem)
{ {
let listItem = this._document.createElementNS(XUL_NS, "richlistitem"); let listItem = this._document.createElementNS(XUL_NS, "richlistitem");
// Items must have an id for accessibility.
listItem.id = this._panel.id + "_item_" + this._itemIdCounter++;
if (this.direction) { if (this.direction) {
listItem.setAttribute("dir", this.direction); listItem.setAttribute("dir", this.direction);
} }

View File

@ -46,6 +46,7 @@ skip-if = os == "linux" || "mac" # bug 949355
[browser_styleeditor_bug_851132_middle_click.js] [browser_styleeditor_bug_851132_middle_click.js]
[browser_styleeditor_bug_870339.js] [browser_styleeditor_bug_870339.js]
[browser_styleeditor_cmd_edit.js] [browser_styleeditor_cmd_edit.js]
skip-if = e10s # Bug 1055333 - style editor tests disabled with e10s
[browser_styleeditor_enabled.js] [browser_styleeditor_enabled.js]
[browser_styleeditor_fetch-from-cache.js] [browser_styleeditor_fetch-from-cache.js]
[browser_styleeditor_filesave.js] [browser_styleeditor_filesave.js]

View File

@ -22,7 +22,14 @@ function consoleOpened(HUD) {
let popup = HUD.jsterm.autocompletePopup; let popup = HUD.jsterm.autocompletePopup;
let input = popup._document.activeElement;
function getActiveDescendant() {
return input.ownerDocument.getElementById(
input.getAttribute("aria-activedescendant"));
}
ok(!popup.isOpen, "popup is not open"); ok(!popup.isOpen, "popup is not open");
ok(!input.hasAttribute("aria-activedescendant"), "no aria-activedescendant");
popup._panel.addEventListener("popupshown", function() { popup._panel.addEventListener("popupshown", function() {
popup._panel.removeEventListener("popupshown", arguments.callee, false); popup._panel.removeEventListener("popupshown", arguments.callee, false);
@ -30,6 +37,8 @@ function consoleOpened(HUD) {
ok(popup.isOpen, "popup is open"); ok(popup.isOpen, "popup is open");
is(popup.itemCount, 0, "no items"); is(popup.itemCount, 0, "no items");
ok(!input.hasAttribute("aria-activedescendant"),
"no aria-activedescendant");
popup.setItems(items); popup.setItems(items);
@ -43,31 +52,37 @@ function consoleOpened(HUD) {
is(popup.selectedIndex, 2, is(popup.selectedIndex, 2,
"Index of the first item from bottom is selected."); "Index of the first item from bottom is selected.");
is(popup.selectedItem, items[2], "First item from bottom is selected"); is(popup.selectedItem, items[2], "First item from bottom is selected");
ok(getActiveDescendant().selected, "aria-activedescendant is correct");
popup.selectedIndex = 1; popup.selectedIndex = 1;
is(popup.selectedIndex, 1, "index 1 is selected"); is(popup.selectedIndex, 1, "index 1 is selected");
is(popup.selectedItem, items[1], "item1 is selected"); is(popup.selectedItem, items[1], "item1 is selected");
ok(getActiveDescendant().selected, "aria-activedescendant is correct");
popup.selectedItem = items[2]; popup.selectedItem = items[2];
is(popup.selectedIndex, 2, "index 2 is selected"); is(popup.selectedIndex, 2, "index 2 is selected");
is(popup.selectedItem, items[2], "item2 is selected"); is(popup.selectedItem, items[2], "item2 is selected");
ok(getActiveDescendant().selected, "aria-activedescendant is correct");
is(popup.selectPreviousItem(), items[1], "selectPreviousItem() works"); is(popup.selectPreviousItem(), items[1], "selectPreviousItem() works");
is(popup.selectedIndex, 1, "index 1 is selected"); is(popup.selectedIndex, 1, "index 1 is selected");
is(popup.selectedItem, items[1], "item1 is selected"); is(popup.selectedItem, items[1], "item1 is selected");
ok(getActiveDescendant().selected, "aria-activedescendant is correct");
is(popup.selectNextItem(), items[2], "selectPreviousItem() works"); is(popup.selectNextItem(), items[2], "selectPreviousItem() works");
is(popup.selectedIndex, 2, "index 2 is selected"); is(popup.selectedIndex, 2, "index 2 is selected");
is(popup.selectedItem, items[2], "item2 is selected"); is(popup.selectedItem, items[2], "item2 is selected");
ok(getActiveDescendant().selected, "aria-activedescendant is correct");
ok(popup.selectNextItem(), "selectPreviousItem() works"); ok(popup.selectNextItem(), "selectPreviousItem() works");
is(popup.selectedIndex, 0, "index 0 is selected"); is(popup.selectedIndex, 0, "index 0 is selected");
is(popup.selectedItem, items[0], "item0 is selected"); is(popup.selectedItem, items[0], "item0 is selected");
ok(getActiveDescendant().selected, "aria-activedescendant is correct");
items.push({label: "label3", value: "value3"}); items.push({label: "label3", value: "value3"});
popup.appendItem(items[3]); popup.appendItem(items[3]);
@ -76,15 +91,19 @@ function consoleOpened(HUD) {
popup.selectedIndex = 3; popup.selectedIndex = 3;
is(popup.selectedItem, items[3], "item3 is selected"); is(popup.selectedItem, items[3], "item3 is selected");
ok(getActiveDescendant().selected, "aria-activedescendant is correct");
popup.removeItem(items[2]); popup.removeItem(items[2]);
is(popup.selectedIndex, 2, "index2 is selected"); is(popup.selectedIndex, 2, "index2 is selected");
is(popup.selectedItem, items[3], "item3 is still selected"); is(popup.selectedItem, items[3], "item3 is still selected");
ok(getActiveDescendant().selected, "aria-activedescendant is correct");
is(popup.itemCount, items.length - 1, "item2 removed"); is(popup.itemCount, items.length - 1, "item2 removed");
popup.clearItems(); popup.clearItems();
is(popup.itemCount, 0, "items cleared"); is(popup.itemCount, 0, "items cleared");
ok(!input.hasAttribute("aria-activedescendant"),
"no aria-activedescendant");
popup.hidePopup(); popup.hidePopup();
finishTest(); finishTest();

View File

@ -183,7 +183,8 @@ function goUpdateConsoleCommands() {
<textbox class="jsterm-complete-node devtools-monospace" <textbox class="jsterm-complete-node devtools-monospace"
multiline="true" rows="1" tabindex="-1"/> multiline="true" rows="1" tabindex="-1"/>
<textbox class="jsterm-input-node devtools-monospace" <textbox class="jsterm-input-node devtools-monospace"
multiline="true" rows="1" tabindex="0"/> multiline="true" rows="1" tabindex="0"
aria-autocomplete="list"/>
</stack> </stack>
</hbox> </hbox>
</notificationbox> </notificationbox>

View File

@ -55,9 +55,11 @@ feedback_category_other=Other:
feedback_custom_category_text_placeholder=What went wrong? feedback_custom_category_text_placeholder=What went wrong?
feedback_submit_button=Submit feedback_submit_button=Submit
feedback_back_button=Back feedback_back_button=Back
## LOCALIZATION NOTE (feedback_window_will_close_in): In this item, don't ## LOCALIZATION NOTE (feedback_window_will_close_in):
## translate the part between {{..}} ## Semicolon-separated list of plural forms. See:
feedback_window_will_close_in=This window will close in {{countdown}} seconds ## http://developer.mozilla.org/en/docs/Localization_and_Plurals
## In this item, don't translate the part between {{..}}
feedback_window_will_close_in=This window will close in {{countdown}} second;This window will close in {{countdown}} seconds
share_email_subject2=Invitation to chat share_email_subject2=Invitation to chat
## LOCALIZATION NOTE (share_email_body2): In this item, don't translate the ## LOCALIZATION NOTE (share_email_body2): In this item, don't translate the

View File

@ -1630,7 +1630,9 @@ var BrowserApp = {
break; break;
case "Browser:Quit": case "Browser:Quit":
this.quit(aData ? JSON.parse(aData) : null); // Add-ons like QuitNow and CleanQuit provide aData as an empty-string ("").
// Pass undefined to invoke the methods default parms.
this.quit(aData ? JSON.parse(aData) : undefined);
break; break;
case "SaveAs:PDF": case "SaveAs:PDF":

View File

@ -117,6 +117,9 @@ SessionStore.prototype = {
} }
Services.obs.notifyObservers(null, "sessionstore-state-purge-complete", ""); Services.obs.notifyObservers(null, "sessionstore-state-purge-complete", "");
if (this._notifyClosedTabs) {
this._sendClosedTabsToJava(Services.wm.getMostRecentWindow("navigator:browser"));
}
break; break;
case "timer-callback": case "timer-callback":
// Timer call back for delayed saving // Timer call back for delayed saving

View File

@ -163,7 +163,18 @@ AccountState.prototype = {
}, },
getKeyPair: function(mustBeValidUntil) { getKeyPair: function(mustBeValidUntil) {
if (this.keyPair && (this.keyPair.validUntil > mustBeValidUntil)) { // If the debugging pref to ignore cached authentication credentials is set for Sync,
// then don't use any cached key pair, i.e., generate a new one and get it signed.
// The purpose of this pref is to expedite any auth errors as the result of a
// expired or revoked FxA session token, e.g., from resetting or changing the FxA
// password.
let ignoreCachedAuthCredentials = false;
try {
ignoreCachedAuthCredentials = Services.prefs.getBoolPref("services.sync.debug.ignoreCachedAuthCredentials");
} catch(e) {
// Pref doesn't exist
}
if (!ignoreCachedAuthCredentials && this.keyPair && (this.keyPair.validUntil > mustBeValidUntil)) {
log.debug("getKeyPair: already have a keyPair"); log.debug("getKeyPair: already have a keyPair");
return this.resolve(this.keyPair.keyPair); return this.resolve(this.keyPair.keyPair);
} }

View File

@ -475,6 +475,17 @@ this.BrowserIDManager.prototype = {
* signed in? * signed in?
*/ */
hasValidToken: function() { hasValidToken: function() {
// If pref is set to ignore cached authentication credentials for debugging,
// then return false to force the fetching of a new token.
let ignoreCachedAuthCredentials = false;
try {
ignoreCachedAuthCredentials = Svc.Prefs.get("debug.ignoreCachedAuthCredentials");
} catch(e) {
// Pref doesn't exist
}
if (ignoreCachedAuthCredentials) {
return false;
}
if (!this._token) { if (!this._token) {
return false; return false;
} }

View File

@ -6506,5 +6506,22 @@
"high": "10000000", "high": "10000000",
"n_buckets": 10, "n_buckets": 10,
"description": "Sidebar showing: seconds that the sidebar has been opened" "description": "Sidebar showing: seconds that the sidebar has been opened"
},
"TRACKING_PROTECTION_ENABLED": {
"expires_in_version": "never",
"kind": "boolean",
"description": "Whether or not a session has tracking protection enabled"
},
"TRACKING_PROTECTION_SHIELD": {
"expires_in_version": "never",
"kind": "enumerated",
"n_values": 4,
"description": "Tracking protection shield (0 = not shown, 1 = blocked, 2 = loaded, 3 = due to mixed content"
},
"TRACKING_PROTECTION_EVENTS": {
"expires_in_version": "never",
"kind": "enumerated",
"n_values": 3,
"description": "Doorhanger shown = 0, Disable = 1, Enable = 2"
} }
} }