mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Merge mozilla-central to inbound. a=merge CLOSED TREE
This commit is contained in:
commit
afe10a4af5
@ -1764,3 +1764,6 @@ pref("browser.onboarding.updatetour", "performance,library,screenshots,singlesea
|
||||
|
||||
// Preference that allows individual users to disable Screenshots.
|
||||
pref("extensions.screenshots.disabled", false);
|
||||
// Preference that allows individual users to leave Screenshots enabled, but
|
||||
// disable uploading to the server.
|
||||
pref("extensions.screenshots.upload-disabled", false);
|
||||
|
@ -11,8 +11,14 @@ const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gXulStore",
|
||||
"@mozilla.org/xul/xulstore;1",
|
||||
"nsIXULStore");
|
||||
|
||||
const PREF_LOGLEVEL = "browser.policies.loglevel";
|
||||
const PREF_MENU_ALREADY_DISPLAYED = "browser.policies.menuBarWasDisplayed";
|
||||
const BROWSER_DOCUMENT_URL = "chrome://browser/content/browser.xul";
|
||||
const PREF_BOOKMARKS_ALREADY_DISPLAYED = "browser.policies.bookmarkBarWasDisplayed";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "log", () => {
|
||||
let { ConsoleAPI } = Cu.import("resource://gre/modules/Console.jsm", {});
|
||||
@ -36,6 +42,40 @@ this.Policies = {
|
||||
}
|
||||
},
|
||||
|
||||
"display_menu_bar": {
|
||||
onBeforeUIStartup(manager, param) {
|
||||
if (param == true) {
|
||||
// This policy is meant to change the default behavior, not to force it.
|
||||
// If this policy was alreay applied and the user chose to re-hide the
|
||||
// menu bar, do not show it again.
|
||||
if (!Services.prefs.getBoolPref(PREF_MENU_ALREADY_DISPLAYED, false)) {
|
||||
log.debug("Showing the menu bar");
|
||||
gXulStore.setValue(BROWSER_DOCUMENT_URL, "toolbar-menubar", "autohide", "false");
|
||||
Services.prefs.setBoolPref(PREF_MENU_ALREADY_DISPLAYED, true);
|
||||
} else {
|
||||
log.debug("Not showing the menu bar because it has already been shown.");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"display_bookmarks_toolbar": {
|
||||
onBeforeUIStartup(manager, param) {
|
||||
if (param == true) {
|
||||
// This policy is meant to change the default behavior, not to force it.
|
||||
// If this policy was alreay applied and the user chose to re-hide the
|
||||
// bookmarks toolbar, do not show it again.
|
||||
if (!Services.prefs.getBoolPref(PREF_BOOKMARKS_ALREADY_DISPLAYED, false)) {
|
||||
log.debug("Showing the bookmarks toolbar");
|
||||
gXulStore.setValue(BROWSER_DOCUMENT_URL, "PersonalToolbar", "collapsed", "false");
|
||||
Services.prefs.setBoolPref(PREF_BOOKMARKS_ALREADY_DISPLAYED, true);
|
||||
} else {
|
||||
log.debug("Not showing the bookmarks toolbar because it has already been shown.");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"dont_check_default_browser": {
|
||||
onBeforeUIStartup(manager, param) {
|
||||
setAndLockPref("browser.shell.checkDefaultBrowser", false);
|
||||
|
@ -10,6 +10,22 @@
|
||||
"enum": [true]
|
||||
},
|
||||
|
||||
"display_menu_bar": {
|
||||
"description": "Causes the menu bar to be displayed by default.",
|
||||
"first_available": "60.0",
|
||||
|
||||
"type": "boolean",
|
||||
"enum": [true]
|
||||
},
|
||||
|
||||
"display_bookmarks_toolbar": {
|
||||
"description": "Causes the bookmarks toolbar to be displayed by default.",
|
||||
"first_available": "60.0",
|
||||
|
||||
"type": "boolean",
|
||||
"enum": [true]
|
||||
},
|
||||
|
||||
"dont_check_default_browser": {
|
||||
"description": "Don't check for the default browser on startup.",
|
||||
"first_available": "60.0",
|
||||
|
@ -8,6 +8,8 @@ support-files =
|
||||
config_setAndLockPref.json
|
||||
config_simple_policies.json
|
||||
config_broken_json.json
|
||||
config_display_menu.json
|
||||
config_display_bookmarks.json
|
||||
|
||||
[browser_policies_broken_json.js]
|
||||
[browser_policies_popups_cookies_addons_flash.js]
|
||||
@ -15,3 +17,5 @@ support-files =
|
||||
[browser_policies_simple_policies.js]
|
||||
[browser_policies_validate_and_parse_API.js]
|
||||
[browser_policy_default_browser_check.js]
|
||||
[browser_policy_display_menu.js]
|
||||
[browser_policy_display_bookmarks.js]
|
||||
|
@ -0,0 +1,19 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async function setup() {
|
||||
await setupPolicyEngineWithJson("config_display_bookmarks.json");
|
||||
});
|
||||
|
||||
add_task(async function test_menu_shown() {
|
||||
// Since testing will apply the policy after the browser has already started,
|
||||
// we will need to open a new window to actually see the toolbar
|
||||
let newWin = await BrowserTestUtils.openNewBrowserWindow();
|
||||
let menuBar = newWin.document.getElementById("PersonalToolbar");
|
||||
is(menuBar.getAttribute("collapsed"), "false",
|
||||
"The bookmarks toolbar should not be hidden");
|
||||
|
||||
await BrowserTestUtils.closeWindow(newWin);
|
||||
});
|
@ -0,0 +1,19 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
add_task(async function setup() {
|
||||
await setupPolicyEngineWithJson("config_display_menu.json");
|
||||
});
|
||||
|
||||
add_task(async function test_menu_shown() {
|
||||
// Since testing will apply the policy after the browser has already started,
|
||||
// we will need to open a new window to actually see the menu bar
|
||||
let newWin = await BrowserTestUtils.openNewBrowserWindow();
|
||||
let menuBar = newWin.document.getElementById("toolbar-menubar");
|
||||
is(menuBar.getAttribute("autohide"), "false",
|
||||
"The menu bar should not be hidden");
|
||||
|
||||
await BrowserTestUtils.closeWindow(newWin);
|
||||
});
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"policies": {
|
||||
"display_bookmarks_toolbar": true
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"policies": {
|
||||
"display_menu_bar": true
|
||||
}
|
||||
}
|
@ -188,7 +188,7 @@ this.MigratorPrototype = {
|
||||
* OVERRIDE IF AND ONLY IF your migrator supports importing the homepage.
|
||||
* @see nsIBrowserProfileMigrator
|
||||
*/
|
||||
get sourceHomePageURL() {
|
||||
getSourceHomePageURL() {
|
||||
return "";
|
||||
},
|
||||
|
||||
|
@ -10,10 +10,6 @@ ac_add_options --enable-valgrind
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.asan
|
||||
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
export PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig
|
||||
fi
|
||||
|
||||
# Enable Telemetry
|
||||
export MOZ_TELEMETRY_REPORTING=1
|
||||
|
||||
|
@ -9,10 +9,6 @@ ac_add_options --enable-valgrind
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.asan
|
||||
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
export PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig
|
||||
fi
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
|
@ -10,10 +10,6 @@ ac_add_options --enable-valgrind
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.asan
|
||||
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
export PKG_CONFIG_LIBDIR=/usr/local/lib64/pkgconfig:/usr/lib64/pkgconfig:/usr/share/pkgconfig
|
||||
fi
|
||||
|
||||
# Enable Telemetry
|
||||
export MOZ_TELEMETRY_REPORTING=1
|
||||
|
||||
|
@ -19,8 +19,4 @@ ac_add_options --enable-mozsearch-plugin
|
||||
|
||||
. "$topsrcdir/build/unix/mozconfig.stdcxx"
|
||||
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
export PKG_CONFIG_LIBDIR=/usr/local/lib64/pkgconfig:/usr/lib64/pkgconfig:/usr/share/pkgconfig
|
||||
fi
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -18,8 +18,4 @@ ac_add_options --enable-clang-plugin
|
||||
|
||||
. "$topsrcdir/build/unix/mozconfig.stdcxx"
|
||||
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
export PKG_CONFIG_LIBDIR=/usr/local/lib64/pkgconfig:/usr/lib64/pkgconfig:/usr/share/pkgconfig
|
||||
fi
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -40,8 +40,4 @@ CFLAGS="$CFLAGS -Wno-attributes"
|
||||
CPPFLAGS="$CPPFLAGS -Wno-attributes"
|
||||
CXXFLAGS="$CXXFLAGS -Wno-attributes"
|
||||
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
export PKG_CONFIG_LIBDIR=/usr/local/lib64/pkgconfig:/usr/lib64/pkgconfig:/usr/share/pkgconfig
|
||||
fi
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -9,10 +9,6 @@ ac_add_options --enable-valgrind
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.asan
|
||||
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
export PKG_CONFIG_LIBDIR=/usr/local/lib64/pkgconfig:/usr/lib64/pkgconfig:/usr/share/pkgconfig
|
||||
fi
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
|
@ -11,10 +11,6 @@ ac_add_options --enable-valgrind
|
||||
|
||||
ac_add_options --enable-address-sanitizer-reporter
|
||||
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
export PKG_CONFIG_LIBDIR=/usr/local/lib64/pkgconfig:/usr/lib64/pkgconfig:/usr/share/pkgconfig
|
||||
fi
|
||||
|
||||
# Need this to prevent name conflicts with the normal nightly build packages
|
||||
export MOZ_PKG_SPECIAL=asan-reporter
|
||||
|
||||
|
@ -17,10 +17,6 @@ ac_add_options --enable-valgrind
|
||||
ac_add_options --enable-fuzzing
|
||||
unset MOZ_STDCXX_COMPAT
|
||||
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
export PKG_CONFIG_LIBDIR=/usr/local/lib64/pkgconfig:/usr/lib64/pkgconfig:/usr/share/pkgconfig
|
||||
fi
|
||||
|
||||
# Package js shell.
|
||||
export MOZ_PACKAGE_JSSHELL=1
|
||||
|
||||
|
@ -17,8 +17,4 @@ ac_add_options --enable-clang-plugin
|
||||
|
||||
. "$topsrcdir/build/unix/mozconfig.stdcxx"
|
||||
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
export PKG_CONFIG_LIBDIR=/usr/local/lib64/pkgconfig:/usr/lib64/pkgconfig:/usr/share/pkgconfig
|
||||
fi
|
||||
|
||||
. "$topsrcdir/build/mozconfig.common.override"
|
||||
|
@ -1,9 +1,5 @@
|
||||
. $topsrcdir/build/unix/mozconfig.tsan
|
||||
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
export PKG_CONFIG_LIBDIR=/usr/local/lib64/pkgconfig:/usr/lib64/pkgconfig:/usr/share/pkgconfig
|
||||
fi
|
||||
|
||||
# Need this to prevent name conflicts with the normal nightly build packages
|
||||
export MOZ_PKG_SPECIAL=tsan
|
||||
|
||||
|
@ -50,14 +50,11 @@ ac_add_options --disable-maintenance-service
|
||||
CC="$TOOLTOOL_DIR/mingw32/bin/i686-w64-mingw32-gcc"
|
||||
CXX="$TOOLTOOL_DIR/mingw32/bin/i686-w64-mingw32-g++"
|
||||
|
||||
HOST_CC="$TOOLTOOL_DIR/gcc/bin/gcc"
|
||||
HOST_CXX="$TOOLTOOL_DIR/gcc/bin/g++"
|
||||
|
||||
# We want to make sure we use binutils and other binaries in the tooltool
|
||||
# package.
|
||||
mk_add_options "export PATH=$TOOLTOOL_DIR/gcc/bin:$TOOLTOOL_DIR/mingw32/bin:$TOOLTOOL_DIR/wine/bin:$TOOLTOOL_DIR/upx/bin:$TOOLTOOL_DIR/fxc2/bin:$PATH"
|
||||
mk_add_options "export PATH=$TOOLTOOL_DIR/mingw32/bin:$TOOLTOOL_DIR/wine/bin:$TOOLTOOL_DIR/upx/bin:$TOOLTOOL_DIR/fxc2/bin:$PATH"
|
||||
|
||||
LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOOLTOOL_DIR/gcc/lib64:$TOOLTOOL_DIR/mingw32/lib64
|
||||
LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOOLTOOL_DIR/mingw32/lib64
|
||||
mk_add_options "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
|
||||
|
||||
# Do not include the visual studio related mozconfigs of course
|
||||
|
@ -598,6 +598,20 @@ var pktApi = (function() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get a user's pocket stories
|
||||
* @return {Boolean} Returns Boolean whether the api call started sucessfully
|
||||
*/
|
||||
function retrieve(data = {}, options = {}) {
|
||||
const requestData = Object.assign({}, data, {access_token: getAccessToken()});
|
||||
return apiRequest({
|
||||
path: "/get",
|
||||
data: requestData,
|
||||
success: options.success,
|
||||
error: options.error
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get current signup AB group the user is in
|
||||
*/
|
||||
@ -644,5 +658,6 @@ var pktApi = (function() {
|
||||
getSuggestedTagsForItem,
|
||||
getSuggestedTagsForURL,
|
||||
getSignupPanelTabTestVariant,
|
||||
retrieve,
|
||||
};
|
||||
}());
|
||||
|
@ -202,6 +202,7 @@ this.Bootstrap = {
|
||||
"lib/ShieldPreferences.jsm",
|
||||
"lib/ShieldRecipeClient.jsm",
|
||||
"lib/Storage.jsm",
|
||||
"lib/TelemetryEvents.jsm",
|
||||
"lib/Uptake.jsm",
|
||||
"lib/Utils.jsm",
|
||||
].map(m => `resource://shield-recipe-client/${m}`);
|
||||
|
@ -165,7 +165,7 @@ XPCOMUtils.defineLazyGetter(this.AboutPages, "aboutStudies", () => {
|
||||
this.sendStudyList(message.target);
|
||||
break;
|
||||
case "Shield:RemoveStudy":
|
||||
this.removeStudy(message.data);
|
||||
this.removeStudy(message.data.recipeId, message.data.reason);
|
||||
break;
|
||||
case "Shield:OpenDataPreferences":
|
||||
this.openDataPreferences();
|
||||
@ -195,8 +195,8 @@ XPCOMUtils.defineLazyGetter(this.AboutPages, "aboutStudies", () => {
|
||||
* Disable an active study and remove its add-on.
|
||||
* @param {String} studyName
|
||||
*/
|
||||
async removeStudy(recipeId) {
|
||||
await AddonStudies.stop(recipeId);
|
||||
async removeStudy(recipeId, reason) {
|
||||
await AddonStudies.stop(recipeId, reason);
|
||||
|
||||
// Update any open tabs with the new study list now that it has changed.
|
||||
Services.mm.broadcastAsyncMessage("Shield:ReceiveStudyList", {
|
||||
|
@ -109,7 +109,7 @@ class StudyListItem extends React.Component {
|
||||
}
|
||||
|
||||
handleClickRemove() {
|
||||
sendPageEvent("RemoveStudy", this.props.study.recipeId);
|
||||
sendPageEvent("RemoveStudy", {recipeId: this.props.study.recipeId, reason: "individual-opt-out"});
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -8,7 +8,7 @@
|
||||
<em:type>2</em:type>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
<em:unpack>false</em:unpack>
|
||||
<em:version>80</em:version>
|
||||
<em:version>83</em:version>
|
||||
<em:name>Shield Recipe Client</em:name>
|
||||
<em:description>Client to download and run recipes for SHIELD, Heartbeat, etc.</em:description>
|
||||
<em:multiprocessCompatible>true</em:multiprocessCompatible>
|
||||
|
@ -35,10 +35,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", "resource://gre/modules/Fil
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "IndexedDB", "resource://gre/modules/IndexedDB.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "Addons", "resource://shield-recipe-client/lib/Addons.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(
|
||||
this, "CleanupManager", "resource://shield-recipe-client/lib/CleanupManager.jsm"
|
||||
);
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "CleanupManager", "resource://shield-recipe-client/lib/CleanupManager.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "LogManager", "resource://shield-recipe-client/lib/LogManager.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TelemetryEvents", "resource://shield-recipe-client/lib/TelemetryEvents.jsm");
|
||||
|
||||
Cu.importGlobalProperties(["fetch"]); /* globals fetch */
|
||||
|
||||
@ -92,12 +91,23 @@ function getStore(db) {
|
||||
* Mark a study object as having ended. Modifies the study in-place.
|
||||
* @param {IDBDatabase} db
|
||||
* @param {Study} study
|
||||
* @param {String} reason Why the study is ending.
|
||||
*/
|
||||
async function markAsEnded(db, study) {
|
||||
async function markAsEnded(db, study, reason) {
|
||||
if (reason === "unknown") {
|
||||
log.warn(`Study ${study.name} ending for unknown reason.`);
|
||||
}
|
||||
|
||||
study.active = false;
|
||||
study.studyEndDate = new Date();
|
||||
await getStore(db).put(study);
|
||||
|
||||
Services.obs.notifyObservers(study, STUDY_ENDED_TOPIC, `${study.recipeId}`);
|
||||
TelemetryEvents.sendEvent("unenroll", "addon_study", study.name, {
|
||||
addonId: study.addonId,
|
||||
addonVersion: study.addonVersion,
|
||||
reason,
|
||||
});
|
||||
}
|
||||
|
||||
this.AddonStudies = {
|
||||
@ -145,7 +155,7 @@ this.AddonStudies = {
|
||||
for (const study of activeStudies) {
|
||||
const addon = await AddonManager.getAddonByID(study.addonId);
|
||||
if (!addon) {
|
||||
await markAsEnded(db, study);
|
||||
await markAsEnded(db, study, "uninstalled-sideload");
|
||||
}
|
||||
}
|
||||
await this.close();
|
||||
@ -168,7 +178,7 @@ this.AddonStudies = {
|
||||
// Use a dedicated DB connection instead of the shared one so that we can
|
||||
// close it without fear of affecting other users of the shared connection.
|
||||
const db = await openDatabase();
|
||||
await markAsEnded(db, matchingStudy);
|
||||
await markAsEnded(db, matchingStudy, "uninstalled");
|
||||
await db.close();
|
||||
}
|
||||
},
|
||||
@ -258,12 +268,24 @@ this.AddonStudies = {
|
||||
studyStartDate: new Date(),
|
||||
};
|
||||
|
||||
TelemetryEvents.sendEvent("enroll", "addon_study", name, {
|
||||
addonId: install.addon.id,
|
||||
addonVersion: install.addon.version,
|
||||
});
|
||||
|
||||
try {
|
||||
await getStore(db).add(study);
|
||||
await Addons.applyInstall(install, false);
|
||||
return study;
|
||||
} catch (err) {
|
||||
await getStore(db).delete(recipeId);
|
||||
|
||||
TelemetryEvents.sendEvent("unenroll", "addon_study", name, {
|
||||
reason: "install-failure",
|
||||
addonId: install.addon.id,
|
||||
addonVersion: install.addon.version,
|
||||
});
|
||||
|
||||
throw err;
|
||||
} finally {
|
||||
Services.obs.notifyObservers(addonFile, "flush-cache-entry");
|
||||
@ -300,21 +322,22 @@ this.AddonStudies = {
|
||||
/**
|
||||
* Stop an active study, uninstalling the associated add-on.
|
||||
* @param {Number} recipeId
|
||||
* @param {String} reason Why the study is ending. Optional, defaults to "unknown".
|
||||
* @throws
|
||||
* If no study is found with the given recipeId.
|
||||
* If the study is already inactive.
|
||||
*/
|
||||
async stop(recipeId) {
|
||||
async stop(recipeId, reason = "unknown") {
|
||||
const db = await getDatabase();
|
||||
const study = await getStore(db).get(recipeId);
|
||||
if (!study) {
|
||||
throw new Error(`No study found for recipe ${recipeId}`);
|
||||
throw new Error(`No study found for recipe ${recipeId}.`);
|
||||
}
|
||||
if (!study.active) {
|
||||
throw new Error(`Cannot stop study for recipe ${recipeId}; it is already inactive.`);
|
||||
}
|
||||
|
||||
await markAsEnded(db, study);
|
||||
await markAsEnded(db, study, reason);
|
||||
|
||||
try {
|
||||
await Addons.uninstall(study.addonId);
|
||||
|
@ -61,6 +61,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "JSONFile", "resource://gre/modules/JSON
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "LogManager", "resource://shield-recipe-client/lib/LogManager.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TelemetryEnvironment", "resource://gre/modules/TelemetryEnvironment.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TelemetryEvents", "resource://shield-recipe-client/lib/TelemetryEvents.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["PreferenceExperiments"];
|
||||
|
||||
@ -186,7 +187,10 @@ this.PreferenceExperiments = {
|
||||
if (getPref(UserPreferences, experiment.preferenceName, experiment.preferenceType) !== experiment.preferenceValue) {
|
||||
// if not, stop the experiment, and skip the remaining steps
|
||||
log.info(`Stopping experiment "${experiment.name}" because its value changed`);
|
||||
await this.stop(experiment.name, false);
|
||||
await this.stop(experiment.name, {
|
||||
didResetValue: false,
|
||||
reason: "user-preference-changed-sideload",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -351,6 +355,7 @@ this.PreferenceExperiments = {
|
||||
store.saveSoon();
|
||||
|
||||
TelemetryEnvironment.setExperimentActive(name, branch, {type: EXPERIMENT_TYPE_PREFIX + experimentType});
|
||||
TelemetryEvents.sendEvent("enroll", "preference_study", name, {experimentType, branch});
|
||||
await this.saveStartupPrefs();
|
||||
},
|
||||
|
||||
@ -377,8 +382,10 @@ this.PreferenceExperiments = {
|
||||
observer() {
|
||||
const newValue = getPref(UserPreferences, preferenceName, preferenceType);
|
||||
if (newValue !== preferenceValue) {
|
||||
PreferenceExperiments.stop(experimentName, false)
|
||||
.catch(Cu.reportError);
|
||||
PreferenceExperiments.stop(experimentName, {
|
||||
didResetValue: false,
|
||||
reason: "user-preference-changed",
|
||||
}).catch(Cu.reportError);
|
||||
}
|
||||
},
|
||||
};
|
||||
@ -448,14 +455,22 @@ this.PreferenceExperiments = {
|
||||
* Stop an active experiment, deactivate preference watchers, and optionally
|
||||
* reset the associated preference to its previous value.
|
||||
* @param {string} experimentName
|
||||
* @param {boolean} [resetValue=true]
|
||||
* If true, reset the preference to its original value.
|
||||
* @param {Object} options
|
||||
* @param {boolean} [options.resetValue = true]
|
||||
* If true, reset the preference to its original value prior to
|
||||
* the experiment. Optional, defauls to true.
|
||||
* @param {String} [options.reason = "unknown"]
|
||||
* Reason that the experiment is ending. Optional, defaults to
|
||||
* "unknown".
|
||||
* @rejects {Error}
|
||||
* If there is no stored experiment with the given name, or if the
|
||||
* experiment has already expired.
|
||||
*/
|
||||
async stop(experimentName, resetValue = true) {
|
||||
async stop(experimentName, {resetValue = true, reason = "unknown"} = {}) {
|
||||
log.debug(`PreferenceExperiments.stop(${experimentName})`);
|
||||
if (reason === "unknown") {
|
||||
log.warn(`experiment ${experimentName} ending for unknown reason`);
|
||||
}
|
||||
|
||||
const store = await ensureStorage();
|
||||
if (!(experimentName in store.data)) {
|
||||
@ -496,6 +511,10 @@ this.PreferenceExperiments = {
|
||||
store.saveSoon();
|
||||
|
||||
TelemetryEnvironment.setExperimentInactive(experimentName, experiment.branch);
|
||||
TelemetryEvents.sendEvent("unenroll", "preference_study", experimentName, {
|
||||
didResetValue: resetValue ? "true" : "false",
|
||||
reason,
|
||||
});
|
||||
await this.saveStartupPrefs();
|
||||
},
|
||||
|
||||
|
@ -73,22 +73,24 @@ this.ShieldPreferences = {
|
||||
let prefValue;
|
||||
switch (prefName) {
|
||||
// If the FHR pref changes, set the opt-out-study pref to the value it is changing to.
|
||||
case FHR_UPLOAD_ENABLED_PREF:
|
||||
case FHR_UPLOAD_ENABLED_PREF: {
|
||||
prefValue = Services.prefs.getBoolPref(FHR_UPLOAD_ENABLED_PREF);
|
||||
Services.prefs.setBoolPref(OPT_OUT_STUDIES_ENABLED_PREF, prefValue);
|
||||
break;
|
||||
}
|
||||
|
||||
// If the opt-out pref changes to be false, disable all current studies.
|
||||
case OPT_OUT_STUDIES_ENABLED_PREF:
|
||||
case OPT_OUT_STUDIES_ENABLED_PREF: {
|
||||
prefValue = Services.prefs.getBoolPref(OPT_OUT_STUDIES_ENABLED_PREF);
|
||||
if (!prefValue) {
|
||||
for (const study of await AddonStudies.getAll()) {
|
||||
if (study.active) {
|
||||
await AddonStudies.stop(study.recipeId);
|
||||
await AddonStudies.stop(study.recipeId, "general-opt-out");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -22,22 +22,11 @@ XPCOMUtils.defineLazyModuleGetter(this, "ShieldPreferences",
|
||||
"resource://shield-recipe-client/lib/ShieldPreferences.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "AddonStudies",
|
||||
"resource://shield-recipe-client/lib/AddonStudies.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TelemetryEvents",
|
||||
"resource://shield-recipe-client/lib/TelemetryEvents.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["ShieldRecipeClient"];
|
||||
|
||||
const {PREF_STRING, PREF_BOOL, PREF_INT} = Ci.nsIPrefBranch;
|
||||
|
||||
const REASONS = {
|
||||
APP_STARTUP: 1, // The application is starting up.
|
||||
APP_SHUTDOWN: 2, // The application is shutting down.
|
||||
ADDON_ENABLE: 3, // The add-on is being enabled.
|
||||
ADDON_DISABLE: 4, // The add-on is being disabled. (Also sent during uninstallation)
|
||||
ADDON_INSTALL: 5, // The add-on is being installed.
|
||||
ADDON_UNINSTALL: 6, // The add-on is being uninstalled.
|
||||
ADDON_UPGRADE: 7, // The add-on is being upgraded.
|
||||
ADDON_DOWNGRADE: 8, // The add-on is being downgraded.
|
||||
};
|
||||
const PREF_DEV_MODE = "extensions.shield-recipe-client.dev_mode";
|
||||
const PREF_LOGGING_LEVEL = "extensions.shield-recipe-client.logging.level";
|
||||
const SHIELD_INIT_NOTIFICATION = "shield-init-complete";
|
||||
|
||||
@ -82,6 +71,12 @@ this.ShieldRecipeClient = {
|
||||
log.error("Failed to initialize preferences UI:", err);
|
||||
}
|
||||
|
||||
try {
|
||||
TelemetryEvents.init();
|
||||
} catch (err) {
|
||||
log.error("Failed to initialize telemetry events:", err);
|
||||
}
|
||||
|
||||
await RecipeRunner.init();
|
||||
Services.obs.notifyObservers(null, SHIELD_INIT_NOTIFICATION);
|
||||
},
|
||||
|
@ -0,0 +1,36 @@
|
||||
/* 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 {utils: Cu, interfaces: Ci} = Components;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["TelemetryEvents"];
|
||||
|
||||
const TELEMETRY_CATEGORY = "normandy";
|
||||
|
||||
const TelemetryEvents = {
|
||||
init() {
|
||||
Services.telemetry.registerEvents(TELEMETRY_CATEGORY, {
|
||||
enroll: {
|
||||
methods: ["enroll"],
|
||||
objects: ["preference_study", "addon_study"],
|
||||
extra_keys: ["experimentType", "branch", "addonId", "addonVersion"],
|
||||
record_on_release: true,
|
||||
},
|
||||
|
||||
unenroll: {
|
||||
methods: ["unenroll"],
|
||||
objects: ["preference_study", "addon_study"],
|
||||
extra_keys: ["reason", "didResetValue", "addonId", "addonVersion"],
|
||||
record_on_release: true,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
sendEvent(method, object, value, extra) {
|
||||
Services.telemetry.recordEvent(TELEMETRY_CATEGORY, method, object, value, extra);
|
||||
},
|
||||
};
|
@ -5,6 +5,7 @@ Cu.import("resource://testing-common/TestUtils.jsm", this);
|
||||
Cu.import("resource://testing-common/AddonTestUtils.jsm", this);
|
||||
Cu.import("resource://shield-recipe-client/lib/Addons.jsm", this);
|
||||
Cu.import("resource://shield-recipe-client/lib/AddonStudies.jsm", this);
|
||||
Cu.import("resource://shield-recipe-client/lib/TelemetryEvents.jsm", this);
|
||||
|
||||
// Initialize test utils
|
||||
AddonTestUtils.initMochitest(this);
|
||||
@ -175,8 +176,9 @@ decorate_task(
|
||||
|
||||
decorate_task(
|
||||
withWebExtension({version: "2.0"}),
|
||||
withStub(TelemetryEvents, "sendEvent"),
|
||||
AddonStudies.withStudies(),
|
||||
async function testStart([addonId, addonFile]) {
|
||||
async function testStart([addonId, addonFile], sendEventStub) {
|
||||
const startupPromise = AddonTestUtils.promiseWebExtensionStartup(addonId);
|
||||
const addonUrl = Services.io.newFileURI(addonFile).spec;
|
||||
|
||||
@ -211,6 +213,12 @@ decorate_task(
|
||||
);
|
||||
ok(study.studyStartDate, "start assigns a value to the study start date.");
|
||||
|
||||
Assert.deepEqual(
|
||||
sendEventStub.getCall(0).args,
|
||||
["enroll", "addon_study", args.name, {addonId, addonVersion: "2.0"}],
|
||||
"AddonStudies.start() should send the correct telemetry event"
|
||||
);
|
||||
|
||||
await AddonStudies.stop(args.recipeId);
|
||||
}
|
||||
);
|
||||
@ -245,14 +253,25 @@ decorate_task(
|
||||
studyFactory({active: true, addonId: testStopId, studyEndDate: null}),
|
||||
]),
|
||||
withInstalledWebExtension({id: testStopId}),
|
||||
async function testStop([study], [addonId, addonFile]) {
|
||||
await AddonStudies.stop(study.recipeId);
|
||||
withStub(TelemetryEvents, "sendEvent"),
|
||||
async function testStop([study], [addonId, addonFile], sendEventStub) {
|
||||
await AddonStudies.stop(study.recipeId, "test-reason");
|
||||
const newStudy = await AddonStudies.get(study.recipeId);
|
||||
ok(!newStudy.active, "stop marks the study as inactive.");
|
||||
ok(newStudy.studyEndDate, "stop saves the study end date.");
|
||||
|
||||
const addon = await Addons.get(addonId);
|
||||
is(addon, null, "stop uninstalls the study add-on.");
|
||||
|
||||
Assert.deepEqual(
|
||||
sendEventStub.getCall(0).args,
|
||||
["unenroll", "addon_study", study.name, {
|
||||
addonId,
|
||||
addonVersion: study.addonVersion,
|
||||
reason: "test-reason",
|
||||
}],
|
||||
"stop should send the correct telemetry event"
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@ -280,16 +299,26 @@ decorate_task(
|
||||
studyFactory({active: true, addonId: "installed@example.com"}),
|
||||
studyFactory({active: false, addonId: "already.gone@example.com", studyEndDate: new Date(2012, 1)}),
|
||||
]),
|
||||
withStub(TelemetryEvents, "sendEvent"),
|
||||
withInstalledWebExtension({id: "installed@example.com"}),
|
||||
async function testInit([activeStudy, activeInstalledStudy, inactiveStudy]) {
|
||||
async function testInit([activeUninstalledStudy, activeInstalledStudy, inactiveStudy], sendEventStub) {
|
||||
await AddonStudies.init();
|
||||
|
||||
const newActiveStudy = await AddonStudies.get(activeStudy.recipeId);
|
||||
const newActiveStudy = await AddonStudies.get(activeUninstalledStudy.recipeId);
|
||||
ok(!newActiveStudy.active, "init marks studies as inactive if their add-on is not installed.");
|
||||
ok(
|
||||
newActiveStudy.studyEndDate,
|
||||
"init sets the study end date if a study's add-on is not installed."
|
||||
);
|
||||
Assert.deepEqual(
|
||||
sendEventStub.getCall(0).args,
|
||||
["unenroll", "addon_study", activeUninstalledStudy.name, {
|
||||
addonId: activeUninstalledStudy.addonId,
|
||||
addonVersion: activeUninstalledStudy.addonVersion,
|
||||
reason: "uninstalled-sideload",
|
||||
}],
|
||||
"AddonStudies.init() should send the correct telemetry event"
|
||||
);
|
||||
|
||||
const newInactiveStudy = await AddonStudies.get(inactiveStudy.recipeId);
|
||||
is(
|
||||
@ -304,6 +333,9 @@ decorate_task(
|
||||
newActiveInstalledStudy,
|
||||
"init does not modify studies whose add-on is still installed."
|
||||
);
|
||||
|
||||
// Only activeUninstalledStudy should have generated any events
|
||||
ok(sendEventStub.calledOnce);
|
||||
}
|
||||
);
|
||||
|
||||
@ -324,3 +356,18 @@ decorate_task(
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
// stop should pass "unknown" to TelemetryEvents for `reason` if none specified
|
||||
decorate_task(
|
||||
AddonStudies.withStudies([studyFactory({ active: true })]),
|
||||
withStub(TelemetryEvents, "sendEvent"),
|
||||
async function testStopUnknownReason([study], sendEventStub) {
|
||||
await AddonStudies.stop(study.recipeId);
|
||||
is(
|
||||
sendEventStub.getCall(0).args[3].reason,
|
||||
"unknown",
|
||||
"stop should send the correct telemetry event",
|
||||
"AddonStudies.stop() should use unknown as the default reason",
|
||||
);
|
||||
}
|
||||
);
|
||||
|
@ -4,6 +4,7 @@ Cu.import("resource://gre/modules/Preferences.jsm", this);
|
||||
Cu.import("resource://gre/modules/TelemetryEnvironment.jsm", this);
|
||||
Cu.import("resource://shield-recipe-client/lib/PreferenceExperiments.jsm", this);
|
||||
Cu.import("resource://shield-recipe-client/lib/CleanupManager.jsm", this);
|
||||
Cu.import("resource://shield-recipe-client/lib/TelemetryEvents.jsm", this);
|
||||
|
||||
// Save ourselves some typing
|
||||
const {withMockExperiments} = PreferenceExperiments;
|
||||
@ -101,7 +102,8 @@ decorate_task(
|
||||
withMockExperiments,
|
||||
withMockPreferences,
|
||||
withStub(PreferenceExperiments, "startObserver"),
|
||||
async function testStart(experiments, mockPreferences, startObserverStub) {
|
||||
withStub(TelemetryEvents, "sendEvent"),
|
||||
async function testStart(experiments, mockPreferences, startObserverStub, sendEventStub) {
|
||||
mockPreferences.set("fake.preference", "oldvalue", "default");
|
||||
mockPreferences.set("fake.preference", "uservalue", "user");
|
||||
|
||||
@ -407,8 +409,12 @@ decorate_task(
|
||||
withMockExperiments,
|
||||
withMockPreferences,
|
||||
withSpy(PreferenceExperiments, "stopObserver"),
|
||||
async function testStop(experiments, mockPreferences, stopObserverSpy) {
|
||||
withStub(TelemetryEvents, "sendEvent"),
|
||||
async function testStop(experiments, mockPreferences, stopObserverSpy, sendEventStub) {
|
||||
// this assertion is mostly useful for --verify test runs, to make
|
||||
// sure that tests clean up correctly.
|
||||
is(Preferences.get("fake.preference"), null, "preference should start unset");
|
||||
|
||||
mockPreferences.set(`${startupPrefs}.fake.preference`, "experimentvalue", "user");
|
||||
mockPreferences.set("fake.preference", "experimentvalue", "default");
|
||||
experiments.test = experimentFactory({
|
||||
@ -422,7 +428,7 @@ decorate_task(
|
||||
});
|
||||
PreferenceExperiments.startObserver("test", "fake.preference", "string", "experimentvalue");
|
||||
|
||||
await PreferenceExperiments.stop("test");
|
||||
await PreferenceExperiments.stop("test", {reason: "test-reason"});
|
||||
ok(stopObserverSpy.calledWith("test"), "stop removed an observer");
|
||||
is(experiments.test.expired, true, "stop marked the experiment as expired");
|
||||
is(
|
||||
@ -435,6 +441,15 @@ decorate_task(
|
||||
"stop cleared the startup preference for fake.preference.",
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
sendEventStub.getCall(0).args,
|
||||
["unenroll", "preference_study", experiments.test.name, {
|
||||
didResetValue: "true",
|
||||
reason: "test-reason",
|
||||
}],
|
||||
"stop should send the correct telemetry event"
|
||||
);
|
||||
|
||||
PreferenceExperiments.stopAllObservers();
|
||||
},
|
||||
);
|
||||
@ -505,8 +520,8 @@ decorate_task(
|
||||
withMockExperiments,
|
||||
withMockPreferences,
|
||||
withStub(PreferenceExperiments, "stopObserver"),
|
||||
|
||||
async function(experiments, mockPreferences, stopObserver) {
|
||||
withStub(TelemetryEvents, "sendEvent"),
|
||||
async function testStopReset(experiments, mockPreferences, stopObserverStub, sendEventStub) {
|
||||
mockPreferences.set("fake.preference", "customvalue", "default");
|
||||
experiments.test = experimentFactory({
|
||||
name: "test",
|
||||
@ -518,12 +533,20 @@ decorate_task(
|
||||
peferenceBranchType: "default",
|
||||
});
|
||||
|
||||
await PreferenceExperiments.stop("test", false);
|
||||
await PreferenceExperiments.stop("test", {reason: "test-reason", resetValue: false});
|
||||
is(
|
||||
DefaultPreferences.get("fake.preference"),
|
||||
"customvalue",
|
||||
"stop did not modify the preference",
|
||||
);
|
||||
Assert.deepEqual(
|
||||
sendEventStub.getCall(0).args,
|
||||
["unenroll", "preference_study", experiments.test.name, {
|
||||
didResetValue: "false",
|
||||
reason: "test-reason",
|
||||
}],
|
||||
"stop should send the correct telemetry event"
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@ -678,7 +701,8 @@ decorate_task(
|
||||
withMockExperiments,
|
||||
withStub(TelemetryEnvironment, "setExperimentActive"),
|
||||
withStub(TelemetryEnvironment, "setExperimentInactive"),
|
||||
async function testInitTelemetry(experiments, setActiveStub, setInactiveStub) {
|
||||
withStub(TelemetryEvents, "sendEvent"),
|
||||
async function testStartAndStopTelemetry(experiments, setActiveStub, setInactiveStub, sendEventStub) {
|
||||
await PreferenceExperiments.start({
|
||||
name: "test",
|
||||
branch: "branch",
|
||||
@ -691,10 +715,28 @@ decorate_task(
|
||||
Assert.deepEqual(
|
||||
setActiveStub.getCall(0).args,
|
||||
["test", "branch", {type: "normandy-exp"}],
|
||||
"Experiment is registerd by start()",
|
||||
"Experiment is registered by start()",
|
||||
);
|
||||
await PreferenceExperiments.stop("test");
|
||||
await PreferenceExperiments.stop("test", {reason: "test-reason"});
|
||||
ok(setInactiveStub.calledWith("test", "branch"), "Experiment is unregistered by stop()");
|
||||
|
||||
Assert.deepEqual(
|
||||
sendEventStub.getCall(0).args,
|
||||
["enroll", "preference_study", "test", {
|
||||
experimentType: "exp",
|
||||
branch: "branch",
|
||||
}],
|
||||
"PreferenceExperiments.start() should send the correct telemetry event"
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
sendEventStub.getCall(1).args,
|
||||
["unenroll", "preference_study", "test", {
|
||||
reason: "test-reason",
|
||||
didResetValue: "true",
|
||||
}],
|
||||
"PreferenceExperiments.stop() should send the correct telemetry event"
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@ -703,7 +745,8 @@ decorate_task(
|
||||
withMockExperiments,
|
||||
withStub(TelemetryEnvironment, "setExperimentActive"),
|
||||
withStub(TelemetryEnvironment, "setExperimentInactive"),
|
||||
async function testInitTelemetry(experiments, setActiveStub, setInactiveStub) {
|
||||
withStub(TelemetryEvents, "sendEvent"),
|
||||
async function testInitTelemetryExperimentType(experiments, setActiveStub, setInactiveStub, sendEventStub) {
|
||||
await PreferenceExperiments.start({
|
||||
name: "test",
|
||||
branch: "branch",
|
||||
@ -720,6 +763,15 @@ decorate_task(
|
||||
"start() should register the experiment with the provided type",
|
||||
);
|
||||
|
||||
Assert.deepEqual(
|
||||
sendEventStub.getCall(0).args,
|
||||
["enroll", "preference_study", "test", {
|
||||
experimentType: "pref-test",
|
||||
branch: "branch",
|
||||
}],
|
||||
"start should include the passed reason in the telemetry event"
|
||||
);
|
||||
|
||||
// start sets the passed preference in a way that is hard to mock.
|
||||
// Reset the preference so it doesn't interfere with other tests.
|
||||
Services.prefs.getDefaultBranch("fake.preference").deleteBranch("");
|
||||
@ -742,7 +794,8 @@ decorate_task(
|
||||
withMockExperiments,
|
||||
withMockPreferences,
|
||||
withStub(PreferenceExperiments, "stop"),
|
||||
async function testInitChanges(experiments, mockPreferences, stopStub) {
|
||||
withStub(TelemetryEvents, "sendEvent"),
|
||||
async function testInitChanges(experiments, mockPreferences, stopStub, sendEventStub) {
|
||||
mockPreferences.set("fake.preference", "experiment value", "default");
|
||||
experiments.test = experimentFactory({
|
||||
name: "test",
|
||||
@ -753,7 +806,7 @@ decorate_task(
|
||||
await PreferenceExperiments.init();
|
||||
ok(stopStub.calledWith("test"), "Experiment is stopped because value changed");
|
||||
is(Preferences.get("fake.preference"), "changed value", "Preference value was not changed");
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// init should register an observer for experiments
|
||||
@ -935,3 +988,21 @@ decorate_task(
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
// stop should pass "unknown" to telemetry event for `reason` if none is specified
|
||||
decorate_task(
|
||||
withMockExperiments,
|
||||
withMockPreferences,
|
||||
withStub(PreferenceExperiments, "stopObserver"),
|
||||
withStub(TelemetryEvents, "sendEvent"),
|
||||
async function testStopUnknownReason(experiments, mockPreferences, stopObserverStub, sendEventStub) {
|
||||
mockPreferences.set("fake.preference", "default value", "default");
|
||||
experiments.test = experimentFactory({ name: "test", preferenceName: "fake.preference" });
|
||||
await PreferenceExperiments.stop("test");
|
||||
is(
|
||||
sendEventStub.getCall(0).args[3].reason,
|
||||
"unknown",
|
||||
"PreferenceExperiments.stop() should use unknown as the default reason",
|
||||
);
|
||||
}
|
||||
);
|
||||
|
@ -5,6 +5,7 @@ Cu.import("resource://shield-recipe-client/lib/RecipeRunner.jsm", this);
|
||||
Cu.import("resource://shield-recipe-client/lib/PreferenceExperiments.jsm", this);
|
||||
Cu.import("resource://shield-recipe-client-content/AboutPages.jsm", this);
|
||||
Cu.import("resource://shield-recipe-client/lib/AddonStudies.jsm", this);
|
||||
Cu.import("resource://shield-recipe-client/lib/TelemetryEvents.jsm", this);
|
||||
|
||||
function withStubInits(testFunction) {
|
||||
return decorate(
|
||||
@ -12,6 +13,7 @@ function withStubInits(testFunction) {
|
||||
withStub(AddonStudies, "init"),
|
||||
withStub(PreferenceExperiments, "init"),
|
||||
withStub(RecipeRunner, "init"),
|
||||
withStub(TelemetryEvents, "init"),
|
||||
testFunction
|
||||
);
|
||||
}
|
||||
@ -39,6 +41,7 @@ decorate_task(
|
||||
ok(AddonStudies.init.called, "startup calls AddonStudies.init");
|
||||
ok(PreferenceExperiments.init.called, "startup calls PreferenceExperiments.init");
|
||||
ok(RecipeRunner.init.called, "startup calls RecipeRunner.init");
|
||||
ok(TelemetryEvents.init.called, "startup calls TelemetryEvents.init");
|
||||
}
|
||||
);
|
||||
|
||||
@ -52,6 +55,7 @@ decorate_task(
|
||||
ok(AddonStudies.init.called, "startup calls AddonStudies.init");
|
||||
ok(PreferenceExperiments.init.called, "startup calls PreferenceExperiments.init");
|
||||
ok(RecipeRunner.init.called, "startup calls RecipeRunner.init");
|
||||
ok(TelemetryEvents.init.called, "startup calls TelemetryEvents.init");
|
||||
}
|
||||
);
|
||||
|
||||
@ -65,5 +69,20 @@ decorate_task(
|
||||
ok(AddonStudies.init.called, "startup calls AddonStudies.init");
|
||||
ok(PreferenceExperiments.init.called, "startup calls PreferenceExperiments.init");
|
||||
ok(RecipeRunner.init.called, "startup calls RecipeRunner.init");
|
||||
ok(TelemetryEvents.init.called, "startup calls TelemetryEvents.init");
|
||||
}
|
||||
);
|
||||
|
||||
decorate_task(
|
||||
withStubInits,
|
||||
async function testStartupTelemetryEventsInitFail() {
|
||||
TelemetryEvents.init.throws();
|
||||
|
||||
await ShieldRecipeClient.startup();
|
||||
ok(AboutPages.init.called, "startup calls AboutPages.init");
|
||||
ok(AddonStudies.init.called, "startup calls AddonStudies.init");
|
||||
ok(PreferenceExperiments.init.called, "startup calls PreferenceExperiments.init");
|
||||
ok(RecipeRunner.init.called, "startup calls RecipeRunner.init");
|
||||
ok(TelemetryEvents.init.called, "startup calls TelemetryEvents.init");
|
||||
}
|
||||
);
|
||||
|
@ -8,6 +8,7 @@ Cu.import("resource://shield-recipe-client/lib/Addons.jsm", this);
|
||||
Cu.import("resource://shield-recipe-client/lib/SandboxManager.jsm", this);
|
||||
Cu.import("resource://shield-recipe-client/lib/NormandyDriver.jsm", this);
|
||||
Cu.import("resource://shield-recipe-client/lib/NormandyApi.jsm", this);
|
||||
Cu.import("resource://shield-recipe-client/lib/TelemetryEvents.jsm", this);
|
||||
Cu.import("resource://shield-recipe-client/lib/Utils.jsm", this);
|
||||
|
||||
// Load mocking/stubbing library, sinon
|
||||
@ -25,6 +26,8 @@ registerCleanupFunction(async function() {
|
||||
delete window.sinon;
|
||||
});
|
||||
|
||||
// Prep Telemetry to receive events from tests
|
||||
TelemetryEvents.init();
|
||||
|
||||
this.UUID_REGEX = /[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/;
|
||||
|
||||
|
@ -1,35 +1,24 @@
|
||||
fbjs@0.8.14 BSD-3-Clause
|
||||
BSD License
|
||||
|
||||
For fbjs software
|
||||
fbjs@0.8.16 MIT
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2013-present, Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name Facebook nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
react-dom@15.6.1 BSD-3-Clause
|
||||
@ -157,38 +146,28 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
create-react-class@15.6.0 BSD-3-Clause
|
||||
BSD License
|
||||
|
||||
For React software
|
||||
create-react-class@15.6.2 MIT
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2013-present, Facebook, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name Facebook nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
mozjexl@1.1.5 MIT
|
||||
|
@ -29,7 +29,7 @@ void CanRunScriptChecker::registerMatchers(MatchFinder *AstMatcher) {
|
||||
// This makes this matcher optional.
|
||||
anything());
|
||||
|
||||
// Please not that the hasCanRunScriptAnnotation() matchers are not present
|
||||
// Please note that the hasCanRunScriptAnnotation() matchers are not present
|
||||
// directly in the cxxMemberCallExpr, callExpr and constructExpr matchers
|
||||
// because we check that the corresponding functions can run script later in
|
||||
// the checker code.
|
||||
@ -93,8 +93,14 @@ private:
|
||||
};
|
||||
|
||||
void FuncSetCallback::run(const MatchFinder::MatchResult &Result) {
|
||||
const FunctionDecl *Func =
|
||||
Result.Nodes.getNodeAs<FunctionDecl>("canRunScriptFunction");
|
||||
const FunctionDecl *Func;
|
||||
if (auto *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda")) {
|
||||
Func = Lambda->getCallOperator();
|
||||
if (!Func || !hasCustomAnnotation(Func, "moz_can_run_script"))
|
||||
return;
|
||||
} else {
|
||||
Func = Result.Nodes.getNodeAs<FunctionDecl>("canRunScriptFunction");
|
||||
}
|
||||
|
||||
CanRunScriptFuncs.insert(Func);
|
||||
|
||||
@ -132,7 +138,9 @@ void CanRunScriptChecker::buildFuncSet(ASTContext *Context) {
|
||||
Finder.addMatcher(
|
||||
functionDecl(hasCanRunScriptAnnotation()).bind("canRunScriptFunction"),
|
||||
&Callback);
|
||||
|
||||
Finder.addMatcher(
|
||||
lambdaExpr().bind("lambda"),
|
||||
&Callback);
|
||||
// We start the analysis, given the ASTContext our main checker is in.
|
||||
Finder.matchAST(*Context);
|
||||
}
|
||||
@ -214,6 +222,9 @@ void CanRunScriptChecker::check(const MatchFinder::MatchResult &Result) {
|
||||
// If the parent function is not marked as MOZ_CAN_RUN_SCRIPT, we emit an
|
||||
// error and a not indicating it.
|
||||
if (ParentFunction) {
|
||||
assert(!hasCustomAnnotation(ParentFunction, "moz_can_run_script") &&
|
||||
"Matcher missed something");
|
||||
|
||||
diag(CallRange.getBegin(), ErrorNonCanRunScriptParent, DiagnosticIDs::Error)
|
||||
<< CallRange;
|
||||
|
||||
|
@ -37,6 +37,19 @@ struct RefCountedBase {
|
||||
}
|
||||
};
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT void testLambda() {
|
||||
auto doIt = []() MOZ_CAN_RUN_SCRIPT {
|
||||
test();
|
||||
};
|
||||
|
||||
auto doItWrong = []() { // expected-note {{parent function declared here}}
|
||||
test(); // expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT can only be called from functions also marked as MOZ_CAN_RUN_SCRIPT}}
|
||||
};
|
||||
|
||||
doIt();
|
||||
doItWrong();
|
||||
}
|
||||
|
||||
void test2_parent() { // expected-note {{parent function declared here}}
|
||||
test2(new RefCountedBase); // expected-error {{arguments must all be strong refs or parent parameters when calling a function marked as MOZ_CAN_RUN_SCRIPT (including the implicit object argument)}} \
|
||||
// expected-error {{functions marked as MOZ_CAN_RUN_SCRIPT can only be called from functions also marked as MOZ_CAN_RUN_SCRIPT}}
|
||||
|
@ -114,8 +114,8 @@ OBJDIR_FILES += ['/.ycm_extra_conf.py']
|
||||
if CONFIG['MOZ_VALGRIND']:
|
||||
OBJDIR_FILES._valgrind += [
|
||||
'valgrind/cross-architecture.sup',
|
||||
'valgrind/i386-redhat-linux-gnu.sup',
|
||||
'valgrind/x86_64-redhat-linux-gnu.sup',
|
||||
'valgrind/i386-pc-linux-gnu.sup',
|
||||
'valgrind/x86_64-pc-linux-gnu.sup',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_ARTIFACT_BUILDS']:
|
||||
|
@ -4,8 +4,6 @@
|
||||
path:taskcluster/
|
||||
|
||||
# Result from `grep -hr %include taskcluster/docker | grep -v " taskcluster/" | sort -u`
|
||||
path:build/unix/build-gtk3/build-gtk3.sh
|
||||
path:build/valgrind/valgrind-epochs.patch
|
||||
path:python/mozbuild/mozbuild/action/tooltool.py
|
||||
path:testing/config/tooltool-manifests/linux64/releng.manifest
|
||||
path:testing/mozharness/external_tools/robustcheckout.py
|
||||
|
@ -119,27 +119,6 @@ build_gcc() {
|
||||
cd $root_dir/tools
|
||||
ln -s gcc gcc/bin/cc
|
||||
|
||||
if [ -f /etc/debian_version ]; then
|
||||
cp -v /usr/lib32/crt*.o /usr/lib32/lib*_nonshared.a gcc/lib32
|
||||
cp -v /usr/lib/x86_64-linux-gnu/crt*.o /usr/lib/x86_64-linux-gnu/lib*_nonshared.a gcc/lib64
|
||||
cat > gcc/lib32/libc.so <<-EOF
|
||||
OUTPUT_FORMAT(elf32-i386)
|
||||
GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux.so.2 ) )
|
||||
EOF
|
||||
cat > gcc/lib32/libpthread.so <<-EOF
|
||||
OUTPUT_FORMAT(elf32-i386)
|
||||
GROUP ( libpthread.so.0 libpthread_nonshared.a )
|
||||
EOF
|
||||
cat > gcc/lib64/libc.so <<-EOF
|
||||
OUTPUT_FORMAT(elf64-x86-64)
|
||||
GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux-x86-64.so.2 ) )
|
||||
EOF
|
||||
cat > gcc/lib64/libpthread.so <<-EOF
|
||||
OUTPUT_FORMAT(elf64-x86-64)
|
||||
GROUP ( libpthread.so.0 libpthread_nonshared.a )
|
||||
EOF
|
||||
fi
|
||||
|
||||
tar caf $root_dir/gcc.tar.xz gcc/
|
||||
popd
|
||||
}
|
||||
|
@ -1,88 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
fontconfig_version=2.8.0
|
||||
libffi_version=3.0.13
|
||||
glib_version=2.34.3
|
||||
gdk_pixbuf_version=2.26.5
|
||||
pixman_version=0.20.2
|
||||
cairo_version=1.10.2
|
||||
pango_version=1.30.1
|
||||
atk_version=2.2.0
|
||||
gtk__version=3.4.4
|
||||
pulseaudio_version=2.0
|
||||
|
||||
fontconfig_url=http://www.freedesktop.org/software/fontconfig/release/fontconfig-${fontconfig_version}.tar.gz
|
||||
libffi_url=ftp://sourceware.org/pub/libffi/libffi-${libffi_version}.tar.gz
|
||||
glib_url=http://ftp.gnome.org/pub/gnome/sources/glib/${glib_version%.*}/glib-${glib_version}.tar.xz
|
||||
gdk_pixbuf_url=http://ftp.gnome.org/pub/gnome/sources/gdk-pixbuf/${gdk_pixbuf_version%.*}/gdk-pixbuf-${gdk_pixbuf_version}.tar.xz
|
||||
pixman_url=http://cairographics.org/releases/pixman-${pixman_version}.tar.gz
|
||||
cairo_url=http://cairographics.org/releases/cairo-${cairo_version}.tar.gz
|
||||
pango_url=http://ftp.gnome.org/pub/GNOME/sources/pango/${pango_version%.*}/pango-${pango_version}.tar.xz
|
||||
atk_url=http://ftp.gnome.org/pub/GNOME/sources/atk/${atk_version%.*}/atk-${atk_version}.tar.xz
|
||||
gtk__url=http://ftp.gnome.org/pub/gnome/sources/gtk+/${gtk__version%.*}/gtk+-${gtk__version}.tar.xz
|
||||
pulseaudio_url=https://freedesktop.org/software/pulseaudio/releases/pulseaudio-${pulseaudio_version}.tar.xz
|
||||
|
||||
root_dir=$(mktemp -d)
|
||||
cd $root_dir
|
||||
|
||||
make_flags=-j$(nproc)
|
||||
|
||||
# Install a few packages for pulseaudio.
|
||||
yum install -y libtool-ltdl-devel libtool-ltdl-devel.i686 json-c-devel json-c-devel.i686 libsndfile-devel libsndfile-devel.i686
|
||||
|
||||
build() {
|
||||
name=$1
|
||||
shift
|
||||
pkg=$(echo $name | tr '+-' '__')
|
||||
version=$(eval echo \$${pkg}_version)
|
||||
url=$(eval echo \$${pkg}_url)
|
||||
wget -c --progress=dot:mega -P $root_dir $url
|
||||
tar -axf $root_dir/$name-$version.tar.*
|
||||
mkdir -p build/$name
|
||||
cd build/$name
|
||||
eval ../../$name-$version/configure --disable-static $* $configure_args --libdir=/usr/local/$lib
|
||||
make $make_flags
|
||||
make install
|
||||
find /usr/local/$lib -name \*.la -delete
|
||||
cd ../..
|
||||
}
|
||||
|
||||
for bits in 32 64; do
|
||||
|
||||
rm -rf $root_dir/build
|
||||
|
||||
case "$bits" in
|
||||
32)
|
||||
configure_args='--host=i686-pc-linux --build=i686-pc-linux CC="gcc -m32" CXX="g++ -m32"'
|
||||
lib=lib
|
||||
;;
|
||||
*)
|
||||
configure_args=
|
||||
lib=lib64
|
||||
;;
|
||||
esac
|
||||
|
||||
export PKG_CONFIG_LIBDIR=/usr/local/$lib/pkgconfig:/usr/$lib/pkgconfig:/usr/share/pkgconfig
|
||||
export LD_LIBRARY_PATH=/usr/local/$lib
|
||||
|
||||
build fontconfig
|
||||
build libffi
|
||||
build glib
|
||||
build gdk-pixbuf --without-libtiff --without-libjpeg
|
||||
build pixman --disable-gtk
|
||||
build cairo --enable-tee
|
||||
build pango
|
||||
build atk
|
||||
make_flags="$make_flags GLIB_COMPILE_SCHEMAS=glib-compile-schemas"
|
||||
build gtk+
|
||||
build pulseaudio --disable-nls
|
||||
|
||||
done
|
||||
|
||||
rm -rf $root_dir
|
||||
|
||||
echo /usr/local/lib > /etc/ld.so.conf.d/local.conf
|
||||
echo /usr/local/lib64 >> /etc/ld.so.conf.d/local.conf
|
||||
ldconfig
|
@ -25,8 +25,3 @@ else
|
||||
fi
|
||||
|
||||
. "$topsrcdir/build/unix/mozconfig.stdcxx"
|
||||
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
# PKG_CONFIG_LIBDIR is appropriately overridden in mozconfig.linux32
|
||||
export PKG_CONFIG_LIBDIR=/usr/local/lib64/pkgconfig:/usr/lib64/pkgconfig:/usr/share/pkgconfig
|
||||
fi
|
||||
|
@ -1,9 +1,5 @@
|
||||
. "$topsrcdir/build/unix/mozconfig.linux"
|
||||
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
export PKG_CONFIG_LIBDIR=/usr/local/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig
|
||||
fi
|
||||
|
||||
export MOZ_LINUX_32_SSE2_STARTUP_ERROR=1
|
||||
|
||||
CFLAGS="$CFLAGS -msse -msse2 -mfpmath=sse"
|
||||
|
@ -5,6 +5,7 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import logging
|
||||
import mozinfo
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
@ -130,12 +131,15 @@ class MachCommands(MachCommandBase):
|
||||
supps_file1 = os.path.join(supps_dir, 'cross-architecture.sup')
|
||||
valgrind_args.append('--suppressions=' + supps_file1)
|
||||
|
||||
# MACHTYPE is an odd bash-only environment variable that doesn't
|
||||
# show up in os.environ, so we have to get it another way.
|
||||
machtype = subprocess.check_output(['bash', '-c', 'echo $MACHTYPE']).rstrip()
|
||||
supps_file2 = os.path.join(supps_dir, machtype + '.sup')
|
||||
if os.path.isfile(supps_file2):
|
||||
valgrind_args.append('--suppressions=' + supps_file2)
|
||||
if mozinfo.os == 'linux':
|
||||
machtype = {
|
||||
'x86_64': 'x86_64-pc-linux-gnu',
|
||||
'x86': 'i386-pc-linux-gnu',
|
||||
}.get(mozinfo.processor)
|
||||
if machtype:
|
||||
supps_file2 = os.path.join(supps_dir, machtype + '.sup')
|
||||
if os.path.isfile(supps_file2):
|
||||
valgrind_args.append('--suppressions=' + supps_file2)
|
||||
|
||||
exitcode = None
|
||||
timeout = 1800
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,14 @@
|
||||
fun:FcPatternObjectInsertElt
|
||||
...
|
||||
}
|
||||
{
|
||||
Bug 1187649
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
fun:FcPatternObjectInsertElt
|
||||
...
|
||||
}
|
||||
# With older versions of fontconfig (e.g. 2.8.0 on taskcluster systems),
|
||||
# there's an uninitialized memory usage and leak when loading app fonts.
|
||||
{
|
||||
@ -53,6 +61,18 @@
|
||||
fun:FcConfigAppFontAddDir
|
||||
...
|
||||
}
|
||||
{
|
||||
Bug 1231701
|
||||
Memcheck:Leak
|
||||
match-leak-kinds: definite
|
||||
fun:malloc
|
||||
fun:FcDirScanConfig
|
||||
fun:FcDirScanConfig
|
||||
fun:FcDirCacheScan
|
||||
fun:FcConfigAddDirList
|
||||
fun:FcConfigAppFontAddDir
|
||||
...
|
||||
}
|
||||
# Leaks due to either Gtk+3 or cairo, but Gecko is not directly involved with
|
||||
# those cairo interactions. One suspected cause is Gecko not closing the
|
||||
# display to work around a bug in old Gtk+3 versions. See also bug 1228724.
|
||||
@ -162,6 +182,15 @@
|
||||
fun:gdk_display_open
|
||||
...
|
||||
}
|
||||
{
|
||||
_g_io_module_get_default
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:g_io_module_new
|
||||
fun:g_io_modules_scan_all_in_directory_with_scope
|
||||
fun:_g_io_modules_ensure_loaded
|
||||
fun:_g_io_module_get_default
|
||||
}
|
||||
|
||||
###################################
|
||||
# Leaks in short lived precesses #
|
@ -7,6 +7,9 @@
|
||||
with Files('**'):
|
||||
BUG_COMPONENT = ('Core', 'Build Config')
|
||||
|
||||
with Files('mozunit.py'):
|
||||
BUG_COMPONENT = ('Testing', 'Python Test')
|
||||
|
||||
DIST_INSTALL = False
|
||||
# For sanity's sake, we compile nsinstall without the wrapped system
|
||||
# headers, so that we can use it to set up the wrapped system headers.
|
||||
|
@ -73,13 +73,10 @@ struct AnimationEventInfo
|
||||
nsCSSPseudoElements::PseudoTypeAsString(aTarget.mPseudoType);
|
||||
}
|
||||
|
||||
// InternalAnimationEvent and InternalTransitionEvent don't support
|
||||
// copy-construction, so we need to ourselves in order to work with nsTArray.
|
||||
//
|
||||
// FIXME: Drop this copy constructor and copy assignment below once
|
||||
// WidgetEvent have move constructor and move assignment (bug 1433008).
|
||||
AnimationEventInfo(const AnimationEventInfo& aOther) = default;
|
||||
AnimationEventInfo& operator=(const AnimationEventInfo& aOther) = default;
|
||||
AnimationEventInfo(const AnimationEventInfo& aOther) = delete;
|
||||
AnimationEventInfo& operator=(const AnimationEventInfo& aOther) = delete;
|
||||
AnimationEventInfo(AnimationEventInfo&& aOther) = default;
|
||||
AnimationEventInfo& operator=(AnimationEventInfo&& aOther) = default;
|
||||
|
||||
WidgetEvent* AsWidgetEvent()
|
||||
{
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "mozilla/ServoStyleSet.h"
|
||||
#include "mozilla/StyleAnimationValue.h"
|
||||
#include "mozilla/TypeTraits.h" // For Forward<>
|
||||
#include "nsComputedDOMStyle.h" // nsComputedDOMStyle::GetPresShellForContent
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCSSPseudoElements.h"
|
||||
#include "nsCSSPropertyIDSet.h"
|
||||
@ -263,7 +262,7 @@ EffectCompositor::RequestRestyle(dom::Element* aElement,
|
||||
|
||||
// Ignore animations on orphaned elements and elements in documents without
|
||||
// a pres shell (e.g. XMLHttpRequest responseXML documents).
|
||||
if (!nsComputedDOMStyle::GetPresShellForContent(aElement)) {
|
||||
if (!nsContentUtils::GetPresShellForContent(aElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -491,7 +490,7 @@ EffectCompositor::GetServoAnimationRule(
|
||||
MOZ_ASSERT(mPresContext && mPresContext->IsDynamic(),
|
||||
"Should not be in print preview");
|
||||
// Gecko_GetAnimationRule should have already checked this
|
||||
MOZ_ASSERT(nsComputedDOMStyle::GetPresShellForContent(aElement),
|
||||
MOZ_ASSERT(nsContentUtils::GetPresShellForContent(aElement),
|
||||
"Should not be trying to run animations on elements in documents"
|
||||
" without a pres shell (e.g. XMLHttpRequest documents)");
|
||||
|
||||
@ -980,7 +979,7 @@ EffectCompositor::PreTraverseInSubtree(ServoTraversalFlags aFlags,
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mPresContext->RestyleManager()->IsServo());
|
||||
MOZ_ASSERT(!aRoot || nsComputedDOMStyle::GetPresShellForContent(aRoot),
|
||||
MOZ_ASSERT(!aRoot || nsContentUtils::GetPresShellForContent(aRoot),
|
||||
"Traversal root, if provided, should be bound to a display "
|
||||
"document");
|
||||
|
||||
@ -1027,7 +1026,7 @@ EffectCompositor::PreTraverseInSubtree(ServoTraversalFlags aFlags,
|
||||
// We will drop them from mElementsToRestyle at the end of the next full
|
||||
// document restyle (at the end of this function) but for consistency with
|
||||
// how we treat such elements in RequestRestyle, we just ignore them here.
|
||||
if (!nsComputedDOMStyle::GetPresShellForContent(target.mElement)) {
|
||||
if (!nsContentUtils::GetPresShellForContent(target.mElement)) {
|
||||
return returnTarget;
|
||||
}
|
||||
|
||||
@ -1133,7 +1132,7 @@ EffectCompositor::PreTraverse(dom::Element* aElement,
|
||||
// If |aElement|'s document does not have a pres shell, e.g. it is document
|
||||
// without a browsing context such as we might get from an XMLHttpRequest, we
|
||||
// should not run animations on it.
|
||||
if (!nsComputedDOMStyle::GetPresShellForContent(aElement)) {
|
||||
if (!nsContentUtils::GetPresShellForContent(aElement)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1002,7 +1002,7 @@ waitForAllPaints(() => {
|
||||
// It's possible that the animation begins at this moment. If this is the
|
||||
// case, an additional superfluous restyle request that we will check later
|
||||
// can't be observed.
|
||||
const expectedRestyleCount = tweakExpectedRestyleCount(animation, 1);
|
||||
const superfluousRestyle = startsRightNow(animation) ? 0 : 1;
|
||||
|
||||
var markers = await observeStyling(5);
|
||||
is(markers.length, 0,
|
||||
@ -1027,7 +1027,7 @@ waitForAllPaints(() => {
|
||||
// Bug 1417354: There will be an additional superfluous restyle request
|
||||
// which results when we detach an element from the document between
|
||||
// the Animation tick and styling, and then re-attach it.
|
||||
is(markers.length, expectedRestyleCount,
|
||||
is(markers.length, 1 + superfluousRestyle,
|
||||
'We should observe one restyle in the first frame right after ' +
|
||||
're-attaching to the document');
|
||||
} else {
|
||||
|
@ -3473,18 +3473,29 @@ nsContentUtils::SplitExpatName(const char16_t *aExpatName, nsAtom **aPrefix,
|
||||
*aLocalName = NS_AtomizeMainThread(Substring(nameStart, nameEnd)).take();
|
||||
}
|
||||
|
||||
// static
|
||||
nsIPresShell*
|
||||
nsContentUtils::GetPresShellForContent(const nsIContent* aContent)
|
||||
{
|
||||
nsIDocument* doc = aContent->GetComposedDoc();
|
||||
if (!doc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return doc->GetShell();
|
||||
}
|
||||
|
||||
// static
|
||||
nsPresContext*
|
||||
nsContentUtils::GetContextForContent(const nsIContent* aContent)
|
||||
{
|
||||
nsIDocument* doc = aContent->GetComposedDoc();
|
||||
if (doc) {
|
||||
nsIPresShell *presShell = doc->GetShell();
|
||||
if (presShell) {
|
||||
return presShell->GetPresContext();
|
||||
}
|
||||
nsIPresShell* presShell = GetPresShellForContent(aContent);
|
||||
|
||||
if (!presShell) {
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
return presShell->GetPresContext();
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -781,10 +781,20 @@ public:
|
||||
*
|
||||
* @param aContent The content node.
|
||||
* @return the presContext, or nullptr if the content is not in a document
|
||||
* (if GetCurrentDoc returns nullptr)
|
||||
* (if GetComposedDoc returns nullptr)
|
||||
*/
|
||||
static nsPresContext* GetContextForContent(const nsIContent* aContent);
|
||||
|
||||
|
||||
/**
|
||||
* Method that gets the pres shell for the node.
|
||||
*
|
||||
* @param aContent The content node.
|
||||
* @return the pres shell, or nullptr if the content is not in a document
|
||||
* (if GetComposedDoc returns nullptr)
|
||||
*/
|
||||
static nsIPresShell* GetPresShellForContent(const nsIContent* aContent);
|
||||
|
||||
/**
|
||||
* Method to do security and content policy checks on the image URI
|
||||
*
|
||||
|
@ -2706,8 +2706,15 @@ class AttrDefiner(PropertyDefiner):
|
||||
not isNonExposedNavigatorObjectGetter(m, descriptor)]
|
||||
else:
|
||||
attributes = []
|
||||
self.chrome = [m for m in attributes if isChromeOnly(m)]
|
||||
self.regular = [m for m in attributes if not isChromeOnly(m)]
|
||||
|
||||
attributes = [
|
||||
{"name": name, "attr": attr}
|
||||
for attr in attributes
|
||||
for name in [attr.identifier.name] + attr.bindingAliases
|
||||
]
|
||||
|
||||
self.chrome = [m for m in attributes if isChromeOnly(m["attr"])]
|
||||
self.regular = [m for m in attributes if not isChromeOnly(m["attr"])]
|
||||
self.static = static
|
||||
self.unforgeable = unforgeable
|
||||
|
||||
@ -2724,6 +2731,9 @@ class AttrDefiner(PropertyDefiner):
|
||||
if len(array) == 0:
|
||||
return ""
|
||||
|
||||
def condition(m, d):
|
||||
return PropertyDefiner.getControllingCondition(m["attr"], d)
|
||||
|
||||
def flags(attr):
|
||||
unforgeable = " | JSPROP_PERMANENT" if self.unforgeable else ""
|
||||
return EnumerabilityFlags(attr) + unforgeable
|
||||
@ -2791,16 +2801,16 @@ class AttrDefiner(PropertyDefiner):
|
||||
return "%s, %s" % \
|
||||
(accessor, jitinfo)
|
||||
|
||||
def specData(attr):
|
||||
return (attr.identifier.name, flags(attr), getter(attr),
|
||||
setter(attr))
|
||||
def specData(entry):
|
||||
name, attr = entry["name"], entry["attr"]
|
||||
return (name, flags(attr), getter(attr), setter(attr))
|
||||
|
||||
return self.generatePrefableArray(
|
||||
array, name,
|
||||
lambda fields: ' { "%s", %s, %s, %s }' % fields,
|
||||
' { nullptr, 0, nullptr, nullptr, nullptr, nullptr }',
|
||||
'JSPropertySpec',
|
||||
PropertyDefiner.getControllingCondition, specData)
|
||||
condition, specData)
|
||||
|
||||
|
||||
class ConstDefiner(PropertyDefiner):
|
||||
|
@ -33,16 +33,15 @@ def generate(output, idlFilename, preprocessorHeader):
|
||||
if pref is not "":
|
||||
extendedAttrs.append('Pref="%s"' % pref)
|
||||
|
||||
# webkit properties get a capitalized "WebkitFoo" accessor (added here)
|
||||
# as well as a camelcase "webkitFoo" accessor (added next).
|
||||
# webkit properties get a camelcase "webkitFoo" accessor
|
||||
# as well as a capitalized "WebkitFoo" alias (added here).
|
||||
if (prop.startswith("Webkit")):
|
||||
props += generateLine(prop, extendedAttrs)
|
||||
extendedAttrs.append('BindingAlias="%s"' % prop)
|
||||
|
||||
# Generate a line with camelCase spelling of property-name (or capitalized,
|
||||
# Generate a name with camelCase spelling of property-name (or capitalized,
|
||||
# for Moz-prefixed properties):
|
||||
if not prop.startswith("Moz"):
|
||||
prop = prop[0].lower() + prop[1:]
|
||||
props += generateLine(prop, extendedAttrs)
|
||||
|
||||
# Per spec, what's actually supposed to happen here is that we're supposed
|
||||
# to have properties for:
|
||||
@ -56,15 +55,14 @@ def generate(output, idlFilename, preprocessorHeader):
|
||||
# in that list.
|
||||
#
|
||||
# In practice, cssFloat is the only case in which "name" doesn't contain
|
||||
# "-" but also doesn't match "prop". So the above generatePropLine() call
|
||||
# covered (3) and all of (1) except "float". If we now output attributes
|
||||
# "-" but also doesn't match "prop". So the generateLine() call will
|
||||
# cover (3) and all of (1) except "float". If we now add an alias
|
||||
# for all the cases where "name" doesn't match "prop", that will cover
|
||||
# "float" and (2).
|
||||
if prop != name:
|
||||
extendedAttrs.append('BinaryName="%s"' % prop)
|
||||
# Throw in a '_' before the attribute name, because some of these
|
||||
# property names collide with IDL reserved words.
|
||||
props += generateLine("_" + name, extendedAttrs)
|
||||
extendedAttrs.append('BindingAlias="%s"' % name)
|
||||
|
||||
props += generateLine(prop, extendedAttrs)
|
||||
|
||||
|
||||
idlFile = open(idlFilename, "r")
|
||||
|
@ -1181,6 +1181,22 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
|
||||
parent = parent.parent
|
||||
|
||||
def validate(self):
|
||||
|
||||
def checkDuplicateNames(member, name, attributeName):
|
||||
for m in self.members:
|
||||
if m.identifier.name == name:
|
||||
raise WebIDLError("[%s=%s] has same name as interface member" %
|
||||
(attributeName, name),
|
||||
[member.location, m.location])
|
||||
if m.isMethod() and m != member and name in m.aliases:
|
||||
raise WebIDLError("conflicting [%s=%s] definitions" %
|
||||
(attributeName, name),
|
||||
[member.location, m.location])
|
||||
if m.isAttr() and m != member and name in m.bindingAliases:
|
||||
raise WebIDLError("conflicting [%s=%s] definitions" %
|
||||
(attributeName, name),
|
||||
[member.location, m.location])
|
||||
|
||||
# We don't support consequential unforgeable interfaces. Need to check
|
||||
# this here, because in finish() an interface might not know yet that
|
||||
# it's consequential.
|
||||
@ -1293,15 +1309,15 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
|
||||
raise WebIDLError("[Alias] must not be used on an "
|
||||
"[Unforgeable] operation",
|
||||
[member.location])
|
||||
for m in self.members:
|
||||
if m.identifier.name == alias:
|
||||
raise WebIDLError("[Alias=%s] has same name as "
|
||||
"interface member" % alias,
|
||||
[member.location, m.location])
|
||||
if m.isMethod() and m != member and alias in m.aliases:
|
||||
raise WebIDLError("duplicate [Alias=%s] definitions" %
|
||||
alias,
|
||||
[member.location, m.location])
|
||||
|
||||
checkDuplicateNames(member, alias, "Alias")
|
||||
|
||||
# Check that the name of a [BindingAlias] doesn't conflict with an
|
||||
# interface member.
|
||||
if member.isAttr():
|
||||
for bindingAlias in member.bindingAliases:
|
||||
checkDuplicateNames(member, bindingAlias, "BindingAlias")
|
||||
|
||||
|
||||
if (self.getExtendedAttribute("Pref") and
|
||||
self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])):
|
||||
@ -3581,6 +3597,11 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
|
||||
[self.location])
|
||||
self.aliases.append(alias)
|
||||
|
||||
def _addBindingAlias(self, bindingAlias):
|
||||
if bindingAlias in self.bindingAliases:
|
||||
raise WebIDLError("Duplicate [BindingAlias=%s] on attribute" % bindingAlias,
|
||||
[self.location])
|
||||
self.bindingAliases.append(bindingAlias)
|
||||
|
||||
class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||
|
||||
@ -4011,6 +4032,7 @@ class IDLAttribute(IDLInterfaceMember):
|
||||
self.dependsOn = "Everything"
|
||||
self.affects = "Everything"
|
||||
self.navigatorObjectGetter = navigatorObjectGetter
|
||||
self.bindingAliases = []
|
||||
|
||||
if static and identifier.name == "prototype":
|
||||
raise WebIDLError("The identifier of a static attribute must not be 'prototype'",
|
||||
@ -4155,6 +4177,11 @@ class IDLAttribute(IDLInterfaceMember):
|
||||
raise WebIDLError("Readonly attributes must not be flagged as "
|
||||
"[%s]" % identifier,
|
||||
[self.location])
|
||||
elif identifier == "BindingAlias":
|
||||
if not attr.hasValue():
|
||||
raise WebIDLError("[BindingAlias] takes an identifier or string",
|
||||
[attr.location])
|
||||
self._addBindingAlias(attr.value())
|
||||
elif (((identifier == "Throws" or identifier == "GetterThrows" or
|
||||
identifier == "CanOOM" or identifier == "GetterCanOOM") and
|
||||
self.getExtendedAttribute("StoreInSlot")) or
|
||||
|
@ -243,8 +243,7 @@ ContentEventHandler::RawRange::SelectNodeContents(
|
||||
// line break caused by the <br> should be included into the flatten text.
|
||||
|
||||
ContentEventHandler::ContentEventHandler(nsPresContext* aPresContext)
|
||||
: mPresContext(aPresContext)
|
||||
, mDocument(aPresContext->Document())
|
||||
: mDocument(aPresContext->Document())
|
||||
{
|
||||
}
|
||||
|
||||
@ -514,8 +513,10 @@ ContentEventHandler::QueryContentRect(nsIContent* aContent,
|
||||
nsresult rv = ConvertToRootRelativeOffset(frame, resultRect);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsPresContext* presContext = frame->PresContext();
|
||||
|
||||
// account for any additional frames
|
||||
while ((frame = frame->GetNextContinuation()) != nullptr) {
|
||||
while ((frame = frame->GetNextContinuation())) {
|
||||
nsRect frameRect(nsPoint(0, 0), frame->GetRect().Size());
|
||||
rv = ConvertToRootRelativeOffset(frame, frameRect);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -523,7 +524,7 @@ ContentEventHandler::QueryContentRect(nsIContent* aContent,
|
||||
}
|
||||
|
||||
aEvent->mReply.mRect = LayoutDeviceIntRect::FromUnknownRect(
|
||||
resultRect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel()));
|
||||
resultRect.ToOutsidePixels(presContext->AppUnitsPerDevPixel()));
|
||||
// Returning empty rect may cause native IME confused, let's make sure to
|
||||
// return non-empty rect.
|
||||
EnsureNonEmptyRect(aEvent->mReply.mRect);
|
||||
@ -1860,10 +1861,10 @@ ContentEventHandler::GetLineBreakerRectBefore(nsIFrame* aFrame)
|
||||
// above of top-right corner of aFrame.
|
||||
result.mRect.x = aFrame->GetRect().XMost() - result.mRect.width;
|
||||
}
|
||||
result.mRect.y = -mPresContext->AppUnitsPerDevPixel();
|
||||
result.mRect.y = -aFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
} else {
|
||||
// left of top-left corner of aFrame.
|
||||
result.mRect.x = -mPresContext->AppUnitsPerDevPixel();
|
||||
result.mRect.x = -aFrame->PresContext()->AppUnitsPerDevPixel();
|
||||
result.mRect.y = 0;
|
||||
}
|
||||
}
|
||||
@ -1908,6 +1909,7 @@ ContentEventHandler::FrameRelativeRect
|
||||
ContentEventHandler::GuessFirstCaretRectIn(nsIFrame* aFrame)
|
||||
{
|
||||
const WritingMode kWritingMode = aFrame->GetWritingMode();
|
||||
nsPresContext* presContext = aFrame->PresContext();
|
||||
|
||||
// Computes the font height, but if it's not available, we should use
|
||||
// default font size of Firefox. The default font size in default settings
|
||||
@ -1916,7 +1918,7 @@ ContentEventHandler::GuessFirstCaretRectIn(nsIFrame* aFrame)
|
||||
nsLayoutUtils::GetInflatedFontMetricsForFrame(aFrame);
|
||||
const nscoord kMaxHeight =
|
||||
fontMetrics ? fontMetrics->MaxHeight() :
|
||||
16 * mPresContext->AppUnitsPerDevPixel();
|
||||
16 * presContext->AppUnitsPerDevPixel();
|
||||
|
||||
nsRect caretRect;
|
||||
const nsRect kContentRect = aFrame->GetContentRect() - aFrame->GetPosition();
|
||||
@ -1926,7 +1928,7 @@ ContentEventHandler::GuessFirstCaretRectIn(nsIFrame* aFrame)
|
||||
caretRect.x = kContentRect.x;
|
||||
} else {
|
||||
// Move 1px left for the space of caret itself.
|
||||
const nscoord kOnePixel = mPresContext->AppUnitsPerDevPixel();
|
||||
const nscoord kOnePixel = presContext->AppUnitsPerDevPixel();
|
||||
caretRect.x = kContentRect.XMost() - kOnePixel;
|
||||
}
|
||||
caretRect.height = kMaxHeight;
|
||||
@ -2176,8 +2178,8 @@ ContentEventHandler::OnQueryTextRectArray(WidgetQueryContentEvent* aEvent)
|
||||
return rv;
|
||||
}
|
||||
|
||||
rect = LayoutDeviceIntRect::FromUnknownRect(
|
||||
charRect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel()));
|
||||
rect = LayoutDeviceIntRect::FromUnknownRect(charRect.ToOutsidePixels(
|
||||
baseFrame->PresContext()->AppUnitsPerDevPixel()));
|
||||
// Returning empty rect may cause native IME confused, let's make sure to
|
||||
// return non-empty rect.
|
||||
EnsureNonEmptyRect(rect);
|
||||
@ -2328,7 +2330,9 @@ ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent)
|
||||
// If there is at least one frame which can be used for computing a rect
|
||||
// for a character or a line breaker, we should use it for guessing the
|
||||
// caret rect at the end of the contents.
|
||||
nsPresContext* presContext;
|
||||
if (lastFrame) {
|
||||
presContext = lastFrame->PresContext();
|
||||
if (NS_WARN_IF(!lastFrame->GetContent())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -2364,6 +2368,7 @@ ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent)
|
||||
if (NS_WARN_IF(!rootContentFrame)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
presContext = rootContentFrame->PresContext();
|
||||
FrameRelativeRect relativeRect = GuessFirstCaretRectIn(rootContentFrame);
|
||||
if (NS_WARN_IF(!relativeRect.IsValid())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -2376,7 +2381,7 @@ ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent)
|
||||
aEvent->mReply.mWritingMode = rootContentFrame->GetWritingMode();
|
||||
}
|
||||
aEvent->mReply.mRect = LayoutDeviceIntRect::FromUnknownRect(
|
||||
rect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel()));
|
||||
rect.ToOutsidePixels(presContext->AppUnitsPerDevPixel()));
|
||||
EnsureNonEmptyRect(aEvent->mReply.mRect);
|
||||
aEvent->mSucceeded = true;
|
||||
return NS_OK;
|
||||
@ -2558,7 +2563,7 @@ ContentEventHandler::OnQueryTextRect(WidgetQueryContentEvent* aEvent)
|
||||
}
|
||||
|
||||
aEvent->mReply.mRect = LayoutDeviceIntRect::FromUnknownRect(
|
||||
rect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel()));
|
||||
rect.ToOutsidePixels(lastFrame->PresContext()->AppUnitsPerDevPixel()));
|
||||
// Returning empty rect may cause native IME confused, let's make sure to
|
||||
// return non-empty rect.
|
||||
EnsureNonEmptyRect(aEvent->mReply.mRect);
|
||||
@ -2808,8 +2813,8 @@ ContentEventHandler::OnQueryDOMWidgetHittest(WidgetQueryContentEvent* aEvent)
|
||||
aEvent->mRefPoint + aEvent->mWidget->WidgetToScreenOffset();
|
||||
CSSIntRect docFrameRect = docFrame->GetScreenRect();
|
||||
CSSIntPoint eventLocCSS(
|
||||
mPresContext->DevPixelsToIntCSSPixels(eventLoc.x) - docFrameRect.x,
|
||||
mPresContext->DevPixelsToIntCSSPixels(eventLoc.y) - docFrameRect.y);
|
||||
docFrame->PresContext()->DevPixelsToIntCSSPixels(eventLoc.x) - docFrameRect.x,
|
||||
docFrame->PresContext()->DevPixelsToIntCSSPixels(eventLoc.y) - docFrameRect.y);
|
||||
|
||||
Element* contentUnderMouse =
|
||||
mDocument->ElementFromPointHelper(eventLocCSS.x, eventLocCSS.y, false, false);
|
||||
|
@ -140,7 +140,6 @@ public:
|
||||
nsresult OnSelectionEvent(WidgetSelectionEvent* aEvent);
|
||||
|
||||
protected:
|
||||
nsPresContext* mPresContext;
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
// mSelection is typically normal selection but if OnQuerySelectedText()
|
||||
// is called, i.e., handling eQuerySelectedText, it's the specified selection
|
||||
|
@ -3050,7 +3050,7 @@ nsGenericHTMLElement::GetInnerText(mozilla::dom::DOMString& aValue,
|
||||
mozilla::ErrorResult& aError)
|
||||
{
|
||||
if (!GetPrimaryFrame(FlushType::Layout)) {
|
||||
nsIPresShell* presShell = nsComputedDOMStyle::GetPresShellForContent(this);
|
||||
nsIPresShell* presShell = nsContentUtils::GetPresShellForContent(this);
|
||||
// NOTE(emilio): We need to check the presshell is initialized in order to
|
||||
// ensure the document is styled.
|
||||
if (!presShell || !presShell->DidInitialize() ||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "GMPContentChild.h"
|
||||
#include "GMPContentParent.h"
|
||||
#include "GMPLog.h"
|
||||
#include "GMPService.h"
|
||||
#include "GMPUtils.h"
|
||||
#include "MediaPrefs.h"
|
||||
#include "mozilla/dom/MediaKeyMessageEventBinding.h"
|
||||
@ -44,17 +45,42 @@ bool
|
||||
ChromiumCDMParent::Init(ChromiumCDMCallback* aCDMCallback,
|
||||
bool aAllowDistinctiveIdentifier,
|
||||
bool aAllowPersistentState,
|
||||
nsIEventTarget* aMainThread)
|
||||
nsIEventTarget* aMainThread,
|
||||
nsCString& aOutFailureReason)
|
||||
{
|
||||
GMP_LOG("ChromiumCDMParent::Init(this=%p)", this);
|
||||
GMP_LOG("ChromiumCDMParent::Init(this=%p) shutdown=%d abormalShutdown=%d "
|
||||
"actorDestroyed=%d",
|
||||
this,
|
||||
mIsShutdown,
|
||||
mAbnormalShutdown,
|
||||
mActorDestroyed);
|
||||
if (!aCDMCallback || !aMainThread) {
|
||||
aOutFailureReason = nsPrintfCString("ChromiumCDMParent::Init() failed "
|
||||
"nullCallback=%d nullMainThread=%d",
|
||||
!aCDMCallback,
|
||||
!aMainThread);
|
||||
GMP_LOG("ChromiumCDMParent::Init(this=%p) failure since aCDMCallback(%p) or"
|
||||
" aMainThread(%p) is nullptr", this, aCDMCallback, aMainThread);
|
||||
return false;
|
||||
}
|
||||
mCDMCallback = aCDMCallback;
|
||||
mMainThread = aMainThread;
|
||||
return SendInit(aAllowDistinctiveIdentifier, aAllowPersistentState);
|
||||
|
||||
if (SendInit(aAllowDistinctiveIdentifier, aAllowPersistentState)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RefPtr<gmp::GeckoMediaPluginService> service =
|
||||
gmp::GeckoMediaPluginService::GetGeckoMediaPluginService();
|
||||
bool xpcomWillShutdown = service && service->XPCOMWillShutdownReceived();
|
||||
aOutFailureReason = nsPrintfCString(
|
||||
"ChromiumCDMParent::Init() failed "
|
||||
"shutdown=%d cdmCrash=%d actorDestroyed=%d browserShutdown=%d",
|
||||
mIsShutdown,
|
||||
mAbnormalShutdown,
|
||||
mActorDestroyed,
|
||||
xpcomWillShutdown);
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
@ -865,11 +891,11 @@ ChromiumCDMParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
mContentParent->ChromiumCDMDestroyed(this);
|
||||
mContentParent = nullptr;
|
||||
}
|
||||
bool abnormalShutdown = (aWhy == AbnormalShutdown);
|
||||
if (abnormalShutdown && callback) {
|
||||
mAbnormalShutdown = (aWhy == AbnormalShutdown);
|
||||
if (mAbnormalShutdown && callback) {
|
||||
callback->Terminated();
|
||||
}
|
||||
MaybeDisconnect(abnormalShutdown);
|
||||
MaybeDisconnect(mAbnormalShutdown);
|
||||
}
|
||||
|
||||
RefPtr<MediaDataDecoder::InitPromise>
|
||||
|
@ -43,7 +43,8 @@ public:
|
||||
bool Init(ChromiumCDMCallback* aCDMCallback,
|
||||
bool aAllowDistinctiveIdentifier,
|
||||
bool aAllowPersistentState,
|
||||
nsIEventTarget* aMainThread);
|
||||
nsIEventTarget* aMainThread,
|
||||
nsCString& aOutFailureReason);
|
||||
|
||||
void CreateSession(uint32_t aCreateSessionToken,
|
||||
uint32_t aSessionType,
|
||||
@ -182,6 +183,7 @@ protected:
|
||||
bool mIsShutdown = false;
|
||||
bool mVideoDecoderInitialized = false;
|
||||
bool mActorDestroyed = false;
|
||||
bool mAbnormalShutdown = false;
|
||||
|
||||
// The H.264 decoder in Widevine CDM versions 970 and later output in decode
|
||||
// order rather than presentation order, so we reorder in presentation order
|
||||
|
@ -101,13 +101,13 @@ ChromiumCDMProxy::Init(PromiseId aPromiseId,
|
||||
[self, aPromiseId](RefPtr<gmp::ChromiumCDMParent> cdm) {
|
||||
self->mCallback =
|
||||
MakeUnique<ChromiumCDMCallbackProxy>(self, self->mMainThread);
|
||||
nsCString failureReason;
|
||||
if (!cdm->Init(self->mCallback.get(),
|
||||
self->mDistinctiveIdentifierRequired,
|
||||
self->mPersistentStateRequired,
|
||||
self->mMainThread)) {
|
||||
self->RejectPromise(aPromiseId,
|
||||
NS_ERROR_FAILURE,
|
||||
NS_LITERAL_CSTRING("GetCDM failed due to CDM initialization failure."));
|
||||
self->mMainThread,
|
||||
failureReason)) {
|
||||
self->RejectPromise(aPromiseId, NS_ERROR_FAILURE, failureReason);
|
||||
return;
|
||||
}
|
||||
{
|
||||
|
@ -150,6 +150,7 @@ GeckoMediaPluginService::GeckoMediaPluginService()
|
||||
: mMutex("GeckoMediaPluginService::mMutex")
|
||||
, mGMPThreadShutdown(false)
|
||||
, mShuttingDownOnGMPThread(false)
|
||||
, mXPCOMWillShutdown(false)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
@ -224,6 +225,8 @@ GeckoMediaPluginService::Init()
|
||||
nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService();
|
||||
MOZ_ASSERT(obsService);
|
||||
MOZ_ALWAYS_SUCCEEDS(obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false));
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
obsService->AddObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID, false));
|
||||
|
||||
// Kick off scanning for plugins
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "mozIGeckoMediaPluginService.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "nsString.h"
|
||||
@ -107,6 +108,8 @@ public:
|
||||
void ConnectCrashHelper(uint32_t aPluginId, GMPCrashHelper* aHelper);
|
||||
void DisconnectCrashHelper(GMPCrashHelper* aHelper);
|
||||
|
||||
bool XPCOMWillShutdownReceived() const { return mXPCOMWillShutdown; }
|
||||
|
||||
protected:
|
||||
GeckoMediaPluginService();
|
||||
virtual ~GeckoMediaPluginService();
|
||||
@ -135,6 +138,7 @@ protected:
|
||||
RefPtr<AbstractThread> mAbstractGMPThread;
|
||||
bool mGMPThreadShutdown;
|
||||
bool mShuttingDownOnGMPThread;
|
||||
Atomic<bool> mXPCOMWillShutdown;
|
||||
|
||||
nsClassHashtable<nsUint32HashKey, nsTArray<RefPtr<GMPCrashHelper>>> mPluginCrashHelpers;
|
||||
};
|
||||
|
@ -387,6 +387,8 @@ GeckoMediaPluginServiceChild::Observe(nsISupports* aSubject,
|
||||
mServiceChild = nullptr;
|
||||
}
|
||||
ShutdownGMPThread();
|
||||
} else if (!strcmp(NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID, aTopic)) {
|
||||
mXPCOMWillShutdown = true;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -309,6 +309,8 @@ GeckoMediaPluginServiceParent::Observe(nsISupports* aSubject,
|
||||
} else if (!strcmp(NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, aTopic)) {
|
||||
MOZ_ASSERT(mShuttingDown);
|
||||
ShutdownGMPThread();
|
||||
} else if (!strcmp(NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID, aTopic)) {
|
||||
mXPCOMWillShutdown = true;
|
||||
} else if (!strcmp("last-pb-context-exited", aTopic)) {
|
||||
// When Private Browsing mode exits, all we need to do is clear
|
||||
// mTempNodeIds. This drops all the node ids we've cached in memory
|
||||
|
@ -465,7 +465,12 @@ class CDMStorageTest
|
||||
self->mCDM = cdm;
|
||||
EXPECT_TRUE(!!self->mCDM);
|
||||
self->mCallback.reset(new CallbackProxy(self));
|
||||
self->mCDM->Init(self->mCallback.get(), false, true, GetMainThreadEventTarget());
|
||||
nsCString failureReason;
|
||||
self->mCDM->Init(self->mCallback.get(),
|
||||
false,
|
||||
true,
|
||||
GetMainThreadEventTarget(),
|
||||
failureReason);
|
||||
|
||||
for (auto& update : aUpdates) {
|
||||
self->Update(update);
|
||||
|
@ -664,6 +664,7 @@ private:
|
||||
DECL_GFX_PREF(Live, "layout.display-list.retain", LayoutRetainDisplayList, bool, true);
|
||||
DECL_GFX_PREF(Live, "layout.display-list.retain.chrome", LayoutRetainDisplayListChrome, bool, false);
|
||||
DECL_GFX_PREF(Live, "layout.display-list.retain.verify", LayoutVerifyRetainDisplayList, bool, false);
|
||||
DECL_GFX_PREF(Live, "layout.display-list.retain.verify.order", LayoutVerifyRetainDisplayListOrder, bool, false);
|
||||
DECL_GFX_PREF(Live, "layout.display-list.rebuild-frame-limit", LayoutRebuildFrameLimit, uint32_t, 500);
|
||||
DECL_GFX_PREF(Live, "layout.display-list.dump", LayoutDumpDisplayList, bool, false);
|
||||
DECL_GFX_PREF(Live, "layout.display-list.dump-content", LayoutDumpDisplayListContent, bool, false);
|
||||
|
@ -564,11 +564,11 @@ Interceptor::GetInitialInterceptorForIID(detail::LiveSetAutoLock& aLiveSetLock,
|
||||
}
|
||||
|
||||
// Raise the refcount for stabilization purposes during aggregation
|
||||
RefPtr<IUnknown> kungFuDeathGrip(static_cast<IUnknown*>(
|
||||
static_cast<WeakReferenceSupport*>(this)));
|
||||
WeakReferenceSupport::StabilizeRefCount stabilizer(*this);
|
||||
|
||||
RefPtr<IUnknown> unkInterceptor;
|
||||
HRESULT hr = CreateInterceptor(aTargetIid, kungFuDeathGrip,
|
||||
HRESULT hr = CreateInterceptor(aTargetIid,
|
||||
static_cast<WeakReferenceSupport*>(this),
|
||||
getter_AddRefs(unkInterceptor));
|
||||
ENSURE_HR_SUCCEEDED(hr);
|
||||
|
||||
@ -678,10 +678,10 @@ Interceptor::GetInterceptorForIID(REFIID aIid, void** aOutInterceptor)
|
||||
// IUnknown to |this|.
|
||||
|
||||
// Raise the refcount for stabilization purposes during aggregation
|
||||
RefPtr<IUnknown> kungFuDeathGrip(static_cast<IUnknown*>(
|
||||
static_cast<WeakReferenceSupport*>(this)));
|
||||
WeakReferenceSupport::StabilizeRefCount stabilizer(*this);
|
||||
|
||||
hr = CreateInterceptor(interceptorIid, kungFuDeathGrip,
|
||||
hr = CreateInterceptor(interceptorIid,
|
||||
static_cast<WeakReferenceSupport*>(this),
|
||||
getter_AddRefs(unkInterceptor));
|
||||
ENSURE_HR_SUCCEEDED(hr);
|
||||
|
||||
|
@ -113,7 +113,7 @@ WeakReferenceSupport::QueryInterface(REFIID riid, void** ppv)
|
||||
*ppv = nullptr;
|
||||
|
||||
// Raise the refcount for stabilization purposes during aggregation
|
||||
RefPtr<IUnknown> kungFuDeathGrip(this);
|
||||
StabilizeRefCount stabilize(*this);
|
||||
|
||||
if (riid == IID_IUnknown || riid == IID_IWeakReferenceSource) {
|
||||
punk = static_cast<IUnknown*>(this);
|
||||
@ -132,6 +132,23 @@ WeakReferenceSupport::QueryInterface(REFIID riid, void** ppv)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
WeakReferenceSupport::StabilizeRefCount::StabilizeRefCount(WeakReferenceSupport& aObject)
|
||||
: mObject(aObject)
|
||||
{
|
||||
SharedRefAutoLock lock(*mObject.mSharedRef);
|
||||
++mObject.mRefCnt;
|
||||
}
|
||||
|
||||
WeakReferenceSupport::StabilizeRefCount::~StabilizeRefCount()
|
||||
{
|
||||
// We directly access these fields instead of calling Release() because we
|
||||
// want to adjust the ref count without the other side effects (such as
|
||||
// deleting this if the count drops back to zero, which may happen during
|
||||
// an initial QI during object creation).
|
||||
SharedRefAutoLock lock(*mObject.mSharedRef);
|
||||
--mObject.mRefCnt;
|
||||
}
|
||||
|
||||
ULONG
|
||||
WeakReferenceSupport::AddRef()
|
||||
{
|
||||
|
@ -101,6 +101,23 @@ protected:
|
||||
virtual HRESULT WeakRefQueryInterface(REFIID aIid,
|
||||
IUnknown** aOutInterface) = 0;
|
||||
|
||||
class MOZ_RAII StabilizeRefCount final
|
||||
{
|
||||
public:
|
||||
explicit StabilizeRefCount(WeakReferenceSupport& aObject);
|
||||
~StabilizeRefCount();
|
||||
|
||||
StabilizeRefCount(const StabilizeRefCount&) = delete;
|
||||
StabilizeRefCount(StabilizeRefCount&&) = delete;
|
||||
StabilizeRefCount& operator=(const StabilizeRefCount&) = delete;
|
||||
StabilizeRefCount& operator=(StabilizeRefCount&&) = delete;
|
||||
|
||||
private:
|
||||
WeakReferenceSupport& mObject;
|
||||
};
|
||||
|
||||
friend class StabilizeRefCount;
|
||||
|
||||
private:
|
||||
RefPtr<detail::SharedRef> mSharedRef;
|
||||
ULONG mRefCnt;
|
||||
|
@ -1896,10 +1896,10 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
|
||||
if (i == 1) {
|
||||
// This is the FlushType::Style case.
|
||||
|
||||
DispatchScrollEvents();
|
||||
DispatchAnimationEvents();
|
||||
DispatchPendingEvents();
|
||||
RunFrameRequestCallbacks(aNowTime);
|
||||
DispatchScrollEvents();
|
||||
|
||||
if (mPresContext && mPresContext->GetPresShell()) {
|
||||
AutoTArray<nsIPresShell*, 16> observers;
|
||||
|
@ -29,15 +29,15 @@ var inner = document.getElementById("inner");
|
||||
var state = "initial";
|
||||
|
||||
function onFrame() {
|
||||
is(state, "initial", "Must be in initial state");
|
||||
ok(d.scrollTop > 0, "Must have scrolled by some amount (got " + d.scrollTop + ")");
|
||||
is(state, "didOnScroll", "Must have got scroll event already");
|
||||
state = "didOnFrame";
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function onScroll() {
|
||||
is(state, "didOnFrame", "Must have got requestAnimationFrame callback already");
|
||||
is(state, "initial", "Must be in initial state");
|
||||
ok(d.scrollTop > 0, "Must have scrolled by some amount (got " + d.scrollTop + ")");
|
||||
SimpleTest.finish();
|
||||
state = "didOnScroll";
|
||||
}
|
||||
|
||||
function doTest() {
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "DisplayListChecker.h"
|
||||
|
||||
#include "gfxPrefs.h"
|
||||
#include "nsDisplayList.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -93,6 +94,7 @@ private:
|
||||
unsigned& aIndex);
|
||||
|
||||
std::vector<DisplayItemBlueprint> mItems;
|
||||
const bool mVerifyOrder = gfxPrefs::LayoutVerifyRetainDisplayListOrder();
|
||||
};
|
||||
|
||||
// Object representing one display item, with just enough information to
|
||||
@ -264,12 +266,47 @@ DisplayListBlueprint::CompareList(
|
||||
const DisplayItemBlueprintStack& aStackOther) const
|
||||
{
|
||||
bool same = true;
|
||||
unsigned previousFoundIndex = 0;
|
||||
const DisplayItemBlueprint* previousFoundItemBefore = nullptr;
|
||||
const DisplayItemBlueprint* previousFoundItemAfter = nullptr;
|
||||
for (const DisplayItemBlueprint& itemBefore : mItems) {
|
||||
bool found = false;
|
||||
unsigned foundIndex = 0;
|
||||
for (const DisplayItemBlueprint& itemAfter : aOther.mItems) {
|
||||
if (itemBefore.CompareItem(itemAfter, aDiff)) {
|
||||
found = true;
|
||||
|
||||
if (mVerifyOrder) {
|
||||
if (foundIndex < previousFoundIndex) {
|
||||
same = false;
|
||||
aDiff << "\n";
|
||||
if (aStack.Output(aDiff)) {
|
||||
aDiff << " > ";
|
||||
}
|
||||
aDiff << itemBefore.mDescription;
|
||||
aDiff << "\n * Corresponding item in unexpected order: ";
|
||||
if (aStackOther.Output(aDiff)) {
|
||||
aDiff << " > ";
|
||||
}
|
||||
aDiff << itemAfter.mDescription;
|
||||
aDiff << "\n * Was expected after: ";
|
||||
if (aStackOther.Output(aDiff)) {
|
||||
aDiff << " > ";
|
||||
}
|
||||
MOZ_ASSERT(previousFoundItemAfter);
|
||||
aDiff << previousFoundItemAfter->mDescription;
|
||||
aDiff << "\n which corresponds to: ";
|
||||
if (aStack.Output(aDiff)) {
|
||||
aDiff << " > ";
|
||||
}
|
||||
MOZ_ASSERT(previousFoundItemBefore);
|
||||
aDiff << previousFoundItemBefore->mDescription;
|
||||
}
|
||||
previousFoundIndex = foundIndex;
|
||||
previousFoundItemBefore = &itemBefore;
|
||||
previousFoundItemAfter = &itemAfter;
|
||||
}
|
||||
|
||||
const DisplayItemBlueprintStack stack = { &aStack, &itemBefore };
|
||||
const DisplayItemBlueprintStack stackOther = { &aStackOther,
|
||||
&itemAfter };
|
||||
@ -283,6 +320,7 @@ DisplayListBlueprint::CompareList(
|
||||
}
|
||||
break;
|
||||
}
|
||||
++foundIndex;
|
||||
}
|
||||
if (!found) {
|
||||
same = false;
|
||||
|
@ -34,10 +34,10 @@ x { background: lime; height:7px; }
|
||||
document.body.style.display = "none";
|
||||
var justify = [
|
||||
"start",
|
||||
"end",
|
||||
"center",
|
||||
"start",
|
||||
"end",
|
||||
// "end",
|
||||
// "center",
|
||||
// "start",
|
||||
// "end",
|
||||
"start",
|
||||
"start",
|
||||
"start",
|
||||
@ -45,20 +45,20 @@ var justify = [
|
||||
"end",
|
||||
"center",
|
||||
"start",
|
||||
"end",
|
||||
"start",
|
||||
"end safe",
|
||||
"end",
|
||||
// "end",
|
||||
// "start",
|
||||
// "end safe",
|
||||
// "end",
|
||||
"center",
|
||||
// "center",
|
||||
// "end",
|
||||
// "end safe",
|
||||
// "start",
|
||||
"center",
|
||||
"end",
|
||||
"end safe",
|
||||
"start",
|
||||
"center",
|
||||
"end",
|
||||
"end safe",
|
||||
"left",
|
||||
"end",
|
||||
// "end",
|
||||
// "end safe",
|
||||
// "left",
|
||||
// "end",
|
||||
];
|
||||
var cols = [ "0", "1", "2", "3", "8", "9" ];
|
||||
var widths = [ "0", "1", "5", "6" ];
|
||||
@ -89,17 +89,21 @@ for (var j = 0; j < justify.length; ++j) {
|
||||
item.className = "gap";
|
||||
grid.appendChild(item);
|
||||
}
|
||||
if (j < 5) { // The stretch tests.
|
||||
// if (j < 5) { // The stretch tests.
|
||||
if (j < 1) { // The stretch test.
|
||||
if (c == 1)
|
||||
grid.style.background = 'pink'
|
||||
}
|
||||
if (j == 6 && cols[c] == 1) { // The 'end safe' tests.
|
||||
// if (j == 6 && cols[c] == 1) { // The 'safe end' tests.
|
||||
if (j == 2 && cols[c] == 1) { // The 'safe end' tests.
|
||||
if (widths[w] != 0) grid.style.justifyContent = 'end';
|
||||
}
|
||||
if (j == 7 && cols[c] == 1) { // The 'center safe' tests.
|
||||
// if (j == 7 && cols[c] == 1) { // The 'safe center' tests.
|
||||
if (j == 3 && cols[c] == 1) { // The 'safe center' tests.
|
||||
if (widths[w] != 0) grid.style.justifyContent = 'center';
|
||||
}
|
||||
if (j > 15) { // The space-around and space-evenly tests.
|
||||
// if (j > 15) { // The space-around and space-evenly tests.
|
||||
if (j > 7) { // The space-around and space-evenly tests.
|
||||
if (cols[c] == 1) {
|
||||
if (widths[w] == 0) {
|
||||
if (grid.style.justifyContent != 'end') {
|
||||
|
@ -36,31 +36,35 @@ x { background: lime; height:7px; }
|
||||
document.body.style.display = "none";
|
||||
var justify = [
|
||||
"stretch",
|
||||
"stretch end",
|
||||
"stretch center",
|
||||
"stretch end safe",
|
||||
"stretch end unsafe",
|
||||
"start safe",
|
||||
"end safe",
|
||||
"center safe",
|
||||
"start unsafe",
|
||||
"end unsafe",
|
||||
"center unsafe",
|
||||
// FIXME: When https://github.com/w3c/csswg-drafts/issues/1002 is implemented.
|
||||
// "stretch end",
|
||||
// "stretch center",
|
||||
// "stretch safe end",
|
||||
// "stretch unsafe end",
|
||||
"safe start",
|
||||
"safe end",
|
||||
"safe center",
|
||||
"unsafe start",
|
||||
"unsafe end",
|
||||
"unsafe center",
|
||||
"space-between",
|
||||
"space-between end",
|
||||
"space-between start",
|
||||
"space-between end safe",
|
||||
"space-between end unsafe",
|
||||
// FIXME: https://github.com/w3c/csswg-drafts/issues/1002
|
||||
// "space-between end",
|
||||
// "space-between start",
|
||||
// "space-between safe end",
|
||||
// "space-between unsafe end",
|
||||
"space-around",
|
||||
"space-around center",
|
||||
"space-around right",
|
||||
"space-around right safe",
|
||||
"space-around left",
|
||||
// FIXME: https://github.com/w3c/csswg-drafts/issues/1002
|
||||
// "space-around center",
|
||||
// "space-around right",
|
||||
// "space-around safe right",
|
||||
// "space-around left",
|
||||
"space-evenly",
|
||||
"space-evenly flex-end",
|
||||
"space-evenly flex-end safe",
|
||||
"space-evenly flex-start unsafe",
|
||||
"space-evenly right",
|
||||
// FIXME: https://github.com/w3c/csswg-drafts/issues/1002
|
||||
// "space-evenly flex-end",
|
||||
// "space-evenly safe flex-end",
|
||||
// "space-evenly unsafe flex-start",
|
||||
// "space-evenly right",
|
||||
];
|
||||
var cols = [ "0", "1", "2", "3", "8", "9" ];
|
||||
var widths = [ "0", "1", "5", "6" ];
|
||||
|
@ -94,7 +94,7 @@ A<div class="ib">
|
||||
|
||||
<br>
|
||||
|
||||
<x style="position:relative; top:-64px">A</x><div class="ib" style="width:200px;margin-top:32px">
|
||||
<x style="position:relative; top:-64px">A</x><div class="ib" style="width:200px;margin-top:3px">
|
||||
<div class="ib vl" style="height:70px; width:196px;">
|
||||
<span class="a" style="display:block; padding-block-end:15px; height:1px">A<br>B</span>
|
||||
</div>
|
||||
@ -102,9 +102,9 @@ A<div class="ib">
|
||||
<div class="ib vl" style="height:70px; width:196px;">
|
||||
<span class="a" style="display:block; padding-block-end:15px; width:148px; height:1px">A<br>B</span>
|
||||
</div>
|
||||
</div><div class="ib" style="width:200px;position:relative; top:-31px">
|
||||
</div><div class="ib" style="width:200px;position:relative;">
|
||||
<div class="ib vl" style="height:70px; width:196px;">
|
||||
<span class="a" style="display:block; height:-moz-min-content; padding-block-end:15px; width:148px; height:-moz-min-content">A<br>B</span>
|
||||
<span class="a" style="display:block; padding-block-end:15px; width:148px; height:1px">A<br>B</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -45,8 +45,6 @@ span.i { font-size:12px; grid-column:2; }
|
||||
|
||||
.sfb { align-self:baseline; }
|
||||
.slb { align-self:last baseline; align-content:self-end; }
|
||||
.jfb { justify-self:baseline; justify-content:self-end; }
|
||||
.jlb { justify-self:last baseline; justify-content:self-end; }
|
||||
|
||||
.hl { writing-mode: horizontal-tb; direction:ltr; }
|
||||
.hr { writing-mode: horizontal-tb; direction:rtl; }
|
||||
@ -145,29 +143,6 @@ A<div class="igrid sfb">
|
||||
|
||||
<br>
|
||||
|
||||
<!-- TODO: impossible to make a reference due to bug 1166120
|
||||
|
||||
A<div class="igrid" style="grid: auto / 100px;">
|
||||
<span class="jfb a vlr" style="margin:1px 3px 5px 7px">A<br>B</span>
|
||||
</div>
|
||||
<div class="igrid" style="grid: auto / 100px;">
|
||||
<span class="jlb a vlr" style="margin:1px 3px 5px 7px">A<br>B</span>
|
||||
</div>
|
||||
<div class="igrid slb" style="grid: auto / 100px;">
|
||||
<span class="jlb a vlr" style="margin:1px 3px 5px 7px">A<br>B</span>
|
||||
</div>
|
||||
<div class="igrid vl" style="grid: 100px / 50px;">
|
||||
<span class="jlb a" style="margin:1px 3px 5px 7px">A<br>B</span>
|
||||
</div>
|
||||
<div class="igrid slb vl" style="grid: 100px / 50px;">
|
||||
<span class="jfb a" style="margin:1px 3px 5px 7px">A<br>B</span>
|
||||
</div>
|
||||
<div class="igrid sfb vl" style="grid: 100px / 50px;">
|
||||
<span class="jfb a" style="margin:1px 3px 5px 7px">A<br>B</span>
|
||||
</div>
|
||||
|
||||
-->
|
||||
|
||||
<!-- TODO: figure out a way to make a reference for these:
|
||||
|
||||
A<div class="igrid" style="grid-template-columns:200px">
|
||||
@ -206,7 +181,7 @@ A<div class="igrid" style="grid-template-columns:200px">
|
||||
</div>
|
||||
</div><div class="igrid" style="grid-template-columns:200px">
|
||||
<div class="igrid sfb vl" style="grid: 1fr / 7px 13px 50px; grid-row: span 4;">
|
||||
<span class="jfb a" style="margin-block-end:27px; padding-block-end:15px;">A<br>B</span>
|
||||
<span class="a" style="margin-block-end:27px; padding-block-end:15px;">A<br>B</span>
|
||||
<n></n>
|
||||
<n></n>
|
||||
</div>
|
||||
|
@ -52,29 +52,29 @@ body,html { color:black; background:white; font:16px/1 monospace; padding:0; mar
|
||||
<br>
|
||||
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:start unsafe; height:24px; width:10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:unsafe start; height:24px; width:10px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:start safe; height:24px; width:10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:safe start; height:24px; width:10px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:end unsafe; height:24px; width:10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:unsafe end; height:24px; width:10px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:end safe; height:24px; width:10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:safe end; height:24px; width:10px">
|
||||
</div>
|
||||
|
||||
<div class="grid" style="grid: 4px / 10px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:start unsafe; width:24px; height:4px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:unsafe start; width:24px; height:4px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 40px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:start safe; width:24px; height:4px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:safe start; width:24px; height:4px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 40px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:end unsafe; width:24px; height:4px; margin-right:-14px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:unsafe end; width:24px; height:4px; margin-right:-14px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 80px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:end safe; width:24px; height:4px; margin-left:-38px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:safe end; width:24px; height:4px; margin-left:-38px">
|
||||
</div>
|
||||
|
||||
<br>
|
||||
@ -112,29 +112,29 @@ body,html { color:black; background:white; font:16px/1 monospace; padding:0; mar
|
||||
<br>
|
||||
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:start unsafe; height:24px; width:10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:unsafe start; height:24px; width:10px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:start safe; height:24px; width:10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:safe start; height:24px; width:10px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:end unsafe; height:24px; width:10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:unsafe end; height:24px; width:10px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:end safe; height:24px; width:10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:safe end; height:24px; width:10px">
|
||||
</div>
|
||||
|
||||
<div class="grid" style="grid: 4px / 10px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:start unsafe; width:24px; height:4px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:unsafe start; width:24px; height:4px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 40px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:start safe; width:24px; height:4px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:safe start; width:24px; height:4px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 40px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:end unsafe; width:24px; height:4px; margin-right:-14px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:unsafe start; width:24px; height:4px; margin-right:-14px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 80px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:end safe; width:24px; height:4px; margin-left:-38px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:safe end; width:24px; height:4px; margin-left:-38px">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -58,29 +58,29 @@ body,html { color:black; background:white; font:16px/1 monospace; padding:0; mar
|
||||
<br>
|
||||
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:start safe;">
|
||||
<img src="support/lime-2x24.png" style="align-self:safe start;">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:start unsafe;">
|
||||
<img src="support/lime-2x24.png" style="align-self:unsafe start;">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:end safe;">
|
||||
<img src="support/lime-2x24.png" style="align-self:safe end;">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:end unsafe;">
|
||||
<img src="support/lime-2x24.png" style="align-self:unsafe end;">
|
||||
</div>
|
||||
|
||||
<div class="grid" style="grid: 4px / 10px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:start safe">
|
||||
<img src="support/lime-24x2.png" style="justify-self:safe start">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 40px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:start unsafe">
|
||||
<img src="support/lime-24x2.png" style="justify-self:unsafe start">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 40px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:end safe">
|
||||
<img src="support/lime-24x2.png" style="justify-self:safe end">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 80px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:end unsafe">
|
||||
<img src="support/lime-24x2.png" style="justify-self:unsafe end">
|
||||
</div>
|
||||
|
||||
<br>
|
||||
@ -118,29 +118,29 @@ body,html { color:black; background:white; font:16px/1 monospace; padding:0; mar
|
||||
<br>
|
||||
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:start safe;">
|
||||
<img src="support/lime-2x24.png" style="align-self:safe start;">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:start unsafe;">
|
||||
<img src="support/lime-2x24.png" style="align-self:unsafe start;">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:end safe;">
|
||||
<img src="support/lime-2x24.png" style="align-self:safe end;">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:end unsafe;">
|
||||
<img src="support/lime-2x24.png" style="align-self:unsafe end;">
|
||||
</div>
|
||||
|
||||
<div class="grid" style="grid: 4px / 10px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:start safe">
|
||||
<img src="support/lime-24x2.png" style="justify-self:safe start">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 40px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:start unsafe">
|
||||
<img src="support/lime-24x2.png" style="justify-self:unsafe start">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 40px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:end safe">
|
||||
<img src="support/lime-24x2.png" style="justify-self:safe end">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 80px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:end unsafe">
|
||||
<img src="support/lime-24x2.png" style="justify-self:unsafe end">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -52,29 +52,29 @@ body,html { color:black; background:white; font:16px/1 monospace; padding:0; mar
|
||||
<br>
|
||||
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:start unsafe; height:24px; width:10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:unsafe start; height:24px; width:10px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:start safe; height:24px; width:10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:safe start; height:24px; width:10px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:end unsafe; height:24px; width:10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:unsafe end; height:24px; width:10px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:end safe; height:24px; width:10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:safe end; height:24px; width:10px">
|
||||
</div>
|
||||
|
||||
<div class="grid" style="grid: 4px / 10px; width:24px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:start unsafe; width:10px; height:4px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:unsafe start; width:10px; height:4px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 40px; width:24px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:start safe; width:10px; height:4px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:safe start; width:10px; height:4px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 40px; width:24px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:end unsafe; width:10px; height:4px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:unsafe end; width:10px; height:4px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 80px; width:24px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:end safe; width:10px; height:4px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:safe end; width:10px; height:4px">
|
||||
</div>
|
||||
|
||||
<br>
|
||||
@ -112,29 +112,29 @@ body,html { color:black; background:white; font:16px/1 monospace; padding:0; mar
|
||||
<br>
|
||||
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:start unsafe; height:24px; width:10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:unsafe start; height:24px; width:10px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:start safe; height:24px; width:10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:safe start; height:24px; width:10px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:end unsafe; height:24px; width:10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:unsafe end; height:24px; width:10px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 96px / 10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:end safe; height:24px; width:10px">
|
||||
<img src="support/lime-2x24.png" style="align-self:safe end; height:24px; width:10px">
|
||||
</div>
|
||||
|
||||
<div class="grid" style="grid: 4px / 10px; width:24px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:start unsafe; width:10px; height:4px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 40px; width:24px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:start safe; width:10px; height:4px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:safe start; width:10px; height:4px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 40px; width:24px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:end unsafe; width:10px; height:4px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:unsafe end; width:10px; height:4px">
|
||||
</div>
|
||||
<div class="grid" style="grid: 4px / 10px; margin-left: 80px; width:24px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:end safe; width:10px; height:4px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:safe end; width:10px; height:4px">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -54,29 +54,29 @@ body,html { color:black; background:white; font:16px/1 monospace; padding:0; mar
|
||||
<br>
|
||||
|
||||
<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
|
||||
<img src="support/lime-2x24.png" style="align-self:start safe;">
|
||||
<img src="support/lime-2x24.png" style="align-self:safe start;">
|
||||
</div>
|
||||
<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
|
||||
<img src="support/lime-2x24.png" style="align-self:start unsafe;">
|
||||
<img src="support/lime-2x24.png" style="align-self:unsafe start;">
|
||||
</div>
|
||||
<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
|
||||
<img src="support/lime-2x24.png" style="align-self:end safe;">
|
||||
<img src="support/lime-2x24.png" style="align-self:safe end;">
|
||||
</div>
|
||||
<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
|
||||
<img src="support/lime-2x24.png" style="align-self:end unsafe;">
|
||||
<img src="support/lime-2x24.png" style="align-self:unsafe end;">
|
||||
</div>
|
||||
|
||||
<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px)">
|
||||
<img src="support/lime-24x2.png" style="justify-self:start safe">
|
||||
<img src="support/lime-24x2.png" style="justify-self:safe start">
|
||||
</div>
|
||||
<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px); margin-left: 40px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:start unsafe">
|
||||
<img src="support/lime-24x2.png" style="justify-self:unsafe start">
|
||||
</div>
|
||||
<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px); margin-left: 40px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:end safe">
|
||||
<img src="support/lime-24x2.png" style="justify-self:safe end">
|
||||
</div>
|
||||
<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px); margin-left: 80px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:end unsafe">
|
||||
<img src="support/lime-24x2.png" style="justify-self:unsafe end">
|
||||
</div>
|
||||
|
||||
<br>
|
||||
@ -114,29 +114,29 @@ body,html { color:black; background:white; font:16px/1 monospace; padding:0; mar
|
||||
<br>
|
||||
|
||||
<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
|
||||
<img src="support/lime-2x24.png" style="align-self:start safe;">
|
||||
<img src="support/lime-2x24.png" style="align-self:safe start;">
|
||||
</div>
|
||||
<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
|
||||
<img src="support/lime-2x24.png" style="align-self:start unsafe;">
|
||||
<img src="support/lime-2x24.png" style="align-self:unsafe start;">
|
||||
</div>
|
||||
<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
|
||||
<img src="support/lime-2x24.png" style="align-self:end safe;">
|
||||
<img src="support/lime-2x24.png" style="align-self:safe end;">
|
||||
</div>
|
||||
<div class="grid" style="grid: minmax(auto, 96px) / minmax(auto, 10px)">
|
||||
<img src="support/lime-2x24.png" style="align-self:end unsafe;">
|
||||
<img src="support/lime-2x24.png" style="align-self:unsafe end;">
|
||||
</div>
|
||||
|
||||
<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px)">
|
||||
<img src="support/lime-24x2.png" style="justify-self:start safe">
|
||||
<img src="support/lime-24x2.png" style="justify-self:safe start">
|
||||
</div>
|
||||
<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px); margin-left: 40px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:start unsafe">
|
||||
<img src="support/lime-24x2.png" style="justify-self:unsafe start">
|
||||
</div>
|
||||
<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px); margin-left: 40px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:end safe">
|
||||
<img src="support/lime-24x2.png" style="justify-self:safe end">
|
||||
</div>
|
||||
<div class="grid" style="grid: minmax(auto, 4px) / minmax(auto, 10px); margin-left: 80px">
|
||||
<img src="support/lime-24x2.png" style="justify-self:end unsafe">
|
||||
<img src="support/lime-24x2.png" style="justify-self:unsafe end">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -30,8 +30,8 @@ body,html { color:black; background:white; font:16px/1 monospace; padding:0; mar
|
||||
.h .grid > * {
|
||||
min-height: 0;
|
||||
max-height: 100px;
|
||||
justify-self:center safe;
|
||||
align-self:center safe;
|
||||
justify-self: safe center;
|
||||
align-self: safe center;
|
||||
}
|
||||
.h > .grid { grid: 7px 102px 3px / 7px 70px 3px; grid-gap: 5px;}
|
||||
.h > .grid.c2 { grid: 7px 30px 3px / 7px 70px 3px; grid-gap: 5px;}
|
||||
|
@ -72,15 +72,6 @@ span:nth-child(4) { font-size:32px; }
|
||||
|
||||
<br clear="all">
|
||||
|
||||
<div class="grid vl"><span class="fb vl">A</span><span class="fb vl">A</span><span class="fb vl">A</span><span class="fb vl">A</span></div>
|
||||
<div class="grid vl"><span class="fb vl pbe">A</span><span class="fb vl">A</span><span class="fb vl">A</span><span class="fb vl">A</span></div>
|
||||
<div class="grid"><span class="fb">A</span><span class="fb">A</span><span class="fb">A</span><span class="fb">A</span></div>
|
||||
<div class="grid"><span class="fb pbs">A</span><span class="fb">A</span><span class="fb">A</span><span class="fb">A</span></div>
|
||||
<div class="grid"><span class="fb" style="order:99">A</span><span class="fb" style="order:98">A</span><span class="fb" style="order:97">A</span><span class="fb" style="order:96">A</span></div>
|
||||
<div class="grid"><span class="fb pbe" style="order:99;">A</span><span class="fb" style="order:98">A</span><span class="fb" style="order:97">A</span><span class="fb" style="order:96">A</span></div>
|
||||
|
||||
<br clear="all">
|
||||
|
||||
<div><span class="lb hl">A<br>A</span><span class="lb hl">A<br>A</span><span class="lb hl">A<br>A</span><span class="lb hl">A<br>A</span></div>
|
||||
<div><span class="lb hl pbe">A<br>A</span><span class="lb hl">A<br>A</span><span class="lb hl">A<br>A</span><span class="lb hl">A<br>A</span></div>
|
||||
<div class="vl"><span class="lb">A<br>A</span><span class="lb">A<br>A</span><span class="lb">A<br>A</span><span class="lb">A<br>A</span></div>
|
||||
|
@ -43,9 +43,6 @@ span:nth-child(4) { font-size:32px; }
|
||||
.fb { align-self:baseline; }
|
||||
.lb { align-self:last baseline; }
|
||||
|
||||
.jfb { justify-self:baseline; }
|
||||
.jlb { justify-self:last baseline; }
|
||||
|
||||
.hl { writing-mode: horizontal-tb; direction:ltr; }
|
||||
.hr { writing-mode: horizontal-tb; direction:rtl; }
|
||||
.vl { writing-mode: vertical-lr; text-orientation: sideways; }
|
||||
@ -75,15 +72,6 @@ span:nth-child(4) { font-size:32px; }
|
||||
|
||||
<br clear="all">
|
||||
|
||||
<div class="grid c"><span class="jfb vl">A</span><span class="jfb vl">A</span><span class="jfb vl">A</span><span class="jfb vl">A</span></div>
|
||||
<div class="grid c"><span class="jfb vl pbe">A</span><span class="jfb vl">A</span><span class="jfb vl">A</span><span class="jfb vl">A</span></div>
|
||||
<div class="grid c vl"><span class="jfb hl">A</span><span class="jfb hl">A</span><span class="jfb hl">A</span><span class="jfb hl">A</span></div>
|
||||
<div class="grid c vl"><span class="jfb hl pbs">A</span><span class="jfb hl">A</span><span class="jfb hl">A</span><span class="jfb hl">A</span></div>
|
||||
<div class="grid c vr"><span class="jfb hl">A</span><span class="jfb hl">A</span><span class="jfb hl">A</span><span class="jfb hl">A</span></div>
|
||||
<div class="grid c vr"><span class="jfb hl pbe">A</span><span class="jfb hl">A</span><span class="jfb hl">A</span><span class="jfb hl">A</span></div>
|
||||
|
||||
<br clear="all">
|
||||
|
||||
<div class="grid"><span class="lb hl">A<br>A</span><span class="lb hl">A<br>A</span><span class="lb hl">A<br>A</span><span class="lb hl">A<br>A</span></div>
|
||||
<div class="grid"><span class="lb hl pbe">A<br>A</span><span class="lb hl">A<br>A</span><span class="lb hl">A<br>A</span><span class="lb hl">A<br>A</span></div>
|
||||
<div class="grid vl"><span class="lb">A<br>A</span><span class="lb">A<br>A</span><span class="lb">A<br>A</span><span class="lb">A<br>A</span></div>
|
||||
|
@ -34,10 +34,10 @@ x { background: lime; height:7px; }
|
||||
document.body.style.display = "none";
|
||||
var justify = [
|
||||
"start",
|
||||
"end",
|
||||
"center",
|
||||
"start",
|
||||
"end",
|
||||
// "end",
|
||||
// "center",
|
||||
// "start",
|
||||
// "end",
|
||||
"start",
|
||||
"start",
|
||||
"start",
|
||||
@ -45,20 +45,20 @@ var justify = [
|
||||
"end",
|
||||
"center",
|
||||
"start",
|
||||
"end",
|
||||
"start",
|
||||
"end safe",
|
||||
"end",
|
||||
// "end",
|
||||
// "start",
|
||||
// "end safe",
|
||||
// "end",
|
||||
"center",
|
||||
// "center",
|
||||
// "end",
|
||||
// "end safe",
|
||||
// "start",
|
||||
"center",
|
||||
"end",
|
||||
"end safe",
|
||||
"start",
|
||||
"center",
|
||||
"end",
|
||||
"end safe",
|
||||
"left",
|
||||
"end",
|
||||
// "end",
|
||||
// "end safe",
|
||||
// "left",
|
||||
// "end",
|
||||
];
|
||||
var cols = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ];
|
||||
var widths = [ "0", "1", "2", "3", "4", "5", "6" ];
|
||||
@ -81,17 +81,21 @@ for (var j = 0; j < justify.length; ++j) {
|
||||
for (var x = 0; x < cols[c]; ++x) {
|
||||
grid.appendChild(document.createElement('x'));
|
||||
}
|
||||
if (j < 5) { // The stretch tests.
|
||||
// if (j < 5) { // The stretch tests.
|
||||
if (j < 1) { // The stretch test.
|
||||
if (c == 1)
|
||||
grid.style.background = 'pink'
|
||||
}
|
||||
if (j == 6 && cols[c] == 1) { // The 'end safe' tests.
|
||||
// if (j == 6 && cols[c] == 1) { // The 'safe end' tests.
|
||||
if (j == 2 && cols[c] == 1) { // The 'safe end' tests.
|
||||
if (widths[w] != 0) grid.style.justifyContent = 'end';
|
||||
}
|
||||
if (j == 7 && cols[c] == 1) { // The 'center safe' tests.
|
||||
// if (j == 7 && cols[c] == 1) { // The 'safe center' tests.
|
||||
if (j == 3 && cols[c] == 1) { // The 'safe center' tests.
|
||||
if (widths[w] != 0) grid.style.justifyContent = 'center';
|
||||
}
|
||||
if (j > 15) { // The space-around and space-evenly tests.
|
||||
// if (j > 15) { // The space-around and space-evenly tests.
|
||||
if (j > 7) { // The space-around and space-evenly tests.
|
||||
if (cols[c] == 1) {
|
||||
if (widths[w] == 0) {
|
||||
if (grid.style.justifyContent != 'end') {
|
||||
|
@ -36,31 +36,35 @@ x { background: lime; height:7px; }
|
||||
document.body.style.display = "none";
|
||||
var justify = [
|
||||
"stretch",
|
||||
"stretch end",
|
||||
"stretch center",
|
||||
"stretch end safe",
|
||||
"stretch end unsafe",
|
||||
"start safe",
|
||||
"end safe",
|
||||
"center safe",
|
||||
"start unsafe",
|
||||
"end unsafe",
|
||||
"center unsafe",
|
||||
// FIXME: When https://github.com/w3c/csswg-drafts/issues/1002 is implemented.
|
||||
// "stretch end",
|
||||
// "stretch center",
|
||||
// "stretch safe end",
|
||||
// "stretch unsafe end",
|
||||
"safe start",
|
||||
"safe end",
|
||||
"safe center",
|
||||
"unsafe start",
|
||||
"unsafe end",
|
||||
"unsafe center",
|
||||
"space-between",
|
||||
"space-between end",
|
||||
"space-between start",
|
||||
"space-between end safe",
|
||||
"space-between end unsafe",
|
||||
// FIXME: https://github.com/w3c/csswg-drafts/issues/1002
|
||||
// "space-between end",
|
||||
// "space-between start",
|
||||
// "space-between safe end",
|
||||
// "space-between unsafe end",
|
||||
"space-around",
|
||||
"space-around center",
|
||||
"space-around right",
|
||||
"space-around right safe",
|
||||
"space-around left",
|
||||
// FIXME: https://github.com/w3c/csswg-drafts/issues/1002
|
||||
// "space-around center",
|
||||
// "space-around right",
|
||||
// "space-around safe right",
|
||||
// "space-around left",
|
||||
"space-evenly",
|
||||
"space-evenly flex-end",
|
||||
"space-evenly flex-end safe",
|
||||
"space-evenly flex-start unsafe",
|
||||
"space-evenly right",
|
||||
// FIXME: https://github.com/w3c/csswg-drafts/issues/1002
|
||||
// "space-evenly flex-end",
|
||||
// "space-evenly safe flex-end",
|
||||
// "space-evenly unsafe flex-start",
|
||||
// "space-evenly right",
|
||||
];
|
||||
var cols = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ];
|
||||
var widths = [ "0", "1", "2", "3", "4", "5", "6" ];
|
||||
|
@ -34,10 +34,10 @@ x { background: lime; width:7px; }
|
||||
document.body.style.display = "none";
|
||||
var align = [
|
||||
"start",
|
||||
"end",
|
||||
"center",
|
||||
"start",
|
||||
"end",
|
||||
// "end",
|
||||
// "center",
|
||||
// "start",
|
||||
// "end",
|
||||
"start",
|
||||
"start",
|
||||
"start",
|
||||
@ -45,16 +45,16 @@ var align = [
|
||||
"end",
|
||||
"center",
|
||||
"start",
|
||||
"end",
|
||||
"start",
|
||||
"end safe",
|
||||
// "end",
|
||||
// "start",
|
||||
// "safe end",
|
||||
"center",
|
||||
// "center",
|
||||
// "start",
|
||||
// "safe end",
|
||||
// "start",
|
||||
"center",
|
||||
"start",
|
||||
"end safe",
|
||||
"start",
|
||||
"center",
|
||||
"end",
|
||||
// "end",
|
||||
];
|
||||
var rows = [ "0", "1", "2", "3", "8", "9" ];
|
||||
var heights = [ "auto", "0", "1", "5", "6" ];
|
||||
@ -85,17 +85,21 @@ for (var j = 0; j < align.length; ++j) {
|
||||
item.className = "gap";
|
||||
grid.appendChild(item);
|
||||
}
|
||||
if (j < 5) { // The stretch tests.
|
||||
// if (j < 5) { // The stretch tests.
|
||||
if (j < 1) { // The stretch test.
|
||||
if (c == 1)
|
||||
grid.style.background = 'pink'
|
||||
}
|
||||
if (j == 6 && rows[c] == 1) { // The 'end safe' tests.
|
||||
// if (j == 6 && rows[c] == 1) { // The 'safe end' tests.
|
||||
if (j == 2 && rows[c] == 1) { // The 'safe end' tests.
|
||||
if (heights[w] != 0) grid.style.alignContent = 'end';
|
||||
}
|
||||
if (j == 7 && rows[c] == 1) { // The 'center safe' tests.
|
||||
// if (j == 7 && rows[c] == 1) { // The 'safe center' tests.
|
||||
if (j == 3 && rows[c] == 1) { // The 'safe center' tests.
|
||||
if (heights[w] != 0) grid.style.alignContent = 'center';
|
||||
}
|
||||
if (j > 15) { // The space-around and space-evenly tests.
|
||||
// if (j > 15) { // The space-around and space-evenly tests.
|
||||
if (j > 7) { // The space-around and space-evenly tests.
|
||||
if (rows[c] == 1) {
|
||||
if (heights[w] == 0) {
|
||||
if (grid.style.alignContent != 'end') {
|
||||
|
@ -36,27 +36,30 @@ x { background: lime; width:7px; }
|
||||
document.body.style.display = "none";
|
||||
var align = [
|
||||
"stretch",
|
||||
"stretch end",
|
||||
"stretch center",
|
||||
"stretch end safe",
|
||||
"stretch end unsafe",
|
||||
"start safe",
|
||||
"end safe",
|
||||
"center safe",
|
||||
"start unsafe",
|
||||
"end unsafe",
|
||||
"center unsafe",
|
||||
// FIXME: When https://github.com/w3c/csswg-drafts/issues/1002 is implemented.
|
||||
// "stretch end",
|
||||
// "stretch center",
|
||||
// "stretch safe end",
|
||||
// "stretch unsafe end",
|
||||
"safe start",
|
||||
"safe end",
|
||||
"safe center",
|
||||
"unsafe start",
|
||||
"unsafe end",
|
||||
"unsafe center",
|
||||
"space-between",
|
||||
"space-between end",
|
||||
"space-between start",
|
||||
"space-between end safe",
|
||||
// FIXME: https://github.com/w3c/csswg-drafts/issues/1002
|
||||
// "space-between end",
|
||||
// "space-between start",
|
||||
// "space-between safe end",
|
||||
"space-around",
|
||||
"space-around center",
|
||||
"space-around right",
|
||||
"space-around right safe",
|
||||
"space-around left",
|
||||
// FIXME: https://github.com/w3c/csswg-drafts/issues/1002
|
||||
// "space-around center",
|
||||
// "space-around right",
|
||||
// "space-around safe right",
|
||||
// "space-around left",
|
||||
"space-evenly",
|
||||
"space-evenly end",
|
||||
// "space-evenly end",
|
||||
];
|
||||
var rows = [ "0", "1", "2", "3", "8", "9" ];
|
||||
var heights = [ "auto", "0", "1", "5", "6" ];
|
||||
|
@ -36,10 +36,10 @@ x { background: lime; height:7px; }
|
||||
document.body.style.display = "none";
|
||||
var align = [
|
||||
"start",
|
||||
"end",
|
||||
"center",
|
||||
"start",
|
||||
"end",
|
||||
// "end",
|
||||
// "center",
|
||||
// "start",
|
||||
// "end",
|
||||
"start",
|
||||
"start",
|
||||
"start",
|
||||
@ -47,16 +47,16 @@ var align = [
|
||||
"end",
|
||||
"center",
|
||||
"start",
|
||||
"end",
|
||||
"start",
|
||||
"end safe",
|
||||
// "end",
|
||||
// "start",
|
||||
// "safe end",
|
||||
"center",
|
||||
// "center",
|
||||
// "start",
|
||||
// "safe end",
|
||||
// "start",
|
||||
"center",
|
||||
"start",
|
||||
"end safe",
|
||||
"start",
|
||||
"center",
|
||||
"end",
|
||||
// "end",
|
||||
];
|
||||
var rows = [ "0", "1", "2", "3", "8", "9" ];
|
||||
var heights = [ "auto", "0", "1", "5", "6" ];
|
||||
@ -87,17 +87,21 @@ for (var j = 0; j < align.length; ++j) {
|
||||
item.className = "gap";
|
||||
grid.appendChild(item);
|
||||
}
|
||||
if (j < 5) { // The stretch tests.
|
||||
// if (j < 5) { // The stretch tests.
|
||||
if (j < 1) { // The stretch test.
|
||||
if (c == 1)
|
||||
grid.style.background = 'pink'
|
||||
}
|
||||
if (j == 6 && rows[c] == 1) { // The 'end safe' tests.
|
||||
// if (j == 6 && rows[c] == 1) { // The 'safe end' tests.
|
||||
if (j == 2 && rows[c] == 1) { // The 'safe end' tests.
|
||||
if (heights[w] != 0) grid.style.alignContent = 'end';
|
||||
}
|
||||
if (j == 7 && rows[c] == 1) { // The 'center safe' tests.
|
||||
// if (j == 7 && rows[c] == 1) { // The 'safe center' tests.
|
||||
if (j == 3 && rows[c] == 1) { // The 'safe center' tests.
|
||||
if (heights[w] != 0) grid.style.alignContent = 'center';
|
||||
}
|
||||
if (j > 15) { // The space-around and space-evenly tests.
|
||||
// if (j > 15) { // The space-around and space-evenly tests.
|
||||
if (j > 7) { // The space-around and space-evenly tests.
|
||||
if (rows[c] == 1) {
|
||||
if (heights[w] == 0) {
|
||||
if (grid.style.alignContent != 'end') {
|
||||
|
@ -38,27 +38,30 @@ x { background: lime; height:7px; }
|
||||
document.body.style.display = "none";
|
||||
var align = [
|
||||
"stretch",
|
||||
"stretch end",
|
||||
"stretch center",
|
||||
"stretch end safe",
|
||||
"stretch end unsafe",
|
||||
"start safe",
|
||||
"end safe",
|
||||
"center safe",
|
||||
"start unsafe",
|
||||
"end unsafe",
|
||||
"center unsafe",
|
||||
// FIXME: When https://github.com/w3c/csswg-drafts/issues/1002 is implemented.
|
||||
// "stretch end",
|
||||
// "stretch center",
|
||||
// "stretch safe end",
|
||||
// "stretch unsafe end",
|
||||
"safe start",
|
||||
"safe end",
|
||||
"safe center",
|
||||
"unsafe start",
|
||||
"unsafe end",
|
||||
"unsafe center",
|
||||
"space-between",
|
||||
"space-between end",
|
||||
"space-between start",
|
||||
"space-between end safe",
|
||||
// FIXME: https://github.com/w3c/csswg-drafts/issues/1002
|
||||
// "space-between end",
|
||||
// "space-between start",
|
||||
// "space-between safe end",
|
||||
"space-around",
|
||||
"space-around center",
|
||||
"space-around right",
|
||||
"space-around right safe",
|
||||
"space-around left",
|
||||
// FIXME: https://github.com/w3c/csswg-drafts/issues/1002
|
||||
// "space-around center",
|
||||
// "space-around right",
|
||||
// "space-around safe right",
|
||||
// "space-around left",
|
||||
"space-evenly",
|
||||
"space-evenly end",
|
||||
// "space-evenly end",
|
||||
];
|
||||
var rows = [ "0", "1", "2", "3", "8", "9" ];
|
||||
var heights = [ "auto", "0", "1", "5", "6" ];
|
||||
|
@ -36,10 +36,10 @@ x { background: lime; height:7px; }
|
||||
document.body.style.display = "none";
|
||||
var align = [
|
||||
"start",
|
||||
"end",
|
||||
"center",
|
||||
"start",
|
||||
"end",
|
||||
// "end",
|
||||
// "center",
|
||||
// "start",
|
||||
// "end",
|
||||
"start",
|
||||
"start",
|
||||
"start",
|
||||
@ -47,16 +47,16 @@ var align = [
|
||||
"end",
|
||||
"center",
|
||||
"start",
|
||||
"end",
|
||||
"start",
|
||||
"end safe",
|
||||
// "end",
|
||||
// "start",
|
||||
// "safe end",
|
||||
"center",
|
||||
// "center",
|
||||
// "start",
|
||||
// "safe end",
|
||||
// "start",
|
||||
"center",
|
||||
"start",
|
||||
"end safe",
|
||||
"start",
|
||||
"center",
|
||||
"end",
|
||||
// "end",
|
||||
];
|
||||
var rows = [ "0", "1", "2", "3", "8", "9" ];
|
||||
var heights = [ "auto", "0", "1", "5", "6" ];
|
||||
@ -87,17 +87,21 @@ for (var j = 0; j < align.length; ++j) {
|
||||
item.className = "gap";
|
||||
grid.appendChild(item);
|
||||
}
|
||||
if (j < 5) { // The stretch tests.
|
||||
// if (j < 5) { // The stretch tests.
|
||||
if (j < 1) { // The stretch test.
|
||||
if (c == 1)
|
||||
grid.style.background = 'pink'
|
||||
}
|
||||
if (j == 6 && rows[c] == 1) { // The 'end safe' tests.
|
||||
// if (j == 6 && rows[c] == 1) { // The 'safe end' tests.
|
||||
if (j == 2 && rows[c] == 1) { // The 'safe end' tests.
|
||||
if (heights[w] != 0) grid.style.alignContent = 'end';
|
||||
}
|
||||
if (j == 7 && rows[c] == 1) { // The 'center safe' tests.
|
||||
// if (j == 7 && rows[c] == 1) { // The 'safe center' tests.
|
||||
if (j == 3 && rows[c] == 1) { // The 'safe center' tests.
|
||||
if (heights[w] != 0) grid.style.alignContent = 'center';
|
||||
}
|
||||
if (j > 15) { // The space-around and space-evenly tests.
|
||||
// if (j > 15) { // The space-around and space-evenly tests.
|
||||
if (j > 7) { // The space-around and space-evenly tests.
|
||||
if (rows[c] == 1) {
|
||||
if (heights[w] != 0) {
|
||||
grid.style.alignContent = 'center';
|
||||
|
@ -38,27 +38,30 @@ x { background: lime; height:7px; }
|
||||
document.body.style.display = "none";
|
||||
var align = [
|
||||
"stretch",
|
||||
"stretch end",
|
||||
"stretch center",
|
||||
"stretch end safe",
|
||||
"stretch end unsafe",
|
||||
"start safe",
|
||||
"end safe",
|
||||
"center safe",
|
||||
"start unsafe",
|
||||
"end unsafe",
|
||||
"center unsafe",
|
||||
// FIXME: When https://github.com/w3c/csswg-drafts/issues/1002 is implemented.
|
||||
// "stretch end",
|
||||
// "stretch center",
|
||||
// "stretch safe end",
|
||||
// "stretch unsafe end",
|
||||
"safe start",
|
||||
"safe end",
|
||||
"safe center",
|
||||
"unsafe start",
|
||||
"unsafe end",
|
||||
"unsafe center",
|
||||
"space-between",
|
||||
"space-between end",
|
||||
"space-between start",
|
||||
"space-between end safe",
|
||||
// FIXME: https://github.com/w3c/csswg-drafts/issues/1002
|
||||
// "space-between end",
|
||||
// "space-between start",
|
||||
// "space-between safe end",
|
||||
"space-around",
|
||||
"space-around center",
|
||||
"space-around right",
|
||||
"space-around right safe",
|
||||
"space-around left",
|
||||
// FIXME: https://github.com/w3c/csswg-drafts/issues/1002
|
||||
// "space-around center",
|
||||
// "space-around right",
|
||||
// "space-around safe right",
|
||||
// "space-around left",
|
||||
"space-evenly",
|
||||
"space-evenly end",
|
||||
// "space-evenly end",
|
||||
];
|
||||
var rows = [ "0", "1", "2", "3", "8", "9" ];
|
||||
var heights = [ "auto", "0", "1", "5", "6" ];
|
||||
|
@ -67,8 +67,6 @@
|
||||
<!-- <content-position>, part 2: -->
|
||||
<div class="container"><div class="alignStart"><!--flex-start--></div></div>
|
||||
<div class="container"><div class="alignEnd"><!--flex-end--></div></div>
|
||||
<div class="container"><div class="alignStart"><!--left--></div></div>
|
||||
<div class="container"><div class="alignStart"><!--right--></div></div>
|
||||
<br>
|
||||
</div>
|
||||
<div class="small">
|
||||
@ -95,8 +93,6 @@
|
||||
<!-- <content-position>, part 2: -->
|
||||
<div class="container"><div class="alignStart"><!--flex-start--></div></div>
|
||||
<div class="container"><div class="alignEnd"><!--flex-end--></div></div>
|
||||
<div class="container"><div class="alignStart"><!--left--></div></div>
|
||||
<div class="container"><div class="alignStart"><!--right--></div></div>
|
||||
<br>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -70,8 +70,6 @@
|
||||
<!-- <content-position>, part 2 -->
|
||||
<div class="container" style="align-content: flex-start"><div></div></div>
|
||||
<div class="container" style="align-content: flex-end"><div></div></div>
|
||||
<div class="container" style="align-content: left"><div></div></div>
|
||||
<div class="container" style="align-content: right"><div></div></div>
|
||||
<br>
|
||||
</div>
|
||||
<div class="small">
|
||||
@ -98,8 +96,6 @@
|
||||
<!-- <content-position>, part 2 -->
|
||||
<div class="container" style="align-content: flex-start"><div></div></div>
|
||||
<div class="container" style="align-content: flex-end"><div></div></div>
|
||||
<div class="container" style="align-content: left"><div></div></div>
|
||||
<div class="container" style="align-content: right"><div></div></div>
|
||||
<br>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -67,8 +67,6 @@
|
||||
<!-- <content-position>, part 2: -->
|
||||
<div class="container"><div class="alignEnd"><!--flex-start--></div></div>
|
||||
<div class="container"><div class="alignStart"><!--flex-end--></div></div>
|
||||
<div class="container"><div class="alignStart"><!--left--></div></div>
|
||||
<div class="container"><div class="alignStart"><!--right--></div></div>
|
||||
<br>
|
||||
</div>
|
||||
<div class="small">
|
||||
@ -95,8 +93,6 @@
|
||||
<!-- <content-position>, part 2: -->
|
||||
<div class="container"><div class="alignEnd"><!--flex-start--></div></div>
|
||||
<div class="container"><div class="alignStart"><!--flex-end--></div></div>
|
||||
<div class="container"><div class="alignStart"><!--left--></div></div>
|
||||
<div class="container"><div class="alignStart"><!--right--></div></div>
|
||||
<br>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -70,8 +70,6 @@
|
||||
<!-- <content-position>, part 2 -->
|
||||
<div class="container" style="align-content: flex-start"><div></div></div>
|
||||
<div class="container" style="align-content: flex-end"><div></div></div>
|
||||
<div class="container" style="align-content: left"><div></div></div>
|
||||
<div class="container" style="align-content: right"><div></div></div>
|
||||
<br>
|
||||
</div>
|
||||
<div class="small">
|
||||
@ -98,8 +96,6 @@
|
||||
<!-- <content-position>, part 2 -->
|
||||
<div class="container" style="align-content: flex-start"><div></div></div>
|
||||
<div class="container" style="align-content: flex-end"><div></div></div>
|
||||
<div class="container" style="align-content: left"><div></div></div>
|
||||
<div class="container" style="align-content: right"><div></div></div>
|
||||
<br>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -70,8 +70,6 @@
|
||||
<!-- <content-position>, part 2: -->
|
||||
<div class="container"><div class="alignStart"><!--flex-start--></div></div>
|
||||
<div class="container"><div class="alignEnd"><!--flex-end--></div></div>
|
||||
<div class="container"><div class="alignStart"><!--left--></div></div>
|
||||
<div class="container"><div class="alignStart"><!--right--></div></div>
|
||||
<br>
|
||||
</div>
|
||||
<div class="small">
|
||||
@ -98,8 +96,6 @@
|
||||
<!-- <content-position>, part 2: -->
|
||||
<div class="container"><div class="alignStart"><!--flex-start--></div></div>
|
||||
<div class="container"><div class="alignEnd"><!--flex-end--></div></div>
|
||||
<div class="container"><div class="alignStart"><!--left--></div></div>
|
||||
<div class="container"><div class="alignStart"><!--right--></div></div>
|
||||
<br>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -70,8 +70,6 @@
|
||||
<!-- <content-position>, part 2 -->
|
||||
<div class="container" style="align-content: flex-start"><div></div></div>
|
||||
<div class="container" style="align-content: flex-end"><div></div></div>
|
||||
<div class="container" style="align-content: left"><div></div></div>
|
||||
<div class="container" style="align-content: right"><div></div></div>
|
||||
<br>
|
||||
</div>
|
||||
<div class="small">
|
||||
@ -98,8 +96,6 @@
|
||||
<!-- <content-position>, part 2 -->
|
||||
<div class="container" style="align-content: flex-start"><div></div></div>
|
||||
<div class="container" style="align-content: flex-end"><div></div></div>
|
||||
<div class="container" style="align-content: left"><div></div></div>
|
||||
<div class="container" style="align-content: right"><div></div></div>
|
||||
<br>
|
||||
</div>
|
||||
</body>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user