mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to fx-team, a=merge
This commit is contained in:
commit
aff57a8327
@ -218,10 +218,25 @@ public:
|
||||
bool IsLinkValid();
|
||||
|
||||
// XXX checking mRole alone may not result in same behavior as Accessibles
|
||||
// due to ARIA roles
|
||||
inline bool IsTable() const { return mRole == roles::TABLE; }
|
||||
inline bool IsTableRow() const { return mRole == roles::ROW; }
|
||||
inline bool IsTableCell() const { return mRole == roles::CELL; }
|
||||
// due to ARIA roles. See bug 1210477.
|
||||
inline bool IsTable() const
|
||||
{
|
||||
return mRole == roles::TABLE || mRole == roles::MATHML_TABLE;
|
||||
}
|
||||
inline bool IsTableRow() const
|
||||
{
|
||||
return (mRole == roles::ROW ||
|
||||
mRole == roles::MATHML_TABLE_ROW ||
|
||||
mRole == roles::MATHML_LABELED_ROW);
|
||||
}
|
||||
inline bool IsTableCell() const
|
||||
{
|
||||
return (mRole == roles::CELL ||
|
||||
mRole == roles::COLUMNHEADER ||
|
||||
mRole == roles::ROWHEADER ||
|
||||
mRole == roles::GRID_CELL ||
|
||||
mRole == roles::MATHML_CELL);
|
||||
}
|
||||
|
||||
uint32_t AnchorCount(bool* aOk);
|
||||
|
||||
|
@ -101,7 +101,7 @@ this.FxAccountsMgmtService = {
|
||||
switch(data.method) {
|
||||
case "getAssertion":
|
||||
let principal = Services.scriptSecurityManager.getSystemPrincipal();
|
||||
let audience = msg.audience || principal.originNoSuffix;
|
||||
let audience = data.audience || principal.originNoSuffix;
|
||||
FxAccountsManager.getAssertion(audience, principal, {
|
||||
silent: msg.silent || false
|
||||
}).then(result => {
|
||||
|
@ -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="9a682cb7bc8b7fde624a9b2b3c2d64415a08b04b"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f3d9981dccfa4dfdfcb865d95fdcfb85e4077e1e"/>
|
||||
<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"/>
|
||||
|
@ -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="9a682cb7bc8b7fde624a9b2b3c2d64415a08b04b"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f3d9981dccfa4dfdfcb865d95fdcfb85e4077e1e"/>
|
||||
<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="9a682cb7bc8b7fde624a9b2b3c2d64415a08b04b"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f3d9981dccfa4dfdfcb865d95fdcfb85e4077e1e"/>
|
||||
<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="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
||||
|
@ -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="9a682cb7bc8b7fde624a9b2b3c2d64415a08b04b"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f3d9981dccfa4dfdfcb865d95fdcfb85e4077e1e"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="58909a53f638af022ab09f7a8f6976b0cae8f133"/>
|
||||
<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="9a682cb7bc8b7fde624a9b2b3c2d64415a08b04b"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f3d9981dccfa4dfdfcb865d95fdcfb85e4077e1e"/>
|
||||
<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"/>
|
||||
@ -128,7 +128,7 @@
|
||||
<!-- Emulator specific things -->
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
|
||||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="8d4018ebd33ac3f1a043b2d54bc578028656a659"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="e002268b30ce69725e60fdc827a19d729cce7396"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="b2773dbc3cb24e70cff2b05522e9c959250400ac"/>
|
||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="f37bd545063039e30a92f2550ae78c0e6e4e2d08"/>
|
||||
<project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="0c6a6547cd1fd302fa2b0f6e375654df36bf0ec4"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="7132bc11fbc68acfebcd509095562ca04fad5584"/>
|
||||
|
@ -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="9a682cb7bc8b7fde624a9b2b3c2d64415a08b04b"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f3d9981dccfa4dfdfcb865d95fdcfb85e4077e1e"/>
|
||||
<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="9a682cb7bc8b7fde624a9b2b3c2d64415a08b04b"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f3d9981dccfa4dfdfcb865d95fdcfb85e4077e1e"/>
|
||||
<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="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
||||
|
@ -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="9a682cb7bc8b7fde624a9b2b3c2d64415a08b04b"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f3d9981dccfa4dfdfcb865d95fdcfb85e4077e1e"/>
|
||||
<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": "9a682cb7bc8b7fde624a9b2b3c2d64415a08b04b",
|
||||
"git_revision": "f3d9981dccfa4dfdfcb865d95fdcfb85e4077e1e",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "73f844def0a5b0a7e077b68e5e16ffd6753129da",
|
||||
"revision": "ad7f7540499e0cf54ddd5cf41ff39886cf63acfb",
|
||||
"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="9a682cb7bc8b7fde624a9b2b3c2d64415a08b04b"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f3d9981dccfa4dfdfcb865d95fdcfb85e4077e1e"/>
|
||||
<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="9a682cb7bc8b7fde624a9b2b3c2d64415a08b04b"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f3d9981dccfa4dfdfcb865d95fdcfb85e4077e1e"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="58909a53f638af022ab09f7a8f6976b0cae8f133"/>
|
||||
<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="9a682cb7bc8b7fde624a9b2b3c2d64415a08b04b"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="f3d9981dccfa4dfdfcb865d95fdcfb85e4077e1e"/>
|
||||
<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"/>
|
||||
|
@ -4960,6 +4960,10 @@ nsBrowserAccess.prototype = {
|
||||
isTabContentWindow: function (aWindow) {
|
||||
return gBrowser.browsers.some(browser => browser.contentWindow == aWindow);
|
||||
},
|
||||
|
||||
canClose() {
|
||||
return CanCloseWindow();
|
||||
},
|
||||
}
|
||||
|
||||
function getTogglableToolbars() {
|
||||
@ -6424,6 +6428,26 @@ 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()) {
|
||||
@ -6434,27 +6458,19 @@ function WindowIsClosing()
|
||||
if (!closeWindow(false, warnAboutClosingWindow))
|
||||
return false;
|
||||
|
||||
// Bug 967873 - Proxy nsDocumentViewer::PermitUnload to the child process
|
||||
if (gMultiProcessBrowser)
|
||||
// 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;
|
||||
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 true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);"/>
|
||||
oncommand="gBrowser.removeTabsToTheEndFrom(TabContextMenu.contextTab, {animate: true});"/>
|
||||
<menuitem id="context_closeOtherTabs" label="&closeOtherTabs.label;" accesskey="&closeOtherTabs.accesskey;"
|
||||
oncommand="gBrowser.removeAllTabsBut(TabContextMenu.contextTab);"/>
|
||||
<menuseparator/>
|
||||
|
@ -131,6 +131,11 @@ 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: 4 -*-
|
||||
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
/* 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,28 +567,17 @@ Sanitizer.prototype = {
|
||||
openWindows: {
|
||||
privateStateForNewWindow: "non-private",
|
||||
_canCloseWindow: function(aWindow) {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
_resetAllWindowClosures: function(aWindowList) {
|
||||
for (let win of aWindowList) {
|
||||
win.getInterface(Ci.nsIDocShell).contentViewer.resetCloseWindow();
|
||||
win.skipNextCanClose = false;
|
||||
}
|
||||
},
|
||||
clear: Task.async(function*() {
|
||||
|
@ -1190,25 +1190,29 @@
|
||||
this._tabAttrModified(this.mCurrentTab, ["selected"]);
|
||||
|
||||
if (oldBrowser != newBrowser &&
|
||||
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.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._urlbarFocused = (gURLBar && gURLBar.focused);
|
||||
@ -2077,12 +2081,13 @@
|
||||
|
||||
<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], {animate: true});
|
||||
this.removeTab(tabs[i], aParams);
|
||||
}
|
||||
}
|
||||
]]>
|
||||
@ -2130,6 +2135,7 @@
|
||||
if (aParams) {
|
||||
var animate = aParams.animate;
|
||||
var byMouse = aParams.byMouse;
|
||||
var skipPermitUnload = aParams.skipPermitUnload;
|
||||
}
|
||||
|
||||
// Handle requests for synchronously removing an already
|
||||
@ -2142,7 +2148,7 @@
|
||||
|
||||
var isLastTab = (this.tabs.length - this._removingTabs.length == 1);
|
||||
|
||||
if (!this._beginRemoveTab(aTab, false, null, true))
|
||||
if (!this._beginRemoveTab(aTab, false, null, true, skipPermitUnload))
|
||||
return;
|
||||
|
||||
if (!aTab.pinned && !aTab.hidden && aTab._fullyOpen && byMouse)
|
||||
@ -2190,6 +2196,7 @@
|
||||
<parameter name="aTabWillBeMoved"/>
|
||||
<parameter name="aCloseWindowWithLastTab"/>
|
||||
<parameter name="aCloseWindowFastpath"/>
|
||||
<parameter name="aSkipPermitUnload"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (aTab.closing ||
|
||||
@ -2220,23 +2227,20 @@
|
||||
newTab = true;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4054,13 +4058,19 @@
|
||||
}
|
||||
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) {
|
||||
this.removeTab(tab);
|
||||
// Skip running PermitUnload since it already happened in
|
||||
// the content process.
|
||||
this.removeTab(tab, {skipPermitUnload: true});
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -4344,12 +4354,18 @@
|
||||
if (!event.isTrusted)
|
||||
return;
|
||||
|
||||
if (this.tabs.length == 1)
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
var tab = this._getTabForContentWindow(event.target);
|
||||
if (tab) {
|
||||
this.removeTab(tab);
|
||||
// Skip running PermitUnload since it already happened.
|
||||
this.removeTab(tab, {skipPermitUnload: true});
|
||||
event.preventDefault();
|
||||
}
|
||||
]]>
|
||||
|
@ -148,7 +148,6 @@ 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]);
|
||||
gBrowser.removeTab(gBrowser.tabs[0], {skipPermitUnload: true});
|
||||
|
||||
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);
|
||||
gBrowser.removeTab(aTab, {skipPermitUnload: true});
|
||||
});
|
||||
}, true);
|
||||
|
||||
gBrowser.removeTab(gBrowser.tabs[0]);
|
||||
gBrowser.removeTab(gBrowser.tabs[0], {skipPermitUnload: true});
|
||||
is(gBrowser.tabs.length, 1, "Related tabs are not closed unexpectedly");
|
||||
|
||||
gBrowser.addTab("about:blank");
|
||||
gBrowser.removeTab(gBrowser.tabs[0]);
|
||||
gBrowser.removeTab(gBrowser.tabs[0], {skipPermitUnload: true});
|
||||
finish();
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ function checkBookmarksPanel(invoker, phase)
|
||||
if (currentInvoker < invokers.length) {
|
||||
checkBookmarksPanel(invokers[currentInvoker], 1);
|
||||
} else {
|
||||
gBrowser.removeCurrentTab();
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {skipPermitUnload: true});
|
||||
PlacesUtils.bookmarks.removeItem(bookmarkId);
|
||||
executeSoon(finish);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
function test() {
|
||||
add_task(function*() {
|
||||
is(gBrowser.tabs.length, 1, "one tab is open");
|
||||
|
||||
gBrowser.selectedBrowser.focus();
|
||||
@ -6,11 +6,15 @@ function test() {
|
||||
|
||||
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,10 +18,13 @@ function record(aName) {
|
||||
if (actual.length == expected.length) {
|
||||
is(actual.toString(), expected.toString(),
|
||||
"got events and progress notifications in expected order");
|
||||
gBrowser.removeTab(tab);
|
||||
gBrowser.removeTabsProgressListener(progressListener);
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", TabOpen, false);
|
||||
finish();
|
||||
|
||||
executeSoon(function(tab) {
|
||||
gBrowser.removeTab(tab);
|
||||
gBrowser.removeTabsProgressListener(progressListener);
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", TabOpen, false);
|
||||
finish();
|
||||
}.bind(null, tab));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,14 +6,14 @@ function test() {
|
||||
|
||||
childTab1 = gBrowser.addTab("about:blank", { relatedToCurrent: true });
|
||||
gBrowser.selectedTab = childTab1;
|
||||
gBrowser.removeCurrentTab();
|
||||
gBrowser.removeTab(gBrowser.selectedTab, { skipPermitUnload: true });
|
||||
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.removeCurrentTab();
|
||||
gBrowser.removeTab(gBrowser.selectedTab, { skipPermitUnload: true });
|
||||
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.removeCurrentTab();
|
||||
gBrowser.removeTab(gBrowser.selectedTab, { skipPermitUnload: true });
|
||||
is(idx(gBrowser.selectedTab), idx(childTab2),
|
||||
"closing a tab next to its parent selects the next tab with the same parent");
|
||||
gBrowser.removeCurrentTab();
|
||||
gBrowser.removeTab(gBrowser.selectedTab, { skipPermitUnload: true });
|
||||
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);
|
||||
gBrowser.removeTab(tab2, { skipPermitUnload: true });
|
||||
}
|
||||
|
||||
function idx(tab) {
|
||||
|
@ -14,6 +14,13 @@ 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,6 +5,12 @@
|
||||
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,4 +1,5 @@
|
||||
function test () {
|
||||
requestLongerTimeout(2);
|
||||
waitForExplicitFinish();
|
||||
|
||||
var isHTTPS = false;
|
||||
|
@ -7,6 +7,12 @@
|
||||
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/. */
|
||||
|
||||
function test() {
|
||||
add_task(function*() {
|
||||
is(gBrowser.tabs.length, 1, "one tab is open initially");
|
||||
|
||||
// Add several new tabs in sequence, interrupted by selecting a
|
||||
@ -10,26 +10,29 @@ function test() {
|
||||
// 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) {
|
||||
tabs.push(gBrowser.addTab(aURL, {referrerURI: aReferrer}));
|
||||
let tab = gBrowser.addTab(aURL, {referrerURI: aReferrer});
|
||||
tabs.push(tab);
|
||||
return BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
}
|
||||
|
||||
addTab("http://mochi.test:8888/#0");
|
||||
yield addTab("http://mochi.test:8888/#0");
|
||||
gBrowser.selectedTab = tabs[0];
|
||||
addTab("http://mochi.test:8888/#1");
|
||||
addTab("http://mochi.test:8888/#2", gBrowser.currentURI);
|
||||
addTab("http://mochi.test:8888/#3", gBrowser.currentURI);
|
||||
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);
|
||||
gBrowser.selectedTab = tabs[tabs.length - 1];
|
||||
gBrowser.selectedTab = tabs[0];
|
||||
addTab("http://mochi.test:8888/#4", gBrowser.currentURI);
|
||||
yield addTab("http://mochi.test:8888/#4", gBrowser.currentURI);
|
||||
gBrowser.selectedTab = tabs[3];
|
||||
addTab("http://mochi.test:8888/#5", gBrowser.currentURI);
|
||||
yield addTab("http://mochi.test:8888/#5", gBrowser.currentURI);
|
||||
gBrowser.removeTab(tabs.pop());
|
||||
addTab("about:blank", gBrowser.currentURI);
|
||||
yield addTab("about:blank", gBrowser.currentURI);
|
||||
gBrowser.moveTabTo(gBrowser.selectedTab, 1);
|
||||
addTab("http://mochi.test:8888/#6", gBrowser.currentURI);
|
||||
addTab();
|
||||
addTab("http://mochi.test:8888/#7");
|
||||
yield addTab("http://mochi.test:8888/#6", gBrowser.currentURI);
|
||||
yield addTab();
|
||||
yield addTab("http://mochi.test:8888/#7");
|
||||
|
||||
function testPosition(tabNum, expectedPosition, msg) {
|
||||
is(Array.indexOf(gBrowser.tabs, tabs[tabNum]), expectedPosition, msg);
|
||||
@ -46,4 +49,4 @@ function test() {
|
||||
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.removeCurrentTab();
|
||||
gBrowser.removeTab(gBrowser.selectedTab, {skipPermitUnload: true});
|
||||
}
|
||||
|
@ -2,7 +2,11 @@
|
||||
* 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/. */
|
||||
|
||||
function test() {
|
||||
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));
|
||||
|
||||
// There should be one tab when we start the test
|
||||
let [origTab] = gBrowser.visibleTabs;
|
||||
|
||||
@ -100,4 +104,5 @@ function test() {
|
||||
|
||||
if (tabViewWindow)
|
||||
tabViewWindow.GroupItems.groupItems[0].close();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -5,6 +5,12 @@
|
||||
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,6 +5,12 @@
|
||||
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,7 +2,11 @@
|
||||
* 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/. */
|
||||
|
||||
function test() {
|
||||
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));
|
||||
|
||||
// There should be one tab when we start the test
|
||||
let [origTab] = gBrowser.visibleTabs;
|
||||
is(gBrowser.visibleTabs.length, 1, "there is one visible tab");
|
||||
@ -51,4 +55,5 @@ function test() {
|
||||
|
||||
gBrowser.removeTab(testTab);
|
||||
gBrowser.removeTab(pinned);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -2,7 +2,11 @@
|
||||
* 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/. */
|
||||
|
||||
function test() {
|
||||
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));
|
||||
|
||||
gPrefService.setBoolPref("browser.ctrlTab.previews", true);
|
||||
|
||||
let [origTab] = gBrowser.visibleTabs;
|
||||
@ -30,7 +34,7 @@ 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);
|
||||
gBrowser.removeTab(tab, {skipPermitUnload: true});
|
||||
return promise;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,10 @@ 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,6 +7,12 @@
|
||||
|
||||
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,11 +39,18 @@ 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);
|
||||
@ -69,6 +76,10 @@ 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.
|
||||
|
@ -107,7 +107,8 @@ function removeTab(aTab, aWindow) {
|
||||
let targetWindow = aWindow || window;
|
||||
let targetBrowser = targetWindow.gBrowser;
|
||||
|
||||
targetBrowser.removeTab(aTab);
|
||||
// browser_net_pane-toggle.js relies on synchronous removeTab behavior.
|
||||
targetBrowser.removeTab(aTab, {skipPermitUnload: true});
|
||||
}
|
||||
|
||||
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); }' +
|
||||
' sendSyncMessage("done", { failed: content.wrappedJSObject.failed });' +
|
||||
' sendAsyncMessage("done", { failed: content.wrappedJSObject.failed });' +
|
||||
'}' +
|
||||
'check();'
|
||||
, true);
|
||||
}
|
||||
}
|
||||
|
@ -7764,7 +7764,7 @@ nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
|
||||
mTiming->NotifyBeforeUnload();
|
||||
|
||||
bool okToUnload;
|
||||
rv = mContentViewer->PermitUnload(false, &okToUnload);
|
||||
rv = mContentViewer->PermitUnload(&okToUnload);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !okToUnload) {
|
||||
// The user chose not to unload the page, interrupt the load.
|
||||
@ -10097,7 +10097,7 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||
// protocol handler deals with this for javascript: URLs.
|
||||
if (!isJavaScript && aFileName.IsVoid() && mContentViewer) {
|
||||
bool okToUnload;
|
||||
rv = mContentViewer->PermitUnload(false, &okToUnload);
|
||||
rv = mContentViewer->PermitUnload(&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(702e0a92-7d63-490e-b5ee-d247e6bd4588)]
|
||||
[scriptable, builtinclass, uuid(91b6c1f3-fc5f-43a9-88f4-9286bd19387f)]
|
||||
interface nsIContentViewer : nsISupports
|
||||
{
|
||||
|
||||
@ -46,12 +46,8 @@ 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([optional] in boolean aCallerClosesWindow);
|
||||
boolean permitUnload();
|
||||
|
||||
/**
|
||||
* Exposes whether we're blocked in a call to permitUnload.
|
||||
@ -63,8 +59,7 @@ 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(in boolean aCallerClosesWindow,
|
||||
inout boolean aShouldPrompt);
|
||||
[noscript,nostdcall] boolean permitUnloadInternal(inout boolean aShouldPrompt);
|
||||
|
||||
/**
|
||||
* Exposes whether we're in the process of firing the beforeunload event.
|
||||
@ -72,16 +67,6 @@ 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,7 +103,6 @@ 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,6 +10,7 @@ SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunlo
|
||||
|
||||
var loadExpected = TEST_PAGE;
|
||||
var testTab;
|
||||
var testsLength;
|
||||
|
||||
var loadStarted = false;
|
||||
var tabStateListener = {
|
||||
@ -40,6 +41,10 @@ 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");
|
||||
@ -102,47 +107,9 @@ 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 >= testFns.length) {
|
||||
if (currentTest >= testsLength) {
|
||||
if (!stayingOnPage) {
|
||||
finish();
|
||||
return;
|
||||
@ -171,10 +138,10 @@ function runCurrentTest() {
|
||||
contentWindow.dialogWasInvoked = false;
|
||||
originalLocation = contentWindow.location.href;
|
||||
// And run this test:
|
||||
info("Running test with onbeforeunload " + testFns[currentTest].toSource());
|
||||
contentWindow.onbeforeunload = testFns[currentTest];
|
||||
info("Running test with onbeforeunload " + contentWindow.wrappedJSObject.testFns[currentTest].toSource());
|
||||
contentWindow.onbeforeunload = contentWindow.wrappedJSObject.testFns[currentTest];
|
||||
loadStarted = false;
|
||||
contentWindow.location.href = TARGETED_PAGE;
|
||||
testTab.linkedBrowser.loadURI(TARGETED_PAGE);
|
||||
}
|
||||
|
||||
var onAfterPageLoad = runNextTest;
|
||||
|
@ -7,4 +7,44 @@
|
||||
<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) {
|
||||
finish();
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#ifndef __nsContentPolicyUtils_h__
|
||||
#define __nsContentPolicyUtils_h__
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
@ -194,7 +195,9 @@ NS_CP_ContentTypeName(uint32_t contentType)
|
||||
do_GetService( \
|
||||
"@mozilla.org/data-document-content-policy;1"); \
|
||||
if (dataPolicy) { \
|
||||
dataPolicy-> action (contentType, contentLocation, \
|
||||
nsContentPolicyType externalType = \
|
||||
nsContentUtils::InternalContentPolicyTypeToExternal(contentType);\
|
||||
dataPolicy-> action (externalType, contentLocation, \
|
||||
requestOrigin, context, \
|
||||
mimeType, extra, \
|
||||
originPrincipal, decision); \
|
||||
|
@ -8754,6 +8754,17 @@ 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;
|
||||
}
|
||||
@ -8767,7 +8778,7 @@ nsGlobalWindow::CanClose()
|
||||
mDocShell->GetContentViewer(getter_AddRefs(cv));
|
||||
if (cv) {
|
||||
bool canClose;
|
||||
nsresult rv = cv->PermitUnload(false, &canClose);
|
||||
nsresult rv = cv->PermitUnload(&canClose);
|
||||
if (NS_SUCCEEDED(rv) && !canClose)
|
||||
return false;
|
||||
|
||||
|
@ -105,7 +105,7 @@ BluetoothDaemonCoreModule::GetAdapterPropertiesCmd(
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothDaemonCoreModule::GetAdapterPropertyCmd(const nsAString& aName,
|
||||
BluetoothDaemonCoreModule::GetAdapterPropertyCmd(BluetoothPropertyType aType,
|
||||
BluetoothResultHandler* aRes)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
@ -114,8 +114,7 @@ BluetoothDaemonCoreModule::GetAdapterPropertyCmd(const nsAString& aName,
|
||||
new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_ADAPTER_PROPERTY,
|
||||
0));
|
||||
|
||||
nsresult rv = PackPDU(
|
||||
PackConversion<const nsAString, BluetoothPropertyType>(aName), *pdu);
|
||||
nsresult rv = PackPDU(aType, *pdu);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -129,7 +128,7 @@ BluetoothDaemonCoreModule::GetAdapterPropertyCmd(const nsAString& aName,
|
||||
|
||||
nsresult
|
||||
BluetoothDaemonCoreModule::SetAdapterPropertyCmd(
|
||||
const BluetoothNamedValue& aProperty, BluetoothResultHandler* aRes)
|
||||
const BluetoothProperty& aProperty, BluetoothResultHandler* aRes)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
@ -174,7 +173,7 @@ BluetoothDaemonCoreModule::GetRemoteDevicePropertiesCmd(
|
||||
nsresult
|
||||
BluetoothDaemonCoreModule::GetRemoteDevicePropertyCmd(
|
||||
const BluetoothAddress& aRemoteAddr,
|
||||
const nsAString& aName,
|
||||
BluetoothPropertyType aType,
|
||||
BluetoothResultHandler* aRes)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
@ -183,9 +182,7 @@ BluetoothDaemonCoreModule::GetRemoteDevicePropertyCmd(
|
||||
new DaemonSocketPDU(SERVICE_ID, OPCODE_GET_REMOTE_DEVICE_PROPERTY,
|
||||
0));
|
||||
|
||||
nsresult rv = PackPDU(
|
||||
aRemoteAddr,
|
||||
PackConversion<nsAString, BluetoothPropertyType>(aName), *pdu);
|
||||
nsresult rv = PackPDU(aRemoteAddr, aType, *pdu);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -200,7 +197,7 @@ BluetoothDaemonCoreModule::GetRemoteDevicePropertyCmd(
|
||||
nsresult
|
||||
BluetoothDaemonCoreModule::SetRemoteDevicePropertyCmd(
|
||||
const BluetoothAddress& aRemoteAddr,
|
||||
const BluetoothNamedValue& aProperty,
|
||||
const BluetoothProperty& aProperty,
|
||||
BluetoothResultHandler* aRes)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
@ -373,7 +370,7 @@ BluetoothDaemonCoreModule::CancelBondCmd(const BluetoothAddress& aBdAddr,
|
||||
nsresult
|
||||
BluetoothDaemonCoreModule::PinReplyCmd(const BluetoothAddress& aBdAddr,
|
||||
bool aAccept,
|
||||
const nsAString& aPinCode,
|
||||
const BluetoothPinCode& aPinCode,
|
||||
BluetoothResultHandler* aRes)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
@ -382,10 +379,7 @@ BluetoothDaemonCoreModule::PinReplyCmd(const BluetoothAddress& aBdAddr,
|
||||
new DaemonSocketPDU(SERVICE_ID, OPCODE_PIN_REPLY,
|
||||
0));
|
||||
|
||||
nsresult rv = PackPDU(
|
||||
aBdAddr,
|
||||
aAccept,
|
||||
PackConversion<nsAString, BluetoothPinCode>(aPinCode), *pdu);
|
||||
nsresult rv = PackPDU(aBdAddr, aAccept, aPinCode, *pdu);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -961,7 +955,8 @@ public:
|
||||
{ }
|
||||
|
||||
nsresult
|
||||
operator () (BluetoothAddress& aArg1, nsString& aArg2, uint32_t& aArg3) const
|
||||
operator () (BluetoothAddress& aArg1, BluetoothRemoteName& aArg2,
|
||||
uint32_t& aArg3) const
|
||||
{
|
||||
DaemonSocketPDU& pdu = GetPDU();
|
||||
|
||||
@ -972,8 +967,7 @@ public:
|
||||
}
|
||||
|
||||
/* Read remote name */
|
||||
rv = UnpackPDU(
|
||||
pdu, UnpackConversion<BluetoothRemoteName, nsAString>(aArg2));
|
||||
rv = UnpackPDU(pdu, aArg2);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -1007,8 +1001,9 @@ public:
|
||||
{ }
|
||||
|
||||
nsresult
|
||||
operator () (BluetoothAddress& aArg1, nsString& aArg2, uint32_t& aArg3,
|
||||
BluetoothSspVariant& aArg4, uint32_t& aArg5) const
|
||||
operator () (BluetoothAddress& aArg1, BluetoothRemoteName& aArg2,
|
||||
uint32_t& aArg3, BluetoothSspVariant& aArg4,
|
||||
uint32_t& aArg5) const
|
||||
{
|
||||
DaemonSocketPDU& pdu = GetPDU();
|
||||
|
||||
@ -1019,8 +1014,7 @@ public:
|
||||
}
|
||||
|
||||
/* Read remote name */
|
||||
rv = UnpackPDU(
|
||||
pdu, UnpackConversion<BluetoothRemoteName, nsAString>(aArg2));
|
||||
rv = UnpackPDU(pdu, aArg2);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -1113,7 +1107,7 @@ public:
|
||||
|
||||
nsresult
|
||||
operator () (BluetoothStatus& aArg1, BluetoothAddress& aArg2,
|
||||
bool& aArg3) const
|
||||
BluetoothAclState& aArg3) const
|
||||
{
|
||||
DaemonSocketPDU& pdu = GetPDU();
|
||||
|
||||
@ -1130,8 +1124,7 @@ public:
|
||||
}
|
||||
|
||||
/* Read ACL state */
|
||||
rv = UnpackPDU(
|
||||
pdu, UnpackConversion<BluetoothAclState, bool>(aArg3));
|
||||
rv = UnpackPDU(pdu, aArg3);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -79,21 +79,21 @@ public:
|
||||
|
||||
nsresult GetAdapterPropertiesCmd(BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult GetAdapterPropertyCmd(const nsAString& aName,
|
||||
nsresult GetAdapterPropertyCmd(BluetoothPropertyType aType,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult SetAdapterPropertyCmd(const BluetoothNamedValue& aProperty,
|
||||
nsresult SetAdapterPropertyCmd(const BluetoothProperty& aProperty,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult GetRemoteDevicePropertiesCmd(const BluetoothAddress& aRemoteAddr,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult GetRemoteDevicePropertyCmd(const BluetoothAddress& aRemoteAddr,
|
||||
const nsAString& aName,
|
||||
BluetoothPropertyType aType,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult SetRemoteDevicePropertyCmd(const BluetoothAddress& aRemoteAddr,
|
||||
const BluetoothNamedValue& aProperty,
|
||||
const BluetoothProperty& aProperty,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult GetRemoteServiceRecordCmd(const BluetoothAddress& aRemoteAddr,
|
||||
@ -118,7 +118,7 @@ public:
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult PinReplyCmd(const BluetoothAddress& aBdAddr, bool aAccept,
|
||||
const nsAString& aPinCode,
|
||||
const BluetoothPinCode& aPinCode,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
nsresult SspReplyCmd(const BluetoothAddress& aBdAddr,
|
||||
@ -266,13 +266,16 @@ private:
|
||||
DiscoveryStateChangedNotification;
|
||||
|
||||
typedef mozilla::ipc::DaemonNotificationRunnable3<
|
||||
NotificationHandlerWrapper, void, BluetoothAddress, nsString, uint32_t,
|
||||
const BluetoothAddress&, const nsAString&>
|
||||
NotificationHandlerWrapper, void,
|
||||
BluetoothAddress, BluetoothRemoteName, uint32_t,
|
||||
const BluetoothAddress&, const BluetoothRemoteName&>
|
||||
PinRequestNotification;
|
||||
|
||||
typedef mozilla::ipc::DaemonNotificationRunnable5<
|
||||
NotificationHandlerWrapper, void, BluetoothAddress, nsString, uint32_t,
|
||||
BluetoothSspVariant, uint32_t, const BluetoothAddress&, const nsAString&>
|
||||
NotificationHandlerWrapper, void,
|
||||
BluetoothAddress, BluetoothRemoteName, uint32_t, BluetoothSspVariant,
|
||||
uint32_t,
|
||||
const BluetoothAddress&, const BluetoothRemoteName&>
|
||||
SspRequestNotification;
|
||||
|
||||
typedef mozilla::ipc::DaemonNotificationRunnable3<
|
||||
@ -281,7 +284,8 @@ private:
|
||||
BondStateChangedNotification;
|
||||
|
||||
typedef mozilla::ipc::DaemonNotificationRunnable3<
|
||||
NotificationHandlerWrapper, void, BluetoothStatus, BluetoothAddress, bool,
|
||||
NotificationHandlerWrapper, void,
|
||||
BluetoothStatus, BluetoothAddress, BluetoothAclState,
|
||||
BluetoothStatus, const BluetoothAddress&>
|
||||
AclStateChangedNotification;
|
||||
|
||||
|
@ -513,71 +513,6 @@ Convert(int32_t aIn, BluetoothGattStatus& aOut)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const nsAString& aIn, BluetoothPinCode& aOut)
|
||||
{
|
||||
if (MOZ_HAL_IPC_CONVERT_WARN_IF(
|
||||
aIn.Length() > MOZ_ARRAY_LENGTH(aOut.mPinCode), nsAString,
|
||||
BluetoothPinCode)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 pinCodeUTF8(aIn);
|
||||
const char* str = pinCodeUTF8.get();
|
||||
|
||||
nsAString::size_type i;
|
||||
|
||||
// Fill pin into aOut
|
||||
for (i = 0; i < aIn.Length(); ++i, ++str) {
|
||||
aOut.mPinCode[i] = static_cast<uint8_t>(*str);
|
||||
}
|
||||
|
||||
// Clear remaining bytes in aOut
|
||||
size_t ntrailing = (MOZ_ARRAY_LENGTH(aOut.mPinCode) - aIn.Length()) *
|
||||
sizeof(aOut.mPinCode[0]);
|
||||
memset(aOut.mPinCode + aIn.Length(), 0, ntrailing);
|
||||
|
||||
aOut.mLength = aIn.Length();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const nsAString& aIn, BluetoothPropertyType& aOut)
|
||||
{
|
||||
if (aIn.EqualsLiteral("Name")) {
|
||||
aOut = PROPERTY_BDNAME;
|
||||
} else if (aIn.EqualsLiteral("Discoverable")) {
|
||||
aOut = PROPERTY_ADAPTER_SCAN_MODE;
|
||||
} else if (aIn.EqualsLiteral("DiscoverableTimeout")) {
|
||||
aOut = PROPERTY_ADAPTER_DISCOVERY_TIMEOUT;
|
||||
} else if (MOZ_HAL_IPC_CONVERT_WARN_IF(
|
||||
false, nsAString, BluetoothPropertyType)) {
|
||||
BT_LOGR("Invalid property name: %s", NS_ConvertUTF16toUTF8(aIn).get());
|
||||
aOut = static_cast<BluetoothPropertyType>(0); // silences compiler warning
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const nsAString& aIn, BluetoothServiceName& aOut)
|
||||
{
|
||||
NS_ConvertUTF16toUTF8 serviceNameUTF8(aIn);
|
||||
const char* str = serviceNameUTF8.get();
|
||||
size_t len = strlen(str);
|
||||
|
||||
if (MOZ_HAL_IPC_CONVERT_WARN_IF(
|
||||
len > sizeof(aOut.mName), nsAString, BluetoothServiceName)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
memcpy(aOut.mName, str, len);
|
||||
memset(aOut.mName + len, 0, sizeof(aOut.mName) - len);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(nsresult aIn, BluetoothStatus& aOut)
|
||||
{
|
||||
@ -591,21 +526,6 @@ Convert(nsresult aIn, BluetoothStatus& aOut)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(BluetoothAclState aIn, bool& aOut)
|
||||
{
|
||||
static const bool sBool[] = {
|
||||
[ACL_STATE_CONNECTED] = true,
|
||||
[ACL_STATE_DISCONNECTED] = false
|
||||
};
|
||||
if (MOZ_HAL_IPC_CONVERT_WARN_IF(
|
||||
aIn >= MOZ_ARRAY_LENGTH(sBool), BluetoothAclState, bool)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
aOut = sBool[aIn];
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const BluetoothAttributeHandle& aIn, int32_t& aOut)
|
||||
{
|
||||
@ -904,18 +824,6 @@ Convert(BluetoothPropertyType aIn, uint8_t& aOut)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const BluetoothRemoteName& aIn, nsAString& aOut)
|
||||
{
|
||||
const char* name = reinterpret_cast<const char*>(aIn.mName);
|
||||
|
||||
// We construct an nsCString here because the string
|
||||
// returned from the PDU is not 0-terminated.
|
||||
aOut = NS_ConvertUTF8toUTF16(
|
||||
nsCString(name, strnlen(name, sizeof(aIn.mName))));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(BluetoothScanMode aIn, int32_t& aOut)
|
||||
{
|
||||
@ -1293,37 +1201,42 @@ PackPDU(const BluetoothHandsfreeWbsConfig& aIn, DaemonSocketPDU& aPDU)
|
||||
}
|
||||
|
||||
nsresult
|
||||
PackPDU(const BluetoothNamedValue& aIn, DaemonSocketPDU& aPDU)
|
||||
PackPDU(const BluetoothProperty& aIn, DaemonSocketPDU& aPDU)
|
||||
{
|
||||
nsresult rv = PackPDU(
|
||||
PackConversion<nsString, BluetoothPropertyType>(aIn.name()), aPDU);
|
||||
nsresult rv = PackPDU(aIn.mType, aPDU);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (aIn.value().type() == BluetoothValue::Tuint32_t) {
|
||||
// Set discoverable timeout
|
||||
rv = PackPDU(static_cast<uint16_t>(sizeof(uint32_t)),
|
||||
aIn.value().get_uint32_t(), aPDU);
|
||||
} else if (aIn.value().type() == BluetoothValue::TnsString) {
|
||||
// Set name
|
||||
const nsCString value =
|
||||
NS_ConvertUTF16toUTF8(aIn.value().get_nsString());
|
||||
switch (aIn.mType) {
|
||||
case PROPERTY_BDNAME:
|
||||
/* fall through */
|
||||
case PROPERTY_REMOTE_FRIENDLY_NAME: {
|
||||
NS_ConvertUTF16toUTF8 stringUTF8(aIn.mString);
|
||||
|
||||
rv = PackPDU(PackConversion<size_t, uint16_t>(value.Length()),
|
||||
PackArray<uint8_t>(
|
||||
reinterpret_cast<const uint8_t*>(value.get()),
|
||||
value.Length()),
|
||||
aPDU);
|
||||
} else if (aIn.value().type() == BluetoothValue::Tbool) {
|
||||
// Set scan mode
|
||||
bool value = aIn.value().get_bool();
|
||||
|
||||
rv = PackPDU(static_cast<uint16_t>(sizeof(int32_t)),
|
||||
PackConversion<bool, BluetoothScanMode>(value), aPDU);
|
||||
} else if (MOZ_HAL_IPC_PACK_WARN_IF(true, BluetoothNamedValue)) {
|
||||
BT_LOGR("Invalid property value type");
|
||||
rv = NS_ERROR_ILLEGAL_VALUE;
|
||||
rv = PackPDU(PackConversion<size_t, uint16_t>(stringUTF8.Length()),
|
||||
PackArray<uint8_t>(
|
||||
reinterpret_cast<const uint8_t*>(stringUTF8.get()),
|
||||
stringUTF8.Length()),
|
||||
aPDU);
|
||||
}
|
||||
break;
|
||||
case PROPERTY_CLASS_OF_DEVICE:
|
||||
/* fall through */
|
||||
case PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
|
||||
rv = PackPDU(PackConversion<size_t, uint16_t>(sizeof(aIn.mUint32)),
|
||||
aIn.mUint32,
|
||||
aPDU);
|
||||
break;
|
||||
case PROPERTY_ADAPTER_SCAN_MODE:
|
||||
/* |mScanMode| is sent as signed int of 4 bytes */
|
||||
rv = PackPDU(PackConversion<size_t, uint16_t>(sizeof(int32_t)),
|
||||
aIn.mScanMode,
|
||||
aPDU);
|
||||
break;
|
||||
default:
|
||||
NS_NOTREACHED("Invalid property for packing");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@ -1357,7 +1270,15 @@ PackPDU(BluetoothScanMode aIn, DaemonSocketPDU& aPDU)
|
||||
nsresult
|
||||
PackPDU(const BluetoothServiceName& aIn, DaemonSocketPDU& aPDU)
|
||||
{
|
||||
return PackPDU(PackArray<uint8_t>(aIn.mName, sizeof(aIn.mName)), aPDU);
|
||||
static const uint8_t sTerminator = '\0';
|
||||
|
||||
nsresult rv =
|
||||
PackPDU(PackArray<uint8_t>(aIn.mName, sizeof(aIn.mName)), aPDU);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
/* The PDU requries one additional byte for \0 termination */
|
||||
return aPDU.Write(sTerminator);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -27,11 +27,6 @@ using namespace mozilla::ipc::DaemonSocketPDUHelpers;
|
||||
// Helper structures
|
||||
//
|
||||
|
||||
enum BluetoothAclState {
|
||||
ACL_STATE_CONNECTED,
|
||||
ACL_STATE_DISCONNECTED
|
||||
};
|
||||
|
||||
struct BluetoothAvrcpAttributeTextPairs {
|
||||
BluetoothAvrcpAttributeTextPairs(const uint8_t* aAttr,
|
||||
const char** aText,
|
||||
@ -108,19 +103,6 @@ struct BluetoothConfigurationParameter {
|
||||
nsAutoArrayPtr<uint8_t> mValue;
|
||||
};
|
||||
|
||||
struct BluetoothPinCode {
|
||||
uint8_t mPinCode[16];
|
||||
uint8_t mLength;
|
||||
};
|
||||
|
||||
struct BluetoothRemoteName {
|
||||
uint8_t mName[249];
|
||||
};
|
||||
|
||||
struct BluetoothServiceName {
|
||||
uint8_t mName[256];
|
||||
};
|
||||
|
||||
//
|
||||
// Conversion
|
||||
//
|
||||
@ -200,18 +182,6 @@ Convert(int32_t aIn, BluetoothAttributeHandle& aOut);
|
||||
nsresult
|
||||
Convert(int32_t aIn, BluetoothGattStatus& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(const nsAString& aIn, BluetoothPinCode& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(const nsAString& aIn, BluetoothPropertyType& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(const nsAString& aIn, BluetoothServiceName& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(BluetoothAclState aIn, bool& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(const BluetoothAttributeHandle& aIn, int32_t& aOut);
|
||||
|
||||
@ -263,9 +233,6 @@ Convert(BluetoothHandsfreeWbsConfig aIn, uint8_t& aOut);
|
||||
nsresult
|
||||
Convert(BluetoothPropertyType aIn, uint8_t& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(const BluetoothRemoteName& aIn, nsAString& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(BluetoothScanMode aIn, uint8_t& aOut);
|
||||
|
||||
@ -357,7 +324,7 @@ nsresult
|
||||
PackPDU(const BluetoothHandsfreeWbsConfig& aIn, DaemonSocketPDU& aPDU);
|
||||
|
||||
nsresult
|
||||
PackPDU(const BluetoothNamedValue& aIn, DaemonSocketPDU& aPDU);
|
||||
PackPDU(const BluetoothProperty& aIn, DaemonSocketPDU& aPDU);
|
||||
|
||||
nsresult
|
||||
PackPDU(const BluetoothPinCode& aIn, DaemonSocketPDU& aPDU);
|
||||
@ -481,7 +448,17 @@ UnpackPDU(DaemonSocketPDU& aPDU, BluetoothRemoteInfo& aOut);
|
||||
inline nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, BluetoothRemoteName& aOut)
|
||||
{
|
||||
return aPDU.Read(aOut.mName, sizeof(aOut.mName));
|
||||
nsresult rv = aPDU.Read(aOut.mName, sizeof(aOut.mName));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
/* The PDU stores one extra byte for the trailing \0 character. We
|
||||
* consume the byte, but don't store the character.
|
||||
*/
|
||||
if (!aPDU.Consume(1)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -642,11 +642,11 @@ BluetoothDaemonInterface::GetAdapterProperties(BluetoothResultHandler* aRes)
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonInterface::GetAdapterProperty(const nsAString& aName,
|
||||
BluetoothDaemonInterface::GetAdapterProperty(BluetoothPropertyType aType,
|
||||
BluetoothResultHandler* aRes)
|
||||
{
|
||||
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||
(mProtocol)->GetAdapterPropertyCmd(aName, aRes);
|
||||
(mProtocol)->GetAdapterPropertyCmd(aType, aRes);
|
||||
if (NS_FAILED(rv)) {
|
||||
DispatchError(aRes, rv);
|
||||
}
|
||||
@ -654,7 +654,7 @@ BluetoothDaemonInterface::GetAdapterProperty(const nsAString& aName,
|
||||
|
||||
void
|
||||
BluetoothDaemonInterface::SetAdapterProperty(
|
||||
const BluetoothNamedValue& aProperty, BluetoothResultHandler* aRes)
|
||||
const BluetoothProperty& aProperty, BluetoothResultHandler* aRes)
|
||||
{
|
||||
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||
(mProtocol)->SetAdapterPropertyCmd(aProperty, aRes);
|
||||
@ -678,11 +678,11 @@ BluetoothDaemonInterface::GetRemoteDeviceProperties(
|
||||
|
||||
void
|
||||
BluetoothDaemonInterface::GetRemoteDeviceProperty(
|
||||
const BluetoothAddress& aRemoteAddr, const nsAString& aName,
|
||||
const BluetoothAddress& aRemoteAddr, BluetoothPropertyType aType,
|
||||
BluetoothResultHandler* aRes)
|
||||
{
|
||||
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||
(mProtocol)->GetRemoteDevicePropertyCmd(aRemoteAddr, aName, aRes);
|
||||
(mProtocol)->GetRemoteDevicePropertyCmd(aRemoteAddr, aType, aRes);
|
||||
if (NS_FAILED(rv)) {
|
||||
DispatchError(aRes, rv);
|
||||
}
|
||||
@ -690,7 +690,7 @@ BluetoothDaemonInterface::GetRemoteDeviceProperty(
|
||||
|
||||
void
|
||||
BluetoothDaemonInterface::SetRemoteDeviceProperty(
|
||||
const BluetoothAddress& aRemoteAddr, const BluetoothNamedValue& aProperty,
|
||||
const BluetoothAddress& aRemoteAddr, const BluetoothProperty& aProperty,
|
||||
BluetoothResultHandler* aRes)
|
||||
{
|
||||
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||
@ -797,7 +797,7 @@ BluetoothDaemonInterface::GetConnectionState(const BluetoothAddress& aBdAddr,
|
||||
void
|
||||
BluetoothDaemonInterface::PinReply(const BluetoothAddress& aBdAddr,
|
||||
bool aAccept,
|
||||
const nsAString& aPinCode,
|
||||
const BluetoothPinCode& aPinCode,
|
||||
BluetoothResultHandler* aRes)
|
||||
{
|
||||
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||
|
@ -55,9 +55,9 @@ public:
|
||||
/* Adapter Properties */
|
||||
|
||||
void GetAdapterProperties(BluetoothResultHandler* aRes) override;
|
||||
void GetAdapterProperty(const nsAString& aName,
|
||||
void GetAdapterProperty(BluetoothPropertyType aType,
|
||||
BluetoothResultHandler* aRes) override;
|
||||
void SetAdapterProperty(const BluetoothNamedValue& aProperty,
|
||||
void SetAdapterProperty(const BluetoothProperty& aProperty,
|
||||
BluetoothResultHandler* aRes) override;
|
||||
|
||||
/* Remote Device Properties */
|
||||
@ -65,10 +65,10 @@ public:
|
||||
void GetRemoteDeviceProperties(const BluetoothAddress& aRemoteAddr,
|
||||
BluetoothResultHandler* aRes) override;
|
||||
void GetRemoteDeviceProperty(const BluetoothAddress& aRemoteAddr,
|
||||
const nsAString& aName,
|
||||
BluetoothPropertyType aType,
|
||||
BluetoothResultHandler* aRes) override;
|
||||
void SetRemoteDeviceProperty(const BluetoothAddress& aRemoteAddr,
|
||||
const BluetoothNamedValue& aProperty,
|
||||
const BluetoothProperty& aProperty,
|
||||
BluetoothResultHandler* aRes) override;
|
||||
|
||||
/* Remote Services */
|
||||
@ -102,7 +102,7 @@ public:
|
||||
/* Authentication */
|
||||
|
||||
void PinReply(const BluetoothAddress& aBdAddr, bool aAccept,
|
||||
const nsAString& aPinCode,
|
||||
const BluetoothPinCode& aPinCode,
|
||||
BluetoothResultHandler* aRes) override;
|
||||
|
||||
void SspReply(const BluetoothAddress& aBdAddr,
|
||||
|
@ -24,7 +24,7 @@ const int BluetoothDaemonSocketModule::MAX_NUM_CLIENTS = 1;
|
||||
|
||||
nsresult
|
||||
BluetoothDaemonSocketModule::ListenCmd(BluetoothSocketType aType,
|
||||
const nsAString& aServiceName,
|
||||
const BluetoothServiceName& aServiceName,
|
||||
const BluetoothUuid& aServiceUuid,
|
||||
int aChannel, bool aEncrypt,
|
||||
bool aAuth,
|
||||
@ -38,7 +38,7 @@ BluetoothDaemonSocketModule::ListenCmd(BluetoothSocketType aType,
|
||||
|
||||
nsresult rv = PackPDU(
|
||||
aType,
|
||||
PackConversion<nsAString, BluetoothServiceName>(aServiceName),
|
||||
aServiceName,
|
||||
aServiceUuid,
|
||||
PackConversion<int, int32_t>(aChannel),
|
||||
SocketFlags(aEncrypt, aAuth), *pdu);
|
||||
@ -306,7 +306,7 @@ BluetoothDaemonSocketInterface::~BluetoothDaemonSocketInterface()
|
||||
|
||||
void
|
||||
BluetoothDaemonSocketInterface::Listen(BluetoothSocketType aType,
|
||||
const nsAString& aServiceName,
|
||||
const BluetoothServiceName& aServiceName,
|
||||
const BluetoothUuid& aServiceUuid,
|
||||
int aChannel, bool aEncrypt,
|
||||
bool aAuth,
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
//
|
||||
|
||||
nsresult ListenCmd(BluetoothSocketType aType,
|
||||
const nsAString& aServiceName,
|
||||
const BluetoothServiceName& aServiceName,
|
||||
const BluetoothUuid& aServiceUuid,
|
||||
int aChannel, bool aEncrypt, bool aAuth,
|
||||
BluetoothSocketResultHandler* aRes);
|
||||
@ -112,7 +112,7 @@ public:
|
||||
~BluetoothDaemonSocketInterface();
|
||||
|
||||
void Listen(BluetoothSocketType aType,
|
||||
const nsAString& aServiceName,
|
||||
const BluetoothServiceName& aServiceName,
|
||||
const BluetoothUuid& aServiceUuid,
|
||||
int aChannel, bool aEncrypt, bool aAuth,
|
||||
BluetoothSocketResultHandler* aRes) override;
|
||||
|
@ -1046,8 +1046,16 @@ BluetoothServiceBluedroid::SetProperty(BluetoothObjectType aType,
|
||||
|
||||
ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
|
||||
|
||||
BluetoothProperty property;
|
||||
nsresult rv = NamedValueToProperty(aValue, property);
|
||||
if (NS_FAILED(rv)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return rv;
|
||||
}
|
||||
|
||||
mSetAdapterPropertyRunnables.AppendElement(aRunnable);
|
||||
sBtInterface->SetAdapterProperty(aValue,
|
||||
sBtInterface->SetAdapterProperty(
|
||||
property,
|
||||
new DispatchReplyErrorResultHandler(mSetAdapterPropertyRunnables,
|
||||
aRunnable));
|
||||
|
||||
@ -1347,7 +1355,14 @@ BluetoothServiceBluedroid::PinReplyInternal(
|
||||
return;
|
||||
}
|
||||
|
||||
sBtInterface->PinReply(address, aAccept, aPinCode,
|
||||
BluetoothPinCode pinCode;
|
||||
rv = StringToPinCode(aPinCode, pinCode);
|
||||
if (NS_FAILED(rv)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
sBtInterface->PinReply(address, aAccept, pinCode,
|
||||
new PinReplyResultHandler(aRunnable));
|
||||
}
|
||||
|
||||
@ -1940,7 +1955,7 @@ BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState)
|
||||
// be connectable and non-discoverable.
|
||||
NS_ENSURE_TRUE_VOID(sBtInterface);
|
||||
sBtInterface->SetAdapterProperty(
|
||||
BluetoothNamedValue(NS_ConvertUTF8toUTF16("Discoverable"), false),
|
||||
BluetoothProperty(PROPERTY_ADAPTER_SCAN_MODE, SCAN_MODE_CONNECTABLE),
|
||||
new SetAdapterPropertyDiscoverableResultHandler());
|
||||
|
||||
// Trigger OPP & PBAP managers to listen
|
||||
@ -2286,7 +2301,8 @@ BluetoothServiceBluedroid::DiscoveryStateChangedNotification(bool aState)
|
||||
|
||||
void
|
||||
BluetoothServiceBluedroid::PinRequestNotification(
|
||||
const BluetoothAddress& aRemoteBdAddr, const nsAString& aBdName, uint32_t aCod)
|
||||
const BluetoothAddress& aRemoteBdAddr, const BluetoothRemoteName& aBdName,
|
||||
uint32_t aCod)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
@ -2297,7 +2313,9 @@ BluetoothServiceBluedroid::PinRequestNotification(
|
||||
nsAutoString bdAddr;
|
||||
AddressToString(aRemoteBdAddr, bdAddr);
|
||||
|
||||
nsString bdName(aBdName);
|
||||
nsAutoString bdName;
|
||||
RemoteNameToString(aBdName, bdName);
|
||||
|
||||
if (bdName.IsEmpty()) {
|
||||
mDeviceNameMap.Get(aRemoteBdAddr, &bdName);
|
||||
} else {
|
||||
@ -2318,7 +2336,7 @@ BluetoothServiceBluedroid::PinRequestNotification(
|
||||
|
||||
void
|
||||
BluetoothServiceBluedroid::SspRequestNotification(
|
||||
const BluetoothAddress& aRemoteBdAddr, const nsAString& aBdName,
|
||||
const BluetoothAddress& aRemoteBdAddr, const BluetoothRemoteName& aBdName,
|
||||
uint32_t aCod, BluetoothSspVariant aPairingVariant, uint32_t aPassKey)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
@ -2330,7 +2348,9 @@ BluetoothServiceBluedroid::SspRequestNotification(
|
||||
nsAutoString bdAddr;
|
||||
AddressToString(aRemoteBdAddr, bdAddr);
|
||||
|
||||
nsString bdName(aBdName);
|
||||
nsAutoString bdName;
|
||||
RemoteNameToString(aBdName, bdName);
|
||||
|
||||
if (bdName.IsEmpty()) {
|
||||
mDeviceNameMap.Get(aRemoteBdAddr, &bdName);
|
||||
} else {
|
||||
@ -2460,7 +2480,8 @@ BluetoothServiceBluedroid::BondStateChangedNotification(
|
||||
|
||||
void
|
||||
BluetoothServiceBluedroid::AclStateChangedNotification(
|
||||
BluetoothStatus aStatus, const BluetoothAddress& aRemoteBdAddr, bool aState)
|
||||
BluetoothStatus aStatus, const BluetoothAddress& aRemoteBdAddr,
|
||||
BluetoothAclState aState)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
|
@ -398,10 +398,10 @@ public:
|
||||
virtual void DiscoveryStateChangedNotification(bool aState) override;
|
||||
|
||||
virtual void PinRequestNotification(const BluetoothAddress& aRemoteBdAddr,
|
||||
const nsAString& aBdName,
|
||||
const BluetoothRemoteName& aBdName,
|
||||
uint32_t aCod) override;
|
||||
virtual void SspRequestNotification(const BluetoothAddress& aRemoteBdAddr,
|
||||
const nsAString& aBdName,
|
||||
const BluetoothRemoteName& aBdName,
|
||||
uint32_t aCod,
|
||||
BluetoothSspVariant aPairingVariant,
|
||||
uint32_t aPasskey) override;
|
||||
@ -411,7 +411,7 @@ public:
|
||||
BluetoothBondState aState) override;
|
||||
virtual void AclStateChangedNotification(
|
||||
BluetoothStatus aStatus, const BluetoothAddress& aRemoteBdAddr,
|
||||
bool aState) override;
|
||||
BluetoothAclState aState) override;
|
||||
|
||||
virtual void DutModeRecvNotification(uint16_t aOpcode,
|
||||
const uint8_t* aBuf,
|
||||
|
@ -732,6 +732,12 @@ BluetoothSocket::Listen(const nsAString& aServiceName,
|
||||
{
|
||||
MOZ_ASSERT(!mImpl);
|
||||
|
||||
BluetoothServiceName serviceName;
|
||||
nsresult rv = StringToServiceName(aServiceName, serviceName);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
SetConnectionStatus(SOCKET_LISTENING);
|
||||
|
||||
mImpl = new DroidSocketImpl(aConsumerLoop, aIOLoop, this);
|
||||
@ -741,7 +747,7 @@ BluetoothSocket::Listen(const nsAString& aServiceName,
|
||||
|
||||
sBluetoothSocketInterface->Listen(
|
||||
aType,
|
||||
aServiceName, aServiceUuid, aChannel,
|
||||
serviceName, aServiceUuid, aChannel,
|
||||
aEncrypt, aAuth, res);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -312,6 +312,11 @@ enum BluetoothStatus {
|
||||
NUM_STATUS
|
||||
};
|
||||
|
||||
enum BluetoothAclState {
|
||||
ACL_STATE_CONNECTED,
|
||||
ACL_STATE_DISCONNECTED
|
||||
};
|
||||
|
||||
enum BluetoothBondState {
|
||||
BOND_STATE_NONE,
|
||||
BOND_STATE_BONDING,
|
||||
@ -492,6 +497,15 @@ struct BluetoothUuid {
|
||||
}
|
||||
};
|
||||
|
||||
struct BluetoothPinCode {
|
||||
uint8_t mPinCode[16]; /* not \0-terminated */
|
||||
uint8_t mLength;
|
||||
};
|
||||
|
||||
struct BluetoothServiceName {
|
||||
uint8_t mName[255]; /* not \0-terminated */
|
||||
};
|
||||
|
||||
struct BluetoothServiceRecord {
|
||||
BluetoothUuid mUuid;
|
||||
uint16_t mChannel;
|
||||
@ -504,6 +518,10 @@ struct BluetoothRemoteInfo {
|
||||
int mManufacturer;
|
||||
};
|
||||
|
||||
struct BluetoothRemoteName {
|
||||
uint8_t mName[248]; /* not \0-terminated */
|
||||
};
|
||||
|
||||
struct BluetoothProperty {
|
||||
/* Type */
|
||||
BluetoothPropertyType mType;
|
||||
@ -542,6 +560,68 @@ struct BluetoothProperty {
|
||||
|
||||
/* PROPERTY_REMOTE_VERSION_INFO */
|
||||
BluetoothRemoteInfo mRemoteInfo;
|
||||
|
||||
BluetoothProperty()
|
||||
: mType(PROPERTY_UNKNOWN)
|
||||
{ }
|
||||
|
||||
explicit BluetoothProperty(BluetoothPropertyType aType,
|
||||
const BluetoothAddress& aBdAddress)
|
||||
: mType(aType)
|
||||
, mBdAddress(aBdAddress)
|
||||
{ }
|
||||
|
||||
explicit BluetoothProperty(BluetoothPropertyType aType,
|
||||
const nsAString& aString)
|
||||
: mType(aType)
|
||||
, mString(aString)
|
||||
{ }
|
||||
|
||||
explicit BluetoothProperty(BluetoothPropertyType aType,
|
||||
const nsTArray<BluetoothUuid>& aUuidArray)
|
||||
: mType(aType)
|
||||
, mUuidArray(aUuidArray)
|
||||
{ }
|
||||
|
||||
explicit BluetoothProperty(BluetoothPropertyType aType,
|
||||
const nsTArray<BluetoothAddress>& aBdAddressArray)
|
||||
: mType(aType)
|
||||
, mBdAddressArray(aBdAddressArray)
|
||||
{ }
|
||||
|
||||
explicit BluetoothProperty(BluetoothPropertyType aType, uint32_t aUint32)
|
||||
: mType(aType)
|
||||
, mUint32(aUint32)
|
||||
{ }
|
||||
|
||||
explicit BluetoothProperty(BluetoothPropertyType aType, int32_t aInt32)
|
||||
: mType(aType)
|
||||
, mInt32(aInt32)
|
||||
{ }
|
||||
|
||||
explicit BluetoothProperty(BluetoothPropertyType aType,
|
||||
BluetoothTypeOfDevice aTypeOfDevice)
|
||||
: mType(aType)
|
||||
, mTypeOfDevice(aTypeOfDevice)
|
||||
{ }
|
||||
|
||||
explicit BluetoothProperty(BluetoothPropertyType aType,
|
||||
const BluetoothServiceRecord& aServiceRecord)
|
||||
: mType(aType)
|
||||
, mServiceRecord(aServiceRecord)
|
||||
{ }
|
||||
|
||||
explicit BluetoothProperty(BluetoothPropertyType aType,
|
||||
BluetoothScanMode aScanMode)
|
||||
: mType(aType)
|
||||
, mScanMode(aScanMode)
|
||||
{ }
|
||||
|
||||
explicit BluetoothProperty(BluetoothPropertyType aType,
|
||||
const BluetoothRemoteInfo& aRemoteInfo)
|
||||
: mType(aType)
|
||||
, mRemoteInfo(aRemoteInfo)
|
||||
{ }
|
||||
};
|
||||
|
||||
enum BluetoothSocketType {
|
||||
|
@ -876,13 +876,13 @@ BluetoothNotificationHandler::DiscoveryStateChangedNotification(bool aState)
|
||||
|
||||
void
|
||||
BluetoothNotificationHandler::PinRequestNotification(
|
||||
const BluetoothAddress& aRemoteBdAddr, const nsAString& aBdName,
|
||||
const BluetoothAddress& aRemoteBdAddr, const BluetoothRemoteName& aBdName,
|
||||
uint32_t aCod)
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothNotificationHandler::SspRequestNotification(
|
||||
const BluetoothAddress& aRemoteBdAddr, const nsAString& aBdName,
|
||||
const BluetoothAddress& aRemoteBdAddr, const BluetoothRemoteName& aBdName,
|
||||
uint32_t aCod, BluetoothSspVariant aPairingVariant, uint32_t aPassKey)
|
||||
{ }
|
||||
|
||||
@ -894,7 +894,8 @@ BluetoothNotificationHandler::BondStateChangedNotification(
|
||||
|
||||
void
|
||||
BluetoothNotificationHandler::AclStateChangedNotification(
|
||||
BluetoothStatus aStatus, const BluetoothAddress& aRemoteBdAddr, bool aState)
|
||||
BluetoothStatus aStatus, const BluetoothAddress& aRemoteBdAddr,
|
||||
BluetoothAclState aState)
|
||||
{ }
|
||||
|
||||
void
|
||||
|
@ -56,7 +56,7 @@ public:
|
||||
// Init and Cleanup is handled by BluetoothInterface
|
||||
|
||||
virtual void Listen(BluetoothSocketType aType,
|
||||
const nsAString& aServiceName,
|
||||
const BluetoothServiceName& aServiceName,
|
||||
const BluetoothUuid& aServiceUuid,
|
||||
int aChannel, bool aEncrypt, bool aAuth,
|
||||
BluetoothSocketResultHandler* aRes) = 0;
|
||||
@ -949,10 +949,10 @@ public:
|
||||
virtual void DiscoveryStateChangedNotification(bool aState);
|
||||
|
||||
virtual void PinRequestNotification(const BluetoothAddress& aRemoteBdAddr,
|
||||
const nsAString& aBdName,
|
||||
const BluetoothRemoteName& aBdName,
|
||||
uint32_t aCod);
|
||||
virtual void SspRequestNotification(const BluetoothAddress& aRemoteBdAddr,
|
||||
const nsAString& aBdName,
|
||||
const BluetoothRemoteName& aBdName,
|
||||
uint32_t aCod,
|
||||
BluetoothSspVariant aPairingVariant,
|
||||
uint32_t aPassKey);
|
||||
@ -962,7 +962,7 @@ public:
|
||||
BluetoothBondState aState);
|
||||
virtual void AclStateChangedNotification(
|
||||
BluetoothStatus aStatus, const BluetoothAddress& aRemoteBdAddr,
|
||||
bool aState);
|
||||
BluetoothAclState aState);
|
||||
|
||||
virtual void DutModeRecvNotification(uint16_t aOpcode,
|
||||
const uint8_t* aBuf, uint8_t aLen);
|
||||
@ -1038,9 +1038,9 @@ public:
|
||||
/* Adapter Properties */
|
||||
|
||||
virtual void GetAdapterProperties(BluetoothResultHandler* aRes) = 0;
|
||||
virtual void GetAdapterProperty(const nsAString& aName,
|
||||
virtual void GetAdapterProperty(BluetoothPropertyType,
|
||||
BluetoothResultHandler* aRes) = 0;
|
||||
virtual void SetAdapterProperty(const BluetoothNamedValue& aProperty,
|
||||
virtual void SetAdapterProperty(const BluetoothProperty& aProperty,
|
||||
BluetoothResultHandler* aRes) = 0;
|
||||
|
||||
/* Remote Device Properties */
|
||||
@ -1048,10 +1048,10 @@ public:
|
||||
virtual void GetRemoteDeviceProperties(const BluetoothAddress& aRemoteAddr,
|
||||
BluetoothResultHandler* aRes) = 0;
|
||||
virtual void GetRemoteDeviceProperty(const BluetoothAddress& aRemoteAddr,
|
||||
const nsAString& aName,
|
||||
BluetoothPropertyType aType,
|
||||
BluetoothResultHandler* aRes) = 0;
|
||||
virtual void SetRemoteDeviceProperty(const BluetoothAddress& aRemoteAddr,
|
||||
const BluetoothNamedValue& aProperty,
|
||||
const BluetoothProperty& aProperty,
|
||||
BluetoothResultHandler* aRes) = 0;
|
||||
|
||||
/* Remote Services */
|
||||
@ -1085,7 +1085,7 @@ public:
|
||||
/* Authentication */
|
||||
|
||||
virtual void PinReply(const BluetoothAddress& aBdAddr, bool aAccept,
|
||||
const nsAString& aPinCode,
|
||||
const BluetoothPinCode& aPinCode,
|
||||
BluetoothResultHandler* aRes) = 0;
|
||||
|
||||
virtual void SspReply(const BluetoothAddress& aBdAddr,
|
||||
|
@ -61,6 +61,126 @@ StringToAddress(const nsAString& aString, BluetoothAddress& aAddress)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
StringToPinCode(const nsAString& aString, BluetoothPinCode& aPinCode)
|
||||
{
|
||||
NS_ConvertUTF16toUTF8 stringUTF8(aString);
|
||||
|
||||
auto len = stringUTF8.Length();
|
||||
|
||||
if (len > sizeof(aPinCode.mPinCode)) {
|
||||
BT_LOGR("Service-name string too long");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
auto str = stringUTF8.get();
|
||||
|
||||
memcpy(aPinCode.mPinCode, str, len);
|
||||
memset(aPinCode.mPinCode + len, 0, sizeof(aPinCode.mPinCode) - len);
|
||||
aPinCode.mLength = len;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
StringToPropertyType(const nsAString& aString, BluetoothPropertyType& aType)
|
||||
{
|
||||
if (aString.EqualsLiteral("Name")) {
|
||||
aType = PROPERTY_BDNAME;
|
||||
} else if (aString.EqualsLiteral("Discoverable")) {
|
||||
aType = PROPERTY_ADAPTER_SCAN_MODE;
|
||||
} else if (aString.EqualsLiteral("DiscoverableTimeout")) {
|
||||
aType = PROPERTY_ADAPTER_DISCOVERY_TIMEOUT;
|
||||
} else {
|
||||
BT_LOGR("Invalid property name: %s", NS_ConvertUTF16toUTF8(aString).get());
|
||||
aType = PROPERTY_UNKNOWN; // silences compiler warning
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NamedValueToProperty(const BluetoothNamedValue& aValue,
|
||||
BluetoothProperty& aProperty)
|
||||
{
|
||||
nsresult rv = StringToPropertyType(aValue.name(), aProperty.mType);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
switch (aProperty.mType) {
|
||||
case PROPERTY_BDNAME:
|
||||
if (aValue.value().type() != BluetoothValue::TnsString) {
|
||||
BT_LOGR("Bluetooth property value is not a string");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
// Set name
|
||||
aProperty.mString = aValue.value().get_nsString();
|
||||
break;
|
||||
|
||||
case PROPERTY_ADAPTER_SCAN_MODE:
|
||||
if (aValue.value().type() != BluetoothValue::Tbool) {
|
||||
BT_LOGR("Bluetooth property value is not a boolean");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
// Set scan mode
|
||||
if (aValue.value().get_bool()) {
|
||||
aProperty.mScanMode = SCAN_MODE_CONNECTABLE_DISCOVERABLE;
|
||||
} else {
|
||||
aProperty.mScanMode = SCAN_MODE_CONNECTABLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
|
||||
if (aValue.value().type() != BluetoothValue::Tuint32_t) {
|
||||
BT_LOGR("Bluetooth property value is not an unsigned integer");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
// Set discoverable timeout
|
||||
aProperty.mUint32 = aValue.value().get_uint32_t();
|
||||
break;
|
||||
|
||||
default:
|
||||
BT_LOGR("Invalid property value type");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
RemoteNameToString(const BluetoothRemoteName& aRemoteName, nsAString& aString)
|
||||
{
|
||||
auto name = reinterpret_cast<const char*>(aRemoteName.mName);
|
||||
|
||||
/* The content in |BluetoothRemoteName| is not a C string and not
|
||||
* terminated by \0. We use |strnlen| to limit its length.
|
||||
*/
|
||||
aString =
|
||||
NS_ConvertUTF8toUTF16(name, strnlen(name, sizeof(aRemoteName.mName)));
|
||||
}
|
||||
|
||||
nsresult
|
||||
StringToServiceName(const nsAString& aString,
|
||||
BluetoothServiceName& aServiceName)
|
||||
{
|
||||
NS_ConvertUTF16toUTF8 serviceNameUTF8(aString);
|
||||
|
||||
auto len = serviceNameUTF8.Length();
|
||||
|
||||
if (len > sizeof(aServiceName.mName)) {
|
||||
BT_LOGR("Service-name string too long");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
auto str = serviceNameUTF8.get();
|
||||
|
||||
memcpy(aServiceName.mName, str, len);
|
||||
memset(aServiceName.mName + len, 0, sizeof(aServiceName.mName) - len);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
UuidToString(const BluetoothUuid& aUuid, nsAString& aString)
|
||||
{
|
||||
|
@ -33,6 +33,43 @@ AddressToString(const BluetoothAddress& aAddress, nsAString& aString);
|
||||
nsresult
|
||||
StringToAddress(const nsAString& aString, BluetoothAddress& aAddress);
|
||||
|
||||
//
|
||||
// Pin code/string conversion
|
||||
//
|
||||
|
||||
nsresult
|
||||
StringToPinCode(const nsAString& aString, BluetoothPinCode& aPinCode);
|
||||
|
||||
//
|
||||
// Property type/string conversion
|
||||
//
|
||||
|
||||
nsresult
|
||||
StringToPropertyType(const nsAString& aString, BluetoothPropertyType& aType);
|
||||
|
||||
//
|
||||
// Property conversion
|
||||
//
|
||||
|
||||
nsresult
|
||||
NamedValueToProperty(const BluetoothNamedValue& aIn,
|
||||
BluetoothProperty& aProperty);
|
||||
|
||||
//
|
||||
// Remote name/string conversion
|
||||
//
|
||||
|
||||
void
|
||||
RemoteNameToString(const BluetoothRemoteName& aRemoteName, nsAString& aString);
|
||||
|
||||
//
|
||||
// Service name/string conversion
|
||||
//
|
||||
|
||||
nsresult
|
||||
StringToServiceName(const nsAString& aString,
|
||||
BluetoothServiceName& aServiceName);
|
||||
|
||||
//
|
||||
// BluetoothUuid <-> uuid string conversion
|
||||
//
|
||||
|
@ -1472,7 +1472,6 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
|
||||
return mode;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
int32_t
|
||||
CanvasRenderingContext2D::GetWidth() const
|
||||
{
|
||||
@ -1484,7 +1483,6 @@ CanvasRenderingContext2D::GetHeight() const
|
||||
{
|
||||
return mHeight;
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
CanvasRenderingContext2D::SetDimensions(int32_t width, int32_t height)
|
||||
|
@ -418,10 +418,9 @@ public:
|
||||
|
||||
nsresult Redraw();
|
||||
|
||||
#ifdef DEBUG
|
||||
virtual int32_t GetWidth() const override;
|
||||
virtual int32_t GetHeight() const override;
|
||||
#endif
|
||||
virtual int32_t GetWidth() const override;
|
||||
virtual int32_t GetHeight() const override;
|
||||
|
||||
// nsICanvasRenderingContextInternal
|
||||
/**
|
||||
* Gets the pres shell from either the canvas element or the doc shell
|
||||
|
@ -480,7 +480,6 @@ WebGLContext::SetContextOptions(JSContext* cx, JS::Handle<JS::Value> options)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
int32_t
|
||||
WebGLContext::GetWidth() const
|
||||
{
|
||||
@ -492,7 +491,6 @@ WebGLContext::GetHeight() const
|
||||
{
|
||||
return mHeight;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* So there are a number of points of failure here. We might fail based
|
||||
* on EGL vs. WGL, or we might fail to alloc a too-large size, or we
|
||||
|
@ -215,10 +215,9 @@ public:
|
||||
NS_DECL_NSIDOMWEBGLRENDERINGCONTEXT
|
||||
|
||||
// nsICanvasRenderingContextInternal
|
||||
#ifdef DEBUG
|
||||
virtual int32_t GetWidth() const override;
|
||||
virtual int32_t GetHeight() const override;
|
||||
#endif
|
||||
|
||||
NS_IMETHOD SetDimensions(int32_t width, int32_t height) override;
|
||||
NS_IMETHOD InitializeWithSurface(nsIDocShell*, gfxASurface*, int32_t,
|
||||
int32_t) override
|
||||
|
@ -80,11 +80,9 @@ public:
|
||||
return mCanvasElement;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Useful for testing
|
||||
virtual int32_t GetWidth() const = 0;
|
||||
virtual int32_t GetHeight() const = 0;
|
||||
#endif
|
||||
// Dimensions of the canvas, in pixels.
|
||||
virtual int32_t GetWidth() const = 0;
|
||||
virtual int32_t GetHeight() const = 0;
|
||||
|
||||
// Sets the dimensions of the canvas, in pixels. Called
|
||||
// whenever the size of the element changes.
|
||||
|
@ -669,18 +669,19 @@ HTMLCanvasElement::ToBlob(JSContext* aCx,
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (mCurrentContext) {
|
||||
// We disallow canvases of width or height zero, and set them to 1, so
|
||||
// we will have a discrepancy with the sizes of the canvas and the context.
|
||||
// That discrepancy is OK, the rest are not.
|
||||
nsIntSize elementSize = GetWidthHeight();
|
||||
MOZ_ASSERT(elementSize.width == mCurrentContext->GetWidth() ||
|
||||
(elementSize.width == 0 && mCurrentContext->GetWidth() == 1));
|
||||
MOZ_ASSERT(elementSize.height == mCurrentContext->GetHeight() ||
|
||||
(elementSize.height == 0 && mCurrentContext->GetHeight() == 1));
|
||||
if ((elementSize.width != mCurrentContext->GetWidth() &&
|
||||
(elementSize.width != 0 || mCurrentContext->GetWidth() != 1)) ||
|
||||
(elementSize.height != mCurrentContext->GetHeight() &&
|
||||
(elementSize.height != 0 || mCurrentContext->GetHeight() != 1))) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t* imageBuffer = nullptr;
|
||||
int32_t format = 0;
|
||||
|
@ -1519,7 +1519,7 @@ nsHTMLDocument::Open(JSContext* cx,
|
||||
|
||||
if (cv) {
|
||||
bool okToUnload;
|
||||
if (NS_SUCCEEDED(cv->PermitUnload(false, &okToUnload)) && !okToUnload) {
|
||||
if (NS_SUCCEEDED(cv->PermitUnload(&okToUnload)) && !okToUnload) {
|
||||
// We don't want to unload, so stop here, but don't throw an
|
||||
// exception.
|
||||
nsCOMPtr<nsIDocument> ret = this;
|
||||
|
@ -23,7 +23,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=448166
|
||||
/** Test for Bug 448166 **/
|
||||
isnot($("test").href, "http://www.mozilla.org/",
|
||||
"Should notice unpaired surrogate");
|
||||
is($("test").href, "http://www.moz\ufffdilla.org/",
|
||||
is($("test").href, "http://www.xn--mozilla-2e14b.org/",
|
||||
"Should replace unpaired surrogate with replacement char");
|
||||
is($("control").href, "http://www.mozilla.org/",
|
||||
"Just making sure .href works");
|
||||
|
@ -17,7 +17,7 @@ interface nsIOpenURIInFrameParams : nsISupports
|
||||
attribute boolean isPrivate;
|
||||
};
|
||||
|
||||
[scriptable, uuid(99f5a347-722c-4337-bd38-f14ec94801b3)]
|
||||
[scriptable, uuid(31da1ce2-aec4-4c26-ac66-d622935c3bf4)]
|
||||
|
||||
/**
|
||||
* The C++ source has access to the browser script source through
|
||||
@ -99,6 +99,14 @@ 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);
|
||||
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();
|
||||
};
|
||||
|
||||
|
@ -749,7 +749,7 @@ nsJSChannel::EvaluateScript()
|
||||
if (cv) {
|
||||
bool okToUnload;
|
||||
|
||||
if (NS_SUCCEEDED(cv->PermitUnload(false, &okToUnload)) &&
|
||||
if (NS_SUCCEEDED(cv->PermitUnload(&okToUnload)) &&
|
||||
!okToUnload) {
|
||||
// The user didn't want to unload the current
|
||||
// page, translate this into an undefined
|
||||
|
@ -200,10 +200,10 @@ DecoderTraits::IsWebMType(const nsACString& aType)
|
||||
static bool
|
||||
IsGStreamerSupportedType(const nsACString& aMimeType)
|
||||
{
|
||||
if (!MediaDecoder::IsGStreamerEnabled())
|
||||
if (DecoderTraits::IsWebMType(aMimeType))
|
||||
return false;
|
||||
|
||||
if (DecoderTraits::IsWebMType(aMimeType) && !Preferences::GetBool("media.prefer-gstreamer", false))
|
||||
if (!MediaDecoder::IsGStreamerEnabled())
|
||||
return false;
|
||||
|
||||
if (IsOggType(aMimeType) && !Preferences::GetBool("media.prefer-gstreamer", false))
|
||||
@ -366,7 +366,7 @@ static bool
|
||||
IsMP3SupportedType(const nsACString& aType,
|
||||
const nsAString& aCodecs = EmptyString())
|
||||
{
|
||||
return aType.EqualsASCII("audio/mpeg") && MP3Decoder::IsEnabled();
|
||||
return MP3Decoder::CanHandleMediaType(aType, aCodecs);
|
||||
}
|
||||
|
||||
#ifdef MOZ_APPLEMEDIA
|
||||
|
@ -10,10 +10,7 @@
|
||||
#include "MediaFormatReader.h"
|
||||
#include "MP3Demuxer.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
#include "AndroidBridge.h"
|
||||
#endif
|
||||
#include "PlatformDecoderModule.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -32,14 +29,61 @@ MP3Decoder::CreateStateMachine() {
|
||||
return new MediaDecoderStateMachine(this, reader);
|
||||
}
|
||||
|
||||
static already_AddRefed<MediaDataDecoder>
|
||||
CreateTestMP3Decoder(AudioInfo& aConfig)
|
||||
{
|
||||
PlatformDecoderModule::Init();
|
||||
|
||||
nsRefPtr<PlatformDecoderModule> platform = PlatformDecoderModule::Create();
|
||||
if (!platform || !platform->SupportsMimeType(aConfig.mMimeType)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<MediaDataDecoder> decoder(
|
||||
platform->CreateDecoder(aConfig, nullptr, nullptr));
|
||||
if (!decoder) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return decoder.forget();
|
||||
}
|
||||
|
||||
static bool
|
||||
CanCreateMP3Decoder()
|
||||
{
|
||||
static bool haveCachedResult = false;
|
||||
static bool result = false;
|
||||
if (haveCachedResult) {
|
||||
return result;
|
||||
}
|
||||
AudioInfo config;
|
||||
config.mMimeType = "audio/mpeg";
|
||||
config.mRate = 48000;
|
||||
config.mChannels = 2;
|
||||
config.mBitDepth = 16;
|
||||
nsRefPtr<MediaDataDecoder> decoder(CreateTestMP3Decoder(config));
|
||||
if (decoder) {
|
||||
result = true;
|
||||
}
|
||||
haveCachedResult = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
MP3Decoder::IsEnabled() {
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
// We need android.media.MediaCodec which exists in API level 16 and higher.
|
||||
return AndroidBridge::Bridge()->GetAPIVersion() >= 16;
|
||||
#else
|
||||
return Preferences::GetBool("media.mp3.enabled");
|
||||
#endif
|
||||
return CanCreateMP3Decoder();
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool MP3Decoder::CanHandleMediaType(const nsACString& aType,
|
||||
const nsAString& aCodecs)
|
||||
{
|
||||
if (aType.EqualsASCII("audio/mp3") || aType.EqualsASCII("audio/mpeg")) {
|
||||
return CanCreateMP3Decoder() &&
|
||||
(aCodecs.IsEmpty() || aCodecs.EqualsASCII("mp3"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -19,6 +19,8 @@ public:
|
||||
// Returns true if the MP3 backend is preffed on, and we're running on a
|
||||
// platform that is likely to have decoders for the format.
|
||||
static bool IsEnabled();
|
||||
static bool CanHandleMediaType(const nsACString& aType,
|
||||
const nsAString& aCodecs);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -318,10 +318,13 @@ MP3TrackDemuxer::GetResourceOffset() const {
|
||||
|
||||
TimeIntervals
|
||||
MP3TrackDemuxer::GetBuffered() {
|
||||
// TODO: bug 1169485.
|
||||
MP3DEMUXER_LOG("MP3TrackDemuxer::GetBuffered()");
|
||||
NS_WARNING("Unimplemented function GetBuffered");
|
||||
return TimeIntervals();
|
||||
TimeUnit duration = Duration();
|
||||
|
||||
if (duration <= TimeUnit()) {
|
||||
return TimeIntervals();
|
||||
}
|
||||
AutoPinned<MediaResource> stream(mSource.GetResource());
|
||||
return GetEstimatedBufferedTimeRanges(stream, duration.ToMicroseconds());
|
||||
}
|
||||
|
||||
int64_t
|
||||
@ -458,6 +461,8 @@ MP3TrackDemuxer::GetNextFrame(const MediaByteRange& aRange) {
|
||||
|
||||
frame->mTime = Duration(mFrameIndex - 1).ToMicroseconds();
|
||||
frame->mDuration = Duration(1).ToMicroseconds();
|
||||
frame->mTimecode = frame->mTime;
|
||||
frame->mKeyframe = true;
|
||||
|
||||
MOZ_ASSERT(frame->mTime >= 0);
|
||||
MOZ_ASSERT(frame->mDuration > 0);
|
||||
|
@ -26,6 +26,11 @@ public:
|
||||
bool IsSeekable() const override;
|
||||
void NotifyDataArrived(uint32_t aLength, int64_t aOffset) override;
|
||||
void NotifyDataRemoved() override;
|
||||
// Do not shift the calculated buffered range by the start time of the first
|
||||
// decoded frame. The mac MP3 decoder will buffer some samples and the first
|
||||
// frame returned has typically a start time that is non-zero, causing our
|
||||
// buffered range to have a negative start time.
|
||||
bool ShouldComputeStartTime() const override { return false; }
|
||||
|
||||
private:
|
||||
// Synchronous initialization.
|
||||
|
@ -387,8 +387,9 @@ RTCPeerConnection.prototype = {
|
||||
"RTCPeerConnection constructor passed invalid RTCConfiguration");
|
||||
}
|
||||
// Save the appId
|
||||
this._appId = Cu.getWebIDLCallerPrincipal().appId;
|
||||
this._https = this._win.document.documentURIObject.schemeIs("https");
|
||||
var principal = Cu.getWebIDLCallerPrincipal();
|
||||
this._appId = principal.appId;
|
||||
this._isChrome = Services.scriptSecurityManager.isSystemPrincipal(principal);
|
||||
|
||||
// Get the offline status for this appId
|
||||
let appOffline = false;
|
||||
@ -778,7 +779,8 @@ RTCPeerConnection.prototype = {
|
||||
if (this._havePermission) {
|
||||
return this._havePermission;
|
||||
}
|
||||
if (AppConstants.MOZ_B2G ||
|
||||
if (this._isChrome ||
|
||||
AppConstants.MOZ_B2G ||
|
||||
Services.prefs.getBoolPref("media.navigator.permission.disabled")) {
|
||||
return this._havePermission = Promise.resolve();
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ var gPlayedTests = [
|
||||
{ name:"seek.ogv", type:"video/ogg", duration:3.966 },
|
||||
{ name:"seek.webm", type:"video/webm", duration:3.966 },
|
||||
{ name:"gizmo.mp4", type:"video/mp4", duration:5.56 },
|
||||
{ name:"owl.mp3", type:"audio/mpeg", duration:3.29 },
|
||||
{ name:"owl.mp3", type:"audio/mpeg", duration:3.343 },
|
||||
// Disable vbr.mp3 to see if it reduces the error of AUDCLNT_E_CPUUSAGE_EXCEEDED.
|
||||
// See bug 1110922 comment 26.
|
||||
//{ name:"vbr.mp3", type:"audio/mpeg", duration:10.0 },
|
||||
@ -237,13 +237,13 @@ var gPlayTests = [
|
||||
|
||||
{ name:"small-shot.m4a", type:"audio/mp4", duration:0.29 },
|
||||
{ name:"small-shot.mp3", type:"audio/mpeg", duration:0.27 },
|
||||
{ name:"owl.mp3", type:"audio/mpeg", duration:3.29 },
|
||||
{ name:"owl.mp3", type:"audio/mpeg", duration:3.343 },
|
||||
// owl.mp3 as above, but with something funny going on in the ID3v2 tag
|
||||
// that causes DirectShow to fail.
|
||||
{ name:"owl-funny-id3.mp3", type:"audio/mpeg", duration:3.29 },
|
||||
{ name:"owl-funny-id3.mp3", type:"audio/mpeg", duration:3.343 },
|
||||
// owl.mp3 as above, but with something even funnier going on in the ID3v2 tag
|
||||
// that causes DirectShow to fail.
|
||||
{ name:"owl-funnier-id3.mp3", type:"audio/mpeg", duration:3.29 },
|
||||
{ name:"owl-funnier-id3.mp3", type:"audio/mpeg", duration:3.343 },
|
||||
// One second of silence with ~140KB of ID3 tags. Usually when the first MP3
|
||||
// frame is at such a high offset into the file, MP3FrameParser will give up
|
||||
// and report that the stream is not MP3. However, it does not count ID3 tags
|
||||
@ -469,7 +469,7 @@ var gSeekTests = [
|
||||
{ name:"split.webm", type:"video/webm", duration:1.967 },
|
||||
{ name:"detodos.opus", type:"audio/ogg; codecs=opus", duration:2.9135 },
|
||||
{ name:"gizmo.mp4", type:"video/mp4", duration:5.56 },
|
||||
{ name:"owl.mp3", type:"audio/mpeg", duration:3.29 },
|
||||
{ name:"owl.mp3", type:"audio/mpeg", duration:3.343 },
|
||||
{ name:"bogus.duh", type:"bogus/duh", duration:123 }
|
||||
];
|
||||
|
||||
@ -523,7 +523,7 @@ if (getAndroidVersion() >= 18) {
|
||||
var gAudioTests = [
|
||||
{ name:"r11025_s16_c1.wav", type:"audio/x-wav", duration:1.0 },
|
||||
{ name:"sound.ogg", type:"audio/ogg" },
|
||||
{ name:"owl.mp3", type:"audio/mpeg", duration:3.29 },
|
||||
{ name:"owl.mp3", type:"audio/mpeg", duration:3.343 },
|
||||
{ name:"small-shot.m4a", type:"audio/mp4", duration:0.29 },
|
||||
{ name:"bogus.duh", type:"bogus/duh", duration:123 }
|
||||
];
|
||||
|
@ -580,8 +580,8 @@ AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* aContext)
|
||||
, mLoopStart(0.0)
|
||||
, mLoopEnd(0.0)
|
||||
// mOffset and mDuration are initialized in Start().
|
||||
, mPlaybackRate(new AudioParam(this, SendPlaybackRateToStream, 1.0f, "playbackRate"))
|
||||
, mDetune(new AudioParam(this, SendDetuneToStream, 0.0f, "detune"))
|
||||
, mPlaybackRate(new AudioParam(this, PLAYBACKRATE, 1.0f, "playbackRate"))
|
||||
, mDetune(new AudioParam(this, DETUNE, 0.0f, "detune"))
|
||||
, mLoop(false)
|
||||
, mStartCalled(false)
|
||||
{
|
||||
@ -784,28 +784,6 @@ AudioBufferSourceNode::NotifyMainThreadStreamFinished()
|
||||
MarkInactive();
|
||||
}
|
||||
|
||||
void
|
||||
AudioBufferSourceNode::SendPlaybackRateToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
AudioBufferSourceNode* This = static_cast<AudioBufferSourceNode*>(aNode);
|
||||
if (!This->mStream) {
|
||||
return;
|
||||
}
|
||||
SendTimelineEventToStream(This, PLAYBACKRATE, aEvent);
|
||||
}
|
||||
|
||||
void
|
||||
AudioBufferSourceNode::SendDetuneToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
AudioBufferSourceNode* This = static_cast<AudioBufferSourceNode*>(aNode);
|
||||
if (!This->mStream) {
|
||||
return;
|
||||
}
|
||||
SendTimelineEventToStream(This, DETUNE, aEvent);
|
||||
}
|
||||
|
||||
void
|
||||
AudioBufferSourceNode::SendDopplerShiftToStream(double aDopplerShift)
|
||||
{
|
||||
|
@ -129,10 +129,6 @@ private:
|
||||
void SendLoopParametersToStream();
|
||||
void SendBufferParameterToStream(JSContext* aCx);
|
||||
void SendOffsetAndDurationParametersToStream(AudioNodeStream* aStream);
|
||||
static void SendPlaybackRateToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent);
|
||||
static void SendDetuneToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent);
|
||||
|
||||
private:
|
||||
double mLoopStart;
|
||||
|
@ -303,15 +303,6 @@ AudioNode::SendChannelMixingParametersToStream()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioNode::SendTimelineEventToStream(AudioNode* aNode, uint32_t aIndex,
|
||||
const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
AudioNodeStream* ns = aNode->mStream;
|
||||
MOZ_ASSERT(ns, "How come we don't have a stream here?");
|
||||
ns->SendTimelineEvent(aIndex, aEvent);
|
||||
}
|
||||
|
||||
void
|
||||
AudioNode::Disconnect(uint32_t aOutput, ErrorResult& aRv)
|
||||
{
|
||||
|
@ -28,7 +28,6 @@ class AudioBufferSourceNode;
|
||||
class AudioParam;
|
||||
class AudioParamTimeline;
|
||||
struct ThreeDPoint;
|
||||
struct AudioTimelineEvent;
|
||||
|
||||
/**
|
||||
* The DOM object representing a Web Audio AudioNode.
|
||||
@ -212,20 +211,15 @@ public:
|
||||
virtual const char* NodeType() const = 0;
|
||||
|
||||
private:
|
||||
friend class AudioBufferSourceNode;
|
||||
// This could possibly delete 'this'.
|
||||
void DisconnectFromGraph();
|
||||
|
||||
protected:
|
||||
static void Callback(AudioNode* aNode) { /* not implemented */ }
|
||||
|
||||
// Helpers for sending different value types to streams
|
||||
void SendDoubleParameterToStream(uint32_t aIndex, double aValue);
|
||||
void SendInt32ParameterToStream(uint32_t aIndex, int32_t aValue);
|
||||
void SendThreeDPointParameterToStream(uint32_t aIndex, const ThreeDPoint& aValue);
|
||||
void SendChannelMixingParametersToStream();
|
||||
static void SendTimelineEventToStream(AudioNode* aNode, uint32_t aIndex,
|
||||
const dom::AudioTimelineEvent& aEvent);
|
||||
|
||||
private:
|
||||
nsRefPtr<AudioContext> mContext;
|
||||
|
@ -493,20 +493,18 @@ AudioNodeStream::UpMixDownMixChunk(const AudioBlock* aChunk,
|
||||
nsTArray<const float*>& aOutputChannels,
|
||||
nsTArray<float>& aDownmixBuffer)
|
||||
{
|
||||
static const float silenceChannel[WEBAUDIO_BLOCK_SIZE] = {0.f};
|
||||
|
||||
for (uint32_t i = 0; i < aChunk->ChannelCount(); i++) {
|
||||
aOutputChannels.AppendElement(static_cast<const float*>(aChunk->mChannelData[i]));
|
||||
}
|
||||
if (aOutputChannels.Length() < aOutputChannelCount) {
|
||||
if (mChannelInterpretation == ChannelInterpretation::Speakers) {
|
||||
AudioChannelsUpMix(&aOutputChannels, aOutputChannelCount, SilentChannel::ZeroChannel<float>());
|
||||
AudioChannelsUpMix<float>(&aOutputChannels, aOutputChannelCount, nullptr);
|
||||
NS_ASSERTION(aOutputChannelCount == aOutputChannels.Length(),
|
||||
"We called GetAudioChannelsSuperset to avoid this");
|
||||
} else {
|
||||
// Fill up the remaining aOutputChannels by zeros
|
||||
for (uint32_t j = aOutputChannels.Length(); j < aOutputChannelCount; ++j) {
|
||||
aOutputChannels.AppendElement(silenceChannel);
|
||||
aOutputChannels.AppendElement(nullptr);
|
||||
}
|
||||
}
|
||||
} else if (aOutputChannels.Length() > aOutputChannelCount) {
|
||||
|
@ -44,14 +44,14 @@ NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AudioParam, AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AudioParam, Release)
|
||||
|
||||
AudioParam::AudioParam(AudioNode* aNode,
|
||||
AudioParam::CallbackType aCallback,
|
||||
uint32_t aIndex,
|
||||
float aDefaultValue,
|
||||
const char* aName)
|
||||
: AudioParamTimeline(aDefaultValue)
|
||||
, mNode(aNode)
|
||||
, mCallback(aCallback)
|
||||
, mDefaultValue(aDefaultValue)
|
||||
, mName(aName)
|
||||
, mIndex(aIndex)
|
||||
, mDefaultValue(aDefaultValue)
|
||||
{
|
||||
}
|
||||
|
||||
@ -120,12 +120,20 @@ AudioParam::Stream()
|
||||
|
||||
// Send the stream to the timeline on the MSG side.
|
||||
AudioTimelineEvent event(mStream);
|
||||
|
||||
mCallback(mNode, event);
|
||||
SendEventToEngine(event);
|
||||
|
||||
return mStream;
|
||||
}
|
||||
|
||||
void
|
||||
AudioParam::SendEventToEngine(const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
AudioNodeStream* stream = mNode->GetStream();
|
||||
if (stream) {
|
||||
stream->SendTimelineEvent(mIndex, aEvent);
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
AudioParamTimeline::AudioNodeInputValue(size_t aCounter) const
|
||||
{
|
||||
|
@ -26,10 +26,8 @@ class AudioParam final : public nsWrapperCache,
|
||||
virtual ~AudioParam();
|
||||
|
||||
public:
|
||||
typedef void (*CallbackType)(AudioNode* aNode, const AudioTimelineEvent&);
|
||||
|
||||
AudioParam(AudioNode* aNode,
|
||||
CallbackType aCallback,
|
||||
uint32_t aIndex,
|
||||
float aDefaultValue,
|
||||
const char* aName);
|
||||
|
||||
@ -72,7 +70,7 @@ public:
|
||||
|
||||
AudioParamTimeline::SetValue(aValue);
|
||||
|
||||
mCallback(mNode, event);
|
||||
SendEventToEngine(event);
|
||||
}
|
||||
|
||||
void SetValueAtTime(float aValue, double aStartTime, ErrorResult& aRv)
|
||||
@ -129,7 +127,7 @@ public:
|
||||
|
||||
AudioTimelineEvent event(AudioTimelineEvent::Cancel, aStartTime, 0.0f);
|
||||
|
||||
mCallback(mNode, event);
|
||||
SendEventToEngine(event);
|
||||
}
|
||||
|
||||
uint32_t ParentNodeId()
|
||||
@ -147,11 +145,6 @@ public:
|
||||
return mDefaultValue;
|
||||
}
|
||||
|
||||
AudioNode* Node() const
|
||||
{
|
||||
return mNode;
|
||||
}
|
||||
|
||||
const nsTArray<AudioNode::InputNode>& InputNodes() const
|
||||
{
|
||||
return mInputNodes;
|
||||
@ -193,10 +186,6 @@ public:
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
protected:
|
||||
nsCycleCollectingAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
|
||||
private:
|
||||
void EventInsertionHelper(ErrorResult& aRv,
|
||||
AudioTimelineEvent::Type aType,
|
||||
@ -215,18 +204,22 @@ private:
|
||||
|
||||
AudioEventTimeline::InsertEvent<double>(event);
|
||||
|
||||
mCallback(mNode, event);
|
||||
SendEventToEngine(event);
|
||||
}
|
||||
|
||||
void SendEventToEngine(const AudioTimelineEvent& aEvent);
|
||||
|
||||
nsCycleCollectingAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
nsRefPtr<AudioNode> mNode;
|
||||
// For every InputNode, there is a corresponding entry in mOutputParams of the
|
||||
// InputNode's mInputNode.
|
||||
nsTArray<AudioNode::InputNode> mInputNodes;
|
||||
CallbackType mCallback;
|
||||
const float mDefaultValue;
|
||||
const char* mName;
|
||||
// The input port used to connect the AudioParam's stream to its node's stream
|
||||
nsRefPtr<MediaInputPort> mNodeStreamPort;
|
||||
const uint32_t mIndex;
|
||||
const float mDefaultValue;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -242,10 +242,11 @@ BiquadFilterNode::BiquadFilterNode(AudioContext* aContext)
|
||||
ChannelCountMode::Max,
|
||||
ChannelInterpretation::Speakers)
|
||||
, mType(BiquadFilterType::Lowpass)
|
||||
, mFrequency(new AudioParam(this, SendFrequencyToStream, 350.f, "frequency"))
|
||||
, mDetune(new AudioParam(this, SendDetuneToStream, 0.f, "detune"))
|
||||
, mQ(new AudioParam(this, SendQToStream, 1.f, "Q"))
|
||||
, mGain(new AudioParam(this, SendGainToStream, 0.f, "gain"))
|
||||
, mFrequency(new AudioParam(this, BiquadFilterNodeEngine::FREQUENCY,
|
||||
350.f, "frequency"))
|
||||
, mDetune(new AudioParam(this, BiquadFilterNodeEngine::DETUNE, 0.f, "detune"))
|
||||
, mQ(new AudioParam(this, BiquadFilterNodeEngine::Q, 1.f, "Q"))
|
||||
, mGain(new AudioParam(this, BiquadFilterNodeEngine::GAIN, 0.f, "gain"))
|
||||
{
|
||||
BiquadFilterNodeEngine* engine = new BiquadFilterNodeEngine(this, aContext->Destination());
|
||||
mStream = AudioNodeStream::Create(aContext, engine,
|
||||
@ -336,33 +337,5 @@ BiquadFilterNode::GetFrequencyResponse(const Float32Array& aFrequencyHz,
|
||||
biquad.getFrequencyResponse(int(length), frequencies, aMagResponse.Data(), aPhaseResponse.Data());
|
||||
}
|
||||
|
||||
void
|
||||
BiquadFilterNode::SendFrequencyToStream(AudioNode* aNode, const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
BiquadFilterNode* This = static_cast<BiquadFilterNode*>(aNode);
|
||||
SendTimelineEventToStream(This, BiquadFilterNodeEngine::FREQUENCY, aEvent);
|
||||
}
|
||||
|
||||
void
|
||||
BiquadFilterNode::SendDetuneToStream(AudioNode* aNode, const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
BiquadFilterNode* This = static_cast<BiquadFilterNode*>(aNode);
|
||||
SendTimelineEventToStream(This, BiquadFilterNodeEngine::DETUNE, aEvent);
|
||||
}
|
||||
|
||||
void
|
||||
BiquadFilterNode::SendQToStream(AudioNode* aNode, const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
BiquadFilterNode* This = static_cast<BiquadFilterNode*>(aNode);
|
||||
SendTimelineEventToStream(This, BiquadFilterNodeEngine::Q, aEvent);
|
||||
}
|
||||
|
||||
void
|
||||
BiquadFilterNode::SendGainToStream(AudioNode* aNode, const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
BiquadFilterNode* This = static_cast<BiquadFilterNode*>(aNode);
|
||||
SendTimelineEventToStream(This, BiquadFilterNodeEngine::GAIN, aEvent);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -15,7 +15,6 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AudioContext;
|
||||
struct AudioTimelineEvent;
|
||||
|
||||
class BiquadFilterNode final : public AudioNode
|
||||
{
|
||||
@ -68,16 +67,6 @@ public:
|
||||
protected:
|
||||
virtual ~BiquadFilterNode();
|
||||
|
||||
private:
|
||||
static void SendFrequencyToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent);
|
||||
static void SendDetuneToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvente);
|
||||
static void SendQToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent);
|
||||
static void SendGainToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent);
|
||||
|
||||
private:
|
||||
BiquadFilterType mType;
|
||||
nsRefPtr<AudioParam> mFrequency;
|
||||
|
@ -196,7 +196,7 @@ DelayNode::DelayNode(AudioContext* aContext, double aMaxDelay)
|
||||
2,
|
||||
ChannelCountMode::Max,
|
||||
ChannelInterpretation::Speakers)
|
||||
, mDelay(new AudioParam(this, SendDelayToStream, 0.0f, "delayTime"))
|
||||
, mDelay(new AudioParam(this, DelayNodeEngine::DELAY, 0.0f, "delayTime"))
|
||||
{
|
||||
DelayNodeEngine* engine =
|
||||
new DelayNodeEngine(this, aContext->Destination(),
|
||||
@ -229,12 +229,5 @@ DelayNode::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
return DelayNodeBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void
|
||||
DelayNode::SendDelayToStream(AudioNode* aNode, const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
DelayNode* This = static_cast<DelayNode*>(aNode);
|
||||
SendTimelineEventToStream(This, DelayNodeEngine::DELAY, aEvent);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -42,8 +42,6 @@ protected:
|
||||
virtual ~DelayNode();
|
||||
|
||||
private:
|
||||
static void SendDelayToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent);
|
||||
friend class DelayNodeEngine;
|
||||
|
||||
private:
|
||||
|
@ -186,12 +186,17 @@ DynamicsCompressorNode::DynamicsCompressorNode(AudioContext* aContext)
|
||||
2,
|
||||
ChannelCountMode::Explicit,
|
||||
ChannelInterpretation::Speakers)
|
||||
, mThreshold(new AudioParam(this, SendThresholdToStream, -24.f, "threshold"))
|
||||
, mKnee(new AudioParam(this, SendKneeToStream, 30.f, "knee"))
|
||||
, mRatio(new AudioParam(this, SendRatioToStream, 12.f, "ratio"))
|
||||
, mThreshold(new AudioParam(this, DynamicsCompressorNodeEngine::THRESHOLD,
|
||||
-24.f, "threshold"))
|
||||
, mKnee(new AudioParam(this, DynamicsCompressorNodeEngine::KNEE,
|
||||
30.f, "knee"))
|
||||
, mRatio(new AudioParam(this, DynamicsCompressorNodeEngine::RATIO,
|
||||
12.f, "ratio"))
|
||||
, mReduction(0)
|
||||
, mAttack(new AudioParam(this, SendAttackToStream, 0.003f, "attack"))
|
||||
, mRelease(new AudioParam(this, SendReleaseToStream, 0.25f, "release"))
|
||||
, mAttack(new AudioParam(this, DynamicsCompressorNodeEngine::ATTACK,
|
||||
0.003f, "attack"))
|
||||
, mRelease(new AudioParam(this, DynamicsCompressorNodeEngine::RELEASE,
|
||||
0.25f, "release"))
|
||||
{
|
||||
DynamicsCompressorNodeEngine* engine = new DynamicsCompressorNodeEngine(this, aContext->Destination());
|
||||
mStream = AudioNodeStream::Create(aContext, engine,
|
||||
@ -226,45 +231,5 @@ DynamicsCompressorNode::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenP
|
||||
return DynamicsCompressorNodeBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void
|
||||
DynamicsCompressorNode::SendThresholdToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
DynamicsCompressorNode* This = static_cast<DynamicsCompressorNode*>(aNode);
|
||||
SendTimelineEventToStream(This, DynamicsCompressorNodeEngine::THRESHOLD, aEvent);
|
||||
}
|
||||
|
||||
void
|
||||
DynamicsCompressorNode::SendKneeToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
DynamicsCompressorNode* This = static_cast<DynamicsCompressorNode*>(aNode);
|
||||
SendTimelineEventToStream(This, DynamicsCompressorNodeEngine::KNEE, aEvent);
|
||||
}
|
||||
|
||||
void
|
||||
DynamicsCompressorNode::SendRatioToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
DynamicsCompressorNode* This = static_cast<DynamicsCompressorNode*>(aNode);
|
||||
SendTimelineEventToStream(This, DynamicsCompressorNodeEngine::RATIO, aEvent);
|
||||
}
|
||||
|
||||
void
|
||||
DynamicsCompressorNode::SendAttackToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
DynamicsCompressorNode* This = static_cast<DynamicsCompressorNode*>(aNode);
|
||||
SendTimelineEventToStream(This, DynamicsCompressorNodeEngine::ATTACK, aEvent);
|
||||
}
|
||||
|
||||
void
|
||||
DynamicsCompressorNode::SendReleaseToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
DynamicsCompressorNode* This = static_cast<DynamicsCompressorNode*>(aNode);
|
||||
SendTimelineEventToStream(This, DynamicsCompressorNodeEngine::RELEASE, aEvent);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -73,18 +73,6 @@ public:
|
||||
protected:
|
||||
virtual ~DynamicsCompressorNode();
|
||||
|
||||
private:
|
||||
static void SendThresholdToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent);
|
||||
static void SendKneeToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent);
|
||||
static void SendRatioToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent);
|
||||
static void SendAttackToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent);
|
||||
static void SendReleaseToStream(AudioNode* aNode,
|
||||
const AudioTimelineEvent& aEvent);
|
||||
|
||||
private:
|
||||
nsRefPtr<AudioParam> mThreshold;
|
||||
nsRefPtr<AudioParam> mKnee;
|
||||
|
@ -117,7 +117,7 @@ GainNode::GainNode(AudioContext* aContext)
|
||||
2,
|
||||
ChannelCountMode::Max,
|
||||
ChannelInterpretation::Speakers)
|
||||
, mGain(new AudioParam(this, SendGainToStream, 1.0f, "gain"))
|
||||
, mGain(new AudioParam(this, GainNodeEngine::GAIN, 1.0f, "gain"))
|
||||
{
|
||||
GainNodeEngine* engine = new GainNodeEngine(this, aContext->Destination());
|
||||
mStream = AudioNodeStream::Create(aContext, engine,
|
||||
@ -148,12 +148,5 @@ GainNode::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
return GainNodeBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void
|
||||
GainNode::SendGainToStream(AudioNode* aNode, const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
GainNode* This = static_cast<GainNode*>(aNode);
|
||||
SendTimelineEventToStream(This, GainNodeEngine::GAIN, aEvent);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -41,9 +41,6 @@ public:
|
||||
protected:
|
||||
virtual ~GainNode();
|
||||
|
||||
private:
|
||||
static void SendGainToStream(AudioNode* aNode, const AudioTimelineEvent& aEvent);
|
||||
|
||||
private:
|
||||
nsRefPtr<AudioParam> mGain;
|
||||
};
|
||||
|
@ -402,8 +402,9 @@ OscillatorNode::OscillatorNode(AudioContext* aContext)
|
||||
ChannelCountMode::Max,
|
||||
ChannelInterpretation::Speakers)
|
||||
, mType(OscillatorType::Sine)
|
||||
, mFrequency(new AudioParam(this, SendFrequencyToStream, 440.0f, "frequency"))
|
||||
, mDetune(new AudioParam(this, SendDetuneToStream, 0.0f, "detune"))
|
||||
, mFrequency(new AudioParam(this, OscillatorNodeEngine::FREQUENCY,
|
||||
440.0f, "frequency"))
|
||||
, mDetune(new AudioParam(this, OscillatorNodeEngine::DETUNE, 0.0f, "detune"))
|
||||
, mStartCalled(false)
|
||||
{
|
||||
OscillatorNodeEngine* engine = new OscillatorNodeEngine(this, aContext->Destination());
|
||||
@ -452,26 +453,6 @@ OscillatorNode::DestroyMediaStream()
|
||||
AudioNode::DestroyMediaStream();
|
||||
}
|
||||
|
||||
void
|
||||
OscillatorNode::SendFrequencyToStream(AudioNode* aNode, const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
OscillatorNode* This = static_cast<OscillatorNode*>(aNode);
|
||||
if (!This->mStream) {
|
||||
return;
|
||||
}
|
||||
SendTimelineEventToStream(This, OscillatorNodeEngine::FREQUENCY, aEvent);
|
||||
}
|
||||
|
||||
void
|
||||
OscillatorNode::SendDetuneToStream(AudioNode* aNode, const AudioTimelineEvent& aEvent)
|
||||
{
|
||||
OscillatorNode* This = static_cast<OscillatorNode*>(aNode);
|
||||
if (!This->mStream) {
|
||||
return;
|
||||
}
|
||||
SendTimelineEventToStream(This, OscillatorNodeEngine::DETUNE, aEvent);
|
||||
}
|
||||
|
||||
void
|
||||
OscillatorNode::SendTypeToStream()
|
||||
{
|
||||
|
@ -87,8 +87,6 @@ protected:
|
||||
virtual ~OscillatorNode();
|
||||
|
||||
private:
|
||||
static void SendFrequencyToStream(AudioNode* aNode, const AudioTimelineEvent& aEvent);
|
||||
static void SendDetuneToStream(AudioNode* aNode, const AudioTimelineEvent& aEvent);
|
||||
void SendTypeToStream();
|
||||
void SendPeriodicWaveToStream();
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user