зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to fx-team
This commit is contained in:
Коммит
7074581085
2
CLOBBER
2
CLOBBER
|
@ -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
|
||||
}
|
||||
]
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче