Merge m-c to f-t

This commit is contained in:
Phil Ringnalda 2014-11-28 15:17:20 -08:00
commit 757831e55e
357 changed files with 19751 additions and 6373 deletions

View File

@ -22,4 +22,9 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Merge day clobber
Bug 1105308 - Cleanup BluetoothUtils.{cpp,h}
This patch set moves some files around and requires a rebuild
of the build system's dependency information.
Merge day clobber

View File

@ -681,6 +681,7 @@ static const EStateRule sWAIUnivStateMap[] = {
eARIAExpanded, // Currently under spec review but precedent exists
eARIAHasPopup, // Note this is technically a "property"
eARIAInvalid,
eARIAModal,
eARIARequired, // XXX not global, Bug 553117
eARIANone
};
@ -716,6 +717,7 @@ static const AttrCharacteristics gWAIUnivAttrMap[] = {
{&nsGkAtoms::aria_labelledby, ATTR_BYPASSOBJ | ATTR_GLOBAL },
{&nsGkAtoms::aria_level, ATTR_BYPASSOBJ }, /* handled via groupPosition */
{&nsGkAtoms::aria_live, ATTR_VALTOKEN | ATTR_GLOBAL },
{&nsGkAtoms::aria_modal, ATTR_BYPASSOBJ | ATTR_VALTOKEN | ATTR_GLOBAL },
{&nsGkAtoms::aria_multiline, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
{&nsGkAtoms::aria_multiselectable, ATTR_BYPASSOBJ | ATTR_VALTOKEN },
{&nsGkAtoms::aria_owns, ATTR_BYPASSOBJ | ATTR_GLOBAL },

View File

@ -228,15 +228,15 @@ uint64_t UniversalStatesFor(mozilla::dom::Element* aElement);
uint8_t AttrCharacteristicsFor(nsIAtom* aAtom);
/**
* Represents a simple enumerator for iterating through ARIA attributes
* exposed as object attributes on a given accessible.
* Represents a simple enumerator for iterating through ARIA attributes
* exposed as object attributes on a given accessible.
*/
class AttrIterator
{
public:
explicit AttrIterator(nsIContent* aContent) :
mContent(aContent), mAttrIdx(0)
{
explicit AttrIterator(nsIContent* aContent) :
mContent(aContent), mAttrIdx(0)
{
mAttrCount = mContent->GetAttrCount();
}

View File

@ -185,6 +185,16 @@ aria::MapToState(EStateRule aRule, dom::Element* aElement, uint64_t* aState)
return true;
}
case eARIAModal:
{
static const TokenTypeData data(
nsGkAtoms::aria_modal, eBoolType,
0, states::MODAL);
MapTokenType(aElement, aState, data);
return true;
}
case eARIAMultiline:
{
static const TokenTypeData data(

View File

@ -33,6 +33,7 @@ enum EStateRule
eARIAExpanded,
eARIAHasPopup,
eARIAInvalid,
eARIAModal,
eARIAMultiline,
eARIAMultiSelectable,
eARIAOrientation,

View File

@ -28,16 +28,18 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
testAbsentAttrs(getNode("atomic_false").firstChild, {"container-atomic" : "false"});
testAttrs("autocomplete", {"autocomplete" : "true"}, true);
testAttrs("checkbox", {"checkable" : "true"}, true);
testAttrs("checkedCheckbox", {"checkable" : "true"}, true);
testAttrs("checkedMenuitem", {"checkable" : "true"}, true);
testAttrs("checkedOption", {"checkable" : "true"}, true);
testAttrs("checkedRadio", {"checkable" : "true"}, true);
testAttrs("checkedTreeitem", {"checkable" : "true"}, true);
testAttrs("checkbox", {"checkable" : "true"}, true);
testAttrs("checkedCheckbox", {"checkable" : "true"}, true);
testAttrs("checkedMenuitem", {"checkable" : "true"}, true);
testAttrs("checkedOption", {"checkable" : "true"}, true);
testAttrs("checkedRadio", {"checkable" : "true"}, true);
testAttrs("checkedTreeitem", {"checkable" : "true"}, true);
testAttrs("dropeffect", {"dropeffect" : "copy"}, true);
testAttrs("grabbed", {"grabbed" : "true"}, true);
testAbsentAttrs("haspopup", { "haspopup": "false" });
testAttrs("hidden", {"hidden" : "true"}, true);
testAbsentAttrs("hidden_false", { "hidden": "false" });
testAbsentAttrs("modal", {"modal" : "true"});
testAttrs("sortAscending", {"sort" : "ascending"}, true);
testAttrs("sortDescending", {"sort" : "descending"}, true);
testAttrs("sortNone", {"sort" : "none"}, true);
@ -198,8 +200,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
<div id="checkedTreeitem" role="treeitem" aria-checked="true"></div>
<div id="dropeffect" aria-dropeffect="copy"></div>
<div id="grabbed" aria-grabbed="true"></div>
<div id="haspopup" aria-haspopup="true"></div>
<div id="hidden" aria-hidden="true"></div>
<div id="hidden_false" aria-hidden="false"></div>
<div id="modal" aria-modal="true"></div>
<div id="sortAscending" role="columnheader" aria-sort="ascending"></div>
<div id="sortDescending" role="columnheader" aria-sort="descending"></div>
<div id="sortNone" role="columnheader" aria-sort="none"></div>

View File

@ -42,6 +42,7 @@ const EXT_STATE_EDITABLE = nsIAccessibleStates.EXT_STATE_EDITABLE;
const EXT_STATE_ENABLED = nsIAccessibleStates.EXT_STATE_ENABLED;
const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE;
const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL;
const EXT_STATE_MODAL = nsIAccessibleStates.EXT_STATE_MODAL;
const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
const EXT_STATE_PINNED = nsIAccessibleStates.EXT_STATE_PINNED;
const EXT_STATE_SENSITIVE = nsIAccessibleStates.EXT_STATE_SENSITIVE;

View File

@ -97,6 +97,10 @@
// disabled, too. See bug 429285.
testAriaDisabledTree("group");
// aria-modal
testStates("aria_modal", 0, EXT_STATE_MODAL);
testStates("aria_modal_false", 0, 0, 0, EXT_STATE_MODAL);
// aria-multiline
testStates("aria_multiline_textbox", 0, EXT_STATE_MULTI_LINE);
@ -379,6 +383,8 @@
<div id="aria_mixed_checkbox" role="checkbox" aria-checked="mixed">
I might agree
</div>
<div id="aria_modal" aria-modal="true">modal stuff</div>
<div id="aria_modal_false" aria-modal="false">non modal stuff</div>div>
<div id="aria_multiline_textbox" role="textbox" aria-multiline="true"></div>
<div id="aria_multiselectable_listbox" role="listbox" aria-multiselectable="true"></div>
<div id="aria_pressed_button" role="button" aria-pressed="true">Button</div>

View File

@ -36,10 +36,42 @@ let principal = Cc["@mozilla.org/scriptsecuritymanager;1"].
getService(Ci.nsIScriptSecurityManager).
getCodebasePrincipal(principaluri);
function toArray(args) {
return Array.prototype.slice.call(args);
}
function openInternal(args, forPrincipal, deleting) {
if (forPrincipal) {
args = toArray(args);
} else {
args = [principal].concat(toArray(args));
}
if (args.length == 2) {
args.push({ storage: "persistent" });
} else if (!deleting && args.length >= 3 && typeof args[2] === "number") {
args[2] = { version: args[2], storage: "persistent" };
}
if (deleting) {
return indexedDB.deleteForPrincipal.apply(indexedDB, args);
}
return indexedDB.openForPrincipal.apply(indexedDB, args);
}
exports.indexedDB = Object.freeze({
open: indexedDB.openForPrincipal.bind(indexedDB, principal),
openForPrincipal: indexedDB.openForPrincipal.bind(indexedDB),
deleteDatabase: indexedDB.deleteForPrincipal.bind(indexedDB, principal),
open: function () {
return openInternal(arguments, false, false);
},
deleteDatabase: function () {
return openInternal(arguments, false, true);
},
openForPrincipal: function () {
return openInternal(arguments, true, false);
},
deleteForPrincipal: function () {
return openInternal(arguments, true, true);
},
cmp: indexedDB.cmp.bind(indexedDB)
});

View File

@ -28,16 +28,82 @@ exports["test db variables"] = function(assert) {
}
exports["test open"] = function(assert, done) {
let request = indexedDB.open("MyTestDatabase");
testOpen(0, assert, done);
}
function testOpen(step, assert, done) {
const dbName = "MyTestDatabase";
const openParams = [
{ dbName: "MyTestDatabase", dbVersion: 10 },
{ dbName: "MyTestDatabase" },
{ dbName: "MyTestDatabase", dbOptions: { storage: "temporary" } },
{ dbName: "MyTestDatabase", dbOptions: { version: 20, storage: "default" } }
];
let params = openParams[step];
let request;
let expectedStorage;
let expectedVersion;
let upgradeNeededCalled = false;
if ("dbVersion" in params) {
request = indexedDB.open(params.dbName, params.dbVersion);
expectedVersion = params.dbVersion;
expectedStorage = "persistent";
} else if ("dbOptions" in params) {
request = indexedDB.open(params.dbName, params.dbOptions);
if ("version" in params.dbOptions) {
expectedVersion = params.dbOptions.version;
} else {
expectedVersion = 1;
}
if ("storage" in params.dbOptions) {
expectedStorage = params.dbOptions.storage;
} else {
expectedStorage = "persistent";
}
} else {
request = indexedDB.open(params.dbName);
expectedVersion = 1;
expectedStorage = "persistent";
}
request.onerror = function(event) {
assert.fail("Failed to open indexedDB")
done();
};
}
request.onupgradeneeded = function(event) {
upgradeNeededCalled = true;
assert.equal(event.oldVersion, 0, "Correct old version");
}
request.onsuccess = function(event) {
assert.pass("IndexedDB was open");
done();
};
};
assert.equal(upgradeNeededCalled, true, "Upgrade needed called");
let db = request.result;
assert.equal(db.storage, expectedStorage, "Storage is correct");
db.onversionchange = function(event) {
assert.equal(event.oldVersion, expectedVersion, "Old version is correct");
db.close();
}
if ("dbOptions" in params) {
request = indexedDB.deleteDatabase(params.dbName, params.dbOptions);
} else {
request = indexedDB.deleteDatabase(params.dbName);
}
request.onerror = function(event) {
assert.fail("Failed to delete indexedDB")
done();
}
request.onsuccess = function(event) {
assert.pass("IndexedDB was deleted");
if (++step == openParams.length) {
done();
} else {
testOpen(step, assert, done);
}
}
}
}
exports["test dbname is unprefixed"] = function(assert, done) {
// verify fixes in https://bugzilla.mozilla.org/show_bug.cgi?id=786688

View File

@ -329,7 +329,7 @@ var shell = {
window.addEventListener('sizemodechange', this);
window.addEventListener('unload', this);
this.contentBrowser.addEventListener('mozbrowserloadstart', this, true);
this.contentBrowser.addEventListener('mozbrowserselectionchange', this, true);
this.contentBrowser.addEventListener('mozbrowserselectionstatechanged', this, true);
this.contentBrowser.addEventListener('mozbrowserscrollviewchange', this, true);
this.contentBrowser.addEventListener('mozbrowsertouchcarettap', this, true);
@ -357,7 +357,7 @@ var shell = {
window.removeEventListener('mozfullscreenchange', this);
window.removeEventListener('sizemodechange', this);
this.contentBrowser.removeEventListener('mozbrowserloadstart', this, true);
this.contentBrowser.removeEventListener('mozbrowserselectionchange', this, true);
this.contentBrowser.removeEventListener('mozbrowserselectionstatechanged', this, true);
this.contentBrowser.removeEventListener('mozbrowserscrollviewchange', this, true);
this.contentBrowser.removeEventListener('mozbrowsertouchcarettap', this, true);
ppmm.removeMessageListener("content-handler", this);
@ -505,8 +505,8 @@ var shell = {
detail: evt.detail,
});
break;
case 'mozbrowserselectionchange':
// The mozbrowserselectionchange event, may have crossed the chrome-content boundary.
case 'mozbrowserselectionstatechanged':
// The mozbrowserselectionstatechanged event, may have crossed the chrome-content boundary.
// This event always dispatch to shell.js. But the offset we got from this event is
// based on tab's coordinate. So get the actual offsets between shell and evt.target.
let elt = evt.target;
@ -524,7 +524,7 @@ var shell = {
DoCommandHelper.setEvent(evt);
shell.sendChromeEvent({
type: 'selectionchange',
type: 'selectionstatechanged',
detail: data,
});
break;

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="7cc460af0f6f491d1afa6b6043cdea5025f0e15f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="47111fd2bbe8b0055c8a596959d701391d2a9953"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -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="7cc460af0f6f491d1afa6b6043cdea5025f0e15f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="47111fd2bbe8b0055c8a596959d701391d2a9953"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
@ -97,7 +97,7 @@
<project name="platform/system/netd" path="system/netd" revision="3d298fde142bee3fc4f07f63f16f2d8ce42339c0"/>
<project name="platform/system/vold" path="system/vold" revision="919829940468066a32f403980b43f6ebfee5d314"/>
<!-- Emulator specific things -->
<project name="android-development" path="development" remote="b2g" revision="c99e41d49f0b98eade30814e52c1de9e818def68"/>
<project name="android-development" path="development" remote="b2g" revision="2bdf22305b523af644e1891b4ddfd9229336d0ce"/>
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="0d5c43228006bae775c4cb57a6d3908484d41718"/>
<project name="platform/external/iproute2" path="external/iproute2" revision="c66c5716d5335e450f7a7b71ccc6a604fb2f41d2"/>
<project name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="d2685281e2e54ca14d1df304867aa82c37b27162"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="7cc460af0f6f491d1afa6b6043cdea5025f0e15f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="47111fd2bbe8b0055c8a596959d701391d2a9953"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="7cc460af0f6f491d1afa6b6043cdea5025f0e15f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="47111fd2bbe8b0055c8a596959d701391d2a9953"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -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="7cc460af0f6f491d1afa6b6043cdea5025f0e15f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="47111fd2bbe8b0055c8a596959d701391d2a9953"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
@ -97,7 +97,7 @@
<project name="platform/system/netd" path="system/netd" revision="3d298fde142bee3fc4f07f63f16f2d8ce42339c0"/>
<project name="platform/system/vold" path="system/vold" revision="919829940468066a32f403980b43f6ebfee5d314"/>
<!-- Emulator specific things -->
<project name="android-development" path="development" remote="b2g" revision="c99e41d49f0b98eade30814e52c1de9e818def68"/>
<project name="android-development" path="development" remote="b2g" revision="2bdf22305b523af644e1891b4ddfd9229336d0ce"/>
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="0d5c43228006bae775c4cb57a6d3908484d41718"/>
<project name="platform/external/iproute2" path="external/iproute2" revision="c66c5716d5335e450f7a7b71ccc6a604fb2f41d2"/>
<project name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="d2685281e2e54ca14d1df304867aa82c37b27162"/>

View File

@ -18,6 +18,7 @@
],
"zip_files": [
["{workdir}/out/target/product/flame/*.img", "out/target/product/flame/"],
["{workdir}/out/target/product/flame/bootloader", "out/target/product/flame/"],
["{workdir}/boot.img", "out/target/product/flame/"],
"{workdir}/flash.sh",
"{workdir}/load-config.sh",

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3ab0d9c70f0b2e1ededc679112c392303f037361">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="7cc460af0f6f491d1afa6b6043cdea5025f0e15f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="47111fd2bbe8b0055c8a596959d701391d2a9953"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="7cc460af0f6f491d1afa6b6043cdea5025f0e15f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="47111fd2bbe8b0055c8a596959d701391d2a9953"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>

View File

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "eb65c4355e0a16dc5cd203c5c007fd7e3bf0e4b2",
"revision": "c65e0f2f00a05a78a57eecb1185c6420b7984d36",
"repo_path": "integration/gaia-central"
}

View File

@ -17,7 +17,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="7cc460af0f6f491d1afa6b6043cdea5025f0e15f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="47111fd2bbe8b0055c8a596959d701391d2a9953"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>

View File

@ -15,7 +15,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="7cc460af0f6f491d1afa6b6043cdea5025f0e15f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="47111fd2bbe8b0055c8a596959d701391d2a9953"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="7cc460af0f6f491d1afa6b6043cdea5025f0e15f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="47111fd2bbe8b0055c8a596959d701391d2a9953"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="6499615ecece69e726657dc5caaeefa05fbb66bf"/>

View File

@ -17,7 +17,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="7cc460af0f6f491d1afa6b6043cdea5025f0e15f"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="47111fd2bbe8b0055c8a596959d701391d2a9953"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="50ad16a280fe9cfa0716f8c6ba16afdf7f266b49"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

View File

@ -151,6 +151,7 @@ const SNIPPETS_UPDATE_INTERVAL_MS = 86400000; // 1 Day.
// IndexedDB storage constants.
const DATABASE_NAME = "abouthome";
const DATABASE_VERSION = 1;
const DATABASE_STORAGE = "persistent";
const SNIPPETS_OBJECTSTORE_NAME = "snippets";
// This global tracks if the page has been set up before, to prevent double inits
@ -224,7 +225,8 @@ function ensureSnippetsMapThen(aCallback)
gSnippetsMapCallbacks.length = 0;
}
let openRequest = indexedDB.open(DATABASE_NAME, DATABASE_VERSION);
let openRequest = indexedDB.open(DATABASE_NAME, {version: DATABASE_VERSION,
storage: DATABASE_STORAGE});
openRequest.onerror = function (event) {
// Try to delete the old database so that we can start this process over

View File

@ -152,6 +152,9 @@ function onCheckboxClick(aPartId)
var checkbox = document.getElementById(aPartId + "Def");
if (checkbox.checked) {
SitePermissions.remove(gPermURI, aPartId);
if (aPartId == "indexedDB") {
SitePermissions.remove(gPermURI, "indexedDB-unlimited");
}
command.setAttribute("disabled", "true");
var perm = SitePermissions.getDefault(aPartId);
setRadioState(aPartId, perm);
@ -206,6 +209,7 @@ function onIndexedDBClear()
.getService(nsIQuotaManager)
.clearStoragesForURI(gPermURI);
SitePermissions.remove(gPermURI, "indexedDB");
SitePermissions.remove(gPermURI, "indexedDB-unlimited");
initIndexedDBRow();
}

View File

@ -717,6 +717,24 @@ function injectLoopAPI(targetWindow) {
request.send();
}
},
/**
* Associates a session-id and a call-id with a window for debugging.
*
* @param {string} windowId The window id.
* @param {string} sessionId OT session id.
* @param {string} callId The callId on the server.
*/
addConversationContext: {
enumerable: true,
writable: true,
value: function(windowId, sessionId, callid) {
MozLoopService.addConversationContext(windowId, {
sessionId: sessionId,
callId: callid
});
}
}
};

View File

@ -120,6 +120,8 @@ let gConversationWindowData = new Map();
* and register with the Loop server.
*/
let MozLoopServiceInternal = {
conversationContexts: new Map(),
mocks: {
pushHandler: undefined,
webSocket: undefined,
@ -817,6 +819,22 @@ let MozLoopServiceInternal = {
if (winID != ourID) {
return;
}
// Chat Window Id, this is different that the internal winId
let windowId = window.location.hash.slice(1);
var context = this.conversationContexts.get(windowId);
var exists = pc.id.match(/session=(\S+)/);
if (context && !exists) {
// Not ideal but insert our data amidst existing data like this:
// - 000 (id=00 url=http)
// + 000 (session=000 call=000 id=00 url=http)
var pair = pc.id.split("("); //)
if (pair.length == 2) {
pc.id = pair[0] + "(session=" + context.sessionId +
(context.callId? " call=" + context.callId : "") + " " + pair[1]; //)
}
}
if (type == "iceconnectionstatechange") {
switch(pc.iceConnectionState) {
case "failed":
@ -1485,5 +1503,13 @@ this.MozLoopService = {
log.error("Window data was already fetched before. Possible race condition!");
return null;
},
getConversationContext: function(winId) {
return MozLoopServiceInternal.conversationContexts.get(winId);
},
addConversationContext: function(windowId, context) {
MozLoopServiceInternal.conversationContexts.set(windowId, context);
}
};

View File

@ -675,10 +675,10 @@ loop.conversation = (function(mozL10n) {
// XXX Old class creation for the incoming conversation view, whilst
// we transition across (bug 1072323).
var conversation = new sharedModels.ConversationModel(
{}, // Model attributes
{sdk: window.OT} // Model dependencies
);
var conversation = new sharedModels.ConversationModel({}, {
sdk: window.OT,
mozLoop: navigator.mozLoop
});
// Obtain the windowId and pass it through
var helper = new loop.shared.utils.Helper();

View File

@ -675,10 +675,10 @@ loop.conversation = (function(mozL10n) {
// XXX Old class creation for the incoming conversation view, whilst
// we transition across (bug 1072323).
var conversation = new sharedModels.ConversationModel(
{}, // Model attributes
{sdk: window.OT} // Model dependencies
);
var conversation = new sharedModels.ConversationModel({}, {
sdk: window.OT,
mozLoop: navigator.mozLoop
});
// Obtain the windowId and pass it through
var helper = new loop.shared.utils.Helper();

View File

@ -161,7 +161,8 @@ loop.store.ActiveRoomStore = (function() {
this._registerPostSetupActions();
this.setStoreState({
roomState: ROOM_STATES.GATHER
roomState: ROOM_STATES.GATHER,
windowId: actionData.windowId
});
// Get the window data from the mozLoop api.
@ -307,6 +308,9 @@ loop.store.ActiveRoomStore = (function() {
this._setRefreshTimeout(actionData.expires);
this._sdkDriver.connectSession(actionData);
this._mozLoop.addConversationContext(this._storeState.windowId,
actionData.sessionId, "");
// If we haven't got a room name yet, go and get one. We typically
// need to do this in the case of the standalone window.
// XXX When bug 1103331 lands this can be moved to earlier.

View File

@ -170,6 +170,9 @@ loop.store.ConversationStore = (function() {
sessionId: this.get("sessionId"),
sessionToken: this.get("sessionToken")
});
navigator.mozLoop.addConversationContext(this.get("windowId"),
this.get("sessionId"),
this.get("callId"));
this.set({callState: CALL_STATES.ONGOING});
break;
}

View File

@ -57,6 +57,7 @@ loop.shared.models = (function(l10n) {
* Constructor.
*
* Options:
* - {OT} mozLoop: browser mozLoop service object.
*
* Required:
* - {OT} sdk: OT SDK object.
@ -66,6 +67,7 @@ loop.shared.models = (function(l10n) {
*/
initialize: function(attributes, options) {
options = options || {};
this.mozLoop = options.mozLoop;
if (!options.sdk) {
throw new Error("missing required sdk");
}
@ -186,6 +188,13 @@ loop.shared.models = (function(l10n) {
this._sessionDisconnected);
this.session.connect(this.get("apiKey"), this.get("sessionToken"),
this._onConnectCompletion.bind(this));
// We store the call credentials for debugging purposes.
if (this.mozLoop) {
this.mozLoop.addConversationContext(this.get("windowId"),
this.get("sessionId"),
this.get("callId"));
}
},
/**

View File

@ -263,7 +263,11 @@ loop.StandaloneMozLoop = (function(mozL10n) {
*/
getLoopPref: function(prefName) {
return localStorage.getItem(prefName);
}
},
// Dummy function to reflect those in the desktop mozLoop that we
// don't currently use.
addConversationContext: function() {}
};
return StandaloneMozLoop;

View File

@ -21,6 +21,7 @@ describe("loop.store.ActiveRoomStore", function () {
fakeMozLoop = {
setLoopPref: sandbox.stub(),
addConversationContext: sandbox.stub(),
rooms: {
get: sinon.stub(),
join: sinon.stub(),
@ -398,6 +399,7 @@ describe("loop.store.ActiveRoomStore", function () {
apiKey: "9876543210",
sessionToken: "12563478",
sessionId: "15263748",
windowId: "42",
expires: 20
};
@ -431,6 +433,21 @@ describe("loop.store.ActiveRoomStore", function () {
actionData);
});
it("should call mozLoop.addConversationContext", function() {
var actionData = new sharedActions.JoinedRoom(fakeJoinedData);
store.setupWindowData(new sharedActions.SetupWindowData({
windowId: "42",
type: "room",
}));
store.joinedRoom(actionData);
sinon.assert.calledOnce(fakeMozLoop.addConversationContext);
sinon.assert.calledWithExactly(fakeMozLoop.addConversationContext,
"42", "15263748", "");
});
it("should call mozLoop.rooms.get to get the room data if the roomName" +
"is not known", function() {
store.setStoreState({roomName: undefined});

View File

@ -38,6 +38,7 @@ describe("loop.store.ConversationStore", function () {
navigator.mozLoop = {
getLoopPref: sandbox.stub(),
addConversationContext: sandbox.stub(),
calls: {
setCallInProgress: sandbox.stub(),
clearCallInProgress: sandbox.stub()
@ -75,6 +76,7 @@ describe("loop.store.ConversationStore", function () {
sessionId: "321456",
sessionToken: "341256",
websocketToken: "543216",
windowId: "28",
progressURL: "fakeURL"
};
@ -222,6 +224,17 @@ describe("loop.store.ConversationStore", function () {
sessionToken: "341256"
});
});
it("should call mozLoop.addConversationContext", function() {
store.set(fakeSessionData);
store.connectionProgress(
new sharedActions.ConnectionProgress({wsState: WS_STATES.CONNECTING}));
sinon.assert.calledOnce(navigator.mozLoop.addConversationContext);
sinon.assert.calledWithExactly(navigator.mozLoop.addConversationContext,
"28", "321456", "142536");
});
});
});

View File

@ -9,8 +9,8 @@ var expect = chai.expect;
describe("loop.shared.models", function() {
"use strict";
var sharedModels = loop.shared.models,
sandbox, fakeXHR, requests = [], fakeSDK, fakeSession, fakeSessionData;
var sharedModels = loop.shared.models, sandbox, fakeXHR,
requests = [], fakeSDK, fakeMozLoop, fakeSession, fakeSessionData;
beforeEach(function() {
sandbox = sinon.sandbox.create();
@ -42,6 +42,7 @@ describe("loop.shared.models", function() {
initPublisher: sandbox.spy(),
initSession: sandbox.stub().returns(fakeSession)
};
fakeMozLoop = {};
});
afterEach(function() {
@ -63,6 +64,7 @@ describe("loop.shared.models", function() {
beforeEach(function() {
conversation = new sharedModels.ConversationModel({}, {
sdk: fakeSDK
mozLoop: fakeMozLoop
});
conversation.set("loopToken", "fakeToken");
});
@ -159,7 +161,8 @@ describe("loop.shared.models", function() {
beforeEach(function() {
model = new sharedModels.ConversationModel(fakeSessionData, {
sdk: fakeSDK
sdk: fakeSDK,
mozLoop: fakeMozLoop
});
model.set({
publishedStream: true,
@ -177,6 +180,21 @@ describe("loop.shared.models", function() {
expect(model.get("subscribedStream")).eql(false);
});
it("should call addConversationContext", function() {
fakeMozLoop.addConversationContext = sandbox.stub();
model.set({
windowId: "28",
sessionId: "321456",
callId: "142536",
});
model.startSession();
sinon.assert.calledOnce(fakeMozLoop.addConversationContext);
sinon.assert.calledWithExactly(fakeMozLoop.addConversationContext,
"28", "321456", "142536");
});
it("should call connect", function() {
fakeSession.connect = sandbox.stub();

View File

@ -115,13 +115,6 @@ this.SitePermissions = {
* a UI for managing permissions.
*/
getStateLabel: function (aPermissionID, aState) {
if (aPermissionID in gPermissionObject &&
gPermissionObject[aPermissionID].getStateLabel) {
let label = gPermissionObject[aPermissionID].getStateLabel(aState);
if (label)
return label;
}
switch (aState) {
case this.UNKNOWN:
return gStringBundle.GetStringFromName("alwaysAsk");
@ -151,11 +144,6 @@ let gPermissionObject = {
* Defaults to UNKNOWN, indicating that the user will be asked each time
* a page asks for that permissions.
*
* - getStateLabel
* Called to get the localized label for the given permission state, to be
* used in a UI for managing permissions. May return null for states that
* should use their default label.
*
* - onChange
* Called when a permission state changes.
*
@ -208,21 +196,8 @@ let gPermissionObject = {
},
"indexedDB": {
states: [ SitePermissions.ALLOW, SitePermissions.UNKNOWN, SitePermissions.BLOCK ],
getStateLabel: function (aState) {
// indexedDB redefines nsIPermissionManager.UNKNOWN_ACTION (the default)
// as "allow" and nsIPermissionManager.ALLOW_ACTION as "ask the user."
switch (aState) {
case SitePermissions.UNKNOWN:
return gStringBundle.GetStringFromName("allow");
case SitePermissions.ALLOW:
return gStringBundle.GetStringFromName("alwaysAsk");
default:
return null;
}
},
onChange: function (aURI, aState) {
if (aState == SitePermissions.ALLOW || aState == SitePermissions.BLOCK)
if (aState == SitePermissions.BLOCK)
Services.perms.remove(aURI.host, "indexedDB-unlimited");
}
},

View File

@ -65,6 +65,8 @@ this.PermissionsInstaller = {
newPermNames = newPermNames.concat(expandedPermNames);
}
newPermNames.push("indexedDB");
// Add the appcache related permissions.
if (newManifest.appcache_path) {
newPermNames = newPermNames.concat(["offline-app", "pin-app"]);
@ -116,6 +118,8 @@ this.PermissionsInstaller = {
break;
}
this._setPermission("indexedDB", "allow", aApp);
// Add the appcache related permissions. We allow it for all kinds of
// apps.
if (newManifest.appcache_path) {

View File

@ -306,8 +306,7 @@ this.PermissionsTable = { geolocation: {
privileged: ALLOW_ACTION,
certified: ALLOW_ACTION,
substitute: [
"indexedDB-unlimited",
"default-persistent-storage"
"indexedDB-unlimited"
]
},
"background-sensors": {
@ -645,7 +644,7 @@ this.AllPossiblePermissions = [];
}
}
AllPossiblePermissions =
AllPossiblePermissions.concat(["offline-app", "pin-app"]);
AllPossiblePermissions.concat(["indexedDB", "offline-app", "pin-app"]);
})();
this.isExplicitInPermissionsTable = function(aPermName, aIntStatus) {

View File

@ -735,25 +735,12 @@ MainProcessRunnable::InitOnMainThread()
NS_ENSURE_STATE(qm);
nsresult rv =
QuotaManager::GetInfoFromPrincipal(mPrincipal,
quota::PERSISTENCE_TYPE_INVALID,
&mGroup, &mOrigin, &mIsApp,
QuotaManager::GetInfoFromPrincipal(mPrincipal, &mGroup, &mOrigin, &mIsApp,
&mHasUnlimStoragePerm);
NS_ENSURE_SUCCESS(rv, rv);
// XXX Don't use mGroup yet! We might need to update it right after we
// initialize persistence type.
InitPersistenceType();
// XXX Since we couldn't pass persistence type to GetInfoFromPrincipal(),
// we need to do this manually.
// This hack is only temporary, it will go away once we have regular
// metadata files for persistent storge.
if (mPersistence == quota::PERSISTENCE_TYPE_PERSISTENT) {
mGroup = mOrigin;
}
mEnforcingQuota =
QuotaManager::IsQuotaEnforced(mPersistence, mOrigin, mIsApp,
mHasUnlimStoragePerm);
@ -1843,7 +1830,7 @@ public:
virtual void
OnOriginClearCompleted(PersistenceType aPersistenceType,
const OriginOrPatternString& aOriginOrPattern)
const nsACString& aOrigin)
MOZ_OVERRIDE
{ }

View File

@ -3119,6 +3119,12 @@ nsDOMWindowUtils::GetFileReferences(const nsAString& aDatabaseName, int64_t aId,
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
nsCString origin;
nsresult rv =
quota::QuotaManager::GetInfoFromWindow(window, nullptr, &origin, nullptr,
nullptr);
NS_ENSURE_SUCCESS(rv, rv);
IDBOpenDBOptions options;
JS::Rooted<JS::Value> optionsVal(aCx, aOptions);
if (!options.Init(aCx, optionsVal)) {
@ -3128,12 +3134,6 @@ nsDOMWindowUtils::GetFileReferences(const nsAString& aDatabaseName, int64_t aId,
quota::PersistenceType persistenceType =
quota::PersistenceTypeFromStorage(options.mStorage);
nsCString origin;
nsresult rv =
quota::QuotaManager::GetInfoFromWindow(window, persistenceType, nullptr,
&origin, nullptr, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<indexedDB::IndexedDatabaseManager> mgr =
indexedDB::IndexedDatabaseManager::Get();

View File

@ -1612,7 +1612,7 @@ nsFocusManager::Blur(nsPIDOMWindow* aWindowToClear,
nsRefPtr<SelectionCarets> selectionCarets = presShell->GetSelectionCarets();
if (selectionCarets) {
selectionCarets->SetVisibility(false);
selectionCarets->NotifyBlur();
}
bool clearFirstBlurEvent = false;

View File

@ -2235,6 +2235,7 @@ GK_ATOM(aria_label, "aria-label")
GK_ATOM(aria_labelledby, "aria-labelledby")
GK_ATOM(aria_level, "aria-level")
GK_ATOM(aria_live, "aria-live")
GK_ATOM(aria_modal, "aria-modal")
GK_ATOM(aria_multiline, "aria-multiline")
GK_ATOM(aria_multiselectable, "aria-multiselectable")
GK_ATOM(aria_orientation, "aria-orientation")

View File

@ -40,8 +40,6 @@
#include "nsWindowMemoryReporter.h"
#include "WindowNamedPropertiesHandler.h"
#include "nsFrameSelection.h"
#include "nsISelectionListener.h"
#include "nsCaret.h"
// Helper Classes
#include "nsJSUtils.h"
@ -194,8 +192,6 @@
#include "nsRefreshDriver.h"
#include "mozilla/dom/SelectionChangeEvent.h"
#include "mozilla/AddonPathService.h"
#include "mozilla/Services.h"
#include "mozilla/Telemetry.h"
@ -275,7 +271,6 @@ static PopupControlState gPopupControlState = openAbused;
static int32_t gRunningTimeoutDepth = 0;
static bool gMouseDown = false;
static bool gDragServiceDisabled = false;
static bool gSelectionCaretPrefEnabled = false;
static FILE *gDumpFile = nullptr;
static uint64_t gNextWindowID = 0;
static uint32_t gSerialCounter = 0;
@ -1191,9 +1186,6 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
Preferences::AddBoolVarCache(&sIdleObserversAPIFuzzTimeDisabled,
"dom.idle-observers-api.fuzz_time.disabled",
false);
Preferences::AddBoolVarCache(&gSelectionCaretPrefEnabled,
"selectioncaret.enabled",
false);
}
if (gDumpFile == nullptr) {
@ -9293,61 +9285,6 @@ public:
nsString mAction;
};
static bool
CheckReason(int16_t aReason, SelectionChangeReason aReasonType)
{
switch (aReasonType) {
case SelectionChangeReason::Drag:
return aReason & nsISelectionListener::DRAG_REASON;
case SelectionChangeReason::Mousedown:
return aReason & nsISelectionListener::MOUSEDOWN_REASON;
case SelectionChangeReason::Mouseup:
return aReason & nsISelectionListener::MOUSEUP_REASON;
case SelectionChangeReason::Keypress:
return aReason & nsISelectionListener::KEYPRESS_REASON;
case SelectionChangeReason::Selectall:
return aReason & nsISelectionListener::SELECTALL_REASON;
case SelectionChangeReason::Collapsetostart:
return aReason & nsISelectionListener::COLLAPSETOSTART_REASON;
case SelectionChangeReason::Collapsetoend:
return aReason & nsISelectionListener::COLLAPSETOEND_REASON;
default:
return false;
}
}
static nsRect
GetSelectionBoundingRect(Selection* aSel, nsIPresShell* aShell)
{
nsRect res;
// Bounding client rect may be empty after calling GetBoundingClientRect
// when range is collapsed. So we get caret's rect when range is
// collapsed.
if (aSel->IsCollapsed()) {
aShell->FlushPendingNotifications(Flush_Layout);
nsIFrame* frame = nsCaret::GetGeometry(aSel, &res);
if (frame) {
nsIFrame* relativeTo =
nsLayoutUtils::GetContainingBlockForClientRect(frame);
res = nsLayoutUtils::TransformFrameRectToAncestor(frame, res, relativeTo);
}
} else {
int32_t rangeCount = aSel->GetRangeCount();
nsLayoutUtils::RectAccumulator accumulator;
for (int32_t idx = 0; idx < rangeCount; ++idx) {
nsRange* range = aSel->GetRangeAt(idx);
nsRange::CollectClientRects(&accumulator, range,
range->GetStartParent(), range->StartOffset(),
range->GetEndParent(), range->EndOffset(),
true, false);
}
res = accumulator.mResultRect.IsEmpty() ? accumulator.mFirstRect :
accumulator.mResultRect;
}
return res;
}
NS_IMETHODIMP
nsGlobalWindow::UpdateCommands(const nsAString& anAction, nsISelection* aSel, int16_t aReason)
{
@ -9370,55 +9307,6 @@ nsGlobalWindow::UpdateCommands(const nsAString& anAction, nsISelection* aSel, in
}
}
if (gSelectionCaretPrefEnabled && mDoc && anAction.EqualsLiteral("selectionchange")) {
SelectionChangeEventInit init;
init.mBubbles = true;
if (aSel) {
bool isTouchCaretVisible = false;
bool isCollapsed = aSel->Collapsed();
nsIPresShell *shell = mDoc->GetShell();
if (shell) {
nsRefPtr<TouchCaret> touchCaret = shell->GetTouchCaret();
if (touchCaret) {
isTouchCaretVisible = touchCaret->GetVisibility();
}
}
// Dispatch selection change events when touch caret is visible even if selection
// is collapsed because it could be the shortcut mode, otherwise ignore this
// UpdateCommands
if (isCollapsed && !isTouchCaretVisible) {
return NS_OK;
}
Selection* selection = static_cast<Selection*>(aSel);
nsRect rect = GetSelectionBoundingRect(selection, mDoc->GetShell());
nsRefPtr<DOMRect> domRect = new DOMRect(ToSupports(this));
domRect->SetLayoutRect(rect);
init.mBoundingClientRect = domRect;
selection->Stringify(init.mSelectedText);
for (uint32_t reasonType = 0;
reasonType < static_cast<uint32_t>(SelectionChangeReason::EndGuard_);
++reasonType) {
SelectionChangeReason strongReasonType =
static_cast<SelectionChangeReason>(reasonType);
if (CheckReason(aReason, strongReasonType)) {
init.mReasons.AppendElement(strongReasonType);
}
}
nsRefPtr<SelectionChangeEvent> event =
SelectionChangeEvent::Constructor(mDoc, NS_LITERAL_STRING("mozselectionchange"), init);
event->SetTrusted(true);
event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
bool ret;
mDoc->DispatchEvent(event, &ret);
}
}
return NS_OK;
}

View File

@ -4,33 +4,17 @@
* 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/. */
#include "base/basictypes.h"
#include "BluetoothUtils.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothService.h"
#include "BluetoothServiceBluedroid.h"
#include "BluetoothUtils.h"
#include "jsapi.h"
#include "mozilla/Scoped.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "nsContentUtils.h"
#include "nsIScriptContext.h"
#include "nsISystemMessagesInternal.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsServiceManagerUtils.h"
BEGIN_BLUETOOTH_NAMESPACE
uint16_t
UuidToServiceClassInt(const BluetoothUuid& mUuid)
{
// extract short UUID 0000xxxx-0000-1000-8000-00805f9b34fb
uint16_t shortUuid;
memcpy(&shortUuid, mUuid.mUuid + 2, sizeof(uint16_t));
return ntohs(shortUuid);
}
bool
SetJsObject(JSContext* aContext,
const BluetoothValue& aValue,
@ -123,6 +107,37 @@ BroadcastSystemMessage(const nsAString& aType,
return true;
}
bool
BroadcastSystemMessage(const nsAString& aType,
const InfallibleTArray<BluetoothNamedValue>& aData)
{
mozilla::AutoSafeJSContext cx;
NS_ASSERTION(!::JS_IsExceptionPending(cx),
"Shouldn't get here when an exception is pending!");
JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(),
JS::NullPtr()));
if (!obj) {
BT_WARNING("Failed to new JSObject for system message!");
return false;
}
if (!SetJsObject(cx, aData, obj)) {
BT_WARNING("Failed to set properties of system message!");
return false;
}
nsCOMPtr<nsISystemMessagesInternal> systemMessenger =
do_GetService("@mozilla.org/system-message-internal;1");
NS_ENSURE_TRUE(systemMessenger, false);
JS::Rooted<JS::Value> value(cx, JS::ObjectValue(*obj));
systemMessenger->BroadcastMessage(aType, value,
JS::UndefinedHandleValue);
return true;
}
void
DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
const BluetoothValue& aValue,

View File

@ -4,8 +4,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_bluetooth_bluetoothutils_h__
#define mozilla_dom_bluetooth_bluetoothutils_h__
#ifndef mozilla_dom_bluetooth_bluetoothutils_h
#define mozilla_dom_bluetooth_bluetoothutils_h
#include "BluetoothCommon.h"
#include "js/TypeDecls.h"
@ -16,9 +16,6 @@ class BluetoothNamedValue;
class BluetoothValue;
class BluetoothReplyRunnable;
uint16_t
UuidToServiceClassInt(const BluetoothUuid& mUuid);
bool
SetJsObject(JSContext* aContext,
const BluetoothValue& aValue,
@ -28,6 +25,10 @@ bool
BroadcastSystemMessage(const nsAString& aType,
const BluetoothValue& aData);
bool
BroadcastSystemMessage(const nsAString& aType,
const InfallibleTArray<BluetoothNamedValue>& aData);
void
DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
const BluetoothValue& aValue,

View File

@ -1098,6 +1098,15 @@ BluetoothServiceBluedroid::ToggleCalls(BluetoothReplyRunnable* aRunnable)
{
}
uint16_t
BluetoothServiceBluedroid::UuidToServiceClassInt(const BluetoothUuid& mUuid)
{
// extract short UUID 0000xxxx-0000-1000-8000-00805f9b34fb
uint16_t shortUuid;
memcpy(&shortUuid, mUuid.mUuid + 2, sizeof(uint16_t));
return ntohs(shortUuid);
}
//
// Bluetooth notifications
//

View File

@ -221,6 +221,8 @@ protected:
static ControlPlayStatus PlayStatusStringToControlPlayStatus(
const nsAString& aPlayStatus);
uint16_t UuidToServiceClassInt(const BluetoothUuid& mUuid);
};
END_BLUETOOTH_NAMESPACE

View File

@ -392,6 +392,37 @@ BluetoothDBusService::~BluetoothDBusService()
sGetPropertyMonitor = nullptr;
}
static nsString
GetObjectPathFromAddress(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress)
{
// The object path would be like /org/bluez/2906/hci0/dev_00_23_7F_CB_B4_F1,
// and the adapter path would be the first part of the object path, according
// to the example above, it's /org/bluez/2906/hci0.
nsString devicePath(aAdapterPath);
devicePath.AppendLiteral("/dev_");
devicePath.Append(aDeviceAddress);
devicePath.ReplaceChar(':', '_');
return devicePath;
}
static nsString
GetAddressFromObjectPath(const nsAString& aObjectPath)
{
// The object path would be like /org/bluez/2906/hci0/dev_00_23_7F_CB_B4_F1,
// and the adapter path would be the first part of the object path, according
// to the example above, it's /org/bluez/2906/hci0.
nsString address(aObjectPath);
int addressHead = address.RFind("/") + 5;
MOZ_ASSERT(addressHead + BLUETOOTH_ADDRESS_LENGTH == (int)address.Length());
address.Cut(0, addressHead);
address.ReplaceChar('_', ':');
return address;
}
static bool
GetConnectedDevicesFilter(const BluetoothValue& aValue)
{

View File

@ -690,6 +690,28 @@ BluetoothHfpManager::HandleShutdown()
sBluetoothHfpManager = nullptr;
}
void
BluetoothHfpManager::ParseAtCommand(const nsACString& aAtCommand,
const int aStart,
nsTArray<nsCString>& aRetValues)
{
int length = aAtCommand.Length();
int begin = aStart;
for (int i = aStart; i < length; ++i) {
// Use ',' as separator
if (aAtCommand[i] == ',') {
nsCString tmp(nsDependentCSubstring(aAtCommand, begin, i - begin));
aRetValues.AppendElement(tmp);
begin = i + 1;
}
}
nsCString tmp(nsDependentCSubstring(aAtCommand, begin));
aRetValues.AppendElement(tmp);
}
// Virtual function of class SocketConsumer
void
BluetoothHfpManager::ReceiveSocketData(BluetoothSocket* aSocket,

View File

@ -132,6 +132,9 @@ public:
#endif
private:
void ParseAtCommand(const nsACString& aAtCommand, const int aStart,
nsTArray<nsCString>& aRetValues);
class CloseScoTask;
class GetVolumeTask;
#ifdef MOZ_B2G_RIL

View File

@ -1,198 +0,0 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
#include "base/basictypes.h"
#include "BluetoothReplyRunnable.h"
#include "BluetoothService.h"
#include "BluetoothUtils.h"
#include "jsapi.h"
#include "mozilla/Scoped.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "nsContentUtils.h"
#include "nsIScriptContext.h"
#include "nsISystemMessagesInternal.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsServiceManagerUtils.h"
BEGIN_BLUETOOTH_NAMESPACE
bool
SetJsObject(JSContext* aContext,
const BluetoothValue& aValue,
JS::Handle<JSObject*> aObj)
{
MOZ_ASSERT(aContext && aObj);
if (aValue.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
BT_WARNING("SetJsObject: Invalid parameter type");
return false;
}
const nsTArray<BluetoothNamedValue>& arr =
aValue.get_ArrayOfBluetoothNamedValue();
for (uint32_t i = 0; i < arr.Length(); i++) {
JS::Rooted<JS::Value> val(aContext);
const BluetoothValue& v = arr[i].value();
switch(v.type()) {
case BluetoothValue::TnsString: {
JSString* jsData = JS_NewUCStringCopyN(aContext,
v.get_nsString().BeginReading(),
v.get_nsString().Length());
NS_ENSURE_TRUE(jsData, false);
val = STRING_TO_JSVAL(jsData);
break;
}
case BluetoothValue::Tuint32_t:
val = INT_TO_JSVAL(v.get_uint32_t());
break;
case BluetoothValue::Tbool:
val = BOOLEAN_TO_JSVAL(v.get_bool());
break;
default:
BT_WARNING("SetJsObject: Parameter is not handled");
break;
}
if (!JS_SetProperty(aContext, aObj,
NS_ConvertUTF16toUTF8(arr[i].name()).get(),
val)) {
BT_WARNING("Failed to set property");
return false;
}
}
return true;
}
nsString
GetObjectPathFromAddress(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress)
{
// The object path would be like /org/bluez/2906/hci0/dev_00_23_7F_CB_B4_F1,
// and the adapter path would be the first part of the object path, according
// to the example above, it's /org/bluez/2906/hci0.
nsString devicePath(aAdapterPath);
devicePath.AppendLiteral("/dev_");
devicePath.Append(aDeviceAddress);
devicePath.ReplaceChar(':', '_');
return devicePath;
}
nsString
GetAddressFromObjectPath(const nsAString& aObjectPath)
{
// The object path would be like /org/bluez/2906/hci0/dev_00_23_7F_CB_B4_F1,
// and the adapter path would be the first part of the object path, according
// to the example above, it's /org/bluez/2906/hci0.
nsString address(aObjectPath);
int addressHead = address.RFind("/") + 5;
MOZ_ASSERT(addressHead + BLUETOOTH_ADDRESS_LENGTH == (int)address.Length());
address.Cut(0, addressHead);
address.ReplaceChar('_', ':');
return address;
}
bool
BroadcastSystemMessage(const nsAString& aType,
const InfallibleTArray<BluetoothNamedValue>& aData)
{
mozilla::AutoSafeJSContext cx;
NS_ASSERTION(!::JS_IsExceptionPending(cx),
"Shouldn't get here when an exception is pending!");
JS::Rooted<JSObject*> obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(),
JS::NullPtr()));
if (!obj) {
BT_WARNING("Failed to new JSObject for system message!");
return false;
}
if (!SetJsObject(cx, aData, obj)) {
BT_WARNING("Failed to set properties of system message!");
return false;
}
nsCOMPtr<nsISystemMessagesInternal> systemMessenger =
do_GetService("@mozilla.org/system-message-internal;1");
NS_ENSURE_TRUE(systemMessenger, false);
JS::Rooted<JS::Value> value(cx, JS::ObjectValue(*obj));
systemMessenger->BroadcastMessage(aType, value,
JS::UndefinedHandleValue);
return true;
}
void
DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
const BluetoothValue& aValue,
const nsAString& aErrorStr)
{
// Reply will be deleted by the runnable after running on main thread
BluetoothReply* reply;
if (!aErrorStr.IsEmpty()) {
nsString err(aErrorStr);
reply = new BluetoothReply(BluetoothReplyError(err));
} else {
MOZ_ASSERT(aValue.type() != BluetoothValue::T__None);
reply = new BluetoothReply(BluetoothReplySuccess(aValue));
}
aRunnable->SetReply(reply);
if (NS_FAILED(NS_DispatchToMainThread(aRunnable))) {
BT_WARNING("Failed to dispatch to main thread!");
}
}
void
ParseAtCommand(const nsACString& aAtCommand, const int aStart,
nsTArray<nsCString>& aRetValues)
{
int length = aAtCommand.Length();
int begin = aStart;
for (int i = aStart; i < length; ++i) {
// Use ',' as separator
if (aAtCommand[i] == ',') {
nsCString tmp(nsDependentCSubstring(aAtCommand, begin, i - begin));
aRetValues.AppendElement(tmp);
begin = i + 1;
}
}
nsCString tmp(nsDependentCSubstring(aAtCommand, begin));
aRetValues.AppendElement(tmp);
}
void
DispatchStatusChangedEvent(const nsAString& aType,
const nsAString& aAddress,
bool aStatus)
{
MOZ_ASSERT(NS_IsMainThread());
InfallibleTArray<BluetoothNamedValue> data;
data.AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("address"), nsString(aAddress)));
data.AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("status"), aStatus));
BluetoothSignal signal(nsString(aType), NS_LITERAL_STRING(KEY_ADAPTER), data);
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
bs->DistributeSignal(signal);
}
END_BLUETOOTH_NAMESPACE

View File

@ -1,51 +0,0 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_bluetooth_bluetoothutils_h__
#define mozilla_dom_bluetooth_bluetoothutils_h__
#include "BluetoothCommon.h"
#include "js/TypeDecls.h"
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothNamedValue;
class BluetoothValue;
class BluetoothReplyRunnable;
bool
SetJsObject(JSContext* aContext,
const BluetoothValue& aValue,
JS::Handle<JSObject*> aObj);
nsString
GetObjectPathFromAddress(const nsAString& aAdapterPath,
const nsAString& aDeviceAddress);
nsString
GetAddressFromObjectPath(const nsAString& aObjectPath);
bool
BroadcastSystemMessage(const nsAString& aType,
const InfallibleTArray<BluetoothNamedValue>& aData);
void
DispatchBluetoothReply(BluetoothReplyRunnable* aRunnable,
const BluetoothValue& aValue,
const nsAString& aErrorStr);
void
ParseAtCommand(const nsACString& aAtCommand, const int aStart,
nsTArray<nsCString>& aRetValues);
void
DispatchStatusChangedEvent(const nsAString& aType,
const nsAString& aDeviceAddress,
bool aStatus);
END_BLUETOOTH_NAMESPACE
#endif

View File

@ -15,6 +15,7 @@ if CONFIG['MOZ_B2G_BT']:
'BluetoothPropertyContainer.cpp',
'BluetoothReplyRunnable.cpp',
'BluetoothService.cpp',
'BluetoothUtils.cpp',
'BluetoothUuid.cpp',
'ipc/BluetoothChild.cpp',
'ipc/BluetoothParent.cpp',
@ -36,8 +37,7 @@ if CONFIG['MOZ_B2G_BT']:
'bluez/BluetoothHfpManager.cpp',
'bluez/BluetoothOppManager.cpp',
'bluez/BluetoothSocket.cpp',
'bluez/BluetoothUnixSocketConnector.cpp',
'bluez/BluetoothUtils.cpp',
'bluez/BluetoothUnixSocketConnector.cpp'
]
LOCAL_INCLUDES += [
'bluez',
@ -60,8 +60,7 @@ if CONFIG['MOZ_B2G_BT']:
'bluedroid/BluetoothServiceBluedroid.cpp',
'bluedroid/BluetoothSocket.cpp',
'bluedroid/BluetoothSocketHALInterface.cpp',
'bluedroid/BluetoothSocketMessageWatcher.cpp',
'bluedroid/BluetoothUtils.cpp',
'bluedroid/BluetoothSocketMessageWatcher.cpp'
]
LOCAL_INCLUDES += [
'bluedroid',

View File

@ -145,34 +145,7 @@ BluetoothService::ToggleBtAck::ToggleBtAck(bool aEnabled)
NS_METHOD
BluetoothService::ToggleBtAck::Run()
{
MOZ_ASSERT(NS_IsMainThread());
// This is requested in Bug 836516. With settings this property, WLAN
// firmware could be aware of Bluetooth has been turned on/off, so that the
// mecahnism of handling coexistence of WIFI and Bluetooth could be started.
//
// In the future, we may have our own way instead of setting a system
// property to let firmware developers be able to sense that Bluetooth has
// been toggled.
#if defined(MOZ_WIDGET_GONK)
if (property_set(PROP_BLUETOOTH_ENABLED, mEnabled ? "true" : "false") != 0) {
BT_WARNING("Failed to set bluetooth enabled property");
}
#endif
NS_ENSURE_TRUE(sBluetoothService, NS_OK);
if (sInShutdown) {
sBluetoothService = nullptr;
return NS_OK;
}
// Update mEnabled of BluetoothService object since
// StartInternal/StopInternal have been already done.
sBluetoothService->SetEnabled(mEnabled);
sToggleInProgress = false;
sBluetoothService->FireAdapterStateChanged(mEnabled);
BluetoothService::AcknowledgeToggleBt(mEnabled);
return NS_OK;
}
@ -709,3 +682,45 @@ BluetoothService::FireAdapterStateChanged(bool aEnable)
NS_LITERAL_STRING(KEY_ADAPTER), value);
DistributeSignal(signal);
}
void
BluetoothService::AcknowledgeToggleBt(bool aEnabled)
{
MOZ_ASSERT(NS_IsMainThread());
#if defined(MOZ_WIDGET_GONK)
// This is requested in Bug 836516. With settings this property, WLAN
// firmware could be aware of Bluetooth has been turned on/off, so that the
// mecahnism of handling coexistence of WIFI and Bluetooth could be started.
//
// In the future, we may have our own way instead of setting a system
// property to let firmware developers be able to sense that Bluetooth has
// been toggled.
if (property_set(PROP_BLUETOOTH_ENABLED, aEnabled ? "true" : "false") != 0) {
BT_WARNING("Failed to set bluetooth enabled property");
}
#endif
if (sInShutdown) {
sBluetoothService = nullptr;
return;
}
NS_ENSURE_TRUE_VOID(sBluetoothService);
sBluetoothService->CompleteToggleBt(aEnabled);
}
void
BluetoothService::CompleteToggleBt(bool aEnabled)
{
MOZ_ASSERT(NS_IsMainThread());
// Update |mEnabled| of |BluetoothService| object since
// |StartInternal| and |StopInternal| have been already
// done.
SetEnabled(aEnabled);
sToggleInProgress = false;
FireAdapterStateChanged(aEnabled);
}

View File

@ -315,6 +315,8 @@ public:
bool
IsToggling() const;
static void AcknowledgeToggleBt(bool aEnabled);
void FireAdapterStateChanged(bool aEnable);
nsresult EnableDisable(bool aEnable,
BluetoothReplyRunnable* aRunnable);
@ -392,6 +394,8 @@ protected:
static BluetoothService*
Create();
void CompleteToggleBt(bool aEnabled);
typedef nsClassHashtable<nsStringHashKey, BluetoothSignalObserverList >
BluetoothSignalObserverTable;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,412 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_bluetooth_bluetoothdaemonhandsfreeinterface_h
#define mozilla_dom_bluetooth_bluetoothdaemonhandsfreeinterface_h
#include "BluetoothDaemonHelpers.h"
#include "BluetoothInterface.h"
#include "BluetoothInterfaceHelpers.h"
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothSetupResultHandler;
class BluetoothDaemonHandsfreeModule
{
public:
enum {
SERVICE_ID = 0x05
};
enum {
OPCODE_ERROR = 0x00,
OPCODE_CONNECT = 0x01,
OPCODE_DISCONNECT = 0x02,
OPCODE_CONNECT_AUDIO = 0x03,
OPCODE_DISCONNECT_AUDIO = 0x04,
OPCODE_START_VOICE_RECOGNITION = 0x05,
OPCODE_STOP_VOICE_RECOGNITION =0x06,
OPCODE_VOLUME_CONTROL = 0x07,
OPCODE_DEVICE_STATUS_NOTIFICATION = 0x08,
OPCODE_COPS_RESPONSE = 0x09,
OPCODE_CIND_RESPONSE = 0x0a,
OPCODE_FORMATTED_AT_RESPONSE = 0x0b,
OPCODE_AT_RESPONSE = 0x0c,
OPCODE_CLCC_RESPONSE = 0x0d,
OPCODE_PHONE_STATE_CHANGE = 0x0e
};
virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0;
virtual nsresult RegisterModule(uint8_t aId, uint8_t aMode,
BluetoothSetupResultHandler* aRes) = 0;
virtual nsresult UnregisterModule(uint8_t aId,
BluetoothSetupResultHandler* aRes) = 0;
void SetNotificationHandler(
BluetoothHandsfreeNotificationHandler* aNotificationHandler);
//
// Commands
//
nsresult ConnectCmd(const nsAString& aBdAddr,
BluetoothHandsfreeResultHandler* aRes);
nsresult DisconnectCmd(const nsAString& aBdAddr,
BluetoothHandsfreeResultHandler* aRes);
nsresult ConnectAudioCmd(const nsAString& aBdAddr,
BluetoothHandsfreeResultHandler* aRes);
nsresult DisconnectAudioCmd(const nsAString& aBdAddr,
BluetoothHandsfreeResultHandler* aRes);
/* Voice Recognition */
nsresult StartVoiceRecognitionCmd(BluetoothHandsfreeResultHandler* aRes);
nsresult StopVoiceRecognitionCmd(BluetoothHandsfreeResultHandler* aRes);
/* Volume */
nsresult VolumeControlCmd(BluetoothHandsfreeVolumeType aType, int aVolume,
BluetoothHandsfreeResultHandler* aRes);
/* Device status */
nsresult DeviceStatusNotificationCmd(
BluetoothHandsfreeNetworkState aNtkState,
BluetoothHandsfreeServiceType aSvcType,
int aSignal, int aBattChg,
BluetoothHandsfreeResultHandler* aRes);
/* Responses */
nsresult CopsResponseCmd(const char* aCops,
BluetoothHandsfreeResultHandler* aRes);
nsresult CindResponseCmd(int aSvc, int aNumActive, int aNumHeld,
BluetoothHandsfreeCallState aCallSetupState,
int aSignal, int aRoam, int aBattChg,
BluetoothHandsfreeResultHandler* aRes);
nsresult FormattedAtResponseCmd(const char* aRsp,
BluetoothHandsfreeResultHandler* aRes);
nsresult AtResponseCmd(BluetoothHandsfreeAtResponse aResponseCode,
int aErrorCode,
BluetoothHandsfreeResultHandler* aRes);
nsresult ClccResponseCmd(int aIndex, BluetoothHandsfreeCallDirection aDir,
BluetoothHandsfreeCallState aState,
BluetoothHandsfreeCallMode aMode,
BluetoothHandsfreeCallMptyType aMpty,
const nsAString& aNumber,
BluetoothHandsfreeCallAddressType aType,
BluetoothHandsfreeResultHandler* aRes);
/* Phone State */
nsresult PhoneStateChangeCmd(int aNumActive, int aNumHeld,
BluetoothHandsfreeCallState aCallSetupState,
const nsAString& aNumber,
BluetoothHandsfreeCallAddressType aType,
BluetoothHandsfreeResultHandler* aRes);
protected:
nsresult Send(BluetoothDaemonPDU* aPDU,
BluetoothHandsfreeResultHandler* aRes);
void HandleSvc(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU, void* aUserData);
//
// Responses
//
typedef BluetoothResultRunnable0<BluetoothHandsfreeResultHandler, void>
ResultRunnable;
typedef BluetoothResultRunnable1<BluetoothHandsfreeResultHandler, void,
BluetoothStatus, BluetoothStatus>
ErrorRunnable;
void ErrorRsp(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeResultHandler* aRes);
void ConnectRsp(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeResultHandler* aRes);
void DisconnectRsp(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeResultHandler* aRes);
void ConnectAudioRsp(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeResultHandler* aRes);
void DisconnectAudioRsp(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeResultHandler* aRes);
void StartVoiceRecognitionRsp(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeResultHandler* aRes);
void StopVoiceRecognitionRsp(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeResultHandler* aRes);
void VolumeControlRsp(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeResultHandler* aRes);
void DeviceStatusNotificationRsp(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeResultHandler* aRes);
void CopsResponseRsp(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeResultHandler* aRes);
void CindResponseRsp(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeResultHandler* aRes);
void FormattedAtResponseRsp(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeResultHandler* aRes);
void AtResponseRsp(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeResultHandler* aRes);
void ClccResponseRsp(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeResultHandler* aRes);
void PhoneStateChangeRsp(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeResultHandler* aRes);
void HandleRsp(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
void* aUserData);
//
// Notifications
//
class NotificationHandlerWrapper;
typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
BluetoothHandsfreeConnectionState,
nsString,
BluetoothHandsfreeConnectionState,
const nsAString&>
ConnectionStateNotification;
typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
BluetoothHandsfreeAudioState,
nsString,
BluetoothHandsfreeAudioState,
const nsAString&>
AudioStateNotification;
typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
BluetoothHandsfreeVoiceRecognitionState>
VoiceRecognitionNotification;
typedef BluetoothNotificationRunnable0<NotificationHandlerWrapper, void>
AnswerCallNotification;
typedef BluetoothNotificationRunnable0<NotificationHandlerWrapper, void>
HangupCallNotification;
typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
BluetoothHandsfreeVolumeType, int>
VolumeNotification;
typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
nsString, const nsAString&>
DialCallNotification;
typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
char>
DtmfNotification;
typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
BluetoothHandsfreeNRECState>
NRECNotification;
typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
BluetoothHandsfreeCallHoldType>
CallHoldNotification;
typedef BluetoothNotificationRunnable0<NotificationHandlerWrapper, void>
CnumNotification;
typedef BluetoothNotificationRunnable0<NotificationHandlerWrapper, void>
CindNotification;
typedef BluetoothNotificationRunnable0<NotificationHandlerWrapper, void>
CopsNotification;
typedef BluetoothNotificationRunnable0<NotificationHandlerWrapper, void>
ClccNotification;
typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
nsCString, const nsACString&>
UnknownAtNotification;
typedef BluetoothNotificationRunnable0<NotificationHandlerWrapper, void>
KeyPressedNotification;
class AudioStateInitOp;
class ConnectionStateInitOp;
class DialCallInitOp;
class VolumeInitOp;
class UnknownAtInitOp;
void ConnectionStateNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU);
void AudioStateNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU);
void VoiceRecognitionNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU);
void AnswerCallNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU);
void HangupCallNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU);
void VolumeNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU);
void DialCallNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU);
void DtmfNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU);
void NRECNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU);
void CallHoldNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU);
void CnumNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU);
void CindNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU);
void CopsNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU);
void ClccNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU);
void UnknownAtNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU);
void KeyPressedNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU);
void HandleNtf(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU,
void* aUserData);
static BluetoothHandsfreeNotificationHandler* sNotificationHandler;
};
class BluetoothDaemonHandsfreeInterface MOZ_FINAL
: public BluetoothHandsfreeInterface
{
class CleanupResultHandler;
class InitResultHandler;
enum {
MODE_HEADSET = 0x00,
MODE_NARROWBAND_SPEECH = 0x01,
MODE_NARROWBAND_WIDEBAND_SPEECH = 0x02
};
public:
BluetoothDaemonHandsfreeInterface(BluetoothDaemonHandsfreeModule* aModule);
~BluetoothDaemonHandsfreeInterface();
void Init(
BluetoothHandsfreeNotificationHandler* aNotificationHandler,
BluetoothHandsfreeResultHandler* aRes);
void Cleanup(BluetoothHandsfreeResultHandler* aRes);
/* Connect / Disconnect */
void Connect(const nsAString& aBdAddr,
BluetoothHandsfreeResultHandler* aRes);
void Disconnect(const nsAString& aBdAddr,
BluetoothHandsfreeResultHandler* aRes);
void ConnectAudio(const nsAString& aBdAddr,
BluetoothHandsfreeResultHandler* aRes);
void DisconnectAudio(const nsAString& aBdAddr,
BluetoothHandsfreeResultHandler* aRes);
/* Voice Recognition */
void StartVoiceRecognition(BluetoothHandsfreeResultHandler* aRes);
void StopVoiceRecognition(BluetoothHandsfreeResultHandler* aRes);
/* Volume */
void VolumeControl(BluetoothHandsfreeVolumeType aType, int aVolume,
BluetoothHandsfreeResultHandler* aRes);
/* Device status */
void DeviceStatusNotification(BluetoothHandsfreeNetworkState aNtkState,
BluetoothHandsfreeServiceType aSvcType,
int aSignal, int aBattChg,
BluetoothHandsfreeResultHandler* aRes);
/* Responses */
void CopsResponse(const char* aCops,
BluetoothHandsfreeResultHandler* aRes);
void CindResponse(int aSvc, int aNumActive, int aNumHeld,
BluetoothHandsfreeCallState aCallSetupState,
int aSignal, int aRoam, int aBattChg,
BluetoothHandsfreeResultHandler* aRes);
void FormattedAtResponse(const char* aRsp,
BluetoothHandsfreeResultHandler* aRes);
void AtResponse(BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
BluetoothHandsfreeResultHandler* aRes);
void ClccResponse(int aIndex, BluetoothHandsfreeCallDirection aDir,
BluetoothHandsfreeCallState aState,
BluetoothHandsfreeCallMode aMode,
BluetoothHandsfreeCallMptyType aMpty,
const nsAString& aNumber,
BluetoothHandsfreeCallAddressType aType,
BluetoothHandsfreeResultHandler* aRes);
/* Phone State */
void PhoneStateChange(int aNumActive, int aNumHeld,
BluetoothHandsfreeCallState aCallSetupState,
const nsAString& aNumber,
BluetoothHandsfreeCallAddressType aType,
BluetoothHandsfreeResultHandler* aRes);
private:
void DispatchError(BluetoothHandsfreeResultHandler* aRes,
BluetoothStatus aStatus);
BluetoothDaemonHandsfreeModule* mModule;
};
END_BLUETOOTH_NAMESPACE
#endif

View File

@ -45,6 +45,18 @@ Convert(bool aIn, BluetoothScanMode& aOut)
return NS_OK;
}
nsresult
Convert(int aIn, uint8_t& aOut)
{
if (NS_WARN_IF(aIn < std::numeric_limits<uint8_t>::min()) ||
NS_WARN_IF(aIn > std::numeric_limits<uint8_t>::max())) {
aOut = 0; // silences compiler warning
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = static_cast<uint8_t>(aIn);
return NS_OK;
}
nsresult
Convert(int aIn, int16_t& aOut)
{
@ -71,6 +83,20 @@ Convert(uint8_t aIn, bool& aOut)
return NS_OK;
}
nsresult
Convert(uint8_t aIn, char& aOut)
{
aOut = static_cast<char>(aIn);
return NS_OK;
}
nsresult
Convert(uint8_t aIn, int& aOut)
{
aOut = static_cast<int>(aIn);
return NS_OK;
}
nsresult
Convert(uint8_t aIn, BluetoothAclState& aOut)
{
@ -100,6 +126,97 @@ Convert(uint8_t aIn, BluetoothBondState& aOut)
return NS_OK;
}
nsresult
Convert(uint8_t aIn, BluetoothHandsfreeAudioState& aOut)
{
static const BluetoothHandsfreeAudioState sAudioState[] = {
CONVERT(0x00, HFP_AUDIO_STATE_DISCONNECTED),
CONVERT(0x01, HFP_AUDIO_STATE_CONNECTING),
CONVERT(0x02, HFP_AUDIO_STATE_CONNECTED),
CONVERT(0x03, HFP_AUDIO_STATE_DISCONNECTING)
};
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sAudioState))) {
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sAudioState[aIn];
return NS_OK;
}
nsresult
Convert(uint8_t aIn, BluetoothHandsfreeCallHoldType& aOut)
{
static const BluetoothHandsfreeCallHoldType sCallHoldType[] = {
CONVERT(0x00, HFP_CALL_HOLD_RELEASEHELD),
CONVERT(0x01, HFP_CALL_HOLD_RELEASEACTIVE_ACCEPTHELD),
CONVERT(0x02, HFP_CALL_HOLD_HOLDACTIVE_ACCEPTHELD),
CONVERT(0x03, HFP_CALL_HOLD_ADDHELDTOCONF)
};
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallHoldType))) {
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sCallHoldType[aIn];
return NS_OK;
}
nsresult
Convert(uint8_t aIn, BluetoothHandsfreeConnectionState& aOut)
{
static const BluetoothHandsfreeConnectionState sConnectionState[] = {
CONVERT(0x00, HFP_CONNECTION_STATE_DISCONNECTED),
CONVERT(0x01, HFP_CONNECTION_STATE_CONNECTING),
CONVERT(0x02, HFP_CONNECTION_STATE_CONNECTED),
CONVERT(0x03, HFP_CONNECTION_STATE_SLC_CONNECTED),
CONVERT(0x04, HFP_CONNECTION_STATE_DISCONNECTING)
};
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sConnectionState))) {
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sConnectionState[aIn];
return NS_OK;
}
nsresult
Convert(uint8_t aIn, BluetoothHandsfreeNRECState& aOut)
{
static const BluetoothHandsfreeNRECState sNRECState[] = {
CONVERT(0x00, HFP_NREC_STOPPED),
CONVERT(0x01, HFP_NREC_STARTED)
};
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sNRECState))) {
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sNRECState[aIn];
return NS_OK;
}
nsresult
Convert(uint8_t aIn, BluetoothHandsfreeVoiceRecognitionState& aOut)
{
static const BluetoothHandsfreeVoiceRecognitionState sState[] = {
CONVERT(0x00, HFP_VOICE_RECOGNITION_STOPPED),
CONVERT(0x01, HFP_VOICE_RECOGNITION_STOPPED)
};
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sState))) {
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sState[aIn];
return NS_OK;
}
nsresult
Convert(uint8_t aIn, BluetoothHandsfreeVolumeType& aOut)
{
static const BluetoothHandsfreeVolumeType sVolumeType[] = {
CONVERT(0x00, HFP_VOLUME_TYPE_SPEAKER),
CONVERT(0x01, HFP_VOLUME_TYPE_MICROPHONE)
};
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sVolumeType))) {
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sVolumeType[aIn];
return NS_OK;
}
nsresult
Convert(int32_t aIn, BluetoothTypeOfDevice& aOut)
{
@ -373,6 +490,147 @@ Convert(const BluetoothAddress& aIn, nsAString& aOut)
return NS_OK;
}
nsresult
Convert(BluetoothHandsfreeAtResponse aIn, uint8_t& aOut)
{
static const uint8_t sAtResponse[] = {
CONVERT(HFP_AT_RESPONSE_ERROR, 0x00),
CONVERT(HFP_AT_RESPONSE_OK, 0x01)
};
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sAtResponse))) {
aOut = 0x00; // silences compiler warning
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sAtResponse[aIn];
return NS_OK;
}
nsresult
Convert(BluetoothHandsfreeCallAddressType aIn, uint8_t& aOut)
{
static const uint8_t sCallAddressType[] = {
CONVERT(HFP_CALL_ADDRESS_TYPE_UNKNOWN, 0x81),
CONVERT(HFP_CALL_ADDRESS_TYPE_INTERNATIONAL, 0x91)
};
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallAddressType))) {
aOut = 0x00; // silences compiler warning
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sCallAddressType[aIn];
return NS_OK;
}
nsresult
Convert(BluetoothHandsfreeCallDirection aIn, uint8_t& aOut)
{
static const uint8_t sCallDirection[] = {
CONVERT(HFP_CALL_DIRECTION_OUTGOING, 0x00),
CONVERT(HFP_CALL_DIRECTION_INCOMING, 0x01)
};
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallDirection))) {
aOut = 0x00; // silences compiler warning
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sCallDirection[aIn];
return NS_OK;
}
nsresult
Convert(BluetoothHandsfreeCallState aIn, uint8_t& aOut)
{
static const uint8_t sCallState[] = {
CONVERT(HFP_CALL_STATE_ACTIVE, 0x00),
CONVERT(HFP_CALL_STATE_HELD, 0x01),
CONVERT(HFP_CALL_STATE_DIALING, 0x02),
CONVERT(HFP_CALL_STATE_ALERTING, 0x03),
CONVERT(HFP_CALL_STATE_INCOMING, 0x04),
CONVERT(HFP_CALL_STATE_WAITING, 0x05),
CONVERT(HFP_CALL_STATE_IDLE, 0x06)
};
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallState))) {
aOut = 0x00; // silences compiler warning
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sCallState[aIn];
return NS_OK;
}
nsresult
Convert(BluetoothHandsfreeCallMode aIn, uint8_t& aOut)
{
static const uint8_t sCallMode[] = {
CONVERT(HFP_CALL_MODE_VOICE, 0x00),
CONVERT(HFP_CALL_MODE_DATA, 0x01),
CONVERT(HFP_CALL_MODE_FAX, 0x02)
};
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallMode))) {
aOut = 0x00; // silences compiler warning
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sCallMode[aIn];
return NS_OK;
}
nsresult
Convert(BluetoothHandsfreeCallMptyType aIn, uint8_t& aOut)
{
static const uint8_t sCallMptyType[] = {
CONVERT(HFP_CALL_MPTY_TYPE_SINGLE, 0x00),
CONVERT(HFP_CALL_MPTY_TYPE_MULTI, 0x01)
};
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sCallMptyType))) {
aOut = 0x00; // silences compiler warning
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sCallMptyType[aIn];
return NS_OK;
}
nsresult
Convert(BluetoothHandsfreeNetworkState aIn, uint8_t& aOut)
{
static const uint8_t sNetworkState[] = {
CONVERT(HFP_NETWORK_STATE_NOT_AVAILABLE, 0x00),
CONVERT(HFP_NETWORK_STATE_AVAILABLE, 0x01)
};
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sNetworkState))) {
aOut = 0x00; // silences compiler warning
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sNetworkState[aIn];
return NS_OK;
}
nsresult
Convert(BluetoothHandsfreeServiceType aIn, uint8_t& aOut)
{
static const uint8_t sServiceType[] = {
CONVERT(HFP_SERVICE_TYPE_HOME, 0x00),
CONVERT(HFP_SERVICE_TYPE_ROAMING, 0x01)
};
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sServiceType))) {
aOut = 0x00; // silences compiler warning
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sServiceType[aIn];
return NS_OK;
}
nsresult
Convert(BluetoothHandsfreeVolumeType aIn, uint8_t& aOut)
{
static const uint8_t sVolumeType[] = {
CONVERT(HFP_VOLUME_TYPE_SPEAKER, 0x00),
CONVERT(HFP_VOLUME_TYPE_MICROPHONE, 0x01)
};
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sVolumeType))) {
aOut = 0x00; // silences compiler warning
return NS_ERROR_ILLEGAL_VALUE;
}
aOut = sVolumeType[aIn];
return NS_OK;
}
nsresult
Convert(BluetoothPropertyType aIn, uint8_t& aOut)
{
@ -506,6 +764,69 @@ PackPDU(const BluetoothDaemonPDUHeader& aIn, BluetoothDaemonPDU& aPDU)
return PackPDU(aIn.mService, aIn.mOpcode, aIn.mLength, aPDU);
}
nsresult
PackPDU(const BluetoothHandsfreeAtResponse& aIn, BluetoothDaemonPDU& aPDU)
{
return PackPDU(
PackConversion<BluetoothHandsfreeAtResponse, uint8_t>(aIn), aPDU);
}
nsresult
PackPDU(const BluetoothHandsfreeCallAddressType& aIn, BluetoothDaemonPDU& aPDU)
{
return PackPDU(
PackConversion<BluetoothHandsfreeCallAddressType, uint8_t>(aIn), aPDU);
}
nsresult
PackPDU(const BluetoothHandsfreeCallDirection& aIn, BluetoothDaemonPDU& aPDU)
{
return PackPDU(
PackConversion<BluetoothHandsfreeCallDirection, uint8_t>(aIn), aPDU);
}
nsresult
PackPDU(const BluetoothHandsfreeCallMode& aIn, BluetoothDaemonPDU& aPDU)
{
return PackPDU(
PackConversion<BluetoothHandsfreeCallMode, uint8_t>(aIn), aPDU);
}
nsresult
PackPDU(const BluetoothHandsfreeCallMptyType& aIn, BluetoothDaemonPDU& aPDU)
{
return PackPDU(
PackConversion<BluetoothHandsfreeCallMptyType, uint8_t>(aIn), aPDU);
}
nsresult
PackPDU(const BluetoothHandsfreeCallState& aIn, BluetoothDaemonPDU& aPDU)
{
return PackPDU(
PackConversion<BluetoothHandsfreeCallState, uint8_t>(aIn), aPDU);
}
nsresult
PackPDU(const BluetoothHandsfreeNetworkState& aIn, BluetoothDaemonPDU& aPDU)
{
return PackPDU(
PackConversion<BluetoothHandsfreeNetworkState, uint8_t>(aIn), aPDU);
}
nsresult
PackPDU(const BluetoothHandsfreeServiceType& aIn, BluetoothDaemonPDU& aPDU)
{
return PackPDU(
PackConversion<BluetoothHandsfreeServiceType, uint8_t>(aIn), aPDU);
}
nsresult
PackPDU(const BluetoothHandsfreeVolumeType& aIn, BluetoothDaemonPDU& aPDU)
{
return PackPDU(
PackConversion<BluetoothHandsfreeVolumeType, uint8_t>(aIn), aPDU);
}
nsresult
PackPDU(const BluetoothNamedValue& aIn, BluetoothDaemonPDU& aPDU)
{
@ -591,6 +912,12 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, bool& aOut)
return UnpackPDU(aPDU, UnpackConversion<uint8_t, bool>(aOut));
}
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, char& aOut)
{
return UnpackPDU(aPDU, UnpackConversion<uint8_t, char>(aOut));
}
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAclState& aOut)
{
@ -610,6 +937,50 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothTypeOfDevice& aOut)
aPDU, UnpackConversion<int32_t, BluetoothTypeOfDevice>(aOut));
}
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeAudioState& aOut)
{
return UnpackPDU(
aPDU, UnpackConversion<uint8_t, BluetoothHandsfreeAudioState>(aOut));
}
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeCallHoldType& aOut)
{
return UnpackPDU(
aPDU, UnpackConversion<uint8_t, BluetoothHandsfreeCallHoldType>(aOut));
}
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeConnectionState& aOut)
{
return UnpackPDU(
aPDU, UnpackConversion<uint8_t, BluetoothHandsfreeConnectionState>(aOut));
}
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeNRECState& aOut)
{
return UnpackPDU(
aPDU, UnpackConversion<uint8_t, BluetoothHandsfreeNRECState>(aOut));
}
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeVoiceRecognitionState& aOut)
{
return UnpackPDU(
aPDU,
UnpackConversion<uint8_t, BluetoothHandsfreeVoiceRecognitionState>(aOut));
}
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeVolumeType& aOut)
{
return UnpackPDU(
aPDU, UnpackConversion<uint8_t, BluetoothHandsfreeVolumeType>(aOut));
}
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothProperty& aOut)
{
@ -753,4 +1124,64 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothStatus& aOut)
return UnpackPDU(aPDU, UnpackConversion<uint8_t, BluetoothStatus>(aOut));
}
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, nsDependentCString& aOut)
{
// We get a pointer to the first character in the PDU, a length
// of 1 ensures we consume the \0 byte. With 'str' pointing to
// the string in the PDU, we can copy the actual bytes.
const char* str = reinterpret_cast<const char*>(aPDU.Consume(1));
if (NS_WARN_IF(!str)) {
return NS_ERROR_ILLEGAL_VALUE; // end of PDU
}
const char* end = static_cast<char*>(memchr(str, '\0', aPDU.GetSize()));
if (NS_WARN_IF(!end)) {
return NS_ERROR_ILLEGAL_VALUE; // no string terminator
}
ptrdiff_t len = end - str;
const uint8_t* rest = aPDU.Consume(len);
if (NS_WARN_IF(!rest)) {
// We couldn't consume bytes that should have been there.
return NS_ERROR_ILLEGAL_VALUE;
}
aOut.Rebind(str, len);
return NS_OK;
}
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackCString0& aOut)
{
nsDependentCString cstring;
nsresult rv = UnpackPDU(aPDU, cstring);
if (NS_FAILED(rv)) {
return NS_ERROR_ILLEGAL_VALUE;
}
aOut.mString->AssignASCII(cstring.get(), cstring.Length());
return NS_OK;
}
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackString0& aOut)
{
nsDependentCString cstring;
nsresult rv = UnpackPDU(aPDU, cstring);
if (NS_FAILED(rv)) {
return NS_ERROR_ILLEGAL_VALUE;
}
*aOut.mString = NS_ConvertUTF8toUTF16(cstring);
return NS_OK;
}
END_BLUETOOTH_NAMESPACE

View File

@ -83,18 +83,45 @@ Convert(bool aIn, uint8_t& aOut);
nsresult
Convert(bool aIn, BluetoothScanMode& aOut);
nsresult
Convert(int aIn, uint8_t& aOut);
nsresult
Convert(int aIn, int16_t& aOut);
nsresult
Convert(uint8_t aIn, bool& aOut);
nsresult
Convert(uint8_t aIn, char& aOut);
nsresult
Convert(uint8_t aIn, int& aOut);
nsresult
Convert(uint8_t aIn, BluetoothAclState& aOut);
nsresult
Convert(uint8_t aIn, BluetoothBondState& aOut);
nsresult
Convert(uint8_t aIn, BluetoothHandsfreeAudioState& aOut);
nsresult
Convert(uint8_t aIn, BluetoothHandsfreeCallHoldType& aOut);
nsresult
Convert(uint8_t aIn, BluetoothHandsfreeConnectionState& aOut);
nsresult
Convert(uint8_t aIn, BluetoothHandsfreeNRECState& aOut);
nsresult
Convert(uint8_t aIn, BluetoothHandsfreeVoiceRecognitionState& aOut);
nsresult
Convert(uint8_t aIn, BluetoothHandsfreeVolumeType& aOut);
nsresult
Convert(uint8_t aIn, BluetoothTypeOfDevice& aOut);
@ -137,6 +164,33 @@ Convert(BluetoothAclState aIn, bool& aOut);
nsresult
Convert(const BluetoothAddress& aIn, nsAString& aOut);
nsresult
Convert(BluetoothHandsfreeAtResponse aIn, uint8_t& aOut);
nsresult
Convert(BluetoothHandsfreeCallAddressType aIn, uint8_t& aOut);
nsresult
Convert(BluetoothHandsfreeCallDirection aIn, uint8_t& aOut);
nsresult
Convert(BluetoothHandsfreeCallState aIn, uint8_t& aOut);
nsresult
Convert(BluetoothHandsfreeCallMode aIn, uint8_t& aOut);
nsresult
Convert(BluetoothHandsfreeCallMptyType aIn, uint8_t& aOut);
nsresult
Convert(BluetoothHandsfreeNetworkState aIn, uint8_t& aOut);
nsresult
Convert(BluetoothHandsfreeServiceType aIn, uint8_t& aOut);
nsresult
Convert(BluetoothHandsfreeVolumeType aIn, uint8_t& aOut);
nsresult
Convert(BluetoothPropertyType aIn, uint8_t& aOut);
@ -192,6 +246,33 @@ PackPDU(const BluetoothConfigurationParameter& aIn, BluetoothDaemonPDU& aPDU);
nsresult
PackPDU(const BluetoothDaemonPDUHeader& aIn, BluetoothDaemonPDU& aPDU);
nsresult
PackPDU(const BluetoothHandsfreeAtResponse& aIn, BluetoothDaemonPDU& aPDU);
nsresult
PackPDU(const BluetoothHandsfreeCallAddressType& aIn, BluetoothDaemonPDU& aPDU);
nsresult
PackPDU(const BluetoothHandsfreeCallDirection& aIn, BluetoothDaemonPDU& aPDU);
nsresult
PackPDU(const BluetoothHandsfreeCallMode& aIn, BluetoothDaemonPDU& aPDU);
nsresult
PackPDU(const BluetoothHandsfreeCallMptyType& aIn, BluetoothDaemonPDU& aPDU);
nsresult
PackPDU(const BluetoothHandsfreeCallState& aIn, BluetoothDaemonPDU& aPDU);
nsresult
PackPDU(const BluetoothHandsfreeNetworkState& aIn, BluetoothDaemonPDU& aPDU);
nsresult
PackPDU(const BluetoothHandsfreeServiceType& aIn, BluetoothDaemonPDU& aPDU);
nsresult
PackPDU(const BluetoothHandsfreeVolumeType& aIn, BluetoothDaemonPDU& aPDU);
nsresult
PackPDU(const BluetoothNamedValue& aIn, BluetoothDaemonPDU& aPDU);
@ -279,6 +360,29 @@ PackPDU<uint8_t>(const PackArray<uint8_t>& aIn, BluetoothDaemonPDU& aPDU)
return aPDU.Write(aIn.mData, aIn.mLength);
}
/* |PackCString0| is a helper for packing 0-terminated C string,
* including the \0 character. Pass an instance of this structure
* as the first argument to |PackPDU| to pack a string.
*/
struct PackCString0
{
PackCString0(const nsCString& aString)
: mString(aString)
{ }
const nsCString& mString;
};
/* This implementation of |PackPDU| packs a 0-terminated C string.
*/
inline nsresult
PackPDU(const PackCString0& aIn, BluetoothDaemonPDU& aPDU)
{
return PackPDU(
PackArray<uint8_t>(reinterpret_cast<const uint8_t*>(aIn.mString.get()),
aIn.mString.Length() + 1), aPDU);
}
template <typename T1, typename T2>
inline nsresult
PackPDU(const T1& aIn1, const T2& aIn2, BluetoothDaemonPDU& aPDU)
@ -352,6 +456,41 @@ PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3,
return PackPDU(aIn5, aPDU);
}
template <typename T1, typename T2, typename T3,
typename T4, typename T5, typename T6,
typename T7>
inline nsresult
PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3,
const T4& aIn4, const T5& aIn5, const T6& aIn6,
const T7& aIn7, BluetoothDaemonPDU& aPDU)
{
nsresult rv = PackPDU(aIn1, aPDU);
if (NS_FAILED(rv)) {
return rv;
}
rv = PackPDU(aIn2, aPDU);
if (NS_FAILED(rv)) {
return rv;
}
rv = PackPDU(aIn3, aPDU);
if (NS_FAILED(rv)) {
return rv;
}
rv = PackPDU(aIn4, aPDU);
if (NS_FAILED(rv)) {
return rv;
}
rv = PackPDU(aIn5, aPDU);
if (NS_FAILED(rv)) {
return rv;
}
rv = PackPDU(aIn6, aPDU);
if (NS_FAILED(rv)) {
return rv;
}
return PackPDU(aIn7, aPDU);
}
//
// Unpacking
//
@ -389,6 +528,9 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, uint32_t& aOut)
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, bool& aOut);
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, char& aOut);
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothAclState& aOut);
@ -418,6 +560,25 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothDaemonPDUHeader& aOut)
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothTypeOfDevice& aOut);
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeAudioState& aOut);
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeCallHoldType& aOut);
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeConnectionState& aOut);
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeNRECState& aOut);
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU,
BluetoothHandsfreeVoiceRecognitionState& aOut);
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothHandsfreeVolumeType& aOut);
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothRemoteInfo& aOut);
@ -451,6 +612,9 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothUuid& aOut)
return aPDU.Read(aOut.mUuid, sizeof(aOut.mUuid));
}
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, nsDependentCString& aOut);
/* |UnpackConversion| is a helper for convering unpacked values. Pass
* an instance of this structure to |UnpackPDU| to read a value from
* the PDU in the input type and convert it to the output type.
@ -542,6 +706,44 @@ UnpackPDU(BluetoothDaemonPDU& aPDU, nsTArray<T>& aOut)
return NS_OK;
}
/* |UnpackCString0| is a helper for unpacking 0-terminated C string,
* including the \0 character. Pass an instance of this structure
* as the first argument to |UnpackPDU| to unpack a string.
*/
struct UnpackCString0
{
UnpackCString0(nsCString& aString)
: mString(&aString)
{ }
nsCString* mString; // non-null by construction
};
/* This implementation of |UnpackPDU| unpacks a 0-terminated C string.
*/
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackCString0& aOut);
/* |UnpackString0| is a helper for unpacking 0-terminated C string,
* including the \0 character. Pass an instance of this structure
* as the first argument to |UnpackPDU| to unpack a C string and convert
* it to wide-character encoding.
*/
struct UnpackString0
{
UnpackString0(nsString& aString)
: mString(&aString)
{ }
nsString* mString; // non-null by construction
};
/* This implementation of |UnpackPDU| unpacks a 0-terminated C string
* and converts it to wide-character encoding.
*/
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackString0& aOut);
//
// Init operators
//

View File

@ -5,6 +5,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BluetoothDaemonInterface.h"
#include "BluetoothDaemonHandsfreeInterface.h"
#include "BluetoothDaemonHelpers.h"
#include "BluetoothDaemonSetupInterface.h"
#include "BluetoothDaemonSocketInterface.h"
@ -1456,10 +1457,17 @@ class BluetoothDaemonProtocol MOZ_FINAL
, public BluetoothDaemonSetupModule
, public BluetoothDaemonCoreModule
, public BluetoothDaemonSocketModule
, public BluetoothDaemonHandsfreeModule
{
public:
BluetoothDaemonProtocol(BluetoothDaemonConnection* aConnection);
nsresult RegisterModule(uint8_t aId, uint8_t aMode,
BluetoothSetupResultHandler* aRes) MOZ_OVERRIDE;
nsresult UnregisterModule(uint8_t aId,
BluetoothSetupResultHandler* aRes) MOZ_OVERRIDE;
// Outgoing PDUs
//
@ -1481,6 +1489,8 @@ private:
BluetoothDaemonPDU& aPDU, void* aUserData);
void HandleSocketSvc(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU, void* aUserData);
void HandleHandsfreeSvc(const BluetoothDaemonPDUHeader& aHeader,
BluetoothDaemonPDU& aPDU, void* aUserData);
BluetoothDaemonConnection* mConnection;
nsTArray<void*> mUserDataQ;
@ -1493,6 +1503,20 @@ BluetoothDaemonProtocol::BluetoothDaemonProtocol(
MOZ_ASSERT(mConnection);
}
nsresult
BluetoothDaemonProtocol::RegisterModule(uint8_t aId, uint8_t aMode,
BluetoothSetupResultHandler* aRes)
{
return BluetoothDaemonSetupModule::RegisterModuleCmd(aId, aMode, aRes);
}
nsresult
BluetoothDaemonProtocol::UnregisterModule(uint8_t aId,
BluetoothSetupResultHandler* aRes)
{
return BluetoothDaemonSetupModule::UnregisterModuleCmd(aId, aRes);
}
nsresult
BluetoothDaemonProtocol::Send(BluetoothDaemonPDU* aPDU, void* aUserData)
{
@ -1527,6 +1551,14 @@ BluetoothDaemonProtocol::HandleSocketSvc(
BluetoothDaemonSocketModule::HandleSvc(aHeader, aPDU, aUserData);
}
void
BluetoothDaemonProtocol::HandleHandsfreeSvc(
const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU,
void* aUserData)
{
BluetoothDaemonHandsfreeModule::HandleSvc(aHeader, aPDU, aUserData);
}
void
BluetoothDaemonProtocol::Handle(BluetoothDaemonPDU& aPDU)
{
@ -1537,7 +1569,11 @@ BluetoothDaemonProtocol::Handle(BluetoothDaemonPDU& aPDU)
INIT_ARRAY_AT(BluetoothDaemonCoreModule::SERVICE_ID,
&BluetoothDaemonProtocol::HandleCoreSvc),
INIT_ARRAY_AT(BluetoothDaemonSocketModule::SERVICE_ID,
&BluetoothDaemonProtocol::HandleSocketSvc)
&BluetoothDaemonProtocol::HandleSocketSvc),
INIT_ARRAY_AT(0x03, nullptr), // HID host
INIT_ARRAY_AT(0x04, nullptr), // PAN
INIT_ARRAY_AT(BluetoothDaemonHandsfreeModule::SERVICE_ID,
&BluetoothDaemonProtocol::HandleHandsfreeSvc)
};
BluetoothDaemonPDUHeader header;
@ -2110,7 +2146,13 @@ BluetoothDaemonInterface::GetBluetoothSocketInterface()
BluetoothHandsfreeInterface*
BluetoothDaemonInterface::GetBluetoothHandsfreeInterface()
{
return nullptr;
if (mHandsfreeInterface) {
return mHandsfreeInterface;
}
mHandsfreeInterface = new BluetoothDaemonHandsfreeInterface(mProtocol);
return mHandsfreeInterface;
}
BluetoothA2dpInterface*

View File

@ -12,6 +12,7 @@
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothDaemonChannel;
class BluetoothDaemonHandsfreeInterface;
class BluetoothDaemonProtocol;
class BluetoothDaemonSocketInterface;
@ -126,6 +127,7 @@ private:
nsTArray<nsRefPtr<BluetoothResultHandler> > mResultHandlerQ;
nsAutoPtr<BluetoothDaemonSocketInterface> mSocketInterface;
nsAutoPtr<BluetoothDaemonHandsfreeInterface> mHandsfreeInterface;
};
END_BLUETOOTH_NAMESPACE

View File

@ -76,146 +76,12 @@ static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sFetchUuidsRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sBondingRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sUnbondingRunnableArray;
/**
* Classes only used in this file
*/
class SetupAfterEnabledTask MOZ_FINAL : public nsRunnable
{
public:
class SetAdapterPropertyResultHandler MOZ_FINAL
: public BluetoothResultHandler
{
public:
void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
{
BT_LOGR("Fail to set: BT_SCAN_MODE_CONNECTABLE");
}
};
NS_IMETHOD
Run()
{
MOZ_ASSERT(NS_IsMainThread());
// Bluetooth just enabled, clear profile controllers and runnable arrays.
sControllerArray.Clear();
sChangeDiscoveryRunnableArray.Clear();
sSetPropertyRunnableArray.Clear();
sGetDeviceRunnableArray.Clear();
sFetchUuidsRunnableArray.Clear();
sBondingRunnableArray.Clear();
sUnbondingRunnableArray.Clear();
// Bluetooth scan mode is SCAN_MODE_CONNECTABLE by default, i.e., It should
// be connectable and non-discoverable.
NS_ENSURE_TRUE(sBtInterface, NS_ERROR_FAILURE);
sBtInterface->SetAdapterProperty(
BluetoothNamedValue(NS_ConvertUTF8toUTF16("Discoverable"), false),
new SetAdapterPropertyResultHandler());
// Trigger BluetoothOppManager to listen
BluetoothOppManager* opp = BluetoothOppManager::Get();
if (!opp || !opp->Listen()) {
BT_LOGR("Fail to start BluetoothOppManager listening");
}
return NS_OK;
}
};
/* |ProfileDeinitResultHandler| collects the results of all profile
* result handlers and calls |Proceed| after all results handlers
* have been run.
*/
class ProfileDeinitResultHandler MOZ_FINAL
: public BluetoothProfileResultHandler
{
public:
ProfileDeinitResultHandler(unsigned char aNumProfiles)
: mNumProfiles(aNumProfiles)
{
MOZ_ASSERT(mNumProfiles);
}
void Deinit() MOZ_OVERRIDE
{
if (!(--mNumProfiles)) {
Proceed();
}
}
void OnError(nsresult aResult) MOZ_OVERRIDE
{
if (!(--mNumProfiles)) {
Proceed();
}
}
private:
void Proceed() const
{
sBtInterface->Cleanup(nullptr);
}
unsigned char mNumProfiles;
};
class CleanupTask MOZ_FINAL : public nsRunnable
{
public:
NS_IMETHOD
Run()
{
static void (* const sDeinitManager[])(BluetoothProfileResultHandler*) = {
BluetoothHfpManager::DeinitHfpInterface,
BluetoothA2dpManager::DeinitA2dpInterface,
BluetoothGattManager::DeinitGattInterface
};
MOZ_ASSERT(NS_IsMainThread());
// Return error if BluetoothService is unavailable
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
// Cleanup static adapter properties and notify adapter.
sAdapterBdAddress.Truncate();
sAdapterBdName.Truncate();
InfallibleTArray<BluetoothNamedValue> props;
BT_APPEND_NAMED_VALUE(props, "Name", sAdapterBdName);
BT_APPEND_NAMED_VALUE(props, "Address", sAdapterBdAddress);
if (sAdapterDiscoverable) {
sAdapterDiscoverable = false;
BT_APPEND_NAMED_VALUE(props, "Discoverable", false);
}
if (sAdapterDiscovering) {
sAdapterDiscovering = false;
BT_APPEND_NAMED_VALUE(props, "Discovering", false);
}
BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
NS_LITERAL_STRING(KEY_ADAPTER), props);
bs->DistributeSignal(signal);
// Cleanup bluetooth interfaces after BT state becomes BT_STATE_OFF.
nsRefPtr<ProfileDeinitResultHandler> res =
new ProfileDeinitResultHandler(MOZ_ARRAY_LENGTH(sDeinitManager));
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(sDeinitManager); ++i) {
sDeinitManager[i](res);
}
return NS_OK;
}
};
/**
* Static callback functions
*/
static ControlPlayStatus
PlayStatusStringToControlPlayStatus(const nsAString& aPlayStatus)
ControlPlayStatus
BluetoothServiceBluedroid::PlayStatusStringToControlPlayStatus(
const nsAString& aPlayStatus)
{
ControlPlayStatus playStatus = ControlPlayStatus::PLAYSTATUS_UNKNOWN;
if (aPlayStatus.EqualsLiteral("STOPPED")) {
@ -238,8 +104,8 @@ PlayStatusStringToControlPlayStatus(const nsAString& aPlayStatus)
/**
* Static functions
*/
static bool
EnsureBluetoothHalLoad()
bool
BluetoothServiceBluedroid::EnsureBluetoothHalLoad()
{
sBtInterface = BluetoothInterface::GetInstance();
NS_ENSURE_TRUE(sBtInterface, false);
@ -247,7 +113,8 @@ EnsureBluetoothHalLoad()
return true;
}
class EnableResultHandler MOZ_FINAL : public BluetoothResultHandler
class BluetoothServiceBluedroid::EnableResultHandler MOZ_FINAL
: public BluetoothResultHandler
{
public:
void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
@ -256,10 +123,7 @@ public:
BT_LOGR("BluetoothInterface::Enable failed: %d", aStatus);
nsRefPtr<nsRunnable> runnable = new BluetoothService::ToggleBtAck(false);
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
BT_WARNING("Failed to dispatch to main thread!");
}
BluetoothService::AcknowledgeToggleBt(false);
}
};
@ -267,12 +131,12 @@ public:
* result handlers and calls |Proceed| after all results handlers
* have been run.
*/
class ProfileInitResultHandler MOZ_FINAL
: public BluetoothProfileResultHandler
class BluetoothServiceBluedroid::ProfileInitResultHandler MOZ_FINAL
: public BluetoothProfileResultHandler
{
public:
ProfileInitResultHandler(unsigned char aNumProfiles)
: mNumProfiles(aNumProfiles)
: mNumProfiles(aNumProfiles)
{
MOZ_ASSERT(mNumProfiles);
}
@ -300,7 +164,8 @@ private:
unsigned char mNumProfiles;
};
class InitResultHandler MOZ_FINAL : public BluetoothResultHandler
class BluetoothServiceBluedroid::InitResultHandler MOZ_FINAL
: public BluetoothResultHandler
{
public:
void Init() MOZ_OVERRIDE
@ -332,15 +197,12 @@ public:
sBtInterface = nullptr;
nsRefPtr<nsRunnable> runnable = new BluetoothService::ToggleBtAck(false);
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
BT_WARNING("Failed to dispatch to main thread!");
}
BluetoothService::AcknowledgeToggleBt(false);
}
};
static nsresult
StartGonkBluetooth()
nsresult
BluetoothServiceBluedroid::StartGonkBluetooth()
{
MOZ_ASSERT(NS_IsMainThread());
@ -351,10 +213,7 @@ StartGonkBluetooth()
if (bs->IsEnabled()) {
// Keep current enable status
nsRefPtr<nsRunnable> runnable = new BluetoothService::ToggleBtAck(true);
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
BT_WARNING("Failed to dispatch to main thread!");
}
BluetoothService::AcknowledgeToggleBt(true);
return NS_OK;
}
@ -364,7 +223,8 @@ StartGonkBluetooth()
return NS_OK;
}
class DisableResultHandler MOZ_FINAL : public BluetoothResultHandler
class BluetoothServiceBluedroid::DisableResultHandler MOZ_FINAL
: public BluetoothResultHandler
{
public:
void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
@ -373,15 +233,12 @@ public:
BT_LOGR("BluetoothInterface::Disable failed: %d", aStatus);
nsRefPtr<nsRunnable> runnable = new BluetoothService::ToggleBtAck(true);
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
BT_WARNING("Failed to dispatch to main thread!");
}
BluetoothService::AcknowledgeToggleBt(true);
}
};
static nsresult
StopGonkBluetooth()
nsresult
BluetoothServiceBluedroid::StopGonkBluetooth()
{
MOZ_ASSERT(NS_IsMainThread());
@ -392,10 +249,7 @@ StopGonkBluetooth()
if (!bs->IsEnabled()) {
// Keep current enable status
nsRefPtr<nsRunnable> runnable = new BluetoothService::ToggleBtAck(false);
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
BT_WARNING("Failed to dispatch to main thread!");
}
BluetoothService::AcknowledgeToggleBt(false);
return NS_OK;
}
@ -404,9 +258,10 @@ StopGonkBluetooth()
return NS_OK;
}
static void
ReplyStatusError(BluetoothReplyRunnable* aBluetoothReplyRunnable,
BluetoothStatus aStatusCode, const nsAString& aCustomMsg)
void
BluetoothServiceBluedroid::ReplyStatusError(
BluetoothReplyRunnable* aBluetoothReplyRunnable,
BluetoothStatus aStatusCode, const nsAString& aCustomMsg)
{
MOZ_ASSERT(aBluetoothReplyRunnable, "Reply runnable is nullptr");
@ -460,12 +315,7 @@ BluetoothServiceBluedroid::StartInternal(BluetoothReplyRunnable* aRunnable)
nsresult ret = StartGonkBluetooth();
if (NS_FAILED(ret)) {
nsRefPtr<nsRunnable> runnable =
new BluetoothService::ToggleBtAck(false);
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
BT_WARNING("Failed to dispatch to main thread!");
}
BluetoothService::AcknowledgeToggleBt(false);
// Reject Promise
if(aRunnable) {
@ -492,12 +342,7 @@ BluetoothServiceBluedroid::StopInternal(BluetoothReplyRunnable* aRunnable)
nsresult ret = StopGonkBluetooth();
if (NS_FAILED(ret)) {
nsRefPtr<nsRunnable> runnable =
new BluetoothService::ToggleBtAck(true);
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
BT_WARNING("Failed to dispatch to main thread!");
}
BluetoothService::AcknowledgeToggleBt(true);
// Reject Promise
if(aRunnable) {
@ -554,8 +399,9 @@ BluetoothServiceBluedroid::GetAdaptersInternal(
return NS_OK;
}
class GetRemoteDevicePropertiesResultHandler MOZ_FINAL
: public BluetoothResultHandler
class BluetoothServiceBluedroid::GetRemoteDevicePropertiesResultHandler
MOZ_FINAL
: public BluetoothResultHandler
{
public:
GetRemoteDevicePropertiesResultHandler(const nsAString& aDeviceAddress)
@ -653,7 +499,8 @@ BluetoothServiceBluedroid::GetPairedDevicePropertiesInternal(
return NS_OK;
}
class StartDiscoveryResultHandler MOZ_FINAL : public BluetoothResultHandler
class BluetoothServiceBluedroid::StartDiscoveryResultHandler MOZ_FINAL
: public BluetoothResultHandler
{
public:
StartDiscoveryResultHandler(BluetoothReplyRunnable* aRunnable)
@ -685,7 +532,8 @@ BluetoothServiceBluedroid::StartDiscoveryInternal(
return NS_OK;
}
class CancelDiscoveryResultHandler MOZ_FINAL : public BluetoothResultHandler
class BluetoothServiceBluedroid::CancelDiscoveryResultHandler MOZ_FINAL
: public BluetoothResultHandler
{
public:
CancelDiscoveryResultHandler(BluetoothReplyRunnable* aRunnable)
@ -717,7 +565,8 @@ BluetoothServiceBluedroid::StopDiscoveryInternal(
return NS_OK;
}
class GetRemoteServicesResultHandler MOZ_FINAL : public BluetoothResultHandler
class BluetoothServiceBluedroid::GetRemoteServicesResultHandler MOZ_FINAL
: public BluetoothResultHandler
{
public:
GetRemoteServicesResultHandler(BluetoothReplyRunnable* aRunnable)
@ -759,7 +608,8 @@ BluetoothServiceBluedroid::FetchUuidsInternal(
return NS_OK;
}
class SetAdapterPropertyResultHandler MOZ_FINAL : public BluetoothResultHandler
class BluetoothServiceBluedroid::SetAdapterPropertyResultHandler MOZ_FINAL
: public BluetoothResultHandler
{
public:
SetAdapterPropertyResultHandler(BluetoothReplyRunnable* aRunnable)
@ -810,7 +660,8 @@ BluetoothServiceBluedroid::UpdateSdpRecords(
return true;
}
class CreateBondResultHandler MOZ_FINAL : public BluetoothResultHandler
class BluetoothServiceBluedroid::CreateBondResultHandler MOZ_FINAL
: public BluetoothResultHandler
{
public:
CreateBondResultHandler(BluetoothReplyRunnable* aRunnable)
@ -845,7 +696,8 @@ BluetoothServiceBluedroid::CreatePairedDeviceInternal(
return NS_OK;
}
class RemoveBondResultHandler MOZ_FINAL : public BluetoothResultHandler
class BluetoothServiceBluedroid::RemoveBondResultHandler MOZ_FINAL
: public BluetoothResultHandler
{
public:
RemoveBondResultHandler(BluetoothReplyRunnable* aRunnable)
@ -880,7 +732,8 @@ BluetoothServiceBluedroid::RemoveDeviceInternal(
return NS_OK;
}
class PinReplyResultHandler MOZ_FINAL : public BluetoothResultHandler
class BluetoothServiceBluedroid::PinReplyResultHandler MOZ_FINAL
: public BluetoothResultHandler
{
public:
PinReplyResultHandler(BluetoothReplyRunnable* aRunnable)
@ -922,7 +775,8 @@ BluetoothServiceBluedroid::SetPasskeyInternal(
return;
}
class SspReplyResultHandler MOZ_FINAL : public BluetoothResultHandler
class BluetoothServiceBluedroid::SspReplyResultHandler MOZ_FINAL
: public BluetoothResultHandler
{
public:
SspReplyResultHandler(BluetoothReplyRunnable* aRunnable)
@ -958,8 +812,8 @@ BluetoothServiceBluedroid::SetPairingConfirmationInternal(
aConfirm, 0, new SspReplyResultHandler(aRunnable));
}
static void
NextBluetoothProfileController()
void
BluetoothServiceBluedroid::NextBluetoothProfileController()
{
MOZ_ASSERT(NS_IsMainThread());
@ -973,10 +827,11 @@ NextBluetoothProfileController()
}
}
static void
ConnectDisconnect(bool aConnect, const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable,
uint16_t aServiceUuid, uint32_t aCod = 0)
void
BluetoothServiceBluedroid::ConnectDisconnect(
bool aConnect, const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable,
uint16_t aServiceUuid, uint32_t aCod)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aRunnable);
@ -1220,6 +1075,54 @@ BluetoothServiceBluedroid::ToggleCalls(BluetoothReplyRunnable* aRunnable)
// Bluetooth notifications
//
/* |ProfileDeinitResultHandler| collects the results of all profile
* result handlers and calls |Proceed| after all results handlers
* have been run.
*/
class BluetoothServiceBluedroid::ProfileDeinitResultHandler MOZ_FINAL
: public BluetoothProfileResultHandler
{
public:
ProfileDeinitResultHandler(unsigned char aNumProfiles)
: mNumProfiles(aNumProfiles)
{
MOZ_ASSERT(mNumProfiles);
}
void Deinit() MOZ_OVERRIDE
{
if (!(--mNumProfiles)) {
Proceed();
}
}
void OnError(nsresult aResult) MOZ_OVERRIDE
{
if (!(--mNumProfiles)) {
Proceed();
}
}
private:
void Proceed() const
{
sBtInterface->Cleanup(nullptr);
}
unsigned char mNumProfiles;
};
class BluetoothServiceBluedroid::SetAdapterPropertyDiscoverableResultHandler
MOZ_FINAL
: public BluetoothResultHandler
{
public:
void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
{
BT_LOGR("Fail to set: BT_SCAN_MODE_CONNECTABLE");
}
};
void
BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState)
{
@ -1229,23 +1132,70 @@ BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState)
sAdapterEnabled = aState;
if (!sAdapterEnabled &&
NS_FAILED(NS_DispatchToMainThread(new CleanupTask()))) {
BT_WARNING("Failed to dispatch to main thread!");
return;
if (!sAdapterEnabled) {
static void (* const sDeinitManager[])(BluetoothProfileResultHandler*) = {
BluetoothHfpManager::DeinitHfpInterface,
BluetoothA2dpManager::DeinitA2dpInterface,
BluetoothGattManager::DeinitGattInterface
};
// Return error if BluetoothService is unavailable
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE_VOID(bs);
// Cleanup static adapter properties and notify adapter.
sAdapterBdAddress.Truncate();
sAdapterBdName.Truncate();
InfallibleTArray<BluetoothNamedValue> props;
BT_APPEND_NAMED_VALUE(props, "Name", sAdapterBdName);
BT_APPEND_NAMED_VALUE(props, "Address", sAdapterBdAddress);
if (sAdapterDiscoverable) {
sAdapterDiscoverable = false;
BT_APPEND_NAMED_VALUE(props, "Discoverable", false);
}
if (sAdapterDiscovering) {
sAdapterDiscovering = false;
BT_APPEND_NAMED_VALUE(props, "Discovering", false);
}
BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
NS_LITERAL_STRING(KEY_ADAPTER), props);
bs->DistributeSignal(signal);
// Cleanup bluetooth interfaces after BT state becomes BT_STATE_OFF.
nsRefPtr<ProfileDeinitResultHandler> res =
new ProfileDeinitResultHandler(MOZ_ARRAY_LENGTH(sDeinitManager));
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(sDeinitManager); ++i) {
sDeinitManager[i](res);
}
}
nsRefPtr<nsRunnable> runnable =
new BluetoothService::ToggleBtAck(sAdapterEnabled);
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
BT_WARNING("Failed to dispatch to main thread!");
return;
}
BluetoothService::AcknowledgeToggleBt(sAdapterEnabled);
if (sAdapterEnabled &&
NS_FAILED(NS_DispatchToMainThread(new SetupAfterEnabledTask()))) {
BT_WARNING("Failed to dispatch to main thread!");
return;
if (sAdapterEnabled) {
// Bluetooth just enabled, clear profile controllers and runnable arrays.
sControllerArray.Clear();
sChangeDiscoveryRunnableArray.Clear();
sSetPropertyRunnableArray.Clear();
sGetDeviceRunnableArray.Clear();
sFetchUuidsRunnableArray.Clear();
sBondingRunnableArray.Clear();
sUnbondingRunnableArray.Clear();
// Bluetooth scan mode is SCAN_MODE_CONNECTABLE by default, i.e., It should
// be connectable and non-discoverable.
NS_ENSURE_TRUE_VOID(sBtInterface);
sBtInterface->SetAdapterProperty(
BluetoothNamedValue(NS_ConvertUTF8toUTF16("Discoverable"), false),
new SetAdapterPropertyDiscoverableResultHandler());
// Trigger BluetoothOppManager to listen
BluetoothOppManager* opp = BluetoothOppManager::Get();
if (!opp || !opp->Listen()) {
BT_LOGR("Fail to start BluetoothOppManager listening");
}
}
// Resolve promise if existed

View File

@ -16,6 +16,22 @@ BEGIN_BLUETOOTH_NAMESPACE
class BluetoothServiceBluedroid : public BluetoothService
, public BluetoothNotificationHandler
{
class CancelDiscoveryResultHandler;
class CreateBondResultHandler;
class DisableResultHandler;
class EnableResultHandler;
class GetRemoteDevicePropertiesResultHandler;
class GetRemoteServicesResultHandler;
class InitResultHandler;
class PinReplyResultHandler;
class ProfileDeinitResultHandler;
class ProfileInitResultHandler;
class RemoveBondResultHandler;
class SetAdapterPropertyDiscoverableResultHandler;
class SetAdapterPropertyResultHandler;
class SspReplyResultHandler;
class StartDiscoveryResultHandler;
public:
BluetoothServiceBluedroid();
~BluetoothServiceBluedroid();
@ -193,6 +209,22 @@ public:
uint8_t aLen) MOZ_OVERRIDE;
virtual void LeTestModeNotification(BluetoothStatus aStatus,
uint16_t aNumPackets) MOZ_OVERRIDE;
protected:
static nsresult StartGonkBluetooth();
static nsresult StopGonkBluetooth();
static bool EnsureBluetoothHalLoad();
static void ConnectDisconnect(bool aConnect,
const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable,
uint16_t aServiceUuid, uint32_t aCod = 0);
static void NextBluetoothProfileController();
static ControlPlayStatus PlayStatusStringToControlPlayStatus(
const nsAString& aPlayStatus);
static void ReplyStatusError(BluetoothReplyRunnable* aReplyRunnable,
BluetoothStatus aStatusCode,
const nsAString& aCustomMsg);
};
END_BLUETOOTH_NAMESPACE

View File

@ -51,6 +51,7 @@ if CONFIG['MOZ_B2G_BT']:
'bluedroid/BluetoothA2dpHALInterface.cpp',
'bluedroid/BluetoothA2dpManager.cpp',
'bluedroid/BluetoothAvrcpHALInterface.cpp',
'bluedroid/BluetoothDaemonHandsfreeInterface.cpp',
'bluedroid/BluetoothDaemonHelpers.cpp',
'bluedroid/BluetoothDaemonInterface.cpp',
'bluedroid/BluetoothDaemonSetupInterface.cpp',

View File

@ -94,6 +94,7 @@ function BrowserElementChild() {
this._isContentWindowCreated = false;
this._pendingSetInputMethodActive = [];
this._forceDispatchSelectionStateChanged = false;
this._init();
};
@ -161,8 +162,8 @@ BrowserElementChild.prototype = {
/* useCapture = */ true,
/* wantsUntrusted = */ false);
addEventListener('mozselectionchange',
this._selectionChangeHandler.bind(this),
addEventListener('mozselectionstatechanged',
this._selectionStateChangedHandler.bind(this),
/* useCapture = */ false,
/* wantsUntrusted = */ false);
@ -591,23 +592,61 @@ BrowserElementChild.prototype = {
sendAsyncMsg('scrollviewchange', detail);
},
_selectionChangeHandler: function(e) {
_selectionStateChangedHandler: function(e) {
e.stopPropagation();
let boundingClientRect = e.boundingClientRect;
if (!boundingClientRect) {
return;
let isCollapsed = (e.selectedText.length == 0);
let isMouseUp = (e.states.indexOf('mouseup') == 0);
let canPaste = this._isCommandEnabled("paste");
if (!this._forceDispatchSelectionStateChanged) {
// SelectionStateChanged events with the following states are not
// necessary to trigger the text dialog, bypass these events
// by default.
//
if(e.states.length == 0 ||
e.states.indexOf('drag') == 0 ||
e.states.indexOf('keypress') == 0 ||
e.states.indexOf('mousedown') == 0) {
return;
}
// The collapsed SelectionStateChanged event is unnecessary to dispatch,
// bypass this event by default. But there is one exception to support
// the shortcut mode which can paste previous copied content easily
if (isCollapsed) {
if (isMouseUp && canPaste) {
//Dispatch this selection change event to support shortcut mode
} else {
return;
}
}
}
// For every touch on the screen, there are always two mouse events received,
// mousedown/mouseup, no matter touch or long tap on the screen. When there is
// is a non-collapsed selection change event which comes with mouseup reason,
// it implies some texts are selected. In order to hide the text dialog during next
// touch, here sets the forceDispatchSelectionStateChanged flag as true to dispatch the
// next SelecitonChange event(with the mousedown) so that the parent side can
// hide the text dialog.
if (isMouseUp && !isCollapsed) {
this._forceDispatchSelectionStateChanged = true;
} else {
this._forceDispatchSelectionStateChanged = false;
}
let zoomFactor = content.screen.width / content.innerWidth;
let detail = {
rect: {
width: boundingClientRect.width,
height: boundingClientRect.height,
top: boundingClientRect.top,
bottom: boundingClientRect.bottom,
left: boundingClientRect.left,
right: boundingClientRect.right,
width: boundingClientRect ? boundingClientRect.width : 0,
height: boundingClientRect ? boundingClientRect.height : 0,
top: boundingClientRect ? boundingClientRect.top : 0,
bottom: boundingClientRect ? boundingClientRect.bottom : 0,
left: boundingClientRect ? boundingClientRect.left : 0,
right: boundingClientRect ? boundingClientRect.right : 0,
},
commands: {
canSelectAll: this._isCommandEnabled("selectall"),
@ -616,7 +655,7 @@ BrowserElementChild.prototype = {
canPaste: this._isCommandEnabled("paste"),
},
zoomFactor: zoomFactor,
reasons: e.reasons,
states: e.states,
isCollapsed: (e.selectedText.length == 0),
};
@ -631,7 +670,7 @@ BrowserElementChild.prototype = {
currentWindow = currentWindow.parent;
}
sendAsyncMsg('selectionchange', detail);
sendAsyncMsg('selectionstatechanged', detail);
},
_themeColorChangedHandler: function(eventType, target) {

View File

@ -197,7 +197,7 @@ BrowserElementParent.prototype = {
"got-visible": this._gotDOMRequestResult,
"visibilitychange": this._childVisibilityChange,
"got-set-input-method-active": this._gotDOMRequestResult,
"selectionchange": this._handleSelectionChange,
"selectionstatechanged": this._handleSelectionStateChanged,
"scrollviewchange": this._handleScrollViewChange,
"touchcarettap": this._handleTouchCaretTap
};
@ -435,8 +435,8 @@ BrowserElementParent.prototype = {
}
},
_handleSelectionChange: function(data) {
let evt = this._createEvent('selectionchange', data.json,
_handleSelectionStateChanged: function(data) {
let evt = this._createEvent('selectionstatechanged', data.json,
/* cancelable = */ false);
this._frameElement.dispatchEvent(evt);
},

View File

@ -1,7 +1,7 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that "cut, copy, paste, selectall" and selectionchange event works from inside an <iframe mozbrowser>.
// Test that "cut, copy, paste, selectall" and selectionstatechanged event works from inside an <iframe mozbrowser>.
"use strict";
SimpleTest.waitForExplicitFinish();
@ -142,9 +142,9 @@ function dispatchTest(e) {
}
function testSelectAll(e) {
iframe.addEventListener("mozbrowserselectionchange", function selectchangeforselectall(e) {
iframe.removeEventListener("mozbrowserselectionchange", selectchangeforselectall, true);
ok(true, "got mozbrowserselectionchange event." + stateMeaning);
iframe.addEventListener("mozbrowserselectionstatechanged", function selectchangeforselectall(e) {
iframe.removeEventListener("mozbrowserselectionstatechanged", selectchangeforselectall, true);
ok(true, "got mozbrowserselectionstatechanged event." + stateMeaning);
ok(e.detail, "event.detail is not null." + stateMeaning);
ok(e.detail.width != 0, "event.detail.width is not zero" + stateMeaning);
ok(e.detail.height != 0, "event.detail.height is not zero" + stateMeaning);
@ -153,7 +153,7 @@ function testSelectAll(e) {
mm.addMessageListener('content-focus', function messageforfocus(msg) {
mm.removeMessageListener('content-focus', messageforfocus);
// test selectall command, after calling this the selectionchange event should be fired.
// test selectall command, after calling this the selectionstatechanged event should be fired.
doCommand('selectall');
});

View File

@ -223,25 +223,6 @@ WebGLFramebuffer::Attachment::RectangleObject() const
// The following IsValidFBOTextureXXX functions check the internal format that
// is used by GL or GL ES texture formats. This corresponds to the state that
// is stored in WebGLTexture::ImageInfo::InternalFormat()
static inline bool
IsValidFBOTextureColorFormat(TexInternalFormat internalformat)
{
/* These formats are internal formats for each texture -- the actual low
* level format, which we might have to do conversions for when running
* against desktop GL (e.g. GL_RGBA + GL_FLOAT -> GL_RGBA32F).
*
* This function just handles all of them whether desktop GL or ES.
*/
TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);
return unsizedformat == LOCAL_GL_ALPHA ||
unsizedformat == LOCAL_GL_LUMINANCE ||
unsizedformat == LOCAL_GL_LUMINANCE_ALPHA ||
unsizedformat == LOCAL_GL_RGB ||
unsizedformat == LOCAL_GL_RGBA ||
unsizedformat == LOCAL_GL_SRGB ||
unsizedformat == LOCAL_GL_SRGB_ALPHA;
}
static inline bool
IsValidFBOTextureDepthFormat(GLenum internalformat)
@ -258,14 +239,6 @@ IsValidFBOTextureDepthStencilFormat(GLenum internalformat)
// The following IsValidFBORenderbufferXXX functions check the internal format
// that is stored by WebGLRenderbuffer::InternalFormat(). Valid values can be
// found in WebGLContext::RenderbufferStorage.
static inline bool
IsValidFBORenderbufferColorFormat(GLenum internalFormat)
{
return internalFormat == LOCAL_GL_RGB565 ||
internalFormat == LOCAL_GL_RGB5_A1 ||
internalFormat == LOCAL_GL_RGBA4 ||
internalFormat == LOCAL_GL_SRGB8_ALPHA8_EXT;
}
static inline bool
IsValidFBORenderbufferDepthFormat(GLenum internalFormat)
@ -702,7 +675,6 @@ WebGLFramebuffer::HasDefinedAttachments() const
return hasAttachments;
}
static bool
IsIncomplete(const WebGLFramebuffer::Attachment& cur)
{
@ -782,7 +754,6 @@ WebGLFramebuffer::AllImageRectsMatch() const
return imageRectsMatch;
}
const WebGLRectangleObject&
WebGLFramebuffer::RectangleObject() const
{

View File

@ -2903,6 +2903,14 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
mDecoder->SetFragmentEndTime(mFragmentEnd);
}
// Tracks just got known, pass the info along to the output streams
uint8_t hints = (mHasAudio ? DOMMediaStream::HINT_CONTENTS_AUDIO : 0) |
(mHasVideo ? DOMMediaStream::HINT_CONTENTS_VIDEO : 0);
for (uint32_t i = 0; i < mOutputStreams.Length(); ++i) {
OutputMediaStream* out = &mOutputStreams[i];
out->mStream->SetHintContents(hints);
}
// If this element had a video track, but consists only of an audio track now,
// delete the VideoFrameContainer. This happens when the src is changed to an
// audio only file.

View File

@ -793,8 +793,6 @@ nsTextInputListener::NotifySelectionChanged(nsIDOMDocument* aDoc, nsISelection*
}
}
UpdateTextInputCommands(NS_LITERAL_STRING("selectionchange"), aSel, aReason);
// if the collapsed state did not change, don't fire notifications
if (collapsed == mSelectionWasCollapsed)
return NS_OK;

View File

@ -5130,7 +5130,7 @@ public:
virtual void
OnOriginClearCompleted(PersistenceType aPersistenceType,
const OriginOrPatternString& aOriginOrPattern)
const nsACString& aOrigin)
MOZ_OVERRIDE;
virtual void
@ -5941,7 +5941,8 @@ Factory::AllocPBackgroundIDBFactoryRequestParent(
const DatabaseMetadata& metadata = commonParams->metadata();
if (NS_WARN_IF(metadata.persistenceType() != PERSISTENCE_TYPE_PERSISTENT &&
metadata.persistenceType() != PERSISTENCE_TYPE_TEMPORARY)) {
metadata.persistenceType() != PERSISTENCE_TYPE_TEMPORARY &&
metadata.persistenceType() != PERSISTENCE_TYPE_DEFAULT)) {
ASSERT_UNLESS_FUZZING();
return nullptr;
}
@ -9429,14 +9430,13 @@ QuotaClient::GetUsageForOrigin(PersistenceType aPersistenceType,
}
void
QuotaClient::OnOriginClearCompleted(
PersistenceType aPersistenceType,
const OriginOrPatternString& aOriginOrPattern)
QuotaClient::OnOriginClearCompleted(PersistenceType aPersistenceType,
const nsACString& aOrigin)
{
AssertIsOnIOThread();
if (IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get()) {
mgr->InvalidateFileManagers(aPersistenceType, aOriginOrPattern);
mgr->InvalidateFileManagers(aPersistenceType, aOrigin);
}
}
@ -10753,6 +10753,9 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
QuotaManager::GetInfoForChrome(&mGroup, &mOrigin, &mIsApp,
&mHasUnlimStoragePerm);
MOZ_ASSERT(!QuotaManager::IsFirstPromptRequired(persistenceType, mOrigin,
mIsApp));
mEnforcingQuota =
QuotaManager::IsQuotaEnforced(persistenceType, mOrigin, mIsApp,
mHasUnlimStoragePerm);
@ -10771,14 +10774,19 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
return rv;
}
nsCString group;
nsCString origin;
bool isApp;
bool hasUnlimStoragePerm;
rv = QuotaManager::GetInfoFromPrincipal(principal, &group, &origin,
&isApp, &hasUnlimStoragePerm);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
PermissionRequestBase::PermissionValue permission;
if (persistenceType == PERSISTENCE_TYPE_TEMPORARY) {
// Temporary storage doesn't need to check the permission.
permission = PermissionRequestBase::kPermissionAllowed;
} else {
MOZ_ASSERT(persistenceType == PERSISTENCE_TYPE_PERSISTENT);
if (QuotaManager::IsFirstPromptRequired(persistenceType, origin, isApp)) {
#ifdef MOZ_CHILD_PERMISSIONS
if (aContentParent) {
if (NS_WARN_IF(!AssertAppPrincipal(aContentParent, principal))) {
@ -10799,16 +10807,16 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
return rv;
}
}
} else {
permission = PermissionRequestBase::kPermissionAllowed;
}
if (permission != PermissionRequestBase::kPermissionDenied &&
State_Initial == mState) {
rv = QuotaManager::GetInfoFromPrincipal(principal, persistenceType, &mGroup,
&mOrigin, &mIsApp,
&mHasUnlimStoragePerm);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mGroup = group;
mOrigin = origin;
mIsApp = isApp;
mHasUnlimStoragePerm = hasUnlimStoragePerm;
mEnforcingQuota =
QuotaManager::IsQuotaEnforced(persistenceType, mOrigin, mIsApp,
@ -10971,22 +10979,14 @@ FactoryOp::FinishOpen()
MOZ_ASSERT(!mContentParent);
MOZ_ASSERT(!QuotaClient::IsShuttingDownOnMainThread());
PersistenceType persistenceType = mCommonParams.metadata().persistenceType();
// XXX This is temporary, but we don't currently support the explicit
// 'persistent' storage type.
if (persistenceType == PERSISTENCE_TYPE_PERSISTENT &&
mCommonParams.metadata().persistenceTypeIsExplicit()) {
IDB_REPORT_INTERNAL_ERR();
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
QuotaManager* quotaManager = QuotaManager::GetOrCreate();
if (NS_WARN_IF(!quotaManager)) {
IDB_REPORT_INTERNAL_ERR();
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
PersistenceType persistenceType = mCommonParams.metadata().persistenceType();
nsresult rv =
quotaManager->
WaitForOpenAllowed(OriginOrPatternString::FromOrigin(mOrigin),

View File

@ -998,10 +998,8 @@ IDBDatabase::GetQuotaInfo(nsACString& aOrigin,
MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
MOZ_ASSERT(NS_IsMainThread());
PersistenceType persistenceType = mSpec->metadata().persistenceType();
if (aPersistenceType) {
*aPersistenceType = persistenceType;
*aPersistenceType = mSpec->metadata().persistenceType();
MOZ_ASSERT(*aPersistenceType != PERSISTENCE_TYPE_INVALID);
}
@ -1025,7 +1023,6 @@ IDBDatabase::GetQuotaInfo(nsACString& aOrigin,
}
rv = QuotaManager::GetInfoFromPrincipal(principal,
persistenceType,
nullptr,
&aOrigin,
nullptr,

View File

@ -479,24 +479,18 @@ IDBFactory::OpenInternal(nsIPrincipal* aPrincipal,
return nullptr;
}
// XXX We need a bug to switch to temporary storage by default.
PersistenceType persistenceType;
bool persistenceTypeIsExplicit;
if (principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo) {
// Chrome privilege always gets persistent storage.
persistenceType = PERSISTENCE_TYPE_PERSISTENT;
persistenceTypeIsExplicit = false;
} else {
persistenceType = PersistenceTypeFromStorage(aStorageType);
persistenceTypeIsExplicit = aStorageType.WasPassed();
}
DatabaseMetadata& metadata = commonParams.metadata();
metadata.name() = aName;
metadata.persistenceType() = persistenceType;
metadata.persistenceTypeIsExplicit() = persistenceTypeIsExplicit;
FactoryRequestParams params;
if (aDeleting) {

View File

@ -157,15 +157,9 @@ IDBMutableFile::Create(IDBDatabase* aDatabase,
return nullptr;
}
const DatabaseSpec* spec = aDatabase->Spec();
MOZ_ASSERT(spec);
PersistenceType persistenceType = spec->metadata().persistenceType();
nsCString group;
nsCString origin;
if (NS_WARN_IF(NS_FAILED(QuotaManager::GetInfoFromPrincipal(principal,
persistenceType,
&group,
&origin,
nullptr,
@ -173,6 +167,11 @@ IDBMutableFile::Create(IDBDatabase* aDatabase,
return nullptr;
}
const DatabaseSpec* spec = aDatabase->Spec();
MOZ_ASSERT(spec);
PersistenceType persistenceType = spec->metadata().persistenceType();
nsCString storageId;
QuotaManager::GetStorageId(persistenceType,
origin,

View File

@ -80,7 +80,8 @@ public:
AssertIsOnIOThread();
return !mPersistentStorageFileManagers.IsEmpty() ||
!mTemporaryStorageFileManagers.IsEmpty();
!mTemporaryStorageFileManagers.IsEmpty() ||
!mDefaultStorageFileManagers.IsEmpty();
}
void
@ -105,6 +106,7 @@ private:
nsTArray<nsRefPtr<FileManager> > mPersistentStorageFileManagers;
nsTArray<nsRefPtr<FileManager> > mTemporaryStorageFileManagers;
nsTArray<nsRefPtr<FileManager> > mDefaultStorageFileManagers;
};
namespace {
@ -178,16 +180,6 @@ private:
bool mWaiting;
};
struct MOZ_STACK_CLASS InvalidateInfo
{
InvalidateInfo(PersistenceType aPersistenceType, const nsACString& aPattern)
: persistenceType(aPersistenceType), pattern(aPattern)
{ }
PersistenceType persistenceType;
const nsACString& pattern;
};
void
TestingPrefChangedCallback(const char* aPrefName, void* aClosure)
{
@ -554,66 +546,49 @@ IndexedDatabaseManager::AddFileManager(FileManager* aFileManager)
info->AddFileManager(aFileManager);
}
// static
PLDHashOperator
IndexedDatabaseManager::InvalidateAndRemoveFileManagers(
const nsACString& aKey,
nsAutoPtr<FileManagerInfo>& aValue,
void* aUserArg)
{
AssertIsOnIOThread();
NS_ASSERTION(!aKey.IsEmpty(), "Empty key!");
NS_ASSERTION(aValue, "Null pointer!");
if (!aUserArg) {
aValue->InvalidateAllFileManagers();
return PL_DHASH_REMOVE;
}
InvalidateInfo* info = static_cast<InvalidateInfo*>(aUserArg);
if (PatternMatchesOrigin(info->pattern, aKey)) {
aValue->InvalidateAndRemoveFileManagers(info->persistenceType);
if (!aValue->HasFileManagers()) {
return PL_DHASH_REMOVE;
}
}
return PL_DHASH_NEXT;
}
void
IndexedDatabaseManager::InvalidateAllFileManagers()
{
AssertIsOnIOThread();
mFileManagerInfos.Enumerate(InvalidateAndRemoveFileManagers, nullptr);
class MOZ_STACK_CLASS Helper MOZ_FINAL
{
public:
static PLDHashOperator
Enumerate(const nsACString& aKey,
FileManagerInfo* aValue,
void* aUserArg)
{
AssertIsOnIOThread();
MOZ_ASSERT(!aKey.IsEmpty());
MOZ_ASSERT(aValue);
aValue->InvalidateAllFileManagers();
return PL_DHASH_NEXT;
}
};
mFileManagerInfos.EnumerateRead(Helper::Enumerate, nullptr);
mFileManagerInfos.Clear();
}
void
IndexedDatabaseManager::InvalidateFileManagers(
PersistenceType aPersistenceType,
const OriginOrPatternString& aOriginOrPattern)
const nsACString& aOrigin)
{
AssertIsOnIOThread();
NS_ASSERTION(!aOriginOrPattern.IsEmpty(), "Empty pattern!");
MOZ_ASSERT(!aOrigin.IsEmpty());
if (aOriginOrPattern.IsOrigin()) {
FileManagerInfo* info;
if (!mFileManagerInfos.Get(aOriginOrPattern, &info)) {
return;
}
info->InvalidateAndRemoveFileManagers(aPersistenceType);
if (!info->HasFileManagers()) {
mFileManagerInfos.Remove(aOriginOrPattern);
}
FileManagerInfo* info;
if (!mFileManagerInfos.Get(aOrigin, &info)) {
return;
}
else {
InvalidateInfo info(aPersistenceType, aOriginOrPattern);
mFileManagerInfos.Enumerate(InvalidateAndRemoveFileManagers, &info);
info->InvalidateAndRemoveFileManagers(aPersistenceType);
if (!info->HasFileManagers()) {
mFileManagerInfos.Remove(aOrigin);
}
}
@ -792,6 +767,10 @@ FileManagerInfo::InvalidateAllFileManagers() const
for (i = 0; i < mTemporaryStorageFileManagers.Length(); i++) {
mTemporaryStorageFileManagers[i]->Invalidate();
}
for (i = 0; i < mDefaultStorageFileManagers.Length(); i++) {
mDefaultStorageFileManagers[i]->Invalidate();
}
}
void
@ -836,11 +815,12 @@ FileManagerInfo::GetArray(PersistenceType aPersistenceType)
return mPersistentStorageFileManagers;
case PERSISTENCE_TYPE_TEMPORARY:
return mTemporaryStorageFileManagers;
case PERSISTENCE_TYPE_DEFAULT:
return mDefaultStorageFileManagers;
case PERSISTENCE_TYPE_INVALID:
default:
MOZ_CRASH("Bad storage type value!");
return mPersistentStorageFileManagers;
}
}

View File

@ -26,12 +26,6 @@ namespace dom {
class TabContext;
namespace quota {
class OriginOrPatternString;
} // namespace quota
namespace indexedDB {
class FileManager;
@ -39,7 +33,6 @@ class FileManagerInfo;
class IndexedDatabaseManager MOZ_FINAL : public nsIObserver
{
typedef mozilla::dom::quota::OriginOrPatternString OriginOrPatternString;
typedef mozilla::dom::quota::PersistenceType PersistenceType;
public:
@ -96,7 +89,7 @@ public:
void
InvalidateFileManagers(PersistenceType aPersistenceType,
const OriginOrPatternString& aOriginOrPattern);
const nsACString& aOrigin);
void
InvalidateFileManager(PersistenceType aPersistenceType,
@ -150,11 +143,6 @@ private:
void
Destroy();
static PLDHashOperator
InvalidateAndRemoveFileManagers(const nsACString& aKey,
nsAutoPtr<FileManagerInfo>& aValue,
void* aUserArg);
// Maintains a list of all file managers per origin. This list isn't
// protected by any mutex but it is only ever touched on the IO thread.
nsClassHashtable<nsCStringHashKey, FileManagerInfo> mFileManagerInfos;

View File

@ -67,7 +67,6 @@ struct DatabaseMetadata
nsString name;
uint64_t version;
PersistenceType persistenceType;
bool persistenceTypeIsExplicit;
};
struct ObjectStoreMetadata

View File

@ -102,13 +102,11 @@ PermissionRequestBase::PermissionValueForIntPermission(uint32_t aIntPermission)
{
AssertSanity();
// The 'indexedDB' permission is unusual in that the default action is to
// allow access. Switch that here to make the logic clearer.
switch (aIntPermission) {
case kPermissionDefault:
return kPermissionAllowed;
case kPermissionAllowed:
return kPermissionPrompt;
case kPermissionAllowed:
return kPermissionAllowed;
case kPermissionDenied:
return kPermissionDenied;
default:
@ -180,13 +178,11 @@ PermissionRequestBase::SetExplicitPermission(nsIPrincipal* aPrincipal,
return;
}
nsresult rv = aIntPermission == kPermissionAllowed ?
permMan->RemoveFromPrincipal(aPrincipal, kPermissionString) :
permMan->AddFromPrincipal(aPrincipal,
kPermissionString,
aIntPermission,
nsIPermissionManager::EXPIRE_NEVER,
/* aExpireTime */ 0);
nsresult rv = permMan->AddFromPrincipal(aPrincipal,
kPermissionString,
aIntPermission,
nsIPermissionManager::EXPIRE_NEVER,
/* aExpireTime */ 0);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}

View File

@ -23,8 +23,8 @@ function test()
requestLongerTimeout(2);
waitForExplicitFinish();
// Avoids the prompt
setPermission(testPageURL1, "indexedDB", "unknown");
setPermission(testPageURL2, "indexedDB", "unknown");
setPermission(testPageURL1, "indexedDB");
setPermission(testPageURL2, "indexedDB");
executeSoon(test1);
}
@ -68,7 +68,7 @@ function test3()
{
// Remove database from domain 2
ForgetAboutSite.removeDataFromDomain(domains[1]);
setPermission(testPageURL4, "indexedDB", "unknown");
setPermission(testPageURL4, "indexedDB");
executeSoon(test4);
}

View File

@ -11,7 +11,8 @@
{
const name = window.location.pathname;
let request = indexedDB.open(name, 1);
let request = indexedDB.open(name, { version: 1,
storage: "persistent" });
request.onerror = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield undefined;

View File

@ -14,7 +14,7 @@ function test()
PopupNotifications.transitionsEnabled = false;
// We want a prompt.
setPermission(testPageURL, "indexedDB", "allow");
removePermission(testPageURL, "indexedDB");
executeSoon(test1);
}
@ -31,7 +31,7 @@ function test1()
"First database creation was successful");
ok(!exception, "No exception");
is(getPermission(testPageURL, "indexedDB"),
Components.interfaces.nsIPermissionManager.UNKNOWN_ACTION,
Components.interfaces.nsIPermissionManager.ALLOW_ACTION,
"Correct permission set");
gBrowser.removeCurrentTab();
executeSoon(test2);
@ -67,7 +67,7 @@ function test2()
"First database creation was successful");
ok(!exception, "No exception");
is(getPermission(testPageURL, "indexedDB"),
Components.interfaces.nsIPermissionManager.UNKNOWN_ACTION,
Components.interfaces.nsIPermissionManager.ALLOW_ACTION,
"Correct permission set");
gBrowser.removeCurrentTab();
unregisterAllPopupEventHandlers();

View File

@ -12,7 +12,7 @@ function test()
waitForExplicitFinish();
// We want the prompt.
PopupNotifications.transitionsEnabled = false;
setPermission(testPageURL, "indexedDB", "allow");
removePermission(testPageURL, "indexedDB");
executeSoon(test1);
}

View File

@ -10,6 +10,8 @@ const notificationID = "indexedDB-permissions-prompt";
function test()
{
waitForExplicitFinish();
// Avoids the actual prompt
setPermission(testPageURL, "indexedDB");
executeSoon(test1);
}

View File

@ -35,7 +35,9 @@
window.removeEventListener("indexedDB-addMore", onAddMore, true);
window.removeEventListener("indexedDB-done", onDone, true);
let request = indexedDB.open(window.location.pathname, version++);
let request =
indexedDB.open(window.location.pathname, { version: version++,
storage: "persistent" });
request.onerror = errorHandler;
request.onupgradeneeded = function(event) {
db.deleteObjectStore("foo");
@ -55,7 +57,8 @@
window.addEventListener("indexedDB-addMore", onAddMore, true);
window.addEventListener("indexedDB-done", onDone, true);
let request = indexedDB.open(name, version++);
let request = indexedDB.open(name, { version: version++,
storage: "persistent" });
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield undefined;

View File

@ -13,6 +13,7 @@ function test()
waitForExplicitFinish();
requestLongerTimeout(10);
PopupNotifications.transitionsEnabled = false;
setPermission(testPageURL, "indexedDB");
removePermission(testPageURL, "indexedDB-unlimited");
Services.prefs.setIntPref("dom.indexedDB.warningQuota", 2);
executeSoon(test1);
@ -43,7 +44,7 @@ function test1()
"Correct permission set");
gBrowser.removeCurrentTab();
unregisterAllPopupEventHandlers();
executeSoon(finish);
executeSoon(test2);
});
executeSoon(function() { dispatchEvent("indexedDB-done"); });
}

View File

@ -13,7 +13,8 @@
function onAddMore() {
const name = window.location.pathname + i++;
let request = indexedDB.open(name, 1);
let request = indexedDB.open(name, { version: 1,
storage: "persistent" });
request.onerror = errorHandler;
request.onsuccess = grabEventAndContinueHandler;

View File

@ -13,6 +13,7 @@ function test()
waitForExplicitFinish();
requestLongerTimeout(10);
PopupNotifications.transitionsEnabled = false;
setPermission(testPageURL, "indexedDB");
removePermission(testPageURL, "indexedDB-unlimited");
Services.prefs.setIntPref("dom.indexedDB.warningQuota", 2);
executeSoon(test1);

View File

@ -49,7 +49,8 @@
deleteRequest.onerror = errorHandler;
deleteRequest.onsuccess = function () {
// It is imperative that we open a different database this time.
let request = indexedDB.open("take2", 1);
let request = indexedDB.open("take2", { version: 1,
storage: "persistent" });
request.onerror = errorHandler;
request.onupgradeneeded = function(event) {
db = event.target.result;
@ -67,7 +68,8 @@
window.addEventListener("indexedDB-reset", onReset, true);
window.addEventListener("indexedDB-done", onDone, true);
let request = indexedDB.open(name, 1);
let request = indexedDB.open(name, { version: 1,
storage: "persistent" });
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
let event = yield undefined;

View File

@ -13,6 +13,7 @@ function test()
waitForExplicitFinish();
requestLongerTimeout(10);
PopupNotifications.transitionsEnabled = false;
setPermission(testPageURL, "indexedDB");
removePermission(testPageURL, "indexedDB-unlimited");
Services.prefs.setIntPref("dom.indexedDB.warningQuota", 2);
executeSoon(test1);

View File

@ -13,6 +13,7 @@ function test()
waitForExplicitFinish();
requestLongerTimeout(10);
PopupNotifications.transitionsEnabled = false;
setPermission(testPageURL, "indexedDB");
removePermission(testPageURL, "indexedDB-unlimited");
Services.prefs.setIntPref("dom.indexedDB.warningQuota", 2);
executeSoon(test1);

View File

@ -49,6 +49,8 @@
};
function testSteps() {
window.parent.SpecialPowers.addPermission("indexedDB", true, document);
let request = indexedDB.open(window.location.pathname, 1);
request.onsuccess = unexpectedSuccessHandler;
request.onerror = grabEventAndContinueHandler;

View File

@ -87,6 +87,8 @@
}
function testSteps() {
window.parent.SpecialPowers.addPermission("indexedDB", true, document);
let request = indexedDB.open(window.location.pathname, 1);
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;

View File

@ -51,6 +51,8 @@
};
function testSteps() {
window.parent.SpecialPowers.addPermission("indexedDB", true, document);
// Test 1: Throwing an exception in an upgradeneeded handler should
// abort the versionchange transaction and fire an error at the request.
let request = indexedDB.open(window.location.pathname, 1);

View File

@ -109,24 +109,10 @@ function dispatchEvent(eventName)
gBrowser.selectedBrowser.contentWindow.dispatchEvent(event);
}
function setPermission(url, permission, value)
function setPermission(url, permission)
{
const nsIPermissionManager = Components.interfaces.nsIPermissionManager;
switch (value) {
case "allow":
value = nsIPermissionManager.ALLOW_ACTION;
break;
case "deny":
value = nsIPermissionManager.DENY_ACTION;
break;
case "unknown":
value = nsIPermissionManager.UNKNOWN_ACTION;
break;
default:
throw new Error("No idea what to set here!");
}
let uri = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService)
.newURI(url, null, null);
@ -135,8 +121,9 @@ function setPermission(url, permission, value)
.getNoAppCodebasePrincipal(uri);
Components.classes["@mozilla.org/permissionmanager;1"]
.getService(Components.interfaces.nsIPermissionManager)
.addFromPrincipal(principal, permission, value);
.getService(nsIPermissionManager)
.addFromPrincipal(principal, permission,
nsIPermissionManager.ALLOW_ACTION);
}
function removePermission(url, permission)

View File

@ -49,6 +49,7 @@ if (!window.runTest) {
{
SimpleTest.waitForExplicitFinish();
allowIndexedDB();
if (limitedQuota) {
denyUnlimitedQuota();
}
@ -66,10 +67,11 @@ if (!window.runTest) {
function finishTest()
{
resetUnlimitedQuota();
resetExperimental();
resetArchiveReader();
resetExperimental();
resetTesting();
resetUnlimitedQuota();
resetIndexedDB();
SpecialPowers.notifyObserversInParentProcess(null, "disk-space-watcher",
"free");
@ -197,6 +199,16 @@ function removePermission(type, url)
SpecialPowers.removePermission(type, url);
}
function allowIndexedDB(url)
{
addPermission("indexedDB", true, url);
}
function resetIndexedDB(url)
{
removePermission("indexedDB", url);
}
function allowUnlimitedQuota(url)
{
addPermission("indexedDB-unlimited", true, url);

View File

@ -151,9 +151,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_deleteDatabase_interactions.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_disabled_quota_prompt.html]
# Test temporarily disabled.
skip-if = true
# skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_error_events_abort_transactions.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
[test_event_propagation.html]

View File

@ -40,6 +40,7 @@
{
const databaseName = window.location.pathname;
const databaseVersion = 1;
const databaseStorage = "persistent";
const objectStoreName = "foo";
info("setting quota pref");
@ -50,7 +51,8 @@
info("opening database");
let request = indexedDB.open(databaseName, databaseVersion);
let request = indexedDB.open(databaseName, {version: databaseVersion,
storage: databaseStorage});
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = unexpectedSuccessHandler;

View File

@ -14,6 +14,7 @@
{
const name = window.location.pathname;
const version = 1;
const storages = ["persistent", "temporary", "default"];
const objectStoreName = "Foo";
const data = { key: 1, value: "bar" };
@ -27,84 +28,44 @@
is(e.name, "TypeError", "Good error name.");
}
let request = indexedDB.open(name, { version: version,
storage: "persistent" });
request.onerror = grabEventAndContinueHandler;
request.onupgradeneeded = unexpectedSuccessHandler;
request.onsuccess = unexpectedSuccessHandler;
let event = yield undefined;
for (let storage of storages) {
let request = indexedDB.open(name, { version: version,
storage: storage });
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;
let event = yield undefined;
is(event.type, "error", "Got error event");
is(event.target, request, "Got correct target");
is(event.target.error.name, "UnknownError", "Got correct error name");
event.preventDefault();
is(event.type, "upgradeneeded", "Got correct event type");
request = indexedDB.open(name, { version: version });
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield undefined;
let db = event.target.result;
db.onerror = errorHandler;
is(event.type, "upgradeneeded", "Got correct event type");
let objectStore = db.createObjectStore(objectStoreName, { });
let db = event.target.result;
db.onerror = errorHandler;
event = yield undefined;
let objectStore = db.createObjectStore(objectStoreName, { });
is(event.type, "success", "Got correct event type");
event = yield undefined;
is(db.name, name, "Correct name");
is(db.version, version, "Correct version");
is(db.storage, storage, "Correct persistence type");
is(event.type, "success", "Got correct event type");
objectStore = db.transaction([objectStoreName], "readwrite")
.objectStore(objectStoreName);
is(db.name, name, "Correct name");
is(db.version, version, "Correct version");
is(db.storage, "persistent", "Correct persistence type");
request = objectStore.get(data.key);
request.onsuccess = grabEventAndContinueHandler;
event = yield undefined;
objectStore = db.transaction([objectStoreName], "readwrite")
.objectStore(objectStoreName);
is(event.target.result, null, "Got no data");
request = objectStore.get(data.key);
request.onsuccess = grabEventAndContinueHandler;
event = yield undefined;
request = objectStore.add(data.value, data.key);
request.onsuccess = grabEventAndContinueHandler;
event = yield undefined;
is(event.target.result, null, "Got no data");
request = objectStore.add(data.value, data.key);
request.onsuccess = grabEventAndContinueHandler;
event = yield undefined;
is(event.target.result, data.key, "Got correct key");
request = indexedDB.open(name, { version: version,
storage: "temporary" });
request.onerror = errorHandler;
request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;
event = yield undefined;
is(event.type, "upgradeneeded", "Got correct event type");
db = event.target.result;
db.onerror = errorHandler;
objectStore = db.createObjectStore(objectStoreName, { });
event = yield undefined;
is(event.type, "success", "Got correct event type");
is(db.name, name, "Correct name");
is(db.version, version, "Correct version");
is(db.storage, "temporary", "Correct persistence type");
objectStore = db.transaction([objectStoreName])
.objectStore(objectStoreName);
request = objectStore.get(data.key);
request.onsuccess = grabEventAndContinueHandler;
event = yield undefined;
is(event.target.result, null, "Got no data");
is(event.target.result, data.key, "Got correct key");
}
finishTest();
yield undefined;

Some files were not shown because too many files have changed in this diff Show More