Merge mozilla-central to inbound. a=merge CLOSED TREE

This commit is contained in:
Gurzau Raul 2018-01-30 12:12:34 +02:00
commit afe10a4af5
444 changed files with 2923 additions and 9415 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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",

View File

@ -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]

View File

@ -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);
});

View File

@ -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);
});

View File

@ -0,0 +1,5 @@
{
"policies": {
"display_bookmarks_toolbar": true
}
}

View File

@ -0,0 +1,5 @@
{
"policies": {
"display_menu_bar": true
}
}

View File

@ -188,7 +188,7 @@ this.MigratorPrototype = {
* OVERRIDE IF AND ONLY IF your migrator supports importing the homepage.
* @see nsIBrowserProfileMigrator
*/
get sourceHomePageURL() {
getSourceHomePageURL() {
return "";
},

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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,
};
}());

View File

@ -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}`);

View File

@ -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", {

View File

@ -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() {

View File

@ -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>

View File

@ -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);

View File

@ -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();
},

View File

@ -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;
}
}
},

View File

@ -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);
},

View File

@ -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);
},
};

View File

@ -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",
);
}
);

View File

@ -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",
);
}
);

View File

@ -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");
}
);

View File

@ -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}/;

View File

@ -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

View File

@ -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;

View File

@ -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}}

View File

@ -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']:

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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 #

View File

@ -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.

View File

@ -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()
{

View File

@ -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;
}

View File

@ -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 {

View File

@ -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

View File

@ -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
*

View File

@ -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):

View File

@ -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")

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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() ||

View File

@ -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>

View File

@ -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

View File

@ -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;
}
{

View File

@ -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;

View File

@ -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;
};

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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()
{

View File

@ -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;

View File

@ -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;

View File

@ -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() {

View File

@ -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;

View File

@ -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') {

View File

@ -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" ];

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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;}

View File

@ -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>

View File

@ -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>

View File

@ -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') {

View File

@ -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" ];

View File

@ -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') {

View File

@ -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" ];

View File

@ -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') {

View File

@ -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" ];

View File

@ -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';

View File

@ -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" ];

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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