зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to central, a=merge
UPGRADE_NSS_RELEASE MozReview-Commit-ID: 4of9LS9sA2I --HG-- extra : amend_source : c399503fa642c04d256ee0ce53b099601259f90a
This commit is contained in:
Коммит
39dd8b763b
|
@ -64,7 +64,9 @@ browser/components/sessionstore/test/unit/data/sessionstore_invalid.js
|
|||
browser/components/tabview/**
|
||||
# generated & special files in cld2
|
||||
browser/components/translation/cld2/**
|
||||
# Screenshots is imported as a system add-on and has its own lint rules currently.
|
||||
# Screenshots and Follow-on search are imported as a system add-on and have
|
||||
# their own lint rules currently.
|
||||
browser/extensions/followonsearch/**
|
||||
browser/extensions/screenshots/**
|
||||
browser/extensions/pdfjs/content/build**
|
||||
browser/extensions/pdfjs/content/web**
|
||||
|
|
|
@ -830,6 +830,12 @@ this.PanelMultiView = class {
|
|||
this.node.removeAttribute("panelopen");
|
||||
this.showMainView();
|
||||
if (this.panelViews) {
|
||||
for (let panelView of this._viewStack.children) {
|
||||
if (panelView.nodeName != "children") {
|
||||
panelView.style.removeProperty("min-width");
|
||||
panelView.style.removeProperty("max-width");
|
||||
}
|
||||
}
|
||||
this.window.removeEventListener("keydown", this);
|
||||
this._panel.removeEventListener("mousemove", this);
|
||||
this._resetKeyNavigation();
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": false
|
||||
}
|
||||
};
|
|
@ -0,0 +1,243 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
|
||||
"resource://gre/modules/UpdateUtils.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TelemetryEnvironment",
|
||||
"resource://gre/modules/TelemetryEnvironment.jsm");
|
||||
|
||||
// The amount of people to be part of the telemetry reporting.
|
||||
const REPORTING_THRESHOLD = {
|
||||
// "default": 1.0, // 100% - self builds, linux distros etc.
|
||||
"nightly": 0.1, // 10%
|
||||
"beta": 0.1, // 10%
|
||||
"release": 0.1, // 10%
|
||||
};
|
||||
|
||||
// Preferences this add-on uses.
|
||||
const kPrefPrefix = "extensions.followonsearch.";
|
||||
const PREF_COHORT_SAMPLE = `${kPrefPrefix}cohortSample`;
|
||||
const PREF_LOGGING = `${kPrefPrefix}logging`;
|
||||
const PREF_CHANNEL_OVERRIDE = `${kPrefPrefix}override`;
|
||||
|
||||
const kExtensionID = "followonsearch@mozilla.com";
|
||||
const kSaveTelemetryMsg = `${kExtensionID}:save-telemetry`;
|
||||
const kShutdownMsg = `${kExtensionID}:shutdown`;
|
||||
|
||||
const frameScript = `chrome://followonsearch/content/followonsearch-fs.js?q=${Math.random()}`;
|
||||
|
||||
const validSearchTypes = [
|
||||
// A search is a follow-on search from an SAP.
|
||||
"follow-on",
|
||||
// The search is a "search access point".
|
||||
"sap",
|
||||
];
|
||||
|
||||
var gLoggingEnabled = false;
|
||||
var gTelemetryActivated = false;
|
||||
|
||||
/**
|
||||
* Logs a message to the console if logging is enabled.
|
||||
*
|
||||
* @param {String} message The message to log.
|
||||
*/
|
||||
function log(message) {
|
||||
if (gLoggingEnabled) {
|
||||
console.log("Follow-On Search", message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles receiving a message from the content process to save telemetry.
|
||||
*
|
||||
* @param {Object} message The message received.
|
||||
*/
|
||||
function handleSaveTelemetryMsg(message) {
|
||||
if (message.name != kSaveTelemetryMsg) {
|
||||
throw new Error(`Unexpected message received: ${kSaveTelemetryMsg}`);
|
||||
}
|
||||
|
||||
let info = message.data;
|
||||
|
||||
if (!validSearchTypes.includes(info.type)) {
|
||||
throw new Error("Unexpected type!");
|
||||
}
|
||||
|
||||
log(info);
|
||||
|
||||
let histogram = Services.telemetry.getKeyedHistogramById("SEARCH_COUNTS");
|
||||
histogram.add(`${info.sap}.${info.type}:unknown:${info.code}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Activites recording of telemetry if it isn't already activated.
|
||||
*/
|
||||
function activateTelemetry() {
|
||||
if (gTelemetryActivated) {
|
||||
return;
|
||||
}
|
||||
|
||||
gTelemetryActivated = true;
|
||||
|
||||
Services.mm.addMessageListener(kSaveTelemetryMsg, handleSaveTelemetryMsg);
|
||||
Services.mm.loadFrameScript(frameScript, true);
|
||||
|
||||
// Record the fact we're saving the extra data as a telemetry environment
|
||||
// value.
|
||||
TelemetryEnvironment.setExperimentActive(kExtensionID, "active");
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivites recording of telemetry if it isn't already deactivated.
|
||||
*/
|
||||
function deactivateTelemetry() {
|
||||
if (!gTelemetryActivated) {
|
||||
return;
|
||||
}
|
||||
|
||||
TelemetryEnvironment.setExperimentInactive(kExtensionID);
|
||||
|
||||
Services.mm.removeMessageListener(kSaveTelemetryMsg, handleSaveTelemetryMsg);
|
||||
Services.mm.removeDelayedFrameScript(frameScript);
|
||||
Services.mm.broadcastAsyncMessage(kShutdownMsg);
|
||||
|
||||
gTelemetryActivated = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* cohortManager is used to decide which users to enable the add-on for.
|
||||
*/
|
||||
var cohortManager = {
|
||||
// Indicates whether the telemetry should be enabled.
|
||||
enableForUser: false,
|
||||
|
||||
// Records if we've already run init.
|
||||
_definedThisSession: false,
|
||||
|
||||
/**
|
||||
* Initialises the manager, working out if telemetry should be enabled
|
||||
* for the user.
|
||||
*/
|
||||
init() {
|
||||
if (this._definedThisSession) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._definedThisSession = true;
|
||||
this.enableForUser = false;
|
||||
|
||||
try {
|
||||
let distId = Services.prefs.getCharPref("distribution.id", "");
|
||||
if (distId) {
|
||||
log("It is a distribution, not setting up nor enabling.");
|
||||
return;
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
let cohortSample;
|
||||
try {
|
||||
cohortSample = Services.prefs.getFloatPref(PREF_COHORT_SAMPLE, undefined);
|
||||
} catch (e) {}
|
||||
if (!cohortSample) {
|
||||
cohortSample = Math.random().toString().substr(0, 8);
|
||||
cohortSample = Services.prefs.setCharPref(PREF_COHORT_SAMPLE, cohortSample);
|
||||
}
|
||||
log(`Cohort Sample value is ${cohortSample}`);
|
||||
|
||||
let updateChannel = UpdateUtils.getUpdateChannel(false);
|
||||
log(`Update channel is ${updateChannel}`);
|
||||
if (!(updateChannel in REPORTING_THRESHOLD)) {
|
||||
let prefOverride = "default";
|
||||
try {
|
||||
prefOverride = Services.prefs.getCharPref(PREF_CHANNEL_OVERRIDE, "default");
|
||||
} catch (e) {}
|
||||
if (prefOverride in REPORTING_THRESHOLD) {
|
||||
updateChannel = prefOverride;
|
||||
} else {
|
||||
// Don't enable, we don't know about the channel, and it isn't overriden.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
log("Not enabling extra telemetry due to bug 1371198");
|
||||
|
||||
// if (cohortSample <= REPORTING_THRESHOLD[updateChannel]) {
|
||||
// log("Enabling telemetry for user");
|
||||
// this.enableForUser = true;
|
||||
// } else {
|
||||
// log("Not enabling telemetry for user - outside threshold.");
|
||||
// }
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when the add-on is installed.
|
||||
*
|
||||
* @param {Object} data Data about the add-on.
|
||||
* @param {Number} reason Indicates why the extension is being installed.
|
||||
*/
|
||||
function install(data, reason) {
|
||||
try {
|
||||
gLoggingEnabled = Services.prefs.getBoolPref(PREF_LOGGING, false);
|
||||
} catch (e) {
|
||||
// Needed until Firefox 54
|
||||
}
|
||||
|
||||
cohortManager.init();
|
||||
if (cohortManager.enableForUser) {
|
||||
activateTelemetry();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the add-on is uninstalled.
|
||||
*
|
||||
* @param {Object} data Data about the add-on.
|
||||
* @param {Number} reason Indicates why the extension is being uninstalled.
|
||||
*/
|
||||
function uninstall(data, reason) {
|
||||
deactivateTelemetry();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the add-on starts up.
|
||||
*
|
||||
* @param {Object} data Data about the add-on.
|
||||
* @param {Number} reason Indicates why the extension is being started.
|
||||
*/
|
||||
function startup(data, reason) {
|
||||
try {
|
||||
gLoggingEnabled = Services.prefs.getBoolPref(PREF_LOGGING, false);
|
||||
} catch (e) {
|
||||
// Needed until Firefox 54
|
||||
}
|
||||
|
||||
cohortManager.init();
|
||||
|
||||
if (cohortManager.enableForUser) {
|
||||
// Workaround for bug 1202125
|
||||
// We need to delay our loading so that when we are upgraded,
|
||||
// our new script doesn't get the shutdown message.
|
||||
setTimeout(() => {
|
||||
activateTelemetry();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the add-on shuts down.
|
||||
*
|
||||
* @param {Object} data Data about the add-on.
|
||||
* @param {Number} reason Indicates why the extension is being shut down.
|
||||
*/
|
||||
function shutdown(data, reason) {
|
||||
deactivateTelemetry();
|
||||
}
|
|
@ -0,0 +1,283 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* eslint-env mozilla/frame-script */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.importGlobalProperties(["URLSearchParams"]);
|
||||
|
||||
const kExtensionID = "followonsearch@mozilla.com";
|
||||
const kSaveTelemetryMsg = `${kExtensionID}:save-telemetry`;
|
||||
const kShutdownMsg = `${kExtensionID}:shutdown`;
|
||||
|
||||
/**
|
||||
* A map of search domains with their expected codes.
|
||||
*/
|
||||
let searchDomains = {
|
||||
"search.yahoo.co.jp": {
|
||||
"search": "p",
|
||||
"followOnSearch": "ai",
|
||||
"prefix": "fr",
|
||||
"codes": ["mozff"],
|
||||
"sap": "yahoo",
|
||||
},
|
||||
"www.bing.com": {
|
||||
"search": "q",
|
||||
"prefix": "pc",
|
||||
"reportPrefix": "form",
|
||||
"codes": ["MOZI"],
|
||||
"sap": "bing",
|
||||
},
|
||||
};
|
||||
|
||||
// The yahoo domains to watch for.
|
||||
const yahooDomains = new Set([
|
||||
"search.yahoo.com", "ca.search.yahoo.com", "hk.search.yahoo.com",
|
||||
"tw.search.yahoo.com",
|
||||
]);
|
||||
|
||||
// Add Yahoo domains to search domains
|
||||
for (let domain of yahooDomains) {
|
||||
searchDomains[domain] = {
|
||||
"search": "p",
|
||||
"followOnSearch": "fr2",
|
||||
"prefix": "hspart",
|
||||
"reportPrefix": "hsimp",
|
||||
"codes": ["mozilla"],
|
||||
"sap": "yahoo",
|
||||
};
|
||||
}
|
||||
|
||||
const yahooLegacyDomains = new Set([
|
||||
"no.search.yahoo.com", "ar.search.yahoo.com", "br.search.yahoo.com",
|
||||
"ch.search.yahoo.com", "cl.search.yahoo.com", "de.search.yahoo.com",
|
||||
"uk.search.yahoo.com", "es.search.yahoo.com", "espanol.search.yahoo.com",
|
||||
"fi.search.yahoo.com", "fr.search.yahoo.com", "nl.search.yahoo.com",
|
||||
"id.search.yahoo.com", "in.search.yahoo.com", "it.search.yahoo.com",
|
||||
"mx.search.yahoo.com", "se.search.yahoo.com", "sg.search.yahoo.com",
|
||||
]);
|
||||
|
||||
// Add Yahoo legacy domains to search domains
|
||||
for (let domain of yahooLegacyDomains) {
|
||||
searchDomains[domain] = {
|
||||
"search": "p",
|
||||
"followOnSearch": "fr2",
|
||||
"prefix": "fr",
|
||||
"codes": ["moz35"],
|
||||
"sap": "yahoo",
|
||||
};
|
||||
}
|
||||
|
||||
const googleDomains = new Set([
|
||||
"www.google.com", "www.google.ac", "www.google.ad", "www.google.ae",
|
||||
"www.google.com.af", "www.google.com.ag", "www.google.com.ai",
|
||||
"www.google.al", "www.google.am", "www.google.co.ao", "www.google.com.ar",
|
||||
"www.google.as", "www.google.at", "www.google.com.au", "www.google.az",
|
||||
"www.google.ba", "www.google.com.bd", "www.google.be", "www.google.bf",
|
||||
"www.google.bg", "www.google.com.bh", "www.google.bi", "www.google.bj",
|
||||
"www.google.com.bn", "www.google.com.bo", "www.google.com.br",
|
||||
"www.google.bs", "www.google.bt", "www.google.co.bw", "www.google.by",
|
||||
"www.google.com.bz", "www.google.ca", "www.google.com.kh", "www.google.cc",
|
||||
"www.google.cd", "www.google.cf", "www.google.cat", "www.google.cg",
|
||||
"www.google.ch", "www.google.ci", "www.google.co.ck", "www.google.cl",
|
||||
"www.google.cm", "www.google.cn", "www.google.com.co", "www.google.co.cr",
|
||||
"www.google.com.cu", "www.google.cv", "www.google.cx", "www.google.com.cy",
|
||||
"www.google.cz", "www.google.de", "www.google.dj", "www.google.dk",
|
||||
"www.google.dm", "www.google.com.do", "www.google.dz", "www.google.com.ec",
|
||||
"www.google.ee", "www.google.com.eg", "www.google.es", "www.google.com.et",
|
||||
"www.google.eu", "www.google.fi", "www.google.com.fj", "www.google.fm",
|
||||
"www.google.fr", "www.google.ga", "www.google.ge", "www.google.gf",
|
||||
"www.google.gg", "www.google.com.gh", "www.google.com.gi", "www.google.gl",
|
||||
"www.google.gm", "www.google.gp", "www.google.gr", "www.google.com.gt",
|
||||
"www.google.gy", "www.google.com.hk", "www.google.hn", "www.google.hr",
|
||||
"www.google.ht", "www.google.hu", "www.google.co.id", "www.google.iq",
|
||||
"www.google.ie", "www.google.co.il", "www.google.im", "www.google.co.in",
|
||||
"www.google.io", "www.google.is", "www.google.it", "www.google.je",
|
||||
"www.google.com.jm", "www.google.jo", "www.google.co.jp", "www.google.co.ke",
|
||||
"www.google.ki", "www.google.kg", "www.google.co.kr", "www.google.com.kw",
|
||||
"www.google.kz", "www.google.la", "www.google.com.lb", "www.google.com.lc",
|
||||
"www.google.li", "www.google.lk", "www.google.co.ls", "www.google.lt",
|
||||
"www.google.lu", "www.google.lv", "www.google.com.ly", "www.google.co.ma",
|
||||
"www.google.md", "www.google.me", "www.google.mg", "www.google.mk",
|
||||
"www.google.ml", "www.google.com.mm", "www.google.mn", "www.google.ms",
|
||||
"www.google.com.mt", "www.google.mu", "www.google.mv", "www.google.mw",
|
||||
"www.google.com.mx", "www.google.com.my", "www.google.co.mz",
|
||||
"www.google.com.na", "www.google.ne", "www.google.nf", "www.google.com.ng",
|
||||
"www.google.com.ni", "www.google.nl", "www.google.no", "www.google.com.np",
|
||||
"www.google.nr", "www.google.nu", "www.google.co.nz", "www.google.com.om",
|
||||
"www.google.com.pk", "www.google.com.pa", "www.google.com.pe",
|
||||
"www.google.com.ph", "www.google.pl", "www.google.com.pg", "www.google.pn",
|
||||
"www.google.com.pr", "www.google.ps", "www.google.pt", "www.google.com.py",
|
||||
"www.google.com.qa", "www.google.ro", "www.google.rs", "www.google.ru",
|
||||
"www.google.rw", "www.google.com.sa", "www.google.com.sb", "www.google.sc",
|
||||
"www.google.se", "www.google.com.sg", "www.google.sh", "www.google.si",
|
||||
"www.google.sk", "www.google.com.sl", "www.google.sn", "www.google.sm",
|
||||
"www.google.so", "www.google.st", "www.google.sr", "www.google.com.sv",
|
||||
"www.google.td", "www.google.tg", "www.google.co.th", "www.google.com.tj",
|
||||
"www.google.tk", "www.google.tl", "www.google.tm", "www.google.to",
|
||||
"www.google.tn", "www.google.com.tr", "www.google.tt", "www.google.com.tw",
|
||||
"www.google.co.tz", "www.google.com.ua", "www.google.co.ug",
|
||||
"www.google.co.uk", "www.google.us", "www.google.com.uy", "www.google.co.uz",
|
||||
"www.google.com.vc", "www.google.co.ve", "www.google.vg", "www.google.co.vi",
|
||||
"www.google.com.vn", "www.google.vu", "www.google.ws", "www.google.co.za",
|
||||
"www.google.co.zm", "www.google.co.zw",
|
||||
]);
|
||||
|
||||
// Add Google domains to search domains
|
||||
for (let domain of googleDomains) {
|
||||
searchDomains[domain] = {
|
||||
"search": "q",
|
||||
"prefix": "client",
|
||||
"codes": ["firefox-b-ab", "firefox-b"],
|
||||
"sap": "google",
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for debugging to log messages.
|
||||
*
|
||||
* @param {String} message The message to log.
|
||||
*/
|
||||
function log(message) {
|
||||
// console.log(message);
|
||||
}
|
||||
|
||||
// Hack to handle the most common reload case.
|
||||
// If gLastSearch is the same as the current URL, ignore the search.
|
||||
// This also prevents us from handling reloads with hashes twice
|
||||
let gLastSearch = null;
|
||||
|
||||
/**
|
||||
* Since most codes are in the URL, we can handle them via
|
||||
* a progress listener.
|
||||
*/
|
||||
var webProgressListener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]),
|
||||
onLocationChange(aWebProgress, aRequest, aLocation, aFlags)
|
||||
{
|
||||
try {
|
||||
if (!aWebProgress.isTopLevel ||
|
||||
// Not a URL
|
||||
(!aLocation.schemeIs("http") && !aLocation.schemeIs("https")) ||
|
||||
// Not a domain we handle
|
||||
!(aLocation.host in searchDomains) ||
|
||||
// Doesn't have a query string or a ref
|
||||
(!aLocation.query && !aLocation.ref) ||
|
||||
// Is the same as our last search (avoids reloads)
|
||||
aLocation.spec == gLastSearch) {
|
||||
return;
|
||||
}
|
||||
let domainInfo = searchDomains[aLocation.host];
|
||||
|
||||
let queries = new URLSearchParams(aLocation.query);
|
||||
let code = queries.get(domainInfo.prefix);
|
||||
if (queries.get(domainInfo.search)) {
|
||||
if (domainInfo.codes.includes(code)) {
|
||||
if (domainInfo.reportPrefix &&
|
||||
queries.get(domainInfo.reportPrefix)) {
|
||||
code = queries.get(domainInfo.reportPrefix);
|
||||
}
|
||||
if (googleDomains.has(aLocation.host) && aLocation.ref) {
|
||||
log(`${aLocation.host} search with code ${code} - Follow on`);
|
||||
sendSaveTelemetryMsg(code, domainInfo.sap, "follow-on");
|
||||
} else if (queries.get(domainInfo.followOnSearch)) {
|
||||
log(`${aLocation.host} search with code ${code} - Follow on`);
|
||||
sendSaveTelemetryMsg(code, domainInfo.sap, "follow-on");
|
||||
} else {
|
||||
log(`${aLocation.host} search with code ${code} - First search via Firefox`);
|
||||
sendSaveTelemetryMsg(code, domainInfo.sap, "sap");
|
||||
}
|
||||
gLastSearch = aLocation.spec;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses a cookie string into separate parts.
|
||||
*
|
||||
* @param {String} cookieString The string to parse.
|
||||
* @param {Object} [params] An optional object to append the parameters to.
|
||||
* @return {Object} An object containing the query keys and values.
|
||||
*/
|
||||
function parseCookies(cookieString, params = {}) {
|
||||
var cookies = cookieString.split(/;\s*/);
|
||||
|
||||
for (var i in cookies) {
|
||||
var kvp = cookies[i].split(/=(.+)/);
|
||||
params[kvp[0]] = kvp[1];
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Page load listener to handle loads www.bing.com only.
|
||||
* We have to use a page load listener because we need
|
||||
* to check cookies.
|
||||
* @param {Object} event The page load event.
|
||||
*/
|
||||
function onPageLoad(event) {
|
||||
var doc = event.target;
|
||||
var win = doc.defaultView;
|
||||
if (win != win.top) {
|
||||
return;
|
||||
}
|
||||
var uri = doc.documentURIObject;
|
||||
if (!(uri instanceof Ci.nsIStandardURL) ||
|
||||
(!uri.schemeIs("http") && !uri.schemeIs("https")) ||
|
||||
uri.host != "www.bing.com" ||
|
||||
!doc.location.search ||
|
||||
uri.spec == gLastSearch) {
|
||||
return;
|
||||
}
|
||||
var queries = new URLSearchParams(doc.location.search);
|
||||
// For Bing, QBRE form code is used for all follow-on search
|
||||
if (queries.get("form") != "QBRE") {
|
||||
return;
|
||||
}
|
||||
if (parseCookies(doc.cookie).SRCHS == "PC=MOZI") {
|
||||
log(`${uri.host} search with code MOZI - Follow on`);
|
||||
sendSaveTelemetryMsg("MOZI", "bing", "follow-on");
|
||||
gLastSearch = uri.spec;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the process that added this script to tell it to save
|
||||
* telemetry.
|
||||
*
|
||||
* @param {String} code The codes used for the search engine.
|
||||
* @param {String} sap The SAP code.
|
||||
* @param {String} type The type of search (sap/follow-on).
|
||||
*/
|
||||
function sendSaveTelemetryMsg(code, sap, type) {
|
||||
sendAsyncMessage(kSaveTelemetryMsg, {
|
||||
code,
|
||||
sap,
|
||||
type,
|
||||
});
|
||||
}
|
||||
|
||||
addEventListener("DOMContentLoaded", onPageLoad, false);
|
||||
docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebProgress)
|
||||
.addProgressListener(webProgressListener, Ci.nsIWebProgress.NOTIFY_LOCATION);
|
||||
|
||||
let gDisabled = false;
|
||||
|
||||
addMessageListener(kShutdownMsg, () => {
|
||||
if (!gDisabled) {
|
||||
removeEventListener("DOMContentLoaded", onPageLoad, false);
|
||||
docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebProgress)
|
||||
.removeProgressListener(webProgressListener);
|
||||
gDisabled = true;
|
||||
}
|
||||
});
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>followonsearch@mozilla.com</em:id>
|
||||
<em:name>Follow-on Search Telemetry</em:name>
|
||||
<em:version>0.8.0</em:version>
|
||||
<em:type>2</em:type>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
<em:multiprocessCompatible>true</em:multiprocessCompatible>
|
||||
<em:targetApplication>
|
||||
<Description>
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||
<em:minVersion>52.0</em:minVersion>
|
||||
<em:maxVersion>59.*</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
</Description>
|
||||
</RDF>
|
|
@ -0,0 +1,7 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
[features/followonsearch@mozilla.com] chrome.jar:
|
||||
% content followonsearch %content/
|
||||
content/ (content/*)
|
|
@ -0,0 +1,15 @@
|
|||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
with Files("**"):
|
||||
BUG_COMPONENT = ("Firefox", "Search")
|
||||
|
||||
FINAL_TARGET_FILES.features['followonsearch@mozilla.com'] += [
|
||||
'bootstrap.js',
|
||||
'install.rdf',
|
||||
]
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
|
@ -7,6 +7,7 @@
|
|||
DIRS += [
|
||||
'aushelper',
|
||||
'e10srollout',
|
||||
'followonsearch',
|
||||
'pdfjs',
|
||||
'pocket',
|
||||
'screenshots',
|
||||
|
|
|
@ -346,6 +346,9 @@ panelview:not([mainview]) .toolbarbutton-text,
|
|||
photonpanelmultiview panelview {
|
||||
background: var(--arrowpanel-background);
|
||||
padding: 6px 0;
|
||||
}
|
||||
|
||||
#appMenu-popup panelview {
|
||||
min-width: @menuPanelWidth@;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ function test() {
|
|||
|
||||
gBrowser.removeCurrentTab();
|
||||
|
||||
yield TestUtils.topicObserved("outer-window-destroyed", (subject, data) => {
|
||||
yield TestUtils.topicObserved("outer-window-nuked", (subject, data) => {
|
||||
let id = subject.QueryInterface(Components.interfaces.nsISupportsPRUint64).data;
|
||||
return id == winID;
|
||||
});
|
||||
|
|
|
@ -21,18 +21,12 @@ public:
|
|||
typedef TimeoutManager::Timeouts Timeouts;
|
||||
typedef Timeouts::TimeoutList TimeoutList;
|
||||
|
||||
// Passing null for aNormalStopAt or aTrackingStopAt means that the
|
||||
// corresponding timeout list should be iterated all the way to the end.
|
||||
OrderedTimeoutIterator(Timeouts& aNormalTimeouts,
|
||||
Timeouts& aTrackingTimeouts,
|
||||
Timeout* aNormalStopAt,
|
||||
Timeout* aTrackingStopAt)
|
||||
Timeouts& aTrackingTimeouts)
|
||||
: mNormalTimeouts(aNormalTimeouts.mTimeoutList),
|
||||
mTrackingTimeouts(aTrackingTimeouts.mTimeoutList),
|
||||
mNormalIter(mNormalTimeouts.getFirst()),
|
||||
mTrackingIter(mTrackingTimeouts.getFirst()),
|
||||
mNormalStopAt(aNormalStopAt),
|
||||
mTrackingStopAt(aTrackingStopAt),
|
||||
mKind(Kind::None),
|
||||
mUpdateIteratorCalled(true)
|
||||
{
|
||||
|
@ -44,16 +38,14 @@ public:
|
|||
Timeout* Next()
|
||||
{
|
||||
MOZ_ASSERT(mUpdateIteratorCalled);
|
||||
MOZ_ASSERT_IF(mNormalIter && mNormalIter != mNormalStopAt,
|
||||
mNormalIter->isInList());
|
||||
MOZ_ASSERT_IF(mTrackingIter && mTrackingIter != mTrackingStopAt,
|
||||
mTrackingIter->isInList());
|
||||
MOZ_ASSERT_IF(mNormalIter, mNormalIter->isInList());
|
||||
MOZ_ASSERT_IF(mTrackingIter, mTrackingIter->isInList());
|
||||
|
||||
mUpdateIteratorCalled = false;
|
||||
mKind = Kind::None;
|
||||
Timeout* timeout = nullptr;
|
||||
if (mNormalIter == mNormalStopAt) {
|
||||
if (mTrackingIter == mTrackingStopAt) {
|
||||
if (!mNormalIter) {
|
||||
if (!mTrackingIter) {
|
||||
// We have reached the end of both lists. Bail out!
|
||||
return nullptr;
|
||||
} else {
|
||||
|
@ -62,7 +54,7 @@ public:
|
|||
timeout = mTrackingIter;
|
||||
mKind = Kind::Tracking;
|
||||
}
|
||||
} else if (mTrackingIter == mTrackingStopAt) {
|
||||
} else if (!mTrackingIter) {
|
||||
// We have reached the end of the tracking timeout list, select the next
|
||||
// normal timeout.
|
||||
timeout = mNormalIter;
|
||||
|
@ -76,17 +68,15 @@ public:
|
|||
// different mWhen values, so in practice we shouldn't fall back to
|
||||
// comparing timeout IDs.
|
||||
if (mNormalIter && mTrackingIter &&
|
||||
mNormalIter != mNormalStopAt &&
|
||||
mTrackingIter != mTrackingStopAt &&
|
||||
(mTrackingIter->When() < mNormalIter->When() ||
|
||||
(mTrackingIter->When() == mNormalIter->When() &&
|
||||
mTrackingIter->mTimeoutId < mNormalIter->mTimeoutId))) {
|
||||
timeout = mTrackingIter;
|
||||
mKind = Kind::Tracking;
|
||||
} else if (mNormalIter && mNormalIter != mNormalStopAt) {
|
||||
} else if (mNormalIter) {
|
||||
timeout = mNormalIter;
|
||||
mKind = Kind::Normal;
|
||||
} else if (mTrackingIter && mTrackingIter != mTrackingStopAt) {
|
||||
} else if (mTrackingIter) {
|
||||
timeout = mTrackingIter;
|
||||
mKind = Kind::Tracking;
|
||||
}
|
||||
|
@ -120,14 +110,12 @@ public:
|
|||
// the timeout pointed to from one of our iterators.
|
||||
if (mKind == Kind::Normal) {
|
||||
mNormalIter = mCurrent->getNext();
|
||||
if (mTrackingIter && mTrackingIter != mTrackingStopAt &&
|
||||
!mTrackingIter->isInList()) {
|
||||
if (mTrackingIter && !mTrackingIter->isInList()) {
|
||||
mTrackingIter = mTrackingTimeouts.getFirst();
|
||||
}
|
||||
} else {
|
||||
mTrackingIter = mCurrent->getNext();
|
||||
if (mNormalIter && mNormalIter != mNormalStopAt &&
|
||||
!mNormalIter->isInList()) {
|
||||
if (mNormalIter && !mNormalIter->isInList()) {
|
||||
mNormalIter = mNormalTimeouts.getFirst();
|
||||
}
|
||||
}
|
||||
|
@ -173,8 +161,6 @@ private:
|
|||
TimeoutList& mTrackingTimeouts; // The list of tracking timeouts.
|
||||
RefPtr<Timeout> mNormalIter; // The iterator over the normal timeout list.
|
||||
RefPtr<Timeout> mTrackingIter; // The iterator over the tracking timeout list.
|
||||
void* mNormalStopAt; // Where to stop iterating the normal list at.
|
||||
void* mTrackingStopAt; // Where to stop iterating the tracking list at.
|
||||
RefPtr<Timeout> mCurrent; // The current timeout that Next() just found.
|
||||
enum class Kind { Normal, Tracking, None };
|
||||
Kind mKind; // The kind of iterator picked the last time.
|
||||
|
|
|
@ -525,10 +525,7 @@ TimeoutManager::ClearTimeout(int32_t aTimerId, Timeout::Reason aReason)
|
|||
// restart at the next soonest deadline.
|
||||
mExecutor->Cancel();
|
||||
|
||||
OrderedTimeoutIterator iter(mNormalTimeouts,
|
||||
mTrackingTimeouts,
|
||||
nullptr,
|
||||
nullptr);
|
||||
OrderedTimeoutIterator iter(mNormalTimeouts, mTrackingTimeouts);
|
||||
Timeout* nextTimeout = iter.Next();
|
||||
if (nextTimeout) {
|
||||
MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(nextTimeout->When()));
|
||||
|
@ -565,10 +562,6 @@ TimeoutManager::RunTimeout(const TimeStamp& aNow, const TimeStamp& aTargetDeadli
|
|||
TimeStamp now(aNow);
|
||||
TimeStamp start = now;
|
||||
|
||||
Timeout* last_expired_normal_timeout = nullptr;
|
||||
Timeout* last_expired_tracking_timeout = nullptr;
|
||||
bool last_expired_timeout_is_normal = false;
|
||||
|
||||
uint32_t firingId = CreateFiringId();
|
||||
auto guard = MakeScopeExit([&] {
|
||||
DestroyFiringId(firingId);
|
||||
|
@ -598,6 +591,7 @@ TimeoutManager::RunTimeout(const TimeStamp& aNow, const TimeStamp& aTargetDeadli
|
|||
}
|
||||
|
||||
TimeStamp nextDeadline;
|
||||
uint32_t numTimersToRun = 0;
|
||||
|
||||
// The timeout list is kept in deadline order. Discover the latest timeout
|
||||
// whose deadline has expired. On some platforms, native timeout events fire
|
||||
|
@ -608,12 +602,7 @@ TimeoutManager::RunTimeout(const TimeStamp& aNow, const TimeStamp& aTargetDeadli
|
|||
{
|
||||
// Use a nested scope in order to make sure the strong references held by
|
||||
// the iterator are freed after the loop.
|
||||
OrderedTimeoutIterator expiredIter(mNormalTimeouts,
|
||||
mTrackingTimeouts,
|
||||
nullptr,
|
||||
nullptr);
|
||||
|
||||
uint32_t numTimersToRun = 0;
|
||||
OrderedTimeoutIterator expiredIter(mNormalTimeouts, mTrackingTimeouts);
|
||||
|
||||
while (true) {
|
||||
Timeout* timeout = expiredIter.Next();
|
||||
|
@ -628,12 +617,6 @@ TimeoutManager::RunTimeout(const TimeStamp& aNow, const TimeStamp& aTargetDeadli
|
|||
// Mark any timeouts that are on the list to be fired with the
|
||||
// firing depth so that we can reentrantly run timeouts
|
||||
timeout->mFiringId = firingId;
|
||||
last_expired_timeout_is_normal = expiredIter.PickedNormalIter();
|
||||
if (last_expired_timeout_is_normal) {
|
||||
last_expired_normal_timeout = timeout;
|
||||
} else {
|
||||
last_expired_tracking_timeout = timeout;
|
||||
}
|
||||
|
||||
numTimersToRun += 1;
|
||||
|
||||
|
@ -666,7 +649,7 @@ TimeoutManager::RunTimeout(const TimeStamp& aNow, const TimeStamp& aTargetDeadli
|
|||
// Maybe the timeout that the event was fired for has been deleted
|
||||
// and there are no others timeouts with deadlines that make them
|
||||
// eligible for execution yet. Go away.
|
||||
if (!last_expired_normal_timeout && !last_expired_tracking_timeout) {
|
||||
if (!numTimersToRun) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -680,14 +663,7 @@ TimeoutManager::RunTimeout(const TimeStamp& aNow, const TimeStamp& aTargetDeadli
|
|||
{
|
||||
// Use a nested scope in order to make sure the strong references held by
|
||||
// the iterator are freed after the loop.
|
||||
OrderedTimeoutIterator runIter(mNormalTimeouts,
|
||||
mTrackingTimeouts,
|
||||
last_expired_normal_timeout ?
|
||||
last_expired_normal_timeout->getNext() :
|
||||
nullptr,
|
||||
last_expired_tracking_timeout ?
|
||||
last_expired_tracking_timeout->getNext() :
|
||||
nullptr);
|
||||
OrderedTimeoutIterator runIter(mNormalTimeouts, mTrackingTimeouts);
|
||||
while (true) {
|
||||
RefPtr<Timeout> timeout = runIter.Next();
|
||||
if (!timeout) {
|
||||
|
@ -696,12 +672,26 @@ TimeoutManager::RunTimeout(const TimeStamp& aNow, const TimeStamp& aTargetDeadli
|
|||
}
|
||||
runIter.UpdateIterator();
|
||||
|
||||
// We should only execute callbacks for the set of expired Timeout
|
||||
// objects we computed above.
|
||||
if (timeout->mFiringId != firingId) {
|
||||
// We skip the timeout since it's on the list to run at another
|
||||
// depth.
|
||||
// If the FiringId does not match, but is still valid, then this is
|
||||
// a TImeout for another RunTimeout() on the call stack. Just
|
||||
// skip it.
|
||||
if (IsValidFiringId(timeout->mFiringId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If, however, the FiringId is invalid then we have reached Timeout
|
||||
// objects beyond the list we calculated above. This can happen
|
||||
// if the Timeout just beyond our last expired Timeout is cancelled
|
||||
// by one of the callbacks we've just executed. In this case we
|
||||
// should just stop iterating. We're done.
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT_IF(mWindow.IsFrozen(), mWindow.IsSuspended());
|
||||
if (mWindow.IsSuspended()) {
|
||||
break;
|
||||
|
@ -847,10 +837,7 @@ TimeoutManager::ResetTimersForThrottleReduction(int32_t aPreviousThrottleDelayMS
|
|||
sortBy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
OrderedTimeoutIterator iter(mNormalTimeouts,
|
||||
mTrackingTimeouts,
|
||||
nullptr,
|
||||
nullptr);
|
||||
OrderedTimeoutIterator iter(mNormalTimeouts, mTrackingTimeouts);
|
||||
Timeout* firstTimeout = iter.Next();
|
||||
if (firstTimeout) {
|
||||
rv = mExecutor->MaybeSchedule(firstTimeout->When());
|
||||
|
|
|
@ -741,16 +741,15 @@ nsExternalResourceMap::RequestResource(nsIURI* aURI,
|
|||
return resource->mDocument;
|
||||
}
|
||||
|
||||
RefPtr<PendingLoad> load;
|
||||
mPendingLoads.Get(clone, getter_AddRefs(load));
|
||||
if (load) {
|
||||
RefPtr<PendingLoad>& loadEntry = mPendingLoads.GetOrInsert(clone);
|
||||
if (loadEntry) {
|
||||
RefPtr<PendingLoad> load(loadEntry);
|
||||
load.forget(aPendingLoad);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
load = new PendingLoad(aDisplayDocument);
|
||||
|
||||
mPendingLoads.Put(clone, load);
|
||||
RefPtr<PendingLoad> load(new PendingLoad(aDisplayDocument));
|
||||
loadEntry = load;
|
||||
|
||||
if (NS_FAILED(load->StartLoad(clone, aRequestingNode))) {
|
||||
// Make sure we don't thrash things by trying this load again, since
|
||||
|
@ -873,8 +872,7 @@ nsExternalResourceMap::AddExternalResource(nsIURI* aURI,
|
|||
"Must have both or neither");
|
||||
|
||||
RefPtr<PendingLoad> load;
|
||||
mPendingLoads.Get(aURI, getter_AddRefs(load));
|
||||
mPendingLoads.Remove(aURI);
|
||||
mPendingLoads.Remove(aURI, getter_AddRefs(load));
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
|
|
@ -9628,16 +9628,24 @@ struct BrowserCompartmentMatcher : public js::CompartmentFilter {
|
|||
};
|
||||
|
||||
|
||||
class WindowDestroyedEvent : public Runnable
|
||||
class WindowDestroyedEvent final : public Runnable
|
||||
{
|
||||
public:
|
||||
WindowDestroyedEvent(nsIDOMWindow* aWindow, uint64_t aID,
|
||||
const char* aTopic) :
|
||||
mID(aID), mTopic(aTopic)
|
||||
mID(aID),
|
||||
mPhase(Phase::Destroying),
|
||||
mTopic(aTopic)
|
||||
{
|
||||
mWindow = do_GetWeakReference(aWindow);
|
||||
}
|
||||
|
||||
enum class Phase
|
||||
{
|
||||
Destroying,
|
||||
Nuking
|
||||
};
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
PROFILER_LABEL("WindowDestroyedEvent", "Run",
|
||||
|
@ -9645,15 +9653,20 @@ public:
|
|||
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
services::GetObserverService();
|
||||
if (observerService) {
|
||||
if (!observerService) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupportsPRUint64> wrapper =
|
||||
do_CreateInstance(NS_SUPPORTS_PRUINT64_CONTRACTID);
|
||||
if (wrapper) {
|
||||
wrapper->SetData(mID);
|
||||
observerService->NotifyObservers(wrapper, mTopic.get(), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
switch (mPhase) {
|
||||
case Phase::Destroying:
|
||||
{
|
||||
bool skipNukeCrossCompartment = false;
|
||||
#ifndef DEBUG
|
||||
nsCOMPtr<nsIAppStartup> appStartup =
|
||||
|
@ -9664,8 +9677,30 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!skipNukeCrossCompartment) {
|
||||
// The compartment nuking phase might be too expensive, so do that
|
||||
// part off of idle dispatch.
|
||||
|
||||
// For the compartment nuking phase, we dispatch either an
|
||||
// inner-window-nuked or an outer-window-nuked notification.
|
||||
// This will allow tests to wait for compartment nuking to happen.
|
||||
if (mTopic.EqualsLiteral("inner-window-destroyed")) {
|
||||
mTopic.AssignLiteral("inner-window-nuked");
|
||||
} else if (mTopic.EqualsLiteral("outer-window-destroyed")) {
|
||||
mTopic.AssignLiteral("outer-window-nuked");
|
||||
}
|
||||
mPhase = Phase::Nuking;
|
||||
|
||||
nsCOMPtr<nsIRunnable> copy(this);
|
||||
NS_IdleDispatchToCurrentThread(copy.forget(), 1000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Phase::Nuking:
|
||||
{
|
||||
nsCOMPtr<nsISupports> window = do_QueryReferent(mWindow);
|
||||
if (!skipNukeCrossCompartment && window) {
|
||||
if (window) {
|
||||
nsGlobalWindow* win = nsGlobalWindow::FromSupports(window);
|
||||
nsGlobalWindow* currentInner = win->IsInnerWindow() ? win : win->GetCurrentInnerWindowInternal();
|
||||
NS_ENSURE_TRUE(currentInner, NS_OK);
|
||||
|
@ -9691,12 +9726,16 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t mID;
|
||||
Phase mPhase;
|
||||
nsCString mTopic;
|
||||
nsWeakPtr mWindow;
|
||||
};
|
||||
|
|
|
@ -13,7 +13,7 @@ add_task(function* test() {
|
|||
let contentDocDead = yield ContentTask.spawn(browser,{innerWindowId}, function*(args){
|
||||
let doc = content.document;
|
||||
let {TestUtils} = Components.utils.import("resource://testing-common/TestUtils.jsm", {});
|
||||
let promise = TestUtils.topicObserved("inner-window-destroyed", (subject, data) => {
|
||||
let promise = TestUtils.topicObserved("inner-window-nuked", (subject, data) => {
|
||||
let id = subject.QueryInterface(Components.interfaces.nsISupportsPRUint64).data;
|
||||
return id == args.innerWindowId;
|
||||
});
|
||||
|
|
|
@ -49,7 +49,7 @@ function go() {
|
|||
// once the window is destroyed.
|
||||
frame.remove();
|
||||
|
||||
TestUtils.topicObserved("outer-window-destroyed", (subject, data) => {
|
||||
TestUtils.topicObserved("outer-window-nuked", (subject, data) => {
|
||||
let id = subject.QueryInterface(SpecialPowers.Ci.nsISupportsPRUint64).data;
|
||||
return id == winID;
|
||||
}).then(() => {
|
||||
|
|
|
@ -25,11 +25,11 @@ function waitForWindowDestroyed(winID, callback) {
|
|||
if (id != winID) {
|
||||
return;
|
||||
}
|
||||
SpecialPowers.removeObserver(observer, "outer-window-destroyed");
|
||||
SpecialPowers.removeObserver(observer, "outer-window-nuked");
|
||||
SpecialPowers.executeSoon(callback);
|
||||
}
|
||||
};
|
||||
SpecialPowers.addObserver(observer, "outer-window-destroyed");
|
||||
SpecialPowers.addObserver(observer, "outer-window-nuked");
|
||||
}
|
||||
|
||||
add_task(function* () {
|
||||
|
|
|
@ -61,8 +61,8 @@ add_task(function*() {
|
|||
|
||||
webnavB.close();
|
||||
|
||||
// Wrappers are destroyed asynchronously, so wait for that to happen.
|
||||
yield TestUtils.topicObserved("inner-window-destroyed");
|
||||
// Wrappers are nuked asynchronously, so wait for that to happen.
|
||||
yield TestUtils.topicObserved("inner-window-nuked");
|
||||
|
||||
// Check that it can't be accessed after he window has been closed.
|
||||
let result = getThing();
|
||||
|
|
|
@ -276,16 +276,26 @@ nsFrameManager::ClearUndisplayedContentIn(nsIContent* aContent,
|
|||
}
|
||||
|
||||
void
|
||||
nsFrameManager::ClearAllUndisplayedContentIn(nsIContent* aParentContent)
|
||||
nsFrameManager::ClearAllMapsFor(nsIContent* aParentContent)
|
||||
{
|
||||
#ifdef DEBUG_UNDISPLAYED_MAP
|
||||
#if defined(DEBUG_UNDISPLAYED_MAP) || defined(DEBUG_DISPLAY_CONTENTS_MAP)
|
||||
static int i = 0;
|
||||
printf("ClearAllUndisplayedContentIn(%d): parent=%p \n", i++, (void*)aParentContent);
|
||||
printf("ClearAllMapsFor(%d): parent=%p \n", i++, aParentContent);
|
||||
#endif
|
||||
|
||||
if (mUndisplayedMap) {
|
||||
mUndisplayedMap->RemoveNodesFor(aParentContent);
|
||||
}
|
||||
if (mDisplayContentsMap) {
|
||||
nsAutoPtr<LinkedList<UndisplayedNode>> list =
|
||||
mDisplayContentsMap->UnlinkNodesFor(aParentContent);
|
||||
if (list) {
|
||||
while (UndisplayedNode* node = list->popFirst()) {
|
||||
ClearAllMapsFor(node->mContent);
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Need to look at aParentContent's content list due to XBL insertions.
|
||||
// Nodes in aParentContent's content list do not have aParentContent as a
|
||||
|
@ -293,8 +303,10 @@ nsFrameManager::ClearAllUndisplayedContentIn(nsIContent* aParentContent)
|
|||
// the flattened content list and just ignore any nodes we don't care about.
|
||||
FlattenedChildIterator iter(aParentContent);
|
||||
for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
|
||||
if (child->GetParent() != aParentContent) {
|
||||
ClearUndisplayedContentIn(child, child->GetParent());
|
||||
auto parent = child->GetParent();
|
||||
if (parent != aParentContent) {
|
||||
ClearUndisplayedContentIn(child, parent);
|
||||
ClearDisplayContentsIn(child, parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -341,8 +353,7 @@ nsFrameManager::ClearDisplayContentsIn(nsIContent* aContent,
|
|||
// make sure that there are no more entries for the same content
|
||||
MOZ_ASSERT(!GetDisplayContentsStyleFor(aContent),
|
||||
"Found more entries for aContent after removal");
|
||||
ClearAllDisplayContentsIn(aContent);
|
||||
ClearAllUndisplayedContentIn(aContent);
|
||||
ClearAllMapsFor(aContent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -351,39 +362,6 @@ nsFrameManager::ClearDisplayContentsIn(nsIContent* aContent,
|
|||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameManager::ClearAllDisplayContentsIn(nsIContent* aParentContent)
|
||||
{
|
||||
#ifdef DEBUG_DISPLAY_CONTENTS_MAP
|
||||
static int i = 0;
|
||||
printf("ClearAllDisplayContentsIn(%d): parent=%p \n", i++, (void*)aParentContent);
|
||||
#endif
|
||||
|
||||
if (mDisplayContentsMap) {
|
||||
nsAutoPtr<LinkedList<UndisplayedNode>> list =
|
||||
mDisplayContentsMap->UnlinkNodesFor(aParentContent);
|
||||
if (list) {
|
||||
while (UndisplayedNode* node = list->popFirst()) {
|
||||
ClearAllDisplayContentsIn(node->mContent);
|
||||
ClearAllUndisplayedContentIn(node->mContent);
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Need to look at aParentContent's content list due to XBL insertions.
|
||||
// Nodes in aParentContent's content list do not have aParentContent as a
|
||||
// parent, but are treated as children of aParentContent. We iterate over
|
||||
// the flattened content list and just ignore any nodes we don't care about.
|
||||
FlattenedChildIterator iter(aParentContent);
|
||||
for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
|
||||
if (child->GetParent() != aParentContent) {
|
||||
ClearDisplayContentsIn(child, child->GetParent());
|
||||
ClearUndisplayedContentIn(child, child->GetParent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void
|
||||
nsFrameManager::AppendFrames(nsContainerFrame* aParentFrame,
|
||||
|
@ -460,8 +438,7 @@ nsFrameManager::NotifyDestroyingFrame(nsIFrame* aFrame)
|
|||
{
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
if (content && content->GetPrimaryFrame() == aFrame) {
|
||||
ClearAllUndisplayedContentIn(content);
|
||||
ClearAllDisplayContentsIn(content);
|
||||
ClearAllMapsFor(content);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,6 @@ public:
|
|||
|
||||
void ClearUndisplayedContentIn(nsIContent* aContent,
|
||||
nsIContent* aParentContent);
|
||||
void ClearAllUndisplayedContentIn(nsIContent* aParentContent);
|
||||
|
||||
// display:contents related methods:
|
||||
/**
|
||||
|
@ -149,7 +148,6 @@ public:
|
|||
* style contexts for its descendants.
|
||||
*/
|
||||
void ClearDisplayContentsIn(nsIContent* aContent, nsIContent* aParentContent);
|
||||
void ClearAllDisplayContentsIn(nsIContent* aParentContent);
|
||||
|
||||
// Functions for manipulating the frame model
|
||||
void AppendFrames(nsContainerFrame* aParentFrame,
|
||||
|
@ -190,6 +188,8 @@ public:
|
|||
void RestoreFrameStateFor(nsIFrame* aFrame, nsILayoutHistoryState* aState);
|
||||
|
||||
protected:
|
||||
void ClearAllMapsFor(nsIContent* aParentContent);
|
||||
|
||||
static nsStyleContext* GetStyleContextInMap(UndisplayedMap* aMap,
|
||||
const nsIContent* aContent);
|
||||
static mozilla::UndisplayedNode*
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestFlakyTimeout('nsPresContext internally delays applying prefs using an nsITimer');
|
||||
|
||||
var cs1 = getComputedStyle(document.getElementById("one"), "");
|
||||
var cs2 = getComputedStyle(document.getElementById("two"), "");
|
||||
|
@ -50,7 +51,18 @@ var cs5 = getComputedStyle(document.getElementById("five"), "");
|
|||
var cs6 = getComputedStyle(document.getElementById("six"), "");
|
||||
var cs7 = getComputedStyle(document.getElementById("seven"), "");
|
||||
|
||||
SpecialPowers.pushPrefEnv({'set': [['browser.display.document_color_use', 1]]}, part1);
|
||||
function pushPrefEnvAndWait(args, cb) {
|
||||
SpecialPowers.pushPrefEnv(args, _ => {
|
||||
// The nsPresContext delays applying a preference change until after a 0ms
|
||||
// nsITimer fires. The SpecialPowers.pushPrefEnv() uses setTimeout(f, 0)
|
||||
// which may execute as a simple runnable dispatch and fire before the
|
||||
// 0ms nsITimer. Therefore wait an additional 1ms to allow the nsPresContext
|
||||
// to apply the preferences.
|
||||
setTimeout(cb, 1);
|
||||
});
|
||||
}
|
||||
|
||||
pushPrefEnvAndWait({'set': [['browser.display.document_color_use', 1]]}, part1);
|
||||
|
||||
var transparentBackgroundColor;
|
||||
var inputBackgroundColor, inputColor, inputBorderTopColor;
|
||||
|
@ -121,7 +133,7 @@ function part1()
|
|||
inputBorderRightColor = cs4.borderRightColor;
|
||||
inputBorderLeftColor = cs4.borderLeftColor;
|
||||
inputBorderBottomColor = cs4.borderBottomColor;
|
||||
SpecialPowers.pushPrefEnv({'set': [['browser.display.document_color_use', 2]]}, part2);
|
||||
pushPrefEnvAndWait({'set': [['browser.display.document_color_use', 2]]}, part2);
|
||||
}
|
||||
|
||||
function part2()
|
||||
|
|
|
@ -45,6 +45,14 @@ android {
|
|||
}
|
||||
|
||||
buildTypes {
|
||||
// Bug 1367768: With current code, we need jumboMode for a string table larger than 65536.
|
||||
// To not interrupt release 55 nightly to beta merge, jumboMode only applies to debug now
|
||||
// and will apply to all builds very soon (Mid June 2017, see bug 1370156).
|
||||
debug {
|
||||
dexOptions {
|
||||
jumboMode = true
|
||||
}
|
||||
}
|
||||
// We have the following difficult situation. Minification (Proguard) is only available per
|
||||
// Android-Gradle `buildType`. Instrumentation (Robocop) is only available for exactly one
|
||||
// `buildType` (see Android-Gradle `testBuildType`, which defaults to "debug"). Local
|
||||
|
|
|
@ -5746,4 +5746,4 @@ pref("layers.advanced.text-layers", 2);
|
|||
pref("layers.advanced.filter-layers", 2);
|
||||
|
||||
// Enable lowercased response header name
|
||||
pref("dom.xhr.lowercase_header.enabled", true);
|
||||
pref("dom.xhr.lowercase_header.enabled", false);
|
||||
|
|
|
@ -1 +1 @@
|
|||
NSS_3_31_BETA2
|
||||
NSS_3_31_RTM
|
||||
|
|
|
@ -10,4 +10,3 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
|
|
@ -22,12 +22,12 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
||||
*/
|
||||
#define NSS_VERSION "3.31" _NSS_CUSTOMIZED " Beta"
|
||||
#define NSS_VERSION "3.31" _NSS_CUSTOMIZED
|
||||
#define NSS_VMAJOR 3
|
||||
#define NSS_VMINOR 31
|
||||
#define NSS_VPATCH 0
|
||||
#define NSS_VBUILD 0
|
||||
#define NSS_BETA PR_TRUE
|
||||
#define NSS_BETA PR_FALSE
|
||||
|
||||
#ifndef RC_INVOKED
|
||||
|
||||
|
|
|
@ -21,11 +21,11 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
||||
*/
|
||||
#define SOFTOKEN_VERSION "3.31" SOFTOKEN_ECC_STRING " Beta"
|
||||
#define SOFTOKEN_VERSION "3.31" SOFTOKEN_ECC_STRING
|
||||
#define SOFTOKEN_VMAJOR 3
|
||||
#define SOFTOKEN_VMINOR 31
|
||||
#define SOFTOKEN_VPATCH 0
|
||||
#define SOFTOKEN_VBUILD 0
|
||||
#define SOFTOKEN_BETA PR_TRUE
|
||||
#define SOFTOKEN_BETA PR_FALSE
|
||||
|
||||
#endif /* _SOFTKVER_H_ */
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
|
||||
*/
|
||||
#define NSSUTIL_VERSION "3.31 Beta"
|
||||
#define NSSUTIL_VERSION "3.31"
|
||||
#define NSSUTIL_VMAJOR 3
|
||||
#define NSSUTIL_VMINOR 31
|
||||
#define NSSUTIL_VPATCH 0
|
||||
#define NSSUTIL_VBUILD 0
|
||||
#define NSSUTIL_BETA PR_TRUE
|
||||
#define NSSUTIL_BETA PR_FALSE
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
|
|
|
@ -58,8 +58,6 @@ linux64-nightly/opt:
|
|||
- web-platform-tests
|
||||
- opt-only-tests
|
||||
- desktop-screenshot-capture
|
||||
- talos
|
||||
- awsy
|
||||
- headless
|
||||
linux64-devedition/opt:
|
||||
build-platform: linux64-devedition-nightly/opt
|
||||
|
@ -68,7 +66,6 @@ linux64-devedition/opt:
|
|||
- web-platform-tests
|
||||
- opt-only-tests
|
||||
- desktop-screenshot-capture
|
||||
- awsy
|
||||
- headless
|
||||
|
||||
# TODO: use 'pgo' and 'asan' labels here, instead of -pgo/opt
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
prefs: [dom.xhr.lowercase_header.enabled:true]
|
|
@ -123,12 +123,7 @@ public:
|
|||
*/
|
||||
DataType& GetOrInsert(const KeyType& aKey)
|
||||
{
|
||||
EntryType* ent = this->GetEntry(aKey);
|
||||
if (ent) {
|
||||
return ent->mData;
|
||||
}
|
||||
|
||||
ent = this->PutEntry(aKey);
|
||||
EntryType* ent = this->PutEntry(aKey);
|
||||
return ent->mData;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче