Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2015-07-24 13:03:36 +02:00
Родитель 033560bf9f cbae5434a4
Коммит 7074581085
88 изменённых файлов: 3196 добавлений и 1337 удалений

Просмотреть файл

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 1186003 needed a CLOBBER
Bug 965151 needed a CLOBBER

Просмотреть файл

@ -835,47 +835,50 @@ Accessible::HandleAccEvent(AccEvent* aEvent)
if (IPCAccessibilityActive() && Document()) {
DocAccessibleChild* ipcDoc = mDoc->IPCDoc();
uint64_t id = aEvent->GetAccessible()->IsDoc() ? 0 :
reinterpret_cast<uintptr_t>(aEvent->GetAccessible());
MOZ_ASSERT(ipcDoc);
if (ipcDoc) {
uint64_t id = aEvent->GetAccessible()->IsDoc() ? 0 :
reinterpret_cast<uintptr_t>(aEvent->GetAccessible());
switch(aEvent->GetEventType()) {
case nsIAccessibleEvent::EVENT_SHOW:
ipcDoc->ShowEvent(downcast_accEvent(aEvent));
break;
switch(aEvent->GetEventType()) {
case nsIAccessibleEvent::EVENT_SHOW:
ipcDoc->ShowEvent(downcast_accEvent(aEvent));
break;
case nsIAccessibleEvent::EVENT_HIDE:
ipcDoc->SendHideEvent(id);
break;
case nsIAccessibleEvent::EVENT_HIDE:
ipcDoc->SendHideEvent(id);
break;
case nsIAccessibleEvent::EVENT_REORDER:
// reorder events on the application acc aren't necessary to tell the parent
// about new top level documents.
if (!aEvent->GetAccessible()->IsApplication())
ipcDoc->SendEvent(id, aEvent->GetEventType());
break;
case nsIAccessibleEvent::EVENT_STATE_CHANGE: {
AccStateChangeEvent* event = downcast_accEvent(aEvent);
ipcDoc->SendStateChangeEvent(id, event->GetState(),
event->IsStateEnabled());
break;
}
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED: {
AccCaretMoveEvent* event = downcast_accEvent(aEvent);
ipcDoc->SendEvent(id, event->GetCaretOffset());
break;
}
case nsIAccessibleEvent::EVENT_TEXT_INSERTED:
case nsIAccessibleEvent::EVENT_TEXT_REMOVED: {
AccTextChangeEvent* event = downcast_accEvent(aEvent);
ipcDoc->SendTextChangeEvent(id, event->ModifiedText(),
event->GetStartOffset(),
event->GetLength(),
event->IsTextInserted(),
event->IsFromUserInput());
break;
}
default:
ipcDoc->SendEvent(id, aEvent->GetEventType());
case nsIAccessibleEvent::EVENT_REORDER:
// reorder events on the application acc aren't necessary to tell the parent
// about new top level documents.
if (!aEvent->GetAccessible()->IsApplication())
ipcDoc->SendEvent(id, aEvent->GetEventType());
break;
case nsIAccessibleEvent::EVENT_STATE_CHANGE: {
AccStateChangeEvent* event = downcast_accEvent(aEvent);
ipcDoc->SendStateChangeEvent(id, event->GetState(),
event->IsStateEnabled());
break;
}
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED: {
AccCaretMoveEvent* event = downcast_accEvent(aEvent);
ipcDoc->SendEvent(id, event->GetCaretOffset());
break;
}
case nsIAccessibleEvent::EVENT_TEXT_INSERTED:
case nsIAccessibleEvent::EVENT_TEXT_REMOVED: {
AccTextChangeEvent* event = downcast_accEvent(aEvent);
ipcDoc->SendTextChangeEvent(id, event->ModifiedText(),
event->GetStartOffset(),
event->GetLength(),
event->IsTextInserted(),
event->IsFromUserInput());
break;
}
default:
ipcDoc->SendEvent(id, aEvent->GetEventType());
}
}
}

Просмотреть файл

@ -47,6 +47,15 @@ public:
SendShutdown();
}
virtual void ActorDestroy(ActorDestroyReason) override
{
if (!mDoc)
return;
mDoc->SetIPCDoc(nullptr);
mDoc = nullptr;
}
void ShowEvent(AccShowEvent* aShowEvent);
/*

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ec2199b324304d3678b6a98a08a31bdc13c9e984"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="db299103dd17a873cba4ff88e62ec173bf80fe62"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ec2199b324304d3678b6a98a08a31bdc13c9e984"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="db299103dd17a873cba4ff88e62ec173bf80fe62"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ec2199b324304d3678b6a98a08a31bdc13c9e984"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="db299103dd17a873cba4ff88e62ec173bf80fe62"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8bc59310552179f9a8bc6cdd0188e2475df52fb7"/>

Просмотреть файл

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ec2199b324304d3678b6a98a08a31bdc13c9e984"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="db299103dd17a873cba4ff88e62ec173bf80fe62"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b587ca868ee75758959c2470a9c35a21299377f"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ec2199b324304d3678b6a98a08a31bdc13c9e984"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="db299103dd17a873cba4ff88e62ec173bf80fe62"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ec2199b324304d3678b6a98a08a31bdc13c9e984"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="db299103dd17a873cba4ff88e62ec173bf80fe62"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ec2199b324304d3678b6a98a08a31bdc13c9e984"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="db299103dd17a873cba4ff88e62ec173bf80fe62"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8bc59310552179f9a8bc6cdd0188e2475df52fb7"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ec2199b324304d3678b6a98a08a31bdc13c9e984"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="db299103dd17a873cba4ff88e62ec173bf80fe62"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "ec2199b324304d3678b6a98a08a31bdc13c9e984",
"git_revision": "db299103dd17a873cba4ff88e62ec173bf80fe62",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "8d48ae501c1ccc26fd2160388fb6094756924da0",
"revision": "16f2c422168acd350ff048a22d39297e60508059",
"repo_path": "integration/gaia-central"
}

Просмотреть файл

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ec2199b324304d3678b6a98a08a31bdc13c9e984"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="db299103dd17a873cba4ff88e62ec173bf80fe62"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b587ca868ee75758959c2470a9c35a21299377f"/>

Просмотреть файл

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ec2199b324304d3678b6a98a08a31bdc13c9e984"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="db299103dd17a873cba4ff88e62ec173bf80fe62"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

Просмотреть файл

@ -1931,7 +1931,7 @@ pref("browser.tabs.remote.autostart.2", true);
#endif
#ifdef NIGHTLY_BUILD
#if defined(XP_MACOSX)
#if defined(XP_MACOSX) || defined(XP_WIN)
pref("layers.async-pan-zoom.enabled", true);
#endif
#endif

Просмотреть файл

@ -1,8 +1,7 @@
no_tooltool=1
no_sccache=1
. $topsrcdir/browser/config/mozconfigs/linux32/nightly
ac_add_options --enable-default-toolkit=cairo-gtk2
ac_add_options --enable-valgrind
ac_add_options --disable-jemalloc
ac_add_options --disable-install-strip

Просмотреть файл

@ -1,8 +1,7 @@
no_tooltool=1
no_sccache=1
. $topsrcdir/browser/config/mozconfigs/linux64/nightly
ac_add_options --enable-default-toolkit=cairo-gtk2
ac_add_options --enable-valgrind
ac_add_options --disable-jemalloc
ac_add_options --disable-install-strip

Просмотреть файл

@ -0,0 +1,16 @@
[
{
"size": 80458572,
"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
"algorithm": "sha512",
"filename": "gcc.tar.xz",
"unpack": true
},
{
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
"filename": "sccache.tar.bz2",
"unpack": true
}
]

Просмотреть файл

@ -0,0 +1,16 @@
[
{
"size": 80458572,
"digest": "e5101f9dee1e462f6cbd3897ea57eede41d23981825c7b20d91d23ab461875d54d3dfc24999aa58a31e8b01f49fb3140e05ffe5af2957ef1d1afb89fd0dfe1ad",
"algorithm": "sha512",
"filename": "gcc.tar.xz",
"unpack": true
},
{
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
"filename": "sccache.tar.bz2",
"unpack": true
}
]

45
build/valgrind/valgrind.sh Executable file
Просмотреть файл

@ -0,0 +1,45 @@
#!/bin/bash
set -e
set -x
srcdir=$PWD/src
objdir=${MOZ_OBJDIR-objdir}
# If the objdir is a relative path, it is relative to the srcdir.
case "$objdir" in
/*)
;;
*)
objdir="$srcdir/$objdir"
;;
esac
if [ ! -d $objdir ]; then
mkdir $objdir
fi
cd $objdir
if [ "`uname -m`" = "x86_64" ]; then
_arch=64
else
_arch=32
fi
TOOLTOOL_MANIFEST=browser/config/tooltool-manifests/linux${_arch}/valgrind.manifest
TOOLTOOL_SERVER=https://api.pub.build.mozilla.org/tooltool/
(cd $srcdir; python /builds/tooltool.py --url $TOOLTOOL_SERVER --overwrite -m $TOOLTOOL_MANIFEST fetch ${TOOLTOOL_CACHE:+ -c ${TOOLTOOL_CACHE}}) || exit 2
# Note: an exit code of 2 turns the job red on TBPL.
MOZCONFIG=$srcdir/browser/config/mozconfigs/linux${_arch}/valgrind make -f $srcdir/client.mk configure || exit 2
make -j4 || exit 2
make package || exit 2
# We need to set MOZBUILD_STATE_PATH so that |mach| skips its first-run
# initialization step and actually runs the |valgrind-test| command.
export MOZBUILD_STATE_PATH=.
# |mach valgrind-test|'s exit code will be 1 (which turns the job orange on
# TBPL) if Valgrind finds errors, and 2 (which turns the job red) if something
# else goes wrong, such as Valgrind crashing.
python2.7 $srcdir/mach valgrind-test
exit $?

Просмотреть файл

@ -14059,7 +14059,10 @@ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNavigate,
bool isThirdPartyURI = true;
result = thirdPartyUtil->IsThirdPartyURI(mCurrentURI, aURI,
&isThirdPartyURI);
NS_ENSURE_SUCCESS(result, result);
if (NS_FAILED(result)) {
return result;
}
if (isThirdPartyURI &&
(Preferences::GetInt("network.cookie.cookieBehavior",
nsICookieService::BEHAVIOR_ACCEPT) ==

Просмотреть файл

@ -344,6 +344,10 @@ NS_IMETHODIMP
ThirdPartyUtil::GetBaseDomain(nsIURI* aHostURI,
nsACString& aBaseDomain)
{
if (!aHostURI) {
return NS_ERROR_INVALID_ARG;
}
// Get the base domain. this will fail if the host contains a leading dot,
// more than one trailing dot, or is otherwise malformed.
nsresult rv = mTLDService->GetBaseDomain(aHostURI, 0, aBaseDomain);
@ -367,7 +371,9 @@ ThirdPartyUtil::GetBaseDomain(nsIURI* aHostURI,
if (aBaseDomain.IsEmpty()) {
bool isFileURI = false;
aHostURI->SchemeIs("file", &isFileURI);
NS_ENSURE_TRUE(isFileURI, NS_ERROR_INVALID_ARG);
if (!isFileURI) {
return NS_ERROR_INVALID_ARG;
}
}
return NS_OK;

Просмотреть файл

@ -2626,18 +2626,16 @@ TabParent::AllocPRenderFrameParent()
TextureFactoryIdentifier textureFactoryIdentifier;
uint64_t layersId = 0;
bool success = false;
if(frameLoader) {
PRenderFrameParent* renderFrame =
new RenderFrameParent(frameLoader,
&textureFactoryIdentifier,
&layersId,
&success);
MOZ_ASSERT(success);
PRenderFrameParent* renderFrame =
new RenderFrameParent(frameLoader,
&textureFactoryIdentifier,
&layersId,
&success);
if (success) {
AddTabParentToTable(layersId, this);
return renderFrame;
} else {
return nullptr;
}
return renderFrame;
}
bool

Просмотреть файл

@ -337,8 +337,22 @@ UpgradeHostToOriginAndInsert(const nsACString& aHost, const nsAFlatCString& aTyp
rv = histSrv->GetNewQuery(getter_AddRefs(histQuery));
NS_ENSURE_SUCCESS(rv, rv);
// We want to only find history items for this particular host, and subdomains
rv = histQuery->SetDomain(aHost);
// Get the eTLD+1 of the domain
nsAutoCString eTLD1;
nsCOMPtr<nsIEffectiveTLDService> tldService =
do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
MOZ_ASSERT(tldService); // We should always have a tldService
if (tldService) {
rv = tldService->GetBaseDomainFromHost(aHost, 0, eTLD1);
NS_ENSURE_SUCCESS(rv, rv);
} else {
// We should never hit this branch, but we produce a fake eTLD1
// to avoid crashing in a release build in case we hit this branch
eTLD1 = aHost;
}
// We want to only find history items for this particular eTLD+1, and subdomains
rv = histQuery->SetDomain(eTLD1);
NS_ENSURE_SUCCESS(rv, rv);
rv = histQuery->SetDomainIsHost(false);
@ -380,11 +394,11 @@ UpgradeHostToOriginAndInsert(const nsACString& aHost, const nsAFlatCString& aTyp
for (uint32_t i = 0; i < childCount; i++) {
nsCOMPtr<nsINavHistoryResultNode> child;
histResultContainer->GetChild(i, getter_AddRefs(child));
if (NS_FAILED(rv)) continue;
if (NS_WARN_IF(NS_FAILED(rv))) continue;
uint32_t type;
rv = child->GetType(&type);
if (NS_FAILED(rv) || type != nsINavHistoryResultNode::RESULT_TYPE_URI) {
if (NS_WARN_IF(NS_FAILED(rv)) || type != nsINavHistoryResultNode::RESULT_TYPE_URI) {
NS_WARNING("Unexpected non-RESULT_TYPE_URI node in "
"UpgradeHostToOriginAndInsert()");
continue;
@ -392,24 +406,24 @@ UpgradeHostToOriginAndInsert(const nsACString& aHost, const nsAFlatCString& aTyp
nsAutoCString uriSpec;
rv = child->GetUri(uriSpec);
if (NS_FAILED(rv)) continue;
if (NS_WARN_IF(NS_FAILED(rv))) continue;
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), uriSpec);
if (NS_FAILED(rv)) continue;
if (NS_WARN_IF(NS_FAILED(rv))) continue;
// Use the provided host - this URI may be for a subdomain, rather than the host we care about.
rv = uri->SetHost(aHost);
if (NS_FAILED(rv)) continue;
if (NS_WARN_IF(NS_FAILED(rv))) continue;
// We now have a URI which we can make a nsIPrincipal out of
nsCOMPtr<nsIPrincipal> principal;
rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal));
if (NS_FAILED(rv)) continue;
if (NS_WARN_IF(NS_FAILED(rv))) continue;
nsAutoCString origin;
rv = principal->GetOrigin(origin);
if (NS_FAILED(rv)) continue;
if (NS_WARN_IF(NS_FAILED(rv))) continue;
// Ensure that we don't insert the same origin repeatedly
if (insertedOrigins.Contains(origin)) {
@ -419,7 +433,7 @@ UpgradeHostToOriginAndInsert(const nsACString& aHost, const nsAFlatCString& aTyp
foundHistory = true;
rv = aHelper->Insert(origin, aType, aPermission,
aExpireType, aExpireTime, aModificationTime);
NS_WARN_IF(NS_FAILED(rv));
NS_WARN_IF(NS_WARN_IF(NS_FAILED(rv)));
insertedOrigins.PutEntry(origin);
}
@ -600,7 +614,7 @@ nsPermissionManager::AppClearDataObserverInit()
// nsPermissionManager Implementation
#define PERMISSIONS_FILE_NAME "permissions.sqlite"
#define HOSTS_SCHEMA_VERSION 6
#define HOSTS_SCHEMA_VERSION 7
#define HOSTPERM_FILE_NAME "hostperm.1"
@ -822,7 +836,7 @@ nsPermissionManager::InitDB(bool aRemoveFile)
"ALTER TABLE moz_hosts ADD isInBrowserElement INTEGER"));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION);
rv = mDBConn->SetSchemaVersion(3);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -839,144 +853,71 @@ nsPermissionManager::InitDB(bool aRemoveFile)
// now() would mean, eg, that doing "remove all from the last hour"
// within the first hour after migration would remove all permissions.
rv = mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION);
rv = mDBConn->SetSchemaVersion(4);
NS_ENSURE_SUCCESS(rv, rv);
}
// fall through to the next upgrade
// Version 4->5 is the merging of host, appId, and isInBrowserElement into origin
case 4:
{
bool tableExists = false;
mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts_new"), &tableExists);
if (tableExists) {
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DROP TABLE moz_hosts_new"));
NS_ENSURE_SUCCESS(rv, rv);
}
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE moz_hosts_new ("
" id INTEGER PRIMARY KEY"
",origin TEXT"
",type TEXT"
",permission INTEGER"
",expireType INTEGER"
",expireTime INTEGER"
",modificationTime INTEGER"
")"));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<mozIStorageStatement> stmt;
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement "
"FROM moz_hosts"), getter_AddRefs(stmt));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<mozIStoragePendingStatement> pending;
int64_t id = 0;
nsAutoCString host, type;
uint32_t permission;
uint32_t expireType;
int64_t expireTime;
int64_t modificationTime;
uint32_t appId;
bool isInBrowserElement;
bool hasResult;
rv = mDBConn->BeginTransaction();
NS_ENSURE_SUCCESS(rv, rv);
while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
// Read in the old row
rv = stmt->GetUTF8String(0, host);
if (NS_FAILED(rv)) {
continue;
}
rv = stmt->GetUTF8String(1, type);
if (NS_FAILED(rv)) {
continue;
}
permission = stmt->AsInt32(2);
expireType = stmt->AsInt32(3);
expireTime = stmt->AsInt64(4);
modificationTime = stmt->AsInt64(5);
if (stmt->AsInt64(6) < 0) {
continue;
}
appId = static_cast<uint32_t>(stmt->AsInt64(6));
isInBrowserElement = static_cast<bool>(stmt->AsInt32(7));
UpgradeHostToOriginDBMigration upHelper(mDBConn, &id);
rv = UpgradeHostToOriginAndInsert(host, type, permission,
expireType, expireTime,
modificationTime, appId,
isInBrowserElement,
&upHelper);
if (NS_FAILED(rv)) {
NS_WARNING("Unexpected failure when upgrading migrating permission from host to origin");
}
}
rv = mDBConn->CommitTransaction();
NS_ENSURE_SUCCESS(rv, rv);
// We rename the old table to moz_hosts_v4 instead of dropping it, such that if
// we discover that there was a problem with our migration code in the future, we have information
// to roll-back with.
bool v4TableExists = false;
mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts_v4"), &v4TableExists);
if (!v4TableExists) {
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("ALTER TABLE moz_hosts RENAME TO moz_hosts_v4"));
NS_ENSURE_SUCCESS(rv, rv);
} else {
NS_WARNING("moz_hosts was not renamed to moz_hosts_v4, as a moz_hosts_v4 table already exists");
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DROP TABLE moz_hosts"));
NS_ENSURE_SUCCESS(rv, rv);
}
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("ALTER TABLE moz_hosts_new RENAME TO moz_hosts"));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION);
NS_ENSURE_SUCCESS(rv, rv);
}
// fall through to the next upgrade
// Version 5->6 is the renaming of moz_hosts to moz_perms, and moz_hosts_v4 to moz_hosts
// In version 5, host appId, and isInBrowserElement were merged into a
// single origin entry
//
// In version 5, we performed the modifications to the permissions database
// in place, this meant that if you upgraded to a version which used V5, and
// then downgraded to a version which used v4 or earlier, the fallback path
// would drop the table, and your permissions data would be lost.
// This migration undoes that mistake, by restoring the old moz_hosts table
// (if it was present), and instead using the new table moz_perms for the
// new permissions schema.
// NOTE: If you downgrade, store new permissions, and then upgrade again,
// these new permissions won't be migrated or reflected in the updated
// database. This migration only occurs once, as if moz_perms exists, it
// will skip creating it. In addition, permissions added after the migration
// will not be visible in previous versions of firefox.
// In version 6, the tables were renamed for backwards compatability reasons
// with version 4 and earlier.
//
// In version 7, a bug in the migration used for version 4->5 was discovered
// which could have triggered data-loss. Because of that, all users with a
// version 4, 5, or 6 database will be re-migrated from the backup database.
// (bug 1186034). This migration bug is not present after bug 1185340, and the
// re-migration ensures that all users have the fix.
case 5:
{
// This branch could also be reached via dbSchemaVersion == 3, in which case
// we want to fall through to the dbSchemaVersion == 4 case.
// The easiest way to do that is to perform this extra check here to make
// sure that we didn't get here via a fallthrough from v3
if (dbSchemaVersion == 5) {
// In version 5, the backup database is named moz_hosts_v4. We perform
// the version 5->6 migration to get the tables to have consistent
// naming conventions.
// Version 5->6 is the renaming of moz_hosts to moz_perms, and
// moz_hosts_v4 to moz_hosts (bug 1185343)
//
// In version 5, we performed the modifications to the permissions
// database in place, this meant that if you upgraded to a version which
// used V5, and then downgraded to a version which used v4 or earlier,
// the fallback path would drop the table, and your permissions data
// would be lost. This migration undoes that mistake, by restoring the
// old moz_hosts table (if it was present), and instead using the new
// table moz_perms for the new permissions schema.
//
// NOTE: If you downgrade, store new permissions, and then upgrade
// again, these new permissions won't be migrated or reflected in the
// updated database. This migration only occurs once, as if moz_perms
// exists, it will skip creating it. In addition, permissions added
// after the migration will not be visible in previous versions of
// firefox.
bool permsTableExists = false;
mDBConn->TableExists(NS_LITERAL_CSTRING("moz_perms"), &permsTableExists);
if (!permsTableExists) {
// Move the upgraded database to moz_perms
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("ALTER TABLE moz_hosts RENAME TO moz_perms"));
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"ALTER TABLE moz_hosts RENAME TO moz_perms"));
NS_ENSURE_SUCCESS(rv, rv);
} else {
NS_WARNING("moz_hosts was not renamed to moz_perms, as a moz_perms table already exists");
NS_WARNING("moz_hosts was not renamed to moz_perms, "
"as a moz_perms table already exists");
// In the situation where a moz_perms table already exists, but the schema is lower than 6,
// a migration has already previously occured to V6, but a downgrade has caused the moz_hosts
// table to be dropped. This should only occur in the case of a downgrade to a V5 database,
// which was only present in a few day's nightlies. As that version was likely used only on
// a very temporary basis, we assume that the database from the previous V6 has the permissions
// which the user actually wants to use.
// We have to get rid of moz_hosts such that moz_hosts_v4 can be moved into its place if it exists.
// In the situation where a moz_perms table already exists, but the
// schema is lower than 6, a migration has already previously occured
// to V6, but a downgrade has caused the moz_hosts table to be
// dropped. This should only occur in the case of a downgrade to a V5
// database, which was only present in a few day's nightlies. As that
// version was likely used only on a temporary basis, we assume that
// the database from the previous V6 has the permissions which the
// user actually wants to use. We have to get rid of moz_hosts such
// that moz_hosts_v4 can be moved into its place if it exists.
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DROP TABLE moz_hosts"));
NS_ENSURE_SUCCESS(rv, rv);
}
@ -992,11 +933,209 @@ nsPermissionManager::InitDB(bool aRemoveFile)
bool v4TableExists = false;
mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts_v4"), &v4TableExists);
if (v4TableExists) {
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("ALTER TABLE moz_hosts_v4 RENAME TO moz_hosts"));
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"ALTER TABLE moz_hosts_v4 RENAME TO moz_hosts"));
NS_ENSURE_SUCCESS(rv, rv);
}
rv = mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION);
rv = mDBConn->SetSchemaVersion(6);
NS_ENSURE_SUCCESS(rv, rv);
}
// fall through to the next upgrade
// At this point, the version 5 table has been migrated to a version 6 table
// We are guaranteed to have at least one of moz_hosts and moz_perms. If
// we have moz_hosts, we will migrate moz_hosts into moz_perms (even if
// we already have a moz_perms, as we need a re-migration due to bug 1186034).
//
// After this migration, we are guaranteed to have both a moz_hosts (for backwards
// compatability), and a moz_perms table. The moz_hosts table will have a v4 schema,
// and the moz_perms table will have a v6 schema.
case 4:
case 6:
{
bool hostsTableExists = false;
mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts"), &hostsTableExists);
if (hostsTableExists) {
bool migrationError = false;
// Both versions 4 and 6 have a version 4 formatted hosts table named
// moz_hosts. We can migrate this table to our version 7 table moz_perms.
// If moz_perms is present, then we can use it as a basis for comparison.
rv = mDBConn->BeginTransaction();
NS_ENSURE_SUCCESS(rv, rv);
bool tableExists = false;
mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts_new"), &tableExists);
if (tableExists) {
NS_WARNING("The temporary database moz_hosts_new already exists, dropping it.");
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DROP TABLE moz_hosts_new"));
NS_ENSURE_SUCCESS(rv, rv);
}
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE moz_hosts_new ("
" id INTEGER PRIMARY KEY"
",origin TEXT"
",type TEXT"
",permission INTEGER"
",expireType INTEGER"
",expireTime INTEGER"
",modificationTime INTEGER"
")"));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<mozIStorageStatement> stmt;
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT host, type, permission, expireType, expireTime, "
"modificationTime, appId, isInBrowserElement FROM moz_hosts"),
getter_AddRefs(stmt));
NS_ENSURE_SUCCESS(rv, rv);
int64_t id = 0;
nsAutoCString host, type;
uint32_t permission;
uint32_t expireType;
int64_t expireTime;
int64_t modificationTime;
uint32_t appId;
bool isInBrowserElement;
bool hasResult;
while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
// Read in the old row
rv = stmt->GetUTF8String(0, host);
if (NS_WARN_IF(NS_FAILED(rv))) {
migrationError = true;
continue;
}
rv = stmt->GetUTF8String(1, type);
if (NS_WARN_IF(NS_FAILED(rv))) {
migrationError = true;
continue;
}
permission = stmt->AsInt32(2);
expireType = stmt->AsInt32(3);
expireTime = stmt->AsInt64(4);
modificationTime = stmt->AsInt64(5);
if (NS_WARN_IF(stmt->AsInt64(6) < 0)) {
migrationError = true;
continue;
}
appId = static_cast<uint32_t>(stmt->AsInt64(6));
isInBrowserElement = static_cast<bool>(stmt->AsInt32(7));
// Perform the meat of the migration by deferring to the
// UpgradeHostToOriginAndInsert function.
UpgradeHostToOriginDBMigration upHelper(mDBConn, &id);
rv = UpgradeHostToOriginAndInsert(host, type, permission,
expireType, expireTime,
modificationTime, appId,
isInBrowserElement,
&upHelper);
if (NS_FAILED(rv)) {
NS_WARNING("Unexpected failure when upgrading migrating permission "
"from host to origin");
migrationError = true;
}
}
// We don't drop the moz_hosts table such that it is avaliable for
// backwards-compatability and for future migrations in case of
// migration errors in the current code.
// Create a marker empty table which will indicate that the moz_hosts
// table is intended to act as a backup. If this table is not present,
// then the moz_hosts table was created as a random empty table.
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE moz_hosts_is_backup (dummy INTEGER PRIMARY KEY)"));
NS_ENSURE_SUCCESS(rv, rv);
bool permsTableExists = false;
mDBConn->TableExists(NS_LITERAL_CSTRING("moz_perms"), &permsTableExists);
if (permsTableExists) {
// The user already had a moz_perms table, and we are performing a
// re-migration. We count the rows in the old table for telemetry,
// and then back up their old database as moz_perms_v6
nsCOMPtr<mozIStorageStatement> countStmt;
mDBConn->CreateStatement(NS_LITERAL_CSTRING("SELECT COUNT(*) FROM moz_perms"),
getter_AddRefs(countStmt));
bool hasResult = false;
if (NS_SUCCEEDED(rv) &&
NS_SUCCEEDED(countStmt->ExecuteStep(&hasResult)) &&
hasResult) {
int32_t permsCount = countStmt->AsInt32(0);
// The id variable contains the number of rows inserted into the
// moz_hosts_new table (as one ID was used per entry)
uint32_t telemetryValue;
if (permsCount > id) {
telemetryValue = 3; // NEW > OLD
} else if (permsCount == id) {
telemetryValue = 2; // NEW == OLD
} else if (permsCount == 0) {
telemetryValue = 0; // NEW = 0
} else {
telemetryValue = 1; // NEW < OLD
}
// Report the telemetry value to telemetry
mozilla::Telemetry::Accumulate(
mozilla::Telemetry::PERMISSIONS_REMIGRATION_COMPARISON,
telemetryValue);
} else {
NS_WARNING("Could not count the rows in moz_perms");
}
// Back up the old moz_perms database as moz_perms_v6 before we
// move the new table into its position
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"ALTER TABLE moz_perms RENAME TO moz_perms_v6"));
NS_ENSURE_SUCCESS(rv, rv);
}
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"ALTER TABLE moz_hosts_new RENAME TO moz_perms"));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBConn->CommitTransaction();
NS_ENSURE_SUCCESS(rv, rv);
mozilla::Telemetry::Accumulate(mozilla::Telemetry::PERMISSIONS_MIGRATION_7_ERROR,
NS_WARN_IF(migrationError));
} else {
// We don't have a moz_hosts table, so we create one for downgrading purposes.
// This table is empty.
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE moz_hosts ("
" id INTEGER PRIMARY KEY"
",host TEXT"
",type TEXT"
",permission INTEGER"
",expireType INTEGER"
",expireTime INTEGER"
",modificationTime INTEGER"
",appId INTEGER"
",isInBrowserElement INTEGER"
")"));
NS_ENSURE_SUCCESS(rv, rv);
// We are guaranteed to have a moz_perms table at this point.
}
#ifdef DEBUG
{
// At this point, both the moz_hosts and moz_perms tables should exist
bool hostsTableExists = false;
bool permsTableExists = false;
mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts"), &hostsTableExists);
mDBConn->TableExists(NS_LITERAL_CSTRING("moz_perms"), &permsTableExists);
MOZ_ASSERT(hostsTableExists && permsTableExists);
}
#endif
rv = mDBConn->SetSchemaVersion(7);
NS_ENSURE_SUCCESS(rv, rv);
}
@ -1015,8 +1154,9 @@ nsPermissionManager::InitDB(bool aRemoveFile)
// check if all the expected columns exist
nsCOMPtr<mozIStorageStatement> stmt;
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT origin, type, permission, expireType, expireTime, modificationTime FROM moz_perms"),
getter_AddRefs(stmt));
"SELECT origin, type, permission, expireType, expireTime, "
"modificationTime FROM moz_perms"),
getter_AddRefs(stmt));
if (NS_SUCCEEDED(rv))
break;
@ -1069,7 +1209,7 @@ nsPermissionManager::CreateTable()
// create the table
// SQL also lives in automation.py.in. If you change this SQL change that
// one too
return mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE moz_perms ("
" id INTEGER PRIMARY KEY"
",origin TEXT"
@ -1079,6 +1219,22 @@ nsPermissionManager::CreateTable()
",expireTime INTEGER"
",modificationTime INTEGER"
")"));
if (NS_FAILED(rv)) return rv;
// We also create a legacy V4 table, for backwards compatability,
// and to ensure that downgrades don't trigger a schema version change.
return mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE moz_hosts ("
" id INTEGER PRIMARY KEY"
",host TEXT"
",type TEXT"
",permission INTEGER"
",expireType INTEGER"
",expireTime INTEGER"
",modificationTime INTEGER"
",appId INTEGER"
",isInBrowserElement INTEGER"
")"));
}
NS_IMETHODIMP

Просмотреть файл

@ -121,7 +121,7 @@ function run_test() {
// The schema should be upgraded to 6, and a 'modificationTime' column should
// exist with all records having a value of 0.
do_check_eq(connection.schemaVersion, 6);
do_check_eq(connection.schemaVersion, 7);
let select = connection.createStatement("SELECT modificationTime FROM moz_perms")
let numMigrated = 0;

Просмотреть файл

@ -47,7 +47,9 @@ add_task(function test() {
let id = 0;
function insertHost(host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement) {
stmtInsert.bindByName("id", id++);
let thisId = id++;
stmtInsert.bindByName("id", thisId);
stmtInsert.bindByName("host", host);
stmtInsert.bindByName("type", type);
stmtInsert.bindByName("permission", permission);
@ -57,30 +59,39 @@ add_task(function test() {
stmtInsert.bindByName("appId", appId);
stmtInsert.bindByName("isInBrowserElement", isInBrowserElement);
try {
stmtInsert.executeStep();
stmtInsert.reset();
} catch (e) {
stmtInsert.reset();
throw e;
}
stmtInsert.execute();
return {
id: thisId,
host: host,
type: type,
permission: permission,
expireType: expireType,
expireTime: expireTime,
modificationTime: modificationTime,
appId: appId,
isInBrowserElement: isInBrowserElement
};
}
// Add some rows to the database
insertHost("foo.com", "A", 1, 0, 0, 0, 0, false);
insertHost("foo.com", "A", 1, 0, 0, 0, 1000, false);
insertHost("foo.com", "A", 1, 0, 0, 0, 2000, true);
insertHost("sub.foo.com", "B", 1, 0, 0, 0, 0, false);
insertHost("subber.sub.foo.com", "B", 1, 0, 0, 0, 0, false);
insertHost("bar.ca", "B", 1, 0, 0, 0, 0, false);
insertHost("bar.ca", "B", 1, 0, 0, 0, 1000, false);
insertHost("bar.ca", "A", 1, 0, 0, 0, 1000, true);
insertHost("file:///some/path/to/file.html", "A", 1, 0, 0, 0, 0, false);
insertHost("file:///another/file.html", "A", 1, 0, 0, 0, 0, false);
insertHost("moz-nullprincipal:{8695105a-adbe-4e4e-8083-851faa5ca2d7}", "A", 1, 0, 0, 0, 0, false);
insertHost("moz-nullprincipal:{12ahjksd-akjs-asd3-8393-asdu2189asdu}", "B", 1, 0, 0, 0, 0, false);
insertHost("<file>", "A", 1, 0, 0, 0, 0, false);
insertHost("<file>", "B", 1, 0, 0, 0, 0, false);
let created = [
insertHost("foo.com", "A", 1, 0, 0, 0, 0, false),
insertHost("foo.com", "C", 1, 0, 0, 0, 0, false),
insertHost("foo.com", "A", 1, 0, 0, 0, 1000, false),
insertHost("foo.com", "A", 1, 0, 0, 0, 2000, true),
insertHost("sub.foo.com", "B", 1, 0, 0, 0, 0, false),
insertHost("subber.sub.foo.com", "B", 1, 0, 0, 0, 0, false),
insertHost("bar.ca", "B", 1, 0, 0, 0, 0, false),
insertHost("bar.ca", "B", 1, 0, 0, 0, 1000, false),
insertHost("bar.ca", "A", 1, 0, 0, 0, 1000, true),
insertHost("file:///some/path/to/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("file:///another/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("moz-nullprincipal:{8695105a-adbe-4e4e-8083-851faa5ca2d7}", "A", 1, 0, 0, 0, 0, false),
insertHost("moz-nullprincipal:{12ahjksd-akjs-asd3-8393-asdu2189asdu}", "B", 1, 0, 0, 0, 0, false),
insertHost("<file>", "A", 1, 0, 0, 0, 0, false),
insertHost("<file>", "B", 1, 0, 0, 0, 0, false),
];
// CLose the db connection
stmtInsert.finalize();
@ -91,22 +102,23 @@ add_task(function test() {
let expected = [
// The http:// entries under foo.com won't be inserted, as there are history entries for foo.com,
// and http://foo.com or a subdomain are never visited.
// However, permissions for subdomains of foo.com will be present for both http:// and https://,
// as they do not apply to any entry in the history
// ["http://foo.com", "A", 1, 0, 0],
// ["http://foo.com^appId=1000", "A", 1, 0, 0],
// ["http://foo.com^appId=2000&inBrowser=1", "A", 1, 0, 0],
["http://sub.foo.com", "B", 1, 0, 0],
["http://subber.sub.foo.com", "B", 1, 0, 0],
//
// Because we search for port/scheme combinations under eTLD+1, we should not have http:// entries
// for subdomains of foo.com either
// ["http://sub.foo.com", "B", 1, 0, 0],
// ["http://subber.sub.foo.com", "B", 1, 0, 0],
["https://foo.com", "A", 1, 0, 0],
["https://foo.com", "C", 1, 0, 0],
["https://foo.com^appId=1000", "A", 1, 0, 0],
["https://foo.com^appId=2000&inBrowser=1", "A", 1, 0, 0],
["https://sub.foo.com", "B", 1, 0, 0],
["https://subber.sub.foo.com", "B", 1, 0, 0],
// bar.ca will have both http:// and https:// for all entries, because the foo did the bar a favour
// bar.ca will have both http:// and https:// for all entries, because there are no associated history entries
["http://bar.ca", "B", 1, 0, 0],
["https://bar.ca", "B", 1, 0, 0],
["http://bar.ca^appId=1000", "B", 1, 0, 0],
@ -119,8 +131,14 @@ add_task(function test() {
// Because we put ftp://some.subdomain.of.foo.com:8000/some/subdirectory in the history, we should
// also have these entries
["ftp://foo.com:8000", "A", 1, 0, 0],
["ftp://foo.com:8000", "C", 1, 0, 0],
["ftp://foo.com:8000^appId=1000", "A", 1, 0, 0],
["ftp://foo.com:8000^appId=2000&inBrowser=1", "A", 1, 0, 0],
// In addition, because we search for port/scheme combinations under eTLD+1, we should have the
// following entries
["ftp://sub.foo.com:8000", "B", 1, 0, 0],
["ftp://subber.sub.foo.com:8000", "B", 1, 0, 0],
];
let found = expected.map((it) => 0);
@ -159,4 +177,40 @@ add_task(function test() {
found.forEach((count, i) => {
do_check_true(count == 1, "Expected count = 1, got count = " + count + " for permission " + expected[i]);
});
// Check to make sure that all of the tables which we care about are present
{
let db = Services.storage.openDatabase(GetPermissionsFile(profile));
do_check_true(db.tableExists("moz_perms"));
do_check_true(db.tableExists("moz_hosts"));
do_check_true(db.tableExists("moz_hosts_is_backup"));
do_check_false(db.tableExists("moz_perms_v6"));
let mozHostsStmt = db.createStatement("SELECT " +
"host, type, permission, expireType, expireTime, " +
"modificationTime, appId, isInBrowserElement " +
"FROM moz_hosts WHERE id = :id");
// Check that the moz_hosts table still contains the correct values.
created.forEach((it) => {
mozHostsStmt.reset();
mozHostsStmt.bindByName("id", it.id);
mozHostsStmt.executeStep();
do_check_eq(mozHostsStmt.getUTF8String(0), it.host);
do_check_eq(mozHostsStmt.getUTF8String(1), it.type);
do_check_eq(mozHostsStmt.getInt64(2), it.permission);
do_check_eq(mozHostsStmt.getInt64(3), it.expireType);
do_check_eq(mozHostsStmt.getInt64(4), it.expireTime);
do_check_eq(mozHostsStmt.getInt64(5), it.modificationTime);
do_check_eq(mozHostsStmt.getInt64(6), it.appId);
do_check_eq(mozHostsStmt.getInt64(7), it.isInBrowserElement);
});
// Check that there are the right number of values
let mozHostsCount = db.createStatement("SELECT count(*) FROM moz_hosts");
mozHostsCount.executeStep();
do_check_eq(mozHostsCount.getInt64(0), created.length);
db.close();
}
});

Просмотреть файл

@ -0,0 +1,235 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let PERMISSIONS_FILE_NAME = "permissions.sqlite";
/*
* Prevent the nsINavHistoryService from being avaliable for the migration
*/
let CONTRACT_ID = "@mozilla.org/browser/nav-history-service;1";
let factory = {
createInstance: function() {
throw new Error("There is no history service");
},
lockFactory: function() {
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
},
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory])
};
let newClassID = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID();
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
let oldClassID = registrar.contractIDToCID(CONTRACT_ID);
let oldFactory = Components.manager.getClassObject(Cc[CONTRACT_ID], Ci.nsIFactory);
registrar.unregisterFactory(oldClassID, oldFactory);
registrar.registerFactory(newClassID, "", CONTRACT_ID, factory);
function cleanupFactory() {
registrar.unregisterFactory(newClassID, factory);
registrar.registerFactory(oldClassID, "", CONTRACT_ID, oldFactory);
}
function GetPermissionsFile(profile)
{
let file = profile.clone();
file.append(PERMISSIONS_FILE_NAME);
return file;
}
/*
* Done nsINavHistoryService code
*/
function run_test() {
run_next_test();
}
add_task(function test() {
/* Create and set up the permissions database */
let profile = do_get_profile();
// Make sure that we can't resolve the nsINavHistoryService
try {
Cc['@mozilla.org/browser/nav-history-service;1'].getService(Ci.nsINavHistoryService);
do_check_true(false, "There shouldn't have been a nsINavHistoryService");
} catch (e) {
do_check_true(true, "There wasn't a nsINavHistoryService");
}
let db = Services.storage.openDatabase(GetPermissionsFile(profile));
db.schemaVersion = 4;
db.executeSimpleSQL(
"CREATE TABLE moz_hosts (" +
" id INTEGER PRIMARY KEY" +
",host TEXT" +
",type TEXT" +
",permission INTEGER" +
",expireType INTEGER" +
",expireTime INTEGER" +
",modificationTime INTEGER" +
",appId INTEGER" +
",isInBrowserElement INTEGER" +
")");
let stmtInsert = db.createStatement(
"INSERT INTO moz_hosts (" +
"id, host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement" +
") VALUES (" +
":id, :host, :type, :permission, :expireType, :expireTime, :modificationTime, :appId, :isInBrowserElement" +
")");
let id = 0;
function insertHost(host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement) {
let thisId = id++;
stmtInsert.bindByName("id", thisId);
stmtInsert.bindByName("host", host);
stmtInsert.bindByName("type", type);
stmtInsert.bindByName("permission", permission);
stmtInsert.bindByName("expireType", expireType);
stmtInsert.bindByName("expireTime", expireTime);
stmtInsert.bindByName("modificationTime", modificationTime);
stmtInsert.bindByName("appId", appId);
stmtInsert.bindByName("isInBrowserElement", isInBrowserElement);
stmtInsert.execute();
return {
id: thisId,
host: host,
type: type,
permission: permission,
expireType: expireType,
expireTime: expireTime,
modificationTime: modificationTime,
appId: appId,
isInBrowserElement: isInBrowserElement
};
}
// Add some rows to the database
let created = [
insertHost("foo.com", "A", 1, 0, 0, 0, 0, false),
insertHost("foo.com", "C", 1, 0, 0, 0, 0, false),
insertHost("foo.com", "A", 1, 0, 0, 0, 1000, false),
insertHost("foo.com", "A", 1, 0, 0, 0, 2000, true),
insertHost("sub.foo.com", "B", 1, 0, 0, 0, 0, false),
insertHost("subber.sub.foo.com", "B", 1, 0, 0, 0, 0, false),
insertHost("bar.ca", "B", 1, 0, 0, 0, 0, false),
insertHost("bar.ca", "B", 1, 0, 0, 0, 1000, false),
insertHost("bar.ca", "A", 1, 0, 0, 0, 1000, true),
insertHost("file:///some/path/to/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("file:///another/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("moz-nullprincipal:{8695105a-adbe-4e4e-8083-851faa5ca2d7}", "A", 1, 0, 0, 0, 0, false),
insertHost("moz-nullprincipal:{12ahjksd-akjs-asd3-8393-asdu2189asdu}", "B", 1, 0, 0, 0, 0, false),
insertHost("<file>", "A", 1, 0, 0, 0, 0, false),
insertHost("<file>", "B", 1, 0, 0, 0, 0, false),
];
// CLose the db connection
stmtInsert.finalize();
db.close();
stmtInsert = null;
db = null;
let expected = [
["http://foo.com", "A", 1, 0, 0],
["http://foo.com", "C", 1, 0, 0],
["http://foo.com^appId=1000", "A", 1, 0, 0],
["http://foo.com^appId=2000&inBrowser=1", "A", 1, 0, 0],
["http://sub.foo.com", "B", 1, 0, 0],
["http://subber.sub.foo.com", "B", 1, 0, 0],
["https://foo.com", "A", 1, 0, 0],
["https://foo.com", "C", 1, 0, 0],
["https://foo.com^appId=1000", "A", 1, 0, 0],
["https://foo.com^appId=2000&inBrowser=1", "A", 1, 0, 0],
["https://sub.foo.com", "B", 1, 0, 0],
["https://subber.sub.foo.com", "B", 1, 0, 0],
// bar.ca will have both http:// and https:// for all entries, because there are no associated history entries
["http://bar.ca", "B", 1, 0, 0],
["https://bar.ca", "B", 1, 0, 0],
["http://bar.ca^appId=1000", "B", 1, 0, 0],
["https://bar.ca^appId=1000", "B", 1, 0, 0],
["http://bar.ca^appId=1000&inBrowser=1", "A", 1, 0, 0],
["https://bar.ca^appId=1000&inBrowser=1", "A", 1, 0, 0],
["file:///some/path/to/file.html", "A", 1, 0, 0],
["file:///another/file.html", "A", 1, 0, 0],
];
let found = expected.map((it) => 0);
// Force initialization of the nsPermissionManager
let enumerator = Services.perms.enumerator;
while (enumerator.hasMoreElements()) {
let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
let isExpected = false;
expected.forEach((it, i) => {
if (permission.principal.origin == it[0] &&
permission.type == it[1] &&
permission.capability == it[2] &&
permission.expireType == it[3] &&
permission.expireTime == it[4]) {
isExpected = true;
found[i]++;
}
});
do_check_true(isExpected,
"Permission " + (isExpected ? "should" : "shouldn't") +
" be in permission database: " +
permission.principal.origin + ", " +
permission.type + ", " +
permission.capability + ", " +
permission.expireType + ", " +
permission.expireTime);
}
found.forEach((count, i) => {
do_check_true(count == 1, "Expected count = 1, got count = " + count + " for permission " + expected[i]);
});
// Check to make sure that all of the tables which we care about are present
{
let db = Services.storage.openDatabase(GetPermissionsFile(profile));
do_check_true(db.tableExists("moz_perms"));
do_check_true(db.tableExists("moz_hosts"));
do_check_true(db.tableExists("moz_hosts_is_backup"));
do_check_false(db.tableExists("moz_perms_v6"));
let mozHostsStmt = db.createStatement("SELECT " +
"host, type, permission, expireType, expireTime, " +
"modificationTime, appId, isInBrowserElement " +
"FROM moz_hosts WHERE id = :id");
// Check that the moz_hosts table still contains the correct values.
created.forEach((it) => {
mozHostsStmt.reset();
mozHostsStmt.bindByName("id", it.id);
mozHostsStmt.executeStep();
do_check_eq(mozHostsStmt.getUTF8String(0), it.host);
do_check_eq(mozHostsStmt.getUTF8String(1), it.type);
do_check_eq(mozHostsStmt.getInt64(2), it.permission);
do_check_eq(mozHostsStmt.getInt64(3), it.expireType);
do_check_eq(mozHostsStmt.getInt64(4), it.expireTime);
do_check_eq(mozHostsStmt.getInt64(5), it.modificationTime);
do_check_eq(mozHostsStmt.getInt64(6), it.appId);
do_check_eq(mozHostsStmt.getInt64(7), it.isInBrowserElement);
});
// Check that there are the right number of values
let mozHostsCount = db.createStatement("SELECT count(*) FROM moz_hosts");
mozHostsCount.executeStep();
do_check_eq(mozHostsCount.getInt64(0), created.length);
db.close();
}
cleanupFactory();
});

Просмотреть файл

@ -1,175 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let PERMISSIONS_FILE_NAME = "permissions.sqlite";
function GetPermissionsFile(profile)
{
let file = profile.clone();
file.append(PERMISSIONS_FILE_NAME);
return file;
}
function run_test() {
run_next_test();
}
add_task(function test() {
/* Create and set up the permissions database */
let profile = do_get_profile();
let perms = [];
let db = Services.storage.openDatabase(GetPermissionsFile(profile));
db.schemaVersion = 5;
db.executeSimpleSQL(
"CREATE TABLE moz_hosts (" +
" id INTEGER PRIMARY KEY" +
",origin TEXT" +
",type TEXT" +
",permission INTEGER" +
",expireType INTEGER" +
",expireTime INTEGER" +
",modificationTime INTEGER" +
")");
db.executeSimpleSQL(
"CREATE TABLE moz_hosts_v4 (" +
" id INTEGER PRIMARY KEY" +
",host TEXT" +
",type TEXT" +
",permission INTEGER" +
",expireType INTEGER" +
",expireTime INTEGER" +
",modificationTime INTEGER" +
",appId INTEGER" +
",isInBrowserElement INTEGER" +
")");
let stmtInsert = db.createStatement(
"INSERT INTO moz_hosts (" +
"id, origin, type, permission, expireType, expireTime, modificationTime" +
") VALUES (" +
":id, :origin, :type, :permission, :expireType, :expireTime, :modificationTime" +
")");
let stmt4Insert = db.createStatement(
"INSERT INTO moz_hosts_v4 (" +
"id, host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement" +
") VALUES (" +
":id, :host, :type, :permission, :expireType, :expireTime, :modificationTime, :appId, :isInBrowserElement" +
")");
let id = 0;
// Insert an origin into the database, and return its principal, type, and permission values
function insertV5(origin, type, permission, expireType, expireTime, modificationTime) {
let thisId = id++;
stmtInsert.bindByName("id", thisId);
stmtInsert.bindByName("origin", origin);
stmtInsert.bindByName("type", type);
stmtInsert.bindByName("permission", permission);
stmtInsert.bindByName("expireType", expireType);
stmtInsert.bindByName("expireTime", expireTime);
stmtInsert.bindByName("modificationTime", modificationTime);
stmtInsert.execute();
return function(stmtLookup, stmt4Lookup) {
stmtLookup.bindByName("id", thisId);
do_check_true(stmtLookup.executeStep());
do_check_eq(stmtLookup.getUTF8String(0), origin);
do_check_eq(stmtLookup.getUTF8String(1), type);
do_check_eq(stmtLookup.getInt64(2), permission);
do_check_eq(stmtLookup.getInt64(3), expireType);
do_check_eq(stmtLookup.getInt64(4), expireTime);
do_check_eq(stmtLookup.getInt64(5), modificationTime);
do_check_false(stmtLookup.executeStep());
stmtLookup.reset();
};
}
function insertV4(host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement) {
let thisId = id++;
stmt4Insert.bindByName("id", thisId);
stmt4Insert.bindByName("host", host);
stmt4Insert.bindByName("type", type);
stmt4Insert.bindByName("permission", permission);
stmt4Insert.bindByName("expireType", expireType);
stmt4Insert.bindByName("expireTime", expireTime);
stmt4Insert.bindByName("modificationTime", modificationTime);
stmt4Insert.bindByName("appId", appId);
stmt4Insert.bindByName("isInBrowserElement", isInBrowserElement);
stmt4Insert.execute();
return function(stmtLookup, stmt4Lookup) {
stmt4Lookup.bindByName("id", thisId);
do_check_true(stmt4Lookup.executeStep());
do_check_eq(stmt4Lookup.getUTF8String(0), host);
do_check_eq(stmt4Lookup.getUTF8String(1), type);
do_check_eq(stmt4Lookup.getInt64(2), permission);
do_check_eq(stmt4Lookup.getInt64(3), expireType);
do_check_eq(stmt4Lookup.getInt64(4), expireTime);
do_check_eq(stmt4Lookup.getInt64(5), modificationTime);
do_check_eq(stmt4Lookup.getInt64(6), appId);
do_check_eq(!!stmt4Lookup.getInt64(7), isInBrowserElement);
do_check_false(stmt4Lookup.executeStep());
stmt4Lookup.reset();
};
}
// Add some rows to the database
perms = [
insertV5("http://foo.com", "A", 1, 0, 0, 0),
insertV5("https://foo.com", "A", 1, 0, 0, 0),
insertV5("https://foo.com^appId=1000", "A", 1, 0, 0, 0),
insertV5("http://foo.com^appId=2000&inBrowser=1", "A", 1, 0, 0, 0),
insertV5("https://sub.foo.com", "B", 1, 0, 0, 0),
insertV5("http://subber.sub.foo.com", "B", 1, 0, 0, 0),
insertV5("http://bar.ca", "B", 1, 0, 0, 0),
insertV5("https://bar.ca", "B", 1, 0, 0, 0),
insertV5("ftp://bar.ca", "A", 2, 0, 0, 0),
insertV5("http://bar.ca^appId=1000", "B", 1, 0, 0, 0),
insertV5("http://bar.ca^appId=1000&inBrowser=1", "A", 1, 0, 0, 0),
insertV5("file:///some/path/to/file.html", "A", 1, 0, 0, 0),
insertV5("file:///another/file.html", "A", 1, 0, 0, 0),
insertV5("about:home", "A", 1, 0, 0, 0),
insertV4("https://foo.com", "A", 1, 0, 0, 0, 1000, false),
insertV4("http://foo.com", "A", 1, 0, 0, 0, 2000, true),
insertV4("https://sub.foo.com", "B", 1, 0, 0, 0, 0, false),
insertV4("http://subber.sub.foo.com", "B", 1, 0, 0, 0, 0, false),
insertV4("http://bar.ca", "B", 1, 0, 0, 0, 0, false),
insertV4("https://bar.ca", "B", 1, 0, 0, 0, 0, false),
];
// Force the permission manager to initialize
let enumerator = Services.perms.enumerator;
do_check_true(enumerator.hasMoreElements());
stmtInsert.finalize();
stmt4Insert.finalize();
db.close();
db = Services.storage.openDatabase(GetPermissionsFile(profile));
do_check_eq(db.schemaVersion, 6);
let stmtLookup = db.createStatement(
"SELECT origin, type, permission, expireType, expireTime, modificationTime FROM moz_perms WHERE id = :id;");
let stmt4Lookup = db.createStatement(
"SELECT host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement FROM moz_hosts WHERE id = :id;");
// Call each of the validation callbacks
perms.forEach((cb) => cb(stmtLookup, stmt4Lookup));
// Close the db connection
stmtLookup.finalize();
stmt4Lookup.finalize();
db.close();
});

Просмотреть файл

@ -0,0 +1,293 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
"resource://testing-common/PlacesTestUtils.jsm");
let PERMISSIONS_FILE_NAME = "permissions.sqlite";
function GetPermissionsFile(profile)
{
let file = profile.clone();
file.append(PERMISSIONS_FILE_NAME);
return file;
}
function run_test() {
run_next_test();
}
add_task(function test() {
/* Create and set up the permissions database */
let profile = do_get_profile();
let db = Services.storage.openDatabase(GetPermissionsFile(profile));
db.schemaVersion = 5;
/*
* V5 table
*/
db.executeSimpleSQL(
"CREATE TABLE moz_hosts (" +
" id INTEGER PRIMARY KEY" +
",origin TEXT" +
",type TEXT" +
",permission INTEGER" +
",expireType INTEGER" +
",expireTime INTEGER" +
",modificationTime INTEGER" +
")");
let stmt5Insert = db.createStatement(
"INSERT INTO moz_hosts (" +
"id, origin, type, permission, expireType, expireTime, modificationTime" +
") VALUES (" +
":id, :origin, :type, :permission, :expireType, :expireTime, :modificationTime" +
")");
/*
* V4 table
*/
db.executeSimpleSQL(
"CREATE TABLE moz_hosts_v4 (" +
" id INTEGER PRIMARY KEY" +
",host TEXT" +
",type TEXT" +
",permission INTEGER" +
",expireType INTEGER" +
",expireTime INTEGER" +
",modificationTime INTEGER" +
",appId INTEGER" +
",isInBrowserElement INTEGER" +
")");
let stmtInsert = db.createStatement(
"INSERT INTO moz_hosts_v4 (" +
"id, host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement" +
") VALUES (" +
":id, :host, :type, :permission, :expireType, :expireTime, :modificationTime, :appId, :isInBrowserElement" +
")");
let id = 0;
function insertOrigin(origin, type, permission, expireType, expireTime, modificationTime) {
let thisId = id++;
stmt5Insert.bindByName("id", thisId);
stmt5Insert.bindByName("origin", origin);
stmt5Insert.bindByName("type", type);
stmt5Insert.bindByName("permission", permission);
stmt5Insert.bindByName("expireType", expireType);
stmt5Insert.bindByName("expireTime", expireTime);
stmt5Insert.bindByName("modificationTime", modificationTime);
stmt5Insert.execute();
return {
id: thisId,
origin: origin,
type: type,
permission: permission,
expireType: expireType,
expireTime: expireTime,
modificationTime: modificationTime
};
}
function insertHost(host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement) {
let thisId = id++;
stmtInsert.bindByName("id", thisId);
stmtInsert.bindByName("host", host);
stmtInsert.bindByName("type", type);
stmtInsert.bindByName("permission", permission);
stmtInsert.bindByName("expireType", expireType);
stmtInsert.bindByName("expireTime", expireTime);
stmtInsert.bindByName("modificationTime", modificationTime);
stmtInsert.bindByName("appId", appId);
stmtInsert.bindByName("isInBrowserElement", isInBrowserElement);
stmtInsert.execute();
return {
id: thisId,
host: host,
type: type,
permission: permission,
expireType: expireType,
expireTime: expireTime,
modificationTime: modificationTime,
appId: appId,
isInBrowserElement: isInBrowserElement
};
}
let created5 = [
insertOrigin("https://foo.com", "A", 2, 0, 0, 0),
insertOrigin("http://foo.com", "A", 2, 0, 0, 0),
insertOrigin("http://foo.com^appId=1000&inBrowser=1", "A", 2, 0, 0, 0),
];
// Add some rows to the database
let created = [
insertHost("foo.com", "A", 1, 0, 0, 0, 0, false),
insertHost("foo.com", "C", 1, 0, 0, 0, 0, false),
insertHost("foo.com", "A", 1, 0, 0, 0, 1000, false),
insertHost("foo.com", "A", 1, 0, 0, 0, 2000, true),
insertHost("sub.foo.com", "B", 1, 0, 0, 0, 0, false),
insertHost("subber.sub.foo.com", "B", 1, 0, 0, 0, 0, false),
insertHost("bar.ca", "B", 1, 0, 0, 0, 0, false),
insertHost("bar.ca", "B", 1, 0, 0, 0, 1000, false),
insertHost("bar.ca", "A", 1, 0, 0, 0, 1000, true),
insertHost("file:///some/path/to/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("file:///another/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("moz-nullprincipal:{8695105a-adbe-4e4e-8083-851faa5ca2d7}", "A", 1, 0, 0, 0, 0, false),
insertHost("moz-nullprincipal:{12ahjksd-akjs-asd3-8393-asdu2189asdu}", "B", 1, 0, 0, 0, 0, false),
insertHost("<file>", "A", 1, 0, 0, 0, 0, false),
insertHost("<file>", "B", 1, 0, 0, 0, 0, false),
];
// CLose the db connection
stmtInsert.finalize();
db.close();
stmtInsert = null;
db = null;
let expected = [
// The http:// entries under foo.com won't be inserted, as there are history entries for foo.com,
// and http://foo.com or a subdomain are never visited.
// ["http://foo.com", "A", 1, 0, 0],
// ["http://foo.com^appId=1000", "A", 1, 0, 0],
// ["http://foo.com^appId=2000&inBrowser=1", "A", 1, 0, 0],
//
// Because we search for port/scheme combinations under eTLD+1, we should not have http:// entries
// for subdomains of foo.com either
// ["http://sub.foo.com", "B", 1, 0, 0],
// ["http://subber.sub.foo.com", "B", 1, 0, 0],
["https://foo.com", "A", 1, 0, 0],
["https://foo.com", "C", 1, 0, 0],
["https://foo.com^appId=1000", "A", 1, 0, 0],
["https://foo.com^appId=2000&inBrowser=1", "A", 1, 0, 0],
["https://sub.foo.com", "B", 1, 0, 0],
["https://subber.sub.foo.com", "B", 1, 0, 0],
// bar.ca will have both http:// and https:// for all entries, because there are no associated history entries
["http://bar.ca", "B", 1, 0, 0],
["https://bar.ca", "B", 1, 0, 0],
["http://bar.ca^appId=1000", "B", 1, 0, 0],
["https://bar.ca^appId=1000", "B", 1, 0, 0],
["http://bar.ca^appId=1000&inBrowser=1", "A", 1, 0, 0],
["https://bar.ca^appId=1000&inBrowser=1", "A", 1, 0, 0],
["file:///some/path/to/file.html", "A", 1, 0, 0],
["file:///another/file.html", "A", 1, 0, 0],
// Because we put ftp://some.subdomain.of.foo.com:8000/some/subdirectory in the history, we should
// also have these entries
["ftp://foo.com:8000", "A", 1, 0, 0],
["ftp://foo.com:8000", "C", 1, 0, 0],
["ftp://foo.com:8000^appId=1000", "A", 1, 0, 0],
["ftp://foo.com:8000^appId=2000&inBrowser=1", "A", 1, 0, 0],
// In addition, because we search for port/scheme combinations under eTLD+1, we should have the
// following entries
["ftp://sub.foo.com:8000", "B", 1, 0, 0],
["ftp://subber.sub.foo.com:8000", "B", 1, 0, 0],
];
let found = expected.map((it) => 0);
// Add some places to the places database
yield PlacesTestUtils.addVisits(Services.io.newURI("https://foo.com/some/other/subdirectory", null, null));
yield PlacesTestUtils.addVisits(Services.io.newURI("ftp://some.subdomain.of.foo.com:8000/some/subdirectory", null, null));
// Force initialization of the nsPermissionManager
let enumerator = Services.perms.enumerator;
while (enumerator.hasMoreElements()) {
let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
let isExpected = false;
expected.forEach((it, i) => {
if (permission.principal.origin == it[0] &&
permission.type == it[1] &&
permission.capability == it[2] &&
permission.expireType == it[3] &&
permission.expireTime == it[4]) {
isExpected = true;
found[i]++;
}
});
do_check_true(isExpected,
"Permission " + (isExpected ? "should" : "shouldn't") +
" be in permission database: " +
permission.principal.origin + ", " +
permission.type + ", " +
permission.capability + ", " +
permission.expireType + ", " +
permission.expireTime);
}
found.forEach((count, i) => {
do_check_true(count == 1, "Expected count = 1, got count = " + count + " for permission " + expected[i]);
});
// Check to make sure that all of the tables which we care about are present
{
let db = Services.storage.openDatabase(GetPermissionsFile(profile));
do_check_true(db.tableExists("moz_perms"));
do_check_true(db.tableExists("moz_hosts"));
do_check_true(db.tableExists("moz_hosts_is_backup"));
do_check_true(db.tableExists("moz_perms_v6"));
let mozHostsStmt = db.createStatement("SELECT " +
"host, type, permission, expireType, expireTime, " +
"modificationTime, appId, isInBrowserElement " +
"FROM moz_hosts WHERE id = :id");
// Check that the moz_hosts table still contains the correct values.
created.forEach((it) => {
mozHostsStmt.reset();
mozHostsStmt.bindByName("id", it.id);
mozHostsStmt.executeStep();
do_check_eq(mozHostsStmt.getUTF8String(0), it.host);
do_check_eq(mozHostsStmt.getUTF8String(1), it.type);
do_check_eq(mozHostsStmt.getInt64(2), it.permission);
do_check_eq(mozHostsStmt.getInt64(3), it.expireType);
do_check_eq(mozHostsStmt.getInt64(4), it.expireTime);
do_check_eq(mozHostsStmt.getInt64(5), it.modificationTime);
do_check_eq(mozHostsStmt.getInt64(6), it.appId);
do_check_eq(mozHostsStmt.getInt64(7), it.isInBrowserElement);
});
// Check that there are the right number of values
let mozHostsCount = db.createStatement("SELECT count(*) FROM moz_hosts");
mozHostsCount.executeStep();
do_check_eq(mozHostsCount.getInt64(0), created.length);
// Check that the moz_perms_v6 table contains the backup of the entry we created
let mozPermsV6Stmt = db.createStatement("SELECT " +
"origin, type, permission, expireType, expireTime, modificationTime " +
"FROM moz_perms_v6 WHERE id = :id");
// Check that the moz_hosts table still contains the correct values.
created5.forEach((it) => {
mozPermsV6Stmt.reset();
mozPermsV6Stmt.bindByName("id", it.id);
mozPermsV6Stmt.executeStep();
do_check_eq(mozPermsV6Stmt.getUTF8String(0), it.origin);
do_check_eq(mozPermsV6Stmt.getUTF8String(1), it.type);
do_check_eq(mozPermsV6Stmt.getInt64(2), it.permission);
do_check_eq(mozPermsV6Stmt.getInt64(3), it.expireType);
do_check_eq(mozPermsV6Stmt.getInt64(4), it.expireTime);
do_check_eq(mozPermsV6Stmt.getInt64(5), it.modificationTime);
});
// Check that there are the right number of values
let mozPermsV6Count = db.createStatement("SELECT count(*) FROM moz_perms_v6");
mozPermsV6Count.executeStep();
do_check_eq(mozPermsV6Count.getInt64(0), created5.length);
db.close();
}
});

Просмотреть файл

@ -0,0 +1,162 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
"resource://testing-common/PlacesTestUtils.jsm");
let PERMISSIONS_FILE_NAME = "permissions.sqlite";
function GetPermissionsFile(profile)
{
let file = profile.clone();
file.append(PERMISSIONS_FILE_NAME);
return file;
}
function run_test() {
run_next_test();
}
add_task(function test() {
/* Create and set up the permissions database */
let profile = do_get_profile();
let db = Services.storage.openDatabase(GetPermissionsFile(profile));
db.schemaVersion = 5;
/*
* V5 table
*/
db.executeSimpleSQL(
"CREATE TABLE moz_hosts (" +
" id INTEGER PRIMARY KEY" +
",origin TEXT" +
",type TEXT" +
",permission INTEGER" +
",expireType INTEGER" +
",expireTime INTEGER" +
",modificationTime INTEGER" +
")");
let stmt5Insert = db.createStatement(
"INSERT INTO moz_hosts (" +
"id, origin, type, permission, expireType, expireTime, modificationTime" +
") VALUES (" +
":id, :origin, :type, :permission, :expireType, :expireTime, :modificationTime" +
")");
let id = 0;
function insertOrigin(origin, type, permission, expireType, expireTime, modificationTime) {
let thisId = id++;
stmt5Insert.bindByName("id", thisId);
stmt5Insert.bindByName("origin", origin);
stmt5Insert.bindByName("type", type);
stmt5Insert.bindByName("permission", permission);
stmt5Insert.bindByName("expireType", expireType);
stmt5Insert.bindByName("expireTime", expireTime);
stmt5Insert.bindByName("modificationTime", modificationTime);
stmt5Insert.execute();
return {
id: thisId,
host: origin,
type: type,
permission: permission,
expireType: expireType,
expireTime: expireTime,
modificationTime: modificationTime
};
}
let created5 = [
insertOrigin("https://foo.com", "A", 2, 0, 0, 0),
insertOrigin("http://foo.com", "A", 2, 0, 0, 0),
insertOrigin("http://foo.com^appId=1000&inBrowser=1", "A", 2, 0, 0, 0),
];
let created4 = []; // Didn't create any v4 entries, so the DB should be empty
// CLose the db connection
stmt5Insert.finalize();
db.close();
stmt5Insert = null;
db = null;
let expected = [
["https://foo.com", "A", 2, 0, 0, 0],
["http://foo.com", "A", 2, 0, 0, 0],
["http://foo.com^appId=1000&inBrowser=1", "A", 2, 0, 0, 0]
];
let found = expected.map((it) => 0);
// Force initialization of the nsPermissionManager
let enumerator = Services.perms.enumerator;
while (enumerator.hasMoreElements()) {
let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
let isExpected = false;
expected.forEach((it, i) => {
if (permission.principal.origin == it[0] &&
permission.type == it[1] &&
permission.capability == it[2] &&
permission.expireType == it[3] &&
permission.expireTime == it[4]) {
isExpected = true;
found[i]++;
}
});
do_check_true(isExpected,
"Permission " + (isExpected ? "should" : "shouldn't") +
" be in permission database: " +
permission.principal.origin + ", " +
permission.type + ", " +
permission.capability + ", " +
permission.expireType + ", " +
permission.expireTime);
}
found.forEach((count, i) => {
do_check_true(count == 1, "Expected count = 1, got count = " + count + " for permission " + expected[i]);
});
// Check to make sure that all of the tables which we care about are present
{
let db = Services.storage.openDatabase(GetPermissionsFile(profile));
do_check_true(db.tableExists("moz_perms"));
do_check_true(db.tableExists("moz_hosts"));
do_check_false(db.tableExists("moz_hosts_is_backup"));
do_check_false(db.tableExists("moz_perms_v6"));
let mozHostsStmt = db.createStatement("SELECT " +
"host, type, permission, expireType, expireTime, " +
"modificationTime, appId, isInBrowserElement " +
"FROM moz_hosts WHERE id = :id");
// Check that the moz_hosts table still contains the correct values.
created4.forEach((it) => {
mozHostsStmt.reset();
mozHostsStmt.bindByName("id", it.id);
mozHostsStmt.executeStep();
do_check_eq(mozHostsStmt.getUTF8String(0), it.host);
do_check_eq(mozHostsStmt.getUTF8String(1), it.type);
do_check_eq(mozHostsStmt.getInt64(2), it.permission);
do_check_eq(mozHostsStmt.getInt64(3), it.expireType);
do_check_eq(mozHostsStmt.getInt64(4), it.expireTime);
do_check_eq(mozHostsStmt.getInt64(5), it.modificationTime);
do_check_eq(mozHostsStmt.getInt64(6), it.appId);
do_check_eq(mozHostsStmt.getInt64(7), it.isInBrowserElement);
});
// Check that there are the right number of values
let mozHostsCount = db.createStatement("SELECT count(*) FROM moz_hosts");
mozHostsCount.executeStep();
do_check_eq(mozHostsCount.getInt64(0), created4.length);
db.close();
}
});

Просмотреть файл

@ -0,0 +1,293 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
"resource://testing-common/PlacesTestUtils.jsm");
let PERMISSIONS_FILE_NAME = "permissions.sqlite";
function GetPermissionsFile(profile)
{
let file = profile.clone();
file.append(PERMISSIONS_FILE_NAME);
return file;
}
function run_test() {
run_next_test();
}
add_task(function test() {
/* Create and set up the permissions database */
let profile = do_get_profile();
let db = Services.storage.openDatabase(GetPermissionsFile(profile));
db.schemaVersion = 6;
/*
* V5 table
*/
db.executeSimpleSQL(
"CREATE TABLE moz_perms (" +
" id INTEGER PRIMARY KEY" +
",origin TEXT" +
",type TEXT" +
",permission INTEGER" +
",expireType INTEGER" +
",expireTime INTEGER" +
",modificationTime INTEGER" +
")");
let stmt6Insert = db.createStatement(
"INSERT INTO moz_perms (" +
"id, origin, type, permission, expireType, expireTime, modificationTime" +
") VALUES (" +
":id, :origin, :type, :permission, :expireType, :expireTime, :modificationTime" +
")");
/*
* V4 table
*/
db.executeSimpleSQL(
"CREATE TABLE moz_hosts (" +
" id INTEGER PRIMARY KEY" +
",host TEXT" +
",type TEXT" +
",permission INTEGER" +
",expireType INTEGER" +
",expireTime INTEGER" +
",modificationTime INTEGER" +
",appId INTEGER" +
",isInBrowserElement INTEGER" +
")");
let stmtInsert = db.createStatement(
"INSERT INTO moz_hosts (" +
"id, host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement" +
") VALUES (" +
":id, :host, :type, :permission, :expireType, :expireTime, :modificationTime, :appId, :isInBrowserElement" +
")");
let id = 0;
function insertOrigin(origin, type, permission, expireType, expireTime, modificationTime) {
let thisId = id++;
stmt6Insert.bindByName("id", thisId);
stmt6Insert.bindByName("origin", origin);
stmt6Insert.bindByName("type", type);
stmt6Insert.bindByName("permission", permission);
stmt6Insert.bindByName("expireType", expireType);
stmt6Insert.bindByName("expireTime", expireTime);
stmt6Insert.bindByName("modificationTime", modificationTime);
stmt6Insert.execute();
return {
id: thisId,
origin: origin,
type: type,
permission: permission,
expireType: expireType,
expireTime: expireTime,
modificationTime: modificationTime
};
}
function insertHost(host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement) {
let thisId = id++;
stmtInsert.bindByName("id", thisId);
stmtInsert.bindByName("host", host);
stmtInsert.bindByName("type", type);
stmtInsert.bindByName("permission", permission);
stmtInsert.bindByName("expireType", expireType);
stmtInsert.bindByName("expireTime", expireTime);
stmtInsert.bindByName("modificationTime", modificationTime);
stmtInsert.bindByName("appId", appId);
stmtInsert.bindByName("isInBrowserElement", isInBrowserElement);
stmtInsert.execute();
return {
id: thisId,
host: host,
type: type,
permission: permission,
expireType: expireType,
expireTime: expireTime,
modificationTime: modificationTime,
appId: appId,
isInBrowserElement: isInBrowserElement
};
}
let created6 = [
insertOrigin("https://foo.com", "A", 2, 0, 0, 0),
insertOrigin("http://foo.com", "A", 2, 0, 0, 0),
insertOrigin("http://foo.com^appId=1000&inBrowser=1", "A", 2, 0, 0, 0),
];
// Add some rows to the database
let created = [
insertHost("foo.com", "A", 1, 0, 0, 0, 0, false),
insertHost("foo.com", "C", 1, 0, 0, 0, 0, false),
insertHost("foo.com", "A", 1, 0, 0, 0, 1000, false),
insertHost("foo.com", "A", 1, 0, 0, 0, 2000, true),
insertHost("sub.foo.com", "B", 1, 0, 0, 0, 0, false),
insertHost("subber.sub.foo.com", "B", 1, 0, 0, 0, 0, false),
insertHost("bar.ca", "B", 1, 0, 0, 0, 0, false),
insertHost("bar.ca", "B", 1, 0, 0, 0, 1000, false),
insertHost("bar.ca", "A", 1, 0, 0, 0, 1000, true),
insertHost("file:///some/path/to/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("file:///another/file.html", "A", 1, 0, 0, 0, 0, false),
insertHost("moz-nullprincipal:{8695105a-adbe-4e4e-8083-851faa5ca2d7}", "A", 1, 0, 0, 0, 0, false),
insertHost("moz-nullprincipal:{12ahjksd-akjs-asd3-8393-asdu2189asdu}", "B", 1, 0, 0, 0, 0, false),
insertHost("<file>", "A", 1, 0, 0, 0, 0, false),
insertHost("<file>", "B", 1, 0, 0, 0, 0, false),
];
// CLose the db connection
stmtInsert.finalize();
db.close();
stmtInsert = null;
db = null;
let expected = [
// The http:// entries under foo.com won't be inserted, as there are history entries for foo.com,
// and http://foo.com or a subdomain are never visited.
// ["http://foo.com", "A", 1, 0, 0],
// ["http://foo.com^appId=1000", "A", 1, 0, 0],
// ["http://foo.com^appId=2000&inBrowser=1", "A", 1, 0, 0],
//
// Because we search for port/scheme combinations under eTLD+1, we should not have http:// entries
// for subdomains of foo.com either
// ["http://sub.foo.com", "B", 1, 0, 0],
// ["http://subber.sub.foo.com", "B", 1, 0, 0],
["https://foo.com", "A", 1, 0, 0],
["https://foo.com", "C", 1, 0, 0],
["https://foo.com^appId=1000", "A", 1, 0, 0],
["https://foo.com^appId=2000&inBrowser=1", "A", 1, 0, 0],
["https://sub.foo.com", "B", 1, 0, 0],
["https://subber.sub.foo.com", "B", 1, 0, 0],
// bar.ca will have both http:// and https:// for all entries, because there are no associated history entries
["http://bar.ca", "B", 1, 0, 0],
["https://bar.ca", "B", 1, 0, 0],
["http://bar.ca^appId=1000", "B", 1, 0, 0],
["https://bar.ca^appId=1000", "B", 1, 0, 0],
["http://bar.ca^appId=1000&inBrowser=1", "A", 1, 0, 0],
["https://bar.ca^appId=1000&inBrowser=1", "A", 1, 0, 0],
["file:///some/path/to/file.html", "A", 1, 0, 0],
["file:///another/file.html", "A", 1, 0, 0],
// Because we put ftp://some.subdomain.of.foo.com:8000/some/subdirectory in the history, we should
// also have these entries
["ftp://foo.com:8000", "A", 1, 0, 0],
["ftp://foo.com:8000", "C", 1, 0, 0],
["ftp://foo.com:8000^appId=1000", "A", 1, 0, 0],
["ftp://foo.com:8000^appId=2000&inBrowser=1", "A", 1, 0, 0],
// In addition, because we search for port/scheme combinations under eTLD+1, we should have the
// following entries
["ftp://sub.foo.com:8000", "B", 1, 0, 0],
["ftp://subber.sub.foo.com:8000", "B", 1, 0, 0],
];
let found = expected.map((it) => 0);
// Add some places to the places database
yield PlacesTestUtils.addVisits(Services.io.newURI("https://foo.com/some/other/subdirectory", null, null));
yield PlacesTestUtils.addVisits(Services.io.newURI("ftp://some.subdomain.of.foo.com:8000/some/subdirectory", null, null));
// Force initialization of the nsPermissionManager
let enumerator = Services.perms.enumerator;
while (enumerator.hasMoreElements()) {
let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
let isExpected = false;
expected.forEach((it, i) => {
if (permission.principal.origin == it[0] &&
permission.type == it[1] &&
permission.capability == it[2] &&
permission.expireType == it[3] &&
permission.expireTime == it[4]) {
isExpected = true;
found[i]++;
}
});
do_check_true(isExpected,
"Permission " + (isExpected ? "should" : "shouldn't") +
" be in permission database: " +
permission.principal.origin + ", " +
permission.type + ", " +
permission.capability + ", " +
permission.expireType + ", " +
permission.expireTime);
}
found.forEach((count, i) => {
do_check_true(count == 1, "Expected count = 1, got count = " + count + " for permission " + expected[i]);
});
// Check to make sure that all of the tables which we care about are present
{
let db = Services.storage.openDatabase(GetPermissionsFile(profile));
do_check_true(db.tableExists("moz_perms"));
do_check_true(db.tableExists("moz_hosts"));
do_check_true(db.tableExists("moz_hosts_is_backup"));
do_check_true(db.tableExists("moz_perms_v6"));
let mozHostsStmt = db.createStatement("SELECT " +
"host, type, permission, expireType, expireTime, " +
"modificationTime, appId, isInBrowserElement " +
"FROM moz_hosts WHERE id = :id");
// Check that the moz_hosts table still contains the correct values.
created.forEach((it) => {
mozHostsStmt.reset();
mozHostsStmt.bindByName("id", it.id);
mozHostsStmt.executeStep();
do_check_eq(mozHostsStmt.getUTF8String(0), it.host);
do_check_eq(mozHostsStmt.getUTF8String(1), it.type);
do_check_eq(mozHostsStmt.getInt64(2), it.permission);
do_check_eq(mozHostsStmt.getInt64(3), it.expireType);
do_check_eq(mozHostsStmt.getInt64(4), it.expireTime);
do_check_eq(mozHostsStmt.getInt64(5), it.modificationTime);
do_check_eq(mozHostsStmt.getInt64(6), it.appId);
do_check_eq(mozHostsStmt.getInt64(7), it.isInBrowserElement);
});
// Check that there are the right number of values
let mozHostsCount = db.createStatement("SELECT count(*) FROM moz_hosts");
mozHostsCount.executeStep();
do_check_eq(mozHostsCount.getInt64(0), created.length);
// Check that the moz_perms_v6 table contains the backup of the entry we created
let mozPermsV6Stmt = db.createStatement("SELECT " +
"origin, type, permission, expireType, expireTime, modificationTime " +
"FROM moz_perms_v6 WHERE id = :id");
// Check that the moz_hosts table still contains the correct values.
created6.forEach((it) => {
mozPermsV6Stmt.reset();
mozPermsV6Stmt.bindByName("id", it.id);
mozPermsV6Stmt.executeStep();
do_check_eq(mozPermsV6Stmt.getUTF8String(0), it.origin);
do_check_eq(mozPermsV6Stmt.getUTF8String(1), it.type);
do_check_eq(mozPermsV6Stmt.getInt64(2), it.permission);
do_check_eq(mozPermsV6Stmt.getInt64(3), it.expireType);
do_check_eq(mozPermsV6Stmt.getInt64(4), it.expireTime);
do_check_eq(mozPermsV6Stmt.getInt64(5), it.modificationTime);
});
// Check that there are the right number of values
let mozPermsV6Count = db.createStatement("SELECT count(*) FROM moz_perms_v6");
mozPermsV6Count.executeStep();
do_check_eq(mozPermsV6Count.getInt64(0), created6.length);
db.close();
}
});

Просмотреть файл

@ -0,0 +1,162 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
"resource://testing-common/PlacesTestUtils.jsm");
let PERMISSIONS_FILE_NAME = "permissions.sqlite";
function GetPermissionsFile(profile)
{
let file = profile.clone();
file.append(PERMISSIONS_FILE_NAME);
return file;
}
function run_test() {
run_next_test();
}
add_task(function test() {
/* Create and set up the permissions database */
let profile = do_get_profile();
let db = Services.storage.openDatabase(GetPermissionsFile(profile));
db.schemaVersion = 6;
/*
* V5 table
*/
db.executeSimpleSQL(
"CREATE TABLE moz_perms (" +
" id INTEGER PRIMARY KEY" +
",origin TEXT" +
",type TEXT" +
",permission INTEGER" +
",expireType INTEGER" +
",expireTime INTEGER" +
",modificationTime INTEGER" +
")");
let stmt6Insert = db.createStatement(
"INSERT INTO moz_perms (" +
"id, origin, type, permission, expireType, expireTime, modificationTime" +
") VALUES (" +
":id, :origin, :type, :permission, :expireType, :expireTime, :modificationTime" +
")");
let id = 0;
function insertOrigin(origin, type, permission, expireType, expireTime, modificationTime) {
let thisId = id++;
stmt6Insert.bindByName("id", thisId);
stmt6Insert.bindByName("origin", origin);
stmt6Insert.bindByName("type", type);
stmt6Insert.bindByName("permission", permission);
stmt6Insert.bindByName("expireType", expireType);
stmt6Insert.bindByName("expireTime", expireTime);
stmt6Insert.bindByName("modificationTime", modificationTime);
stmt6Insert.execute();
return {
id: thisId,
host: origin,
type: type,
permission: permission,
expireType: expireType,
expireTime: expireTime,
modificationTime: modificationTime
};
}
let created6 = [
insertOrigin("https://foo.com", "A", 2, 0, 0, 0),
insertOrigin("http://foo.com", "A", 2, 0, 0, 0),
insertOrigin("http://foo.com^appId=1000&inBrowser=1", "A", 2, 0, 0, 0),
];
let created4 = []; // Didn't create any v4 entries, so the DB should be empty
// CLose the db connection
stmt6Insert.finalize();
db.close();
stmt6Insert = null;
db = null;
let expected = [
["https://foo.com", "A", 2, 0, 0, 0],
["http://foo.com", "A", 2, 0, 0, 0],
["http://foo.com^appId=1000&inBrowser=1", "A", 2, 0, 0, 0]
];
let found = expected.map((it) => 0);
// Force initialization of the nsPermissionManager
let enumerator = Services.perms.enumerator;
while (enumerator.hasMoreElements()) {
let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
let isExpected = false;
expected.forEach((it, i) => {
if (permission.principal.origin == it[0] &&
permission.type == it[1] &&
permission.capability == it[2] &&
permission.expireType == it[3] &&
permission.expireTime == it[4]) {
isExpected = true;
found[i]++;
}
});
do_check_true(isExpected,
"Permission " + (isExpected ? "should" : "shouldn't") +
" be in permission database: " +
permission.principal.origin + ", " +
permission.type + ", " +
permission.capability + ", " +
permission.expireType + ", " +
permission.expireTime);
}
found.forEach((count, i) => {
do_check_true(count == 1, "Expected count = 1, got count = " + count + " for permission " + expected[i]);
});
// Check to make sure that all of the tables which we care about are present
{
let db = Services.storage.openDatabase(GetPermissionsFile(profile));
do_check_true(db.tableExists("moz_perms"));
do_check_true(db.tableExists("moz_hosts"));
do_check_false(db.tableExists("moz_hosts_is_backup"));
do_check_false(db.tableExists("moz_perms_v6"));
let mozHostsStmt = db.createStatement("SELECT " +
"host, type, permission, expireType, expireTime, " +
"modificationTime, appId, isInBrowserElement " +
"FROM moz_hosts WHERE id = :id");
// Check that the moz_hosts table still contains the correct values.
created4.forEach((it) => {
mozHostsStmt.reset();
mozHostsStmt.bindByName("id", it.id);
mozHostsStmt.executeStep();
do_check_eq(mozHostsStmt.getUTF8String(0), it.host);
do_check_eq(mozHostsStmt.getUTF8String(1), it.type);
do_check_eq(mozHostsStmt.getInt64(2), it.permission);
do_check_eq(mozHostsStmt.getInt64(3), it.expireType);
do_check_eq(mozHostsStmt.getInt64(4), it.expireTime);
do_check_eq(mozHostsStmt.getInt64(5), it.modificationTime);
do_check_eq(mozHostsStmt.getInt64(6), it.appId);
do_check_eq(mozHostsStmt.getInt64(7), it.isInBrowserElement);
});
// Check that there are the right number of values
let mozHostsCount = db.createStatement("SELECT count(*) FROM moz_hosts");
mozHostsCount.executeStep();
do_check_eq(mozHostsCount.getInt64(0), created4.length);
db.close();
}
});

Просмотреть файл

@ -36,5 +36,9 @@ skip-if = debug == true
[test_permmanager_removepermission.js]
[test_permmanager_matchesuri.js]
[test_permmanager_matches.js]
[test_permmanager_migrate_4-5.js]
[test_permmanager_migrate_5-6.js]
[test_permmanager_migrate_4-7.js]
[test_permmanager_migrate_5-7a.js]
[test_permmanager_migrate_5-7b.js]
[test_permmanager_migrate_6-7a.js]
[test_permmanager_migrate_6-7b.js]
[test_permmanager_migrate_4-7_no_history.js]

Просмотреть файл

@ -121,7 +121,6 @@ Compositor::DrawDiagnosticsInternal(DiagnosticFlags aFlags,
#else
int lWidth = 2;
#endif
float opacity = 0.7f;
gfx::Color color;
if (aFlags & DiagnosticFlags::CONTENT) {
@ -142,12 +141,15 @@ Compositor::DrawDiagnosticsInternal(DiagnosticFlags aFlags,
aFlags & DiagnosticFlags::BIGIMAGE ||
aFlags & DiagnosticFlags::REGION_RECT) {
lWidth = 1;
opacity = 0.5f;
color.r *= 0.7f;
color.g *= 0.7f;
color.b *= 0.7f;
color.a = color.a * 0.5f;
} else {
color.a = color.a * 0.7f;
}
if (mDiagnosticTypes & DiagnosticTypes::FLASH_BORDERS) {
float flash = (float)aFlashCounter / (float)DIAGNOSTIC_FLASH_COUNTER_MAX;
color.r *= flash;
@ -155,31 +157,57 @@ Compositor::DrawDiagnosticsInternal(DiagnosticFlags aFlags,
color.b *= flash;
}
SlowDrawRect(aVisibleRect, color, aClipRect, aTransform, lWidth);
}
void
Compositor::SlowDrawRect(const gfx::Rect& aRect, const gfx::Color& aColor,
const gfx::Rect& aClipRect,
const gfx::Matrix4x4& aTransform, int aStrokeWidth)
{
// TODO This should draw a rect using a single draw call but since
// this is only used for debugging overlays it's not worth optimizing ATM.
float opacity = 1.0f;
EffectChain effects;
effects.mPrimaryEffect = new EffectSolidColor(color);
effects.mPrimaryEffect = new EffectSolidColor(aColor);
// left
this->DrawQuad(gfx::Rect(aVisibleRect.x, aVisibleRect.y,
lWidth, aVisibleRect.height),
this->DrawQuad(gfx::Rect(aRect.x, aRect.y,
aStrokeWidth, aRect.height),
aClipRect, effects, opacity,
aTransform);
// top
this->DrawQuad(gfx::Rect(aVisibleRect.x + lWidth, aVisibleRect.y,
aVisibleRect.width - 2 * lWidth, lWidth),
this->DrawQuad(gfx::Rect(aRect.x + aStrokeWidth, aRect.y,
aRect.width - 2 * aStrokeWidth, aStrokeWidth),
aClipRect, effects, opacity,
aTransform);
// right
this->DrawQuad(gfx::Rect(aVisibleRect.x + aVisibleRect.width - lWidth, aVisibleRect.y,
lWidth, aVisibleRect.height),
this->DrawQuad(gfx::Rect(aRect.x + aRect.width - aStrokeWidth, aRect.y,
aStrokeWidth, aRect.height),
aClipRect, effects, opacity,
aTransform);
// bottom
this->DrawQuad(gfx::Rect(aVisibleRect.x + lWidth, aVisibleRect.y + aVisibleRect.height-lWidth,
aVisibleRect.width - 2 * lWidth, lWidth),
this->DrawQuad(gfx::Rect(aRect.x + aStrokeWidth, aRect.y + aRect.height - aStrokeWidth,
aRect.width - 2 * aStrokeWidth, aStrokeWidth),
aClipRect, effects, opacity,
aTransform);
}
void
Compositor::FillRect(const gfx::Rect& aRect, const gfx::Color& aColor,
const gfx::Rect& aClipRect,
const gfx::Matrix4x4& aTransform)
{
float opacity = 1.0f;
EffectChain effects;
effects.mPrimaryEffect = new EffectSolidColor(aColor);
this->DrawQuad(aRect,
aClipRect, effects, opacity,
aTransform);
}
static float
WrapTexCoord(float v)
{

Просмотреть файл

@ -320,6 +320,21 @@ public:
DrawQuad(aRect, aClipRect, aEffectChain, aOpacity, aTransform, aRect);
}
/**
* Draw an unfilled solid color rect. Typically used for debugging overlays.
*/
void SlowDrawRect(const gfx::Rect& aRect, const gfx::Color& color,
const gfx::Rect& aClipRect = gfx::Rect(),
const gfx::Matrix4x4& aTransform = gfx::Matrix4x4(),
int aStrokeWidth = 1);
/**
* Draw a solid color filled rect. This is a simple DrawQuad helper.
*/
void FillRect(const gfx::Rect& aRect, const gfx::Color& color,
const gfx::Rect& aClipRect = gfx::Rect(),
const gfx::Matrix4x4& aTransform = gfx::Matrix4x4());
/*
* Clear aRect on current render target.
*/

Просмотреть файл

@ -329,6 +329,86 @@ ContainerPrepare(ContainerT* aContainer,
}
}
template<class ContainerT> void
RenderMinimap(ContainerT* aContainer, LayerManagerComposite* aManager,
const RenderTargetIntRect& aClipRect, Layer* aLayer)
{
Compositor* compositor = aManager->GetCompositor();
if (aLayer->GetFrameMetricsCount() < 1) {
return;
}
AsyncPanZoomController* controller = aLayer->GetAsyncPanZoomController(0);
if (!controller) {
return;
}
ViewTransform asyncTransformWithoutOverscroll;
ParentLayerPoint scrollOffset;
controller->SampleContentTransformForFrame(&asyncTransformWithoutOverscroll,
scrollOffset);
// Options
const int verticalPadding = 10;
const int horizontalPadding = 5;
gfx::Color backgroundColor(0.3f, 0.3f, 0.3f, 0.3f);
gfx::Color tileActiveColor(1, 1, 1, 0.5f);
gfx::Color tileBorderColor(0, 0, 0, 0.1f);
gfx::Color pageBorderColor(0, 0, 0);
gfx::Color displayPortColor(0, 1.f, 0);
gfx::Color viewPortColor(0, 0, 1.f);
// Rects
const FrameMetrics& fm = aLayer->GetFrameMetrics(0);
LayerRect scrollRect = fm.GetScrollableRect() * fm.LayersPixelsPerCSSPixel();
LayerRect viewRect = ParentLayerRect(scrollOffset, fm.GetCompositionBounds().Size()) / LayerToParentLayerScale(1);
LayerRect dp = (fm.GetDisplayPort() + fm.GetScrollOffset()) * fm.LayersPixelsPerCSSPixel();
// Compute a scale with an appropriate aspect ratio
// We allocate up to 100px of width and the height of this layer.
float scaleFactor;
float scaleFactorX;
float scaleFactorY;
scaleFactorX = 100.f / scrollRect.width;
scaleFactorY = ((viewRect.height) - 2 * verticalPadding) / scrollRect.height;
scaleFactor = std::min(scaleFactorX, scaleFactorY);
Matrix4x4 transform = Matrix4x4::Scaling(scaleFactor, scaleFactor, 1);
transform.PostTranslate(horizontalPadding, verticalPadding, 0);
Rect clipRect = aContainer->GetEffectiveTransform().TransformBounds(
transform.TransformBounds(scrollRect.ToUnknownRect()));
clipRect.width++;
clipRect.height++;
Rect r;
r = transform.TransformBounds(scrollRect.ToUnknownRect());
compositor->FillRect(r, backgroundColor, clipRect, aContainer->GetEffectiveTransform());
int tileW = gfxPrefs::LayersTileWidth();
int tileH = gfxPrefs::LayersTileHeight();
for (int x = scrollRect.x; x < scrollRect.XMost(); x += tileW) {
for (int y = scrollRect.y; y < scrollRect.YMost(); y += tileH) {
LayerRect tileRect = LayerRect(x - x % tileW, y - y % tileH, tileW, tileH);
r = transform.TransformBounds(tileRect.ToUnknownRect());
if (tileRect.Intersects(dp)) {
compositor->FillRect(r, tileActiveColor, clipRect, aContainer->GetEffectiveTransform());
}
compositor->SlowDrawRect(r, tileBorderColor, clipRect, aContainer->GetEffectiveTransform());
}
}
r = transform.TransformBounds(scrollRect.ToUnknownRect());
compositor->SlowDrawRect(r, pageBorderColor, clipRect, aContainer->GetEffectiveTransform());
r = transform.TransformBounds(dp.ToUnknownRect());
compositor->SlowDrawRect(r, displayPortColor, clipRect, aContainer->GetEffectiveTransform());
r = transform.TransformBounds(viewRect.ToUnknownRect());
compositor->SlowDrawRect(r, viewPortColor, clipRect, aContainer->GetEffectiveTransform());
}
template<class ContainerT> void
RenderLayers(ContainerT* aContainer,
LayerManagerComposite* aManager,
@ -407,6 +487,10 @@ RenderLayers(ContainerT* aContainer,
}
}
if (gfxPrefs::APZMinimap()) {
RenderMinimap(aContainer, aManager, aClipRect, layer);
}
// invariant: our GL context should be current here, I don't think we can
// assert it though
}

Просмотреть файл

@ -50,6 +50,9 @@ class ContainerLayerComposite : public ContainerLayer,
LayerManagerComposite* aManager,
const RenderTargetIntRect& aClipRect);
template<class ContainerT>
void RenderMinimap(ContainerT* aContainer, LayerManagerComposite* aManager,
const RenderTargetIntRect& aClipRect, Layer* aLayer);
public:
explicit ContainerLayerComposite(LayerManagerComposite *aManager);

Просмотреть файл

@ -163,6 +163,7 @@ private:
DECL_GFX_PREF(Once, "apz.max_velocity_inches_per_ms", APZMaxVelocity, float, -1.0f);
DECL_GFX_PREF(Once, "apz.max_velocity_queue_size", APZMaxVelocityQueueSize, uint32_t, 5);
DECL_GFX_PREF(Live, "apz.min_skate_speed", APZMinSkateSpeed, float, 1.0f);
DECL_GFX_PREF(Live, "apz.minimap.enabled", APZMinimap, bool, false);
DECL_GFX_PREF(Live, "apz.num_paint_duration_samples", APZNumPaintDurationSamples, int32_t, 3);
DECL_GFX_PREF(Live, "apz.overscroll.enabled", APZOverscrollEnabled, bool, false);
DECL_GFX_PREF(Live, "apz.overscroll.min_pan_distance_ratio", APZMinPanDistanceRatio, float, 1.0f);

Просмотреть файл

@ -989,12 +989,11 @@ class PersistentRooted : public js::PersistentRootedBase<T>,
friend struct js::gc::PersistentRootedMarker<T>;
friend void js::gc::FinishPersistentRootedChains(JSRuntime* rt);
friend void js::gc::FinishPersistentRootedChains(js::RootLists&);
void registerWithRuntime(JSRuntime* rt) {
void registerWithRootLists(js::RootLists& roots) {
MOZ_ASSERT(!initialized());
JS::shadow::Runtime* srt = JS::shadow::Runtime::asShadowRuntime(rt);
srt->getPersistentRootedList<T>().insertBack(this);
roots.getPersistentRootedList<T>().insertBack(this);
}
public:
@ -1041,7 +1040,7 @@ class PersistentRooted : public js::PersistentRootedBase<T>,
void init(JSContext* cx, T initial) {
ptr = initial;
registerWithRuntime(js::GetRuntime(cx));
registerWithRootLists(js::ContextFriendFields::get(cx)->roots);
}
void init(JSRuntime* rt) {
@ -1050,7 +1049,7 @@ class PersistentRooted : public js::PersistentRootedBase<T>,
void init(JSRuntime* rt, T initial) {
ptr = initial;
registerWithRuntime(rt);
registerWithRootLists(js::PerThreadDataFriendFields::getMainThread(rt)->roots);
}
void reset() {

173
js/public/TraceableVector.h Normal file
Просмотреть файл

@ -0,0 +1,173 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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/. */
#ifndef js_TraceableVector_h
#define js_TraceableVector_h
#include "mozilla/Vector.h"
#include "js/RootingAPI.h"
#include "js/Vector.h"
namespace js {
template <typename> struct DefaultTracer;
// A TraceableVector is a Vector with an additional trace method that knows how
// to visit all of the items stored in the Vector. For vectors that contain GC
// things, this is usually more convenient than manually iterating and marking
// the contents.
//
// Most types of GC pointers as keys and values can be traced with no extra
// infrastructure. For structs and non-gc-pointer members, ensure that there
// is a specialization of DefaultTracer<T> with an appropriate trace method
// available to handle the custom type.
//
// Note that although this Vector's trace will deal correctly with moved items,
// it does not itself know when to barrier or trace items. To function properly
// it must either be used with Rooted, or barriered and traced manually.
template <typename T,
size_t MinInlineCapacity = 0,
typename AllocPolicy = TempAllocPolicy,
typename TraceFunc = DefaultTracer<T>>
class TraceableVector
: public mozilla::VectorBase<T,
MinInlineCapacity,
AllocPolicy,
TraceableVector<T, MinInlineCapacity, AllocPolicy, TraceFunc>>,
public JS::DynamicTraceable
{
using Base = mozilla::VectorBase<T, MinInlineCapacity, AllocPolicy, TraceableVector>;
public:
explicit TraceableVector(AllocPolicy alloc = AllocPolicy()) : Base(alloc) {}
TraceableVector(TraceableVector&& vec) : Base(mozilla::Forward<TraceableVector>(vec)) {}
TraceableVector& operator=(TraceableVector&& vec) {
return Base::operator=(mozilla::Forward<TraceableVector>(vec));
}
void trace(JSTracer* trc) override {
for (size_t i = 0; i < this->length(); ++i)
TraceFunc::trace(trc, &Base::operator[](i), "vector element");
}
};
template <typename Outer, typename T, size_t Capacity, typename AllocPolicy, typename TraceFunc>
class TraceableVectorOperations
{
using Vec = TraceableVector<T, Capacity, AllocPolicy, TraceFunc>;
const Vec& vec() const { return static_cast<const Outer*>(this)->extract(); }
public:
const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
size_t length() const { return vec().length(); }
bool empty() const { return vec().empty(); }
size_t capacity() const { return vec().capacity(); }
const T* begin() const { return vec().begin(); }
const T* end() const { return vec().end(); }
const T& operator[](size_t aIndex) const { return vec().operator[](aIndex); }
const T& back() const { return vec().back(); }
bool canAppendWithoutRealloc(size_t aNeeded) const { return vec().canAppendWithoutRealloc(); }
};
template <typename Outer, typename T, size_t Capacity, typename AllocPolicy, typename TraceFunc>
class MutableTraceableVectorOperations
: public TraceableVectorOperations<Outer, T, Capacity, AllocPolicy, TraceFunc>
{
using Vec = TraceableVector<T, Capacity, AllocPolicy, TraceFunc>;
Vec& vec() { return static_cast<Outer*>(this)->extract(); }
public:
AllocPolicy& allocPolicy() { return vec().allocPolicy(); }
T* begin() { return vec().begin(); }
T* end() { return vec().end(); }
T& operator[](size_t aIndex) { return vec().operator[](aIndex); }
T& back() { return vec().back(); }
bool initCapacity(size_t aRequest) { return vec().initCapacity(aRequest); }
bool reserve(size_t aRequest) { return vec().reserve(aRequest); }
void shrinkBy(size_t aIncr) { vec().shrinkBy(aIncr); }
bool growBy(size_t aIncr) { return vec().growBy(aIncr); }
bool resize(size_t aNewLength) { return vec().resize(aNewLength); }
bool growByUninitialized(size_t aIncr) { return vec().growByUninitialized(aIncr); }
void infallibleGrowByUninitialized(size_t aIncr) { vec().infallibleGrowByUninitialized(aIncr); }
bool resizeUninitialized(size_t aNewLength) { return vec().resizeUninitialized(aNewLength); }
void clear() { vec().clear(); }
void clearAndFree() { vec().clearAndFree(); }
template<typename U> bool append(U&& aU) { return vec().append(mozilla::Forward<U>(aU)); }
template<typename... Args> bool emplaceBack(Args&&... aArgs) {
return vec().emplaceBack(mozilla::Forward<Args...>(aArgs...));
}
template<typename U, size_t O, class BP, class UV>
bool appendAll(const mozilla::VectorBase<U, O, BP, UV>& aU) { return vec().appendAll(aU); }
bool appendN(const T& aT, size_t aN) { return vec().appendN(aT, aN); }
template<typename U> bool append(const U* aBegin, const U* aEnd) {
return vec().append(aBegin, aEnd);
}
template<typename U> bool append(const U* aBegin, size_t aLength) {
return vec().append(aBegin, aLength);
}
template<typename U> void infallibleAppend(U&& aU) {
vec().infallibleAppend(mozilla::Forward<U>(aU));
}
void infallibleAppendN(const T& aT, size_t aN) { vec().infallibleAppendN(aT, aN); }
template<typename U> void infallibleAppend(const U* aBegin, const U* aEnd) {
vec().infallibleAppend(aBegin, aEnd);
}
template<typename U> void infallibleAppend(const U* aBegin, size_t aLength) {
vec().infallibleAppend(aBegin, aLength);
}
void popBack() { vec().popBack(); }
T popCopy() { return vec().podCopy(); }
template<typename U> T* insert(T* aP, U&& aVal) {
return vec().insert(aP, mozilla::Forward<U>(aVal));
}
void erase(T* aT) { vec().erase(aT); }
void erase(T* aBegin, T* aEnd) { vec().erase(aBegin, aEnd); }
};
template <typename A, size_t B, typename C, typename D>
class RootedBase<TraceableVector<A,B,C,D>>
: public MutableTraceableVectorOperations<JS::Rooted<TraceableVector<A,B,C,D>>, A,B,C,D>
{
using Vec = TraceableVector<A,B,C,D>;
friend class TraceableVectorOperations<JS::Rooted<Vec>, A,B,C,D>;
const Vec& extract() const { return *static_cast<const JS::Rooted<Vec>*>(this)->address(); }
friend class MutableTraceableVectorOperations<JS::Rooted<Vec>, A,B,C,D>;
Vec& extract() { return *static_cast<JS::Rooted<Vec>*>(this)->address(); }
};
template <typename A, size_t B, typename C, typename D>
class MutableHandleBase<TraceableVector<A,B,C,D>>
: public MutableTraceableVectorOperations<JS::MutableHandle<TraceableVector<A,B,C,D>>, A,B,C,D>
{
using Vec = TraceableVector<A,B,C,D>;
friend class TraceableVectorOperations<JS::MutableHandle<Vec>, A,B,C,D>;
const Vec& extract() const {
return *static_cast<const JS::MutableHandle<Vec>*>(this)->address();
}
friend class MutableTraceableVectorOperations<JS::MutableHandle<Vec>, A,B,C,D>;
Vec& extract() { return *static_cast<JS::MutableHandle<Vec>*>(this)->address(); }
};
template <typename A, size_t B, typename C, typename D>
class HandleBase<TraceableVector<A,B,C,D>>
: public TraceableVectorOperations<JS::Handle<TraceableVector<A,B,C,D>>, A,B,C,D>
{
using Vec = TraceableVector<A,B,C,D>;
friend class TraceableVectorOperations<JS::Handle<Vec>, A,B,C,D>;
const Vec& extract() const {
return *static_cast<const JS::Handle<Vec>*>(this)->address();
}
};
} // namespace js
#endif // js_TraceableVector_h

Просмотреть файл

@ -8,11 +8,5 @@
"algorithm": "sha512",
"filename": "gcc.tar.xz",
"unpack": true
},
{
"size": 40,
"digest": "459b332864aece4742cd1a6886e56cf3f202e5c27bb481cfae6145ce3e2e52fb34d1448788c6618e58a26a64e415341895326d293e0d2968e56efc0ae990acd0",
"algorithm": "sha512",
"filename": "setup.sh.gcc"
}
]

Просмотреть файл

@ -8,11 +8,5 @@
"algorithm": "sha512",
"filename": "gcc.tar.xz",
"unpack": true
},
{
"size": 40,
"digest": "459b332864aece4742cd1a6886e56cf3f202e5c27bb481cfae6145ce3e2e52fb34d1448788c6618e58a26a64e415341895326d293e0d2968e56efc0ae990acd0",
"algorithm": "sha512",
"filename": "setup.sh.gcc"
}
]

Просмотреть файл

@ -9,11 +9,5 @@
"filename" : "sixgill.tar.xz",
"size" : 2159496,
"unpack": true
},
{
"algorithm" : "sha512",
"digest" : "9f4a123b8b037c4313c7065f872e07af38390f352f2498b41779c389fa1a0712e5f588d7b3d9a124875916f5257434da83553b560d7d146192f3f6c8da6f0412",
"filename" : "setup.sh.sixgill",
"size" : 48
}
]

Просмотреть файл

@ -9,11 +9,5 @@
"filename" : "sixgill.tar.xz",
"size" : 2255520,
"unpack": true
},
{
"algorithm" : "sha512",
"digest" : "9f4a123b8b037c4313c7065f872e07af38390f352f2498b41779c389fa1a0712e5f588d7b3d9a124875916f5257434da83553b560d7d146192f3f6c8da6f0412",
"filename" : "setup.sh.sixgill",
"size" : 48
}
]

Просмотреть файл

@ -317,23 +317,29 @@ struct PersistentRootedMarker
} // namespace gc
} // namespace js
void
js::gc::MarkPersistentRootedChainsInLists(RootLists& roots, JSTracer* trc)
{
PersistentRootedMarker<JSFunction*>::markChain(trc, roots.functionPersistentRooteds,
"PersistentRooted<JSFunction*>");
PersistentRootedMarker<JSObject*>::markChain(trc, roots.objectPersistentRooteds,
"PersistentRooted<JSObject*>");
PersistentRootedMarker<JSScript*>::markChain(trc, roots.scriptPersistentRooteds,
"PersistentRooted<JSScript*>");
PersistentRootedMarker<JSString*>::markChain(trc, roots.stringPersistentRooteds,
"PersistentRooted<JSString*>");
PersistentRootedMarker<jsid>::markChain(trc, roots.idPersistentRooteds,
"PersistentRooted<jsid>");
PersistentRootedMarker<Value>::markChain(trc, roots.valuePersistentRooteds,
"PersistentRooted<Value>");
}
void
js::gc::MarkPersistentRootedChains(JSTracer* trc)
{
JSRuntime* rt = trc->runtime();
PersistentRootedMarker<JSFunction*>::markChain(trc, rt->functionPersistentRooteds,
"PersistentRooted<JSFunction*>");
PersistentRootedMarker<JSObject*>::markChain(trc, rt->objectPersistentRooteds,
"PersistentRooted<JSObject*>");
PersistentRootedMarker<JSScript*>::markChain(trc, rt->scriptPersistentRooteds,
"PersistentRooted<JSScript*>");
PersistentRootedMarker<JSString*>::markChain(trc, rt->stringPersistentRooteds,
"PersistentRooted<JSString*>");
PersistentRootedMarker<jsid>::markChain(trc, rt->idPersistentRooteds,
"PersistentRooted<jsid>");
PersistentRootedMarker<Value>::markChain(trc, rt->valuePersistentRooteds,
"PersistentRooted<Value>");
for (ContextIter cx(trc->runtime()); !cx.done(); cx.next())
MarkPersistentRootedChainsInLists(cx->roots, trc);
MarkPersistentRootedChainsInLists(trc->runtime()->mainThread.roots, trc);
}
void

Просмотреть файл

@ -27,6 +27,7 @@
#include "jit/SharedICHelpers.h"
#include "jit/VMFunctions.h"
#include "js/Conversions.h"
#include "js/TraceableVector.h"
#include "vm/Opcodes.h"
#include "vm/TypedArrayCommon.h"
@ -5047,11 +5048,11 @@ ICSetElem_DenseOrUnboxedArray::Compiler::generateStubCode(MacroAssembler& masm)
}
static bool
GetProtoShapes(JSObject* obj, size_t protoChainDepth, AutoShapeVector* shapes)
GetProtoShapes(JSObject* obj, size_t protoChainDepth, MutableHandle<ShapeVector> shapes)
{
JSObject* curProto = obj->getProto();
for (size_t i = 0; i < protoChainDepth; i++) {
if (!shapes->append(curProto->as<NativeObject>().lastProperty()))
if (!shapes.append(curProto->as<NativeObject>().lastProperty()))
return false;
curProto = curProto->getProto();
}
@ -5066,7 +5067,7 @@ GetProtoShapes(JSObject* obj, size_t protoChainDepth, AutoShapeVector* shapes)
ICUpdatedStub*
ICSetElemDenseOrUnboxedArrayAddCompiler::getStub(ICStubSpace* space)
{
AutoShapeVector shapes(cx);
Rooted<ShapeVector> shapes(cx, ShapeVector(cx));
if (!shapes.append(obj_->maybeShape()))
return nullptr;
@ -5077,11 +5078,11 @@ ICSetElemDenseOrUnboxedArrayAddCompiler::getStub(ICStubSpace* space)
ICUpdatedStub* stub = nullptr;
switch (protoChainDepth_) {
case 0: stub = getStubSpecific<0>(space, &shapes); break;
case 1: stub = getStubSpecific<1>(space, &shapes); break;
case 2: stub = getStubSpecific<2>(space, &shapes); break;
case 3: stub = getStubSpecific<3>(space, &shapes); break;
case 4: stub = getStubSpecific<4>(space, &shapes); break;
case 0: stub = getStubSpecific<0>(space, shapes); break;
case 1: stub = getStubSpecific<1>(space, shapes); break;
case 2: stub = getStubSpecific<2>(space, shapes); break;
case 3: stub = getStubSpecific<3>(space, shapes); break;
case 4: stub = getStubSpecific<4>(space, shapes); break;
default: MOZ_CRASH("ProtoChainDepth too high.");
}
if (!stub || !stub->initUpdatingChain(cx, space))
@ -5660,7 +5661,7 @@ ICInNativeCompiler::generateStubCode(MacroAssembler& masm)
ICStub*
ICInNativeDoesNotExistCompiler::getStub(ICStubSpace* space)
{
AutoShapeVector shapes(cx);
Rooted<ShapeVector> shapes(cx, ShapeVector(cx));
if (!shapes.append(obj_->as<NativeObject>().lastProperty()))
return nullptr;
@ -5671,15 +5672,15 @@ ICInNativeDoesNotExistCompiler::getStub(ICStubSpace* space)
ICStub* stub = nullptr;
switch (protoChainDepth_) {
case 0: stub = getStubSpecific<0>(space, &shapes); break;
case 1: stub = getStubSpecific<1>(space, &shapes); break;
case 2: stub = getStubSpecific<2>(space, &shapes); break;
case 3: stub = getStubSpecific<3>(space, &shapes); break;
case 4: stub = getStubSpecific<4>(space, &shapes); break;
case 5: stub = getStubSpecific<5>(space, &shapes); break;
case 6: stub = getStubSpecific<6>(space, &shapes); break;
case 7: stub = getStubSpecific<7>(space, &shapes); break;
case 8: stub = getStubSpecific<8>(space, &shapes); break;
case 0: stub = getStubSpecific<0>(space, shapes); break;
case 1: stub = getStubSpecific<1>(space, shapes); break;
case 2: stub = getStubSpecific<2>(space, shapes); break;
case 3: stub = getStubSpecific<3>(space, shapes); break;
case 4: stub = getStubSpecific<4>(space, shapes); break;
case 5: stub = getStubSpecific<5>(space, shapes); break;
case 6: stub = getStubSpecific<6>(space, shapes); break;
case 7: stub = getStubSpecific<7>(space, shapes); break;
case 8: stub = getStubSpecific<8>(space, shapes); break;
default: MOZ_CRASH("ProtoChainDepth too high.");
}
if (!stub)
@ -6018,7 +6019,7 @@ TryAttachScopeNameStub(JSContext* cx, HandleScript script, ICGetName_Fallback* s
{
MOZ_ASSERT(!*attached);
AutoShapeVector shapes(cx);
Rooted<ShapeVector> shapes(cx, ShapeVector(cx));
RootedId id(cx, NameToId(name));
RootedObject scopeChain(cx, initialScopeChain);
@ -6063,37 +6064,44 @@ TryAttachScopeNameStub(JSContext* cx, HandleScript script, ICGetName_Fallback* s
switch (shapes.length()) {
case 1: {
ICGetName_Scope<0>::Compiler compiler(cx, monitorStub, &shapes, isFixedSlot, offset);
ICGetName_Scope<0>::Compiler compiler(cx, monitorStub, Move(shapes.get()), isFixedSlot,
offset);
newStub = compiler.getStub(compiler.getStubSpace(script));
break;
}
case 2: {
ICGetName_Scope<1>::Compiler compiler(cx, monitorStub, &shapes, isFixedSlot, offset);
ICGetName_Scope<1>::Compiler compiler(cx, monitorStub, Move(shapes.get()), isFixedSlot,
offset);
newStub = compiler.getStub(compiler.getStubSpace(script));
break;
}
case 3: {
ICGetName_Scope<2>::Compiler compiler(cx, monitorStub, &shapes, isFixedSlot, offset);
ICGetName_Scope<2>::Compiler compiler(cx, monitorStub, Move(shapes.get()), isFixedSlot,
offset);
newStub = compiler.getStub(compiler.getStubSpace(script));
break;
}
case 4: {
ICGetName_Scope<3>::Compiler compiler(cx, monitorStub, &shapes, isFixedSlot, offset);
ICGetName_Scope<3>::Compiler compiler(cx, monitorStub, Move(shapes.get()), isFixedSlot,
offset);
newStub = compiler.getStub(compiler.getStubSpace(script));
break;
}
case 5: {
ICGetName_Scope<4>::Compiler compiler(cx, monitorStub, &shapes, isFixedSlot, offset);
ICGetName_Scope<4>::Compiler compiler(cx, monitorStub, Move(shapes.get()), isFixedSlot,
offset);
newStub = compiler.getStub(compiler.getStubSpace(script));
break;
}
case 6: {
ICGetName_Scope<5>::Compiler compiler(cx, monitorStub, &shapes, isFixedSlot, offset);
ICGetName_Scope<5>::Compiler compiler(cx, monitorStub, Move(shapes.get()), isFixedSlot,
offset);
newStub = compiler.getStub(compiler.getStubSpace(script));
break;
}
case 7: {
ICGetName_Scope<6>::Compiler compiler(cx, monitorStub, &shapes, isFixedSlot, offset);
ICGetName_Scope<6>::Compiler compiler(cx, monitorStub, Move(shapes.get()), isFixedSlot,
offset);
newStub = compiler.getStub(compiler.getStubSpace(script));
break;
}
@ -7490,7 +7498,7 @@ ICGetPropNativeCompiler::generateStubCode(MacroAssembler& masm)
ICStub*
ICGetPropNativeDoesNotExistCompiler::getStub(ICStubSpace* space)
{
AutoShapeVector shapes(cx);
Rooted<ShapeVector> shapes(cx, ShapeVector(cx));
if (!GetProtoShapes(obj_, protoChainDepth_, &shapes))
return nullptr;
@ -7499,15 +7507,15 @@ ICGetPropNativeDoesNotExistCompiler::getStub(ICStubSpace* space)
ICStub* stub = nullptr;
switch(protoChainDepth_) {
case 0: stub = getStubSpecific<0>(space, &shapes); break;
case 1: stub = getStubSpecific<1>(space, &shapes); break;
case 2: stub = getStubSpecific<2>(space, &shapes); break;
case 3: stub = getStubSpecific<3>(space, &shapes); break;
case 4: stub = getStubSpecific<4>(space, &shapes); break;
case 5: stub = getStubSpecific<5>(space, &shapes); break;
case 6: stub = getStubSpecific<6>(space, &shapes); break;
case 7: stub = getStubSpecific<7>(space, &shapes); break;
case 8: stub = getStubSpecific<8>(space, &shapes); break;
case 0: stub = getStubSpecific<0>(space, shapes); break;
case 1: stub = getStubSpecific<1>(space, shapes); break;
case 2: stub = getStubSpecific<2>(space, shapes); break;
case 3: stub = getStubSpecific<3>(space, shapes); break;
case 4: stub = getStubSpecific<4>(space, shapes); break;
case 5: stub = getStubSpecific<5>(space, shapes); break;
case 6: stub = getStubSpecific<6>(space, shapes); break;
case 7: stub = getStubSpecific<7>(space, shapes); break;
case 8: stub = getStubSpecific<8>(space, shapes); break;
default: MOZ_CRASH("ProtoChainDepth too high.");
}
if (!stub)
@ -8743,7 +8751,7 @@ ICSetProp_Native::Compiler::generateStubCode(MacroAssembler& masm)
ICUpdatedStub*
ICSetPropNativeAddCompiler::getStub(ICStubSpace* space)
{
AutoShapeVector shapes(cx);
Rooted<ShapeVector> shapes(cx, ShapeVector(cx));
if (!shapes.append(oldShape_))
return nullptr;
@ -8754,11 +8762,11 @@ ICSetPropNativeAddCompiler::getStub(ICStubSpace* space)
ICUpdatedStub* stub = nullptr;
switch(protoChainDepth_) {
case 0: stub = getStubSpecific<0>(space, &shapes); break;
case 1: stub = getStubSpecific<1>(space, &shapes); break;
case 2: stub = getStubSpecific<2>(space, &shapes); break;
case 3: stub = getStubSpecific<3>(space, &shapes); break;
case 4: stub = getStubSpecific<4>(space, &shapes); break;
case 0: stub = getStubSpecific<0>(space, shapes); break;
case 1: stub = getStubSpecific<1>(space, shapes); break;
case 2: stub = getStubSpecific<2>(space, shapes); break;
case 3: stub = getStubSpecific<3>(space, shapes); break;
case 4: stub = getStubSpecific<4>(space, shapes); break;
default: MOZ_CRASH("ProtoChainDepth too high.");
}
if (!stub || !stub->initUpdatingChain(cx, space))
@ -12127,7 +12135,8 @@ ICSetElem_DenseOrUnboxedArrayAdd::ICSetElem_DenseOrUnboxedArrayAdd(JitCode* stub
template <size_t ProtoChainDepth>
ICUpdatedStub*
ICSetElemDenseOrUnboxedArrayAddCompiler::getStubSpecific(ICStubSpace* space, const AutoShapeVector* shapes)
ICSetElemDenseOrUnboxedArrayAddCompiler::getStubSpecific(ICStubSpace* space,
Handle<ShapeVector> shapes)
{
RootedObjectGroup group(cx, obj_->getGroup(cx));
if (!group)
@ -12181,12 +12190,12 @@ ICIn_NativeDoesNotExist::offsetOfShape(size_t idx)
template <size_t ProtoChainDepth>
ICIn_NativeDoesNotExistImpl<ProtoChainDepth>::ICIn_NativeDoesNotExistImpl(
JitCode* stubCode, const AutoShapeVector* shapes, HandlePropertyName name)
JitCode* stubCode, Handle<ShapeVector> shapes, HandlePropertyName name)
: ICIn_NativeDoesNotExist(stubCode, ProtoChainDepth, name)
{
MOZ_ASSERT(shapes->length() == NumShapes);
MOZ_ASSERT(shapes.length() == NumShapes);
for (size_t i = 0; i < NumShapes; i++)
shapes_[i].init((*shapes)[i]);
shapes_[i].init(shapes[i]);
}
ICInNativeDoesNotExistCompiler::ICInNativeDoesNotExistCompiler(
@ -12213,14 +12222,14 @@ ICGetName_Global::ICGetName_Global(JitCode* stubCode, ICStub* firstMonitorStub,
template <size_t NumHops>
ICGetName_Scope<NumHops>::ICGetName_Scope(JitCode* stubCode, ICStub* firstMonitorStub,
AutoShapeVector* shapes, uint32_t offset)
Handle<ShapeVector> shapes, uint32_t offset)
: ICMonitoredStub(GetStubKind(), stubCode, firstMonitorStub),
offset_(offset)
{
JS_STATIC_ASSERT(NumHops <= MAX_HOPS);
MOZ_ASSERT(shapes->length() == NumHops + 1);
MOZ_ASSERT(shapes.length() == NumHops + 1);
for (size_t i = 0; i < NumHops + 1; i++)
shapes_[i].init((*shapes)[i]);
shapes_[i].init(shapes[i]);
}
ICGetIntrinsic_Constant::ICGetIntrinsic_Constant(JitCode* stubCode, const Value& value)
@ -12297,14 +12306,14 @@ ICGetProp_NativeDoesNotExist::offsetOfShape(size_t idx)
template <size_t ProtoChainDepth>
ICGetProp_NativeDoesNotExistImpl<ProtoChainDepth>::ICGetProp_NativeDoesNotExistImpl(
JitCode* stubCode, ICStub* firstMonitorStub, ReceiverGuard guard,
const AutoShapeVector* shapes)
Handle<ShapeVector> shapes)
: ICGetProp_NativeDoesNotExist(stubCode, firstMonitorStub, guard, ProtoChainDepth)
{
MOZ_ASSERT(shapes->length() == NumShapes);
MOZ_ASSERT(shapes.length() == NumShapes);
// Note: using int32_t here to avoid gcc warning.
for (int32_t i = 0; i < int32_t(NumShapes); i++)
shapes_[i].init((*shapes)[i]);
shapes_[i].init(shapes[i]);
}
ICGetPropNativeDoesNotExistCompiler::ICGetPropNativeDoesNotExistCompiler(
@ -12401,15 +12410,15 @@ ICSetProp_NativeAdd::ICSetProp_NativeAdd(JitCode* stubCode, ObjectGroup* group,
template <size_t ProtoChainDepth>
ICSetProp_NativeAddImpl<ProtoChainDepth>::ICSetProp_NativeAddImpl(JitCode* stubCode,
ObjectGroup* group,
const AutoShapeVector* shapes,
Handle<ShapeVector> shapes,
Shape* newShape,
ObjectGroup* newGroup,
uint32_t offset)
: ICSetProp_NativeAdd(stubCode, group, ProtoChainDepth, newShape, newGroup, offset)
{
MOZ_ASSERT(shapes->length() == NumShapes);
MOZ_ASSERT(shapes.length() == NumShapes);
for (size_t i = 0; i < NumShapes; i++)
shapes_[i].init((*shapes)[i]);
shapes_[i].init(shapes[i]);
}
ICSetPropNativeAddCompiler::ICSetPropNativeAddCompiler(JSContext* cx, HandleObject obj,

Просмотреть файл

@ -19,6 +19,7 @@
#include "jit/BaselineJIT.h"
#include "jit/SharedIC.h"
#include "jit/SharedICRegisters.h"
#include "js/TraceableVector.h"
#include "vm/ArrayObject.h"
#include "vm/ReceiverGuard.h"
#include "vm/TypedArrayCommon.h"
@ -2247,12 +2248,12 @@ class ICSetElem_DenseOrUnboxedArrayAddImpl : public ICSetElem_DenseOrUnboxedArra
mozilla::Array<HeapPtrShape, NumShapes> shapes_;
ICSetElem_DenseOrUnboxedArrayAddImpl(JitCode* stubCode, ObjectGroup* group,
const AutoShapeVector* shapes)
Handle<ShapeVector> shapes)
: ICSetElem_DenseOrUnboxedArrayAdd(stubCode, group, ProtoChainDepth)
{
MOZ_ASSERT(shapes->length() == NumShapes);
MOZ_ASSERT(shapes.length() == NumShapes);
for (size_t i = 0; i < NumShapes; i++)
shapes_[i].init((*shapes)[i]);
shapes_[i].init(shapes[i]);
}
public:
@ -2297,7 +2298,7 @@ class ICSetElemDenseOrUnboxedArrayAddCompiler : public ICStubCompiler {
{}
template <size_t ProtoChainDepth>
ICUpdatedStub* getStubSpecific(ICStubSpace* space, const AutoShapeVector* shapes);
ICUpdatedStub* getStubSpecific(ICStubSpace* space, Handle<ShapeVector> shapes);
ICUpdatedStub* getStub(ICStubSpace* space);
@ -2540,7 +2541,7 @@ class ICIn_NativeDoesNotExistImpl : public ICIn_NativeDoesNotExist
private:
mozilla::Array<HeapPtrShape, NumShapes> shapes_;
ICIn_NativeDoesNotExistImpl(JitCode* stubCode, const AutoShapeVector* shapes,
ICIn_NativeDoesNotExistImpl(JitCode* stubCode, Handle<ShapeVector> shapes,
HandlePropertyName name);
public:
@ -2574,7 +2575,7 @@ class ICInNativeDoesNotExistCompiler : public ICStubCompiler
size_t protoChainDepth);
template <size_t ProtoChainDepth>
ICStub* getStubSpecific(ICStubSpace* space, const AutoShapeVector* shapes) {
ICStub* getStubSpecific(ICStubSpace* space, Handle<ShapeVector> shapes) {
return newStub<ICIn_NativeDoesNotExistImpl<ProtoChainDepth>>(space, getStubCode(), shapes,
name_);}
@ -2715,7 +2716,7 @@ class ICGetName_Scope : public ICMonitoredStub
uint32_t offset_;
ICGetName_Scope(JitCode* stubCode, ICStub* firstMonitorStub,
AutoShapeVector* shapes, uint32_t offset);
Handle<ShapeVector> shapes, uint32_t offset);
static Kind GetStubKind() {
return (Kind) (GetName_Scope0 + NumHops);
@ -2737,7 +2738,7 @@ class ICGetName_Scope : public ICMonitoredStub
class Compiler : public ICStubCompiler {
ICStub* firstMonitorStub_;
AutoShapeVector* shapes_;
Rooted<ShapeVector> shapes_;
bool isFixedSlot_;
uint32_t offset_;
@ -2753,10 +2754,10 @@ class ICGetName_Scope : public ICMonitoredStub
public:
Compiler(JSContext* cx, ICStub* firstMonitorStub,
AutoShapeVector* shapes, bool isFixedSlot, uint32_t offset)
ShapeVector&& shapes, bool isFixedSlot, uint32_t offset)
: ICStubCompiler(cx, GetStubKind(), Engine::Baseline),
firstMonitorStub_(firstMonitorStub),
shapes_(shapes),
shapes_(cx, mozilla::Forward<ShapeVector>(shapes)),
isFixedSlot_(isFixedSlot),
offset_(offset)
{
@ -3263,7 +3264,7 @@ class ICGetProp_NativeDoesNotExistImpl : public ICGetProp_NativeDoesNotExist
ICGetProp_NativeDoesNotExistImpl(JitCode* stubCode, ICStub* firstMonitorStub,
ReceiverGuard guard,
const AutoShapeVector* shapes);
Handle<ShapeVector> shapes);
public:
void traceShapes(JSTracer* trc) {
@ -3298,7 +3299,7 @@ class ICGetPropNativeDoesNotExistCompiler : public ICStubCompiler
HandleObject obj, size_t protoChainDepth);
template <size_t ProtoChainDepth>
ICStub* getStubSpecific(ICStubSpace* space, const AutoShapeVector* shapes) {
ICStub* getStubSpecific(ICStubSpace* space, Handle<ShapeVector> shapes) {
ReceiverGuard guard(obj_);
return newStub<ICGetProp_NativeDoesNotExistImpl<ProtoChainDepth>>
(space, getStubCode(), firstMonitorStub_, guard, shapes);
@ -4024,7 +4025,7 @@ class ICSetProp_NativeAddImpl : public ICSetProp_NativeAdd
mozilla::Array<HeapPtrShape, NumShapes> shapes_;
ICSetProp_NativeAddImpl(JitCode* stubCode, ObjectGroup* group,
const AutoShapeVector* shapes,
Handle<ShapeVector> shapes,
Shape* newShape, ObjectGroup* newGroup, uint32_t offset);
public:
@ -4064,7 +4065,7 @@ class ICSetPropNativeAddCompiler : public ICStubCompiler
size_t protoChainDepth, bool isFixedSlot, uint32_t offset);
template <size_t ProtoChainDepth>
ICUpdatedStub* getStubSpecific(ICStubSpace* space, const AutoShapeVector* shapes)
ICUpdatedStub* getStubSpecific(ICStubSpace* space, Handle<ShapeVector> shapes)
{
RootedObjectGroup newGroup(cx, obj_->getGroup(cx));
if (!newGroup)

Просмотреть файл

@ -7,6 +7,7 @@
#include "js/RootingAPI.h"
#include "js/TraceableHashTable.h"
#include "js/TraceableVector.h"
#include "jsapi-tests/tests.h"
@ -167,6 +168,8 @@ BEGIN_TEST(testGCRootedHashMap)
for (size_t i = 0; i < 10; ++i) {
RootedObject obj(cx, JS_NewObject(cx, nullptr));
RootedValue val(cx, UndefinedValue());
// Construct a unique property name to ensure that the object creates a
// new shape.
char buffer[2];
buffer[0] = 'a' + i;
buffer[1] = '\0';
@ -192,6 +195,8 @@ FillMyHashMap(JSContext* cx, MutableHandle<MyHashMap> map)
for (size_t i = 0; i < 10; ++i) {
RootedObject obj(cx, JS_NewObject(cx, nullptr));
RootedValue val(cx, UndefinedValue());
// Construct a unique property name to ensure that the object creates a
// new shape.
char buffer[2];
buffer[0] = 'a' + i;
buffer[1] = '\0';
@ -230,3 +235,109 @@ BEGIN_TEST(testGCHandleHashMap)
return true;
}
END_TEST(testGCHandleHashMap)
BEGIN_TEST(testGCRootedVector)
{
using ShapeVec = TraceableVector<Shape*>;
JS::Rooted<ShapeVec> shapes(cx, ShapeVec(cx));
for (size_t i = 0; i < 10; ++i) {
RootedObject obj(cx, JS_NewObject(cx, nullptr));
RootedValue val(cx, UndefinedValue());
// Construct a unique property name to ensure that the object creates a
// new shape.
char buffer[2];
buffer[0] = 'a' + i;
buffer[1] = '\0';
CHECK(JS_SetProperty(cx, obj, buffer, val));
CHECK(shapes.append(obj->as<NativeObject>().lastProperty()));
}
JS_GC(rt);
JS_GC(rt);
for (size_t i = 0; i < 10; ++i) {
// Check the shape to ensure it did not get collected.
char buffer[2];
buffer[0] = 'a' + i;
buffer[1] = '\0';
bool match;
CHECK(JS_StringEqualsAscii(cx, JSID_TO_STRING(shapes[i]->propid()), buffer, &match));
CHECK(match);
}
// Ensure iterator enumeration works through the rooted.
for (auto shape : shapes) {
CHECK(shape);
}
return true;
}
END_TEST(testGCRootedVector)
using ShapeVec = TraceableVector<Shape*>;
static bool
FillVector(JSContext* cx, MutableHandle<ShapeVec> shapes)
{
for (size_t i = 0; i < 10; ++i) {
RootedObject obj(cx, JS_NewObject(cx, nullptr));
RootedValue val(cx, UndefinedValue());
// Construct a unique property name to ensure that the object creates a
// new shape.
char buffer[2];
buffer[0] = 'a' + i;
buffer[1] = '\0';
if (!JS_SetProperty(cx, obj, buffer, val))
return false;
if (!shapes.append(obj->as<NativeObject>().lastProperty()))
return false;
}
// Ensure iterator enumeration works through the mutable handle.
for (auto shape : shapes) {
if (!shape)
return false;
}
return true;
}
static bool
CheckVector(JSContext* cx, Handle<ShapeVec> shapes)
{
for (size_t i = 0; i < 10; ++i) {
// Check the shape to ensure it did not get collected.
char buffer[2];
buffer[0] = 'a' + i;
buffer[1] = '\0';
bool match;
if (!JS_StringEqualsAscii(cx, JSID_TO_STRING(shapes[i]->propid()), buffer, &match))
return false;
if (!match)
return false;
}
// Ensure iterator enumeration works through the handle.
for (auto shape : shapes) {
if (!shape)
return false;
}
return true;
}
BEGIN_TEST(testGCHandleVector)
{
JS::Rooted<ShapeVec> vec(cx, ShapeVec(cx));
CHECK(FillVector(cx, &vec));
JS_GC(rt);
JS_GC(rt);
CHECK(CheckVector(cx, vec));
return true;
}
END_TEST(testGCHandleVector)

Просмотреть файл

@ -154,9 +154,10 @@ js::DestroyContext(JSContext* cx, DestroyContextMode mode)
JS_AbortIfWrongThread(rt);
if (cx->outstandingRequests != 0)
MOZ_CRASH();
MOZ_CRASH("Attempted to destroy a context while it is in a request.");
cx->roots.checkNoGCRooters();
FinishPersistentRootedChains(cx->roots);
if (mode != DCM_NEW_FAILED) {
if (JSContextCallback cxCallback = rt->cxCallback) {

Просмотреть файл

@ -11,6 +11,7 @@
#include "mozilla/MemoryReporting.h"
#include "js/TraceableVector.h"
#include "js/Vector.h"
#include "vm/Runtime.h"
@ -666,6 +667,8 @@ typedef JS::AutoVectorRooter<JSString*> AutoStringVector;
typedef JS::AutoVectorRooter<PropertyName*> AutoPropertyNameVector;
typedef JS::AutoVectorRooter<Shape*> AutoShapeVector;
using ShapeVector = js::TraceableVector<Shape*>;
/* AutoArrayRooter roots an external array of Values. */
class AutoArrayRooter : private JS::AutoGCRooter
{

Просмотреть файл

@ -1364,15 +1364,14 @@ FinishPersistentRootedChain(mozilla::LinkedList<PersistentRooted<T>>& list)
}
void
js::gc::FinishPersistentRootedChains(JSRuntime* rt)
js::gc::FinishPersistentRootedChains(RootLists& roots)
{
/* The lists of persistent roots are stored on the shadow runtime. */
FinishPersistentRootedChain(rt->functionPersistentRooteds);
FinishPersistentRootedChain(rt->idPersistentRooteds);
FinishPersistentRootedChain(rt->objectPersistentRooteds);
FinishPersistentRootedChain(rt->scriptPersistentRooteds);
FinishPersistentRootedChain(rt->stringPersistentRooteds);
FinishPersistentRootedChain(rt->valuePersistentRooteds);
FinishPersistentRootedChain(roots.functionPersistentRooteds);
FinishPersistentRootedChain(roots.idPersistentRooteds);
FinishPersistentRootedChain(roots.objectPersistentRooteds);
FinishPersistentRootedChain(roots.scriptPersistentRooteds);
FinishPersistentRootedChain(roots.stringPersistentRooteds);
FinishPersistentRootedChain(roots.valuePersistentRooteds);
}
void
@ -1381,7 +1380,7 @@ GCRuntime::finishRoots()
if (rootsHash.initialized())
rootsHash.clear();
FinishPersistentRootedChains(rt);
FinishPersistentRootedChains(rt->mainThread.roots);
}
void

Просмотреть файл

@ -46,6 +46,7 @@ struct Zone;
namespace js {
struct ContextFriendFields;
class RootLists;
class Shape;
} // namespace js
@ -131,7 +132,8 @@ namespace gc {
class AutoTraceSession;
class StoreBuffer;
void MarkPersistentRootedChains(JSTracer*);
void FinishPersistentRootedChains(JSRuntime*);
void MarkPersistentRootedChainsInLists(js::RootLists&, JSTracer*);
void FinishPersistentRootedChains(js::RootLists&);
} // namespace gc
} // namespace js
@ -175,49 +177,8 @@ struct Runtime
void setGCStoreBufferPtr(js::gc::StoreBuffer* storeBuffer) {
gcStoreBufferPtr_ = storeBuffer;
}
/* Allow inlining of PersistentRooted constructors and destructors. */
private:
template <typename Referent> friend class JS::PersistentRooted;
friend void js::gc::MarkPersistentRootedChains(JSTracer*);
friend void js::gc::FinishPersistentRootedChains(JSRuntime* rt);
mozilla::LinkedList<PersistentRootedFunction> functionPersistentRooteds;
mozilla::LinkedList<PersistentRootedId> idPersistentRooteds;
mozilla::LinkedList<PersistentRootedObject> objectPersistentRooteds;
mozilla::LinkedList<PersistentRootedScript> scriptPersistentRooteds;
mozilla::LinkedList<PersistentRootedString> stringPersistentRooteds;
mozilla::LinkedList<PersistentRootedValue> valuePersistentRooteds;
/* Specializations of this return references to the appropriate list. */
template<typename Referent>
inline mozilla::LinkedList<PersistentRooted<Referent> >& getPersistentRootedList();
};
template<>
inline mozilla::LinkedList<PersistentRootedFunction>
&Runtime::getPersistentRootedList<JSFunction*>() { return functionPersistentRooteds; }
template<>
inline mozilla::LinkedList<PersistentRootedId>
&Runtime::getPersistentRootedList<jsid>() { return idPersistentRooteds; }
template<>
inline mozilla::LinkedList<PersistentRootedObject>
&Runtime::getPersistentRootedList<JSObject*>() { return objectPersistentRooteds; }
template<>
inline mozilla::LinkedList<PersistentRootedScript>
&Runtime::getPersistentRootedList<JSScript*>() { return scriptPersistentRooteds; }
template<>
inline mozilla::LinkedList<PersistentRootedString>
&Runtime::getPersistentRootedList<JSString*>() { return stringPersistentRooteds; }
template<>
inline mozilla::LinkedList<PersistentRootedValue>
&Runtime::getPersistentRootedList<Value>() { return valuePersistentRooteds; }
} /* namespace shadow */
class JS_PUBLIC_API(AutoGCRooter)
@ -376,8 +337,50 @@ class RootLists
}
void checkNoGCRooters();
/* Allow inlining of PersistentRooted constructors and destructors. */
private:
template <typename Referent> friend class JS::PersistentRooted;
friend void js::gc::MarkPersistentRootedChains(JSTracer*);
friend void js::gc::MarkPersistentRootedChainsInLists(RootLists&, JSTracer*);
friend void js::gc::FinishPersistentRootedChains(RootLists&);
mozilla::LinkedList<JS::PersistentRootedFunction> functionPersistentRooteds;
mozilla::LinkedList<JS::PersistentRootedId> idPersistentRooteds;
mozilla::LinkedList<JS::PersistentRootedObject> objectPersistentRooteds;
mozilla::LinkedList<JS::PersistentRootedScript> scriptPersistentRooteds;
mozilla::LinkedList<JS::PersistentRootedString> stringPersistentRooteds;
mozilla::LinkedList<JS::PersistentRootedValue> valuePersistentRooteds;
/* Specializations of this return references to the appropriate list. */
template<typename Referent>
inline mozilla::LinkedList<JS::PersistentRooted<Referent>>& getPersistentRootedList();
};
template<>
inline mozilla::LinkedList<JS::PersistentRootedFunction>
&RootLists::getPersistentRootedList<JSFunction*>() { return functionPersistentRooteds; }
template<>
inline mozilla::LinkedList<JS::PersistentRootedId>
&RootLists::getPersistentRootedList<jsid>() { return idPersistentRooteds; }
template<>
inline mozilla::LinkedList<JS::PersistentRootedObject>
&RootLists::getPersistentRootedList<JSObject*>() { return objectPersistentRooteds; }
template<>
inline mozilla::LinkedList<JS::PersistentRootedScript>
&RootLists::getPersistentRootedList<JSScript*>() { return scriptPersistentRooteds; }
template<>
inline mozilla::LinkedList<JS::PersistentRootedString>
&RootLists::getPersistentRootedList<JSString*>() { return stringPersistentRooteds; }
template<>
inline mozilla::LinkedList<JS::PersistentRootedValue>
&RootLists::getPersistentRootedList<JS::Value>() { return valuePersistentRooteds; }
struct ContextFriendFields
{
protected:

Просмотреть файл

@ -123,6 +123,7 @@ EXPORTS.js += [
'../public/SliceBudget.h',
'../public/StructuredClone.h',
'../public/TraceableHashTable.h',
'../public/TraceableVector.h',
'../public/TraceKind.h',
'../public/TracingAPI.h',
'../public/TrackedOptimizationInfo.h',

Просмотреть файл

@ -201,7 +201,7 @@ ParseTask::ParseTask(ExclusiveContext* cx, JSObject* exclusiveContextGlobal, JSC
JS::OffThreadCompileCallback callback, void* callbackData)
: cx(cx), options(initCx), chars(chars), length(length),
alloc(JSRuntime::TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
exclusiveContextGlobal(initCx, exclusiveContextGlobal),
exclusiveContextGlobal(initCx->runtime(), exclusiveContextGlobal),
callback(callback), callbackData(callbackData),
script(nullptr), errors(cx), overRecursed(false)
{

Просмотреть файл

@ -791,12 +791,12 @@ js::XDRStaticBlockObject(XDRState<mode>* xdr, HandleObject enclosingScope,
obj->setAliased(i, aliased);
}
} else {
AutoShapeVector shapes(cx);
Rooted<ShapeVector> shapes(cx, ShapeVector(cx));
if (!shapes.growBy(count))
return false;
for (Shape::Range<NoGC> r(obj->lastProperty()); !r.empty(); r.popFront())
shapes[obj->shapeToIndex(r.front())].set(&r.front());
shapes[obj->shapeToIndex(r.front())] = &r.front();
RootedShape shape(cx);
RootedId propid(cx);
@ -844,19 +844,20 @@ CloneStaticBlockObject(JSContext* cx, HandleObject enclosingScope, Handle<Static
clone->setLocalOffset(srcBlock->localOffset());
/* Shape::Range is reverse order, so build a list in forward order. */
AutoShapeVector shapes(cx);
Rooted<ShapeVector> shapes(cx, ShapeVector(cx));
if (!shapes.growBy(srcBlock->numVariables()))
return nullptr;
for (Shape::Range<NoGC> r(srcBlock->lastProperty()); !r.empty(); r.popFront())
shapes[srcBlock->shapeToIndex(r.front())].set(&r.front());
shapes[srcBlock->shapeToIndex(r.front())] = &r.front();
for (Shape** p = shapes.begin(); p != shapes.end(); ++p) {
RootedId id(cx, (*p)->propid());
unsigned i = srcBlock->shapeToIndex(**p);
RootedId id(cx);
for (Shape* shape : shapes) {
id = shape->propid();
unsigned i = srcBlock->shapeToIndex(*shape);
bool redeclared;
if (!StaticBlockObject::addVar(cx, clone, id, !(*p)->writable(), i, &redeclared)) {
if (!StaticBlockObject::addVar(cx, clone, id, !shape->writable(), i, &redeclared)) {
MOZ_ASSERT(!redeclared);
return nullptr;
}

Просмотреть файл

@ -1651,7 +1651,7 @@ CloneProperties(JSContext* cx, HandleNativeObject selfHostedObject, HandleObject
}
}
AutoShapeVector shapes(cx);
Rooted<ShapeVector> shapes(cx, ShapeVector(cx));
for (Shape::Range<NoGC> range(selfHostedObject->lastProperty()); !range.empty(); range.popFront()) {
Shape& shape = range.front();
if (shape.enumerable() && !shapes.append(&shape))

Просмотреть файл

@ -88,7 +88,7 @@ class mozJSComponentLoader : public mozilla::ModuleLoader,
{
public:
explicit ModuleEntry(JSContext* aCx)
: mozilla::Module(), obj(aCx, nullptr), thisObjectKey(aCx, nullptr)
: mozilla::Module(), obj(JS_GetRuntime(aCx)), thisObjectKey(JS_GetRuntime(aCx))
{
mVersion = mozilla::Module::kVersion;
mCIDs = nullptr;

Просмотреть файл

@ -32,7 +32,6 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(XPCVariant)
XPCVariant::XPCVariant(JSContext* cx, Value aJSVal)
: mJSVal(aJSVal), mCCGeneration(0)
{
nsVariant::Initialize(&mData);
if (!mJSVal.isPrimitive()) {
// XXXbholley - The innerization here was from bug 638026. Blake says
// the basic problem was that we were storing the C++ inner but the JS
@ -59,7 +58,7 @@ XPCTraceableVariant::~XPCTraceableVariant()
MOZ_ASSERT(val.isGCThing(), "Must be traceable or unlinked");
nsVariant::Cleanup(&mData);
mData.Cleanup();
if (!val.isNull())
RemoveFromRootSet();
@ -80,13 +79,13 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(XPCVariant)
cb.NoteJSObject(&val.toObject());
}
nsVariant::Traverse(tmp->mData, cb);
tmp->mData.Traverse(cb);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XPCVariant)
JS::Value val = tmp->GetJSValPreserveColor();
nsVariant::Cleanup(&tmp->mData);
tmp->mData.Cleanup();
if (val.isMarkable()) {
XPCTraceableVariant* v = static_cast<XPCTraceableVariant*>(tmp);
@ -260,26 +259,26 @@ bool XPCVariant::InitializeData(JSContext* cx)
RootedValue val(cx, GetJSVal());
if (val.isInt32())
return NS_SUCCEEDED(nsVariant::SetFromInt32(&mData, val.toInt32()));
return NS_SUCCEEDED(mData.SetFromInt32(val.toInt32()));
if (val.isDouble())
return NS_SUCCEEDED(nsVariant::SetFromDouble(&mData, val.toDouble()));
return NS_SUCCEEDED(mData.SetFromDouble(val.toDouble()));
if (val.isBoolean())
return NS_SUCCEEDED(nsVariant::SetFromBool(&mData, val.toBoolean()));
return NS_SUCCEEDED(mData.SetFromBool(val.toBoolean()));
// We can't represent symbol on C++ side, so pretend it is void.
if (val.isUndefined() || val.isSymbol())
return NS_SUCCEEDED(nsVariant::SetToVoid(&mData));
return NS_SUCCEEDED(mData.SetToVoid());
if (val.isNull())
return NS_SUCCEEDED(nsVariant::SetToEmpty(&mData));
return NS_SUCCEEDED(mData.SetToEmpty());
if (val.isString()) {
JSString* str = val.toString();
if (!str)
return false;
MOZ_ASSERT(mData.mType == nsIDataType::VTYPE_EMPTY,
MOZ_ASSERT(mData.GetType() == nsIDataType::VTYPE_EMPTY,
"Why do we already have data?");
size_t length = JS_GetStringLength(str);
if (!NS_SUCCEEDED(nsVariant::AllocateWStringWithSize(&mData, length)))
if (!NS_SUCCEEDED(mData.AllocateWStringWithSize(length)))
return false;
mozilla::Range<char16_t> destChars(mData.u.wstr.mWStringValue, length);
@ -299,7 +298,7 @@ bool XPCVariant::InitializeData(JSContext* cx)
const nsID* id = xpc_JSObjectToID(cx, jsobj);
if (id)
return NS_SUCCEEDED(nsVariant::SetFromID(&mData, *id));
return NS_SUCCEEDED(mData.SetFromID(*id));
// Let's see if it is a js array object.
@ -308,7 +307,7 @@ bool XPCVariant::InitializeData(JSContext* cx)
if (JS_IsArrayObject(cx, jsobj) && JS_GetArrayLength(cx, jsobj, &len)) {
if (!len) {
// Zero length array
nsVariant::SetToEmptyArray(&mData);
mData.SetToEmptyArray();
return true;
}
@ -339,7 +338,7 @@ bool XPCVariant::InitializeData(JSContext* cx)
return NS_SUCCEEDED(xpc->WrapJS(cx, jsobj,
iid, getter_AddRefs(wrapper))) &&
NS_SUCCEEDED(nsVariant::SetFromInterface(&mData, iid, wrapper));
NS_SUCCEEDED(mData.SetFromInterface(iid, wrapper));
}
NS_IMETHODIMP
@ -542,7 +541,6 @@ XPCVariant::VariantDataToJS(nsIVariant* variant,
case nsIDataType::VTYPE_ARRAY:
{
nsDiscriminatedUnion du;
nsVariant::Initialize(&du);
nsresult rv;
rv = variant->GetAsArray(&du.u.array.mArrayType,
@ -605,7 +603,6 @@ XPCVariant::VariantDataToJS(nsIVariant* variant,
case nsIDataType::VTYPE_EMPTY:
default:
NS_ERROR("bad type in array!");
nsVariant::Cleanup(&du);
return false;
}
@ -615,7 +612,6 @@ XPCVariant::VariantDataToJS(nsIVariant* variant,
conversionType, pid,
du.u.array.mArrayCount, pErr);
nsVariant::Cleanup(&du);
return success;
}
case nsIDataType::VTYPE_EMPTY_ARRAY:
@ -647,98 +643,98 @@ XPCVariant::VariantDataToJS(nsIVariant* variant,
/* readonly attribute uint16_t dataType; */
NS_IMETHODIMP XPCVariant::GetDataType(uint16_t* aDataType)
{
*aDataType = mData.mType;
*aDataType = mData.GetType();
return NS_OK;
}
/* uint8_t getAsInt8 (); */
NS_IMETHODIMP XPCVariant::GetAsInt8(uint8_t* _retval)
{
return nsVariant::ConvertToInt8(mData, _retval);
return mData.ConvertToInt8(_retval);
}
/* int16_t getAsInt16 (); */
NS_IMETHODIMP XPCVariant::GetAsInt16(int16_t* _retval)
{
return nsVariant::ConvertToInt16(mData, _retval);
return mData.ConvertToInt16(_retval);
}
/* int32_t getAsInt32 (); */
NS_IMETHODIMP XPCVariant::GetAsInt32(int32_t* _retval)
{
return nsVariant::ConvertToInt32(mData, _retval);
return mData.ConvertToInt32(_retval);
}
/* int64_t getAsInt64 (); */
NS_IMETHODIMP XPCVariant::GetAsInt64(int64_t* _retval)
{
return nsVariant::ConvertToInt64(mData, _retval);
return mData.ConvertToInt64(_retval);
}
/* uint8_t getAsUint8 (); */
NS_IMETHODIMP XPCVariant::GetAsUint8(uint8_t* _retval)
{
return nsVariant::ConvertToUint8(mData, _retval);
return mData.ConvertToUint8(_retval);
}
/* uint16_t getAsUint16 (); */
NS_IMETHODIMP XPCVariant::GetAsUint16(uint16_t* _retval)
{
return nsVariant::ConvertToUint16(mData, _retval);
return mData.ConvertToUint16(_retval);
}
/* uint32_t getAsUint32 (); */
NS_IMETHODIMP XPCVariant::GetAsUint32(uint32_t* _retval)
{
return nsVariant::ConvertToUint32(mData, _retval);
return mData.ConvertToUint32(_retval);
}
/* uint64_t getAsUint64 (); */
NS_IMETHODIMP XPCVariant::GetAsUint64(uint64_t* _retval)
{
return nsVariant::ConvertToUint64(mData, _retval);
return mData.ConvertToUint64(_retval);
}
/* float getAsFloat (); */
NS_IMETHODIMP XPCVariant::GetAsFloat(float* _retval)
{
return nsVariant::ConvertToFloat(mData, _retval);
return mData.ConvertToFloat(_retval);
}
/* double getAsDouble (); */
NS_IMETHODIMP XPCVariant::GetAsDouble(double* _retval)
{
return nsVariant::ConvertToDouble(mData, _retval);
return mData.ConvertToDouble(_retval);
}
/* bool getAsBool (); */
NS_IMETHODIMP XPCVariant::GetAsBool(bool* _retval)
{
return nsVariant::ConvertToBool(mData, _retval);
return mData.ConvertToBool(_retval);
}
/* char getAsChar (); */
NS_IMETHODIMP XPCVariant::GetAsChar(char* _retval)
{
return nsVariant::ConvertToChar(mData, _retval);
return mData.ConvertToChar(_retval);
}
/* wchar getAsWChar (); */
NS_IMETHODIMP XPCVariant::GetAsWChar(char16_t* _retval)
{
return nsVariant::ConvertToWChar(mData, _retval);
return mData.ConvertToWChar(_retval);
}
/* [notxpcom] nsresult getAsID (out nsID retval); */
NS_IMETHODIMP_(nsresult) XPCVariant::GetAsID(nsID* retval)
{
return nsVariant::ConvertToID(mData, retval);
return mData.ConvertToID(retval);
}
/* AString getAsAString (); */
NS_IMETHODIMP XPCVariant::GetAsAString(nsAString & _retval)
{
return nsVariant::ConvertToAString(mData, _retval);
return mData.ConvertToAString(_retval);
}
/* DOMString getAsDOMString (); */
@ -746,60 +742,60 @@ NS_IMETHODIMP XPCVariant::GetAsDOMString(nsAString & _retval)
{
// A DOMString maps to an AString internally, so we can re-use
// ConvertToAString here.
return nsVariant::ConvertToAString(mData, _retval);
return mData.ConvertToAString(_retval);
}
/* ACString getAsACString (); */
NS_IMETHODIMP XPCVariant::GetAsACString(nsACString & _retval)
{
return nsVariant::ConvertToACString(mData, _retval);
return mData.ConvertToACString(_retval);
}
/* AUTF8String getAsAUTF8String (); */
NS_IMETHODIMP XPCVariant::GetAsAUTF8String(nsAUTF8String & _retval)
{
return nsVariant::ConvertToAUTF8String(mData, _retval);
return mData.ConvertToAUTF8String(_retval);
}
/* string getAsString (); */
NS_IMETHODIMP XPCVariant::GetAsString(char** _retval)
{
return nsVariant::ConvertToString(mData, _retval);
return mData.ConvertToString(_retval);
}
/* wstring getAsWString (); */
NS_IMETHODIMP XPCVariant::GetAsWString(char16_t** _retval)
{
return nsVariant::ConvertToWString(mData, _retval);
return mData.ConvertToWString(_retval);
}
/* nsISupports getAsISupports (); */
NS_IMETHODIMP XPCVariant::GetAsISupports(nsISupports** _retval)
{
return nsVariant::ConvertToISupports(mData, _retval);
return mData.ConvertToISupports(_retval);
}
/* void getAsInterface (out nsIIDPtr iid, [iid_is (iid), retval] out nsQIResult iface); */
NS_IMETHODIMP XPCVariant::GetAsInterface(nsIID * *iid, void * *iface)
NS_IMETHODIMP XPCVariant::GetAsInterface(nsIID** iid, void** iface)
{
return nsVariant::ConvertToInterface(mData, iid, iface);
return mData.ConvertToInterface(iid, iface);
}
/* [notxpcom] nsresult getAsArray (out uint16_t type, out nsIID iid, out uint32_t count, out voidPtr ptr); */
NS_IMETHODIMP_(nsresult) XPCVariant::GetAsArray(uint16_t* type, nsIID* iid, uint32_t* count, void * *ptr)
{
return nsVariant::ConvertToArray(mData, type, iid, count, ptr);
return mData.ConvertToArray(type, iid, count, ptr);
}
/* void getAsStringWithSize (out uint32_t size, [size_is (size), retval] out string str); */
NS_IMETHODIMP XPCVariant::GetAsStringWithSize(uint32_t* size, char** str)
{
return nsVariant::ConvertToStringWithSize(mData, size, str);
return mData.ConvertToStringWithSize(size, str);
}
/* void getAsWStringWithSize (out uint32_t size, [size_is (size), retval] out wstring str); */
NS_IMETHODIMP XPCVariant::GetAsWStringWithSize(uint32_t* size, char16_t** str)
{
return nsVariant::ConvertToWStringWithSize(mData, size, str);
return mData.ConvertToWStringWithSize(size, str);
}

Просмотреть файл

@ -1736,6 +1736,12 @@ PresShell::Initialize(nscoord aWidth, nscoord aHeight)
}
}
// If we get here and painting is not suppressed, then we can paint anytime
// and we should fire the before-first-paint notification
if (!mPaintingSuppressed) {
ScheduleBeforeFirstPaint();
}
if (root && root->IsXULElement()) {
mozilla::Telemetry::AccumulateTimeDelta(Telemetry::XUL_INITIAL_FRAME_CONSTRUCTION,
timerStart);
@ -3773,6 +3779,17 @@ PresShell::CaptureHistoryState(nsILayoutHistoryState** aState)
return NS_OK;
}
void
PresShell::ScheduleBeforeFirstPaint()
{
if (!mDocument->IsResourceDoc()) {
// Notify observers that a new page is about to be drawn. Execute this
// as soon as it is safe to run JS, which is guaranteed to be before we
// go back to the event loop and actually draw the page.
nsContentUtils::AddScriptRunner(new nsBeforeFirstPaintDispatcher(mDocument));
}
}
void
PresShell::UnsuppressAndInvalidate()
{
@ -3784,12 +3801,7 @@ PresShell::UnsuppressAndInvalidate()
return;
}
if (!mDocument->IsResourceDoc()) {
// Notify observers that a new page is about to be drawn. Execute this
// as soon as it is safe to run JS, which is guaranteed to be before we
// go back to the event loop and actually draw the page.
nsContentUtils::AddScriptRunner(new nsBeforeFirstPaintDispatcher(mDocument));
}
ScheduleBeforeFirstPaint();
mPaintingSuppressed = false;
nsIFrame* rootFrame = mFrameConstructor->GetRootFrame();

Просмотреть файл

@ -413,6 +413,7 @@ protected:
void HandlePostedReflowCallbacks(bool aInterruptible);
void CancelPostedReflowCallbacks();
void ScheduleBeforeFirstPaint();
void UnsuppressAndInvalidate();
void WillCauseReflow() {

Просмотреть файл

@ -293,13 +293,12 @@ RenderFrameParent::RenderFrameParent(nsFrameLoader* aFrameLoader,
, mBackgroundColor(gfxRGBA(1, 1, 1))
, mAsyncPanZoomEnabled(false)
{
*aId = 0;
*aSuccess = false;
if (!mFrameLoader) {
return;
}
*aId = 0;
nsRefPtr<LayerManager> lm = GetFrom(mFrameLoader);
mAsyncPanZoomEnabled = lm && lm->AsyncPanZoomEnabled();

Просмотреть файл

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg">
<style>
text { fill: url(#green); }
</style>
<linearGradient id="green">
<stop stop-color="green"/>
</linearGradient>
<text x="10" y="20">This text must be green.</text>
</svg>

После

Ширина:  |  Высота:  |  Размер: 236 B

Просмотреть файл

@ -0,0 +1,23 @@
<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait">
<style>
g { fill: url(#red); }
g.x { fill: url(#green); }
</style>
<linearGradient id="red">
<stop stop-color="red"/>
</linearGradient>
<linearGradient id="green">
<stop stop-color="green"/>
</linearGradient>
<g>
<text x="10" y="20">This text must be green.</text>
</g>
<script>
function run() {
var g = document.querySelector("g");
g.setAttribute("class", "x");
document.documentElement.removeAttribute("class");
}
document.addEventListener("MozReftestInvalidate", run, false);
</script>
</svg>

После

Ширина:  |  Высота:  |  Размер: 628 B

Просмотреть файл

@ -572,8 +572,18 @@ nsSVGEffects::GetPaintServer(nsIFrame *aTargetFrame, const nsStyleSVGPaint *aPai
if (aPaint->mType != eStyleSVGPaintType_Server)
return nullptr;
nsIFrame *frame = aTargetFrame->GetContent()->IsNodeOfType(nsINode::eTEXT) ?
aTargetFrame->GetParent() : aTargetFrame;
// If we're looking at a frame within SVG text, then we need to look up
// to find the right frame to get the painting property off. We should at
// least look up past a text frame, and if the text frame's parent is the
// anonymous block frame, then we look up to its parent (the SVGTextFrame).
nsIFrame* frame = aTargetFrame;
if (frame->GetContent()->IsNodeOfType(nsINode::eTEXT)) {
frame = frame->GetParent();
nsIFrame* grandparent = frame->GetParent();
if (grandparent && grandparent->GetType() == nsGkAtoms::svgTextFrame) {
frame = grandparent;
}
}
nsSVGPaintingProperty *property =
nsSVGEffects::GetPaintingProperty(aPaint->mPaint.mPaintServer, frame, aType);
if (!property)

Просмотреть файл

@ -118,7 +118,7 @@ function load() {
req.open('GET', gParams.logurl, true);
req.send();
}
window.addEventListener('keypress', maybe_load_image, false);
window.addEventListener('keypress', handle_keyboard_shortcut, false);
ID("image1").addEventListener('error', image_load_error, false);
ID("image2").addEventListener('error', image_load_error, false);
}
@ -390,7 +390,7 @@ function show_image(i) {
}
}
function maybe_load_image(event) {
function handle_keyboard_shortcut(event) {
switch (event.charCode) {
case 49: // "1" key
document.getElementById("radio1").checked = true;
@ -400,6 +400,32 @@ function maybe_load_image(event) {
document.getElementById("radio2").checked = true;
show_image(2);
break;
case 100: // "d" key
document.getElementById("differences").click();
break;
case 112: // "p" key
shift_images(-1);
break;
case 110: // "n" key
shift_images(1);
break;
}
}
function shift_images(dir) {
var activeItem = document.querySelector(".activeitem");
if (!activeItem) {
return;
}
for (var elm = activeItem; elm; elm = elm.parentElement) {
if (elm.tagName != "tr") {
continue;
}
elm = dir > 0 ? elm.nextElementSibling : elm.previousElementSibling;
if (elm) {
elm.getElementsByTagName("a")[0].click();
}
return;
}
}
@ -546,7 +572,7 @@ function show_pixelinfo(x, y, pix1rgb, pix1hex, pix2rgb, pix2hex) {
<form id="imgcontrols">
<input id="radio1" type="radio" name="which" value="0" onchange="show_image(1)" checked="checked" /><label id="label1" title="1" for="radio1">Image 1</label>
<input id="radio2" type="radio" name="which" value="1" onchange="show_image(2)" /><label id="label2" title="2" for="radio2">Image 2</label>
<label><input type="checkbox" onchange="show_differences(this)" />Circle differences</label>
<label><input id="differences" type="checkbox" onchange="show_differences(this)" />Circle differences</label>
</form>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="800" height="1000" id="svg">
<defs>

Просмотреть файл

@ -548,6 +548,7 @@ pref("apz.fling_stopped_threshold", "0.01");
pref("apz.max_velocity_inches_per_ms", "-1.0");
pref("apz.max_velocity_queue_size", 5);
pref("apz.min_skate_speed", "1.0");
pref("apz.minimap.enabled", false);
pref("apz.num_paint_duration_samples", 3);
pref("apz.overscroll.enabled", false);
pref("apz.overscroll.min_pan_distance_ratio", "1.0");
@ -1697,6 +1698,7 @@ pref("network.predictor.preconnect-min-confidence", 90);
pref("network.predictor.preresolve-min-confidence", 60);
pref("network.predictor.redirect-likely-confidence", 75);
pref("network.predictor.max-resources-per-entry", 100);
pref("network.predictor.max-uri-length", 500);
pref("network.predictor.cleaned-up", false);
// The following prefs pertain to the negotiate-auth extension (see bug 17578),

Просмотреть файл

@ -117,6 +117,12 @@ const char PREDICTOR_MAX_RESOURCES_PREF[] =
"network.predictor.max-resources-per-entry";
const uint32_t PREDICTOR_MAX_RESOURCES_DEFAULT = 100;
// This is selected in concert with max-resources-per-entry to keep memory usage
// low-ish. The default of the combo of the two is ~50k
const char PREDICTOR_MAX_URI_LENGTH_PREF[] =
"network.predictor.max-uri-length";
const uint32_t PREDICTOR_MAX_URI_LENGTH_DEFAULT = 500;
const char PREDICTOR_CLEANED_UP_PREF[] = "network.predictor.cleaned-up";
// All these time values are in sec
@ -314,6 +320,7 @@ Predictor::Predictor()
,mRedirectLikelyConfidence(REDIRECT_LIKELY_DEFAULT)
,mMaxResourcesPerEntry(PREDICTOR_MAX_RESOURCES_DEFAULT)
,mStartupCount(1)
,mMaxURILength(PREDICTOR_MAX_URI_LENGTH_DEFAULT)
{
gPredictorLog = PR_NewLogModule("NetworkPredictor");
@ -402,6 +409,9 @@ Predictor::InstallObserver()
Preferences::AddBoolVarCache(&mCleanedUp, PREDICTOR_CLEANED_UP_PREF, false);
Preferences::AddUintVarCache(&mMaxURILength, PREDICTOR_MAX_URI_LENGTH_PREF,
PREDICTOR_MAX_URI_LENGTH_DEFAULT);
if (!mCleanedUp) {
mCleanupTimer = do_CreateInstance("@mozilla.org/timer;1");
mCleanupTimer->Init(this, 60 * 1000, nsITimer::TYPE_ONE_SHOT);
@ -511,15 +521,24 @@ class NuwaMarkPredictorThreadRunner : public nsRunnable
// Predictor::nsICacheEntryMetaDataVisitor
#define SEEN_META_DATA "predictor::seen"
#define RESOURCE_META_DATA "predictor::resource-count"
#define META_DATA_PREFIX "predictor::"
static bool
IsURIMetadataElement(const char *key)
{
return StringBeginsWith(nsDependentCString(key),
NS_LITERAL_CSTRING(META_DATA_PREFIX)) &&
!NS_LITERAL_CSTRING(SEEN_META_DATA).Equals(key) &&
!NS_LITERAL_CSTRING(RESOURCE_META_DATA).Equals(key);
}
nsresult
Predictor::OnMetaDataElement(const char *asciiKey, const char *asciiValue)
{
MOZ_ASSERT(NS_IsMainThread());
if (!StringBeginsWith(nsDependentCString(asciiKey),
NS_LITERAL_CSTRING(META_DATA_PREFIX)) ||
NS_LITERAL_CSTRING(SEEN_META_DATA).Equals(asciiKey)) {
if (!IsURIMetadataElement(asciiKey)) {
// This isn't a bit of metadata we care about
return NS_OK;
}
@ -1432,7 +1451,11 @@ Predictor::LearnInternal(PredictorLearnReason reason, nsICacheEntry *entry,
// This is an origin-only entry that we haven't seen before. Let's mark it
// as seen.
PREDICTOR_LOG((" marking new origin entry as seen"));
entry->SetMetaDataElement(SEEN_META_DATA, "1");
nsresult rv = entry->SetMetaDataElement(SEEN_META_DATA, "1");
if (NS_FAILED(rv)) {
PREDICTOR_LOG((" failed to mark origin entry seen"));
return;
}
// Need to ensure someone else can get to the entry if necessary
entry->MetaDataReady();
@ -1470,21 +1493,40 @@ Predictor::SpaceCleaner::OnMetaDataElement(const char *key, const char *value)
{
MOZ_ASSERT(NS_IsMainThread());
if (!StringBeginsWith(nsDependentCString(key),
NS_LITERAL_CSTRING(META_DATA_PREFIX)) ||
NS_LITERAL_CSTRING(SEEN_META_DATA).Equals(key)) {
if (!IsURIMetadataElement(key)) {
// This isn't a bit of metadata we care about
return NS_OK;
}
nsCOMPtr<nsIURI> sanityCheck;
nsCOMPtr<nsIURI> parsedURI;
uint32_t hitCount, lastHit, flags;
bool ok = mPredictor->ParseMetaDataEntry(key, value,
getter_AddRefs(sanityCheck),
getter_AddRefs(parsedURI),
hitCount, lastHit, flags);
if (!ok || !mKeyToDelete || lastHit < mLRUStamp) {
mKeyToDelete = key;
if (!ok) {
// Couldn't parse this one, just get rid of it
nsCString nsKey;
nsKey.AssignASCII(key);
mLongKeysToDelete.AppendElement(nsKey);
return NS_OK;
}
nsCString uri;
nsresult rv = parsedURI->GetAsciiSpec(uri);
uint32_t uriLength = uri.Length();
if (ok && NS_SUCCEEDED(rv) &&
uriLength > mPredictor->mMaxURILength) {
// Default to getting rid of URIs that are too long and were put in before
// we had our limit on URI length, in order to free up some space.
nsCString nsKey;
nsKey.AssignASCII(key);
mLongKeysToDelete.AppendElement(nsKey);
return NS_OK;
}
if (!ok || !mLRUKeyToDelete || lastHit < mLRUStamp) {
mLRUKeyToDelete = key;
mLRUStamp = ok ? lastHit : 0;
}
@ -1496,7 +1538,13 @@ Predictor::SpaceCleaner::Finalize(nsICacheEntry *entry)
{
MOZ_ASSERT(NS_IsMainThread());
entry->SetMetaDataElement(mKeyToDelete, nullptr);
if (mLRUKeyToDelete) {
entry->SetMetaDataElement(mLRUKeyToDelete, nullptr);
}
for (size_t i = 0; i < mLongKeysToDelete.Length(); ++i) {
entry->SetMetaDataElement(mLongKeysToDelete[i].BeginReading(), nullptr);
}
}
// Called when a subresource has been hit from a top-level load. Uses the two
@ -1521,6 +1569,12 @@ Predictor::LearnForSubresource(nsICacheEntry *entry, nsIURI *targetURI)
nsCString uri;
targetURI->GetAsciiSpec(uri);
key.Append(uri);
if (uri.Length() > mMaxURILength) {
// We do this to conserve space/prevent OOMs
PREDICTOR_LOG((" uri too long!"));
entry->SetMetaDataElement(key.BeginReading(), nullptr);
return;
}
nsCString value;
rv = entry->GetMetaDataElement(key.BeginReading(), getter_Copies(value));
@ -1530,16 +1584,13 @@ Predictor::LearnForSubresource(nsICacheEntry *entry, nsIURI *targetURI)
!ParseMetaDataEntry(nullptr, value.BeginReading(),
nullptr, hitCount, lastHit, flags));
int32_t resourceCount = 0;
if (isNewResource) {
// This is a new addition
PREDICTOR_LOG((" new resource"));
int32_t resourceCount;
nsCString s;
rv = entry->GetMetaDataElement("predictor::resource-count",
getter_Copies(s));
if (NS_FAILED(rv)) {
resourceCount = 0;
} else {
rv = entry->GetMetaDataElement(RESOURCE_META_DATA, getter_Copies(s));
if (NS_SUCCEEDED(rv)) {
resourceCount = atoi(s.BeginReading());
}
if (resourceCount >= mMaxResourcesPerEntry) {
@ -1552,7 +1603,11 @@ Predictor::LearnForSubresource(nsICacheEntry *entry, nsIURI *targetURI)
}
nsAutoCString count;
count.AppendInt(resourceCount);
entry->SetMetaDataElement("predictor::resource-count", count.BeginReading());
rv = entry->SetMetaDataElement(RESOURCE_META_DATA, count.BeginReading());
if (NS_FAILED(rv)) {
PREDICTOR_LOG((" failed to update resource count"));
return;
}
hitCount = 1;
} else {
PREDICTOR_LOG((" existing resource"));
@ -1569,7 +1624,20 @@ Predictor::LearnForSubresource(nsICacheEntry *entry, nsIURI *targetURI)
// things later on
newValue.AppendLiteral(",");
newValue.AppendInt(0);
entry->SetMetaDataElement(key.BeginReading(), newValue.BeginReading());
rv = entry->SetMetaDataElement(key.BeginReading(), newValue.BeginReading());
PREDICTOR_LOG((" SetMetaDataElement -> 0x%08X", rv));
if (NS_FAILED(rv) && isNewResource) {
// Roll back the increment to the resource count we made above.
PREDICTOR_LOG((" rolling back resource count update"));
--resourceCount;
if (resourceCount == 0) {
entry->SetMetaDataElement(RESOURCE_META_DATA, nullptr);
} else {
nsAutoCString count;
count.AppendInt(resourceCount);
entry->SetMetaDataElement(RESOURCE_META_DATA, count.BeginReading());
}
}
}
// This is called when a top-level loaded ended up redirecting to a different

Просмотреть файл

@ -146,7 +146,7 @@ private:
explicit SpaceCleaner(Predictor *predictor)
:mLRUStamp(0)
,mKeyToDelete(nullptr)
,mLRUKeyToDelete(nullptr)
,mPredictor(predictor)
{ }
@ -155,7 +155,8 @@ private:
private:
virtual ~SpaceCleaner() { }
uint32_t mLRUStamp;
const char *mKeyToDelete;
const char *mLRUKeyToDelete;
nsTArray<nsCString> mLongKeysToDelete;
nsRefPtr<Predictor> mPredictor;
};
@ -354,6 +355,8 @@ private:
uint32_t mLastStartupTime;
int32_t mStartupCount;
uint32_t mMaxURILength;
nsCOMPtr<nsIDNSService> mDnsService;
nsRefPtr<DNSListener> mDNSListener;

Просмотреть файл

@ -2091,7 +2091,9 @@ HttpBaseChannel::ShouldIntercept()
nsresult rv = controller->ShouldPrepareForIntercept(mURI,
IsNavigation(),
&shouldIntercept);
NS_ENSURE_SUCCESS(rv, false);
if (NS_FAILED(rv)) {
return false;
}
}
return shouldIntercept;
}

Просмотреть файл

@ -6,5 +6,5 @@ tasks in automated testing, such as extracting files or recursively removing
directories.
.. automodule:: mozfile
:members: extract, extract_tarball, extract_zip, remove
:members: extract, extract_tarball, extract_zip, move, remove

Просмотреть файл

@ -20,6 +20,7 @@ __all__ = ['extract_tarball',
'extract',
'is_url',
'load',
'move',
'remove',
'rmtree',
'tree',
@ -134,6 +135,35 @@ def rmtree(dir):
return remove(dir)
def _call_windows_retry(func, args=(), retry_max=5, retry_delay=0.5):
"""
It's possible to see spurious errors on Windows due to various things
keeping a handle to the directory open (explorer, virus scanners, etc)
So we try a few times if it fails with a known error.
"""
retry_count = 0
while True:
try:
func(*args)
except OSError, e:
# Error codes are defined in:
# http://docs.python.org/2/library/errno.html#module-errno
if e.errno not in (errno.EACCES, errno.ENOTEMPTY):
raise
if retry_count == retry_max:
raise
retry_count += 1
print '%s() failed for "%s". Reason: %s (%s). Retrying...' % \
(func.__name__, args, e.strerror, e.errno)
time.sleep(retry_delay)
else:
# If no exception has been thrown it should be done
break
def remove(path):
"""Removes the specified file, link, or directory tree.
@ -154,37 +184,13 @@ def remove(path):
import shutil
def _call_with_windows_retry(func, args=(), retry_max=5, retry_delay=0.5):
"""
It's possible to see spurious errors on Windows due to various things
keeping a handle to the directory open (explorer, virus scanners, etc)
So we try a few times if it fails with a known error.
"""
retry_count = 0
while True:
try:
func(*args)
except OSError, e:
# The file or directory to be removed doesn't exist anymore
if e.errno == errno.ENOENT:
break
# Error codes are defined in:
# http://docs.python.org/2/library/errno.html#module-errno
if e.errno not in [errno.EACCES, errno.ENOTEMPTY]:
raise
if retry_count == retry_max:
raise
retry_count += 1
print '%s() failed for "%s". Reason: %s (%s). Retrying...' % \
(func.__name__, args, e.strerror, e.errno)
time.sleep(retry_delay)
else:
# If no exception has been thrown it should be done
break
def _call_with_windows_retry(*args, **kwargs):
try:
_call_windows_retry(*args, **kwargs)
except OSError, e:
# The file or directory to be removed doesn't exist anymore
if e.errno != errno.ENOENT:
raise
def _update_permissions(path):
"""Sets specified pemissions depending on filetype"""
@ -224,6 +230,18 @@ def remove(path):
_call_with_windows_retry(shutil.rmtree, (path,))
def move(src, dst):
"""
Move a file or directory path.
This is a replacement for shutil.move that works better under windows,
retrying operations on some known errors due to various things keeping
a handle on file paths.
"""
import shutil
_call_windows_retry(shutil.move, (src, dst))
def depth(directory):
"""returns the integer depth of a directory or path relative to '/' """

Просмотреть файл

@ -5,7 +5,7 @@
from setuptools import setup
PACKAGE_NAME = 'mozfile'
PACKAGE_VERSION = '1.1'
PACKAGE_VERSION = '1.2'
setup(name=PACKAGE_NAME,
version=PACKAGE_VERSION,

Просмотреть файл

@ -1,6 +1,6 @@
[test_extract.py]
[test_load.py]
[test_remove.py]
[test_move_remove.py]
[test_tempdir.py]
[test_tempfile.py]
[test_url.py]

Просмотреть файл

@ -7,6 +7,7 @@ import threading
import time
import unittest
import errno
from contextlib import contextmanager
import mozfile
import mozinfo
@ -27,12 +28,14 @@ class FileOpenCloseThread(threading.Thread):
"""Helper thread for asynchronous file handling"""
def __init__(self, path, delay, delete=False):
threading.Thread.__init__(self)
self.file_opened = threading.Event()
self.delay = delay
self.path = path
self.delete = delete
def run(self):
with open(self.path):
self.file_opened.set()
time.sleep(self.delay)
if self.delete:
try:
@ -41,6 +44,17 @@ class FileOpenCloseThread(threading.Thread):
pass
@contextmanager
def wait_file_opened_in_thread(*args, **kwargs):
thread = FileOpenCloseThread(*args, **kwargs)
thread.start()
thread.file_opened.wait()
try:
yield thread
finally:
thread.join()
class MozfileRemoveTestCase(unittest.TestCase):
"""Test our ability to remove directories and files"""
@ -90,13 +104,10 @@ class MozfileRemoveTestCase(unittest.TestCase):
"""Test removing a file in use with retry"""
filepath = os.path.join(self.tempdir, *stubs.files[1])
thread = FileOpenCloseThread(filepath, 1)
thread.start()
# Wait a bit so we can be sure the file has been opened
time.sleep(.5)
mozfile.remove(filepath)
thread.join()
with wait_file_opened_in_thread(filepath, 0.2):
# on windows first attempt will fail,
# and it will be retried until the thread leave the handle
mozfile.remove(filepath)
# Check deletion was successful
self.assertFalse(os.path.exists(filepath))
@ -105,14 +116,10 @@ class MozfileRemoveTestCase(unittest.TestCase):
"""Test removing a meanwhile removed file with retry"""
filepath = os.path.join(self.tempdir, *stubs.files[1])
thread = FileOpenCloseThread(filepath, .8, True)
thread.start()
# Wait a bit so we can be sure the file has been opened and gets deleted
# while remove() waits for the next retry
time.sleep(.5)
mozfile.remove(filepath)
thread.join()
with wait_file_opened_in_thread(filepath, 0.2, True):
# on windows first attempt will fail, and before
# the retry the opened file will be deleted in the thread
mozfile.remove(filepath)
# Check deletion was successful
self.assertFalse(os.path.exists(filepath))
@ -192,5 +199,32 @@ class MozfileRemoveTestCase(unittest.TestCase):
self.fail("removing non existing path must not raise error")
raise
class MozFileMoveTestCase(unittest.TestCase):
def setUp(self):
# Generate a stub
self.tempdir = stubs.create_stub()
self.addCleanup(mozfile.rmtree, self.tempdir)
def test_move_file(self):
file_path = os.path.join(self.tempdir, *stubs.files[1])
moved_path = file_path + '.moved'
self.assertTrue(os.path.isfile(file_path))
self.assertFalse(os.path.exists(moved_path))
mozfile.move(file_path, moved_path)
self.assertFalse(os.path.exists(file_path))
self.assertTrue(os.path.isfile(moved_path))
def test_move_file_with_retry(self):
file_path = os.path.join(self.tempdir, *stubs.files[1])
moved_path = file_path + '.moved'
with wait_file_opened_in_thread(file_path, 0.2):
# first move attempt should fail on windows and be retried
mozfile.move(file_path, moved_path)
self.assertFalse(os.path.exists(file_path))
self.assertTrue(os.path.isfile(moved_path))
if __name__ == '__main__':
unittest.main()

Просмотреть файл

@ -36,7 +36,7 @@ config = {
'c:\\mozilla-build\\buildbotve\\scripts\\buildbot'
],
'puppet_location': [
sys.executable,
'c:\\mozilla-build\\buildbot-0.8.4-pre-moz6\\Scripts\\python.exe',
'c:\\mozilla-build\\buildbot-0.8.4-pre-moz6\\scripts\\buildbot'
]
},

Просмотреть файл

@ -36,7 +36,7 @@ config = {
'c:\\mozilla-build\\buildbotve\\scripts\\buildbot'
],
'puppet_location': [
sys.executable,
'c:\\mozilla-build\\buildbot-0.8.4-pre-moz6\\Scripts\\python.exe',
'c:\\mozilla-build\\buildbot-0.8.4-pre-moz6\\scripts\\buildbot'
]
},

Просмотреть файл

@ -38,9 +38,7 @@ config = {
'tools_dir': "/tools",
'compiler_manifest': "build/gcc.manifest",
'b2g_compiler_manifest': "build/gcc-b2g.manifest",
'compiler_setup': "setup.sh.gcc",
'sixgill_manifest': "build/sixgill.manifest",
'sixgill_setup': "setup.sh.sixgill",
# Mock.
"mock_packages": [

Просмотреть файл

@ -26,7 +26,6 @@ config = {
"tooltool_config": {
"manifest": "mobile/android/config/tooltool-manifests/android/releng.manifest",
"output_dir": "%(abs_work_dir)s/" + MOZILLA_DIR,
"bootstrap_cmd": ["bash", "-xe", "setup.sh"],
},
"exes": {
'tooltool.py': '/tools/tooltool.py',

Просмотреть файл

@ -26,7 +26,6 @@ config = {
"tooltool_config": {
"manifest": "mobile/android/config/tooltool-manifests/android/releng.manifest",
"output_dir": "%(abs_work_dir)s/" + MOZILLA_DIR,
"bootstrap_cmd": ["bash", "-xe", "setup.sh"],
},
"exes": {
'tooltool.py': '/tools/tooltool.py',

Просмотреть файл

@ -26,7 +26,6 @@ config = {
"tooltool_config": {
"manifest": "mobile/android/config/tooltool-manifests/android/releng.manifest",
"output_dir": "%(abs_work_dir)s/" + MOZILLA_DIR,
"bootstrap_cmd": ["bash", "-xe", "setup.sh"],
},
"exes": {
'tooltool.py': '/tools/tooltool.py',

Просмотреть файл

@ -355,9 +355,7 @@ class B2GBuild(LocalesMixin, PurgeMixin,
config_dir = os.path.join(dirs['gecko_src'], 'b2g', 'config',
self.config.get('b2g_config_dir', self.config['target']))
manifest = os.path.abspath(os.path.join(config_dir, gecko_config['tooltool_manifest']))
self.tooltool_fetch(manifest=manifest,
bootstrap_cmd=gecko_config.get('tooltool_bootstrap_cmd'),
output_dir=dirs['work_dir'])
self.tooltool_fetch(manifest=manifest, output_dir=dirs['work_dir'])
def unpack_blobs(self):
dirs = self.query_abs_dirs()

Просмотреть файл

@ -272,14 +272,14 @@ class B2GHazardBuild(PurgeMixin, B2GBuildBaseScript):
def get_blobs(self):
dirs = self.query_abs_dirs()
self.tooltool_fetch(self.query_compiler_manifest(), "sh " + self.config['compiler_setup'],
dirs['abs_work_dir'])
self.tooltool_fetch(self.query_sixgill_manifest(), "sh " + self.config['sixgill_setup'],
dirs['abs_work_dir'])
self.tooltool_fetch(self.query_compiler_manifest(),
output_dir=dirs['abs_work_dir'])
self.tooltool_fetch(self.query_sixgill_manifest(),
output_dir=dirs['abs_work_dir'])
if not os.path.exists(dirs['target_compiler_base']):
self.mkdir_p(dirs['target_compiler_base'])
self.tooltool_fetch(self.query_b2g_compiler_manifest(), "sh " + self.config['compiler_setup'],
dirs['target_compiler_base'])
self.tooltool_fetch(self.query_b2g_compiler_manifest(),
output_dir=dirs['target_compiler_base'])
def clobber_shell(self):
dirs = self.query_abs_dirs()

Просмотреть файл

@ -363,7 +363,7 @@ class MobileSingleLocale(MockMixin, LocalesMixin, ReleaseMixin,
if self.config.get("tooltool_config"):
self.tooltool_fetch(
self.config['tooltool_config']['manifest'],
bootstrap_cmd=self.config['tooltool_config']['bootstrap_cmd'],
bootstrap_cmd=self.config['tooltool_config'].get('bootstrap_cmd'),
output_dir=self.config['tooltool_config']['output_dir'] % self.query_abs_dirs(),
)
self._setup_configure()

Просмотреть файл

@ -387,10 +387,8 @@ class SpidermonkeyBuild(MockMixin,
work_dir = self.query_abs_dirs()['abs_work_dir']
if not os.path.exists(work_dir):
self.mkdir_p(work_dir)
self.tooltool_fetch(self.query_compiler_manifest(), "sh " + self.config['compiler_setup'],
work_dir)
self.tooltool_fetch(self.query_sixgill_manifest(), "sh " + self.config['sixgill_setup'],
work_dir)
self.tooltool_fetch(self.query_compiler_manifest(), output_dir=work_dir)
self.tooltool_fetch(self.query_sixgill_manifest(), output_dir=work_dir)
def clobber_shell(self):
self.analysis.clobber_shell(self)

Просмотреть файл

@ -8087,14 +8087,14 @@
},
"VIDEO_ADOBE_GMP_DISAPPEARED": {
"alert_emails": ["cpearce@mozilla.com"],
"expires_in_version": "42",
"expires_in_version": "50",
"kind": "flag",
"description": "Whether or not the Adobe EME GMP was expected to be resident on disk but mysteriously isn't.",
"releaseChannelCollection": "opt-out"
},
"VIDEO_ADOBE_GMP_MISSING_FILES": {
"alert_emails": ["cpearce@mozilla.com"],
"expires_in_version": "42",
"expires_in_version": "50",
"kind": "enumerated",
"n_values" : 8,
"description": "Adobe EME GMP files missing (0=none, or sum of: 1=library, 2=info, 4=voucher)",
@ -8102,14 +8102,14 @@
},
"VIDEO_OPENH264_GMP_DISAPPEARED": {
"alert_emails": ["cpearce@mozilla.com", "rjesup@mozilla.com"],
"expires_in_version": "42",
"expires_in_version": "50",
"kind": "flag",
"description": "Whether or not the OpenH264 GMP was expected to be resident on disk but mysteriously isn't.",
"releaseChannelCollection": "opt-out"
},
"VIDEO_OPENH264_GMP_MISSING_FILES": {
"alert_emails": ["cpearce@mozilla.com", "rjesup@mozilla.com"],
"expires_in_version": "42",
"expires_in_version": "50",
"kind": "enumerated",
"n_values" : 4,
"description": "OpenH264 GMP files missing (0=none, or sum of: 1=library, 2=info)",
@ -8542,5 +8542,18 @@
"n_values": 20,
"releaseChannelCollection": "opt-out",
"description": "Reports why a graphics sanity test was run. 0=First Run, 1=App Updated, 2=Device Change, 3=Driver Change."
},
"PERMISSIONS_REMIGRATION_COMPARISON": {
"alert_emails": ["michael@thelayzells.com"],
"expires_in_version": "44",
"kind": "enumerated",
"n_values": 10,
"description": "Reports a comparison between row count of original and re-migration of the v7 permissions DB. 0=New == 0, 1=New < Old, 2=New == Old, 3=New > Old"
},
"PERMISSIONS_MIGRATION_7_ERROR": {
"alert_emails": ["michael@thelayzells.com"],
"expires_in_version": "44",
"kind": "boolean",
"description": "Was there an error while performing the v7 permissions DB migration?"
}
}

Просмотреть файл

@ -3716,10 +3716,20 @@ nsWindow::EndRemoteDrawing()
void
nsWindow::UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries)
{
nsIntRegion clearRegion;
if (!HasGlass() || !nsUXThemeData::CheckForCompositor()) {
nsRefPtr<LayerManager> layerManager = GetLayerManager();
if (!layerManager) {
return;
}
nsIntRegion clearRegion;
if (!HasGlass() || !nsUXThemeData::CheckForCompositor()) {
// Make sure and clear old regions we've set previously. Note HasGlass can be false
// for glass desktops if the window we are rendering to doesn't make use of glass
// (e.g. fullscreen browsing).
layerManager->SetRegionToClear(clearRegion);
return;
}
// On Win10, force show the top border:
if (IsWin10OrLater() && mCustomNonClient && mSizeMode == nsSizeMode_Normal) {
RECT rect;
@ -3728,10 +3738,10 @@ nsWindow::UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries)
double borderSize = RoundDown(GetDefaultScale().scale);
clearRegion.Or(clearRegion, nsIntRect(0, 0, rect.right - rect.left, borderSize));
}
if (!IsWin10OrLater()) {
for (size_t i = 0; i < aThemeGeometries.Length(); i++) {
if (aThemeGeometries[i].mType == nsNativeThemeWin::eThemeGeometryTypeWindowButtons)
{
if (aThemeGeometries[i].mType == nsNativeThemeWin::eThemeGeometryTypeWindowButtons) {
nsIntRect bounds = aThemeGeometries[i].mRect;
clearRegion.Or(clearRegion, nsIntRect(bounds.X(), bounds.Y(), bounds.Width(), bounds.Height() - 2.0));
clearRegion.Or(clearRegion, nsIntRect(bounds.X() + 1.0, bounds.YMost() - 2.0, bounds.Width() - 1.0, 1.0));
@ -3740,10 +3750,7 @@ nsWindow::UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries)
}
}
nsRefPtr<LayerManager> layerManager = GetLayerManager();
if (layerManager) {
layerManager->SetRegionToClear(clearRegion);
}
layerManager->SetRegionToClear(clearRegion);
}
uint32_t

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -4,8 +4,6 @@
* 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/. */
/* The long avoided variant support for xpcom. */
#ifndef nsVariant_h
#define nsVariant_h
@ -25,13 +23,102 @@ class nsCycleCollectionTraversalCallback;
#define PromiseFlatUTF8String PromiseFlatCString
/**
* nsDiscriminatedUnion is a type that nsIVariant implementors *may* use
* to hold underlying data. It has no methods. So, its use requires no linkage
* to the xpcom module.
* nsDiscriminatedUnion is a class that nsIVariant implementors can use
* to hold the underlying data.
*/
struct nsDiscriminatedUnion
class nsDiscriminatedUnion
{
public:
nsDiscriminatedUnion() : mType(nsIDataType::VTYPE_EMPTY) {}
nsDiscriminatedUnion(const nsDiscriminatedUnion&) = delete;
nsDiscriminatedUnion(nsDiscriminatedUnion&&) = delete;
~nsDiscriminatedUnion() { Cleanup(); }
nsDiscriminatedUnion& operator=(const nsDiscriminatedUnion&) = delete;
nsDiscriminatedUnion& operator=(nsDiscriminatedUnion&&) = delete;
void Cleanup();
uint16_t GetType() const { return mType; }
nsresult ConvertToInt8(uint8_t* aResult) const;
nsresult ConvertToInt16(int16_t* aResult) const;
nsresult ConvertToInt32(int32_t* aResult) const;
nsresult ConvertToInt64(int64_t* aResult) const;
nsresult ConvertToUint8(uint8_t* aResult) const;
nsresult ConvertToUint16(uint16_t* aResult) const;
nsresult ConvertToUint32(uint32_t* aResult) const;
nsresult ConvertToUint64(uint64_t* aResult) const;
nsresult ConvertToFloat(float* aResult) const;
nsresult ConvertToDouble(double* aResult) const;
nsresult ConvertToBool(bool* aResult) const;
nsresult ConvertToChar(char* aResult) const;
nsresult ConvertToWChar(char16_t* aResult) const;
nsresult ConvertToID(nsID* aResult) const;
nsresult ConvertToAString(nsAString& aResult) const;
nsresult ConvertToAUTF8String(nsAUTF8String& aResult) const;
nsresult ConvertToACString(nsACString& aResult) const;
nsresult ConvertToString(char** aResult) const;
nsresult ConvertToWString(char16_t** aResult) const;
nsresult ConvertToStringWithSize(uint32_t* aSize, char** aStr) const;
nsresult ConvertToWStringWithSize(uint32_t* aSize, char16_t** aStr) const;
nsresult ConvertToISupports(nsISupports** aResult) const;
nsresult ConvertToInterface(nsIID** aIID, void** aInterface) const;
nsresult ConvertToArray(uint16_t* aType, nsIID* aIID,
uint32_t* aCount, void** aPtr) const;
nsresult SetFromVariant(nsIVariant* aValue);
nsresult SetFromInt8(uint8_t aValue);
nsresult SetFromInt16(int16_t aValue);
nsresult SetFromInt32(int32_t aValue);
nsresult SetFromInt64(int64_t aValue);
nsresult SetFromUint8(uint8_t aValue);
nsresult SetFromUint16(uint16_t aValue);
nsresult SetFromUint32(uint32_t aValue);
nsresult SetFromUint64(uint64_t aValue);
nsresult SetFromFloat(float aValue);
nsresult SetFromDouble(double aValue);
nsresult SetFromBool(bool aValue);
nsresult SetFromChar(char aValue);
nsresult SetFromWChar(char16_t aValue);
nsresult SetFromID(const nsID& aValue);
nsresult SetFromAString(const nsAString& aValue);
nsresult SetFromDOMString(const nsAString& aValue);
nsresult SetFromAUTF8String(const nsAUTF8String& aValue);
nsresult SetFromACString(const nsACString& aValue);
nsresult SetFromString(const char* aValue);
nsresult SetFromWString(const char16_t* aValue);
nsresult SetFromISupports(nsISupports* aValue);
nsresult SetFromInterface(const nsIID& aIID, nsISupports* aValue);
nsresult SetFromArray(uint16_t aType, const nsIID* aIID, uint32_t aCount,
void* aValue);
nsresult SetFromStringWithSize(uint32_t aSize, const char* aValue);
nsresult SetFromWStringWithSize(uint32_t aSize, const char16_t* aValue);
// Like SetFromWStringWithSize, but leaves the string uninitialized. It does
// does write the null-terminator.
nsresult AllocateWStringWithSize(uint32_t aSize);
nsresult SetToVoid();
nsresult SetToEmpty();
nsresult SetToEmptyArray();
void Traverse(nsCycleCollectionTraversalCallback& aCb) const;
private:
nsresult ToManageableNumber(nsDiscriminatedUnion* aOutData) const;
void FreeArray();
bool String2ID(nsID* aPid) const;
nsresult ToString(nsACString& aOutString) const;
public:
union
{
int8_t mInt8Value;
@ -100,113 +187,8 @@ public:
nsVariant();
static nsresult Initialize(nsDiscriminatedUnion* aData);
static nsresult Cleanup(nsDiscriminatedUnion* aData);
static nsresult ConvertToInt8(const nsDiscriminatedUnion& aData,
uint8_t* aResult);
static nsresult ConvertToInt16(const nsDiscriminatedUnion& aData,
int16_t* aResult);
static nsresult ConvertToInt32(const nsDiscriminatedUnion& aData,
int32_t* aResult);
static nsresult ConvertToInt64(const nsDiscriminatedUnion& aData,
int64_t* aResult);
static nsresult ConvertToUint8(const nsDiscriminatedUnion& aData,
uint8_t* aResult);
static nsresult ConvertToUint16(const nsDiscriminatedUnion& aData,
uint16_t* aResult);
static nsresult ConvertToUint32(const nsDiscriminatedUnion& aData,
uint32_t* aResult);
static nsresult ConvertToUint64(const nsDiscriminatedUnion& aData,
uint64_t* aResult);
static nsresult ConvertToFloat(const nsDiscriminatedUnion& aData,
float* aResult);
static nsresult ConvertToDouble(const nsDiscriminatedUnion& aData,
double* aResult);
static nsresult ConvertToBool(const nsDiscriminatedUnion& aData,
bool* aResult);
static nsresult ConvertToChar(const nsDiscriminatedUnion& aData,
char* aResult);
static nsresult ConvertToWChar(const nsDiscriminatedUnion& aData,
char16_t* aResult);
static nsresult ConvertToID(const nsDiscriminatedUnion& aData,
nsID* aResult);
static nsresult ConvertToAString(const nsDiscriminatedUnion& aData,
nsAString& aResult);
static nsresult ConvertToAUTF8String(const nsDiscriminatedUnion& aData,
nsAUTF8String& aResult);
static nsresult ConvertToACString(const nsDiscriminatedUnion& aData,
nsACString& aResult);
static nsresult ConvertToString(const nsDiscriminatedUnion& aData,
char** aResult);
static nsresult ConvertToWString(const nsDiscriminatedUnion& aData,
char16_t** aResult);
static nsresult ConvertToISupports(const nsDiscriminatedUnion& aData,
nsISupports** aResult);
static nsresult ConvertToInterface(const nsDiscriminatedUnion& aData,
nsIID** aIID, void** aInterface);
static nsresult ConvertToArray(const nsDiscriminatedUnion& aData,
uint16_t* aType, nsIID* aIID,
uint32_t* aCount, void** aPtr);
static nsresult ConvertToStringWithSize(const nsDiscriminatedUnion& aData,
uint32_t* aSize, char** aStr);
static nsresult ConvertToWStringWithSize(const nsDiscriminatedUnion& aData,
uint32_t* aSize, char16_t** aStr);
static nsresult SetFromVariant(nsDiscriminatedUnion* aData,
nsIVariant* aValue);
static nsresult SetFromInt8(nsDiscriminatedUnion* aData, uint8_t aValue);
static nsresult SetFromInt16(nsDiscriminatedUnion* aData, int16_t aValue);
static nsresult SetFromInt32(nsDiscriminatedUnion* aData, int32_t aValue);
static nsresult SetFromInt64(nsDiscriminatedUnion* aData, int64_t aValue);
static nsresult SetFromUint8(nsDiscriminatedUnion* aData, uint8_t aValue);
static nsresult SetFromUint16(nsDiscriminatedUnion* aData, uint16_t aValue);
static nsresult SetFromUint32(nsDiscriminatedUnion* aData, uint32_t aValue);
static nsresult SetFromUint64(nsDiscriminatedUnion* aData, uint64_t aValue);
static nsresult SetFromFloat(nsDiscriminatedUnion* aData, float aValue);
static nsresult SetFromDouble(nsDiscriminatedUnion* aData, double aValue);
static nsresult SetFromBool(nsDiscriminatedUnion* aData, bool aValue);
static nsresult SetFromChar(nsDiscriminatedUnion* aData, char aValue);
static nsresult SetFromWChar(nsDiscriminatedUnion* aData, char16_t aValue);
static nsresult SetFromID(nsDiscriminatedUnion* aData, const nsID& aValue);
static nsresult SetFromAString(nsDiscriminatedUnion* aData,
const nsAString& aValue);
static nsresult SetFromAUTF8String(nsDiscriminatedUnion* aData,
const nsAUTF8String& aValue);
static nsresult SetFromACString(nsDiscriminatedUnion* aData,
const nsACString& aValue);
static nsresult SetFromString(nsDiscriminatedUnion* aData,
const char* aValue);
static nsresult SetFromWString(nsDiscriminatedUnion* aData,
const char16_t* aValue);
static nsresult SetFromISupports(nsDiscriminatedUnion* aData,
nsISupports* aValue);
static nsresult SetFromInterface(nsDiscriminatedUnion* aData,
const nsIID& aIID, nsISupports* aValue);
static nsresult SetFromArray(nsDiscriminatedUnion* aData, uint16_t aType,
const nsIID* aIID, uint32_t aCount,
void* aValue);
static nsresult SetFromStringWithSize(nsDiscriminatedUnion* aData,
uint32_t aSize, const char* aValue);
static nsresult SetFromWStringWithSize(nsDiscriminatedUnion* aData,
uint32_t aSize,
const char16_t* aValue);
// Like SetFromWStringWithSize, but leaves the string uninitialized. It does
// does write the null-terminator.
static nsresult AllocateWStringWithSize(nsDiscriminatedUnion* aData,
uint32_t aSize);
static nsresult SetToVoid(nsDiscriminatedUnion* aData);
static nsresult SetToEmpty(nsDiscriminatedUnion* aData);
static nsresult SetToEmptyArray(nsDiscriminatedUnion* aData);
static void Traverse(const nsDiscriminatedUnion& aData,
nsCycleCollectionTraversalCallback& aCb);
private:
~nsVariant();
~nsVariant() {};
protected:
nsDiscriminatedUnion mData;