зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to fx-team
This commit is contained in:
Коммит
6e07fc601b
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 1193206 - Building with Android support library 23.0.1
|
||||
Bug 1212764 - Clobber needed for bug 957911
|
||||
|
|
|
@ -985,6 +985,13 @@ UpdateAtkRelation(RelationType aType, Accessible* aAcc,
|
|||
while ((tempAcc = rel.Next()))
|
||||
targets.AppendElement(AccessibleWrap::GetAtkObject(tempAcc));
|
||||
|
||||
if (aType == RelationType::EMBEDS && aAcc->IsRoot()) {
|
||||
if (ProxyAccessible* proxyDoc =
|
||||
aAcc->AsRoot()->GetPrimaryRemoteTopLevelContentDoc()) {
|
||||
targets.AppendElement(GetWrapperFor(proxyDoc));
|
||||
}
|
||||
}
|
||||
|
||||
if (targets.Length()) {
|
||||
atkRelation = atk_relation_new(targets.Elements(),
|
||||
targets.Length(), aAtkType);
|
||||
|
@ -1121,6 +1128,10 @@ GetInterfacesForProxy(ProxyAccessible* aProxy, uint32_t aInterfaces)
|
|||
interfaces |= 1 << MAI_INTERFACE_SELECTION;
|
||||
}
|
||||
|
||||
if (aInterfaces & Interfaces::ACTION) {
|
||||
interfaces |= 1 << MAI_INTERFACE_ACTION;
|
||||
}
|
||||
|
||||
return interfaces;
|
||||
}
|
||||
|
||||
|
|
|
@ -1364,14 +1364,15 @@ DocAccessible::ProcessInvalidationList()
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!child->Parent()) {
|
||||
Accessible* oldParent = child->Parent();
|
||||
if (!oldParent) {
|
||||
NS_ERROR("The accessible is in document but doesn't have a parent");
|
||||
continue;
|
||||
}
|
||||
int32_t idxInParent = child->IndexInParent();
|
||||
|
||||
// XXX: update context flags
|
||||
{
|
||||
Accessible* oldParent = child->Parent();
|
||||
nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(oldParent);
|
||||
nsRefPtr<AccMutationEvent> hideEvent =
|
||||
new AccHideEvent(child, child->GetContent(), false);
|
||||
|
@ -1385,21 +1386,29 @@ DocAccessible::ProcessInvalidationList()
|
|||
FireDelayedEvent(reorderEvent);
|
||||
}
|
||||
|
||||
bool isReinserted = false;
|
||||
{
|
||||
AutoTreeMutation mut(owner);
|
||||
owner->AppendChild(child);
|
||||
|
||||
nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(owner);
|
||||
nsRefPtr<AccMutationEvent> showEvent =
|
||||
new AccShowEvent(child, child->GetContent());
|
||||
FireDelayedEvent(showEvent);
|
||||
reorderEvent->AddSubMutationEvent(showEvent);
|
||||
|
||||
MaybeNotifyOfValueChange(owner);
|
||||
FireDelayedEvent(reorderEvent);
|
||||
isReinserted = owner->AppendChild(child);
|
||||
}
|
||||
|
||||
child->SetRepositioned(true);
|
||||
Accessible* newParent = owner;
|
||||
if (!isReinserted) {
|
||||
AutoTreeMutation mut(oldParent);
|
||||
oldParent->InsertChildAt(idxInParent, child);
|
||||
newParent = oldParent;
|
||||
}
|
||||
|
||||
nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(newParent);
|
||||
nsRefPtr<AccMutationEvent> showEvent =
|
||||
new AccShowEvent(child, child->GetContent());
|
||||
FireDelayedEvent(showEvent);
|
||||
reorderEvent->AddSubMutationEvent(showEvent);
|
||||
|
||||
MaybeNotifyOfValueChange(newParent);
|
||||
FireDelayedEvent(reorderEvent);
|
||||
|
||||
child->SetRepositioned(isReinserted);
|
||||
}
|
||||
|
||||
mARIAOwnsInvalidationList.Clear();
|
||||
|
|
|
@ -192,14 +192,8 @@ OuterDocAccessible::RemoteChildDoc() const
|
|||
if (!tab)
|
||||
return nullptr;
|
||||
|
||||
// XXX Consider managing non top level remote documents with there parent
|
||||
// document.
|
||||
const nsTArray<PDocAccessibleParent*>& docs = tab->ManagedPDocAccessibleParent();
|
||||
size_t docCount = docs.Length();
|
||||
for (size_t i = 0; i < docCount; i++) {
|
||||
auto doc = static_cast<DocAccessibleParent*>(docs[i]);
|
||||
if (!doc->ParentDoc())
|
||||
return doc;
|
||||
if (DocAccessibleParent* doc = tab->GetTopLevelDocAccessible()) {
|
||||
return doc;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(false, "no top level tab document?");
|
||||
|
|
|
@ -716,3 +716,20 @@ RootAccessible::HandleTreeInvalidatedEvent(nsIDOMEvent* aEvent,
|
|||
aAccessible->TreeViewInvalidated(startRow, endRow, startCol, endCol);
|
||||
}
|
||||
#endif
|
||||
|
||||
ProxyAccessible*
|
||||
RootAccessible::GetPrimaryRemoteTopLevelContentDoc() const
|
||||
{
|
||||
nsCOMPtr<nsIDocShellTreeOwner> owner;
|
||||
mDocumentNode->GetDocShell()->GetTreeOwner(getter_AddRefs(owner));
|
||||
NS_ENSURE_TRUE(owner, nullptr);
|
||||
|
||||
nsCOMPtr<nsITabParent> tabParent;
|
||||
owner->GetPrimaryTabParent(getter_AddRefs(tabParent));
|
||||
if (!tabParent) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto tab = static_cast<dom::TabParent*>(tabParent.get());
|
||||
return tab->GetTopLevelDocAccessible();
|
||||
}
|
||||
|
|
|
@ -42,6 +42,11 @@ public:
|
|||
*/
|
||||
virtual void DocumentActivated(DocAccessible* aDocument);
|
||||
|
||||
/**
|
||||
* Return the primary remote top level document if any.
|
||||
*/
|
||||
ProxyAccessible* GetPrimaryRemoteTopLevelContentDoc() const;
|
||||
|
||||
protected:
|
||||
virtual ~RootAccessible();
|
||||
|
||||
|
|
|
@ -50,6 +50,10 @@ InterfacesFor(Accessible* aAcc)
|
|||
interfaces |= Interfaces::SELECTION;
|
||||
}
|
||||
|
||||
if (aAcc->ActionCount()) {
|
||||
interfaces |= Interfaces::ACTION;
|
||||
}
|
||||
|
||||
return interfaces;
|
||||
}
|
||||
|
||||
|
|
|
@ -395,6 +395,7 @@ enum Interfaces
|
|||
TABLECELL = 32,
|
||||
DOCUMENT = 64,
|
||||
SELECTION = 128,
|
||||
ACTION = 256,
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -952,11 +952,13 @@ AccessibleWrap::accLocation(
|
|||
if (xpAccessible->IsDefunct())
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
|
||||
// TODO make this work with proxies.
|
||||
if (xpAccessible->IsProxy())
|
||||
return E_NOTIMPL;
|
||||
nsIntRect rect;
|
||||
if (xpAccessible->IsProxy()) {
|
||||
rect = xpAccessible->Proxy()->Bounds();
|
||||
} else {
|
||||
rect = xpAccessible->Bounds();
|
||||
}
|
||||
|
||||
nsIntRect rect = xpAccessible->Bounds();
|
||||
*pxLeft = rect.x;
|
||||
*pyTop = rect.y;
|
||||
*pcxWidth = rect.width;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||
|
@ -122,7 +122,7 @@
|
|||
<project name="platform/system/media" path="system/media" revision="c1332c21c608f4932a6d7e83450411cde53315ef"/>
|
||||
<default remote="caf" revision="LNX.LA.3.5.2.1.1" sync-j="4"/>
|
||||
<!-- Platform common things -->
|
||||
<project name="device-shinano-common" path="device/sony/shinano-common" remote="b2g" revision="2f09386bb130b0111219cfc830316797392d48b0"/>
|
||||
<project name="device-shinano-common" path="device/sony/shinano-common" remote="b2g" revision="4a5672c356ba539095109d827ba103cd8dfdcf1a"/>
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="1bb28abbc215f45220620af5cd60a8ac1be93722"/>
|
||||
<project name="device/qcom/common" path="device/qcom/common" revision="2501e5940ba69ece7654ff85611c76ae5bda299c"/>
|
||||
<project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="d620691cad7aee780018e98159ff03bf99840317"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||
|
|
|
@ -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="b99837aa2294348317bcae68acabe71d9a83d774"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>
|
||||
|
|
|
@ -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="b99837aa2294348317bcae68acabe71d9a83d774"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||
<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="b99837aa2294348317bcae68acabe71d9a83d774"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"config_version": 2,
|
||||
"tooltool_manifest": "releng-flame-kk.tt",
|
||||
"mock_target": "mozilla-centos6-x86_64",
|
||||
"mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel", "glibc-devel.i686", "libstdc++.i686", "zlib-devel.i686", "ncurses-devel.i686", "libX11-devel.i686", "mesa-libGL-devel.i686", "mesa-libGL-devel", "libX11-devel", "git", "libxml2", "dosfstools"],
|
||||
"mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel", "glibc-devel.i686", "libstdc++.i686", "zlib-devel.i686", "ncurses-devel.i686", "libX11-devel.i686", "mesa-libGL-devel.i686", "mesa-libGL-devel", "libX11-devel", "git", "libxml2", "dosfstools", "java-1.6.0-openjdk"],
|
||||
"mock_files": [
|
||||
["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"],
|
||||
["/builds/crash-stats-api.token", "/builds/crash-stats-api.token"]
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "b99837aa2294348317bcae68acabe71d9a83d774",
|
||||
"git_revision": "4973f57cd8f9a62a95f783a24eac32da2bde99fc",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "cd2549520049a8532b966d3edda167f7bc444fba",
|
||||
"revision": "c728de03bc96ef160fd5a662b3efcd5cf2c2b844",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="b99837aa2294348317bcae68acabe71d9a83d774"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||
|
@ -141,7 +141,7 @@
|
|||
<default remote="caf" revision="refs/tags/android-5.1.0_r1" sync-j="4"/>
|
||||
<!-- Nexus 5 specific things -->
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="fe7df1bc8dd0fd71571505d7be1c31a4ad1e40fb"/>
|
||||
<project name="device-hammerhead" path="device/lge/hammerhead" remote="b2g" revision="844d9fe1c7114c6d586fbea611cbb7038413d762"/>
|
||||
<project name="device-hammerhead" path="device/lge/hammerhead" remote="b2g" revision="2900636d764df131e7914923c1ca813fc8879a7b"/>
|
||||
<project name="device_lge_hammerhead-kernel" path="device/lge/hammerhead-kernel" remote="b2g" revision="8b3ffcfdd3d3852eca5488628f8bb2a08acbffa7"/>
|
||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="5d0ae53d9588c3d70c005aec9be94af9a534de16"/>
|
||||
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="c15b6e266136cd0cdd9b94d0bbed1962d9dd6672"/>
|
||||
|
|
|
@ -1825,6 +1825,11 @@ pref("ui.key.menuAccessKeyFocuses", true);
|
|||
pref("media.eme.enabled", true);
|
||||
pref("media.eme.apiVisible", true);
|
||||
|
||||
// If decoding-via-gmp is turned on for <video>, default to using
|
||||
// Adobe's GMP for decoding.
|
||||
pref("media.fragmented-mp4.gmp.aac", 2);
|
||||
pref("media.fragmented-mp4.gmp.h264", 2);
|
||||
|
||||
// Whether we should run a test-pattern through EME GMPs before assuming they'll
|
||||
// decode H.264.
|
||||
pref("media.gmp.trial-create.enabled", true);
|
||||
|
|
|
@ -4977,10 +4977,6 @@ nsBrowserAccess.prototype = {
|
|||
isTabContentWindow: function (aWindow) {
|
||||
return gBrowser.browsers.some(browser => browser.contentWindow == aWindow);
|
||||
},
|
||||
|
||||
canClose() {
|
||||
return CanCloseWindow();
|
||||
},
|
||||
}
|
||||
|
||||
function getTogglableToolbars() {
|
||||
|
@ -6446,26 +6442,6 @@ var IndexedDBPromptHelper = {
|
|||
}
|
||||
};
|
||||
|
||||
function CanCloseWindow()
|
||||
{
|
||||
// Avoid redundant calls to canClose from showing multiple
|
||||
// PermitUnload dialogs.
|
||||
if (window.skipNextCanClose) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (let browser of gBrowser.browsers) {
|
||||
let {permitUnload, timedOut} = browser.permitUnload();
|
||||
if (timedOut) {
|
||||
return true;
|
||||
}
|
||||
if (!permitUnload) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function WindowIsClosing()
|
||||
{
|
||||
if (TabView.isVisible()) {
|
||||
|
@ -6476,19 +6452,27 @@ function WindowIsClosing()
|
|||
if (!closeWindow(false, warnAboutClosingWindow))
|
||||
return false;
|
||||
|
||||
// In theory we should exit here and the Window's internal Close
|
||||
// method should trigger canClose on nsBrowserAccess. However, by
|
||||
// that point it's too late to be able to show a prompt for
|
||||
// PermitUnload. So we do it here, when we still can.
|
||||
if (CanCloseWindow()) {
|
||||
// This flag ensures that the later canClose call does nothing.
|
||||
// It's only needed to make tests pass, since they detect the
|
||||
// prompt even when it's not actually shown.
|
||||
window.skipNextCanClose = true;
|
||||
// Bug 967873 - Proxy nsDocumentViewer::PermitUnload to the child process
|
||||
if (gMultiProcessBrowser)
|
||||
return true;
|
||||
|
||||
for (let browser of gBrowser.browsers) {
|
||||
let ds = browser.docShell;
|
||||
// Passing true to permitUnload indicates we plan on closing the window.
|
||||
// This means that once unload is permitted, all further calls to
|
||||
// permitUnload will be ignored. This avoids getting multiple prompts
|
||||
// to unload the page.
|
||||
if (ds.contentViewer && !ds.contentViewer.permitUnload(true)) {
|
||||
// ... however, if the user aborts closing, we need to undo that,
|
||||
// to ensure they get prompted again when we next try to close the window.
|
||||
// We do this on the window's toplevel docshell instead of on the tab, so
|
||||
// that all tabs we iterated before will get this reset.
|
||||
window.getInterface(Ci.nsIDocShell).contentViewer.resetCloseWindow();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -119,7 +119,7 @@
|
|||
accesskey="&bookmarkAllTabs.accesskey;"
|
||||
command="Browser:BookmarkAllTabs"/>
|
||||
<menuitem id="context_closeTabsToTheEnd" label="&closeTabsToTheEnd.label;" accesskey="&closeTabsToTheEnd.accesskey;"
|
||||
oncommand="gBrowser.removeTabsToTheEndFrom(TabContextMenu.contextTab, {animate: true});"/>
|
||||
oncommand="gBrowser.removeTabsToTheEndFrom(TabContextMenu.contextTab);"/>
|
||||
<menuitem id="context_closeOtherTabs" label="&closeOtherTabs.label;" accesskey="&closeOtherTabs.accesskey;"
|
||||
oncommand="gBrowser.removeAllTabsBut(TabContextMenu.contextTab);"/>
|
||||
<menuseparator/>
|
||||
|
|
|
@ -131,11 +131,6 @@ chatBrowserAccess.prototype = {
|
|||
isTabContentWindow: function (aWindow) {
|
||||
return this.contentWindow == aWindow;
|
||||
},
|
||||
|
||||
canClose() {
|
||||
let {BrowserUtils} = Cu.import("resource://gre/modules/BrowserUtils.jsm", {});
|
||||
return BrowserUtils.canCloseWindow(window);
|
||||
},
|
||||
};
|
||||
|
||||
</script>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
// -*- indent-tabs-mode: nil; js-indent-level: 4 -*-
|
||||
/* 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/. */
|
||||
|
@ -567,17 +567,28 @@ Sanitizer.prototype = {
|
|||
openWindows: {
|
||||
privateStateForNewWindow: "non-private",
|
||||
_canCloseWindow: function(aWindow) {
|
||||
if (aWindow.CanCloseWindow()) {
|
||||
// We already showed PermitUnload for the window, so let's
|
||||
// make sure we don't do it again when we actually close the
|
||||
// window.
|
||||
aWindow.skipNextCanClose = true;
|
||||
return true;
|
||||
// Bug 967873 - Proxy nsDocumentViewer::PermitUnload to the child process
|
||||
if (!aWindow.gMultiProcessBrowser) {
|
||||
// Cargo-culted out of browser.js' WindowIsClosing because we don't care
|
||||
// about TabView or the regular 'warn me before closing windows with N tabs'
|
||||
// stuff here, and more importantly, we want to set aCallerClosesWindow to true
|
||||
// when calling into permitUnload:
|
||||
for (let browser of aWindow.gBrowser.browsers) {
|
||||
let ds = browser.docShell;
|
||||
// 'true' here means we will be closing the window soon, so please don't dispatch
|
||||
// another onbeforeunload event when we do so. If unload is *not* permitted somewhere,
|
||||
// we will reset the flag that this triggers everywhere so that we don't interfere
|
||||
// with the browser after all:
|
||||
if (ds.contentViewer && !ds.contentViewer.permitUnload(true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
_resetAllWindowClosures: function(aWindowList) {
|
||||
for (let win of aWindowList) {
|
||||
win.skipNextCanClose = false;
|
||||
win.getInterface(Ci.nsIDocShell).contentViewer.resetCloseWindow();
|
||||
}
|
||||
},
|
||||
clear: Task.async(function*() {
|
||||
|
|
|
@ -1190,29 +1190,25 @@
|
|||
this._tabAttrModified(this.mCurrentTab, ["selected"]);
|
||||
|
||||
if (oldBrowser != newBrowser &&
|
||||
oldBrowser.getInPermitUnload) {
|
||||
oldBrowser.getInPermitUnload(inPermitUnload => {
|
||||
if (!inPermitUnload) {
|
||||
return;
|
||||
}
|
||||
// Since the user is switching away from a tab that has
|
||||
// a beforeunload prompt active, we remove the prompt.
|
||||
// This prevents confusing user flows like the following:
|
||||
// 1. User attempts to close Firefox
|
||||
// 2. User switches tabs (ingoring a beforeunload prompt)
|
||||
// 3. User returns to tab, presses "Leave page"
|
||||
let promptBox = this.getTabModalPromptBox(oldBrowser);
|
||||
let prompts = promptBox.listPrompts();
|
||||
// There might not be any prompts here if the tab was closed
|
||||
// while in an onbeforeunload prompt, which will have
|
||||
// destroyed aforementioned prompt already, so check there's
|
||||
// something to remove, first:
|
||||
if (prompts.length) {
|
||||
// NB: This code assumes that the beforeunload prompt
|
||||
// is the top-most prompt on the tab.
|
||||
prompts[prompts.length - 1].abortPrompt();
|
||||
}
|
||||
});
|
||||
oldBrowser.docShell &&
|
||||
oldBrowser.docShell.contentViewer.inPermitUnload) {
|
||||
// Since the user is switching away from a tab that has
|
||||
// a beforeunload prompt active, we remove the prompt.
|
||||
// This prevents confusing user flows like the following:
|
||||
// 1. User attempts to close Firefox
|
||||
// 2. User switches tabs (ingoring a beforeunload prompt)
|
||||
// 3. User returns to tab, presses "Leave page"
|
||||
let promptBox = this.getTabModalPromptBox(oldBrowser);
|
||||
let prompts = promptBox.listPrompts();
|
||||
// There might not be any prompts here if the tab was closed
|
||||
// while in an onbeforeunload prompt, which will have
|
||||
// destroyed aforementioned prompt already, so check there's
|
||||
// something to remove, first:
|
||||
if (prompts.length) {
|
||||
// NB: This code assumes that the beforeunload prompt
|
||||
// is the top-most prompt on the tab.
|
||||
prompts[prompts.length - 1].abortPrompt();
|
||||
}
|
||||
}
|
||||
|
||||
oldBrowser._urlbarFocused = (gURLBar && gURLBar.focused);
|
||||
|
@ -2081,13 +2077,12 @@
|
|||
|
||||
<method name="removeTabsToTheEndFrom">
|
||||
<parameter name="aTab"/>
|
||||
<parameter name="aParams"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this.warnAboutClosingTabs(this.closingTabsEnum.TO_END, aTab)) {
|
||||
let tabs = this.getTabsToTheEndFrom(aTab);
|
||||
for (let i = tabs.length - 1; i >= 0; --i) {
|
||||
this.removeTab(tabs[i], aParams);
|
||||
this.removeTab(tabs[i], {animate: true});
|
||||
}
|
||||
}
|
||||
]]>
|
||||
|
@ -2135,7 +2130,6 @@
|
|||
if (aParams) {
|
||||
var animate = aParams.animate;
|
||||
var byMouse = aParams.byMouse;
|
||||
var skipPermitUnload = aParams.skipPermitUnload;
|
||||
}
|
||||
|
||||
// Handle requests for synchronously removing an already
|
||||
|
@ -2148,7 +2142,7 @@
|
|||
|
||||
var isLastTab = (this.tabs.length - this._removingTabs.length == 1);
|
||||
|
||||
if (!this._beginRemoveTab(aTab, false, null, true, skipPermitUnload))
|
||||
if (!this._beginRemoveTab(aTab, false, null, true))
|
||||
return;
|
||||
|
||||
if (!aTab.pinned && !aTab.hidden && aTab._fullyOpen && byMouse)
|
||||
|
@ -2196,7 +2190,6 @@
|
|||
<parameter name="aTabWillBeMoved"/>
|
||||
<parameter name="aCloseWindowWithLastTab"/>
|
||||
<parameter name="aCloseWindowFastpath"/>
|
||||
<parameter name="aSkipPermitUnload"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (aTab.closing ||
|
||||
|
@ -2227,20 +2220,23 @@
|
|||
newTab = true;
|
||||
}
|
||||
|
||||
if (!aTab._pendingPermitUnload && !aTabWillBeMoved && !aSkipPermitUnload) {
|
||||
// We need to block while calling permitUnload() because it
|
||||
// processes the event queue and may lead to another removeTab()
|
||||
// call before permitUnload() returns.
|
||||
aTab._pendingPermitUnload = true;
|
||||
let {permitUnload} = browser.permitUnload();
|
||||
delete aTab._pendingPermitUnload;
|
||||
// If we were closed during onbeforeunload, we return false now
|
||||
// so we don't (try to) close the same tab again. Of course, we
|
||||
// also stop if the unload was cancelled by the user:
|
||||
if (aTab.closing || !permitUnload) {
|
||||
// NB: deliberately keep the _closedDuringPermitUnload set to
|
||||
// true so we keep exiting early in case of multiple calls.
|
||||
return false;
|
||||
if (!aTab._pendingPermitUnload && !aTabWillBeMoved) {
|
||||
let ds = browser.docShell;
|
||||
if (ds && ds.contentViewer) {
|
||||
// We need to block while calling permitUnload() because it
|
||||
// processes the event queue and may lead to another removeTab()
|
||||
// call before permitUnload() returns.
|
||||
aTab._pendingPermitUnload = true;
|
||||
let permitUnload = ds.contentViewer.permitUnload();
|
||||
delete aTab._pendingPermitUnload;
|
||||
// If we were closed during onbeforeunload, we return false now
|
||||
// so we don't (try to) close the same tab again. Of course, we
|
||||
// also stop if the unload was cancelled by the user:
|
||||
if (aTab.closing || !permitUnload) {
|
||||
// NB: deliberately keep the _closedDuringPermitUnload set to
|
||||
// true so we keep exiting early in case of multiple calls.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4058,19 +4054,13 @@
|
|||
}
|
||||
case "DOMWindowClose": {
|
||||
if (this.tabs.length == 1) {
|
||||
// We already did PermitUnload in the content process
|
||||
// for this tab (the only one in the window). So we don't
|
||||
// need to do it again for any tabs.
|
||||
window.skipNextCanClose = true;
|
||||
window.close();
|
||||
return;
|
||||
}
|
||||
|
||||
let tab = this.getTabForBrowser(browser);
|
||||
if (tab) {
|
||||
// Skip running PermitUnload since it already happened in
|
||||
// the content process.
|
||||
this.removeTab(tab, {skipPermitUnload: true});
|
||||
this.removeTab(tab);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -4354,18 +4344,12 @@
|
|||
if (!event.isTrusted)
|
||||
return;
|
||||
|
||||
if (this.tabs.length == 1) {
|
||||
// We already did PermitUnload in nsGlobalWindow::Close
|
||||
// for this tab. There are no other tabs we need to do
|
||||
// PermitUnload for.
|
||||
window.skipNextCanClose = true;
|
||||
if (this.tabs.length == 1)
|
||||
return;
|
||||
}
|
||||
|
||||
var tab = this._getTabForContentWindow(event.target);
|
||||
if (tab) {
|
||||
// Skip running PermitUnload since it already happened.
|
||||
this.removeTab(tab, {skipPermitUnload: true});
|
||||
this.removeTab(tab);
|
||||
event.preventDefault();
|
||||
}
|
||||
]]>
|
||||
|
|
|
@ -133,6 +133,7 @@ skip-if = e10s # Bug 1093153 - no about:home support yet
|
|||
[browser_action_searchengine_alias.js]
|
||||
[browser_addKeywordSearch.js]
|
||||
[browser_search_favicon.js]
|
||||
skip-if = e10s # Bug 1212647
|
||||
[browser_alltabslistener.js]
|
||||
[browser_audioTabIcon.js]
|
||||
[browser_autocomplete_a11y_label.js]
|
||||
|
@ -147,6 +148,7 @@ skip-if = e10s # Bug 1101993 - times out for unknown reasons when run in the dir
|
|||
[browser_backButtonFitts.js]
|
||||
skip-if = os == "mac" # The Fitt's Law back button is not supported on OS X
|
||||
[browser_beforeunload_duplicate_dialogs.js]
|
||||
skip-if = e10s # bug 967873 means permitUnload doesn't work in e10s mode
|
||||
[browser_blob-channelname.js]
|
||||
[browser_bookmark_titles.js]
|
||||
skip-if = buildapp == 'mulet' || toolkit == "windows" # Disabled on Windows due to frequent failures (bugs 825739, 841341)
|
||||
|
|
|
@ -22,7 +22,7 @@ function test() {
|
|||
function addTab(aURI, aIndex) {
|
||||
var tab = gBrowser.addTab(aURI);
|
||||
if (aIndex == 0)
|
||||
gBrowser.removeTab(gBrowser.tabs[0], {skipPermitUnload: true});
|
||||
gBrowser.removeTab(gBrowser.tabs[0]);
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", function (event) {
|
||||
event.currentTarget.removeEventListener("load", arguments.callee, true);
|
||||
|
@ -41,14 +41,14 @@ function doTabsTest() {
|
|||
var scheme = closedTab.linkedBrowser.currentURI.scheme;
|
||||
Array.slice(gBrowser.tabs).forEach(function (aTab) {
|
||||
if (aTab != closedTab && aTab.linkedBrowser.currentURI.scheme == scheme)
|
||||
gBrowser.removeTab(aTab, {skipPermitUnload: true});
|
||||
gBrowser.removeTab(aTab);
|
||||
});
|
||||
}, true);
|
||||
|
||||
gBrowser.removeTab(gBrowser.tabs[0], {skipPermitUnload: true});
|
||||
gBrowser.removeTab(gBrowser.tabs[0]);
|
||||
is(gBrowser.tabs.length, 1, "Related tabs are not closed unexpectedly");
|
||||
|
||||
gBrowser.addTab("about:blank");
|
||||
gBrowser.removeTab(gBrowser.tabs[0], {skipPermitUnload: true});
|
||||
gBrowser.removeTab(gBrowser.tabs[0]);
|
||||
finish();
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ function checkBookmarksPanel(invoker, phase)
|
|||
if (currentInvoker < invokers.length) {
|
||||
checkBookmarksPanel(invokers[currentInvoker], 1);
|
||||
} else {
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {skipPermitUnload: true});
|
||||
gBrowser.removeCurrentTab();
|
||||
PlacesUtils.bookmarks.removeItem(bookmarkId);
|
||||
executeSoon(finish);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
add_task(function*() {
|
||||
function test() {
|
||||
is(gBrowser.tabs.length, 1, "one tab is open");
|
||||
|
||||
gBrowser.selectedBrowser.focus();
|
||||
|
@ -6,15 +6,11 @@ add_task(function*() {
|
|||
|
||||
var tab = gBrowser.selectedTab;
|
||||
gPrefService.setBoolPref("browser.tabs.closeWindowWithLastTab", false);
|
||||
|
||||
let tabClosedPromise = BrowserTestUtils.removeTab(tab, {dontRemove: true});
|
||||
EventUtils.synthesizeKey("w", { accelKey: true });
|
||||
yield tabClosedPromise;
|
||||
|
||||
is(tab.parentNode, null, "ctrl+w removes the tab");
|
||||
is(gBrowser.tabs.length, 1, "a new tab has been opened");
|
||||
is(document.activeElement, gURLBar.inputField, "location bar is focused for the new tab");
|
||||
|
||||
if (gPrefService.prefHasUserValue("browser.tabs.closeWindowWithLastTab"))
|
||||
gPrefService.clearUserPref("browser.tabs.closeWindowWithLastTab");
|
||||
});
|
||||
}
|
||||
|
|
|
@ -18,13 +18,10 @@ function record(aName) {
|
|||
if (actual.length == expected.length) {
|
||||
is(actual.toString(), expected.toString(),
|
||||
"got events and progress notifications in expected order");
|
||||
|
||||
executeSoon(function(tab) {
|
||||
gBrowser.removeTab(tab);
|
||||
gBrowser.removeTabsProgressListener(progressListener);
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", TabOpen, false);
|
||||
finish();
|
||||
}.bind(null, tab));
|
||||
gBrowser.removeTab(tab);
|
||||
gBrowser.removeTabsProgressListener(progressListener);
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", TabOpen, false);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,14 +6,14 @@ function test() {
|
|||
|
||||
childTab1 = gBrowser.addTab("about:blank", { relatedToCurrent: true });
|
||||
gBrowser.selectedTab = childTab1;
|
||||
gBrowser.removeTab(gBrowser.selectedTab, { skipPermitUnload: true });
|
||||
gBrowser.removeCurrentTab();
|
||||
is(idx(gBrowser.selectedTab), idx(tab1),
|
||||
"closing a tab next to its parent selects the parent");
|
||||
|
||||
childTab1 = gBrowser.addTab("about:blank", { relatedToCurrent: true });
|
||||
gBrowser.selectedTab = tab2;
|
||||
gBrowser.selectedTab = childTab1;
|
||||
gBrowser.removeTab(gBrowser.selectedTab, { skipPermitUnload: true });
|
||||
gBrowser.removeCurrentTab();
|
||||
is(idx(gBrowser.selectedTab), idx(tab2),
|
||||
"closing a tab next to its parent doesn't select the parent if another tab had been selected ad interim");
|
||||
|
||||
|
@ -21,14 +21,14 @@ function test() {
|
|||
childTab1 = gBrowser.addTab("about:blank", { relatedToCurrent: true });
|
||||
childTab2 = gBrowser.addTab("about:blank", { relatedToCurrent: true });
|
||||
gBrowser.selectedTab = childTab1;
|
||||
gBrowser.removeTab(gBrowser.selectedTab, { skipPermitUnload: true });
|
||||
gBrowser.removeCurrentTab();
|
||||
is(idx(gBrowser.selectedTab), idx(childTab2),
|
||||
"closing a tab next to its parent selects the next tab with the same parent");
|
||||
gBrowser.removeTab(gBrowser.selectedTab, { skipPermitUnload: true });
|
||||
gBrowser.removeCurrentTab();
|
||||
is(idx(gBrowser.selectedTab), idx(tab2),
|
||||
"closing the last tab in a set of child tabs doesn't go back to the parent");
|
||||
|
||||
gBrowser.removeTab(tab2, { skipPermitUnload: true });
|
||||
gBrowser.removeTab(tab2);
|
||||
}
|
||||
|
||||
function idx(tab) {
|
||||
|
|
|
@ -14,13 +14,6 @@ function testAttrib(elem, attrib, attribValue, msg) {
|
|||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Ensure TabView has been initialized already. Otherwise it could
|
||||
// activate at an unexpected time and show/hide tabs.
|
||||
TabView._initFrame(runTest);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
is(gBrowser.tabs.length, 1, "one tab is open initially");
|
||||
|
||||
// Add several new tabs in sequence, hiding some, to ensure that the
|
||||
|
|
|
@ -5,12 +5,6 @@
|
|||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Ensure TabView has been initialized already. Otherwise it could
|
||||
// activate at an unexpected time and show/hide tabs.
|
||||
TabView._initFrame(runTest);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
// establish initial state
|
||||
is(gBrowser.tabs.length, 1, "we start with one tab");
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
function test () {
|
||||
requestLongerTimeout(2);
|
||||
waitForExplicitFinish();
|
||||
|
||||
var isHTTPS = false;
|
||||
|
|
|
@ -7,12 +7,6 @@
|
|||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Ensure TabView has been initialized already. Otherwise it could
|
||||
// activate at an unexpected time and show/hide tabs.
|
||||
TabView._initFrame(runTest);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
// Add a tab that will get removed and hidden
|
||||
let testTab = gBrowser.addTab("about:blank", {skipAnimation: true});
|
||||
is(gBrowser.visibleTabs.length, 2, "just added a tab, so 2 tabs");
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
add_task(function*() {
|
||||
function test() {
|
||||
is(gBrowser.tabs.length, 1, "one tab is open initially");
|
||||
|
||||
// Add several new tabs in sequence, interrupted by selecting a
|
||||
|
@ -10,29 +10,26 @@ add_task(function*() {
|
|||
// returning a list of opened tabs for verifying the expected order.
|
||||
// The new tab behaviour is documented in bug 465673
|
||||
let tabs = [];
|
||||
let promises = [];
|
||||
function addTab(aURL, aReferrer) {
|
||||
let tab = gBrowser.addTab(aURL, {referrerURI: aReferrer});
|
||||
tabs.push(tab);
|
||||
return BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
tabs.push(gBrowser.addTab(aURL, {referrerURI: aReferrer}));
|
||||
}
|
||||
|
||||
yield addTab("http://mochi.test:8888/#0");
|
||||
addTab("http://mochi.test:8888/#0");
|
||||
gBrowser.selectedTab = tabs[0];
|
||||
yield addTab("http://mochi.test:8888/#1");
|
||||
yield addTab("http://mochi.test:8888/#2", gBrowser.currentURI);
|
||||
yield addTab("http://mochi.test:8888/#3", gBrowser.currentURI);
|
||||
addTab("http://mochi.test:8888/#1");
|
||||
addTab("http://mochi.test:8888/#2", gBrowser.currentURI);
|
||||
addTab("http://mochi.test:8888/#3", gBrowser.currentURI);
|
||||
gBrowser.selectedTab = tabs[tabs.length - 1];
|
||||
gBrowser.selectedTab = tabs[0];
|
||||
yield addTab("http://mochi.test:8888/#4", gBrowser.currentURI);
|
||||
addTab("http://mochi.test:8888/#4", gBrowser.currentURI);
|
||||
gBrowser.selectedTab = tabs[3];
|
||||
yield addTab("http://mochi.test:8888/#5", gBrowser.currentURI);
|
||||
addTab("http://mochi.test:8888/#5", gBrowser.currentURI);
|
||||
gBrowser.removeTab(tabs.pop());
|
||||
yield addTab("about:blank", gBrowser.currentURI);
|
||||
addTab("about:blank", gBrowser.currentURI);
|
||||
gBrowser.moveTabTo(gBrowser.selectedTab, 1);
|
||||
yield addTab("http://mochi.test:8888/#6", gBrowser.currentURI);
|
||||
yield addTab();
|
||||
yield addTab("http://mochi.test:8888/#7");
|
||||
addTab("http://mochi.test:8888/#6", gBrowser.currentURI);
|
||||
addTab();
|
||||
addTab("http://mochi.test:8888/#7");
|
||||
|
||||
function testPosition(tabNum, expectedPosition, msg) {
|
||||
is(Array.indexOf(gBrowser.tabs, tabs[tabNum]), expectedPosition, msg);
|
||||
|
@ -49,4 +46,4 @@ add_task(function*() {
|
|||
testPosition(8, 9, "tab without referrer opens at the end");
|
||||
|
||||
tabs.forEach(gBrowser.removeTab, gBrowser);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -18,5 +18,5 @@ function test() {
|
|||
"gBrowser.selectTabAtIndex(-3) selects expected tab");
|
||||
|
||||
for (let i = 0; i < 9; i++)
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {skipPermitUnload: true});
|
||||
gBrowser.removeCurrentTab();
|
||||
}
|
||||
|
|
|
@ -2,11 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
add_task(function* () {
|
||||
// Ensure TabView has been initialized already. Otherwise it could
|
||||
// activate at an unexpected time and show/hide tabs.
|
||||
yield new Promise(resolve => TabView._initFrame(resolve));
|
||||
|
||||
function test() {
|
||||
// There should be one tab when we start the test
|
||||
let [origTab] = gBrowser.visibleTabs;
|
||||
|
||||
|
@ -104,5 +100,4 @@ add_task(function* () {
|
|||
|
||||
if (tabViewWindow)
|
||||
tabViewWindow.GroupItems.groupItems[0].close();
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -5,12 +5,6 @@
|
|||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Ensure TabView has been initialized already. Otherwise it could
|
||||
// activate at an unexpected time and show/hide tabs.
|
||||
TabView._initFrame(runTest);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
let tabOne = gBrowser.addTab("about:blank");
|
||||
let tabTwo = gBrowser.addTab("http://mochi.test:8888/");
|
||||
gBrowser.selectedTab = tabTwo;
|
||||
|
|
|
@ -5,12 +5,6 @@
|
|||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Ensure TabView has been initialized already. Otherwise it could
|
||||
// activate at an unexpected time and show/hide tabs.
|
||||
TabView._initFrame(runTest);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
// There should be one tab when we start the test
|
||||
let [origTab] = gBrowser.visibleTabs;
|
||||
is(gBrowser.visibleTabs.length, 1, "1 tab should be open");
|
||||
|
|
|
@ -2,11 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
add_task(function* test() {
|
||||
// Ensure TabView has been initialized already. Otherwise it could
|
||||
// activate at an unexpected time and show/hide tabs.
|
||||
yield new Promise(resolve => TabView._initFrame(resolve));
|
||||
|
||||
function test() {
|
||||
// There should be one tab when we start the test
|
||||
let [origTab] = gBrowser.visibleTabs;
|
||||
is(gBrowser.visibleTabs.length, 1, "there is one visible tab");
|
||||
|
@ -55,5 +51,4 @@ add_task(function* test() {
|
|||
|
||||
gBrowser.removeTab(testTab);
|
||||
gBrowser.removeTab(pinned);
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -2,11 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
add_task(function* test() {
|
||||
// Ensure TabView has been initialized already. Otherwise it could
|
||||
// activate at an unexpected time and show/hide tabs.
|
||||
yield new Promise(resolve => TabView._initFrame(resolve));
|
||||
|
||||
function test() {
|
||||
gPrefService.setBoolPref("browser.ctrlTab.previews", true);
|
||||
|
||||
let [origTab] = gBrowser.visibleTabs;
|
||||
|
@ -34,7 +30,7 @@ add_task(function* test() {
|
|||
|
||||
if (gPrefService.prefHasUserValue("browser.ctrlTab.previews"))
|
||||
gPrefService.clearUserPref("browser.ctrlTab.previews");
|
||||
});
|
||||
}
|
||||
|
||||
function pressCtrlTab(aShiftKey) {
|
||||
EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: !!aShiftKey });
|
||||
|
|
|
@ -416,7 +416,7 @@ function loadIntoTab(tab, url, callback) {
|
|||
|
||||
function ensureBrowserTabClosed(tab) {
|
||||
let promise = ensureEventFired(gBrowser.tabContainer, "TabClose");
|
||||
gBrowser.removeTab(tab, {skipPermitUnload: true});
|
||||
gBrowser.removeTab(tab);
|
||||
return promise;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,10 +6,6 @@ add_task(function* () {
|
|||
/** Bug 607016 - If a tab is never restored, attributes (eg. hidden) aren't updated correctly **/
|
||||
ignoreAllUncaughtExceptions();
|
||||
|
||||
// Ensure TabView has been initialized already. Otherwise it could
|
||||
// activate at an unexpected time and show/hide tabs.
|
||||
yield new Promise(resolve => TabView._initFrame(resolve));
|
||||
|
||||
// Set the pref to true so we know exactly how many tabs should be restoring at
|
||||
// any given time. This guarantees that a finishing load won't start another.
|
||||
Services.prefs.setBoolPref("browser.sessionstore.restore_on_demand", true);
|
||||
|
|
|
@ -7,12 +7,6 @@
|
|||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
// Ensure TabView has been initialized already. Otherwise it could
|
||||
// activate at an unexpected time and show/hide tabs.
|
||||
TabView._initFrame(runTest);
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
// We speed up the interval between session saves to ensure that the test
|
||||
// runs quickly.
|
||||
Services.prefs.setIntPref("browser.sessionstore.interval", 2000);
|
||||
|
|
|
@ -39,18 +39,11 @@ var RemotePrompt = {
|
|||
let tabPrompt = window.gBrowser.getTabModalPromptBox(browser)
|
||||
let callbackInvoked = false;
|
||||
let newPrompt;
|
||||
let needRemove = false;
|
||||
let promptId = args._remoteId;
|
||||
|
||||
function onPromptClose(forceCleanup) {
|
||||
// It's possible that we removed the prompt during the
|
||||
// appendPrompt call below. In that case, newPrompt will be
|
||||
// undefined. We set the needRemove flag to remember to remove
|
||||
// it right after we've finished adding it.
|
||||
if (newPrompt)
|
||||
tabPrompt.removePrompt(newPrompt);
|
||||
else
|
||||
needRemove = true;
|
||||
|
||||
PromptUtils.fireDialogEvent(window, "DOMModalDialogClosed", browser);
|
||||
browser.messageManager.sendAsyncMessage("Prompt:Close", args);
|
||||
|
@ -76,10 +69,6 @@ var RemotePrompt = {
|
|||
|
||||
newPrompt = tabPrompt.appendPrompt(args, onPromptClose);
|
||||
|
||||
if (needRemove) {
|
||||
tabPrompt.removePrompt(newPrompt);
|
||||
}
|
||||
|
||||
// TODO since we don't actually open a window, need to check if
|
||||
// there's other stuff in nsWindowWatcher::OpenWindowInternal
|
||||
// that we might need to do here as well.
|
||||
|
|
2279
config/configobj.py
2279
config/configobj.py
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -27,10 +27,6 @@
|
|||
# - PYTHON, the path to the python executable
|
||||
# - ACDEFINES, which contains a set of -Dvar=name to be used during
|
||||
# preprocessing
|
||||
# - MOZ_CHROME_FILE_FORMAT, which defines whether to use file copies or
|
||||
# symbolic links
|
||||
# - JAR_MN_TARGETS, which defines the targets to use for jar manifest
|
||||
# processing, see further below
|
||||
# - INSTALL_MANIFESTS, which defines the list of base directories handled
|
||||
# by install manifests, see further below
|
||||
# - MANIFEST_TARGETS, which defines the file paths of chrome manifests, see
|
||||
|
@ -42,7 +38,6 @@
|
|||
|
||||
# Targets to be triggered for a default build
|
||||
default: $(addprefix install-,$(INSTALL_MANIFESTS))
|
||||
default: $(addprefix jar-,$(JAR_MN_TARGETS))
|
||||
|
||||
# Explicit files to be built for a default build
|
||||
default: $(addprefix $(TOPOBJDIR)/,$(MANIFEST_TARGETS))
|
||||
|
@ -53,6 +48,12 @@ default: $(TOPOBJDIR)/dist/bin/webapprt/webapprt.ini
|
|||
# Targets from the recursive make backend to be built for a default build
|
||||
default: $(TOPOBJDIR)/config/makefiles/xpidl/xpidl
|
||||
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
# Mac builds require to copy things in dist/bin/*.app
|
||||
default:
|
||||
$(MAKE) -C $(TOPOBJDIR)/$(MOZ_BUILD_APP)/app repackage
|
||||
endif
|
||||
|
||||
.PHONY: FORCE
|
||||
|
||||
# Extra define to trigger some workarounds. We should strive to limit the
|
||||
|
@ -95,52 +96,6 @@ $(addprefix install-,$(INSTALL_MANIFESTS)): install-%: $(TOPOBJDIR)/config/build
|
|||
$(MOZ_DEBUG_DEFINES) \
|
||||
install_$(subst /,_,$*)
|
||||
|
||||
# Install files from jar manifests. Ideally, they would be using install
|
||||
# manifests, but the code to read jar manifests and emit appropriate
|
||||
# install manifests is not there yet.
|
||||
# Things missing:
|
||||
# - DEFINES from config/config.mk
|
||||
# - L10N
|
||||
# - -e when USE_EXTENSION_MANIFEST is set in moz.build
|
||||
#
|
||||
# The list given in JAR_MN_TARGETS corresponds to the list of `jar-%` targets
|
||||
# to be processed, with the `jar-` prefix stripped.
|
||||
# The Makefile is expected to specify the source jar manifest as a dependency
|
||||
# to each target. There is no expectation that the `jar-%` target name matches
|
||||
# the source file name in any way. For example:
|
||||
# JAR_MN_TARGETS = foo
|
||||
# jar-foo: /path/to/some/jar.mn
|
||||
# Additionally, extra defines can be specified for the processing of the jar
|
||||
# manifest by settig the `defines` variable specifically for the given target.
|
||||
# For example:
|
||||
# jar-foo: defines = -Dqux=foo
|
||||
# The default base path where files are going to be installed is `dist/bin`.
|
||||
# It is possible to use a different path by setting the `install_target`
|
||||
# variable. For example:
|
||||
# jar-foo: install_target = dist/bin/foo
|
||||
# When processing jar manifests, relative paths given inside a jar manifest
|
||||
# can be resolved from an object directory. The default path for that object
|
||||
# directory is the translation of the jar manifest directory path from the
|
||||
# source directory to the object directory. That is, for
|
||||
# $(TOPSRCDIR)/path/to/jar.mn, the default would be $(TOPOBJDIR)/path/to.
|
||||
# In case a different path must be used for the object directory, the `objdir`
|
||||
# variable can be set. For example:
|
||||
# jar-foo: objdir=/some/other/path
|
||||
jar-%: objdir ?= $(dir $(patsubst $(TOPSRCDIR)%,$(TOPOBJDIR)%,$<))
|
||||
jar-%: install_target ?= dist/bin
|
||||
jar-%:
|
||||
cd $(objdir) && \
|
||||
$(PYTHON) -m mozbuild.action.jar_maker \
|
||||
-j $(TOPOBJDIR)/$(install_target)/chrome \
|
||||
-t $(TOPSRCDIR) \
|
||||
-f $(MOZ_CHROME_FILE_FORMAT) \
|
||||
-c $(dir $<)/en-US \
|
||||
-DAB_CD=en-US \
|
||||
$(defines) \
|
||||
$(ACDEFINES) \
|
||||
$(MOZ_DEBUG_DEFINES) \
|
||||
$<
|
||||
|
||||
# Create some chrome manifests
|
||||
# This rule is forced to run every time because it may be updating files that
|
||||
# already exit.
|
||||
|
@ -159,13 +114,6 @@ $(addprefix $(TOPOBJDIR)/,$(MANIFEST_TARGETS)): FORCE
|
|||
# Below is a set of additional dependencies and variables used to build things
|
||||
# that are not supported by data in moz.build.
|
||||
|
||||
# GENERATED_FILES are not supported yet, and even if they were, the
|
||||
# dependencies are missing information.
|
||||
$(foreach p,linux osx windows,jar-browser-themes-$(p)-jar.mn): \
|
||||
jar-browser-themes-%-jar.mn: \
|
||||
$(TOPOBJDIR)/browser/themes/%/tab-selected-end.svg \
|
||||
$(TOPOBJDIR)/browser/themes/%/tab-selected-start.svg
|
||||
|
||||
# Files to build with the recursive backend and simply copy
|
||||
$(TOPOBJDIR)/dist/bin/greprefs.js: $(TOPOBJDIR)/modules/libpref/greprefs.js
|
||||
$(TOPOBJDIR)/dist/bin/platform.ini: $(TOPOBJDIR)/toolkit/xre/platform.ini
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
# 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/.
|
||||
|
||||
import configobj, sys
|
||||
import configobj
|
||||
import sys
|
||||
import re
|
||||
from StringIO import StringIO
|
||||
|
||||
try:
|
||||
(file, section, key) = sys.argv[1:]
|
||||
|
@ -10,7 +13,10 @@ except ValueError:
|
|||
print "Usage: printconfigsetting.py <file> <section> <setting>"
|
||||
sys.exit(1)
|
||||
|
||||
c = configobj.ConfigObj(file)
|
||||
with open(file) as fh:
|
||||
content = re.sub('^\s*;', '#', fh.read(), flags=re.M)
|
||||
|
||||
c = configobj.ConfigObj(StringIO(content))
|
||||
|
||||
try:
|
||||
s = c[section]
|
||||
|
|
|
@ -107,8 +107,7 @@ function removeTab(aTab, aWindow) {
|
|||
let targetWindow = aWindow || window;
|
||||
let targetBrowser = targetWindow.gBrowser;
|
||||
|
||||
// browser_net_pane-toggle.js relies on synchronous removeTab behavior.
|
||||
targetBrowser.removeTab(aTab, {skipPermitUnload: true});
|
||||
targetBrowser.removeTab(aTab);
|
||||
}
|
||||
|
||||
function waitForNavigation(aTarget) {
|
||||
|
|
|
@ -28,8 +28,8 @@ function runCodeMirrorTest(browser) {
|
|||
'function check() { ' +
|
||||
' var doc = content.document; var out = doc.getElementById("status"); ' +
|
||||
' if (!out || !out.classList.contains("done")) { return setTimeout(check, 100); }' +
|
||||
' sendAsyncMessage("done", { failed: content.wrappedJSObject.failed });' +
|
||||
' sendSyncMessage("done", { failed: content.wrappedJSObject.failed });' +
|
||||
'}' +
|
||||
'check();'
|
||||
, true);
|
||||
}
|
||||
}
|
|
@ -5004,6 +5004,7 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
|
|||
case NS_ERROR_CLIENT_REQUEST_OPAQUE_INTERCEPTION:
|
||||
case NS_ERROR_BAD_OPAQUE_REDIRECT_INTERCEPTION:
|
||||
case NS_ERROR_INTERCEPTION_CANCELED:
|
||||
case NS_ERROR_REJECTED_RESPONSE_INTERCEPTION:
|
||||
// ServiceWorker intercepted request, but something went wrong.
|
||||
nsContentUtils::MaybeReportInterceptionErrorToConsole(GetDocument(),
|
||||
aError);
|
||||
|
@ -7669,6 +7670,7 @@ nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
|
|||
aStatus == NS_ERROR_INTERCEPTED_USED_RESPONSE ||
|
||||
aStatus == NS_ERROR_CLIENT_REQUEST_OPAQUE_INTERCEPTION ||
|
||||
aStatus == NS_ERROR_INTERCEPTION_CANCELED ||
|
||||
aStatus == NS_ERROR_REJECTED_RESPONSE_INTERCEPTION ||
|
||||
NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY) {
|
||||
// Errors to be shown for any frame
|
||||
DisplayLoadError(aStatus, url, nullptr, aChannel);
|
||||
|
@ -7772,7 +7774,7 @@ nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
|
|||
mTiming->NotifyBeforeUnload();
|
||||
|
||||
bool okToUnload;
|
||||
rv = mContentViewer->PermitUnload(&okToUnload);
|
||||
rv = mContentViewer->PermitUnload(false, &okToUnload);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !okToUnload) {
|
||||
// The user chose not to unload the page, interrupt the load.
|
||||
|
@ -10111,7 +10113,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
|||
// protocol handler deals with this for javascript: URLs.
|
||||
if (!isJavaScript && aFileName.IsVoid() && mContentViewer) {
|
||||
bool okToUnload;
|
||||
rv = mContentViewer->PermitUnload(&okToUnload);
|
||||
rv = mContentViewer->PermitUnload(false, &okToUnload);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !okToUnload) {
|
||||
// The user chose not to unload the page, interrupt the
|
||||
|
|
|
@ -31,7 +31,7 @@ class nsDOMNavigationTiming;
|
|||
[ptr] native nsDOMNavigationTimingPtr(nsDOMNavigationTiming);
|
||||
[ref] native nsIContentViewerTArray(nsTArray<nsCOMPtr<nsIContentViewer> >);
|
||||
|
||||
[scriptable, builtinclass, uuid(91b6c1f3-fc5f-43a9-88f4-9286bd19387f)]
|
||||
[scriptable, builtinclass, uuid(702e0a92-7d63-490e-b5ee-d247e6bd4588)]
|
||||
interface nsIContentViewer : nsISupports
|
||||
{
|
||||
|
||||
|
@ -46,8 +46,12 @@ interface nsIContentViewer : nsISupports
|
|||
/**
|
||||
* Checks if the document wants to prevent unloading by firing beforeunload on
|
||||
* the document, and if it does, prompts the user. The result is returned.
|
||||
*
|
||||
* @param aCallerClosesWindow indicates that the current caller will close the
|
||||
* window. If the method returns true, all subsequent calls will be
|
||||
* ignored.
|
||||
*/
|
||||
boolean permitUnload();
|
||||
boolean permitUnload([optional] in boolean aCallerClosesWindow);
|
||||
|
||||
/**
|
||||
* Exposes whether we're blocked in a call to permitUnload.
|
||||
|
@ -59,7 +63,8 @@ interface nsIContentViewer : nsISupports
|
|||
* track of whether the user has responded to a prompt.
|
||||
* Used internally by the scriptable version to ensure we only prompt once.
|
||||
*/
|
||||
[noscript,nostdcall] boolean permitUnloadInternal(inout boolean aShouldPrompt);
|
||||
[noscript,nostdcall] boolean permitUnloadInternal(in boolean aCallerClosesWindow,
|
||||
inout boolean aShouldPrompt);
|
||||
|
||||
/**
|
||||
* Exposes whether we're in the process of firing the beforeunload event.
|
||||
|
@ -67,6 +72,16 @@ interface nsIContentViewer : nsISupports
|
|||
*/
|
||||
readonly attribute boolean beforeUnloadFiring;
|
||||
|
||||
/**
|
||||
* Works in tandem with permitUnload, if the caller decides not to close the
|
||||
* window it indicated it will, it is the caller's responsibility to reset
|
||||
* that with this method.
|
||||
*
|
||||
* @Note this method is only meant to be called on documents for which the
|
||||
* caller has indicated that it will close the window. If that is not the case
|
||||
* the behavior of this method is undefined.
|
||||
*/
|
||||
void resetCloseWindow();
|
||||
void pageHide(in boolean isUnload);
|
||||
|
||||
/**
|
||||
|
|
|
@ -103,6 +103,7 @@ skip-if = e10s
|
|||
skip-if = e10s # Bug ?????? - event handler checks event.target is the content document and test e10s-utils doesn't do that.
|
||||
[browser_multiple_pushState.js]
|
||||
[browser_onbeforeunload_navigation.js]
|
||||
skip-if = e10s
|
||||
[browser_search_notification.js]
|
||||
[browser_timelineMarkers-01.js]
|
||||
[browser_timelineMarkers-02.js]
|
||||
|
|
|
@ -10,7 +10,6 @@ SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunlo
|
|||
|
||||
var loadExpected = TEST_PAGE;
|
||||
var testTab;
|
||||
var testsLength;
|
||||
|
||||
var loadStarted = false;
|
||||
var tabStateListener = {
|
||||
|
@ -41,10 +40,6 @@ function onTabLoaded(event) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!testsLength) {
|
||||
testsLength = testTab.linkedBrowser.contentWindow.wrappedJSObject.testFns.length;
|
||||
}
|
||||
|
||||
is(loadedPage, loadExpected, "Loaded the expected page");
|
||||
if (contentWindow) {
|
||||
is(contentWindow.document, event.target, "Same doc");
|
||||
|
@ -107,9 +102,47 @@ function onTabModalDialogLoaded(node) {
|
|||
// Listen for the dialog being created
|
||||
Services.obs.addObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded", false);
|
||||
|
||||
var testFns = [
|
||||
function(e) {
|
||||
e.target.location.href = 'otherpage-href-set.html';
|
||||
return "stop";
|
||||
},
|
||||
function(e) {
|
||||
e.target.location.reload();
|
||||
return "stop";
|
||||
},
|
||||
function(e) {
|
||||
e.target.location.replace('otherpage-location-replaced.html');
|
||||
return "stop";
|
||||
},
|
||||
function(e) {
|
||||
var link = e.target.createElement('a');
|
||||
link.href = "otherpage.html";
|
||||
e.target.body.appendChild(link);
|
||||
link.click();
|
||||
return "stop";
|
||||
},
|
||||
function(e) {
|
||||
var link = e.target.createElement('a');
|
||||
link.href = "otherpage.html";
|
||||
link.setAttribute("target", "_blank");
|
||||
e.target.body.appendChild(link);
|
||||
link.click();
|
||||
return "stop";
|
||||
},
|
||||
function(e) {
|
||||
var link = e.target.createElement('a');
|
||||
link.href = e.target.location.href;
|
||||
e.target.body.appendChild(link);
|
||||
link.setAttribute("target", "somearbitrarywindow");
|
||||
link.click();
|
||||
return "stop";
|
||||
},
|
||||
];
|
||||
|
||||
function runNextTest() {
|
||||
currentTest++;
|
||||
if (currentTest >= testsLength) {
|
||||
if (currentTest >= testFns.length) {
|
||||
if (!stayingOnPage) {
|
||||
finish();
|
||||
return;
|
||||
|
@ -138,10 +171,10 @@ function runCurrentTest() {
|
|||
contentWindow.dialogWasInvoked = false;
|
||||
originalLocation = contentWindow.location.href;
|
||||
// And run this test:
|
||||
info("Running test with onbeforeunload " + contentWindow.wrappedJSObject.testFns[currentTest].toSource());
|
||||
contentWindow.onbeforeunload = contentWindow.wrappedJSObject.testFns[currentTest];
|
||||
info("Running test with onbeforeunload " + testFns[currentTest].toSource());
|
||||
contentWindow.onbeforeunload = testFns[currentTest];
|
||||
loadStarted = false;
|
||||
testTab.linkedBrowser.loadURI(TARGETED_PAGE);
|
||||
contentWindow.location.href = TARGETED_PAGE;
|
||||
}
|
||||
|
||||
var onAfterPageLoad = runNextTest;
|
||||
|
|
|
@ -7,44 +7,4 @@
|
|||
<body>
|
||||
Waiting for onbeforeunload to hit...
|
||||
</body>
|
||||
|
||||
<script>
|
||||
var testFns = [
|
||||
function(e) {
|
||||
e.target.location.href = 'otherpage-href-set.html';
|
||||
return "stop";
|
||||
},
|
||||
function(e) {
|
||||
e.target.location.reload();
|
||||
return "stop";
|
||||
},
|
||||
function(e) {
|
||||
e.target.location.replace('otherpage-location-replaced.html');
|
||||
return "stop";
|
||||
},
|
||||
function(e) {
|
||||
var link = e.target.createElement('a');
|
||||
link.href = "otherpage.html";
|
||||
e.target.body.appendChild(link);
|
||||
link.click();
|
||||
return "stop";
|
||||
},
|
||||
function(e) {
|
||||
var link = e.target.createElement('a');
|
||||
link.href = "otherpage.html";
|
||||
link.setAttribute("target", "_blank");
|
||||
e.target.body.appendChild(link);
|
||||
link.click();
|
||||
return "stop";
|
||||
},
|
||||
function(e) {
|
||||
var link = e.target.createElement('a');
|
||||
link.href = e.target.location.href;
|
||||
e.target.body.appendChild(link);
|
||||
link.setAttribute("target", "somearbitrarywindow");
|
||||
link.click();
|
||||
return "stop";
|
||||
},
|
||||
];
|
||||
</script>
|
||||
</html>
|
||||
|
|
|
@ -31,8 +31,8 @@ function makeTimelineTest(frameScriptName, url) {
|
|||
info(message.data.message);
|
||||
});
|
||||
mm.addMessageListener("browser:test:finish", function(ignore) {
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ AudioChannelAgent::AudioChannelAgent()
|
|||
: mAudioChannelType(AUDIO_AGENT_CHANNEL_ERROR)
|
||||
, mInnerWindowID(0)
|
||||
, mIsRegToService(false)
|
||||
, mNotifyPlayback(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -49,7 +50,7 @@ void
|
|||
AudioChannelAgent::Shutdown()
|
||||
{
|
||||
if (mIsRegToService) {
|
||||
NotifyStoppedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY);
|
||||
NotifyStoppedPlaying();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,11 +163,12 @@ NS_IMETHODIMP AudioChannelAgent::NotifyStartedPlaying(uint32_t aNotifyPlayback,
|
|||
|
||||
service->GetState(mWindow, mAudioChannelType, aVolume, aMuted);
|
||||
|
||||
mNotifyPlayback = aNotifyPlayback;
|
||||
mIsRegToService = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP AudioChannelAgent::NotifyStoppedPlaying(uint32_t aNotifyPlayback)
|
||||
NS_IMETHODIMP AudioChannelAgent::NotifyStoppedPlaying()
|
||||
{
|
||||
if (mAudioChannelType == AUDIO_AGENT_CHANNEL_ERROR ||
|
||||
!mIsRegToService) {
|
||||
|
@ -174,7 +176,7 @@ NS_IMETHODIMP AudioChannelAgent::NotifyStoppedPlaying(uint32_t aNotifyPlayback)
|
|||
}
|
||||
|
||||
nsRefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
|
||||
service->UnregisterAudioChannelAgent(this, aNotifyPlayback);
|
||||
service->UnregisterAudioChannelAgent(this, mNotifyPlayback);
|
||||
mIsRegToService = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ private:
|
|||
int32_t mAudioChannelType;
|
||||
uint64_t mInnerWindowID;
|
||||
bool mIsRegToService;
|
||||
bool mNotifyPlayback;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -34,7 +34,7 @@ interface nsIAudioChannelAgentCallback : nsISupports
|
|||
* 1. Changes to the playable status of this channel.
|
||||
*/
|
||||
|
||||
[uuid(62e0037c-9786-4b79-b986-27111f6e553b)]
|
||||
[uuid(18222148-1b32-463d-b050-b741f43a07ba)]
|
||||
interface nsIAudioChannelAgent : nsISupports
|
||||
{
|
||||
const long AUDIO_AGENT_CHANNEL_NORMAL = 0;
|
||||
|
@ -118,14 +118,10 @@ interface nsIAudioChannelAgent : nsISupports
|
|||
/**
|
||||
* Notify the agent we no longer want to play.
|
||||
*
|
||||
* @param notifyPlaying
|
||||
* Whether to send audio-playback notifications, one of AUDIO_CHANNEL_NOTIFY
|
||||
* or AUDIO_CHANNEL_DONT_NOTIFY.
|
||||
*
|
||||
* Note : even if notifyStartedPlaying() returned false, the agent would
|
||||
* still be registered with the audio channel service and receive callbacks
|
||||
* for status changes. So notifyStoppedPlaying must still eventually be
|
||||
* called to unregister the agent with the channel service.
|
||||
*/
|
||||
void notifyStoppedPlaying(in unsigned long notifyPlayback);
|
||||
void notifyStoppedPlaying();
|
||||
};
|
||||
|
|
|
@ -383,8 +383,7 @@ StructuredCloneHolder::FreeBuffer(uint64_t* aBuffer,
|
|||
/* static */ JSObject*
|
||||
StructuredCloneHolder::ReadFullySerializableObjects(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32_t aTag,
|
||||
uint32_t aIndex)
|
||||
uint32_t aTag)
|
||||
{
|
||||
if (aTag == SCTAG_DOM_IMAGEDATA) {
|
||||
return ReadStructuredCloneImageData(aCx, aReader);
|
||||
|
@ -928,7 +927,7 @@ StructuredCloneHolder::CustomReadHandler(JSContext* aCx,
|
|||
parent, GetImages(), aIndex);
|
||||
}
|
||||
|
||||
return ReadFullySerializableObjects(aCx, aReader, aTag, aIndex);
|
||||
return ReadFullySerializableObjects(aCx, aReader, aTag);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -254,8 +254,7 @@ public:
|
|||
|
||||
static JSObject* ReadFullySerializableObjects(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32_t aTag,
|
||||
uint32_t aIndex);
|
||||
uint32_t aTag);
|
||||
|
||||
static bool WriteFullySerializableObjects(JSContext* aCx,
|
||||
JSStructuredCloneWriter* aWriter,
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "TabParent.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/HTMLAreaElement.h"
|
||||
#include "nsVariant.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
|
@ -726,11 +727,9 @@ DragDataProducer::AddString(DataTransfer* aDataTransfer,
|
|||
const nsAString& aData,
|
||||
nsIPrincipal* aPrincipal)
|
||||
{
|
||||
nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
|
||||
if (variant) {
|
||||
variant->SetAsAString(aData);
|
||||
aDataTransfer->SetDataWithPrincipal(aFlavor, variant, 0, aPrincipal);
|
||||
}
|
||||
nsRefPtr<nsVariant> variant = new nsVariant();
|
||||
variant->SetAsAString(aData);
|
||||
aDataTransfer->SetDataWithPrincipal(aFlavor, variant, 0, aPrincipal);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -784,12 +783,10 @@ DragDataProducer::AddStringsToDataTransfer(nsIContent* aDragNode,
|
|||
// a new flavor so as not to confuse anyone who is really registered
|
||||
// for image/gif or image/jpg.
|
||||
if (mImage) {
|
||||
nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
|
||||
if (variant) {
|
||||
variant->SetAsISupports(mImage);
|
||||
aDataTransfer->SetDataWithPrincipal(NS_LITERAL_STRING(kNativeImageMime),
|
||||
variant, 0, principal);
|
||||
}
|
||||
nsRefPtr<nsVariant> variant = new nsVariant();
|
||||
variant->SetAsISupports(mImage);
|
||||
aDataTransfer->SetDataWithPrincipal(NS_LITERAL_STRING(kNativeImageMime),
|
||||
variant, 0, principal);
|
||||
|
||||
// assume the image comes from a file, and add a file promise. We
|
||||
// register ourselves as a nsIFlavorDataProvider, and will use the
|
||||
|
@ -798,12 +795,10 @@ DragDataProducer::AddStringsToDataTransfer(nsIContent* aDragNode,
|
|||
nsCOMPtr<nsIFlavorDataProvider> dataProvider =
|
||||
new nsContentAreaDragDropDataProvider();
|
||||
if (dataProvider) {
|
||||
nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
|
||||
if (variant) {
|
||||
variant->SetAsISupports(dataProvider);
|
||||
aDataTransfer->SetDataWithPrincipal(NS_LITERAL_STRING(kFilePromiseMime),
|
||||
variant, 0, principal);
|
||||
}
|
||||
nsRefPtr<nsVariant> variant = new nsVariant();
|
||||
variant->SetAsISupports(dataProvider);
|
||||
aDataTransfer->SetDataWithPrincipal(NS_LITERAL_STRING(kFilePromiseMime),
|
||||
variant, 0, principal);
|
||||
}
|
||||
|
||||
AddString(aDataTransfer, NS_LITERAL_STRING(kFilePromiseURLMime),
|
||||
|
|
|
@ -3494,6 +3494,8 @@ nsContentUtils::MaybeReportInterceptionErrorToConsole(nsIDocument* aDocument,
|
|||
messageName = "BadOpaqueRedirectInterception";
|
||||
} else if (aError == NS_ERROR_INTERCEPTION_CANCELED) {
|
||||
messageName = "InterceptionCanceled";
|
||||
} else if (aError == NS_ERROR_REJECTED_RESPONSE_INTERCEPTION) {
|
||||
messageName = "InterceptionRejectedResponse";
|
||||
}
|
||||
|
||||
if (messageName) {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "mozilla/AutoRestore.h"
|
||||
#include "mozilla/BinarySearch.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/IntegerRange.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include <algorithm>
|
||||
|
@ -154,6 +155,7 @@
|
|||
#include "nsHtml5TreeOpExecutor.h"
|
||||
#include "mozilla/dom/HTMLLinkElement.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "mozilla/dom/HTMLIFrameElement.h"
|
||||
#include "mozilla/dom/HTMLImageElement.h"
|
||||
#include "mozilla/dom/MediaSource.h"
|
||||
|
||||
|
@ -11224,15 +11226,39 @@ nsDocument::RestorePreviousFullScreenState()
|
|||
return;
|
||||
}
|
||||
|
||||
// Check whether we are restoring to non-fullscreen state.
|
||||
bool exitingFullscreen = true;
|
||||
for (nsIDocument* doc = this; doc; doc = doc->GetParentDocument()) {
|
||||
if (static_cast<nsDocument*>(doc)->mFullScreenStack.Length() > 1) {
|
||||
exitingFullscreen = false;
|
||||
nsCOMPtr<nsIDocument> fullScreenDoc = GetFullscreenLeaf(this);
|
||||
nsAutoTArray<nsDocument*, 8> exitDocs;
|
||||
|
||||
nsIDocument* doc = fullScreenDoc;
|
||||
// Collect all subdocuments.
|
||||
for (; doc != this; doc = doc->GetParentDocument()) {
|
||||
exitDocs.AppendElement(static_cast<nsDocument*>(doc));
|
||||
}
|
||||
MOZ_ASSERT(doc == this, "Must have reached this doc");
|
||||
// Collect all ancestor documents which we are going to change.
|
||||
for (; doc; doc = doc->GetParentDocument()) {
|
||||
nsDocument* theDoc = static_cast<nsDocument*>(doc);
|
||||
MOZ_ASSERT(!theDoc->mFullScreenStack.IsEmpty(),
|
||||
"Ancestor of fullscreen document must also be in fullscreen");
|
||||
if (doc != this) {
|
||||
Element* top = theDoc->FullScreenStackTop();
|
||||
if (top->IsHTMLElement(nsGkAtoms::iframe)) {
|
||||
if (static_cast<HTMLIFrameElement*>(top)->FullscreenFlag()) {
|
||||
// If this is an iframe, and it explicitly requested
|
||||
// fullscreen, don't rollback it automatically.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
exitDocs.AppendElement(theDoc);
|
||||
if (theDoc->mFullScreenStack.Length() > 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (exitingFullscreen) {
|
||||
|
||||
nsDocument* lastDoc = exitDocs.LastElement();
|
||||
if (!lastDoc->GetParentDocument() &&
|
||||
lastDoc->mFullScreenStack.Length() == 1) {
|
||||
// If we are fully exiting fullscreen, don't touch anything here,
|
||||
// just wait for the window to get out from fullscreen first.
|
||||
AskWindowToExitFullscreen(this);
|
||||
|
@ -11241,50 +11267,39 @@ nsDocument::RestorePreviousFullScreenState()
|
|||
|
||||
// If fullscreen mode is updated the pointer should be unlocked
|
||||
UnlockPointer();
|
||||
|
||||
nsCOMPtr<nsIDocument> fullScreenDoc = GetFullscreenLeaf(this);
|
||||
|
||||
// Clear full-screen stacks in all descendant in process documents, bottom up.
|
||||
nsIDocument* doc = fullScreenDoc;
|
||||
while (doc != this) {
|
||||
NS_ASSERTION(doc->IsFullScreenDoc(), "Should be full-screen doc");
|
||||
static_cast<nsDocument*>(doc)->CleanupFullscreenState();
|
||||
DispatchFullScreenChange(doc);
|
||||
doc = doc->GetParentDocument();
|
||||
// All documents listed in the array except the last one are going to
|
||||
// completely exit from the fullscreen state.
|
||||
for (auto i : MakeRange(exitDocs.Length() - 1)) {
|
||||
exitDocs[i]->CleanupFullscreenState();
|
||||
}
|
||||
// The last document will either rollback one fullscreen element, or
|
||||
// completely exit from the fullscreen state as well.
|
||||
nsIDocument* newFullscreenDoc;
|
||||
if (lastDoc->mFullScreenStack.Length() > 1) {
|
||||
lastDoc->FullScreenStackPop();
|
||||
newFullscreenDoc = lastDoc;
|
||||
} else {
|
||||
lastDoc->CleanupFullscreenState();
|
||||
newFullscreenDoc = lastDoc->GetParentDocument();
|
||||
}
|
||||
// Dispatch the fullscreenchange event to all document listed.
|
||||
for (nsDocument* d : exitDocs) {
|
||||
DispatchFullScreenChange(d);
|
||||
}
|
||||
|
||||
// Roll-back full-screen state to previous full-screen element.
|
||||
NS_ASSERTION(doc == this, "Must have reached this doc.");
|
||||
while (doc != nullptr) {
|
||||
static_cast<nsDocument*>(doc)->FullScreenStackPop();
|
||||
DispatchFullScreenChange(doc);
|
||||
if (static_cast<nsDocument*>(doc)->mFullScreenStack.IsEmpty()) {
|
||||
// Full-screen stack in document is empty. Go back up to the parent
|
||||
// document. We'll pop the containing element off its stack, and use
|
||||
// its next full-screen element as the full-screen element.
|
||||
static_cast<nsDocument*>(doc)->CleanupFullscreenState();
|
||||
doc = doc->GetParentDocument();
|
||||
} else {
|
||||
// Else we popped the top of the stack, and there's still another
|
||||
// element in there, so that will become the full-screen element.
|
||||
if (fullScreenDoc != doc) {
|
||||
// We've popped so enough off the stack that we've rolled back to
|
||||
// a fullscreen element in a parent document. If this document isn't
|
||||
// approved for fullscreen, or if it's cross origin, dispatch an
|
||||
// event to chrome so it knows to show the authorization/warning UI.
|
||||
if (!nsContentUtils::HaveEqualPrincipals(fullScreenDoc, doc)) {
|
||||
DispatchCustomEventWithFlush(
|
||||
doc, NS_LITERAL_STRING("MozDOMFullscreen:NewOrigin"),
|
||||
/* Bubbles */ true, /* ChromeOnly */ true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
MOZ_ASSERT(newFullscreenDoc, "If we were going to exit from fullscreen on "
|
||||
"all documents in this doctree, we should've asked the window to "
|
||||
"exit first instead of reaching here.");
|
||||
if (fullScreenDoc != newFullscreenDoc &&
|
||||
!nsContentUtils::HaveEqualPrincipals(fullScreenDoc, newFullscreenDoc)) {
|
||||
// We've popped so enough off the stack that we've rolled back to
|
||||
// a fullscreen element in a parent document. If this document is
|
||||
// cross origin, dispatch an event to chrome so it knows to show
|
||||
// the warning UI.
|
||||
DispatchCustomEventWithFlush(
|
||||
newFullscreenDoc, NS_LITERAL_STRING("MozDOMFullscreen:NewOrigin"),
|
||||
/* Bubbles */ true, /* ChromeOnly */ true);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(doc, "If we were going to exit from fullscreen on all documents "
|
||||
"in this doctree, we should've asked the window to exit first "
|
||||
"instead of reaching here.");
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -11350,6 +11365,19 @@ UpdateViewportScrollbarOverrideForFullscreen(nsIDocument* aDoc)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ClearFullscreenStateOnElement(Element* aElement)
|
||||
{
|
||||
// Remove any VR state properties
|
||||
aElement->DeleteProperty(nsGkAtoms::vr_state);
|
||||
// Remove styles from existing top element.
|
||||
EventStateManager::SetFullScreenState(aElement, false);
|
||||
// Reset iframe fullscreen flag.
|
||||
if (aElement->IsHTMLElement(nsGkAtoms::iframe)) {
|
||||
static_cast<HTMLIFrameElement*>(aElement)->SetFullscreenFlag(false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::CleanupFullscreenState()
|
||||
{
|
||||
|
@ -11362,9 +11390,7 @@ nsDocument::CleanupFullscreenState()
|
|||
// after bug 1195213.
|
||||
for (nsWeakPtr& weakPtr : Reversed(mFullScreenStack)) {
|
||||
if (nsCOMPtr<Element> element = do_QueryReferent(weakPtr)) {
|
||||
// Remove any VR state properties
|
||||
element->DeleteProperty(nsGkAtoms::vr_state);
|
||||
EventStateManager::SetFullScreenState(element, false);
|
||||
ClearFullscreenStateOnElement(element);
|
||||
}
|
||||
}
|
||||
mFullScreenStack.Clear();
|
||||
|
@ -11394,13 +11420,7 @@ nsDocument::FullScreenStackPop()
|
|||
return;
|
||||
}
|
||||
|
||||
Element* top = FullScreenStackTop();
|
||||
|
||||
// Remove any VR state properties
|
||||
top->DeleteProperty(nsGkAtoms::vr_state);
|
||||
|
||||
// Remove styles from existing top element.
|
||||
EventStateManager::SetFullScreenState(top, false);
|
||||
ClearFullscreenStateOnElement(FullScreenStackTop());
|
||||
|
||||
// Remove top element. Note the remaining top element in the stack
|
||||
// will not have full-screen style bits set, so we will need to restore
|
||||
|
@ -11848,6 +11868,10 @@ nsDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
|
|||
// in this document.
|
||||
DebugOnly<bool> x = FullScreenStackPush(elem);
|
||||
NS_ASSERTION(x, "Full-screen state of requesting doc should always change!");
|
||||
// Set the iframe fullscreen flag.
|
||||
if (elem->IsHTMLElement(nsGkAtoms::iframe)) {
|
||||
static_cast<HTMLIFrameElement*>(elem)->SetFullscreenFlag(true);
|
||||
}
|
||||
changed.AppendElement(this);
|
||||
|
||||
// Propagate up the document hierarchy, setting the full-screen element as
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "WindowNamedPropertiesHandler.h"
|
||||
#include "nsFrameSelection.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsVariant.h"
|
||||
|
||||
// Helper Classes
|
||||
#include "nsJSUtils.h"
|
||||
|
@ -559,6 +560,27 @@ nsTimeout::HasRefCntOne()
|
|||
return mRefCnt.get() == 1;
|
||||
}
|
||||
|
||||
static already_AddRefed<nsIVariant>
|
||||
CreateVoidVariant()
|
||||
{
|
||||
nsRefPtr<nsVariant> writable = new nsVariant();
|
||||
writable->SetAsVoid();
|
||||
return writable.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
DialogValueHolder::Get(nsIPrincipal* aSubject, nsIVariant** aResult)
|
||||
{
|
||||
nsCOMPtr<nsIVariant> result;
|
||||
if (aSubject->SubsumesConsideringDomain(mOrigin)) {
|
||||
result = mValue;
|
||||
} else {
|
||||
result = CreateVoidVariant();
|
||||
}
|
||||
result.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
extern uint64_t
|
||||
|
@ -8752,17 +8774,6 @@ nsGlobalWindow::CanClose()
|
|||
{
|
||||
MOZ_ASSERT(IsOuterWindow());
|
||||
|
||||
if (mIsChrome) {
|
||||
nsCOMPtr<nsIBrowserDOMWindow> bwin;
|
||||
nsIDOMChromeWindow* chromeWin = static_cast<nsGlobalChromeWindow*>(this);
|
||||
chromeWin->GetBrowserDOMWindow(getter_AddRefs(bwin));
|
||||
|
||||
bool canClose = true;
|
||||
if (bwin && NS_SUCCEEDED(bwin->CanClose(&canClose))) {
|
||||
return canClose;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mDocShell) {
|
||||
return true;
|
||||
}
|
||||
|
@ -8776,7 +8787,7 @@ nsGlobalWindow::CanClose()
|
|||
mDocShell->GetContentViewer(getter_AddRefs(cv));
|
||||
if (cv) {
|
||||
bool canClose;
|
||||
nsresult rv = cv->PermitUnload(&canClose);
|
||||
nsresult rv = cv->PermitUnload(false, &canClose);
|
||||
if (NS_SUCCEEDED(rv) && !canClose)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -241,15 +241,6 @@ struct IdleObserverHolder
|
|||
}
|
||||
};
|
||||
|
||||
static inline already_AddRefed<nsIVariant>
|
||||
CreateVoidVariant()
|
||||
{
|
||||
nsCOMPtr<nsIWritableVariant> writable =
|
||||
do_CreateInstance(NS_VARIANT_CONTRACTID);
|
||||
writable->SetAsVoid();
|
||||
return writable.forget();
|
||||
}
|
||||
|
||||
// Helper class to manage modal dialog arguments and all their quirks.
|
||||
//
|
||||
// Given our clunky embedding APIs, modal dialog arguments need to be passed
|
||||
|
@ -271,17 +262,7 @@ public:
|
|||
DialogValueHolder(nsIPrincipal* aSubject, nsIVariant* aValue)
|
||||
: mOrigin(aSubject)
|
||||
, mValue(aValue) {}
|
||||
nsresult Get(nsIPrincipal* aSubject, nsIVariant** aResult)
|
||||
{
|
||||
nsCOMPtr<nsIVariant> result;
|
||||
if (aSubject->SubsumesConsideringDomain(mOrigin)) {
|
||||
result = mValue;
|
||||
} else {
|
||||
result = CreateVoidVariant();
|
||||
}
|
||||
result.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult Get(nsIPrincipal* aSubject, nsIVariant** aResult);
|
||||
void Get(JSContext* aCx, JS::Handle<JSObject*> aScope, nsIPrincipal* aSubject,
|
||||
JS::MutableHandle<JS::Value> aResult, mozilla::ErrorResult& aError)
|
||||
{
|
||||
|
|
|
@ -1876,6 +1876,50 @@ bool IsAllowedAsChild(nsIContent* aNewChild, nsINode* aParent,
|
|||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nsINode::EnsurePreInsertionValidity(nsINode& aNewChild, nsINode* aRefChild,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
EnsurePreInsertionValidity1(aNewChild, aRefChild, aError);
|
||||
if (aError.Failed()) {
|
||||
return;
|
||||
}
|
||||
EnsurePreInsertionValidity2(false, aNewChild, aRefChild, aError);
|
||||
}
|
||||
|
||||
void
|
||||
nsINode::EnsurePreInsertionValidity1(nsINode& aNewChild, nsINode* aRefChild,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
if ((!IsNodeOfType(eDOCUMENT) &&
|
||||
!IsNodeOfType(eDOCUMENT_FRAGMENT) &&
|
||||
!IsElement()) ||
|
||||
!aNewChild.IsNodeOfType(eCONTENT)) {
|
||||
aError.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsINode::EnsurePreInsertionValidity2(bool aReplace, nsINode& aNewChild,
|
||||
nsINode* aRefChild, ErrorResult& aError)
|
||||
{
|
||||
nsIContent* newContent = aNewChild.AsContent();
|
||||
if (newContent->IsRootOfAnonymousSubtree()) {
|
||||
// This is anonymous content. Don't allow its insertion
|
||||
// anywhere, since it might have UnbindFromTree calls coming
|
||||
// its way.
|
||||
aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure that the inserted node is allowed as a child of its new parent.
|
||||
if (!IsAllowedAsChild(newContent, this, aReplace, aRefChild)) {
|
||||
aError.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nsINode*
|
||||
nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
||||
nsINode* aRefChild, ErrorResult& aError)
|
||||
|
@ -1887,11 +1931,8 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
|||
// the bad XBL cases.
|
||||
MOZ_ASSERT_IF(aReplace, aRefChild);
|
||||
|
||||
if ((!IsNodeOfType(eDOCUMENT) &&
|
||||
!IsNodeOfType(eDOCUMENT_FRAGMENT) &&
|
||||
!IsElement()) ||
|
||||
!aNewChild->IsNodeOfType(eCONTENT)) {
|
||||
aError.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
|
||||
EnsurePreInsertionValidity1(*aNewChild, aRefChild, aError);
|
||||
if (aError.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1939,19 +1980,8 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
|||
}
|
||||
}
|
||||
|
||||
nsIDocument* doc = OwnerDoc();
|
||||
nsIContent* newContent = static_cast<nsIContent*>(aNewChild);
|
||||
if (newContent->IsRootOfAnonymousSubtree()) {
|
||||
// This is anonymous content. Don't allow its insertion
|
||||
// anywhere, since it might have UnbindFromTree calls coming
|
||||
// its way.
|
||||
aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Make sure that the inserted node is allowed as a child of its new parent.
|
||||
if (!IsAllowedAsChild(newContent, this, aReplace, aRefChild)) {
|
||||
aError.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR);
|
||||
EnsurePreInsertionValidity2(aReplace, *aNewChild, aRefChild, aError);
|
||||
if (aError.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1971,6 +2001,7 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
|||
Maybe<nsAutoTArray<nsCOMPtr<nsIContent>, 50> > fragChildren;
|
||||
|
||||
// Remove the new child from the old parent if one exists
|
||||
nsIContent* newContent = aNewChild->AsContent();
|
||||
nsCOMPtr<nsINode> oldParent = newContent->GetParentNode();
|
||||
if (oldParent) {
|
||||
int32_t removeIndex = oldParent->IndexOf(newContent);
|
||||
|
@ -2180,6 +2211,7 @@ nsINode::ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
|||
// DocumentType nodes are the only nodes that can have a null
|
||||
// ownerDocument according to the DOM spec, and we need to allow
|
||||
// inserting them w/o calling AdoptNode().
|
||||
nsIDocument* doc = OwnerDoc();
|
||||
if (doc != newContent->OwnerDoc()) {
|
||||
aError = AdoptNodeIntoOwnerDoc(this, aNewChild);
|
||||
if (aError.Failed()) {
|
||||
|
|
|
@ -1735,6 +1735,8 @@ public:
|
|||
// The DOM spec says that when nodeValue is defined to be null "setting it
|
||||
// has no effect", so we don't throw an exception.
|
||||
}
|
||||
void EnsurePreInsertionValidity(nsINode& aNewChild, nsINode* aRefChild,
|
||||
mozilla::ErrorResult& aError);
|
||||
nsINode* InsertBefore(nsINode& aNode, nsINode* aChild,
|
||||
mozilla::ErrorResult& aError)
|
||||
{
|
||||
|
@ -1884,6 +1886,11 @@ protected:
|
|||
nsresult CompareDocumentPosition(nsIDOMNode* aOther,
|
||||
uint16_t* aReturn);
|
||||
|
||||
void EnsurePreInsertionValidity1(nsINode& aNewChild, nsINode* aRefChild,
|
||||
mozilla::ErrorResult& aError);
|
||||
void EnsurePreInsertionValidity2(bool aReplace, nsINode& aNewChild,
|
||||
nsINode* aRefChild,
|
||||
mozilla::ErrorResult& aError);
|
||||
nsresult ReplaceOrInsertBefore(bool aReplace, nsIDOMNode *aNewChild,
|
||||
nsIDOMNode *aRefChild, nsIDOMNode **aReturn);
|
||||
nsINode* ReplaceOrInsertBefore(bool aReplace, nsINode* aNewChild,
|
||||
|
|
|
@ -2485,6 +2485,12 @@ nsRange::InsertNode(nsINode& aNode, ErrorResult& aRv)
|
|||
return;
|
||||
}
|
||||
|
||||
referenceParentNode->EnsurePreInsertionValidity(aNode, tStartContainer,
|
||||
aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMText> secondPart;
|
||||
aRv = startTextNode->SplitText(tStartOffset, getter_AddRefs(secondPart));
|
||||
if (aRv.Failed()) {
|
||||
|
@ -2505,6 +2511,11 @@ nsRange::InsertNode(nsINode& aNode, ErrorResult& aRv)
|
|||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
tStartContainer->EnsurePreInsertionValidity(aNode, referenceNode, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We might need to update the end to include the new node (bug 433662).
|
||||
|
|
|
@ -1425,16 +1425,9 @@ nsScriptLoader::OnStreamComplete(nsIStreamLoader* aLoader,
|
|||
NS_ASSERTION(request, "null request in stream complete handler");
|
||||
NS_ENSURE_TRUE(request, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel;
|
||||
{
|
||||
nsCOMPtr<nsIRequest> req;
|
||||
aLoader->GetRequest(getter_AddRefs(req));
|
||||
httpChannel = do_QueryInterface(req);
|
||||
} // throw away req, we only need the channel
|
||||
|
||||
nsresult rv = NS_ERROR_SRI_CORRUPT;
|
||||
if (request->mIntegrity.IsEmpty() ||
|
||||
NS_SUCCEEDED(SRICheck::VerifyIntegrity(request->mIntegrity, httpChannel,
|
||||
NS_SUCCEEDED(SRICheck::VerifyIntegrity(request->mIntegrity, aLoader,
|
||||
request->mCORSMode, aStringLen,
|
||||
aString, mDocument))) {
|
||||
rv = PrepareLoadedRequest(request, aLoader, aStatus, aStringLen, aString);
|
||||
|
|
|
@ -851,3 +851,4 @@ skip-if = e10s || os != 'linux' || buildapp != 'browser'
|
|||
[test_explicit_user_agent.html]
|
||||
[test_change_policy.html]
|
||||
skip-if = buildapp == 'b2g' #no ssl support
|
||||
[test_document.all_iteration.html]
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>Test for document.all iteration behavior</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
test(function() {
|
||||
assert_array_equals([...document.all], document.getElementsByTagName("*"));
|
||||
}, "document.all should be iterable");
|
||||
</script>
|
|
@ -2222,7 +2222,14 @@ class MethodDefiner(PropertyDefiner):
|
|||
return (any("@@iterator" in m.aliases for m in methods) or
|
||||
any("@@iterator" == r["name"] for r in regular))
|
||||
|
||||
if (any(m.isGetter() and m.isIndexed() for m in methods)):
|
||||
# Check whether we need to output an @@iterator due to having an indexed
|
||||
# getter. We only do this while outputting non-static and
|
||||
# non-unforgeable methods, since the @@iterator function will be
|
||||
# neither.
|
||||
if (not static and
|
||||
not unforgeable and
|
||||
descriptor.supportsIndexedProperties() and
|
||||
isMaybeExposedIn(descriptor.operations['IndexedGetter'], descriptor)):
|
||||
if hasIterator(methods, self.regular):
|
||||
raise TypeError("Cannot have indexed getter/attr on "
|
||||
"interface %s with other members "
|
||||
|
@ -2820,6 +2827,19 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
chromeProperties=chromeProperties,
|
||||
name='"' + self.descriptor.interface.identifier.name + '"' if needInterfaceObject else "nullptr")
|
||||
|
||||
# If we fail after here, we must clear interface and prototype caches
|
||||
# using this code: intermediate failure must not expose the interface in
|
||||
# partially-constructed state. Note that every case after here needs an
|
||||
# interface prototype object.
|
||||
failureCode = dedent(
|
||||
"""
|
||||
*protoCache = nullptr;
|
||||
if (interfaceCache) {
|
||||
*interfaceCache = nullptr;
|
||||
}
|
||||
return;
|
||||
""")
|
||||
|
||||
aliasedMembers = [m for m in self.descriptor.interface.members if m.isMethod() and m.aliases]
|
||||
if aliasedMembers:
|
||||
assert needInterfacePrototypeObject
|
||||
|
@ -2839,17 +2859,18 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
prop = '"%s"' % alias
|
||||
return CGList([
|
||||
getSymbolJSID,
|
||||
# XXX If we ever create non-enumerate properties that can be
|
||||
# aliased, we should consider making the aliases match
|
||||
# the enumerability of the property being aliased.
|
||||
# XXX If we ever create non-enumerable properties that can
|
||||
# be aliased, we should consider making the aliases
|
||||
# match the enumerability of the property being aliased.
|
||||
CGGeneric(fill(
|
||||
"""
|
||||
if (!${defineFn}(aCx, proto, ${prop}, aliasedVal, JSPROP_ENUMERATE)) {
|
||||
return;
|
||||
$*{failureCode}
|
||||
}
|
||||
""",
|
||||
defineFn=defineFn,
|
||||
prop=prop))
|
||||
prop=prop,
|
||||
failureCode=failureCode))
|
||||
], "\n")
|
||||
|
||||
def defineAliasesFor(m):
|
||||
|
@ -2857,21 +2878,23 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
CGGeneric(fill(
|
||||
"""
|
||||
if (!JS_GetProperty(aCx, proto, \"${prop}\", &aliasedVal)) {
|
||||
return;
|
||||
$*{failureCode}
|
||||
}
|
||||
""",
|
||||
failureCode=failureCode,
|
||||
prop=m.identifier.name))
|
||||
] + [defineAlias(alias) for alias in sorted(m.aliases)])
|
||||
|
||||
defineAliases = CGList([
|
||||
CGGeneric(dedent("""
|
||||
CGGeneric(fill("""
|
||||
// Set up aliases on the interface prototype object we just created.
|
||||
JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx, aGlobal);
|
||||
if (!proto) {
|
||||
return;
|
||||
$*{failureCode}
|
||||
}
|
||||
|
||||
""")),
|
||||
""",
|
||||
failureCode=failureCode)),
|
||||
CGGeneric("JS::Rooted<JS::Value> aliasedVal(aCx);\n\n")
|
||||
] + [defineAliasesFor(m) for m in sorted(aliasedMembers)])
|
||||
else:
|
||||
|
@ -2897,14 +2920,6 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
else:
|
||||
holderClass = "Class.ToJSClass()"
|
||||
holderProto = "*protoCache"
|
||||
failureCode = dedent(
|
||||
"""
|
||||
*protoCache = nullptr;
|
||||
if (interfaceCache) {
|
||||
*interfaceCache = nullptr;
|
||||
}
|
||||
return;
|
||||
""")
|
||||
createUnforgeableHolder = CGGeneric(fill(
|
||||
"""
|
||||
JS::Rooted<JSObject*> unforgeableHolder(aCx);
|
||||
|
|
|
@ -1089,7 +1089,7 @@ nsDOMCameraControl::ReleaseAudioChannelAgent()
|
|||
{
|
||||
#ifdef MOZ_B2G
|
||||
if (mAudioChannelAgent) {
|
||||
mAudioChannelAgent->NotifyStoppedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_DONT_NOTIFY);
|
||||
mAudioChannelAgent->NotifyStoppedPlaying();
|
||||
mAudioChannelAgent = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -823,22 +823,20 @@ DataStoreService::GetDataStores(nsIDOMWindow* aWindow,
|
|||
// window, so we can skip the ipc communication.
|
||||
if (XRE_IsParentProcess()) {
|
||||
uint32_t appId;
|
||||
nsresult rv = principal->GetAppId(&appId);
|
||||
if (NS_FAILED(rv)) {
|
||||
RejectPromise(window, promise, rv);
|
||||
rv = principal->GetAppId(&appId);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
RejectPromise(window, promise, rv.StealNSResult());
|
||||
promise.forget(aDataStores);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = GetDataStoreInfos(aName, aOwner, appId, principal, stores);
|
||||
if (NS_FAILED(rv)) {
|
||||
RejectPromise(window, promise, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
RejectPromise(window, promise, rv.StealNSResult());
|
||||
promise.forget(aDataStores);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
} else {
|
||||
// This method can be called in the child so we need to send a request
|
||||
// to the parent and create DataStore object here.
|
||||
ContentChild* contentChild = ContentChild::GetSingleton();
|
||||
|
@ -971,7 +969,7 @@ DataStoreService::GetDataStoresResolve(nsPIDOMWindow* aWindow,
|
|||
}
|
||||
}
|
||||
|
||||
// Thie method populates 'aStores' with the list of DataStores with 'aName' as
|
||||
// This method populates 'aStores' with the list of DataStores with 'aName' as
|
||||
// name and available for this 'aAppId'.
|
||||
nsresult
|
||||
DataStoreService::GetDataStoreInfos(const nsAString& aName,
|
||||
|
@ -1009,12 +1007,12 @@ DataStoreService::GetDataStoreInfos(const nsAString& aName,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
DataStoreInfo* info = nullptr;
|
||||
if (apps->Get(aAppId, &info) &&
|
||||
(aOwner.IsEmpty() || aOwner.Equals(info->mManifestURL))) {
|
||||
DataStoreInfo* appsInfo = nullptr;
|
||||
if (apps->Get(aAppId, &appsInfo) &&
|
||||
(aOwner.IsEmpty() || aOwner.Equals(appsInfo->mManifestURL))) {
|
||||
DataStoreInfo* owned = aStores.AppendElement();
|
||||
owned->Init(info->mName, info->mOriginURL, info->mManifestURL, false,
|
||||
info->mEnabled);
|
||||
owned->Init(appsInfo->mName, appsInfo->mOriginURL, appsInfo->mManifestURL,
|
||||
false, appsInfo->mEnabled);
|
||||
}
|
||||
|
||||
for (auto iter = apps->ConstIter(); !iter.Done(); iter.Next()) {
|
||||
|
@ -1022,29 +1020,29 @@ DataStoreService::GetDataStoreInfos(const nsAString& aName,
|
|||
continue;
|
||||
}
|
||||
|
||||
DataStoreInfo* info = iter.UserData();
|
||||
MOZ_ASSERT(info);
|
||||
DataStoreInfo* appInfo = iter.UserData();
|
||||
MOZ_ASSERT(appInfo);
|
||||
|
||||
HashApp* app;
|
||||
if (!mAccessStores.Get(aName, &app)) {
|
||||
HashApp* accessApp;
|
||||
if (!mAccessStores.Get(aName, &accessApp)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!aOwner.IsEmpty() &&
|
||||
!aOwner.Equals(info->mManifestURL)) {
|
||||
!aOwner.Equals(appInfo->mManifestURL)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DataStoreInfo* accessInfo = nullptr;
|
||||
if (!app->Get(aAppId, &accessInfo)) {
|
||||
if (!accessApp->Get(aAppId, &accessInfo)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool readOnly = info->mReadOnly || accessInfo->mReadOnly;
|
||||
bool readOnly = appInfo->mReadOnly || accessInfo->mReadOnly;
|
||||
DataStoreInfo* accessStore = aStores.AppendElement();
|
||||
accessStore->Init(aName, info->mOriginURL,
|
||||
info->mManifestURL, readOnly,
|
||||
info->mEnabled);
|
||||
accessStore->Init(aName, appInfo->mOriginURL,
|
||||
appInfo->mManifestURL, readOnly,
|
||||
appInfo->mEnabled);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -45,3 +45,6 @@ MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
|
|||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wshadow']
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "DataTransfer.h"
|
||||
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIVariant.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "mozilla/dom/DOMStringList.h"
|
||||
|
@ -24,6 +23,7 @@
|
|||
#include "nsIScriptContext.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsVariant.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/DataTransferBinding.h"
|
||||
#include "mozilla/dom/Directory.h"
|
||||
|
@ -435,12 +435,7 @@ void
|
|||
DataTransfer::SetData(const nsAString& aFormat, const nsAString& aData,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
|
||||
if (!variant) {
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<nsVariant> variant = new nsVariant();
|
||||
variant->SetAsAString(aData);
|
||||
|
||||
aRv = MozSetDataAt(aFormat, variant, 0);
|
||||
|
@ -1350,9 +1345,7 @@ DataTransfer::FillInExternalData(TransferItem& aItem, uint32_t aIndex)
|
|||
if (!data)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIWritableVariant> variant = do_CreateInstance(NS_VARIANT_CONTRACTID);
|
||||
if (!variant)
|
||||
return;
|
||||
nsRefPtr<nsVariant> variant = new nsVariant();
|
||||
|
||||
nsCOMPtr<nsISupportsString> supportsstr = do_QueryInterface(data);
|
||||
if (supportsstr) {
|
||||
|
|
|
@ -413,19 +413,23 @@ FetchDriver::HttpFetch(bool aCORSFlag, bool aCORSPreflightFlag, bool aAuthentica
|
|||
// if it succeeds, so we need to have everything setup for the original
|
||||
// request too.
|
||||
|
||||
// Step 3.3 "Let credentials flag be set if either request's credentials mode
|
||||
// is include, or request's credentials mode is same-origin and the CORS flag
|
||||
// is unset, and unset otherwise."
|
||||
// Step 3.3 "Let credentials flag be set if one of
|
||||
// - request's credentials mode is "include"
|
||||
// - request's credentials mode is "same-origin" and either the CORS flag
|
||||
// is unset or response tainting is "opaque"
|
||||
// is true, and unset otherwise."
|
||||
bool useCredentials = false;
|
||||
if (mRequest->GetCredentialsMode() == RequestCredentials::Include ||
|
||||
(mRequest->GetCredentialsMode() == RequestCredentials::Same_origin && !aCORSFlag)) {
|
||||
(mRequest->GetCredentialsMode() == RequestCredentials::Same_origin && !aCORSFlag &&
|
||||
mRequest->GetResponseTainting() != InternalRequest::RESPONSETAINT_OPAQUE)) {
|
||||
useCredentials = true;
|
||||
}
|
||||
|
||||
// This is effectivetly the opposite of the use credentials flag in "HTTP
|
||||
// network or cache fetch" in the spec and decides whether to transmit
|
||||
// cookies and other identifying information. LOAD_ANONYMOUS also prevents
|
||||
// new cookies sent by the server from being stored.
|
||||
// new cookies sent by the server from being stored. This value will
|
||||
// propagate across redirects, which is what we want.
|
||||
const nsLoadFlags credentialsFlag = useCredentials ? 0 : nsIRequest::LOAD_ANONYMOUS;
|
||||
|
||||
// Set skip serviceworker flag.
|
||||
|
@ -583,17 +587,25 @@ FetchDriver::HttpFetch(bool aCORSFlag, bool aCORSPreflightFlag, bool aAuthentica
|
|||
|
||||
nsCOMPtr<nsIStreamListener> listener = this;
|
||||
|
||||
MOZ_ASSERT_IF(aCORSFlag, mRequest->Mode() == RequestMode::Cors);
|
||||
|
||||
// Only use nsCORSListenerProxy if we are in CORS mode. Otherwise it
|
||||
// will overwrite the CorsMode flag unconditionally to "cors" or
|
||||
// "cors-with-forced-preflight".
|
||||
if (mRequest->Mode() == RequestMode::Cors) {
|
||||
// Passing false for the credentials flag to nsCORSListenerProxy is semantically
|
||||
// the same as the "same-origin" RequestCredentials value. We implement further
|
||||
// blocking of credentials for "omit" by setting LOAD_ANONYMOUS manually above.
|
||||
bool corsCredentials =
|
||||
mRequest->GetCredentialsMode() == RequestCredentials::Include;
|
||||
|
||||
// Set up a CORS proxy that will handle the various requirements of the CORS
|
||||
// protocol. It handles the preflight cache and CORS response headers.
|
||||
// If the request is allowed, it will start our original request
|
||||
// and our observer will be notified. On failure, our observer is notified
|
||||
// directly.
|
||||
nsRefPtr<nsCORSListenerProxy> corsListener =
|
||||
new nsCORSListenerProxy(this, mPrincipal, useCredentials);
|
||||
new nsCORSListenerProxy(this, mPrincipal, corsCredentials);
|
||||
rv = corsListener->Init(chan, DataURIHandling::Allow);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return FailWithNetworkError();
|
||||
|
@ -1086,6 +1098,42 @@ FetchDriver::OnRedirectVerifyCallback(nsresult aResult)
|
|||
MOZ_ASSERT(nextOp.mType == BASIC_FETCH || nextOp.mType == HTTP_FETCH);
|
||||
MOZ_ASSERT_IF(mCORSFlagEverSet, nextOp.mType == HTTP_FETCH);
|
||||
MOZ_ASSERT_IF(mCORSFlagEverSet, nextOp.mCORSFlag);
|
||||
|
||||
// Examine and possibly set the LOAD_ANONYMOUS flag on the channel.
|
||||
nsLoadFlags flags;
|
||||
aResult = mNewRedirectChannel->GetLoadFlags(&flags);
|
||||
if (NS_SUCCEEDED(aResult)) {
|
||||
if (mRequest->GetCredentialsMode() == RequestCredentials::Same_origin &&
|
||||
mRequest->GetResponseTainting() == InternalRequest::RESPONSETAINT_OPAQUE) {
|
||||
// In the case of a "no-cors" mode request with "same-origin" credentials,
|
||||
// we have to set LOAD_ANONYMOUS manually here in order to avoid sending
|
||||
// credentials on a cross-origin redirect.
|
||||
flags |= nsIRequest::LOAD_ANONYMOUS;
|
||||
aResult = mNewRedirectChannel->SetLoadFlags(flags);
|
||||
|
||||
} else if (mRequest->GetCredentialsMode() == RequestCredentials::Omit) {
|
||||
// Make sure nothing in the redirect chain screws up our credentials
|
||||
// settings. LOAD_ANONYMOUS must be set if we RequestCredentials is "omit".
|
||||
MOZ_ASSERT(flags & nsIRequest::LOAD_ANONYMOUS);
|
||||
|
||||
} else if (mRequest->GetCredentialsMode() == RequestCredentials::Same_origin &&
|
||||
nextOp.mCORSFlag) {
|
||||
// We also want to verify the LOAD_ANONYMOUS flag is set when we are in
|
||||
// "same-origin" credentials mode and the CORS flag is set. We can't
|
||||
// unconditionally assert here, however, because the nsCORSListenerProxy
|
||||
// will set the flag later in the redirect callback chain. Instead,
|
||||
// perform a weaker assertion here by checking if CORS flag was set
|
||||
// before this redirect. In that case LOAD_ANONYMOUS must still be set.
|
||||
MOZ_ASSERT_IF(mCORSFlagEverSet, flags & nsIRequest::LOAD_ANONYMOUS);
|
||||
|
||||
} else {
|
||||
// Otherwise, we should be sending credentials
|
||||
MOZ_ASSERT(!(flags & nsIRequest::LOAD_ANONYMOUS));
|
||||
}
|
||||
}
|
||||
|
||||
// Track the CORSFlag through redirects.
|
||||
mCORSFlagEverSet = mCORSFlagEverSet || nextOp.mCORSFlag;
|
||||
}
|
||||
|
||||
mOldRedirectChannel = nullptr;
|
||||
|
|
|
@ -190,7 +190,7 @@ FMRadio::Notify(const FMRadioEventType& aType)
|
|||
DispatchTrustedEvent(NS_LITERAL_STRING("enabled"));
|
||||
} else {
|
||||
if (mAudioChannelAgentEnabled) {
|
||||
mAudioChannelAgent->NotifyStoppedPlaying(nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY);
|
||||
mAudioChannelAgent->NotifyStoppedPlaying();
|
||||
mAudioChannelAgentEnabled = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -184,6 +184,13 @@ public:
|
|||
// nsGenericHTMLFrameElement::GetFrameLoader is fine
|
||||
// nsGenericHTMLFrameElement::GetAppManifestURL is fine
|
||||
|
||||
// The fullscreen flag is set to true only when requestFullscreen is
|
||||
// explicitly called on this <iframe> element. In case this flag is
|
||||
// set, the fullscreen state of this element will not be reverted
|
||||
// automatically when its subdocument exits fullscreen.
|
||||
bool FullscreenFlag() const { return mFullscreenFlag; }
|
||||
void SetFullscreenFlag(bool aValue) { mFullscreenFlag = aValue; }
|
||||
|
||||
protected:
|
||||
virtual ~HTMLIFrameElement();
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
#include "nsReadableUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsVariant.h"
|
||||
|
||||
#include "nsIDOMMutationEvent.h"
|
||||
#include "mozilla/ContentEvents.h"
|
||||
|
@ -807,9 +808,7 @@ UploadLastDir::StoreLastUsedDirectory(nsIDocument* aDoc, nsIFile* aDir)
|
|||
aDir->GetPath(unicodePath);
|
||||
if (unicodePath.IsEmpty()) // nothing to do
|
||||
return NS_OK;
|
||||
nsCOMPtr<nsIWritableVariant> prefValue = do_CreateInstance(NS_VARIANT_CONTRACTID);
|
||||
if (!prefValue)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
nsRefPtr<nsVariant> prefValue = new nsVariant();
|
||||
prefValue->SetAsAString(unicodePath);
|
||||
|
||||
// Use the document's current load context to ensure that the content pref
|
||||
|
|
|
@ -4757,17 +4757,17 @@ HTMLMediaElement::NotifyAudioChannelAgent(bool aPlaying)
|
|||
// this method has some content JS in its stack.
|
||||
AutoNoJSAPI nojsapi;
|
||||
|
||||
// Don't notify playback if this element doesn't have any audio tracks.
|
||||
uint32_t notify = HasAudio() ? nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY :
|
||||
nsIAudioChannelAgent::AUDIO_AGENT_DONT_NOTIFY;
|
||||
|
||||
if (aPlaying) {
|
||||
// Don't notify playback if this element doesn't have any audio tracks.
|
||||
uint32_t notify = HasAudio() ? nsIAudioChannelAgent::AUDIO_AGENT_NOTIFY :
|
||||
nsIAudioChannelAgent::AUDIO_AGENT_DONT_NOTIFY;
|
||||
|
||||
float volume = 0.0;
|
||||
bool muted = true;
|
||||
mAudioChannelAgent->NotifyStartedPlaying(notify, &volume, &muted);
|
||||
WindowVolumeChanged(volume, muted);
|
||||
} else {
|
||||
mAudioChannelAgent->NotifyStoppedPlaying(notify);
|
||||
mAudioChannelAgent->NotifyStoppedPlaying();
|
||||
mAudioChannelAgent = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsVariant.h"
|
||||
#include "nsVideoFrame.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsTArrayHelpers.h"
|
||||
|
@ -214,8 +215,7 @@ TextTrackManager::UpdateCueDisplay()
|
|||
mTextTracks->UpdateAndGetShowingCues(activeCues);
|
||||
|
||||
if (activeCues.Length() > 0) {
|
||||
nsCOMPtr<nsIWritableVariant> jsCues =
|
||||
do_CreateInstance("@mozilla.org/variant;1");
|
||||
nsRefPtr<nsVariant> jsCues = new nsVariant();
|
||||
|
||||
jsCues->SetAsArray(nsIDataType::VTYPE_INTERFACE,
|
||||
&NS_GET_IID(nsIDOMEventTarget),
|
||||
|
|
|
@ -113,6 +113,11 @@ protected:
|
|||
bool mBrowserFrameListenersRegistered;
|
||||
bool mFrameLoaderCreationDisallowed;
|
||||
|
||||
// This flag is only used by <iframe>. See HTMLIFrameElement::
|
||||
// FullscreenFlag() for details. It is placed here so that we
|
||||
// do not bloat any struct.
|
||||
bool mFullscreenFlag = false;
|
||||
|
||||
private:
|
||||
void GetManifestURLByType(nsIAtom *aAppType, nsAString& aOut);
|
||||
};
|
||||
|
|
|
@ -1519,7 +1519,7 @@ nsHTMLDocument::Open(JSContext* cx,
|
|||
|
||||
if (cv) {
|
||||
bool okToUnload;
|
||||
if (NS_SUCCEEDED(cv->PermitUnload(&okToUnload)) && !okToUnload) {
|
||||
if (NS_SUCCEEDED(cv->PermitUnload(false, &okToUnload)) && !okToUnload) {
|
||||
// We don't want to unload, so stop here, but don't throw an
|
||||
// exception.
|
||||
nsCOMPtr<nsIDocument> ret = this;
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Bug 1187801</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="file_fullscreen-utils.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="about:blank" allowfullscreen></iframe>
|
||||
<script type="text/javascript">
|
||||
|
||||
/** Test for Bug 1187801 **/
|
||||
|
||||
function info(msg) {
|
||||
opener.info("[nested] " + msg);
|
||||
}
|
||||
|
||||
function ok(condition, msg) {
|
||||
opener.ok(condition, "[nested] " + msg);
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
opener.is(a, b, "[nested] " + msg);
|
||||
}
|
||||
|
||||
var gInnerDoc;
|
||||
var gTestSteps;
|
||||
var gTestIndex = 0;
|
||||
|
||||
function begin() {
|
||||
var root = document.documentElement;
|
||||
var iframe = document.querySelector("iframe");
|
||||
var innerDoc = gInnerDoc = iframe.contentDocument;
|
||||
var innerRoot = innerDoc.documentElement;
|
||||
|
||||
// The format of each test step is:
|
||||
// [[action, target], [fsOuter, fsInner]] where:
|
||||
// * "action" is either "enter" or "exit", means whether we want to
|
||||
// enter or exit fullscreen in this step.
|
||||
// * "target" is where we apply this action. For "enter" action, it
|
||||
// is the element we want to call requestFullscreen() on, and for
|
||||
// "exit", it is the document we want to call exitFullscreen() on.
|
||||
// * "fsOuter" and "fsInner" are the expected fullscreen elements of
|
||||
// the outer and inner document respectively after executing the
|
||||
// action in this step.
|
||||
gTestSteps = [
|
||||
// innerRoot
|
||||
[["enter", innerRoot], [iframe, innerRoot]],
|
||||
[[ "exit", innerDoc], [ null, null]],
|
||||
[["enter", innerRoot], [iframe, innerRoot]],
|
||||
[[ "exit", document], [ null, null]],
|
||||
// root, innerRoot
|
||||
[["enter", root], [ root, null]],
|
||||
[["enter", innerRoot], [iframe, innerRoot]],
|
||||
[[ "exit", innerDoc], [ root, null]],
|
||||
[[ "exit", document], [ null, null]],
|
||||
[["enter", root], [ root, null]],
|
||||
[["enter", innerRoot], [iframe, innerRoot]],
|
||||
[[ "exit", document], [ root, null]],
|
||||
[[ "exit", document], [ null, null]],
|
||||
// iframe, innerRoot
|
||||
[["enter", iframe], [iframe, null]],
|
||||
[["enter", innerRoot], [iframe, innerRoot]],
|
||||
[[ "exit", innerDoc], [iframe, null]],
|
||||
[[ "exit", document], [ null, null]],
|
||||
[["enter", iframe], [iframe, null]],
|
||||
[["enter", innerRoot], [iframe, innerRoot]],
|
||||
[[ "exit", document], [ null, null]],
|
||||
// root, iframe, innerRoot
|
||||
[["enter", root], [ root, null]],
|
||||
[["enter", iframe], [iframe, null]],
|
||||
[["enter", innerRoot], [iframe, innerRoot]],
|
||||
[[ "exit", innerDoc], [iframe, null]],
|
||||
[[ "exit", document], [ root, null]],
|
||||
[[ "exit", document], [ null, null]],
|
||||
[["enter", root], [ root, null]],
|
||||
[["enter", iframe], [iframe, null]],
|
||||
[["enter", innerRoot], [iframe, innerRoot]],
|
||||
[[ "exit", document], [ root, null]],
|
||||
[[ "exit", document], [ null, null]],
|
||||
];
|
||||
|
||||
nextStep();
|
||||
}
|
||||
|
||||
function nextStep() {
|
||||
if (gTestIndex == gTestSteps.length) {
|
||||
opener.nextTest();
|
||||
return;
|
||||
}
|
||||
|
||||
var index = gTestIndex;
|
||||
var [[action, target], [fsOuter, fsInner]] = gTestSteps[gTestIndex++];
|
||||
|
||||
function checkAndNext() {
|
||||
is(document.mozFullScreenElement, fsOuter,
|
||||
`Fullscreen element of outer doc should match after step ${index}`);
|
||||
is(gInnerDoc.mozFullScreenElement, fsInner,
|
||||
`Fullscreen element of inner doc should match after step ${index}`);
|
||||
nextStep();
|
||||
}
|
||||
|
||||
info(`Executing step ${index}: ${action} on ${target}...`);
|
||||
if (action == "enter") {
|
||||
// For "enter" action, the target is the element
|
||||
var doc = target.ownerDocument;
|
||||
addFullscreenChangeContinuation("enter", checkAndNext, doc);
|
||||
target.mozRequestFullScreen();
|
||||
} else if (action == "exit") {
|
||||
// For "exit" action, the target is the document
|
||||
addFullscreenChangeContinuation("exit", checkAndNext, target);
|
||||
target.mozCancelFullScreen();
|
||||
} else {
|
||||
ok(false, `Unknown action ${action}`);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -37,8 +37,11 @@ function addFullscreenChangeContinuation(type, callback, inDoc) {
|
|||
} else if (type == "exit") {
|
||||
// If we just revert the state to a previous fullscreen state,
|
||||
// the window won't back to the normal mode. Hence we check
|
||||
// mozFullScreenElement first here.
|
||||
return doc.mozFullScreenElement || inNormalMode();
|
||||
// mozFullScreenElement first here. Note that we need to check
|
||||
// the fullscreen element of the outmost document here instead
|
||||
// of the current one.
|
||||
var topDoc = doc.defaultView.top.document;
|
||||
return topDoc.mozFullScreenElement || inNormalMode();
|
||||
} else {
|
||||
throw "'type' must be either 'enter', or 'exit'.";
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ support-files =
|
|||
file_fullscreen-multiple-inner.html
|
||||
file_fullscreen-multiple.html
|
||||
file_fullscreen-navigation.html
|
||||
file_fullscreen-nested.html
|
||||
file_fullscreen-plugins.html
|
||||
file_fullscreen-rollback.html
|
||||
file_fullscreen-scrollbar.html
|
||||
|
|
|
@ -41,7 +41,8 @@ var gTestWindows = [
|
|||
"file_fullscreen-navigation.html",
|
||||
"file_fullscreen-scrollbar.html",
|
||||
"file_fullscreen-selector.html",
|
||||
"file_fullscreen-top-layer.html"
|
||||
"file_fullscreen-top-layer.html",
|
||||
"file_fullscreen-nested.html",
|
||||
];
|
||||
|
||||
var testWindow = null;
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
|
||||
|
||||
[test_Range-insertNode.html.json]
|
||||
[test_Range-surroundContents.html.json]
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"0,1: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node paras[0].firstChild": true,
|
||||
"4,2: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node paras[1].firstChild": true,
|
||||
"6,6: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node detachedPara1.firstChild": true,
|
||||
"8,4: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node foreignPara1.firstChild": true
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"0,1: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 0], node paras[0].firstChild": true,
|
||||
"1,1: resulting range position for range [paras[0].firstChild, 0, paras[0].firstChild, 1], node paras[0].firstChild": true,
|
||||
"2,1: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 8], node paras[0].firstChild": true,
|
||||
"3,1: resulting range position for range [paras[0].firstChild, 2, paras[0].firstChild, 9], node paras[0].firstChild": true,
|
||||
"4,2: resulting range position for range [paras[1].firstChild, 0, paras[1].firstChild, 0], node paras[1].firstChild": true,
|
||||
"5,2: resulting range position for range [paras[1].firstChild, 2, paras[1].firstChild, 9], node paras[1].firstChild": true,
|
||||
"6,6: resulting range position for range [detachedPara1.firstChild, 0, detachedPara1.firstChild, 0], node detachedPara1.firstChild": true,
|
||||
"7,6: resulting range position for range [detachedPara1.firstChild, 2, detachedPara1.firstChild, 8], node detachedPara1.firstChild": true,
|
||||
"8,4: resulting range position for range [foreignPara1.firstChild, 0, foreignPara1.firstChild, 0], node foreignPara1.firstChild": true,
|
||||
"9,4: resulting range position for range [foreignPara1.firstChild, 2, foreignPara1.firstChild, 8], node foreignPara1.firstChild": true,
|
||||
"37,0: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node paras[0]": true,
|
||||
"37,0: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node paras[0]": true,
|
||||
"37,1: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node paras[0].firstChild": true,
|
||||
"37,1: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node paras[0].firstChild": true,
|
||||
"37,2: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node paras[1].firstChild": true,
|
||||
"37,2: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node paras[1].firstChild": true,
|
||||
"37,3: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node foreignPara1": true,
|
||||
"37,3: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node foreignPara1": true,
|
||||
"37,4: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node foreignPara1.firstChild": true,
|
||||
"37,4: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node foreignPara1.firstChild": true,
|
||||
"37,5: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node detachedPara1": true,
|
||||
"37,5: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node detachedPara1": true,
|
||||
"37,6: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node detachedPara1.firstChild": true,
|
||||
"37,6: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node detachedPara1.firstChild": true,
|
||||
"37,8: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node detachedDiv": true,
|
||||
"37,8: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node detachedDiv": true,
|
||||
"37,10: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node foreignPara2": true,
|
||||
"37,10: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node foreignPara2": true,
|
||||
"37,12: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node xmlElement": true,
|
||||
"37,12: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node xmlElement": true,
|
||||
"37,13: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node detachedTextNode": true,
|
||||
"37,13: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node detachedTextNode": true,
|
||||
"37,14: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node foreignTextNode": true,
|
||||
"37,14: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node foreignTextNode": true,
|
||||
"37,15: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node processingInstruction": true,
|
||||
"37,15: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node processingInstruction": true,
|
||||
"37,16: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node detachedProcessingInstruction": true,
|
||||
"37,16: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node detachedProcessingInstruction": true,
|
||||
"37,17: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node comment": true,
|
||||
"37,17: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node comment": true,
|
||||
"37,18: resulting DOM for range [processingInstruction, 0, processingInstruction, 4], node detachedComment": true,
|
||||
"37,18: resulting range position for range [processingInstruction, 0, processingInstruction, 4], node detachedComment": true
|
||||
}
|
|
@ -827,94 +827,211 @@ function myExtractContents(range) {
|
|||
}
|
||||
|
||||
/**
|
||||
* insertNode() implementation, following the spec. If an exception is
|
||||
* supposed to be thrown, will return a string with the name (e.g.,
|
||||
* "HIERARCHY_REQUEST_ERR") instead of a document fragment. It might also
|
||||
* return an arbitrary human-readable string if a condition is hit that implies
|
||||
* a spec bug.
|
||||
* insertNode() implementation, following the spec. If an exception is meant
|
||||
* to be thrown, will return a string with the expected exception name, for
|
||||
* instance "HIERARCHY_REQUEST_ERR".
|
||||
*/
|
||||
function myInsertNode(range, node) {
|
||||
// "If the detached flag is set, throw an "InvalidStateError" exception and
|
||||
// terminate these steps."
|
||||
//
|
||||
// Assume that if accessing collapsed throws, it's detached.
|
||||
try {
|
||||
range.collapsed;
|
||||
} catch (e) {
|
||||
return "INVALID_STATE_ERR";
|
||||
}
|
||||
// "If range's start node is either a ProcessingInstruction or Comment
|
||||
// node, or a Text node whose parent is null, throw an
|
||||
// "HierarchyRequestError" exception and terminate these steps."
|
||||
if (range.startContainer.nodeType == Node.PROCESSING_INSTRUCTION_NODE
|
||||
|| range.startContainer.nodeType == Node.COMMENT_NODE
|
||||
|| (range.startContainer.nodeType == Node.TEXT_NODE
|
||||
&& !range.startContainer.parentNode)) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
|
||||
// "If start node is a Comment node, or a Text node whose parent is null,
|
||||
// throw an "HierarchyRequestError" exception and terminate these steps."
|
||||
if (range.startContainer.nodeType == Node.COMMENT_NODE
|
||||
|| (range.startContainer.nodeType == Node.TEXT_NODE
|
||||
&& !range.startContainer.parentNode)) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
// "Let referenceNode be null."
|
||||
var referenceNode = null;
|
||||
|
||||
// "If start node is a Text node, split it with offset context object's
|
||||
// start offset, and let reference node be the result."
|
||||
var referenceNode;
|
||||
if (range.startContainer.nodeType == Node.TEXT_NODE) {
|
||||
// We aren't testing how ranges vary under mutations, and browsers vary
|
||||
// in how they mutate for splitText, so let's just force the correct
|
||||
// way.
|
||||
var start = [range.startContainer, range.startOffset];
|
||||
var end = [range.endContainer, range.endOffset];
|
||||
// "If range's start node is a Text node, set referenceNode to that Text node."
|
||||
if (range.startContainer.nodeType == Node.TEXT_NODE) {
|
||||
referenceNode = range.startContainer;
|
||||
|
||||
referenceNode = range.startContainer.splitText(range.startOffset);
|
||||
// "Otherwise, set referenceNode to the child of start node whose index is
|
||||
// start offset, and null if there is no such child."
|
||||
} else {
|
||||
if (range.startOffset < range.startContainer.childNodes.length) {
|
||||
referenceNode = range.startContainer.childNodes[range.startOffset];
|
||||
} else {
|
||||
referenceNode = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (start[0] == end[0]
|
||||
&& end[1] > start[1]) {
|
||||
end[0] = referenceNode;
|
||||
end[1] -= start[1];
|
||||
} else if (end[0] == start[0].parentNode
|
||||
&& end[1] > indexOf(referenceNode)) {
|
||||
end[1]++;
|
||||
}
|
||||
range.setStart(start[0], start[1]);
|
||||
range.setEnd(end[0], end[1]);
|
||||
// "Let parent be range's start node if referenceNode is null, and
|
||||
// referenceNode's parent otherwise."
|
||||
var parent_ = referenceNode === null ? range.startContainer :
|
||||
referenceNode.parentNode;
|
||||
|
||||
// "Otherwise, let reference node be the child of start node whose index is
|
||||
// start offset, or null if there is no such child."
|
||||
} else {
|
||||
referenceNode = range.startContainer.childNodes[range.startOffset];
|
||||
if (typeof referenceNode == "undefined") {
|
||||
referenceNode = null;
|
||||
}
|
||||
}
|
||||
// "Ensure pre-insertion validity of node into parent before
|
||||
// referenceNode."
|
||||
var error = ensurePreInsertionValidity(node, parent_, referenceNode);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
// "If reference node is null, let parent be start node."
|
||||
var parent_;
|
||||
if (!referenceNode) {
|
||||
parent_ = range.startContainer;
|
||||
// "If range's start node is a Text node, set referenceNode to the result
|
||||
// of splitting it with offset range's start offset."
|
||||
if (range.startContainer.nodeType == Node.TEXT_NODE) {
|
||||
referenceNode = range.startContainer.splitText(range.startOffset);
|
||||
}
|
||||
|
||||
// "Otherwise, let parent be the parent of reference node."
|
||||
} else {
|
||||
parent_ = referenceNode.parentNode;
|
||||
}
|
||||
// "If node is referenceNode, set referenceNode to its next sibling."
|
||||
if (node == referenceNode) {
|
||||
referenceNode = referenceNode.nextSibling;
|
||||
}
|
||||
|
||||
// "Let new offset be the index of reference node, or parent's length if
|
||||
// reference node is null."
|
||||
var newOffset = referenceNode ? indexOf(referenceNode) : nodeLength(parent_);
|
||||
// "If node's parent is not null, remove node from its parent."
|
||||
if (node.parentNode) {
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
|
||||
// "Add node's length to new offset, if node is a DocumentFragment.
|
||||
// Otherwise add one to new offset."
|
||||
newOffset += node.nodeType == Node.DOCUMENT_FRAGMENT_NODE
|
||||
? nodeLength(node)
|
||||
: 1;
|
||||
// "Let newOffset be parent's length if referenceNode is null, and
|
||||
// referenceNode's index otherwise."
|
||||
var newOffset = referenceNode === null ? nodeLength(parent_) :
|
||||
indexOf(referenceNode);
|
||||
|
||||
// "Pre-insert node into parent before reference node."
|
||||
try {
|
||||
parent_.insertBefore(node, referenceNode);
|
||||
} catch (e) {
|
||||
return getDomExceptionName(e);
|
||||
}
|
||||
// "Increase newOffset by node's length if node is a DocumentFragment node,
|
||||
// and one otherwise."
|
||||
newOffset += node.nodeType == Node.DOCUMENT_FRAGMENT_NODE ?
|
||||
nodeLength(node) : 1;
|
||||
|
||||
// "If start and end are the same, set end to (parent, new offset)."
|
||||
if (range.collapsed) {
|
||||
range.setEnd(parent_, newOffset);
|
||||
}
|
||||
// "Pre-insert node into parent before referenceNode."
|
||||
parent_.insertBefore(node, referenceNode);
|
||||
|
||||
// "If range's start and end are the same, set range's end to (parent,
|
||||
// newOffset)."
|
||||
if (range.startContainer == range.endContainer
|
||||
&& range.startOffset == range.endOffset) {
|
||||
range.setEnd(parent_, newOffset);
|
||||
}
|
||||
}
|
||||
|
||||
// To make filter() calls more readable
|
||||
function isElement(node) {
|
||||
return node.nodeType == Node.ELEMENT_NODE;
|
||||
}
|
||||
|
||||
function isText(node) {
|
||||
return node.nodeType == Node.TEXT_NODE;
|
||||
}
|
||||
|
||||
function isDoctype(node) {
|
||||
return node.nodeType == Node.DOCUMENT_TYPE_NODE;
|
||||
}
|
||||
|
||||
function ensurePreInsertionValidity(node, parent_, child) {
|
||||
// "If parent is not a Document, DocumentFragment, or Element node, throw a
|
||||
// HierarchyRequestError."
|
||||
if (parent_.nodeType != Node.DOCUMENT_NODE
|
||||
&& parent_.nodeType != Node.DOCUMENT_FRAGMENT_NODE
|
||||
&& parent_.nodeType != Node.ELEMENT_NODE) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
|
||||
// "If node is a host-including inclusive ancestor of parent, throw a
|
||||
// HierarchyRequestError."
|
||||
//
|
||||
// XXX Does not account for host
|
||||
if (isInclusiveAncestor(node, parent_)) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
|
||||
// "If child is not null and its parent is not parent, throw a NotFoundError
|
||||
// exception."
|
||||
if (child && child.parentNode != parent_) {
|
||||
return "NOT_FOUND_ERR";
|
||||
}
|
||||
|
||||
// "If node is not a DocumentFragment, DocumentType, Element, Text,
|
||||
// ProcessingInstruction, or Comment node, throw a HierarchyRequestError."
|
||||
if (node.nodeType != Node.DOCUMENT_FRAGMENT_NODE
|
||||
&& node.nodeType != Node.DOCUMENT_TYPE_NODE
|
||||
&& node.nodeType != Node.ELEMENT_NODE
|
||||
&& node.nodeType != Node.TEXT_NODE
|
||||
&& node.nodeType != Node.PROCESSING_INSTRUCTION_NODE
|
||||
&& node.nodeType != Node.COMMENT_NODE) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
|
||||
// "If either node is a Text node and parent is a document, or node is a
|
||||
// doctype and parent is not a document, throw a HierarchyRequestError."
|
||||
if ((node.nodeType == Node.TEXT_NODE
|
||||
&& parent_.nodeType == Node.DOCUMENT_NODE)
|
||||
|| (node.nodeType == Node.DOCUMENT_TYPE_NODE
|
||||
&& parent_.nodeType != Node.DOCUMENT_NODE)) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
|
||||
// "If parent is a document, and any of the statements below, switched on
|
||||
// node, are true, throw a HierarchyRequestError."
|
||||
if (parent_.nodeType == Node.DOCUMENT_NODE) {
|
||||
switch (node.nodeType) {
|
||||
case Node.DOCUMENT_FRAGMENT_NODE:
|
||||
// "If node has more than one element child or has a Text node
|
||||
// child. Otherwise, if node has one element child and either
|
||||
// parent has an element child, child is a doctype, or child is not
|
||||
// null and a doctype is following child."
|
||||
if ([].filter.call(node.childNodes, isElement).length > 1) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
|
||||
if ([].some.call(node.childNodes, isText)) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
|
||||
if ([].filter.call(node.childNodes, isElement).length == 1) {
|
||||
if ([].some.call(parent_.childNodes, isElement)) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
|
||||
if (child && child.nodeType == Node.DOCUMENT_TYPE_NODE) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
|
||||
if (child && [].slice.call(parent_.childNodes, indexOf(child) + 1)
|
||||
.filter(isDoctype)) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Node.ELEMENT_NODE:
|
||||
// "parent has an element child, child is a doctype, or child is
|
||||
// not null and a doctype is following child."
|
||||
if ([].some.call(parent_.childNodes, isElement)) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
|
||||
if (child.nodeType == Node.DOCUMENT_TYPE_NODE) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
|
||||
if (child && [].slice.call(parent_.childNodes, indexOf(child) + 1)
|
||||
.filter(isDoctype)) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
break;
|
||||
|
||||
case Node.DOCUMENT_TYPE_NODE:
|
||||
// "parent has a doctype child, an element is preceding child, or
|
||||
// child is null and parent has an element child."
|
||||
if ([].some.call(parent_.childNodes, isDoctype)) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
|
||||
if (child && [].slice.call(parent_.childNodes, 0, indexOf(child))
|
||||
.some(isElement)) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
|
||||
if (!child && [].some.call(parent_.childNodes, isElement)) {
|
||||
return "HIERARCHY_REQUEST_ERR";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,6 +18,7 @@ MOCHITEST_MANIFESTS += [
|
|||
'failures/html/dom/lists/mochitest.ini',
|
||||
'failures/html/dom/mochitest.ini',
|
||||
'failures/html/dom/nodes/mochitest.ini',
|
||||
'failures/html/dom/ranges/mochitest.ini',
|
||||
'failures/html/html/browsers/the-window-object/mochitest.ini',
|
||||
'failures/html/html/browsers/the-window-object/named-access-on-the-window-object/mochitest.ini',
|
||||
'failures/html/html/dom/documents/dta/doc.gEBN/mochitest.ini',
|
||||
|
|
|
@ -894,7 +894,7 @@ CommonStructuredCloneReadCallback(JSContext* aCx,
|
|||
}
|
||||
|
||||
return StructuredCloneHolder::ReadFullySerializableObjects(aCx, aReader,
|
||||
aTag, aData);
|
||||
aTag);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -17,7 +17,7 @@ interface nsIOpenURIInFrameParams : nsISupports
|
|||
attribute boolean isPrivate;
|
||||
};
|
||||
|
||||
[scriptable, uuid(31da1ce2-aec4-4c26-ac66-d622935c3bf4)]
|
||||
[scriptable, uuid(99f5a347-722c-4337-bd38-f14ec94801b3)]
|
||||
|
||||
/**
|
||||
* The C++ source has access to the browser script source through
|
||||
|
@ -99,14 +99,6 @@ interface nsIBrowserDOMWindow : nsISupports
|
|||
* @return whether the window is the main content window for any
|
||||
* currently open tab in this toplevel browser window.
|
||||
*/
|
||||
boolean isTabContentWindow(in nsIDOMWindow aWindow);
|
||||
|
||||
/**
|
||||
* This function is responsible for calling
|
||||
* nsIContentViewer::PermitUnload on each frame in the window. It
|
||||
* returns true if closing the window is allowed. See canClose() in
|
||||
* BrowserUtils.jsm for a simple implementation of this method.
|
||||
*/
|
||||
boolean canClose();
|
||||
boolean isTabContentWindow(in nsIDOMWindow aWindow);
|
||||
};
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче