зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound
This commit is contained in:
Коммит
2cf79ec292
|
@ -22,6 +22,9 @@ with Files("tests/unit/test_distribution.js"):
|
|||
with Files("safebrowsing/**"):
|
||||
BUG_COMPONENT = ("Toolkit", "Safe Browsing")
|
||||
|
||||
with Files('controlcenter/**'):
|
||||
BUG_COMPONENT = ('Firefox', 'General')
|
||||
|
||||
|
||||
DIRS += [
|
||||
'about',
|
||||
|
@ -77,9 +80,3 @@ BROWSER_CHROME_MANIFESTS += [
|
|||
XPCSHELL_TESTS_MANIFESTS += [
|
||||
'tests/unit/xpcshell.ini'
|
||||
]
|
||||
|
||||
with Files('safebrowsing/*'):
|
||||
BUG_COMPONENT = ('Toolkit', 'Phishing Protection')
|
||||
|
||||
with Files('controlcenter/**'):
|
||||
BUG_COMPONENT = ('Firefox', 'General')
|
||||
|
|
|
@ -1110,8 +1110,13 @@ this.PlacesUIUtils = {
|
|||
return this.leftPaneQueries;
|
||||
},
|
||||
|
||||
// Get the folder id for the organizer left-pane folder.
|
||||
get leftPaneFolderId() {
|
||||
delete this.leftPaneFolderId;
|
||||
return this.leftPaneFolderId = this.maybeRebuildLeftPane();
|
||||
},
|
||||
|
||||
// Get the folder id for the organizer left-pane folder.
|
||||
maybeRebuildLeftPane() {
|
||||
let leftPaneRoot = -1;
|
||||
let allBookmarksId;
|
||||
|
||||
|
@ -1163,8 +1168,8 @@ this.PlacesUIUtils = {
|
|||
// Returns true if item really exists, false otherwise.
|
||||
function itemExists(aItemId) {
|
||||
try {
|
||||
bs.getItemIndex(aItemId);
|
||||
return true;
|
||||
let index = bs.getItemIndex(aItemId);
|
||||
return index > -1;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1251,8 +1256,7 @@ this.PlacesUIUtils = {
|
|||
safeRemoveItem(leftPaneRoot);
|
||||
} else {
|
||||
// Everything is fine, return the current left pane folder.
|
||||
delete this.leftPaneFolderId;
|
||||
return this.leftPaneFolderId = leftPaneRoot;
|
||||
return leftPaneRoot;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1345,8 +1349,7 @@ this.PlacesUIUtils = {
|
|||
};
|
||||
bs.runInBatchMode(callback, null);
|
||||
|
||||
delete this.leftPaneFolderId;
|
||||
return this.leftPaneFolderId = leftPaneRoot;
|
||||
return leftPaneRoot;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -251,11 +251,7 @@ if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -z "$DEVELOPER_OPTIONS"; then
|
|||
fi
|
||||
|
||||
# bionic in Android < 4.1 doesn't support PIE
|
||||
# On OSX, the linker defaults to building PIE programs when targetting OSX 10.7+,
|
||||
# but not when targetting OSX < 10.7. OSX < 10.7 doesn't support running PIE
|
||||
# programs, so as long as support for OSX 10.6 is kept, we can't build PIE.
|
||||
# Even after dropping 10.6 support, MOZ_PIE would not be useful since it's the
|
||||
# default (and clang says the -pie option is not used).
|
||||
# On OSX, the linker defaults to building PIE programs when targeting OSX 10.7.
|
||||
# On other Unix systems, some file managers (Nautilus) can't start PIE programs
|
||||
if test -n "$gonkdir" && test "$ANDROID_VERSION" -ge 16; then
|
||||
MOZ_PIE=1
|
||||
|
@ -268,7 +264,7 @@ MOZ_ARG_ENABLE_BOOL(pie,
|
|||
MOZ_PIE=1,
|
||||
MOZ_PIE= )
|
||||
|
||||
if test "$GNU_CC" -a -n "$MOZ_PIE"; then
|
||||
if test "$GNU_CC$CLANG_CC" -a -n "$MOZ_PIE"; then
|
||||
AC_MSG_CHECKING([for PIE support])
|
||||
_SAVE_LDFLAGS=$LDFLAGS
|
||||
LDFLAGS="$LDFLAGS -pie"
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1315874
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test SMIL does not trigger CSS Transitions (bug 1315874)</title>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1315874">Mozilla Bug
|
||||
1315874</a>
|
||||
<svg>
|
||||
<rect width="100%" height="100%"
|
||||
style="fill: red; transition: fill 10s" id="rect">
|
||||
<animate attributeName="fill" to="lime" dur="1s" fill="freeze">
|
||||
</rect>
|
||||
</svg>
|
||||
<script type="text/javascript">
|
||||
// Bring SimpleTest's function from opener.
|
||||
if (opener) {
|
||||
var is = opener.is.bind(opener);
|
||||
var ok = opener.ok.bind(opener);
|
||||
function finish() {
|
||||
var o = opener;
|
||||
self.close();
|
||||
o.SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('load', runTests, false);
|
||||
|
||||
var rect = document.getElementById('rect');
|
||||
var svg = document.getElementsByTagName('svg')[0];
|
||||
is(getComputedStyle(rect).fill, 'rgb(255, 0, 0)',
|
||||
'The initial color should be red.');
|
||||
|
||||
function runTests() {
|
||||
waitForFrame().then(function() {
|
||||
svg.setCurrentTime(1);
|
||||
ok(getComputedStyle(rect).fill, 'rgb(0, 255, 0)',
|
||||
'The end color should be lime.');
|
||||
|
||||
return waitForAnimationFrames(2);
|
||||
}).then(function() {
|
||||
var anim = document.getAnimations()[0];
|
||||
ok(!anim, 'Transition should not be created by restyling for SMIL');
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
// Utility methods from testcommon.js
|
||||
// For detail, see dom/animation/test/testcommon.js.
|
||||
|
||||
function waitForFrame() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
requestAnimationFrame(function(time) {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function waitForAnimationFrames(frameCount) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
function handleFrame() {
|
||||
if (--frameCount <= 0) {
|
||||
resolve();
|
||||
} else {
|
||||
window.requestAnimationFrame(handleFrame);
|
||||
}
|
||||
}
|
||||
window.requestAnimationFrame(handleFrame);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -6,6 +6,7 @@ support-files =
|
|||
db_smilCSSPaced.js
|
||||
db_smilCSSPropertyList.js
|
||||
db_smilMappedAttrList.js
|
||||
file_smilWithTransition.html
|
||||
smilAnimateMotionValueLists.js
|
||||
smilExtDoc_helper.svg
|
||||
smilTestUtils.js
|
||||
|
|
|
@ -1,72 +1,18 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1315874
|
||||
-->
|
||||
<meta charset=utf-8>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test SMIL does not trigger CSS Transitions (bug 1315874)</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1315874">Mozilla Bug
|
||||
1315874</a>
|
||||
<svg>
|
||||
<rect width="100%" height="100%"
|
||||
style="fill: red; transition: fill 10s" id="rect">
|
||||
<animate attributeName="fill" to="lime" dur="1s" fill="freeze">
|
||||
</rect>
|
||||
</svg>
|
||||
<pre id="test">
|
||||
<script type="text/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
window.addEventListener('load', runTests, false);
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
var rect = document.getElementById('rect');
|
||||
var svg = document.getElementsByTagName('svg')[0];
|
||||
is(getComputedStyle(rect).fill, 'rgb(255, 0, 0)',
|
||||
'The initial color should be red.');
|
||||
|
||||
function runTests() {
|
||||
waitForFrame().then(function() {
|
||||
svg.setCurrentTime(1);
|
||||
ok(getComputedStyle(rect).fill, 'rgb(0, 255, 0)',
|
||||
'The end color should be lime.');
|
||||
|
||||
return waitForAnimationFrames(2);
|
||||
}).then(function() {
|
||||
var anim = document.getAnimations()[0];
|
||||
ok(!anim, 'Transition should not be created by restyling for SMIL');
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
// Utility methods from testcommon.js
|
||||
// For detail, see dom/animation/test/testcommon.js.
|
||||
|
||||
function waitForFrame() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
requestAnimationFrame(function(time) {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function waitForAnimationFrames(frameCount) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
function handleFrame() {
|
||||
if (--frameCount <= 0) {
|
||||
resolve();
|
||||
} else {
|
||||
window.requestAnimationFrame(handleFrame);
|
||||
}
|
||||
}
|
||||
window.requestAnimationFrame(handleFrame);
|
||||
});
|
||||
}
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{ "set": [["dom.animations-api.core.enabled", true]]},
|
||||
function() {
|
||||
window.open("file_smilWithTransition.html");
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -2883,9 +2883,10 @@ StyleAnimationValue::AddWeighted(nsCSSPropertyID aProperty,
|
|||
case eUnit_Enumerated:
|
||||
switch (aProperty) {
|
||||
case eCSSProperty_font_stretch: {
|
||||
// Animate just like eUnit_Integer.
|
||||
int32_t result = floor(aCoeff1 * double(aValue1.GetIntValue()) +
|
||||
aCoeff2 * double(aValue2.GetIntValue()));
|
||||
// https://drafts.csswg.org/css-fonts-3/#font-stretch-animation
|
||||
double interpolatedValue = aCoeff1 * double(aValue1.GetIntValue()) +
|
||||
aCoeff2 * double(aValue2.GetIntValue());
|
||||
int32_t result = floor(interpolatedValue + 0.5);
|
||||
if (result < NS_STYLE_FONT_STRETCH_ULTRA_CONDENSED) {
|
||||
result = NS_STYLE_FONT_STRETCH_ULTRA_CONDENSED;
|
||||
} else if (result > NS_STYLE_FONT_STRETCH_ULTRA_EXPANDED) {
|
||||
|
@ -2917,10 +2918,10 @@ StyleAnimationValue::AddWeighted(nsCSSPropertyID aProperty,
|
|||
return true;
|
||||
}
|
||||
case eUnit_Integer: {
|
||||
// http://dev.w3.org/csswg/css3-transitions/#animation-of-property-types-
|
||||
// says we should use floor
|
||||
int32_t result = floor(aCoeff1 * double(aValue1.GetIntValue()) +
|
||||
aCoeff2 * double(aValue2.GetIntValue()));
|
||||
// https://drafts.csswg.org/css-transitions/#animtype-integer
|
||||
double interpolatedValue = aCoeff1 * double(aValue1.GetIntValue()) +
|
||||
aCoeff2 * double(aValue2.GetIntValue());
|
||||
int32_t result = floor(interpolatedValue + 0.5);
|
||||
if (aProperty == eCSSProperty_font_weight) {
|
||||
if (result < 100) {
|
||||
result = 100;
|
||||
|
|
|
@ -1836,7 +1836,7 @@ function test_integer_transition(prop) {
|
|||
"integer-valued property " + prop + ": computed value before transition");
|
||||
div.style.setProperty("transition-property", prop, "");
|
||||
div.style.setProperty(prop, "-14", "");
|
||||
is(cs.getPropertyValue(prop), "-1",
|
||||
is(cs.getPropertyValue(prop), "0",
|
||||
"integer-valued property " + prop + ": interpolation of integers");
|
||||
check_distance(prop, "6", "1", "-14");
|
||||
|
||||
|
@ -1880,7 +1880,7 @@ function test_font_stretch(prop) {
|
|||
"font-stretch property " + prop + ": computed value before transition");
|
||||
div.style.setProperty("transition-property", prop, "");
|
||||
div.style.setProperty(prop, "extra-condensed", "");
|
||||
is(cs.getPropertyValue(prop), "normal",
|
||||
is(cs.getPropertyValue(prop), "semi-expanded",
|
||||
"font-stretch property " + prop + ": interpolation of font-stretches");
|
||||
check_distance(prop, "expanded", "semi-expanded", "condensed");
|
||||
|
||||
|
@ -1964,7 +1964,7 @@ function test_pos_integer_or_auto_transition(prop) {
|
|||
"integer-valued property " + prop + ": computed value before transition");
|
||||
div.style.setProperty("transition-property", prop, "");
|
||||
div.style.setProperty(prop, "11", "");
|
||||
is(cs.getPropertyValue(prop), "5",
|
||||
is(cs.getPropertyValue(prop), "6",
|
||||
"integer-valued property " + prop + ": interpolation of integers");
|
||||
check_distance(prop, "4", "6", "12");
|
||||
div.style.setProperty(prop, "auto", "");
|
||||
|
|
|
@ -264,17 +264,20 @@ static const char contentSandboxRules[] = R"(
|
|||
; This process has blanket file read privileges
|
||||
(allow file-read*)
|
||||
; This process does not have blanket file read privileges
|
||||
(if (string=? hasProfileDir "TRUE")
|
||||
; we have a profile dir
|
||||
(begin
|
||||
(allow file-read* (require-all
|
||||
(require-not (home-subpath "/Library"))
|
||||
(require-not (subpath profileDir))))
|
||||
(allow file-read*
|
||||
(profile-subpath "/extensions")
|
||||
(profile-subpath "/chrome")))
|
||||
; we don't have a profile dir
|
||||
(allow file-read* (require-not (home-subpath "/Library"))))))
|
||||
(begin
|
||||
; bug 1201935
|
||||
(allow file-read* (home-subpath "/Library/Caches/TemporaryItems"))
|
||||
(if (string=? hasProfileDir "TRUE")
|
||||
; we have a profile dir
|
||||
(begin
|
||||
(allow file-read* (require-all
|
||||
(require-not (home-subpath "/Library"))
|
||||
(require-not (subpath profileDir))))
|
||||
(allow file-read*
|
||||
(profile-subpath "/extensions")
|
||||
(profile-subpath "/chrome")))
|
||||
; we don't have a profile dir
|
||||
(allow file-read* (require-not (home-subpath "/Library")))))))
|
||||
|
||||
; level 3: global read access permitted, no global write access,
|
||||
; no read access to the home directory,
|
||||
|
@ -317,10 +320,6 @@ static const char contentSandboxRules[] = R"(
|
|||
(iokit-user-client-class "NVDVDContextTesla")
|
||||
(iokit-user-client-class "Gen6DVDContext"))
|
||||
|
||||
; bug 1201935
|
||||
(allow file-read*
|
||||
(home-subpath "/Library/Caches/TemporaryItems"))
|
||||
|
||||
; bug 1237847
|
||||
(allow file-read*
|
||||
(subpath appTempDir))
|
||||
|
|
|
@ -248,6 +248,9 @@ function* testFileAccess() {
|
|||
fileBrowser = gBrowser.getBrowserForTab(gBrowser.selectedTab);
|
||||
}
|
||||
|
||||
// Current level
|
||||
let level = prefs.getIntPref("security.sandbox.content.level");
|
||||
|
||||
// Directories/files to test accessing from content processes.
|
||||
// For directories, we test whether a directory listing is allowed
|
||||
// or blocked. For files, we test if we can read from the file.
|
||||
|
@ -291,6 +294,30 @@ function* testFileAccess() {
|
|||
});
|
||||
}
|
||||
|
||||
if (isMac()) {
|
||||
// If ~/Library/Caches/TemporaryItems exists, when level <= 2 we
|
||||
// make sure it's readable. For level 3, we make sure it isn't.
|
||||
let homeTempDir = GetHomeDir();
|
||||
homeTempDir.appendRelativePath('Library/Caches/TemporaryItems');
|
||||
if (homeTempDir.exists()) {
|
||||
let shouldBeReadable, minLevel;
|
||||
if (level >= minHomeReadSandboxLevel()) {
|
||||
shouldBeReadable = false;
|
||||
minLevel = minHomeReadSandboxLevel();
|
||||
} else {
|
||||
shouldBeReadable = true;
|
||||
minLevel = 0;
|
||||
}
|
||||
tests.push({
|
||||
desc: "home library cache temp dir",
|
||||
ok: shouldBeReadable,
|
||||
browser: webBrowser,
|
||||
file: homeTempDir,
|
||||
minLevel: minLevel,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let extensionsDir = GetProfileEntry("extensions");
|
||||
if (extensionsDir.exists() && extensionsDir.isDirectory()) {
|
||||
tests.push({
|
||||
|
@ -331,7 +358,6 @@ function* testFileAccess() {
|
|||
}
|
||||
|
||||
// remove tests not enabled by the current sandbox level
|
||||
let level = prefs.getIntPref("security.sandbox.content.level");
|
||||
tests = tests.filter((test) => { return (test.minLevel <= level); });
|
||||
|
||||
for (let test of tests) {
|
||||
|
|
|
@ -501,3 +501,46 @@ function enableValidationPrefs() {
|
|||
Svc.Prefs.set("engine.bookmarks.validation.maxRecords", -1);
|
||||
Svc.Prefs.set("engine.bookmarks.validation.enabled", true);
|
||||
}
|
||||
|
||||
function serverForEnginesWithKeys(users, engines, callback) {
|
||||
// Generate and store a fake default key bundle to avoid resetting the client
|
||||
// before the first sync.
|
||||
let wbo = Service.collectionKeys.generateNewKeysWBO();
|
||||
let modified = new_timestamp();
|
||||
Service.collectionKeys.setContents(wbo.cleartext, modified);
|
||||
|
||||
let allEngines = [Service.clientsEngine].concat(engines);
|
||||
|
||||
let globalEngines = allEngines.reduce((entries, engine) => {
|
||||
let { name, version, syncID } = engine;
|
||||
entries[name] = { version, syncID };
|
||||
return entries;
|
||||
}, {});
|
||||
|
||||
let contents = allEngines.reduce((collections, engine) => {
|
||||
collections[engine.name] = {};
|
||||
return collections;
|
||||
}, {
|
||||
meta: {
|
||||
global: {
|
||||
syncID: Service.syncID,
|
||||
storageVersion: STORAGE_VERSION,
|
||||
engines: globalEngines,
|
||||
},
|
||||
},
|
||||
crypto: {
|
||||
keys: encryptPayload(wbo.cleartext),
|
||||
},
|
||||
});
|
||||
|
||||
return serverForUsers(users, contents, callback);
|
||||
}
|
||||
|
||||
function serverForFoo(engine, callback) {
|
||||
// The bookmarks engine *always* tracks changes, meaning we might try
|
||||
// and sync due to the bookmarks we ourselves create! Worse, because we
|
||||
// do an engine sync only, there's no locking - so we end up with multiple
|
||||
// syncs running. Neuter that by making the threshold very large.
|
||||
Service.scheduler.syncThreshold = 10000000;
|
||||
return serverForEnginesWithKeys({"foo": "password"}, engine, callback);
|
||||
}
|
||||
|
|
|
@ -16,45 +16,6 @@ initTestLogging("Trace");
|
|||
|
||||
Service.engineManager.register(BookmarksEngine);
|
||||
|
||||
function serverForFoo(engine) {
|
||||
// The bookmarks engine *always* tracks changes, meaning we might try
|
||||
// and sync due to the bookmarks we ourselves create! Worse, because we
|
||||
// do an engine sync only, there's no locking - so we end up with multiple
|
||||
// syncs running. Neuter that by making the threshold very large.
|
||||
Service.scheduler.syncThreshold = 10000000;
|
||||
let clientsEngine = Service.clientsEngine;
|
||||
return serverForUsers({"foo": "password"}, {
|
||||
meta: {
|
||||
global: {
|
||||
syncID: Service.syncID,
|
||||
storageVersion: STORAGE_VERSION,
|
||||
engines: {
|
||||
clients: {
|
||||
version: clientsEngine.version,
|
||||
syncID: clientsEngine.syncID,
|
||||
},
|
||||
bookmarks: {
|
||||
version: engine.version,
|
||||
syncID: engine.syncID,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
crypto: {
|
||||
keys: encryptPayload({
|
||||
id: "keys",
|
||||
// Generate a fake default key bundle to avoid resetting the client
|
||||
// before the first sync.
|
||||
default: [
|
||||
Svc.Crypto.generateRandomKey(),
|
||||
Svc.Crypto.generateRandomKey(),
|
||||
],
|
||||
}),
|
||||
},
|
||||
bookmarks: {}
|
||||
});
|
||||
}
|
||||
|
||||
// A stored reference to the collection won't be valid after disabling.
|
||||
function getBookmarkWBO(server, guid) {
|
||||
let coll = server.user("foo").collection("bookmarks");
|
||||
|
|
|
@ -25,24 +25,11 @@ store._log.level = Log.Level.Trace;
|
|||
engine._log.level = Log.Level.Trace;
|
||||
|
||||
async function setup() {
|
||||
let server = serverForUsers({"foo": "password"}, {
|
||||
meta: {global: {engines: {bookmarks: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
bookmarks: {},
|
||||
});
|
||||
|
||||
generateNewKeys(Service.collectionKeys);
|
||||
|
||||
let server = serverForFoo(engine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
|
||||
let collection = server.user("foo").collection("bookmarks");
|
||||
|
||||
// The bookmarks engine *always* tracks changes, meaning we might try
|
||||
// and sync due to the bookmarks we ourselves create! Worse, because we
|
||||
// do an engine sync only, there's no locking - so we end up with multiple
|
||||
// syncs running. Neuter that by making the threshold very large.
|
||||
Service.scheduler.syncThreshold = 10000000;
|
||||
|
||||
Svc.Obs.notify("weave:engine:start-tracking"); // We skip usual startup...
|
||||
|
||||
return { server, collection };
|
||||
|
|
|
@ -282,20 +282,6 @@ add_task(async function bad_record_allIDs() {
|
|||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
function serverForFoo(engine) {
|
||||
// The bookmarks engine *always* tracks changes, meaning we might try
|
||||
// and sync due to the bookmarks we ourselves create! Worse, because we
|
||||
// do an engine sync only, there's no locking - so we end up with multiple
|
||||
// syncs running. Neuter that by making the threshold very large.
|
||||
Service.scheduler.syncThreshold = 10000000;
|
||||
|
||||
return serverForUsers({"foo": "password"}, {
|
||||
meta: {global: {engines: {bookmarks: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
bookmarks: {}
|
||||
});
|
||||
}
|
||||
|
||||
add_task(async function test_processIncoming_error_orderChildren() {
|
||||
_("Ensure that _orderChildren() is called even when _processIncoming() throws an error.");
|
||||
|
||||
|
|
|
@ -89,26 +89,7 @@ add_task(async function test_bookmark_repair_integration() {
|
|||
|
||||
_("Ensure that a validation error triggers a repair request.");
|
||||
|
||||
let contents = {
|
||||
meta: {
|
||||
global: {
|
||||
engines: {
|
||||
clients: {
|
||||
version: clientsEngine.version,
|
||||
syncID: clientsEngine.syncID,
|
||||
},
|
||||
bookmarks: {
|
||||
version: bookmarksEngine.version,
|
||||
syncID: bookmarksEngine.syncID,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
clients: {},
|
||||
bookmarks: {},
|
||||
crypto: {},
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(bookmarksEngine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
|
||||
let user = server.user("foo");
|
||||
|
@ -329,26 +310,7 @@ add_task(async function test_repair_client_missing() {
|
|||
|
||||
_("Ensure that a record missing from the client only will get re-downloaded from the server");
|
||||
|
||||
let contents = {
|
||||
meta: {
|
||||
global: {
|
||||
engines: {
|
||||
clients: {
|
||||
version: clientsEngine.version,
|
||||
syncID: clientsEngine.syncID,
|
||||
},
|
||||
bookmarks: {
|
||||
version: bookmarksEngine.version,
|
||||
syncID: bookmarksEngine.syncID,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
clients: {},
|
||||
bookmarks: {},
|
||||
crypto: {},
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(bookmarksEngine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
|
||||
let user = server.user("foo");
|
||||
|
@ -420,26 +382,7 @@ add_task(async function test_repair_server_missing() {
|
|||
|
||||
_("Ensure that a record missing from the server only will get re-upload from the client");
|
||||
|
||||
let contents = {
|
||||
meta: {
|
||||
global: {
|
||||
engines: {
|
||||
clients: {
|
||||
version: clientsEngine.version,
|
||||
syncID: clientsEngine.syncID,
|
||||
},
|
||||
bookmarks: {
|
||||
version: bookmarksEngine.version,
|
||||
syncID: bookmarksEngine.syncID,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
clients: {},
|
||||
bookmarks: {},
|
||||
crypto: {},
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(bookmarksEngine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
|
||||
let user = server.user("foo");
|
||||
|
@ -504,26 +447,7 @@ add_task(async function test_repair_server_deleted() {
|
|||
|
||||
_("Ensure that a record marked as deleted on the server but present on the client will get deleted on the client");
|
||||
|
||||
let contents = {
|
||||
meta: {
|
||||
global: {
|
||||
engines: {
|
||||
clients: {
|
||||
version: clientsEngine.version,
|
||||
syncID: clientsEngine.syncID,
|
||||
},
|
||||
bookmarks: {
|
||||
version: bookmarksEngine.version,
|
||||
syncID: bookmarksEngine.syncID,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
clients: {},
|
||||
bookmarks: {},
|
||||
crypto: {},
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(bookmarksEngine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
|
||||
let user = server.user("foo");
|
||||
|
|
|
@ -34,39 +34,9 @@ function getServerBookmarks(server) {
|
|||
}
|
||||
|
||||
async function setup() {
|
||||
let clientsEngine = Service.clientsEngine;
|
||||
let bookmarksEngine = Service.engineManager.get("bookmarks");
|
||||
|
||||
let server = serverForUsers({"foo": "password"}, {
|
||||
meta: {
|
||||
global: {
|
||||
syncID: Service.syncID,
|
||||
storageVersion: STORAGE_VERSION,
|
||||
engines: {
|
||||
clients: {
|
||||
version: clientsEngine.version,
|
||||
syncID: clientsEngine.syncID,
|
||||
},
|
||||
bookmarks: {
|
||||
version: bookmarksEngine.version,
|
||||
syncID: bookmarksEngine.syncID,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
crypto: {
|
||||
keys: encryptPayload({
|
||||
id: "keys",
|
||||
// Generate a fake default key bundle to avoid resetting the client
|
||||
// before the first sync.
|
||||
default: [
|
||||
Svc.Crypto.generateRandomKey(),
|
||||
Svc.Crypto.generateRandomKey(),
|
||||
],
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
let server = serverForFoo(bookmarksEngine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
|
||||
// Disable validation so that we don't try to automatically repair the server
|
||||
|
|
|
@ -46,14 +46,6 @@ function clearBookmarks() {
|
|||
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.bookmarks.unfiledBookmarksFolder);
|
||||
}
|
||||
|
||||
function serverForFoo(engineData) {
|
||||
return serverForUsers({"foo": "password"}, {
|
||||
meta: {global: {engines: {bookmarks: {version: engineData.version,
|
||||
syncID: engineData.syncID}}}},
|
||||
bookmarks: {}
|
||||
});
|
||||
}
|
||||
|
||||
// Verify that Places smart bookmarks have their annotation uploaded and
|
||||
// handled locally.
|
||||
add_task(async function test_annotation_uploaded() {
|
||||
|
|
|
@ -138,6 +138,165 @@ async function insertBookmarksToMigrate() {
|
|||
await PlacesUtils.bookmarks.remove(exampleBmk.guid);
|
||||
}
|
||||
|
||||
// `PlacesUtils.annotations.setItemAnnotation` prevents us from setting
|
||||
// annotations on nonexistent items, so this test helper writes to the DB
|
||||
// directly.
|
||||
function setAnnoUnchecked(itemId, name, value, type) {
|
||||
return PlacesUtils.withConnectionWrapper(
|
||||
"test_bookmark_tracker: setItemAnnoUnchecked", async function(db) {
|
||||
await db.executeCached(`
|
||||
INSERT OR IGNORE INTO moz_anno_attributes (name)
|
||||
VALUES (:name)`,
|
||||
{ name });
|
||||
|
||||
let annoIds = await db.executeCached(`
|
||||
SELECT a.id, a.dateAdded
|
||||
FROM moz_items_annos a WHERE a.item_id = :itemId`,
|
||||
{ itemId });
|
||||
|
||||
let annoId;
|
||||
let dateAdded;
|
||||
let lastModified = PlacesUtils.toPRTime(Date.now());
|
||||
|
||||
if (annoIds.length) {
|
||||
annoId = annoIds[0].getResultByName("id");
|
||||
dateAdded = annoIds[0].getResultByName("dateAdded");
|
||||
} else {
|
||||
annoId = null;
|
||||
dateAdded = lastModified;
|
||||
}
|
||||
|
||||
await db.executeCached(`
|
||||
INSERT OR REPLACE INTO moz_items_annos (id, item_id, anno_attribute_id,
|
||||
content, flags, expiration, type, dateAdded, lastModified)
|
||||
VALUES (:annoId, :itemId, (SELECT id FROM moz_anno_attributes
|
||||
WHERE name = :name),
|
||||
:value, 0, :expiration, :type, :dateAdded, :lastModified)`,
|
||||
{ annoId, itemId, name, value, type,
|
||||
expiration: PlacesUtils.annotations.EXPIRE_NEVER,
|
||||
dateAdded, lastModified });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
add_task(async function test_leftPaneFolder() {
|
||||
_("Ensure we never track left pane roots");
|
||||
|
||||
try {
|
||||
await startTracking();
|
||||
|
||||
// Creates the organizer queries as a side effect.
|
||||
let leftPaneId = PlacesUIUtils.maybeRebuildLeftPane();
|
||||
_(`Left pane root ID: ${leftPaneId}`);
|
||||
|
||||
{
|
||||
let changes = await tracker.promiseChangedIDs();
|
||||
deepEqual(changes, {}, "New left pane queries should not be tracked");
|
||||
do_check_eq(tracker.score, SCORE_INCREMENT_XLARGE);
|
||||
}
|
||||
|
||||
_("Reset synced bookmarks to simulate a disconnect");
|
||||
await PlacesSyncUtils.bookmarks.reset();
|
||||
|
||||
{
|
||||
let changes = await tracker.promiseChangedIDs();
|
||||
deepEqual(Object.keys(changes).sort(), ["menu", "mobile", "toolbar", "unfiled"],
|
||||
"Left pane queries should not be tracked after reset");
|
||||
do_check_eq(tracker.score, SCORE_INCREMENT_XLARGE);
|
||||
await PlacesTestUtils.markBookmarksAsSynced();
|
||||
}
|
||||
|
||||
// The following tests corrupt the left pane queries in different ways.
|
||||
// `PlacesUIUtils.maybeRebuildLeftPane` will rebuild the entire root, but
|
||||
// none of those changes should be tracked by Sync.
|
||||
|
||||
_("Annotate unrelated folder as left pane root");
|
||||
{
|
||||
let folder = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: PlacesUtils.bookmarks.rootGuid,
|
||||
type: PlacesUtils.bookmarks.TYPE_FOLDER,
|
||||
title: "Fake left pane root",
|
||||
});
|
||||
let folderId = await PlacesUtils.promiseItemId(folder.guid);
|
||||
await setAnnoUnchecked(folderId, PlacesUIUtils.ORGANIZER_FOLDER_ANNO, 0,
|
||||
PlacesUtils.annotations.TYPE_INT32);
|
||||
|
||||
leftPaneId = PlacesUIUtils.maybeRebuildLeftPane();
|
||||
_(`Left pane root ID after deleting unrelated folder: ${leftPaneId}`);
|
||||
|
||||
let changes = await tracker.promiseChangedIDs();
|
||||
deepEqual(changes, {},
|
||||
"Should not track left pane items after deleting unrelated folder");
|
||||
}
|
||||
|
||||
_("Corrupt organizer left pane version");
|
||||
{
|
||||
await setAnnoUnchecked(leftPaneId, PlacesUIUtils.ORGANIZER_FOLDER_ANNO,
|
||||
-1, PlacesUtils.annotations.TYPE_INT32);
|
||||
|
||||
leftPaneId = PlacesUIUtils.maybeRebuildLeftPane();
|
||||
_(`Left pane root ID after restoring version: ${leftPaneId}`);
|
||||
|
||||
let changes = await tracker.promiseChangedIDs();
|
||||
deepEqual(changes, {},
|
||||
"Should not track left pane items after restoring version");
|
||||
}
|
||||
|
||||
_("Set left pane anno on nonexistent item");
|
||||
{
|
||||
await setAnnoUnchecked(999, PlacesUIUtils.ORGANIZER_QUERY_ANNO,
|
||||
"Tags", PlacesUtils.annotations.TYPE_STRING);
|
||||
|
||||
leftPaneId = PlacesUIUtils.maybeRebuildLeftPane();
|
||||
_(`Left pane root ID after detecting nonexistent item: ${leftPaneId}`);
|
||||
|
||||
let changes = await tracker.promiseChangedIDs();
|
||||
deepEqual(changes, {},
|
||||
"Should not track left pane items after detecting nonexistent item");
|
||||
}
|
||||
|
||||
_("Move query out of left pane root");
|
||||
{
|
||||
let queryId = await PlacesUIUtils.leftPaneQueries.Downloads;
|
||||
let queryGuid = await PlacesUtils.promiseItemGuid(queryId);
|
||||
await PlacesUtils.bookmarks.update({
|
||||
guid: queryGuid,
|
||||
parentGuid: PlacesUtils.bookmarks.rootGuid,
|
||||
index: PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
});
|
||||
|
||||
leftPaneId = PlacesUIUtils.maybeRebuildLeftPane();
|
||||
_(`Left pane root ID after restoring moved query: ${leftPaneId}`);
|
||||
|
||||
let changes = await tracker.promiseChangedIDs();
|
||||
deepEqual(changes, {},
|
||||
"Should not track left pane items after restoring moved query");
|
||||
}
|
||||
|
||||
_("Add duplicate query");
|
||||
{
|
||||
let leftPaneGuid = await PlacesUtils.promiseItemGuid(leftPaneId);
|
||||
let query = await PlacesUtils.bookmarks.insert({
|
||||
parentGuid: leftPaneGuid,
|
||||
url: `place:folder=TAGS`,
|
||||
});
|
||||
let queryId = await PlacesUtils.promiseItemId(query.guid);
|
||||
await setAnnoUnchecked(queryId, PlacesUIUtils.ORGANIZER_QUERY_ANNO,
|
||||
"Tags", PlacesUtils.annotations.TYPE_STRING);
|
||||
|
||||
leftPaneId = PlacesUIUtils.maybeRebuildLeftPane();
|
||||
_(`Left pane root ID after removing dupe query: ${leftPaneId}`);
|
||||
|
||||
let changes = await tracker.promiseChangedIDs();
|
||||
deepEqual(changes, {},
|
||||
"Should not track left pane items after removing dupe query");
|
||||
}
|
||||
} finally {
|
||||
_("Clean up.");
|
||||
await cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_tracking() {
|
||||
_("Test starting and stopping the tracker");
|
||||
|
||||
|
@ -1526,11 +1685,6 @@ add_task(async function test_onItemDeleted_tree() {
|
|||
}
|
||||
});
|
||||
|
||||
async function ensureMobileQuery() {
|
||||
tracker._ensureMobileQuery();
|
||||
await PlacesTestUtils.promiseAsyncUpdates();
|
||||
}
|
||||
|
||||
add_task(async function test_mobile_query() {
|
||||
_("Ensure we correctly create the mobile query");
|
||||
|
||||
|
@ -1540,7 +1694,6 @@ add_task(async function test_mobile_query() {
|
|||
// Creates the organizer queries as a side effect.
|
||||
let leftPaneId = PlacesUIUtils.leftPaneFolderId;
|
||||
_(`Left pane root ID: ${leftPaneId}`);
|
||||
await PlacesTestUtils.promiseAsyncUpdates();
|
||||
|
||||
let allBookmarksGuids = await fetchGuidsWithAnno("PlacesOrganizer/OrganizerQuery",
|
||||
"AllBookmarks");
|
||||
|
@ -1548,7 +1701,7 @@ add_task(async function test_mobile_query() {
|
|||
let allBookmarkGuid = allBookmarksGuids[0];
|
||||
|
||||
_("Try creating query after organizer is ready");
|
||||
await ensureMobileQuery();
|
||||
tracker._ensureMobileQuery();
|
||||
let queryGuids = await fetchGuidsWithAnno("PlacesOrganizer/OrganizerQuery",
|
||||
"MobileBookmarks");
|
||||
equal(queryGuids.length, 0, "Should not create query without any mobile bookmarks");
|
||||
|
@ -1558,7 +1711,7 @@ add_task(async function test_mobile_query() {
|
|||
parentGuid: PlacesUtils.bookmarks.mobileGuid,
|
||||
url: "https://mozilla.org",
|
||||
});
|
||||
await ensureMobileQuery();
|
||||
tracker._ensureMobileQuery();
|
||||
queryGuids = await fetchGuidsWithAnno("PlacesOrganizer/OrganizerQuery",
|
||||
"MobileBookmarks");
|
||||
equal(queryGuids.length, 1, "Should create query once mobile bookmarks exist");
|
||||
|
@ -1579,7 +1732,7 @@ add_task(async function test_mobile_query() {
|
|||
guid: queryGuid,
|
||||
title: "renamed query",
|
||||
});
|
||||
await ensureMobileQuery();
|
||||
tracker._ensureMobileQuery();
|
||||
let rootInfo = await PlacesUtils.bookmarks.fetch(PlacesUtils.bookmarks.mobileGuid);
|
||||
equal(rootInfo.title, "Mobile Bookmarks", "Should fix root title");
|
||||
queryInfo = await PlacesUtils.bookmarks.fetch(queryGuid);
|
||||
|
@ -1590,14 +1743,13 @@ add_task(async function test_mobile_query() {
|
|||
guid: queryGuid,
|
||||
url: "place:folder=BOOKMARKS_MENU",
|
||||
});
|
||||
await ensureMobileQuery();
|
||||
tracker._ensureMobileQuery();
|
||||
queryInfo = await PlacesUtils.bookmarks.fetch(queryGuid);
|
||||
equal(queryInfo.url.href, `place:folder=${PlacesUtils.mobileFolderId}`,
|
||||
"Should fix query URL to point to mobile root");
|
||||
|
||||
_("We shouldn't track the query or the left pane root");
|
||||
await verifyTrackedItems([mozBmk.guid, "mobile"]);
|
||||
do_check_eq(tracker.score, SCORE_INCREMENT_XLARGE * 5);
|
||||
} finally {
|
||||
_("Clean up.");
|
||||
await cleanup();
|
||||
|
|
|
@ -58,12 +58,6 @@ function cleanup() {
|
|||
|
||||
add_task(async function test_bad_hmac() {
|
||||
_("Ensure that Clients engine deletes corrupt records.");
|
||||
let contents = {
|
||||
meta: {global: {engines: {clients: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
clients: {},
|
||||
crypto: {}
|
||||
};
|
||||
let deletedCollections = [];
|
||||
let deletedItems = [];
|
||||
let callback = {
|
||||
|
@ -75,7 +69,7 @@ add_task(async function test_bad_hmac() {
|
|||
deletedCollections.push(coll);
|
||||
}
|
||||
}
|
||||
let server = serverForUsers({"foo": "password"}, contents, callback);
|
||||
let server = serverForFoo(engine, callback);
|
||||
let user = server.user("foo");
|
||||
|
||||
function check_clients_count(expectedCount) {
|
||||
|
@ -212,13 +206,7 @@ add_task(async function test_full_sync() {
|
|||
_("Ensure that Clients engine fetches all records for each sync.");
|
||||
|
||||
let now = Date.now() / 1000;
|
||||
let contents = {
|
||||
meta: {global: {engines: {clients: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
clients: {},
|
||||
crypto: {}
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(engine);
|
||||
let user = server.user("foo");
|
||||
|
||||
await SyncTestingInfrastructure(server);
|
||||
|
@ -283,13 +271,7 @@ add_task(async function test_full_sync() {
|
|||
add_task(async function test_sync() {
|
||||
_("Ensure that Clients engine uploads a new client record once a week.");
|
||||
|
||||
let contents = {
|
||||
meta: {global: {engines: {clients: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
clients: {},
|
||||
crypto: {}
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(engine);
|
||||
let user = server.user("foo");
|
||||
|
||||
await SyncTestingInfrastructure(server);
|
||||
|
@ -369,13 +351,7 @@ add_task(async function test_last_modified() {
|
|||
_("Ensure that remote records have a sane serverLastModified attribute.");
|
||||
|
||||
let now = Date.now() / 1000;
|
||||
let contents = {
|
||||
meta: {global: {engines: {clients: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
clients: {},
|
||||
crypto: {}
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(engine);
|
||||
let user = server.user("foo");
|
||||
|
||||
await SyncTestingInfrastructure(server);
|
||||
|
@ -590,13 +566,7 @@ add_task(async function test_filter_duplicate_names() {
|
|||
_("Ensure that we exclude clients with identical names that haven't synced in a week.");
|
||||
|
||||
let now = Date.now() / 1000;
|
||||
let contents = {
|
||||
meta: {global: {engines: {clients: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
clients: {},
|
||||
crypto: {}
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(engine);
|
||||
let user = server.user("foo");
|
||||
|
||||
await SyncTestingInfrastructure(server);
|
||||
|
@ -747,13 +717,7 @@ add_task(async function test_command_sync() {
|
|||
engine._store.wipe();
|
||||
generateNewKeys(Service.collectionKeys);
|
||||
|
||||
let contents = {
|
||||
meta: {global: {engines: {clients: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
clients: {},
|
||||
crypto: {}
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(engine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
|
||||
let user = server.user("foo");
|
||||
|
@ -824,13 +788,7 @@ add_task(async function test_clients_not_in_fxa_list() {
|
|||
engine._store.wipe();
|
||||
generateNewKeys(Service.collectionKeys);
|
||||
|
||||
let contents = {
|
||||
meta: {global: {engines: {clients: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
clients: {},
|
||||
crypto: {}
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(engine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
|
||||
let user = server.user("foo");
|
||||
|
@ -1006,13 +964,7 @@ add_task(async function test_merge_commands() {
|
|||
_("Verifies local commands for remote clients are merged with the server's");
|
||||
|
||||
let now = Date.now() / 1000;
|
||||
let contents = {
|
||||
meta: {global: {engines: {clients: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
clients: {},
|
||||
crypto: {}
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(engine);
|
||||
|
||||
await SyncTestingInfrastructure(server);
|
||||
generateNewKeys(Service.collectionKeys);
|
||||
|
@ -1082,13 +1034,7 @@ add_task(async function test_duplicate_remote_commands() {
|
|||
_("Verifies local commands for remote clients are sent only once (bug 1289287)");
|
||||
|
||||
let now = Date.now() / 1000;
|
||||
let contents = {
|
||||
meta: {global: {engines: {clients: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
clients: {},
|
||||
crypto: {}
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(engine);
|
||||
|
||||
await SyncTestingInfrastructure(server);
|
||||
generateNewKeys(Service.collectionKeys);
|
||||
|
@ -1147,13 +1093,7 @@ add_task(async function test_upload_after_reboot() {
|
|||
_("Multiple downloads, reboot, then upload (bug 1289287)");
|
||||
|
||||
let now = Date.now() / 1000;
|
||||
let contents = {
|
||||
meta: {global: {engines: {clients: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
clients: {},
|
||||
crypto: {}
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(engine);
|
||||
|
||||
await SyncTestingInfrastructure(server);
|
||||
generateNewKeys(Service.collectionKeys);
|
||||
|
@ -1235,13 +1175,7 @@ add_task(async function test_keep_cleared_commands_after_reboot() {
|
|||
_("Download commands, fail upload, reboot, then apply new commands (bug 1289287)");
|
||||
|
||||
let now = Date.now() / 1000;
|
||||
let contents = {
|
||||
meta: {global: {engines: {clients: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
clients: {},
|
||||
crypto: {}
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(engine);
|
||||
|
||||
await SyncTestingInfrastructure(server);
|
||||
generateNewKeys(Service.collectionKeys);
|
||||
|
@ -1359,13 +1293,7 @@ add_task(async function test_deleted_commands() {
|
|||
_("Verifies commands for a deleted client are discarded");
|
||||
|
||||
let now = Date.now() / 1000;
|
||||
let contents = {
|
||||
meta: {global: {engines: {clients: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
clients: {},
|
||||
crypto: {}
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(engine);
|
||||
|
||||
await SyncTestingInfrastructure(server);
|
||||
generateNewKeys(Service.collectionKeys);
|
||||
|
@ -1423,13 +1351,7 @@ add_task(async function test_send_uri_ack() {
|
|||
_("Ensure a sent URI is deleted when the client syncs");
|
||||
|
||||
let now = Date.now() / 1000;
|
||||
let contents = {
|
||||
meta: {global: {engines: {clients: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
clients: {},
|
||||
crypto: {}
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(engine);
|
||||
|
||||
await SyncTestingInfrastructure(server);
|
||||
generateNewKeys(Service.collectionKeys);
|
||||
|
@ -1486,13 +1408,7 @@ add_task(async function test_command_sync() {
|
|||
engine._store.wipe();
|
||||
generateNewKeys(Service.collectionKeys);
|
||||
|
||||
let contents = {
|
||||
meta: {global: {engines: {clients: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
clients: {},
|
||||
crypto: {}
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(engine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
|
||||
let collection = server.getCollection("foo", "clients");
|
||||
|
@ -1557,13 +1473,7 @@ add_task(async function ensureSameFlowIDs() {
|
|||
try {
|
||||
// Setup 2 clients, send them a command, and ensure we get to events
|
||||
// written, both with the same flowID.
|
||||
let contents = {
|
||||
meta: {global: {engines: {clients: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
clients: {},
|
||||
crypto: {}
|
||||
};
|
||||
let server = serverForUsers({"foo": "password"}, contents);
|
||||
let server = serverForFoo(engine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
|
||||
let remoteId = Utils.makeGUID();
|
||||
|
|
|
@ -8,51 +8,16 @@ const LoginInfo = Components.Constructor(
|
|||
const PropertyBag = Components.Constructor(
|
||||
"@mozilla.org/hash-property-bag;1", Ci.nsIWritablePropertyBag);
|
||||
|
||||
function serverForEngine(engine) {
|
||||
let clientsEngine = Service.clientsEngine;
|
||||
return serverForUsers({"foo": "password"}, {
|
||||
meta: {
|
||||
global: {
|
||||
syncID: Service.syncID,
|
||||
storageVersion: STORAGE_VERSION,
|
||||
engines: {
|
||||
clients: {
|
||||
version: clientsEngine.version,
|
||||
syncID: clientsEngine.syncID,
|
||||
},
|
||||
[engine.name]: {
|
||||
version: engine.version,
|
||||
syncID: engine.syncID,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
crypto: {
|
||||
keys: encryptPayload({
|
||||
id: "keys",
|
||||
// Generate a fake default key bundle to avoid resetting the client
|
||||
// before the first sync.
|
||||
default: [
|
||||
Svc.Crypto.generateRandomKey(),
|
||||
Svc.Crypto.generateRandomKey(),
|
||||
],
|
||||
}),
|
||||
},
|
||||
[engine.name]: {},
|
||||
});
|
||||
}
|
||||
|
||||
add_task(async function test_password_engine() {
|
||||
_("Basic password sync test");
|
||||
|
||||
let engine = Service.engineManager.get("passwords");
|
||||
let store = engine._store;
|
||||
|
||||
let server = serverForEngine(engine);
|
||||
let server = serverForFoo(engine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
let collection = server.user("foo").collection("passwords");
|
||||
|
||||
generateNewKeys(Service.collectionKeys);
|
||||
enableValidationPrefs();
|
||||
|
||||
_("Add new login to upload during first sync");
|
||||
|
|
|
@ -100,11 +100,7 @@ add_task(async function test_basic() {
|
|||
add_task(async function test_processIncoming_error() {
|
||||
let engine = new BookmarksEngine(Service);
|
||||
let store = engine._store;
|
||||
let server = serverForUsers({"foo": "password"}, {
|
||||
meta: {global: {engines: {bookmarks: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
bookmarks: {}
|
||||
});
|
||||
let server = serverForFoo(engine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
let collection = server.user("foo").collection("bookmarks");
|
||||
try {
|
||||
|
@ -154,11 +150,7 @@ add_task(async function test_processIncoming_error() {
|
|||
add_task(async function test_uploading() {
|
||||
let engine = new BookmarksEngine(Service);
|
||||
let store = engine._store;
|
||||
let server = serverForUsers({"foo": "password"}, {
|
||||
meta: {global: {engines: {bookmarks: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
bookmarks: {}
|
||||
});
|
||||
let server = serverForFoo(engine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
|
||||
let parent = PlacesUtils.toolbarFolderId;
|
||||
|
@ -338,11 +330,7 @@ add_task(async function test_generic_engine_fail() {
|
|||
Service.engineManager.register(SteamEngine);
|
||||
let engine = Service.engineManager.get("steam");
|
||||
engine.enabled = true;
|
||||
let server = serverForUsers({"foo": "password"}, {
|
||||
meta: {global: {engines: {steam: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
steam: {}
|
||||
});
|
||||
let server = serverForFoo(engine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
let e = new Error("generic failure message")
|
||||
engine._errToThrow = e;
|
||||
|
@ -368,11 +356,7 @@ add_task(async function test_engine_fail_ioerror() {
|
|||
Service.engineManager.register(SteamEngine);
|
||||
let engine = Service.engineManager.get("steam");
|
||||
engine.enabled = true;
|
||||
let server = serverForUsers({"foo": "password"}, {
|
||||
meta: {global: {engines: {steam: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
steam: {}
|
||||
});
|
||||
let server = serverForFoo(engine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
// create an IOError to re-throw as part of Sync.
|
||||
try {
|
||||
|
@ -410,12 +394,9 @@ add_task(async function test_initial_sync_engines() {
|
|||
let engines = {};
|
||||
// These are the only ones who actually have things to sync at startup.
|
||||
let engineNames = ["clients", "bookmarks", "prefs", "tabs"];
|
||||
let conf = { meta: { global: { engines } } };
|
||||
for (let e of engineNames) {
|
||||
engines[e] = { version: engine.version, syncID: engine.syncID };
|
||||
conf[e] = {};
|
||||
}
|
||||
let server = serverForUsers({"foo": "password"}, conf);
|
||||
let server = serverForEnginesWithKeys({"foo": "password"}, ["bookmarks", "prefs", "tabs"].map(name =>
|
||||
Service.engineManager.get(name)
|
||||
));
|
||||
await SyncTestingInfrastructure(server);
|
||||
try {
|
||||
_(`test_initial_sync_engines: Steam tracker contents: ${
|
||||
|
@ -448,11 +429,7 @@ add_task(async function test_nserror() {
|
|||
Service.engineManager.register(SteamEngine);
|
||||
let engine = Service.engineManager.get("steam");
|
||||
engine.enabled = true;
|
||||
let server = serverForUsers({"foo": "password"}, {
|
||||
meta: {global: {engines: {steam: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
steam: {}
|
||||
});
|
||||
let server = serverForFoo(engine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
engine._errToThrow = Components.Exception("NS_ERROR_UNKNOWN_HOST", Cr.NS_ERROR_UNKNOWN_HOST);
|
||||
try {
|
||||
|
@ -527,10 +504,7 @@ add_task(async function test_no_foreign_engines_in_error_ping() {
|
|||
Service.engineManager.register(BogusEngine);
|
||||
let engine = Service.engineManager.get("bogus");
|
||||
engine.enabled = true;
|
||||
let server = serverForUsers({"foo": "password"}, {
|
||||
meta: {global: {engines: {bogus: {version: engine.version, syncID: engine.syncID}}}},
|
||||
steam: {}
|
||||
});
|
||||
let server = serverForFoo(engine);
|
||||
engine._errToThrow = new Error("Oh no!");
|
||||
await SyncTestingInfrastructure(server);
|
||||
try {
|
||||
|
@ -549,11 +523,7 @@ add_task(async function test_sql_error() {
|
|||
Service.engineManager.register(SteamEngine);
|
||||
let engine = Service.engineManager.get("steam");
|
||||
engine.enabled = true;
|
||||
let server = serverForUsers({"foo": "password"}, {
|
||||
meta: {global: {engines: {steam: {version: engine.version,
|
||||
syncID: engine.syncID}}}},
|
||||
steam: {}
|
||||
});
|
||||
let server = serverForFoo(engine);
|
||||
await SyncTestingInfrastructure(server);
|
||||
engine._sync = function() {
|
||||
// Just grab a DB connection and issue a bogus SQL statement synchronously.
|
||||
|
@ -578,10 +548,7 @@ add_task(async function test_no_foreign_engines_in_success_ping() {
|
|||
Service.engineManager.register(BogusEngine);
|
||||
let engine = Service.engineManager.get("bogus");
|
||||
engine.enabled = true;
|
||||
let server = serverForUsers({"foo": "password"}, {
|
||||
meta: {global: {engines: {bogus: {version: engine.version, syncID: engine.syncID}}}},
|
||||
steam: {}
|
||||
});
|
||||
let server = serverForFoo(engine);
|
||||
|
||||
await SyncTestingInfrastructure(server);
|
||||
try {
|
||||
|
@ -599,10 +566,7 @@ add_task(async function test_events() {
|
|||
Service.engineManager.register(BogusEngine);
|
||||
let engine = Service.engineManager.get("bogus");
|
||||
engine.enabled = true;
|
||||
let server = serverForUsers({"foo": "password"}, {
|
||||
meta: {global: {engines: {bogus: {version: engine.version, syncID: engine.syncID}}}},
|
||||
steam: {}
|
||||
});
|
||||
let server = serverForFoo(engine);
|
||||
|
||||
await SyncTestingInfrastructure(server);
|
||||
try {
|
||||
|
@ -646,10 +610,7 @@ add_task(async function test_invalid_events() {
|
|||
Service.engineManager.register(BogusEngine);
|
||||
let engine = Service.engineManager.get("bogus");
|
||||
engine.enabled = true;
|
||||
let server = serverForUsers({"foo": "password"}, {
|
||||
meta: {global: {engines: {bogus: {version: engine.version, syncID: engine.syncID}}}},
|
||||
steam: {}
|
||||
});
|
||||
let server = serverForFoo(engine);
|
||||
|
||||
async function checkNotRecorded(...args) {
|
||||
Service.recordTelemetryEvent.call(args);
|
||||
|
@ -695,10 +656,7 @@ add_task(async function test_no_ping_for_self_hosters() {
|
|||
Service.engineManager.register(BogusEngine);
|
||||
let engine = Service.engineManager.get("bogus");
|
||||
engine.enabled = true;
|
||||
let server = serverForUsers({"foo": "password"}, {
|
||||
meta: {global: {engines: {bogus: {version: engine.version, syncID: engine.syncID}}}},
|
||||
steam: {}
|
||||
});
|
||||
let server = serverForFoo(engine);
|
||||
|
||||
await SyncTestingInfrastructure(server);
|
||||
try {
|
||||
|
|
|
@ -169,27 +169,6 @@ impl<Impl: SelectorImpl> SelectorInner<Impl> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a clone of this selector with everything to the left of
|
||||
/// (and including) the rightmost ancestor combinator removed. So
|
||||
/// the selector |span foo > bar + baz| will become |bar + baz|.
|
||||
/// This is used for revalidation selectors in servo.
|
||||
///
|
||||
/// The bloom filter hashes are copied, even though they correspond to
|
||||
/// parts of the selector that have been stripped out, because they are
|
||||
/// still useful for fast-rejecting the reduced selectors.
|
||||
pub fn slice_to_first_ancestor_combinator(&self) -> Self {
|
||||
let maybe_pos = self.complex.iter_raw()
|
||||
.position(|s| s.as_combinator()
|
||||
.map_or(false, |c| c.is_ancestor()));
|
||||
match maybe_pos {
|
||||
None => self.clone(),
|
||||
Some(index) => SelectorInner {
|
||||
complex: self.complex.slice_to(index),
|
||||
ancestor_hashes: self.ancestor_hashes.clone(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a SelectorInner from a Vec of Components. Used in tests.
|
||||
pub fn from_vec(vec: Vec<Component<Impl>>) -> Self {
|
||||
let complex = ComplexSelector::from_vec(vec);
|
||||
|
|
|
@ -27,7 +27,8 @@ use selectors::Element;
|
|||
use selectors::bloom::BloomFilter;
|
||||
use selectors::matching::{AFFECTED_BY_STYLE_ATTRIBUTE, AFFECTED_BY_PRESENTATIONAL_HINTS};
|
||||
use selectors::matching::{ElementSelectorFlags, StyleRelations, matches_selector};
|
||||
use selectors::parser::{Component, Selector, SelectorInner, SelectorMethods, LocalName as LocalNameSelector};
|
||||
use selectors::parser::{Combinator, Component, Selector, SelectorInner, SelectorIter};
|
||||
use selectors::parser::{SelectorMethods, LocalName as LocalNameSelector};
|
||||
use selectors::visitor::SelectorVisitor;
|
||||
use shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
|
||||
use sink::Push;
|
||||
|
@ -375,10 +376,7 @@ impl Stylist {
|
|||
#[inline]
|
||||
fn note_for_revalidation(&mut self, selector: &Selector<SelectorImpl>) {
|
||||
if needs_revalidation(selector) {
|
||||
// For revalidation, we can skip everything left of the first ancestor
|
||||
// combinator.
|
||||
let revalidation_sel = selector.inner.slice_to_first_ancestor_combinator();
|
||||
self.selectors_for_cache_revalidation.push(revalidation_sel);
|
||||
self.selectors_for_cache_revalidation.push(selector.inner.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -923,18 +921,47 @@ impl Drop for Stylist {
|
|||
/// Visitor determine whether a selector requires cache revalidation.
|
||||
///
|
||||
/// Note that we just check simple selectors and eagerly return when the first
|
||||
/// need for revalidation is found, so we don't need to store state on the visitor.
|
||||
/// need for revalidation is found, so we don't need to store state on the
|
||||
/// visitor.
|
||||
///
|
||||
/// Also, note that it's important to check the whole selector, due to cousins
|
||||
/// sharing arbitrarily deep in the DOM, not just the rightmost part of it
|
||||
/// (unfortunately, though).
|
||||
///
|
||||
/// With cousin sharing, we not only need to care about selectors in stuff like
|
||||
/// foo:first-child, but also about selectors like p:first-child foo, since the
|
||||
/// two parents may have shared style, and in that case we can test cousins
|
||||
/// whose matching depends on the selector up in the chain.
|
||||
///
|
||||
/// TODO(emilio): We can optimize when matching only siblings to only match the
|
||||
/// rightmost selector until a descendant combinator is found, I guess, and in
|
||||
/// general when we're sharing at depth `n`, to the `n + 1` sequences of
|
||||
/// descendant combinators.
|
||||
///
|
||||
/// I don't think that in presence of the bloom filter it's worth it, though.
|
||||
struct RevalidationVisitor;
|
||||
|
||||
impl SelectorVisitor for RevalidationVisitor {
|
||||
type Impl = SelectorImpl;
|
||||
|
||||
/// Check whether a rightmost sequence of simple selectors containing this
|
||||
/// simple selector to be explicitly matched against both the style sharing
|
||||
/// cache entry and the candidate.
|
||||
|
||||
fn visit_complex_selector(&mut self,
|
||||
_: SelectorIter<SelectorImpl>,
|
||||
combinator: Option<Combinator>) -> bool {
|
||||
let is_sibling_combinator =
|
||||
combinator.map_or(false, |c| c.is_sibling());
|
||||
|
||||
!is_sibling_combinator
|
||||
}
|
||||
|
||||
|
||||
/// Check whether sequence of simple selectors containing this simple
|
||||
/// selector to be explicitly matched against both the style sharing cache
|
||||
/// entry and the candidate.
|
||||
///
|
||||
/// We use this for selectors that can have different matching behavior between
|
||||
/// siblings that are otherwise identical as far as the cache is concerned.
|
||||
/// We use this for selectors that can have different matching behavior
|
||||
/// between siblings that are otherwise identical as far as the cache is
|
||||
/// concerned.
|
||||
fn visit_simple_selector(&mut self, s: &Component<SelectorImpl>) -> bool {
|
||||
match *s {
|
||||
Component::AttrExists(_) |
|
||||
|
@ -970,23 +997,7 @@ impl SelectorVisitor for RevalidationVisitor {
|
|||
/// Returns true if the given selector needs cache revalidation.
|
||||
pub fn needs_revalidation(selector: &Selector<SelectorImpl>) -> bool {
|
||||
let mut visitor = RevalidationVisitor;
|
||||
|
||||
// We only need to consider the rightmost sequence of simple selectors, so
|
||||
// we can stop at the first combinator. This is because:
|
||||
// * If it's an ancestor combinator, we can ignore everything to the left
|
||||
// because matching won't differ between siblings.
|
||||
// * If it's a sibling combinator, then we know we need revalidation.
|
||||
let mut iter = selector.inner.complex.iter();
|
||||
for ss in &mut iter {
|
||||
if !ss.visit(&mut visitor) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If none of the simple selectors in the rightmost sequence required
|
||||
// revalidation, we need revalidation if and only if the combinator is a
|
||||
// sibling combinator.
|
||||
iter.next_sequence().map_or(false, |c| c.is_sibling())
|
||||
!selector.visit(&mut visitor)
|
||||
}
|
||||
|
||||
/// Map that contains the CSS rules for a specific PseudoElement
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#![allow(non_camel_case_types)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(link_args)]
|
||||
|
||||
#[macro_use]
|
||||
|
|
|
@ -12,9 +12,7 @@ macro_rules! stub(
|
|||
#[allow(non_snake_case)]
|
||||
pub extern "C" fn $name() {
|
||||
println!("CEF stub function called: {}", stringify!($name));
|
||||
unsafe {
|
||||
::std::intrinsics::abort()
|
||||
}
|
||||
::std::process::abort()
|
||||
}
|
||||
)
|
||||
);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
//!
|
||||
//! [glutin]: https://github.com/tomaka/glutin
|
||||
|
||||
#![feature(start, core_intrinsics)]
|
||||
#![feature(start)]
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
extern crate android_injected_glue;
|
||||
|
@ -58,7 +58,7 @@ pub mod platform {
|
|||
fn install_crash_handler() {
|
||||
use backtrace::Backtrace;
|
||||
use sig::ffi::Sig;
|
||||
use std::intrinsics::abort;
|
||||
use std::process::abort;
|
||||
use std::thread;
|
||||
|
||||
fn handler(_sig: i32) {
|
||||
|
@ -67,9 +67,7 @@ fn install_crash_handler() {
|
|||
.map(|n| format!(" for thread \"{}\"", n))
|
||||
.unwrap_or("".to_owned());
|
||||
println!("Stack trace{}\n{:?}", name, Backtrace::new());
|
||||
unsafe {
|
||||
abort();
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
||||
signal!(Sig::SEGV, handler); // handle segfaults
|
||||
|
|
|
@ -109,13 +109,11 @@ fn test_revalidation_selectors() {
|
|||
"span + div",
|
||||
"span ~ div",
|
||||
|
||||
// Revalidation selectors that will get sliced.
|
||||
"td > h1[dir]",
|
||||
"td > span + h1[dir]",
|
||||
"table td > span + div ~ h1[dir]",
|
||||
// Selectors in the ancestor chain (needed for cousin sharing).
|
||||
"p:first-child span",
|
||||
]).into_iter()
|
||||
.filter(|s| needs_revalidation(&s))
|
||||
.map(|s| s.inner.slice_to_first_ancestor_combinator().complex)
|
||||
.map(|s| s.inner.complex)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let reference = parse_selectors(&[
|
||||
|
@ -147,10 +145,8 @@ fn test_revalidation_selectors() {
|
|||
"span + div",
|
||||
"span ~ div",
|
||||
|
||||
// Revalidation selectors that got sliced.
|
||||
"h1[dir]",
|
||||
"span + h1[dir]",
|
||||
"span + div ~ h1[dir]",
|
||||
// Selectors in the ancestor chain (needed for cousin sharing).
|
||||
"p:first-child span",
|
||||
]).into_iter()
|
||||
.map(|s| s.inner.complex)
|
||||
.collect::<Vec<_>>();
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "prio.h"
|
||||
#include "prprf.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Printf.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
using namespace JS;
|
||||
|
@ -64,7 +65,7 @@ TestStartupCache::TestStartupCache()
|
|||
mSCFile->AppendNative(NS_LITERAL_CSTRING("test-startupcache.tmp"));
|
||||
nsAutoCString path;
|
||||
mSCFile->GetNativePath(path);
|
||||
char* env = PR_smprintf("MOZ_STARTUP_CACHE=%s", path.get());
|
||||
char* env = mozilla::Smprintf("MOZ_STARTUP_CACHE=%s", path.get()).release();
|
||||
PR_SetEnv(env);
|
||||
// We intentionally leak `env` here because it is required by PR_SetEnv
|
||||
MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(env);
|
||||
|
|
|
@ -314,7 +314,7 @@ EnvHasValue(const char *name)
|
|||
static void
|
||||
SaveWordToEnv(const char *name, const nsACString & word)
|
||||
{
|
||||
char *expr = PR_smprintf("%s=%s", name, PromiseFlatCString(word).get());
|
||||
char *expr = Smprintf("%s=%s", name, PromiseFlatCString(word).get()).release();
|
||||
if (expr)
|
||||
PR_SetEnv(expr);
|
||||
// We intentionally leak |expr| here since it is required by PR_SetEnv.
|
||||
|
@ -2810,7 +2810,7 @@ static void SaveStateForAppInitiatedRestart()
|
|||
for (auto & savedVar : gSavedVars) {
|
||||
const char *s = PR_GetEnv(savedVar.name);
|
||||
if (s)
|
||||
savedVar.value = PR_smprintf("%s=%s", savedVar.name, s);
|
||||
savedVar.value = Smprintf("%s=%s", savedVar.name, s).release();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4415,7 +4415,8 @@ XREMain::XRE_mainRun()
|
|||
char appFile[MAX_PATH];
|
||||
if (GetEnvironmentVariableA("XUL_APP_FILE", appFile, sizeof(appFile))) {
|
||||
SmprintfPointer saved = mozilla::Smprintf("XUL_APP_FILE=%s", appFile);
|
||||
PR_SetEnv(saved.get());
|
||||
// We intentionally leak the string here since it is required by PR_SetEnv.
|
||||
PR_SetEnv(saved.release());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "mozilla/Preferences.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Printf.h"
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#include "nsILocalFileMac.h"
|
||||
|
@ -406,18 +407,15 @@ AppendToLibPath(const char *pathToAppend)
|
|||
{
|
||||
char *pathValue = getenv(LD_LIBRARY_PATH_ENVVAR_NAME);
|
||||
if (nullptr == pathValue || '\0' == *pathValue) {
|
||||
char *s = PR_smprintf("%s=%s", LD_LIBRARY_PATH_ENVVAR_NAME, pathToAppend);
|
||||
// Leak the string because that is required by PR_SetEnv.
|
||||
char *s = Smprintf("%s=%s", LD_LIBRARY_PATH_ENVVAR_NAME, pathToAppend).release();
|
||||
PR_SetEnv(s);
|
||||
} else if (!strstr(pathValue, pathToAppend)) {
|
||||
char *s = PR_smprintf("%s=%s" PATH_SEPARATOR "%s",
|
||||
LD_LIBRARY_PATH_ENVVAR_NAME, pathToAppend, pathValue);
|
||||
// Leak the string because that is required by PR_SetEnv.
|
||||
char *s = Smprintf("%s=%s" PATH_SEPARATOR "%s",
|
||||
LD_LIBRARY_PATH_ENVVAR_NAME, pathToAppend, pathValue).release();
|
||||
PR_SetEnv(s);
|
||||
}
|
||||
|
||||
// The memory used by PR_SetEnv is not copied to the environment on all
|
||||
// platform, it can be used by reference directly. So we purposely do not
|
||||
// call PR_smprintf_free on s. Subsequent calls to PR_SetEnv will free
|
||||
// the old memory first.
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include "nsMemory.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCRTGlue.h"
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
#include "mozilla/Printf.h"
|
||||
|
||||
/***************************************************************************/
|
||||
// Helpers for static convert functions...
|
||||
|
@ -746,7 +748,7 @@ nsDiscriminatedUnion::ConvertToID(nsID* aResult) const
|
|||
nsresult
|
||||
nsDiscriminatedUnion::ToString(nsACString& aOutString) const
|
||||
{
|
||||
char* ptr;
|
||||
mozilla::SmprintfPointer pptr;
|
||||
|
||||
switch (mType) {
|
||||
// all the stuff we don't handle...
|
||||
|
@ -778,16 +780,17 @@ nsDiscriminatedUnion::ToString(nsACString& aOutString) const
|
|||
|
||||
// nsID has its own text formatter.
|
||||
|
||||
case nsIDataType::VTYPE_ID:
|
||||
ptr = u.mIDValue.ToString();
|
||||
case nsIDataType::VTYPE_ID: {
|
||||
char* ptr = u.mIDValue.ToString();
|
||||
if (!ptr) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
aOutString.Assign(ptr);
|
||||
free(ptr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Can't use PR_smprintf for floats, since it's locale-dependent
|
||||
// Can't use Smprintf for floats, since it's locale-dependent
|
||||
#define CASE__APPENDFLOAT_NUMBER(type_, member_) \
|
||||
case nsIDataType::type_ : \
|
||||
{ \
|
||||
|
@ -802,22 +805,24 @@ nsDiscriminatedUnion::ToString(nsACString& aOutString) const
|
|||
|
||||
#undef CASE__APPENDFLOAT_NUMBER
|
||||
|
||||
// the rest can be PR_smprintf'd and use common code.
|
||||
// the rest can be Smprintf'd and use common code.
|
||||
|
||||
#define CASE__SMPRINTF_NUMBER(type_, format_, cast_, member_) \
|
||||
case nsIDataType::type_: \
|
||||
ptr = PR_smprintf( format_ , (cast_) u.member_); \
|
||||
static_assert(sizeof(cast_) >= sizeof(u.member_), \
|
||||
"size of type should be at least as big as member"); \
|
||||
pptr = mozilla::Smprintf( format_ , (cast_) u.member_); \
|
||||
break;
|
||||
|
||||
CASE__SMPRINTF_NUMBER(VTYPE_INT8, "%d", int, mInt8Value)
|
||||
CASE__SMPRINTF_NUMBER(VTYPE_INT16, "%d", int, mInt16Value)
|
||||
CASE__SMPRINTF_NUMBER(VTYPE_INT32, "%d", int, mInt32Value)
|
||||
CASE__SMPRINTF_NUMBER(VTYPE_INT64, "%lld", int64_t, mInt64Value)
|
||||
CASE__SMPRINTF_NUMBER(VTYPE_INT64, "%" PRId64, int64_t, mInt64Value)
|
||||
|
||||
CASE__SMPRINTF_NUMBER(VTYPE_UINT8, "%u", unsigned, mUint8Value)
|
||||
CASE__SMPRINTF_NUMBER(VTYPE_UINT16, "%u", unsigned, mUint16Value)
|
||||
CASE__SMPRINTF_NUMBER(VTYPE_UINT32, "%u", unsigned, mUint32Value)
|
||||
CASE__SMPRINTF_NUMBER(VTYPE_UINT64, "%llu", int64_t, mUint64Value)
|
||||
CASE__SMPRINTF_NUMBER(VTYPE_UINT64, "%" PRIu64, int64_t, mUint64Value)
|
||||
|
||||
// XXX Would we rather print "true" / "false" ?
|
||||
CASE__SMPRINTF_NUMBER(VTYPE_BOOL, "%d", int, mBoolValue)
|
||||
|
@ -827,11 +832,10 @@ nsDiscriminatedUnion::ToString(nsACString& aOutString) const
|
|||
#undef CASE__SMPRINTF_NUMBER
|
||||
}
|
||||
|
||||
if (!ptr) {
|
||||
if (!pptr) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
aOutString.Assign(ptr);
|
||||
PR_smprintf_free(ptr);
|
||||
aOutString.Assign(pptr.get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче