This commit is contained in:
Carsten "Tomcat" Book 2015-10-08 16:11:56 +02:00
Родитель 6561fc54bc 634dc488d6
Коммит 6e07fc601b
367 изменённых файлов: 8383 добавлений и 6957 удалений

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

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

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

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

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

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше