Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2014-06-05 15:14:29 +02:00
Родитель a9161a7362 83702104a1
Коммит e929ac9097
250 изменённых файлов: 4894 добавлений и 2685 удалений

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

@ -22,5 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 1014976 - Windows debug bustage from linking changes.
Preemptive clobber for a vm/Xdr.h change to evade bug 1019955 (should it have otherwise arisen, which is unclear).

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

@ -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="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8e4420c0c5c8e8c8e58a000278a7129403769f96"/>

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

@ -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="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="276ce45e78b09c4a4ee643646f691d22804754c1">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

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

@ -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="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8e4420c0c5c8e8c8e58a000278a7129403769f96"/>

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

@ -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="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>

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

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "7f0af1e164a39efb732c0c341c2a8e51f681d913",
"revision": "c3d40600c0090c5ca6ca4427f3a870ff443a109d",
"repo_path": "/integration/gaia-central"
}

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

@ -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="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

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

@ -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="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

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

@ -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="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>

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

@ -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="d2cfef555dabab415085e548ed44c48a99be5c32"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="908f94fda04462001ece86e6b6c15ad8b05f7526"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

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

@ -2885,7 +2885,7 @@
onget="return this.mCurrentBrowser.isSyntheticDocument;"
readonly="true"/>
<method name="_handleKeyEvent">
<method name="_handleKeyDownEvent">
<parameter name="aEvent"/>
<body><![CDATA[
if (!aEvent.isTrusted) {
@ -2896,21 +2896,44 @@
if (aEvent.altKey)
return;
// Don't check if the event was already consumed because tab
// navigation should always work for better user experience.
if (aEvent.ctrlKey && aEvent.shiftKey && !aEvent.metaKey) {
switch (aEvent.keyCode) {
case aEvent.DOM_VK_PAGE_UP:
this.moveTabBackward();
aEvent.stopPropagation();
aEvent.preventDefault();
return;
case aEvent.DOM_VK_PAGE_DOWN:
this.moveTabForward();
aEvent.stopPropagation();
aEvent.preventDefault();
return;
}
}
#ifndef XP_MACOSX
if (aEvent.ctrlKey && !aEvent.shiftKey && !aEvent.metaKey &&
aEvent.keyCode == KeyEvent.DOM_VK_F4 &&
!this.mCurrentTab.pinned) {
this.removeCurrentTab({animate: true});
aEvent.preventDefault();
}
#endif
]]></body>
</method>
<method name="_handleKeyPressEvent">
<parameter name="aEvent"/>
<body><![CDATA[
if (!aEvent.isTrusted) {
// Don't let untrusted events mess with tabs.
return;
}
if (aEvent.altKey)
return;
// We need to take care of FAYT-watching as long as the findbar
// isn't initialized. The checks on aEvent are copied from
// _shouldFastFind (see findbar.xml).
@ -2940,17 +2963,8 @@
if (window.getComputedStyle(this, null).direction == "ltr")
offset *= -1;
this.tabContainer.advanceSelectedTab(offset, true);
aEvent.stopPropagation();
aEvent.preventDefault();
}
#else
if (aEvent.ctrlKey && !aEvent.shiftKey && !aEvent.metaKey &&
aEvent.keyCode == KeyEvent.DOM_VK_F4 &&
!this.mCurrentTab.pinned) {
this.removeCurrentTab({animate: true});
aEvent.stopPropagation();
aEvent.preventDefault();
}
#endif
]]></body>
</method>
@ -2982,8 +2996,11 @@
<parameter name="aEvent"/>
<body><![CDATA[
switch (aEvent.type) {
case "keydown":
this._handleKeyDownEvent(aEvent);
break;
case "keypress":
this._handleKeyEvent(aEvent);
this._handleKeyPressEvent(aEvent);
break;
case "sizemodechange":
if (aEvent.target == window) {
@ -3050,7 +3067,9 @@
this.mCurrentBrowser = document.getAnonymousElementByAttribute(this, "anonid", "initialBrowser");
this.mCurrentTab = this.tabContainer.firstChild;
document.addEventListener("keypress", this, false);
let els = Cc["@mozilla.org/eventlistenerservice;1"].getService(Ci.nsIEventListenerService);
els.addSystemEventListener(document, "keydown", this, false);
els.addSystemEventListener(document, "keypress", this, false);
window.addEventListener("sizemodechange", this, false);
var uniqueId = this._generateUniquePanelID();
@ -3128,7 +3147,9 @@
this.mTabListeners[i].destroy();
this.mTabListeners[i] = null;
}
document.removeEventListener("keypress", this, false);
let els = Cc["@mozilla.org/eventlistenerservice;1"].getService(Ci.nsIEventListenerService);
els.removeSystemEventListener(document, "keydown", this, false);
els.removeSystemEventListener(document, "keypress", this, false);
window.removeEventListener("sizemodechange", this, false);
if (gMultiProcessBrowser) {
@ -4247,7 +4268,7 @@
event.stopPropagation();
]]></handler>
<handler event="keypress"><![CDATA[
<handler event="keydown" group="system"><![CDATA[
if (event.altKey || event.shiftKey ||
#ifdef XP_MACOSX
!event.metaKey)
@ -4256,6 +4277,9 @@
#endif
return;
// Don't check if the event was already consumed because tab navigation
// should work always for better user experience.
switch (event.keyCode) {
case KeyEvent.DOM_VK_UP:
this.tabbrowser.moveTabBackward();
@ -4274,11 +4298,10 @@
this.tabbrowser.moveTabToEnd();
break;
default:
// Stop the keypress event for the above keyboard
// Consume the keydown event for the above keyboard
// shortcuts only.
return;
}
event.stopPropagation();
event.preventDefault();
]]></handler>

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

@ -380,6 +380,7 @@ skip-if = os == "linux" || os == "mac" # No tabs in titlebar on linux
# Disabled on OS X because of bug 967917
[browser_tabfocus.js]
skip-if = e10s # Bug 921935 - focusmanager issues with e10s (test calls getFocusedElementForWindow with a content window)
[browser_tabkeynavigation.js]
[browser_tabopen_reflows.js]
skip-if = e10s # Bug ?????? - test needs to be updated for e10s (captures a stack that isn't correct in e10s)
[browser_tabs_isActive.js]

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

@ -0,0 +1,214 @@
/*
* This test checks that keyboard navigation for tabs isn't blocked by content
*/
function test() {
waitForExplicitFinish();
let testPage1 = "data:text/html,<html id='tab1'><body><button id='button1'>Tab 1</button></body></html>";
let testPage2 = "data:text/html,<html id='tab2'><body><button id='button2'>Tab 2</button><script>function preventDefault(event) { event.preventDefault(); event.stopImmediatePropagation(); } window.addEventListener('keydown', preventDefault, true); window.addEventListener('keypress', preventDefault, true);</script></body></html>";
let testPage3 = "data:text/html,<html id='tab3'><body><button id='button3'>Tab 3</button></body></html>";
let tab1 = gBrowser.addTab();
let browser1 = gBrowser.getBrowserForTab(tab1);
let tab2 = gBrowser.addTab();
let browser2 = gBrowser.getBrowserForTab(tab2);
let tab3 = gBrowser.addTab();
let browser3 = gBrowser.getBrowserForTab(tab3);
let loadCount = 0;
function check()
{
// wait for all tabs to load
if (++loadCount != 3) {
return;
}
browser1.removeEventListener("load", check, true);
browser2.removeEventListener("load", check, true);
browser3.removeEventListener("load", check, true);
executeSoon(_run_tab_keyboard_navigation_tests);
}
function _run_tab_keyboard_navigation_tests()
{
// Kill the animation for simpler test.
Services.prefs.setBoolPref("browser.tabs.animate", false);
gBrowser.selectedTab = tab1;
browser1.contentWindow.focus();
is(gBrowser.selectedTab, tab1,
"Tab1 should be activated");
EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true },
browser1.contentWindow);
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+Tab on Tab1");
EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true },
browser2.contentWindow);
is(gBrowser.selectedTab, tab3,
"Tab3 should be activated by pressing Ctrl+Tab on Tab2");
EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true },
browser3.contentWindow);
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+Shift+Tab on Tab3");
EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: true },
browser2.contentWindow);
is(gBrowser.selectedTab, tab1,
"Tab1 should be activated by pressing Ctrl+Shift+Tab on Tab2");
gBrowser.selectedTab = tab1;
browser1.contentWindow.focus();
is(gBrowser.selectedTab, tab1,
"Tab1 should be activated");
EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true },
browser1.contentWindow);
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+PageDown on Tab1");
EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true },
browser2.contentWindow);
is(gBrowser.selectedTab, tab3,
"Tab3 should be activated by pressing Ctrl+PageDown on Tab2");
EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true },
browser3.contentWindow);
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+PageUp on Tab3");
EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true },
browser2.contentWindow);
is(gBrowser.selectedTab, tab1,
"Tab1 should be activated by pressing Ctrl+PageUp on Tab2");
if (gBrowser.mTabBox._handleMetaAltArrows) {
gBrowser.selectedTab = tab1;
browser1.contentWindow.focus();
let ltr =
window.getComputedStyle(gBrowser.mTabBox, "").direction == "ltr";
let advanceKey = ltr ? "VK_RIGHT" : "VK_LEFT";
let reverseKey = ltr ? "VK_LEFT" : "VK_RIGHT";
is(gBrowser.selectedTab, tab1,
"Tab1 should be activated");
EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true },
browser1.contentWindow);
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+" + advanceKey + " on Tab1");
EventUtils.synthesizeKey(advanceKey, { altKey: true, metaKey: true },
browser2.contentWindow);
is(gBrowser.selectedTab, tab3,
"Tab3 should be activated by pressing Ctrl+" + advanceKey + " on Tab2");
EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true },
browser3.contentWindow);
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+" + reverseKey + " on Tab3");
EventUtils.synthesizeKey(reverseKey, { altKey: true, metaKey: true },
browser2.contentWindow);
is(gBrowser.selectedTab, tab1,
"Tab1 should be activated by pressing Ctrl+" + reverseKey + " on Tab2");
}
gBrowser.selectedTab = tab2;
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated");
is(gBrowser.tabContainer.selectedIndex, 2,
"Tab2 index should be 2");
EventUtils.synthesizeKey("VK_PAGE_DOWN", { ctrlKey: true, shiftKey: true },
browser2.contentWindow);
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated after Ctrl+Shift+PageDown");
is(gBrowser.tabContainer.selectedIndex, 3,
"Tab2 index should be 1 after Ctrl+Shift+PageDown");
EventUtils.synthesizeKey("VK_PAGE_UP", { ctrlKey: true, shiftKey: true },
browser2.contentWindow);
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated after Ctrl+Shift+PageUp");
is(gBrowser.tabContainer.selectedIndex, 2,
"Tab2 index should be 2 after Ctrl+Shift+PageUp");
if (navigator.platform.indexOf("Mac") == 0) {
gBrowser.selectedTab = tab1;
browser1.contentWindow.focus();
// XXX Currently, Command + "{" and "}" don't work if keydown event is
// consumed because following keypress event isn't fired.
let ltr =
window.getComputedStyle(gBrowser.mTabBox, "").direction == "ltr";
let advanceKey = ltr ? "}" : "{";
let reverseKey = ltr ? "{" : "}";
is(gBrowser.selectedTab, tab1,
"Tab1 should be activated");
EventUtils.synthesizeKey(advanceKey, { metaKey: true },
browser1.contentWindow);
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+" + advanceKey + " on Tab1");
EventUtils.synthesizeKey(advanceKey, { metaKey: true },
browser2.contentWindow);
todo_is(gBrowser.selectedTab, tab3,
"Tab3 should be activated by pressing Ctrl+" + advanceKey + " on Tab2");
if (gBrowser.selectedTab != tab3) {
EventUtils.synthesizeKey(reverseKey, { metaKey: true },
browser3.contentWindow);
is(gBrowser.selectedTab, tab2,
"Tab2 should be activated by pressing Ctrl+" + reverseKey + " on Tab3");
}
EventUtils.synthesizeKey(reverseKey, { metaKey: true },
browser2.contentWindow);
todo_is(gBrowser.selectedTab, tab1,
"Tab1 should be activated by pressing Ctrl+" + reverseKey + " on Tab2");
} else {
gBrowser.selectedTab = tab2;
EventUtils.synthesizeKey("VK_F4", { type: "keydown", ctrlKey: true },
browser2.contentWindow);
isnot(gBrowser.selectedTab, tab2,
"Tab2 should be closed by pressing Ctrl+F4 on Tab2");
is(gBrowser.tabs.length, 3,
"The count of tabs should be 3 since tab2 should be closed");
let activeWindow =
gBrowser.getBrowserForTab(gBrowser.selectedTab).contentWindow;
// NOTE: keypress event shouldn't be fired since the keydown event should
// be consumed by tab2.
EventUtils.synthesizeKey("VK_F4", { type: "keyup", ctrlKey: true },
activeWindow);
is(gBrowser.tabs.length, 3,
"The count of tabs should be 3 since renaming key events shouldn't close other tabs");
}
gBrowser.selectedTab = tab3;
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
Services.prefs.clearUserPref("browser.tabs.animate");
finish();
}
browser1.addEventListener("load", check, true);
browser2.addEventListener("load", check, true);
browser3.addEventListener("load", check, true);
browser1.contentWindow.location = testPage1;
browser2.contentWindow.location = testPage2;
browser3.contentWindow.location = testPage3;
}

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

@ -9032,15 +9032,17 @@ dnl ========================================================
dnl ICU Support
dnl ========================================================
if test "$MOZ_BUILD_APP" = "browser"; then
_INTL_API=yes
else
# Internationalization isn't built or exposed by default in non-desktop
# builds. Bugs to enable:
#
# Android: bug 864843
# B2G: bug 866301
# Internationalization isn't built or exposed by default in non-desktop
# builds. Bugs to enable:
#
# Android: bug 864843
# B2G: bug 866301
if test "$MOZ_WIDGET_TOOLKIT" = "android" ||
test "$MOZ_BUILD_APP" = "b2g"; then
_INTL_API=no
else
_INTL_API=yes
fi
MOZ_CONFIG_ICU()

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

@ -2597,9 +2597,10 @@ Serialize(FragmentOrElement* aRoot, bool aDescendentsOnly, nsAString& aOut)
current = current->GetParentNode();
// Template case, if we are in a template's content, then the parent
// should be the host template element.
if (current->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
// Handle template element. If the parent is a template's content,
// then adjust the parent to be the template element.
if (current != aRoot &&
current->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
DocumentFragment* frag = static_cast<DocumentFragment*>(current);
nsIContent* fragHost = frag->GetHost();
if (fragHost && nsNodeUtils::IsTemplateElement(fragHost)) {

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

@ -231,8 +231,8 @@ nsCSPParser::port()
// Port must start with a number
if (!accept(isNumberToken)) {
const char16_t* params[] = { mCurValue.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "policyURIParseError",
const char16_t* params[] = { mCurToken.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParsePort",
params, ArrayLength(params));
return false;
}
@ -260,6 +260,14 @@ nsCSPParser::subPath(nsCSPHostSrc* aCspHost)
++charCounter;
}
if (accept(SLASH)) {
// do not accept double slashes
// see http://tools.ietf.org/html/rfc3986#section-3.3
if (accept(SLASH)) {
const char16_t* params[] = { mCurToken.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParseInvalidSource",
params, ArrayLength(params));
return false;
}
aCspHost->appendPath(mCurValue);
// Resetting current value since we are appending parts of the path
// to aCspHost, e.g; "http://www.example.com/path1/path2" then the
@ -289,12 +297,18 @@ nsCSPParser::path(nsCSPHostSrc* aCspHost)
resetCurValue();
if (!accept(SLASH)) {
const char16_t* params[] = { mCurToken.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParseInvalidSource",
params, ArrayLength(params));
return false;
}
if (atEnd()) {
return true;
}
if (!hostChar()) {
const char16_t* params[] = { mCurToken.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParseInvalidSource",
params, ArrayLength(params));
return false;
}
return subPath(aCspHost);
@ -347,8 +361,8 @@ nsCSPParser::host()
}
// If the token is not only the "*", a "." must follow right after
if (!accept(DOT)) {
const char16_t* params[] = { mCurValue.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "policyURIParseError",
const char16_t* params[] = { mCurToken.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParseInvalidHost",
params, ArrayLength(params));
return nullptr;
}
@ -356,16 +370,16 @@ nsCSPParser::host()
// Expecting at least one Character
if (!accept(isCharacterToken)) {
const char16_t* params[] = { mCurValue.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "policyURIParseError",
const char16_t* params[] = { mCurToken.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParseInvalidHost",
params, ArrayLength(params));
return nullptr;
}
// There might be several sub hosts defined.
if (!subHost()) {
const char16_t* params[] = { mCurValue.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "policyURIParseError",
const char16_t* params[] = { mCurToken.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParseInvalidHost",
params, ArrayLength(params));
return nullptr;
}
@ -374,7 +388,7 @@ nsCSPParser::host()
if (CSP_IsQuotelessKeyword(mCurValue)) {
nsString keyword = mCurValue;
ToLowerCase(keyword);
const char16_t* params[] = { mCurValue.get(), keyword.get() };
const char16_t* params[] = { mCurToken.get(), keyword.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "hostNameMightBeKeyword",
params, ArrayLength(params));
}
@ -395,8 +409,8 @@ nsCSPParser::appHost()
// appHosts have to end with "}", otherwise we have to report an error
if (!accept(CLOSE_CURL)) {
const char16_t* params[] = { mCurValue.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "policyURIParseError",
const char16_t* params[] = { mCurToken.get() };
logWarningErrorToConsole(nsIScriptError::warningFlag, "couldntParseInvalidSource",
params, ArrayLength(params));
return nullptr;
}
@ -464,7 +478,11 @@ nsCSPParser::hostSource()
// occurs, path() reports the error; handing cspHost as an argument
// which simplifies parsing of several paths.
if (!path(cspHost)) {
return cspHost;
// If the host [port] is followed by a path, it has to be a valid path,
// otherwise we pass the nullptr, indicating an error, up the callstack.
// see also http://www.w3.org/TR/CSP11/#source-list
delete cspHost;
return nullptr;
}
// Calling fileAndArguments to see if there are any files to parse;

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

@ -4513,6 +4513,11 @@ nsDocument::SetScriptGlobalObject(nsIScriptGlobalObject *aScriptGlobalObject)
// doing the initial document load and don't want to fire the event for this
// change.
mVisibilityState = GetVisibilityState();
// The global in the template contents owner document should be the same.
if (mTemplateContentsOwner && mTemplateContentsOwner != this) {
mTemplateContentsOwner->SetScriptGlobalObject(aScriptGlobalObject);
}
}
nsIScriptGlobalObject*
@ -9443,7 +9448,6 @@ nsDocument::GetTemplateContentsOwner()
bool hasHadScriptObject = true;
nsIScriptGlobalObject* scriptObject =
GetScriptHandlingObject(hasHadScriptObject);
NS_ENSURE_TRUE(scriptObject || !hasHadScriptObject, nullptr);
nsCOMPtr<nsIDOMDocument> domDocument;
nsresult rv = NS_NewDOMDocument(getter_AddRefs(domDocument),
@ -9461,12 +9465,16 @@ nsDocument::GetTemplateContentsOwner()
mTemplateContentsOwner = do_QueryInterface(domDocument);
NS_ENSURE_TRUE(mTemplateContentsOwner, nullptr);
mTemplateContentsOwner->SetScriptHandlingObject(scriptObject);
nsDocument* doc = static_cast<nsDocument*>(mTemplateContentsOwner.get());
doc->mHasHadScriptHandlingObject = hasHadScriptObject;
if (!scriptObject) {
mTemplateContentsOwner->SetScopeObject(GetScopeObject());
}
// Set |doc| as the template contents owner of itself so that
// |doc| is the template contents owner of template elements created
// by |doc|.
nsDocument* doc = static_cast<nsDocument*>(mTemplateContentsOwner.get());
doc->mTemplateContentsOwner = doc;
}

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

@ -522,12 +522,12 @@ nsDocumentEncoder::SerializeToStringIterative(nsINode* aNode,
{
nsresult rv;
nsINode* node = aNode->GetFirstChild();
nsINode* node = nsNodeUtils::GetFirstChildOfTemplateOrNode(aNode);
while (node) {
nsINode* current = node;
rv = SerializeNodeStart(current, 0, -1, aStr, current);
NS_ENSURE_SUCCESS(rv, rv);
node = current->GetFirstChild();
node = nsNodeUtils::GetFirstChildOfTemplateOrNode(current);
while (!node && current && current != aNode) {
rv = SerializeNodeEnd(current, aStr);
NS_ENSURE_SUCCESS(rv, rv);
@ -536,6 +536,17 @@ nsDocumentEncoder::SerializeToStringIterative(nsINode* aNode,
if (!node) {
// Perhaps parent node has siblings.
current = current->GetParentNode();
// Handle template element. If the parent is a template's content,
// then adjust the parent to be the template element.
if (current && current != aNode &&
current->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) {
DocumentFragment* frag = static_cast<DocumentFragment*>(current);
nsIContent* host = frag->GetHost();
if (host && host->IsHTML(nsGkAtoms::_template)) {
current = host;
}
}
}
}
}

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

@ -2525,8 +2525,8 @@ GetRequestBody(nsIVariant* aBody, nsIInputStream** aResult, uint64_t* aContentLe
nsresult rv = aBody->GetAsJSVal(&realVal);
if (NS_SUCCEEDED(rv) && !realVal.isPrimitive()) {
JS::Rooted<JSObject*> obj(cx, realVal.toObjectOrNull());
if (JS_IsArrayBufferObject(obj)) {
ArrayBuffer buf(obj);
ArrayBuffer buf;
if (buf.Init(obj)) {
buf.ComputeLengthAndData();
return GetRequestBody(buf.Data(), buf.Length(), aResult,
aContentLength, aContentType, aCharset);

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

@ -407,28 +407,6 @@ nsresult TestPoliciesThatLogWarning() {
"script-src http://www.selfuri.com" },
{ "script-src 'none' test.com; script-src example.com",
"script-src http://test.com" },
{ "script-src http://www.example.com//",
"script-src http://www.example.com" },
{ "script-src http://www.example.com/path-1//",
"script-src http://www.example.com" },
{ "script-src http://www.example.com/path-1//path_2",
"script-src http://www.example.com" },
{ "script-src http://www.example.com:88path-1/",
"script-src http://www.example.com:88" },
{ "script-src http://www.example.com:88//",
"script-src http://www.example.com:88" },
{ "script-src http://www.example.com:88//path-1",
"script-src http://www.example.com:88" },
{ "script-src http://www.example.com:88//path-1",
"script-src http://www.example.com:88" },
{ "script-src http://www.example.com:88/.js",
"script-src http://www.example.com:88" },
{ "script-src http://www.example.com:88.js",
"script-src http://www.example.com:88" },
{ "script-src http://www.example.com:*.js",
"script-src http://www.example.com:*" },
{ "script-src http://www.example.com:*.",
"script-src http://www.example.com:*" }
};
uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);
@ -461,7 +439,18 @@ nsresult TestBadPolicies() {
{ "img-src *::88", "" },
{ "object-src http://localhost:", "" },
{ "script-src test..com", "" },
{ "script-src sub1.sub2.example+", "" }
{ "script-src sub1.sub2.example+", "" },
{ "script-src http://www.example.com//", "" },
{ "script-src http://www.example.com/path-1//", "" },
{ "script-src http://www.example.com/path-1//path_2", "" },
{ "script-src http://www.example.com:88path-1/", "" },
{ "script-src http://www.example.com:88//", "" },
{ "script-src http://www.example.com:88//path-1", "" },
{ "script-src http://www.example.com:88//path-1", "" },
{ "script-src http://www.example.com:88/.js", "" },
{ "script-src http://www.example.com:88.js", "" },
{ "script-src http://www.example.com:*.js", "" },
{ "script-src http://www.example.com:*.", "" },
};
uint32_t policyCount = sizeof(policies) / sizeof(PolicyTest);

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

@ -27,6 +27,8 @@ support-files =
[test_cspreports.js]
[test_error_codes.js]
run-sequentially = Hardcoded 4444 port.
# Bug 1018414: hardcoded localhost doesn't work properly on some OS X installs
skip-if = os == 'mac'
[test_thirdpartyutil.js]
[test_xhr_standalone.js]
[test_xmlserializer.js]

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

@ -70,6 +70,7 @@
#include "mozilla/Alignment.h"
#include "mozilla/Assertions.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ImageData.h"
#include "mozilla/dom/PBrowserParent.h"
@ -4006,7 +4007,9 @@ void
CanvasRenderingContext2D::PutImageData(ImageData& imageData, double dx,
double dy, ErrorResult& error)
{
dom::Uint8ClampedArray arr(imageData.GetDataObject());
dom::Uint8ClampedArray arr;
DebugOnly<bool> inited = arr.Init(imageData.GetDataObject());
MOZ_ASSERT(inited);
error = PutImageData_explicit(JS_DoubleToInt32(dx), JS_DoubleToInt32(dy),
imageData.Width(), imageData.Height(),
@ -4020,7 +4023,9 @@ CanvasRenderingContext2D::PutImageData(ImageData& imageData, double dx,
double dirtyHeight,
ErrorResult& error)
{
dom::Uint8ClampedArray arr(imageData.GetDataObject());
dom::Uint8ClampedArray arr;
DebugOnly<bool> inited = arr.Init(imageData.GetDataObject());
MOZ_ASSERT(inited);
error = PutImageData_explicit(JS_DoubleToInt32(dx), JS_DoubleToInt32(dy),
imageData.Width(), imageData.Height(),

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

@ -42,6 +42,7 @@
#include "nsCocoaFeatures.h"
#endif
#include "mozilla/DebugOnly.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/ImageData.h"
#include "mozilla/dom/ToJSValue.h"
@ -3713,7 +3714,9 @@ WebGLContext::TexImage2D(GLenum target, GLint level,
return ErrorInvalidValue("texImage2D: null ImageData");
}
Uint8ClampedArray arr(pixels->GetDataObject());
Uint8ClampedArray arr;
DebugOnly<bool> inited = arr.Init(pixels->GetDataObject());
MOZ_ASSERT(inited);
arr.ComputeLengthAndData();
return TexImage2D_base(target, level, internalformat, pixels->Width(),
@ -3846,7 +3849,9 @@ WebGLContext::TexSubImage2D(GLenum target, GLint level,
if (!pixels)
return ErrorInvalidValue("texSubImage2D: pixels must not be null!");
Uint8ClampedArray arr(pixels->GetDataObject());
Uint8ClampedArray arr;
DebugOnly<bool> inited = arr.Init(pixels->GetDataObject());
MOZ_ASSERT(inited);
arr.ComputeLengthAndData();
return TexSubImage2D_base(target, level, xoffset, yoffset,

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

@ -11,21 +11,7 @@
#include "nsIAtom.h"
#include "nsRuleData.h"
using namespace mozilla::dom;
nsGenericHTMLElement*
NS_NewHTMLTemplateElement(already_AddRefed<nsINodeInfo>&& aNodeInfo,
FromParser aFromParser)
{
HTMLTemplateElement* it = new HTMLTemplateElement(aNodeInfo);
nsresult rv = it->Init();
if (NS_FAILED(rv)) {
delete it;
return nullptr;
}
return it;
}
NS_IMPL_NS_NEW_HTML_ELEMENT(Template)
namespace mozilla {
namespace dom {
@ -34,18 +20,14 @@ HTMLTemplateElement::HTMLTemplateElement(already_AddRefed<nsINodeInfo>& aNodeInf
: nsGenericHTMLElement(aNodeInfo)
{
SetHasWeirdParserInsertionMode();
}
nsresult
HTMLTemplateElement::Init()
{
nsIDocument* contentsOwner = OwnerDoc()->GetTemplateContentsOwner();
NS_ENSURE_TRUE(contentsOwner, NS_ERROR_UNEXPECTED);
if (!contentsOwner) {
MOZ_CRASH("There should always be a template contents owner.");
}
mContent = contentsOwner->CreateDocumentFragment();
mContent->SetHost(this);
return NS_OK;
}
HTMLTemplateElement::~HTMLTemplateElement()
@ -77,7 +59,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLTemplateElement)
NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
NS_IMPL_ELEMENT_CLONE_WITH_INIT(HTMLTemplateElement)
NS_IMPL_ELEMENT_CLONE(HTMLTemplateElement)
JSObject*
HTMLTemplateElement::WrapNode(JSContext *aCx)

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

@ -28,8 +28,6 @@ public:
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
nsresult Init();
DocumentFragment* Content()
{
return mContent;

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

@ -13,6 +13,7 @@
#include "mozilla/Mutex.h"
#include <algorithm>
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "soundtouch/SoundTouch.h"
#include "Latency.h"
@ -72,6 +73,16 @@ bool AudioStream::sCubebLatencyPrefSet;
}
}
/*static*/ bool AudioStream::GetFirstStream()
{
static bool sFirstStream = true;
StaticMutexAutoLock lock(sMutex);
bool result = sFirstStream;
sFirstStream = false;
return result;
}
/*static*/ double AudioStream::GetVolumeScale()
{
StaticMutexAutoLock lock(sMutex);
@ -384,6 +395,9 @@ AudioStream::Init(int32_t aNumChannels, int32_t aRate,
const dom::AudioChannel aAudioChannel,
LatencyRequest aLatencyRequest)
{
mStartTime = TimeStamp::Now();
mIsFirst = GetFirstStream();
if (!GetCubebContext() || aNumChannels < 0 || aRate < 0) {
return NS_ERROR_FAILURE;
}
@ -494,6 +508,14 @@ AudioStream::OpenCubeb(cubeb_stream_params &aParams,
}
}
if (!mStartTime.IsNull()) {
TimeDuration timeDelta = TimeStamp::Now() - mStartTime;
LOG(("AudioStream creation time %sfirst: %u ms", mIsFirst ? "" : "not ",
(uint32_t) timeDelta.ToMilliseconds()));
Telemetry::Accumulate(mIsFirst ? Telemetry::AUDIOSTREAM_FIRST_OPEN_MS :
Telemetry::AUDIOSTREAM_LATER_OPEN_MS, timeDelta.ToMilliseconds());
}
return NS_OK;
}

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

@ -307,6 +307,7 @@ private:
static void PrefChanged(const char* aPref, void* aClosure);
static double GetVolumeScale();
static bool GetFirstStream();
static cubeb* GetCubebContext();
static cubeb* GetCubebContextUnlocked();
static uint32_t GetCubebLatency();
@ -423,6 +424,7 @@ private:
StreamState mState;
bool mNeedsStart; // needed in case Start() is called before cubeb is open
bool mIsFirst;
// This mutex protects the static members below.
static StaticMutex sMutex;

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

@ -80,7 +80,7 @@ OMXCodecProxy::~OMXCodecProxy()
IPCThreadState::self()->flushCommands();
if (mManagerService.get() && mClient.get()) {
mManagerService->cancelClient(mClient);
mManagerService->cancelClient(mClient, IMediaResourceManagerService::HW_VIDEO_DECODER);
}
mSource.clear();
@ -126,7 +126,7 @@ void OMXCodecProxy::requestResource()
return;
}
mManagerService->requestMediaResource(mClient, MediaResourceManagerClient::HW_VIDEO_DECODER);
mManagerService->requestMediaResource(mClient, IMediaResourceManagerService::HW_VIDEO_DECODER, true /* will wait */);
}
bool OMXCodecProxy::IsWaitingResources()

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

@ -34,6 +34,32 @@ using namespace mozilla::layers;
namespace android {
bool
OMXCodecReservation::ReserveOMXCodec()
{
if (!mManagerService.get()) {
sp<MediaResourceManagerClient::EventListener> listener = this;
mClient = new MediaResourceManagerClient(listener);
mManagerService = mClient->getMediaResourceManagerService();
if (!mManagerService.get()) {
mClient = nullptr;
return true; // not really in use, but not usable
}
}
return (mManagerService->requestMediaResource(mClient, mType, false) == OK); // don't wait
}
void
OMXCodecReservation::ReleaseOMXCodec()
{
if (!mManagerService.get() || !mClient.get()) {
return;
}
mManagerService->cancelClient(mClient, mType);
}
OMXAudioEncoder*
OMXCodecWrapper::CreateAACEncoder()
{

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

@ -7,6 +7,7 @@
#define OMXCodecWrapper_h_
#include <gui/Surface.h>
#include <utils/RefBase.h>
#include <stagefright/foundation/ABuffer.h>
#include <stagefright/foundation/AMessage.h>
#include <stagefright/MediaCodec.h>
@ -15,10 +16,45 @@
#include "GonkNativeWindow.h"
#include "GonkNativeWindowClient.h"
#include "IMediaResourceManagerService.h"
#include "MediaResourceManagerClient.h"
#include <speex/speex_resampler.h>
namespace android {
// Wrapper class for managing HW codec reservations
class OMXCodecReservation : public MediaResourceManagerClient::EventListener
{
public:
OMXCodecReservation(bool aEncoder)
{
mType = aEncoder ? IMediaResourceManagerService::HW_VIDEO_ENCODER :
IMediaResourceManagerService::HW_VIDEO_DECODER;
}
virtual ~OMXCodecReservation()
{
ReleaseOMXCodec();
}
/** Reserve the Encode or Decode resource for this instance */
virtual bool ReserveOMXCodec();
/** Release the Encode or Decode resource for this instance */
virtual void ReleaseOMXCodec();
// MediaResourceManagerClient::EventListener
virtual void statusChanged(int event) {}
private:
IMediaResourceManagerService::ResourceType mType;
sp<MediaResourceManagerClient> mClient;
sp<IMediaResourceManagerService> mManagerService;
};
class OMXAudioEncoder;
class OMXVideoEncoder;

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

@ -34,20 +34,23 @@ public:
{
}
virtual void requestMediaResource(const sp<IMediaResourceManagerClient>& client, int resourceType)
virtual status_t requestMediaResource(const sp<IMediaResourceManagerClient>& client, int resourceType, bool willWait)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaResourceManagerService::getInterfaceDescriptor());
data.writeStrongBinder(client->asBinder());
data.writeInt32(resourceType);
data.writeInt32(willWait ? 1 : 0);
remote()->transact(REQUEST_MEDIA_RESOURCE, data, &reply);
return reply.readInt32();
}
virtual status_t cancelClient(const sp<IMediaResourceManagerClient>& client)
virtual status_t cancelClient(const sp<IMediaResourceManagerClient>& client, int resourceType)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaResourceManagerService::getInterfaceDescriptor());
data.writeStrongBinder(client->asBinder());
data.writeInt32(resourceType);
remote()->transact(DEREGISTER_CLIENT, data, &reply);
return reply.readInt32();
}
@ -66,14 +69,17 @@ status_t BnMediaResourceManagerService::onTransact(
CHECK_INTERFACE(IMediaResourceManagerService, data, reply);
sp<IMediaResourceManagerClient> client = interface_cast<IMediaResourceManagerClient>(data.readStrongBinder());
int resourceType = data.readInt32();
requestMediaResource(client, resourceType);
bool willWait = (data.readInt32() == 1);
status_t result = requestMediaResource(client, resourceType, willWait);
reply->writeInt32(result);
return NO_ERROR;
} break;
case DEREGISTER_CLIENT: {
CHECK_INTERFACE(IMediaResourceManagerService, data, reply);
sp<IMediaResourceManagerClient> client = interface_cast<IMediaResourceManagerClient>(data.readStrongBinder());
cancelClient(client);
reply->writeInt32(NO_ERROR);
int resourceType = data.readInt32();
status_t result = cancelClient(client, resourceType);
reply->writeInt32(result);
return NO_ERROR;
} break;
default:

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

@ -22,10 +22,36 @@ class IMediaResourceManagerService : public IInterface
public:
DECLARE_META_INTERFACE(MediaResourceManagerService);
// Enumeration for the resource types
enum ResourceType {
HW_VIDEO_DECODER = 0,
HW_AUDIO_DECODER, // Not supported currently.
HW_VIDEO_ENCODER,
HW_CAMERA, // Not supported currently.
NUM_OF_RESOURCE_TYPES,
INVALID_RESOURCE_TYPE = -1
};
enum ErrorCode {
RESOURCE_NOT_AVAILABLE = -EAGAIN
};
// Request a media resource for IMediaResourceManagerClient.
virtual void requestMediaResource(const sp<IMediaResourceManagerClient>& client, int resourceType) = 0;
// client is the binder that service will notify (through
// IMediaResourceManagerClient::statusChanged()) when request status changed.
// resourceType is type of resource that client would like to request.
// willWait indicates that, when the resource is not currently available
// (i.e., already in use by another client), if the client wants to wait. If
// true, client will be put into a (FIFO) waiting list and be notified when
// resource is available.
// For unsupported types, this function returns BAD_TYPE. For supported
// types, it always returns OK when willWait is true; otherwise it will
// return true when resouce is available, or RESOURCE_NOT_AVAILABLE when
// resouce is in use.
virtual status_t requestMediaResource(const sp<IMediaResourceManagerClient>& client, int resourceType, bool willWait) = 0;
// Cancel a media resource request and a resource allocated to IMediaResourceManagerClient.
virtual status_t cancelClient(const sp<IMediaResourceManagerClient>& client) = 0;
// Client must call this function after it's done with the media resource requested.
virtual status_t cancelClient(const sp<IMediaResourceManagerClient>& client, int resourceType) = 0;
};

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

@ -22,12 +22,6 @@ public:
CLIENT_STATE_RESOURCE_ASSIGNED,
CLIENT_STATE_SHUTDOWN
};
// Enumeration for the resource types
enum ResourceType {
HW_VIDEO_DECODER,
HW_AUDIO_DECODER,
HW_CAMERA
};
struct EventListener : public virtual RefBase {
// Notifies a change of media resource request status.

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

@ -7,6 +7,8 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaResourceManagerService"
#include <mozilla/Assertions.h>
#include <binder/IServiceManager.h>
#include <media/stagefright/foundation/AMessage.h>
#include <utils/Log.h>
@ -16,14 +18,16 @@
namespace android {
const char* MediaResourceManagerService::kMsgKeyResourceType = "res-type";
/* static */
void MediaResourceManagerService::instantiate() {
defaultServiceManager()->addService(
String16("media.resource_manager"), new MediaResourceManagerService());
String16("media.resource_manager"),
new MediaResourceManagerService());
}
MediaResourceManagerService::MediaResourceManagerService()
: mVideoDecoderCount(VIDEO_DECODER_COUNT)
{
mLooper = new ALooper;
mLooper->setName("MediaResourceManagerService");
@ -49,99 +53,319 @@ void MediaResourceManagerService::binderDied(const wp<IBinder>& who)
Mutex::Autolock autoLock(mLock);
sp<IBinder> binder = who.promote();
if (binder != NULL) {
cancelClientLocked(binder);
mResources.forgetClient(binder);
}
}
}
void MediaResourceManagerService::requestMediaResource(const sp<IMediaResourceManagerClient>& client, int resourceType)
status_t MediaResourceManagerService::requestMediaResource(const sp<IMediaResourceManagerClient>& client,
int resourceType, bool willWait)
{
if (resourceType != MediaResourceManagerClient::HW_VIDEO_DECODER) {
// Support only HW_VIDEO_DECODER
return;
ResourceType type = static_cast<ResourceType>(resourceType);
// Support only HW_VIDEO_DECODER and HW_VIDEO_ENCODER.
switch (type) {
case HW_VIDEO_DECODER:
case HW_VIDEO_ENCODER:
break;
default:
// Type not supported.
return BAD_TYPE;
}
{
Mutex::Autolock autoLock(mLock);
sp<IBinder> binder = client->asBinder();
mVideoCodecRequestQueue.push_back(binder);
binder->linkToDeath(this);
}
Mutex::Autolock autoLock(mLock);
sp<AMessage> notify =
new AMessage(kNotifyRequest, mReflector->id());
// Must know if it will be granted or not - if there are enough unfufilled requests to
// use up the resource, fail. Otherwise we know that enqueuing under lock will succeed.
if (!willWait &&
(mResources.findAvailableResource(type, mResources.countRequests(type) + 1) ==
NAME_NOT_FOUND)) {
return RESOURCE_NOT_AVAILABLE;
}
// We could early-return here without enqueuing IF we can do the rest of
// the allocation safely here. However, enqueuing ensures there's only
// one copy of that code, and that any callbacks are made from the same
// context.
sp<IBinder> binder = client->asBinder();
mResources.enqueueRequest(binder, type);
binder->linkToDeath(this);
sp<AMessage> notify = new AMessage(kNotifyRequest, mReflector->id());
notify->setInt32(kMsgKeyResourceType, resourceType);
// Post AMessage to MediaResourceManagerService via ALooper.
notify->post();
return OK;
}
status_t MediaResourceManagerService::cancelClient(const sp<IMediaResourceManagerClient>& client)
status_t MediaResourceManagerService::cancelClient(const sp<IMediaResourceManagerClient>& client,
int resourceType)
{
{
Mutex::Autolock autoLock(mLock);
sp<IBinder> binder = client->asBinder();
cancelClientLocked(binder);
}
Mutex::Autolock autoLock(mLock);
sp<AMessage> notify =
new AMessage(kNotifyRequest, mReflector->id());
// Post AMessage to MediaResourceManagerService via ALooper.
sp<IBinder> binder = client->asBinder();
cancelClientLocked(binder, static_cast<ResourceType>(resourceType));
sp<AMessage> notify = new AMessage(kNotifyRequest, mReflector->id());
notify->setInt32(kMsgKeyResourceType, resourceType);
// Next!
// Note: since we held the lock while releasing and then posting, if there is
// a queue, no willWait==false entries can jump into the queue thinking they'll
// get the resource.
notify->post();
return NO_ERROR;
}
// Extract resource type from message.
static int32_t getResourceType(const sp<AMessage>& message)
{
int32_t resourceType = MediaResourceManagerService::INVALID_RESOURCE_TYPE;
return message->findInt32(MediaResourceManagerService::kMsgKeyResourceType, &resourceType) ?
resourceType : MediaResourceManagerService::INVALID_RESOURCE_TYPE;
}
// Called on ALooper thread.
void MediaResourceManagerService::onMessageReceived(const sp<AMessage> &msg)
{
Mutex::Autolock autoLock(mLock);
ResourceType type = static_cast<ResourceType>(getResourceType(msg));
// Exit if no request.
if (mVideoCodecRequestQueue.empty()) {
// Note: a message is sent both for "I added an entry to the queue"
// (which may succeed, typically if the queue is empty), and for "I gave
// up the resource", in which case it's "give to the next waiting client,
// or no one".
// Exit if no resource is available, but leave the client in the waiting
// list.
int found = mResources.findAvailableResource(type);
if (found == NAME_NOT_FOUND) {
return;
}
// Check if resource is available
int found = -1;
for (int i=0 ; i<mVideoDecoderCount ; i++) {
if (!mVideoDecoderSlots[i].mClient.get()) {
// Exit if no request.
if (!mResources.hasRequest(type)) {
return;
}
const sp<IBinder>& req = mResources.nextRequest(type);
mResources.aquireResource(req, type, found);
// Notify resource assignment to the client.
sp<IMediaResourceManagerClient> client = interface_cast<IMediaResourceManagerClient>(req);
client->statusChanged(MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED);
mResources.dequeueRequest(type);
}
void MediaResourceManagerService::cancelClientLocked(const sp<IBinder>& binder,
ResourceType resourceType)
{
mResources.forgetClient(binder, resourceType);
binder->unlinkToDeath(this);
}
MediaResourceManagerService::ResourceTable::ResourceTable()
{
// Populate types of resources.
for (int type = 0; type < NUM_OF_RESOURCE_TYPES; type++) {
ssize_t index = mMap.add(static_cast<ResourceType>(type), Resources());
Resources& resources = mMap.editValueAt(index);
int available;
switch (type) {
case HW_VIDEO_DECODER:
available = VIDEO_DECODER_COUNT;
break;
case HW_VIDEO_ENCODER:
available = VIDEO_ENCODER_COUNT;
break;
default:
available = 0;
break;
}
resources.mSlots.insertAt(0, available);
}
}
MediaResourceManagerService::ResourceTable::~ResourceTable() {
// Remove resouces.
mMap.clear();
}
bool MediaResourceManagerService::ResourceTable::supportsType(ResourceType type)
{
return mMap.indexOfKey(type) != NAME_NOT_FOUND;
}
ssize_t MediaResourceManagerService::ResourceTable::findAvailableResource(ResourceType type,
size_t numberNeeded)
{
MOZ_ASSERT(numberNeeded > 0);
ssize_t found = mMap.indexOfKey(type);
if (found == NAME_NOT_FOUND) {
// Unsupported type.
return found;
}
const Slots& slots = mMap.valueAt(found).mSlots;
found = NAME_NOT_FOUND;
for (size_t i = 0; i < slots.size(); i++) {
if (slots[i].mClient != nullptr) {
// Already in use.
continue;
}
if (--numberNeeded == 0) {
found = i;
break;
}
}
// Exit if no resource is available.
if (found == -1) {
return;
}
// Assign resource to IMediaResourceManagerClient
Fifo::iterator front(mVideoCodecRequestQueue.begin());
mVideoDecoderSlots[found].mClient = *front;
mVideoCodecRequestQueue.erase(front);
// Notify resource assignment to the client.
sp<IMediaResourceManagerClient> client = interface_cast<IMediaResourceManagerClient>(mVideoDecoderSlots[found].mClient);
client->statusChanged(MediaResourceManagerClient::CLIENT_STATE_RESOURCE_ASSIGNED);
return found;
}
void MediaResourceManagerService::cancelClientLocked(const sp<IBinder>& binder)
bool MediaResourceManagerService::ResourceTable::isOwnedByClient(const sp<IBinder>& client,
ResourceType type,
size_t index)
{
// Clear the request from request queue.
Fifo::iterator it(mVideoCodecRequestQueue.begin());
while (it != mVideoCodecRequestQueue.end()) {
if ((*it).get() == binder.get()) {
mVideoCodecRequestQueue.erase(it);
ResourceSlot* slot = resourceOfTypeAt(type, index);
return slot && slot->mClient == client;
}
status_t MediaResourceManagerService::ResourceTable::aquireResource(const sp<IBinder>& client,
ResourceType type,
size_t index)
{
ResourceSlot* slot = resourceOfTypeAt(type, index);
// Resouce should not be in use.
MOZ_ASSERT(slot && slot->mClient == nullptr);
if (!slot) {
return NAME_NOT_FOUND;
} else if (slot->mClient != nullptr) {
// Resource already in use by other client.
return PERMISSION_DENIED;
}
slot->mClient = client;
return OK;
}
MediaResourceManagerService::ResourceSlot*
MediaResourceManagerService::ResourceTable::resourceOfTypeAt(ResourceType type,
size_t index)
{
ssize_t found = mMap.indexOfKey(type);
if (found == NAME_NOT_FOUND) {
// Unsupported type.
return nullptr;
}
Slots& slots = mMap.editValueAt(found).mSlots;
MOZ_ASSERT(index < slots.size());
if (index >= slots.size()) {
// Index out of range.
return nullptr;
}
return &(slots.editItemAt(index));
}
bool MediaResourceManagerService::ResourceTable::hasRequest(ResourceType type)
{
ssize_t found = mMap.indexOfKey(type);
if (found == NAME_NOT_FOUND) {
// Unsupported type.
return nullptr;
}
const Fifo& queue = mMap.valueAt(found).mRequestQueue;
return !queue.empty();
}
uint32_t MediaResourceManagerService::ResourceTable::countRequests(ResourceType type)
{
ssize_t found = mMap.indexOfKey(type);
if (found == NAME_NOT_FOUND) {
// Unsupported type.
return 0;
}
const Fifo& queue = mMap.valueAt(found).mRequestQueue;
return queue.size();
}
const sp<IBinder>& MediaResourceManagerService::ResourceTable::nextRequest(ResourceType type)
{
ssize_t found = mMap.indexOfKey(type);
if (found == NAME_NOT_FOUND) {
// Unsupported type.
return nullptr;
}
const Fifo& queue = mMap.valueAt(found).mRequestQueue;
return *(queue.begin());
}
status_t MediaResourceManagerService::ResourceTable::enqueueRequest(const sp<IBinder>& client,
ResourceType type)
{
ssize_t found = mMap.indexOfKey(type);
if (found == NAME_NOT_FOUND) {
// Unsupported type.
return found;
}
mMap.editValueAt(found).mRequestQueue.push_back(client);
return OK;
}
status_t MediaResourceManagerService::ResourceTable::dequeueRequest(ResourceType type)
{
ssize_t found = mMap.indexOfKey(type);
if (found == NAME_NOT_FOUND) {
// Unsupported type.
return found;
}
Fifo& queue = mMap.editValueAt(found).mRequestQueue;
queue.erase(queue.begin());
return OK;
}
status_t MediaResourceManagerService::ResourceTable::forgetClient(const sp<IBinder>& client)
{
// Traverse all resources.
for (int i = 0; i < mMap.size(); i++) {
forgetClient(client, mMap.keyAt(i));
}
return OK;
}
status_t MediaResourceManagerService::ResourceTable::forgetClient(const sp<IBinder>& client, ResourceType type)
{
MOZ_ASSERT(supportsType(type));
Resources& resources = mMap.editValueFor(type);
// Remove pending requests for given client.
Fifo& queue = resources.mRequestQueue;
Fifo::iterator it(queue.begin());
while (it != queue.end()) {
if ((*it).get() == client.get()) {
queue.erase(it);
break;
}
it++;
}
// Clear the client from the resource
for (int i=0 ; i<mVideoDecoderCount ; i++) {
if (mVideoDecoderSlots[i].mClient.get() == binder.get()) {
mVideoDecoderSlots[i].mClient = NULL;
// Revoke ownership for given client.
Slots& slots = resources.mSlots;
for (int i = 0; i < slots.size(); i++) {
ResourceSlot& slot = slots.editItemAt(i);
if (client.get() == slot.mClient.get()) {
slot.mClient = nullptr;
}
}
binder->unlinkToDeath(this);
return OK;
}
}; // namespace android

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

@ -10,8 +10,10 @@
#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/foundation/AHandlerReflector.h>
#include <media/stagefright/foundation/ALooper.h>
#include <utils/KeyedVector.h>
#include <utils/List.h>
#include <utils/RefBase.h>
#include <utils/Vector.h>
#include "IMediaResourceManagerClient.h"
#include "IMediaResourceManagerService.h"
@ -20,20 +22,27 @@ namespace android {
/**
* Manage permissions of using media resources(hw decoder, hw encoder, camera)
* XXX Current implementaion support only one hw video decoder.
* XXX Current implementation supports only one hw video codec.
* Need to extend to support multiple instance and other resources.
*/
class MediaResourceManagerService: public BnMediaResourceManagerService,
public IBinder::DeathRecipient
{
public:
// The maximum number of hardware decoders available.
enum { VIDEO_DECODER_COUNT = 1 };
enum {
kNotifyRequest = 'noti'
// The maximum number of hardware resoureces available.
enum
{
VIDEO_DECODER_COUNT = 1,
VIDEO_ENCODER_COUNT = 1
};
enum
{
kNotifyRequest = 'noti',
};
static const char* kMsgKeyResourceType;
// Instantiate MediaResourceManagerService and register to service manager.
// If service manager is not present, wait until service manager becomes present.
static void instantiate();
@ -42,8 +51,10 @@ public:
virtual void binderDied(const wp<IBinder>& who);
// derived from IMediaResourceManagerService
virtual void requestMediaResource(const sp<IMediaResourceManagerClient>& client, int resourceType);
virtual status_t cancelClient(const sp<IMediaResourceManagerClient>& client);
virtual status_t requestMediaResource(const sp<IMediaResourceManagerClient>& client,
int resourceType, bool willWait);
virtual status_t cancelClient(const sp<IMediaResourceManagerClient>& client,
int resourceType);
// Receive a message from AHandlerReflector.
// Called on ALooper thread.
@ -53,30 +64,54 @@ protected:
MediaResourceManagerService();
virtual ~MediaResourceManagerService();
protected:
private:
// Represent a media resouce.
// Hold a IMediaResourceManagerClient that got a media resource as IBinder.
struct ResourceSlot {
ResourceSlot ()
{
}
sp<IBinder> mClient;
};
struct ResourceSlot
{
sp<IBinder> mClient;
};
typedef Vector<ResourceSlot> Slots;
void cancelClientLocked(const sp<IBinder>& binder);
// mVideoDecoderSlots is the array of slots that represent a media resource.
ResourceSlot mVideoDecoderSlots[VIDEO_DECODER_COUNT];
// The maximum number of hardware decoders available on the device.
int mVideoDecoderCount;
// The lock protects mVideoDecoderSlots and mVideoCodecRequestQueue called
// from multiple threads.
Mutex mLock;
typedef List<sp<IBinder> > Fifo;
// Queue of media resource requests.
// Hold IMediaResourceManagerClient that requesting a media resource as IBinder.
Fifo mVideoCodecRequestQueue;
struct Resources
{
// Queue of media resource requests. Hold IMediaResourceManagerClient that
// requesting a media resource as IBinder.
Fifo mRequestQueue;
// All resources that can be requested. Hold |ResourceSlot|s that track
// their usage.
Slots mSlots;
};
typedef KeyedVector<ResourceType, Resources> ResourcesMap;
// Manages requests from clients and availability of resources.
class ResourceTable
{
ResourceTable();
~ResourceTable();
// Resource operations.
bool supportsType(ResourceType type);
ssize_t findAvailableResource(ResourceType type, size_t number_needed = 1);
bool isOwnedByClient(const sp<IBinder>& client, ResourceType type, size_t index);
status_t aquireResource(const sp<IBinder>& client, ResourceType type, size_t index);
ResourceSlot* resourceOfTypeAt(ResourceType type, size_t index);
// Request operations.
bool hasRequest(ResourceType type);
uint32_t countRequests(ResourceType type);
const sp<IBinder>& nextRequest(ResourceType type);
status_t enqueueRequest(const sp<IBinder>& client, ResourceType type);
status_t dequeueRequest(ResourceType type);
status_t forgetClient(const sp<IBinder>& client, ResourceType type);
status_t forgetClient(const sp<IBinder>& client);
friend class MediaResourceManagerService;
// A map for all types of supported resources.
ResourcesMap mMap;
};
void cancelClientLocked(const sp<IBinder>& binder, ResourceType resourceType);
// ALooper is a message loop used in stagefright.
// It creates a thread for messages and handles messages in the thread.
@ -88,6 +123,11 @@ protected:
// http://developer.android.com/reference/android/os/Handler.html
sp<AHandlerReflector<MediaResourceManagerService> > mReflector;
// The lock protects manager operations called from multiple threads.
Mutex mLock;
// Keeps all the records.
ResourceTable mResources;
};
}; // namespace android

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

@ -4,6 +4,14 @@
# 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/.
EXPORTS += [
'IMediaResourceManagerClient.h',
'IMediaResourceManagerDeathNotifier.h',
'IMediaResourceManagerService.h',
'MediaResourceManagerClient.h',
'MediaResourceManagerService.h',
]
SOURCES += [
'IMediaResourceManagerClient.cpp',
'IMediaResourceManagerDeathNotifier.cpp',

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

@ -227,7 +227,6 @@ NS_IMPL_CYCLE_COLLECTION_INHERITED(AudioDestinationNode, AudioNode,
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioDestinationNode)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgentCallback)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END_INHERITING(AudioNode)
NS_IMPL_ADDREF_INHERITED(AudioDestinationNode, AudioNode)

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

@ -12,7 +12,6 @@
#include "nsIDOMEventListener.h"
#include "nsIAudioChannelAgent.h"
#include "AudioChannelCommon.h"
#include "nsWeakReference.h"
namespace mozilla {
namespace dom {
@ -22,7 +21,6 @@ class AudioContext;
class AudioDestinationNode : public AudioNode
, public nsIDOMEventListener
, public nsIAudioChannelAgentCallback
, public nsSupportsWeakReference
, public MainThreadMediaStreamListener
{
public:

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

@ -9,11 +9,14 @@
#include "AudioNodeStream.h"
#include "AudioNodeEngine.h"
#include "mozilla/dom/AudioParam.h"
#include "mozilla/Services.h"
#include "nsIObserverService.h"
namespace mozilla {
namespace dom {
static const uint32_t INVALID_PORT = 0xffffffff;
static uint32_t gId = 0;
NS_IMPL_CYCLE_COLLECTION_CLASS(AudioNode)
@ -49,6 +52,7 @@ AudioNode::Release()
}
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioNode)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
AudioNode::AudioNode(AudioContext* aContext,
@ -60,6 +64,10 @@ AudioNode::AudioNode(AudioContext* aContext,
, mChannelCount(aChannelCount)
, mChannelCountMode(aChannelCountMode)
, mChannelInterpretation(aChannelInterpretation)
, mId(gId++)
#ifdef DEBUG
, mDemiseNotified(false)
#endif
{
MOZ_ASSERT(aContext);
DOMEventTargetHelper::BindToOwner(aContext->GetParentObject());
@ -72,6 +80,10 @@ AudioNode::~AudioNode()
MOZ_ASSERT(mInputNodes.IsEmpty());
MOZ_ASSERT(mOutputNodes.IsEmpty());
MOZ_ASSERT(mOutputParams.IsEmpty());
#ifdef DEBUG
MOZ_ASSERT(mDemiseNotified,
"The webaudio-node-demise notification must have been sent");
#endif
if (mContext) {
mContext->UpdateNodeCount(-1);
}
@ -385,6 +397,16 @@ AudioNode::DestroyMediaStream()
mStream->Destroy();
mStream = nullptr;
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
if (obs) {
nsAutoString id;
id.AppendPrintf("%u", mId);
obs->NotifyObservers(nullptr, "webaudio-node-demise", id.get());
}
#ifdef DEBUG
mDemiseNotified = true;
#endif
}
}

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

@ -16,6 +16,7 @@
#include "MediaStreamGraph.h"
#include "WebAudioUtils.h"
#include "mozilla/MemoryReporting.h"
#include "nsWeakReference.h"
namespace mozilla {
@ -82,7 +83,8 @@ private:
* still alive, and will still be alive when it receives a message from the
* engine.
*/
class AudioNode : public DOMEventTargetHelper
class AudioNode : public DOMEventTargetHelper,
public nsSupportsWeakReference
{
protected:
// You can only use refcounting to delete this object
@ -133,6 +135,8 @@ public:
virtual uint16_t NumberOfInputs() const { return 1; }
virtual uint16_t NumberOfOutputs() const { return 1; }
uint32_t Id() const { return mId; }
uint32_t ChannelCount() const { return mChannelCount; }
virtual void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv)
{
@ -266,6 +270,12 @@ private:
uint32_t mChannelCount;
ChannelCountMode mChannelCountMode;
ChannelInterpretation mChannelInterpretation;
const uint32_t mId;
#ifdef DEBUG
// In debug builds, check to make sure that the node demise notification has
// been properly sent before the node is destroyed.
bool mDemiseNotified;
#endif
};
}

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

@ -42,7 +42,7 @@ MediaStreamAudioSourceNode::MediaStreamAudioSourceNode(AudioContext* aContext,
ProcessedMediaStream* outputStream = static_cast<ProcessedMediaStream*>(mStream.get());
mInputPort = outputStream->AllocateInputPort(aMediaStream->GetStream(),
MediaInputPort::FLAG_BLOCK_INPUT);
mInputStream->AddConsumerToKeepAlive(this);
mInputStream->AddConsumerToKeepAlive(static_cast<nsIDOMEventTarget*>(this));
PrincipalChanged(mInputStream); // trigger enabling/disabling of the connector
mInputStream->AddPrincipalChangeObserver(this);

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

@ -0,0 +1,3 @@
[DEFAULT]
[test_AudioNodeDevtoolsAPI.html]

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

@ -8,3 +8,7 @@ MOCHITEST_MANIFESTS += [
'blink/mochitest.ini',
'mochitest.ini',
]
MOCHITEST_CHROME_MANIFESTS += [
'chrome.ini'
]

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

@ -0,0 +1,57 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test the devtool AudioNode API</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
Components.utils.import('resource://gre/modules/Services.jsm');
SimpleTest.waitForExplicitFinish();
var ac = new AudioContext();
var ids;
var weak;
(function() {
var src1 = ac.createBufferSource();
var src2 = ac.createBufferSource();
ok(src2.id > src1.id, "The ID should be monotonic");
ok(src1.id > ac.destination.id, "The ID of the destination node should be the lowest");
ids = [src1.id, src2.id];
weak = Components.utils.getWeakReference(src1);
is(weak.get(), src1, "The node should support a weak reference");
})();
function observer(subject, topic, data) {
var id = parseInt(data);
var index = ids.indexOf(id);
if (index != -1) {
info("Dropping id " + id + " at index " + index);
ids.splice(index, 1);
if (ids.length == 0) {
SimpleTest.executeSoon(function() {
is(weak.get(), null, "The weak reference must be dropped now");
Services.obs.removeObserver(observer, "webaudio-node-demise");
SimpleTest.finish();
});
}
}
}
Services.obs.addObserver(observer, "webaudio-node-demise", false);
forceCC();
forceCC();
function forceCC() {
SpecialPowers.DOMWindowUtils.cycleCollect();
SpecialPowers.DOMWindowUtils.garbageCollect();
SpecialPowers.DOMWindowUtils.garbageCollect();
}
</script>
</pre>
</body>
</html>

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

@ -60,6 +60,7 @@
#include "mozilla/dom/CDATASection.h"
#include "mozilla/dom/Comment.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/HTMLTemplateElement.h"
#include "mozilla/dom/ProcessingInstruction.h"
using namespace mozilla::dom;
@ -848,7 +849,17 @@ nsXMLContentSink::PushContent(nsIContent *aContent)
StackNode *sn = mContentStack.AppendElement();
NS_ENSURE_TRUE(sn, NS_ERROR_OUT_OF_MEMORY);
sn->mContent = aContent;
nsIContent* contentToPush = aContent;
// When an XML parser would append a node to a template element, it
// must instead append it to the template element's template contents.
if (contentToPush->IsHTML(nsGkAtoms::_template)) {
HTMLTemplateElement* templateElement =
static_cast<HTMLTemplateElement*>(contentToPush);
contentToPush = templateElement->Content();
}
sn->mContent = contentToPush;
sn->mNumFlushed = 0;
return NS_OK;
}
@ -1076,8 +1087,13 @@ nsXMLContentSink::HandleEndElement(const char16_t *aName,
nsContentUtils::SplitExpatName(aName, getter_AddRefs(debugNameSpacePrefix),
getter_AddRefs(debugTagAtom),
&debugNameSpaceID);
NS_ASSERTION(content->NodeInfo()->Equals(debugTagAtom, debugNameSpaceID),
"Wrong element being closed");
// Check if we are closing a template element because template
// elements do not get pushed on the stack, the template
// element content is pushed instead.
bool isTemplateElement = debugTagAtom == nsGkAtoms::_template &&
debugNameSpaceID == kNameSpaceID_XHTML;
NS_ASSERTION(content->NodeInfo()->Equals(debugTagAtom, debugNameSpaceID) ||
isTemplateElement, "Wrong element being closed");
#endif
result = CloseElement(content);

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

@ -154,9 +154,13 @@ ArchiveRequest::ReaderReady(nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList,
rv = GetFileResult(cx, &result, aFileList);
break;
case GetFiles:
rv = GetFilesResult(cx, &result, aFileList);
break;
case GetFiles:
rv = GetFilesResult(cx, &result, aFileList);
break;
default:
rv = NS_ERROR_UNEXPECTED;
break;
}
if (NS_FAILED(rv)) {

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

@ -1497,7 +1497,7 @@ Navigator::GetFeature(const nsAString& aName)
if (XRE_GetProcessType() == GeckoProcessType_Default) {
uint32_t memLevel = mozilla::hal::GetTotalSystemMemoryLevel();
if (memLevel == 0) {
p->MaybeReject(NS_LITERAL_STRING("Abnormal"));
p->MaybeReject(NS_ERROR_NOT_AVAILABLE);
return p.forget();
}
p->MaybeResolve((int)memLevel);

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

@ -244,6 +244,7 @@ AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
, ScriptSettingsStackEntry(aGlobalObject, /* aCandidate = */ true)
, mAc(cx(), aGlobalObject->GetGlobalJSObject())
, mStack(ScriptSettingsStack::Ref())
, mWebIDLCallerPrincipal(nullptr)
{
MOZ_ASSERT(aGlobalObject);
MOZ_ASSERT_IF(!aCx, aIsMainThread); // cx is mandatory off-main-thread.

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

@ -179,7 +179,14 @@ public:
private:
JSAutoCompartment mAc;
dom::ScriptSettingsStack& mStack;
nsCOMPtr<nsIPrincipal> mWebIDLCallerPrincipal;
// It's safe to make this a weak pointer, since it's the subject principal
// when we go on the stack, so can't go away until after we're gone. In
// particular, this is only used from the CallSetup constructor, and only in
// the aIsJSImplementedWebIDL case. And in that case, the subject principal
// is the principal of the callee function that is part of the CallArgs just a
// bit up the stack, and which will outlive us. So we know the principal
// can't go away until then either.
nsIPrincipal* mWebIDLCallerPrincipal;
friend nsIPrincipal* GetWebIDLCallerPrincipal();
};

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

@ -2615,13 +2615,6 @@ OldBindingConstructorEnabled(const nsGlobalNameStruct *aStruct,
}
}
// Don't expose CSSSupportsRule unless @supports processing is enabled.
if (aStruct->mDOMClassInfoID == eDOMClassInfo_CSSSupportsRule_id) {
if (!CSSSupportsRule::PrefEnabled()) {
return false;
}
}
// Don't expose CSSFontFeatureValuesRule unless the pref is enabled
if (aStruct->mDOMClassInfoID == eDOMClassInfo_CSSFontFeatureValuesRule_id) {
return nsCSSFontFeatureValuesRule::PrefEnabled();

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

@ -3025,7 +3025,7 @@ nsDOMWindowUtils::GetFileId(JS::Handle<JS::Value> aFile, JSContext* aCx,
if (!aFile.isPrimitive()) {
JSObject* obj = aFile.toObjectOrNull();
FileHandle* fileHandle;
FileHandle* fileHandle = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(FileHandle, obj, fileHandle))) {
*aResult = fileHandle->GetFileId();
return NS_OK;

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

@ -1562,7 +1562,7 @@ class CGClassConstructor(CGAbstractStaticMethod):
ctorName=ctorName)
name = self._ctor.identifier.name
nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
nativeName = MakeNativeName(self.descriptor.binaryNameFor(name))
callGenerator = CGMethodCall(nativeName, True, self.descriptor,
self._ctor, isConstructor=True,
constructorName=ctorName)
@ -6947,7 +6947,7 @@ class CGSpecializedMethod(CGAbstractStaticMethod):
@staticmethod
def makeNativeName(descriptor, method):
name = method.identifier.name
return MakeNativeName(descriptor.binaryNames.get(name, name))
return MakeNativeName(descriptor.binaryNameFor(name))
class CGMethodPromiseWrapper(CGAbstractStaticMethod):
@ -7036,7 +7036,7 @@ class CGLegacyCallHook(CGAbstractBindingMethod):
def generate_code(self):
name = self._legacycaller.identifier.name
nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
nativeName = MakeNativeName(self.descriptor.binaryNameFor(name))
return CGMethodCall(nativeName, False, self.descriptor,
self._legacycaller)
@ -7287,7 +7287,7 @@ class CGSpecializedGetter(CGAbstractStaticMethod):
@staticmethod
def makeNativeName(descriptor, attr):
name = attr.identifier.name
nativeName = MakeNativeName(descriptor.binaryNames.get(name, name))
nativeName = MakeNativeName(descriptor.binaryNameFor(name))
# resultOutParam does not depend on whether resultAlreadyAddRefed is set
_, resultOutParam, _, _ = getRetvalDeclarationForType(attr.type,
descriptor,
@ -7390,7 +7390,7 @@ class CGSpecializedSetter(CGAbstractStaticMethod):
@staticmethod
def makeNativeName(descriptor, attr):
name = attr.identifier.name
return "Set" + MakeNativeName(descriptor.binaryNames.get(name, name))
return "Set" + MakeNativeName(descriptor.binaryNameFor(name))
class CGStaticSetter(CGAbstractStaticBindingMethod):
@ -9095,7 +9095,7 @@ class CGProxySpecialOperation(CGPerSignatureCall):
def __init__(self, descriptor, operation, checkFound=True, argumentMutableValue=None):
self.checkFound = checkFound
nativeName = MakeNativeName(descriptor.binaryNames.get(operation, operation))
nativeName = MakeNativeName(descriptor.binaryNameFor(operation))
operation = descriptor.operations[operation]
assert len(operation.signatures()) == 1
signature = operation.signatures()[0]
@ -12308,12 +12308,12 @@ def genConstructorBody(descriptor, initCall=""):
# We're always fallible
def callbackGetterName(attr, descriptor):
return "Get" + MakeNativeName(
descriptor.binaryNames.get(attr.identifier.name, attr.identifier.name))
descriptor.binaryNameFor(attr.identifier.name))
def callbackSetterName(attr, descriptor):
return "Set" + MakeNativeName(
descriptor.binaryNames.get(attr.identifier.name, attr.identifier.name))
descriptor.binaryNameFor(attr.identifier.name))
class CGJSImplGetter(CGJSImplMember):
@ -13052,7 +13052,7 @@ class CallbackOperationBase(CallbackMethod):
"""
def __init__(self, signature, jsName, nativeName, descriptor, singleOperation, rethrowContentException=False):
self.singleOperation = singleOperation
self.methodName = descriptor.binaryNames.get(jsName, jsName)
self.methodName = descriptor.binaryNameFor(jsName)
CallbackMethod.__init__(self, signature, nativeName, descriptor, singleOperation, rethrowContentException)
def getThisDecl(self):
@ -13107,7 +13107,7 @@ class CallbackOperation(CallbackOperationBase):
jsName = method.identifier.name
CallbackOperationBase.__init__(self, signature,
jsName,
MakeNativeName(descriptor.binaryNames.get(jsName, jsName)),
MakeNativeName(descriptor.binaryNameFor(jsName)),
descriptor, descriptor.interface.isSingleOperationInterface(),
rethrowContentException=descriptor.interface.isJSImplemented())
@ -13151,8 +13151,7 @@ class CallbackGetter(CallbackAccessor):
return${errorReturn};
}
""",
attrName=self.descriptorProvider.binaryNames.get(self.attrName,
self.attrName),
attrName=self.descriptorProvider.binaryNameFor(self.attrName),
errorReturn=self.getDefaultRetval())
@ -13177,8 +13176,7 @@ class CallbackSetter(CallbackAccessor):
return${errorReturn};
}
""",
attrName=self.descriptorProvider.binaryNames.get(self.attrName,
self.attrName),
attrName=self.descriptorProvider.binaryNameFor(self.attrName),
errorReturn=self.getDefaultRetval())
def getArgcDecl(self):

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

@ -414,12 +414,9 @@ class Descriptor(DescriptorProvider):
for attribute in ['implicitJSContext', 'resultNotAddRefed']:
addExtendedAttribute(attribute, desc.get(attribute, {}))
self.binaryNames = desc.get('binaryNames', {})
if '__legacycaller' not in self.binaryNames:
self.binaryNames["__legacycaller"] = "LegacyCall"
if '__stringifier' not in self.binaryNames:
self.binaryNames["__stringifier"] = "Stringify"
self._binaryNames = desc.get('binaryNames', {})
self._binaryNames.setdefault('__legacycaller', 'LegacyCall')
self._binaryNames.setdefault('__stringifier', 'Stringify')
if not self.interface.isExternal():
self.permissions = dict()
@ -457,6 +454,9 @@ class Descriptor(DescriptorProvider):
config.maxProtoChainLength = max(config.maxProtoChainLength,
len(self.prototypeChain))
def binaryNameFor(self, name):
return self._binaryNames.get(name, name)
def hasInterfaceOrInterfacePrototypeObject(self):
# Forward-declared interfaces don't need either interface object or

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

@ -26,7 +26,7 @@ struct TypedArrayObjectStorage : AllTypedArraysBase {
protected:
JSObject* mObj;
TypedArrayObjectStorage(JSObject *obj) : mObj(obj)
TypedArrayObjectStorage() : mObj(nullptr)
{
}
@ -60,18 +60,8 @@ template<typename T,
struct TypedArray_base : public TypedArrayObjectStorage {
typedef T element_type;
TypedArray_base(JSObject* obj)
: TypedArrayObjectStorage(obj),
mData(nullptr),
mLength(0),
mComputed(false)
{
MOZ_ASSERT(obj != nullptr);
}
TypedArray_base()
: TypedArrayObjectStorage(nullptr),
mData(nullptr),
: mData(nullptr),
mLength(0),
mComputed(false)
{
@ -97,7 +87,7 @@ public:
inline bool Init(JSObject* obj)
{
MOZ_ASSERT(!inited());
DoInit(obj);
mObj = UnwrapArray(obj);
return inited();
}
@ -135,11 +125,6 @@ public:
}
protected:
inline void DoInit(JSObject* obj)
{
mObj = UnwrapArray(obj);
}
inline void ComputeData() const {
MOZ_ASSERT(inited());
if (!mComputed) {
@ -163,10 +148,6 @@ private:
typedef TypedArray_base<T, UnwrapArray, GetLengthAndData> Base;
public:
TypedArray(JSObject* obj)
: Base(obj)
{}
TypedArray()
: Base()
{}

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

@ -24,6 +24,9 @@
#include "BluetoothService.h"
#include "BluetoothUtils.h"
#define ERR_INVALID_ADAPTER_STATE "InvalidAdapterStateError"
#define ERR_CHANGE_ADAPTER_STATE "ChangeAdapterStateError"
using namespace mozilla;
using namespace mozilla::dom;
@ -121,6 +124,7 @@ public:
BluetoothReplyRunnable::ReleaseMembers();
mAdapterPtr = nullptr;
}
private:
nsRefPtr<BluetoothAdapter> mAdapterPtr;
};
@ -156,6 +160,38 @@ public:
}
};
class EnableDisableAdapterTask : public BluetoothReplyRunnable
{
public:
EnableDisableAdapterTask(Promise* aPromise)
: BluetoothReplyRunnable(nullptr)
, mPromise(aPromise)
{ }
bool
ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue)
{
/*
* It is supposed to be Promise<void> according to BluetoothAdapter.webidl,
* but we have to pass "true" since it is mandatory to pass an
* argument while calling MaybeResolve.
*/
mPromise->MaybeResolve(true);
aValue.setUndefined();
return true;
}
void
ReleaseMembers()
{
BluetoothReplyRunnable::ReleaseMembers();
mPromise = nullptr;
}
private:
nsRefPtr<Promise> mPromise;
};
static int kCreatePairedDeviceTimeout = 50000; // unit: msec
BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow* aWindow,
@ -164,12 +200,13 @@ BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow* aWindow,
, BluetoothPropertyContainer(BluetoothObjectType::TYPE_ADAPTER)
, mJsUuids(nullptr)
, mJsDeviceAddresses(nullptr)
// TODO: Change to Disabled after Bug 1006309 landed
, mState(BluetoothAdapterState::Enabled)
, mDiscoverable(false)
, mDiscovering(false)
, mPairable(false)
, mPowered(false)
, mIsRooted(false)
, mState(BluetoothAdapterState::Disabled)
{
MOZ_ASSERT(aWindow);
MOZ_ASSERT(IsDOMBinding());
@ -231,7 +268,11 @@ BluetoothAdapter::SetPropertyByValue(const BluetoothNamedValue& aValue)
{
const nsString& name = aValue.name();
const BluetoothValue& value = aValue.value();
if (name.EqualsLiteral("Name")) {
if (name.EqualsLiteral("State")) {
bool isEnabled = value.get_bool();
mState = isEnabled ? BluetoothAdapterState::Enabled
: BluetoothAdapterState::Disabled;
} else if (name.EqualsLiteral("Name")) {
mName = value.get_nsString();
} else if (name.EqualsLiteral("Address")) {
mAddress = value.get_nsString();
@ -669,19 +710,55 @@ BluetoothAdapter::SetPairingConfirmation(const nsAString& aDeviceAddress,
return request.forget();
}
/*
* TODO: Implement Enable/Disable functions
*/
already_AddRefed<Promise>
BluetoothAdapter::EnableDisable(bool aEnable)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
NS_ENSURE_TRUE(global, nullptr);
nsRefPtr<Promise> promise = new Promise(global);
// Make sure BluetoothService is available before modifying adapter state
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
promise->MaybeReject(ERR_CHANGE_ADAPTER_STATE);
return promise.forget();
}
if (aEnable) {
if (mState != BluetoothAdapterState::Disabled) {
promise->MaybeReject(ERR_INVALID_ADAPTER_STATE);
return promise.forget();
}
mState = BluetoothAdapterState::Enabling;
} else {
if (mState != BluetoothAdapterState::Enabled) {
promise->MaybeReject(ERR_INVALID_ADAPTER_STATE);
return promise.forget();
}
mState = BluetoothAdapterState::Disabling;
}
// TODO: Fire attr changed event for this state change
nsRefPtr<BluetoothReplyRunnable> result = new EnableDisableAdapterTask(promise);
if(NS_FAILED(bs->EnableDisable(aEnable, result))) {
promise->MaybeReject(ERR_CHANGE_ADAPTER_STATE);
}
return promise.forget();
}
already_AddRefed<Promise>
BluetoothAdapter::Enable()
{
return nullptr;
return EnableDisable(true);
}
already_AddRefed<Promise>
BluetoothAdapter::Disable()
{
return nullptr;
return EnableDisable(false);
}
already_AddRefed<DOMRequest>

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

@ -122,10 +122,9 @@ public:
SetAuthorization(const nsAString& aDeviceAddress, bool aAllow,
ErrorResult& aRv);
already_AddRefed<Promise>
Enable();
already_AddRefed<Promise>
Disable();
already_AddRefed<Promise> EnableDisable(bool aEnable);
already_AddRefed<Promise> Enable();
already_AddRefed<Promise> Disable();
already_AddRefed<DOMRequest>
Connect(BluetoothDevice& aDevice,

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

@ -163,14 +163,8 @@ BluetoothService::ToggleBtAck::Run()
sBluetoothService->SetEnabled(mEnabled);
sToggleInProgress = false;
nsAutoString signalName;
signalName = mEnabled ? NS_LITERAL_STRING("Enabled")
: NS_LITERAL_STRING("Disabled");
BluetoothSignal signal(signalName, NS_LITERAL_STRING(KEY_MANAGER), true);
sBluetoothService->DistributeSignal(signal);
// Event 'AdapterAdded' has to be fired after firing 'Enabled'
sBluetoothService->TryFiringAdapterAdded();
sBluetoothService->FireAdapterStateChanged(mEnabled);
return NS_OK;
}
@ -220,19 +214,6 @@ BluetoothService::~BluetoothService()
Cleanup();
}
PLDHashOperator
RemoveObserversExceptBluetoothManager
(const nsAString& key,
nsAutoPtr<BluetoothSignalObserverList>& value,
void* arg)
{
if (!key.EqualsLiteral(KEY_MANAGER)) {
return PL_DHASH_REMOVE;
}
return PL_DHASH_NEXT;
}
// static
BluetoothService*
BluetoothService::Create()
@ -384,7 +365,8 @@ BluetoothService::DistributeSignal(const BluetoothSignal& aSignal)
}
nsresult
BluetoothService::StartBluetooth(bool aIsStartup)
BluetoothService::StartBluetooth(bool aIsStartup,
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
@ -405,7 +387,7 @@ BluetoothService::StartBluetooth(bool aIsStartup)
*/
if (aIsStartup || !sBluetoothService->IsEnabled()) {
// Switch Bluetooth on
if (NS_FAILED(sBluetoothService->StartInternal())) {
if (NS_FAILED(sBluetoothService->StartInternal(aRunnable))) {
BT_WARNING("Bluetooth service failed to start!");
}
} else {
@ -420,7 +402,8 @@ BluetoothService::StartBluetooth(bool aIsStartup)
}
nsresult
BluetoothService::StopBluetooth(bool aIsStartup)
BluetoothService::StopBluetooth(bool aIsStartup,
BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
@ -466,7 +449,7 @@ BluetoothService::StopBluetooth(bool aIsStartup)
*/
if (aIsStartup || sBluetoothService->IsEnabled()) {
// Switch Bluetooth off
if (NS_FAILED(sBluetoothService->StopInternal())) {
if (NS_FAILED(sBluetoothService->StopInternal(aRunnable))) {
BT_WARNING("Bluetooth service failed to stop!");
}
} else {
@ -481,13 +464,15 @@ BluetoothService::StopBluetooth(bool aIsStartup)
}
nsresult
BluetoothService::StartStopBluetooth(bool aStart, bool aIsStartup)
BluetoothService::StartStopBluetooth(bool aStart,
bool aIsStartup,
BluetoothReplyRunnable* aRunnable)
{
nsresult rv;
if (aStart) {
rv = StartBluetooth(aIsStartup);
rv = StartBluetooth(aIsStartup, aRunnable);
} else {
rv = StopBluetooth(aIsStartup);
rv = StopBluetooth(aIsStartup, aRunnable);
}
return rv;
}
@ -504,17 +489,6 @@ BluetoothService::SetEnabled(bool aEnabled)
unused << childActors[index]->SendEnabled(aEnabled);
}
if (!aEnabled) {
/**
* Remove all handlers except BluetoothManager when turning off bluetooth
* since it is possible that the event 'onAdapterAdded' would be fired after
* BluetoothManagers of child process are registered. Please see Bug 827759
* for more details.
*/
mBluetoothSignalObserverTable.Enumerate(
RemoveObserversExceptBluetoothManager, nullptr);
}
/**
* mEnabled: real status of bluetooth
* aEnabled: expected status of bluetooth
@ -553,7 +527,7 @@ nsresult
BluetoothService::HandleStartupSettingsCheck(bool aEnable)
{
MOZ_ASSERT(NS_IsMainThread());
return StartStopBluetooth(aEnable, true);
return StartStopBluetooth(aEnable, true, nullptr);
}
nsresult
@ -610,37 +584,6 @@ BluetoothService::HandleSettingsChanged(const nsAString& aData)
}
SWITCH_BT_DEBUG(value.toBoolean());
return NS_OK;
}
// Second, check if the string is BLUETOOTH_ENABLED_SETTING
if (!JS_StringEqualsAscii(cx, key.toString(), BLUETOOTH_ENABLED_SETTING, &match)) {
MOZ_ASSERT(!JS_IsExceptionPending(cx));
return NS_ERROR_OUT_OF_MEMORY;
}
if (match) {
JS::Rooted<JS::Value> value(cx);
if (!JS_GetProperty(cx, obj, "value", &value)) {
MOZ_ASSERT(!JS_IsExceptionPending(cx));
return NS_ERROR_OUT_OF_MEMORY;
}
if (!value.isBoolean()) {
MOZ_ASSERT(false, "Expecting a boolean for 'bluetooth.enabled'!");
return NS_ERROR_UNEXPECTED;
}
if (sToggleInProgress || value.toBoolean() == IsEnabled()) {
// Nothing to do here.
return NS_OK;
}
sToggleInProgress = true;
nsresult rv = StartStopBluetooth(value.toBoolean(), false);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
@ -704,7 +647,7 @@ BluetoothService::HandleShutdown()
}
}
if (IsEnabled() && NS_FAILED(StopBluetooth(false))) {
if (IsEnabled() && NS_FAILED(StopBluetooth(false, nullptr))) {
MOZ_ASSERT(false, "Failed to deliver stop message!");
}
@ -785,6 +728,38 @@ BluetoothService::AdapterAddedReceived()
mAdapterAddedReceived = true;
}
/**
* Enable/Disable the local adapter.
*
* There is only one adapter on the mobile in current use cases.
* In addition, bluedroid couldn't enable/disable a single adapter.
* So currently we will turn on/off BT to enable/disable the adapter.
*
* TODO: To support enable/disable single adapter in the future,
* we will need to implement EnableDisableInternal for different stacks.
*/
nsresult
BluetoothService::EnableDisable(bool aEnable,
BluetoothReplyRunnable* aRunnable)
{
sToggleInProgress = true;
return StartStopBluetooth(aEnable, false, aRunnable);
}
void
BluetoothService::FireAdapterStateChanged(bool aEnable)
{
MOZ_ASSERT(NS_IsMainThread());
InfallibleTArray<BluetoothNamedValue> props;
BT_APPEND_NAMED_VALUE(props, "State", aEnable);
BluetoothValue value(props);
BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
NS_LITERAL_STRING(KEY_ADAPTER), value);
DistributeSignal(signal);
}
void
BluetoothService::Notify(const BluetoothSignal& aData)
{

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

@ -315,6 +315,28 @@ public:
void TryFiringAdapterAdded();
void AdapterAddedReceived();
void FireAdapterStateChanged(bool aEnable);
nsresult EnableDisable(bool aEnable,
BluetoothReplyRunnable* aRunnable);
/**
* Platform specific startup functions go here. Usually deals with member
* variables, so not static. Guaranteed to be called outside of main thread.
*
* @return NS_OK on correct startup, NS_ERROR_FAILURE otherwise
*/
virtual nsresult
StartInternal(BluetoothReplyRunnable* aRunnable) = 0;
/**
* Platform specific startup functions go here. Usually deals with member
* variables, so not static. Guaranteed to be called outside of main thread.
*
* @return NS_OK on correct startup, NS_ERROR_FAILURE otherwise
*/
virtual nsresult
StopInternal(BluetoothReplyRunnable* aRunnable) = 0;
protected:
BluetoothService() : mEnabled(false)
, mAdapterAddedReceived(false)
@ -330,31 +352,15 @@ protected:
Cleanup();
nsresult
StartBluetooth(bool aIsStartup);
StartBluetooth(bool aIsStartup, BluetoothReplyRunnable* aRunnable);
nsresult
StopBluetooth(bool aIsStartup);
StopBluetooth(bool aIsStartup, BluetoothReplyRunnable* aRunnable);
nsresult
StartStopBluetooth(bool aStart, bool aIsStartup);
/**
* Platform specific startup functions go here. Usually deals with member
* variables, so not static. Guaranteed to be called outside of main thread.
*
* @return NS_OK on correct startup, NS_ERROR_FAILURE otherwise
*/
virtual nsresult
StartInternal() = 0;
/**
* Platform specific startup functions go here. Usually deals with member
* variables, so not static. Guaranteed to be called outside of main thread.
*
* @return NS_OK on correct startup, NS_ERROR_FAILURE otherwise
*/
virtual nsresult
StopInternal() = 0;
StartStopBluetooth(bool aStart,
bool aIsStartup,
BluetoothReplyRunnable* aRunnable);
/**
* Called when XPCOM first creates this service.

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

@ -33,34 +33,47 @@
#include "mozilla/StaticPtr.h"
#include "mozilla/unused.h"
#define ENSURE_BLUETOOTH_IS_READY(runnable, result) \
do { \
if (!sBtInterface || !IsEnabled()) { \
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth is not ready"); \
DispatchBluetoothReply(runnable, BluetoothValue(), errorStr); \
return result; \
} \
} while(0)
using namespace mozilla;
using namespace mozilla::ipc;
USING_BLUETOOTH_NAMESPACE
/**
* Static variables
*/
static bluetooth_device_t* sBtDevice;
static const bt_interface_t* sBtInterface;
static bool sAdapterDiscoverable = false;
static bool sIsBtEnabled = false;
// TODO: Non thread-safe static variables
static nsString sAdapterBdAddress;
static nsString sAdapterBdName;
static uint32_t sAdapterDiscoverableTimeout;
static InfallibleTArray<nsString> sAdapterBondedAddressArray;
static InfallibleTArray<BluetoothNamedValue> sRemoteDevicesPack;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sChangeAdapterStateRunnableArray;
// Static variables below should only be used on *main thread*
static const bt_interface_t* sBtInterface;
static nsTArray<nsRefPtr<BluetoothProfileController> > sControllerArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sBondingRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sChangeDiscoveryRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sGetDeviceRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sSetPropertyRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sUnbondingRunnableArray;
static nsTArray<int> sRequestedDeviceCountArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sChangeDiscoveryRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sSetPropertyRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sGetDeviceRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sBondingRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sUnbondingRunnableArray;
// Static variables below should only be used on *callback thread*
// Atomic static variables
static Atomic<bool> sAdapterDiscoverable(false);
static Atomic<uint32_t> sAdapterDiscoverableTimeout(0);
/**
* Classes only used in this file
*/
class DistributeBluetoothSignalTask : public nsRunnable {
class DistributeBluetoothSignalTask MOZ_FINAL : public nsRunnable
{
public:
DistributeBluetoothSignalTask(const BluetoothSignal& aSignal) :
mSignal(aSignal)
@ -84,12 +97,9 @@ private:
BluetoothSignal mSignal;
};
class SetupAfterEnabledTask : public nsRunnable
class SetupAfterEnabledTask MOZ_FINAL : public nsRunnable
{
public:
SetupAfterEnabledTask()
{ }
NS_IMETHOD
Run()
{
@ -135,17 +145,37 @@ public:
}
};
class CleanupTask : public nsRunnable
class CleanupTask MOZ_FINAL : public nsRunnable
{
public:
CleanupTask()
{ }
NS_IMETHOD
Run()
{
MOZ_ASSERT(NS_IsMainThread());
/*
* Cleanup static adapter properties and notify adapter to clean them
*
* TODO: clean up and notify Discovering also
*/
sAdapterBdAddress.Truncate();
sAdapterBdName.Truncate();
sAdapterDiscoverable = false;
InfallibleTArray<BluetoothNamedValue> props;
BT_APPEND_NAMED_VALUE(props, "Name", sAdapterBdName);
BT_APPEND_NAMED_VALUE(props, "Address", sAdapterBdAddress);
BT_APPEND_NAMED_VALUE(props, "Discoverable",
BluetoothValue(sAdapterDiscoverable));
BluetoothValue value(props);
BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
NS_LITERAL_STRING(KEY_ADAPTER), value);
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
bs->DistributeSignal(signal);
// Cleanup bluetooth interfaces after BT state becomes BT_STATE_OFF.
BluetoothHfpManager::DeinitHfpInterface();
BluetoothA2dpManager::DeinitA2dpInterface();
@ -270,45 +300,69 @@ PlayStatusStringToControlPlayStatus(const nsAString& aPlayStatus)
return playStatus;
}
static bool
IsReady()
{
if (!sBtInterface || !sIsBtEnabled) {
BT_LOGR("Warning! Bluetooth Service is not ready");
return false;
}
return true;
}
/**
* Bluedroid HAL callback functions
*
* Several callbacks are dispatched to main thread to avoid racing issues.
*/
static void
AdapterStateChangeCallback(bt_state_t aStatus)
{
MOZ_ASSERT(!NS_IsMainThread());
BT_LOGR("BT_STATE %d", aStatus);
BT_LOGR("BT_STATE: %d", aStatus);
sIsBtEnabled = (aStatus == BT_STATE_ON);
bool isBtEnabled = (aStatus == BT_STATE_ON);
if (!sIsBtEnabled && NS_FAILED(NS_DispatchToMainThread(new CleanupTask()))) {
if (!isBtEnabled &&
NS_FAILED(NS_DispatchToMainThread(new CleanupTask()))) {
BT_WARNING("Failed to dispatch to main thread!");
return;
}
nsRefPtr<nsRunnable> runnable =
new BluetoothService::ToggleBtAck(sIsBtEnabled);
new BluetoothService::ToggleBtAck(isBtEnabled);
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
BT_WARNING("Failed to dispatch to main thread!");
return;
}
if (sIsBtEnabled &&
if (isBtEnabled &&
NS_FAILED(NS_DispatchToMainThread(new SetupAfterEnabledTask()))) {
BT_WARNING("Failed to dispatch to main thread!");
return;
}
// Resolve promise if existed
if(!sChangeAdapterStateRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sChangeAdapterStateRunnableArray[0],
BluetoothValue(true),
EmptyString());
sChangeAdapterStateRunnableArray.RemoveElementAt(0);
}
}
class AdapterPropertiesCallbackTask MOZ_FINAL : public nsRunnable
{
public:
NS_IMETHOD
Run()
{
MOZ_ASSERT(NS_IsMainThread());
if (!sSetPropertyRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sSetPropertyRunnableArray[0],
BluetoothValue(true), EmptyString());
sSetPropertyRunnableArray.RemoveElementAt(0);
}
return NS_OK;
}
};
/**
* AdapterPropertiesCallback will be called after enable() but before
* AdapterStateChangeCallback sIsBtEnabled get updated. At that moment, both
* AdapterStateChangeCallback is called. At that moment, both
* BluetoothManager/BluetoothAdapter does not register observer yet.
*/
static void
@ -385,14 +439,64 @@ AdapterPropertiesCallback(bt_status_t aStatus, int aNumProperties,
BT_WARNING("Failed to dispatch to main thread!");
}
// bluedroid BTU task was stored in the task queue, see GKI_send_msg
if (!sSetPropertyRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sSetPropertyRunnableArray[0], BluetoothValue(true),
EmptyString());
sSetPropertyRunnableArray.RemoveElementAt(0);
}
// Redirect to main thread to avoid racing problem
NS_DispatchToMainThread(new AdapterPropertiesCallbackTask());
}
class RemoteDevicePropertiesCallbackTask : public nsRunnable
{
const InfallibleTArray<BluetoothNamedValue> mProps;
nsString mRemoteDeviceBdAddress;
public:
RemoteDevicePropertiesCallbackTask(
const InfallibleTArray<BluetoothNamedValue>& aProps,
const nsAString& aRemoteDeviceBdAddress)
: mProps(aProps)
, mRemoteDeviceBdAddress(aRemoteDeviceBdAddress)
{ }
NS_IMETHOD
Run()
{
MOZ_ASSERT(NS_IsMainThread());
if (sRequestedDeviceCountArray.IsEmpty()) {
// This is possible because the callback would be called after turning
// Bluetooth on.
return NS_OK;
}
// Update to registered BluetoothDevice objects
BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
mRemoteDeviceBdAddress, mProps);
nsRefPtr<DistributeBluetoothSignalTask>
t = new DistributeBluetoothSignalTask(signal);
if (NS_FAILED(NS_DispatchToMainThread(t))) {
BT_WARNING("Failed to dispatch to main thread!");
return NS_OK;
}
static InfallibleTArray<BluetoothNamedValue> sRemoteDevicesPack;
// Use address as the index
sRemoteDevicesPack.AppendElement(
BluetoothNamedValue(mRemoteDeviceBdAddress, mProps));
if (--sRequestedDeviceCountArray[0] == 0) {
if (!sGetDeviceRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sGetDeviceRunnableArray[0],
sRemoteDevicesPack, EmptyString());
sGetDeviceRunnableArray.RemoveElementAt(0);
}
sRequestedDeviceCountArray.RemoveElementAt(0);
sRemoteDevicesPack.Clear();
}
return NS_OK;
}
};
/**
* RemoteDevicePropertiesCallback will be called, as the following conditions:
* 1. When BT is turning on, bluedroid automatically execute this callback
@ -404,13 +508,6 @@ RemoteDevicePropertiesCallback(bt_status_t aStatus, bt_bdaddr_t *aBdAddress,
{
MOZ_ASSERT(!NS_IsMainThread());
if (sRequestedDeviceCountArray.IsEmpty()) {
MOZ_ASSERT(sGetDeviceRunnableArray.IsEmpty());
return;
}
sRequestedDeviceCountArray[0]--;
InfallibleTArray<BluetoothNamedValue> props;
nsString remoteDeviceBdAddress;
@ -435,36 +532,9 @@ RemoteDevicePropertiesCallback(bt_status_t aStatus, bt_bdaddr_t *aBdAddress,
}
}
// Update to registered BluetoothDevice objects
BluetoothSignal signal(NS_LITERAL_STRING("PropertyChanged"),
remoteDeviceBdAddress, props);
nsRefPtr<DistributeBluetoothSignalTask>
t = new DistributeBluetoothSignalTask(signal);
if (NS_FAILED(NS_DispatchToMainThread(t))) {
BT_WARNING("Failed to dispatch to main thread!");
}
// Use address as the index
sRemoteDevicesPack.AppendElement(
BluetoothNamedValue(remoteDeviceBdAddress, props));
if (sRequestedDeviceCountArray[0] == 0) {
MOZ_ASSERT(!sGetDeviceRunnableArray.IsEmpty());
if (sGetDeviceRunnableArray.IsEmpty()) {
BT_LOGR("No runnable to return");
return;
}
DispatchBluetoothReply(sGetDeviceRunnableArray[0],
sRemoteDevicesPack, EmptyString());
// After firing it, clean up cache
sRemoteDevicesPack.Clear();
sRequestedDeviceCountArray.RemoveElementAt(0);
sGetDeviceRunnableArray.RemoveElementAt(0);
}
// Redirect to main thread to avoid racing problem
NS_DispatchToMainThread(
new RemoteDevicePropertiesCallbackTask(props, remoteDeviceBdAddress));
}
static void
@ -511,18 +581,33 @@ DeviceFoundCallback(int aNumProperties, bt_property_t *aProperties)
}
}
class DiscoveryStateChangedCallbackTask MOZ_FINAL : public nsRunnable
{
public:
NS_IMETHOD
Run()
{
MOZ_ASSERT(NS_IsMainThread());
if (!sChangeDiscoveryRunnableArray.IsEmpty()) {
BluetoothValue values(true);
DispatchBluetoothReply(sChangeDiscoveryRunnableArray[0],
values, EmptyString());
sChangeDiscoveryRunnableArray.RemoveElementAt(0);
}
return NS_OK;
}
};
static void
DiscoveryStateChangedCallback(bt_discovery_state_t aState)
{
MOZ_ASSERT(!NS_IsMainThread());
if (!sChangeDiscoveryRunnableArray.IsEmpty()) {
BluetoothValue values(true);
DispatchBluetoothReply(sChangeDiscoveryRunnableArray[0],
values, EmptyString());
sChangeDiscoveryRunnableArray.RemoveElementAt(0);
}
// Redirect to main thread to avoid racing problem
NS_DispatchToMainThread(new DiscoveryStateChangedCallbackTask());
}
static void
@ -581,26 +666,75 @@ SspRequestCallback(bt_bdaddr_t* aRemoteBdAddress, bt_bdname_t* aRemoteBdName,
}
}
class BondStateChangedCallbackTask : public nsRunnable
{
nsString mRemoteDeviceBdAddress;
bool mBonded;
public:
BondStateChangedCallbackTask(const nsAString& aRemoteDeviceBdAddress,
bool aBonded)
: mRemoteDeviceBdAddress(aRemoteDeviceBdAddress)
, mBonded(aBonded)
{ }
NS_IMETHOD
Run()
{
MOZ_ASSERT(NS_IsMainThread());
if (mBonded && !sBondingRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sBondingRunnableArray[0],
BluetoothValue(true), EmptyString());
sBondingRunnableArray.RemoveElementAt(0);
} else if (!mBonded && !sUnbondingRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sUnbondingRunnableArray[0],
BluetoothValue(true), EmptyString());
sUnbondingRunnableArray.RemoveElementAt(0);
}
// Update bonding status to gaia
InfallibleTArray<BluetoothNamedValue> propertiesArray;
BT_APPEND_NAMED_VALUE(propertiesArray, "address", mRemoteDeviceBdAddress);
BT_APPEND_NAMED_VALUE(propertiesArray, "status", mBonded);
BluetoothSignal signal(NS_LITERAL_STRING(PAIRED_STATUS_CHANGED_ID),
NS_LITERAL_STRING(KEY_ADAPTER),
BluetoothValue(propertiesArray));
NS_DispatchToMainThread(new DistributeBluetoothSignalTask(signal));
return NS_OK;
}
};
static void
BondStateChangedCallback(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress,
bt_bond_state_t aState)
{
MOZ_ASSERT(!NS_IsMainThread());
nsAutoString remoteAddress;
BdAddressTypeToString(aRemoteBdAddress, remoteAddress);
if (aState == BT_BOND_STATE_BONDING) {
// No need to handle bonding state
return;
}
nsAutoString remoteBdAddress;
BdAddressTypeToString(aRemoteBdAddress, remoteBdAddress);
if (aState == BT_BOND_STATE_BONDED &&
sAdapterBondedAddressArray.Contains(remoteBdAddress)) {
// See bug 940271 for more details about this case.
return;
}
// We don't need to handle bonding state
NS_ENSURE_TRUE_VOID(aState != BT_BOND_STATE_BONDING);
NS_ENSURE_FALSE_VOID(aState == BT_BOND_STATE_BONDED &&
sAdapterBondedAddressArray.Contains(remoteAddress));
bool bonded;
if (aState == BT_BOND_STATE_NONE) {
bonded = false;
sAdapterBondedAddressArray.RemoveElement(remoteAddress);
sAdapterBondedAddressArray.RemoveElement(remoteBdAddress);
} else if (aState == BT_BOND_STATE_BONDED) {
bonded = true;
sAdapterBondedAddressArray.AppendElement(remoteAddress);
sAdapterBondedAddressArray.AppendElement(remoteBdAddress);
}
// Update bonded address list to BluetoothAdapter
@ -614,27 +748,9 @@ BondStateChangedCallback(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress,
BluetoothValue(propertiesChangeArray));
NS_DispatchToMainThread(new DistributeBluetoothSignalTask(signal));
// Update bonding status to gaia
InfallibleTArray<BluetoothNamedValue> propertiesArray;
BT_APPEND_NAMED_VALUE(propertiesArray, "address", remoteAddress);
BT_APPEND_NAMED_VALUE(propertiesArray, "status", bonded);
BluetoothSignal newSignal(NS_LITERAL_STRING(PAIRED_STATUS_CHANGED_ID),
NS_LITERAL_STRING(KEY_ADAPTER),
BluetoothValue(propertiesArray));
NS_DispatchToMainThread(new DistributeBluetoothSignalTask(newSignal));
if (bonded && !sBondingRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sBondingRunnableArray[0],
BluetoothValue(true), EmptyString());
sBondingRunnableArray.RemoveElementAt(0);
} else if (!bonded && !sUnbondingRunnableArray.IsEmpty()) {
DispatchBluetoothReply(sUnbondingRunnableArray[0],
BluetoothValue(true), EmptyString());
sUnbondingRunnableArray.RemoveElementAt(0);
}
// Redirect to main thread to avoid racing problem
NS_DispatchToMainThread(
new BondStateChangedCallbackTask(remoteBdAddress, bonded));
}
static void
@ -673,15 +789,17 @@ EnsureBluetoothHalLoad()
{
hw_module_t* module;
hw_device_t* device;
int err = hw_get_module(BT_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err != 0) {
BT_LOGR("Error: %s", strerror(err));
return false;
}
module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
sBtDevice = (bluetooth_device_t *)device;
NS_ENSURE_TRUE(sBtDevice, false);
sBtInterface = sBtDevice->get_bluetooth_interface();
bluetooth_device_t* btDevice = (bluetooth_device_t *)device;
NS_ENSURE_TRUE(btDevice, false);
sBtInterface = btDevice->get_bluetooth_interface();
NS_ENSURE_TRUE(sBtInterface, false);
return true;
@ -709,12 +827,16 @@ static nsresult
StartStopGonkBluetooth(bool aShouldEnable)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE(sBtInterface, NS_ERROR_FAILURE);
if (sIsBtEnabled == aShouldEnable) {
BluetoothService* bs = BluetoothService::Get();
NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
if (bs->IsEnabled() == aShouldEnable) {
// Keep current enable status
nsRefPtr<nsRunnable> runnable =
new BluetoothService::ToggleBtAck(sIsBtEnabled);
new BluetoothService::ToggleBtAck(aShouldEnable);
if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
BT_WARNING("Failed to dispatch to main thread!");
}
@ -772,10 +894,15 @@ BluetoothServiceBluedroid::~BluetoothServiceBluedroid()
}
nsresult
BluetoothServiceBluedroid::StartInternal()
BluetoothServiceBluedroid::StartInternal(BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
// aRunnable will be a nullptr while startup
if(aRunnable) {
sChangeAdapterStateRunnableArray.AppendElement(aRunnable);
}
nsresult ret = StartStopGonkBluetooth(true);
if (NS_FAILED(ret)) {
nsRefPtr<nsRunnable> runnable =
@ -790,10 +917,15 @@ BluetoothServiceBluedroid::StartInternal()
}
nsresult
BluetoothServiceBluedroid::StopInternal()
BluetoothServiceBluedroid::StopInternal(BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(NS_IsMainThread());
// aRunnable will be a nullptr during starup and shutdown
if(aRunnable) {
sChangeAdapterStateRunnableArray.AppendElement(aRunnable);
}
nsresult ret = StartStopGonkBluetooth(false);
if (NS_FAILED(ret)) {
nsRefPtr<nsRunnable> runnable =
@ -828,6 +960,11 @@ BluetoothServiceBluedroid::GetAdaptersInternal(
uint32_t numAdapters = 1; // Bluedroid supports single adapter only
for (uint32_t i = 0; i < numAdapters; i++) {
// Since Atomic<*> is not acceptable for BT_APPEND_NAMED_VALUE(),
// create another variable to store data.
bool discoverable = sAdapterDiscoverable;
uint32_t discoverableTimeout = sAdapterDiscoverableTimeout;
BluetoothValue properties = InfallibleTArray<BluetoothNamedValue>();
// TODO: Revise here based on new BluetoothAdapter interface
@ -836,9 +973,9 @@ BluetoothServiceBluedroid::GetAdaptersInternal(
BT_APPEND_NAMED_VALUE(properties.get_ArrayOfBluetoothNamedValue(),
"Name", sAdapterBdName);
BT_APPEND_NAMED_VALUE(properties.get_ArrayOfBluetoothNamedValue(),
"Discoverable", sAdapterDiscoverable);
"Discoverable", discoverable);
BT_APPEND_NAMED_VALUE(properties.get_ArrayOfBluetoothNamedValue(),
"DiscoverableTimeout", sAdapterDiscoverableTimeout);
"DiscoverableTimeout", discoverableTimeout);
BT_APPEND_NAMED_VALUE(properties.get_ArrayOfBluetoothNamedValue(),
"Devices", sAdapterBondedAddressArray);
@ -856,11 +993,7 @@ BluetoothServiceBluedroid::GetConnectedDevicePropertiesInternal(
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return NS_OK;
}
ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
BluetoothProfileManagerBase* profile =
BluetoothUuidHelper::GetBluetoothProfileManager(aServiceUuid);
@ -910,11 +1043,7 @@ BluetoothServiceBluedroid::GetPairedDevicePropertiesInternal(
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return NS_OK;
}
ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
int requestedDeviceCount = aDeviceAddress.Length();
if (requestedDeviceCount == 0) {
@ -947,12 +1076,8 @@ BluetoothServiceBluedroid::StartDiscoveryInternal(
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
return NS_OK;
}
int ret = sBtInterface->start_discovery();
if (ret != BT_STATUS_SUCCESS) {
ReplyStatusError(aRunnable, ret, NS_LITERAL_STRING("StartDiscovery"));
@ -970,11 +1095,7 @@ BluetoothServiceBluedroid::StopDiscoveryInternal(
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return NS_OK;
}
ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
int ret = sBtInterface->cancel_discovery();
if (ret != BT_STATUS_SUCCESS) {
@ -994,12 +1115,7 @@ BluetoothServiceBluedroid::SetProperty(BluetoothObjectType aType,
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return NS_OK;
}
ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
const nsString propName = aValue.name();
bt_property_t prop;
@ -1072,11 +1188,7 @@ BluetoothServiceBluedroid::CreatePairedDeviceInternal(
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return NS_OK;
}
ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
bt_bdaddr_t remoteAddress;
StringToBdAddressType(aDeviceAddress, &remoteAddress);
@ -1097,11 +1209,7 @@ BluetoothServiceBluedroid::RemoveDeviceInternal(
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return NS_OK;
}
ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
bt_bdaddr_t remoteAddress;
StringToBdAddressType(aDeviceAddress, &remoteAddress);
@ -1124,11 +1232,7 @@ BluetoothServiceBluedroid::SetPinCodeInternal(
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return false;
}
ENSURE_BLUETOOTH_IS_READY(aRunnable, false);
bt_bdaddr_t remoteAddress;
StringToBdAddressType(aDeviceAddress, &remoteAddress);
@ -1161,11 +1265,7 @@ BluetoothServiceBluedroid::SetPairingConfirmationInternal(
{
MOZ_ASSERT(NS_IsMainThread());
if (!IsReady()) {
NS_NAMED_LITERAL_STRING(errorStr, "Bluetooth service is not ready yet!");
DispatchBluetoothReply(aRunnable, BluetoothValue(), errorStr);
return false;
}
ENSURE_BLUETOOTH_IS_READY(aRunnable, false);
bt_bdaddr_t remoteAddress;
StringToBdAddressType(aDeviceAddress, &remoteAddress);

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

@ -22,8 +22,8 @@ public:
BluetoothServiceBluedroid();
~BluetoothServiceBluedroid();
virtual nsresult StartInternal();
virtual nsresult StopInternal();
virtual nsresult StartInternal(BluetoothReplyRunnable* aRunnable);
virtual nsresult StopInternal(BluetoothReplyRunnable* aRunnable);
virtual nsresult
GetAdaptersInternal(BluetoothReplyRunnable* aRunnable);

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

@ -2097,8 +2097,10 @@ public:
};
nsresult
BluetoothDBusService::StartInternal()
BluetoothDBusService::StartInternal(BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(!aRunnable);
nsRefPtr<nsRunnable> runnable = new StartBluetoothRunnable();
nsresult rv = DispatchToBtThread(runnable);
if (NS_FAILED(rv)) {
@ -2225,8 +2227,10 @@ public:
};
nsresult
BluetoothDBusService::StopInternal()
BluetoothDBusService::StopInternal(BluetoothReplyRunnable* aRunnable)
{
MOZ_ASSERT(!aRunnable);
nsRefPtr<nsRunnable> runnable = new StopBluetoothRunnable();
nsresult rv = DispatchToBtThread(runnable);
if (NS_FAILED(rv)) {

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

@ -47,9 +47,9 @@ public:
bool IsReady();
virtual nsresult StartInternal() MOZ_OVERRIDE;
virtual nsresult StartInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult StopInternal() MOZ_OVERRIDE;
virtual nsresult StopInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult
GetAdaptersInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;

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

@ -192,6 +192,10 @@ BluetoothParent::RecvPBluetoothRequestConstructor(
switch (aRequest.type()) {
case Request::TGetAdaptersRequest:
return actor->DoRequest(aRequest.get_GetAdaptersRequest());
case Request::TStartBluetoothRequest:
return actor->DoRequest(aRequest.get_StartBluetoothRequest());
case Request::TStopBluetoothRequest:
return actor->DoRequest(aRequest.get_StopBluetoothRequest());
case Request::TSetPropertyRequest:
return actor->DoRequest(aRequest.get_SetPropertyRequest());
case Request::TStartDiscoveryRequest:
@ -321,6 +325,30 @@ BluetoothRequestParent::DoRequest(const GetAdaptersRequest& aRequest)
return true;
}
bool
BluetoothRequestParent::DoRequest(const StartBluetoothRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TStartBluetoothRequest);
nsresult rv = mService->StartInternal(mReplyRunnable.get());
NS_ENSURE_SUCCESS(rv, false);
return true;
}
bool
BluetoothRequestParent::DoRequest(const StopBluetoothRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TStopBluetoothRequest);
nsresult rv = mService->StopInternal(mReplyRunnable.get());
NS_ENSURE_SUCCESS(rv, false);
return true;
}
bool
BluetoothRequestParent::DoRequest(const SetPropertyRequest& aRequest)
{

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

@ -128,6 +128,12 @@ protected:
bool
DoRequest(const GetAdaptersRequest& aRequest);
bool
DoRequest(const StartBluetoothRequest& aRequest);
bool
DoRequest(const StopBluetoothRequest& aRequest);
bool
DoRequest(const SetPropertyRequest& aRequest);

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

@ -103,6 +103,20 @@ BluetoothServiceChildProcess::GetAdaptersInternal(
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::StartInternal(BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable, StartBluetoothRequest());
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::StopInternal(BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable, StopBluetoothRequest());
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::GetConnectedDevicePropertiesInternal(
uint16_t aServiceUuid,
@ -377,18 +391,6 @@ BluetoothServiceChildProcess::HandleShutdown()
return NS_OK;
}
nsresult
BluetoothServiceChildProcess::StartInternal()
{
MOZ_CRASH("This should never be called!");
}
nsresult
BluetoothServiceChildProcess::StopInternal()
{
MOZ_CRASH("This should never be called!");
}
bool
BluetoothServiceChildProcess::IsConnected(uint16_t aServiceUuid)
{

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

@ -46,6 +46,12 @@ public:
virtual nsresult
GetAdaptersInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult
StartInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult
StopInternal(BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual nsresult
GetPairedDevicePropertiesInternal(const nsTArray<nsString>& aDeviceAddresses,
BluetoothReplyRunnable* aRunnable)
@ -199,14 +205,6 @@ protected:
HandleShutdown() MOZ_OVERRIDE;
private:
// This method should never be called.
virtual nsresult
StartInternal() MOZ_OVERRIDE;
// This method should never be called.
virtual nsresult
StopInternal() MOZ_OVERRIDE;
bool
IsSignalRegistered(const nsAString& aNodeName) {
return !!mBluetoothSignalObserverTable.Get(aNodeName);

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

@ -25,6 +25,14 @@ namespace bluetooth {
struct GetAdaptersRequest
{ };
struct StartBluetoothRequest
{
};
struct StopBluetoothRequest
{
};
struct SetPropertyRequest
{
BluetoothObjectType type;
@ -166,6 +174,8 @@ struct SendPlayStatusRequest
union Request
{
GetAdaptersRequest;
StartBluetoothRequest;
StopBluetoothRequest;
SetPropertyRequest;
GetPropertyRequest;
StartDiscoveryRequest;

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

@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "domstubs.idl"
#include "nsISupports.idl"
interface nsIDOMMozCellBroadcastEtwsInfo;
@ -10,7 +11,7 @@ interface nsIDOMMozCellBroadcastEtwsInfo;
* MozCellBroadcastMessage encapsulates Cell Broadcast short message service
* (CBS) messages.
*/
[scriptable, uuid(6abe65de-6729-41f7-906a-3f3a2dbe30ae)]
[scriptable, uuid(701e74a9-5fc4-4e2d-a324-9b7693395159)]
interface nsIDOMMozCellBroadcastMessage : nsISupports
{
/**
@ -53,7 +54,7 @@ interface nsIDOMMozCellBroadcastMessage : nsISupports
/**
* System time stamp at receival.
*/
readonly attribute jsval timestamp; // jsval is for Date.
readonly attribute DOMTimeStamp timestamp;
/**
* Additional ETWS-specific info.

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

@ -196,7 +196,7 @@ function testReceiving_ETWS_Timestamp() {
doTestHelper(pdu, testReceiving_ETWS_WarningType, function(message) {
// Cell Broadcast messages do not contain a timestamp field (however, ETWS
// does). We only check the timestamp doesn't go too far (60 seconds) here.
let msMessage = message.timestamp.getTime();
let msMessage = message.timestamp;
let msNow = Date.now();
ok(Math.abs(msMessage - msNow) < (1000 * 60), "message.timestamp");
});

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

@ -361,7 +361,7 @@ function testReceiving_GSM_Timestamp() {
doTestHelper(pdu, testReceiving_GSM_WarningType, function(message) {
// Cell Broadcast messages do not contain a timestamp field (however, ETWS
// does). We only check the timestamp doesn't go too far (60 seconds) here.
let msMessage = message.timestamp.getTime();
let msMessage = message.timestamp;
let msNow = Date.now();
ok(Math.abs(msMessage - msNow) < (1000 * 60), "message.timestamp");
});

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

@ -150,7 +150,7 @@ RejectPromise(nsPIDOMWindow* aWindow, Promise* aPromise, nsresult aRv)
NS_LITERAL_STRING("An error occurred"));
}
aPromise->MaybeReject(error);
aPromise->MaybeRejectBrokenly(error);
}
void

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

@ -20,13 +20,149 @@
#define DEFINE_KEYNAME_WITH_SAME_NAME(aName) \
DEFINE_KEYNAME_INTERNAL(aName, #aName)
/******************************************************************************
* Special Key Values
*****************************************************************************/
DEFINE_KEYNAME_WITH_SAME_NAME(Unidentified)
/******************************************************************************
* Our Internal Key Values (must have "Moz" prefix)
*****************************************************************************/
DEFINE_KEYNAME_INTERNAL(PrintableKey, "MozPrintableKey")
/******************************************************************************
* Modifier Keys
*****************************************************************************/
DEFINE_KEYNAME_WITH_SAME_NAME(Alt)
DEFINE_KEYNAME_WITH_SAME_NAME(AltGraph)
DEFINE_KEYNAME_WITH_SAME_NAME(CapsLock)
DEFINE_KEYNAME_WITH_SAME_NAME(Control)
DEFINE_KEYNAME_WITH_SAME_NAME(Fn)
// DEFINE_KEYNAME_WITH_SAME_NAME(FnLock)
// DEFINE_KEYNAME_WITH_SAME_NAME(Hyper)
DEFINE_KEYNAME_WITH_SAME_NAME(Meta)
DEFINE_KEYNAME_WITH_SAME_NAME(NumLock)
DEFINE_KEYNAME_WITH_SAME_NAME(OS)
DEFINE_KEYNAME_WITH_SAME_NAME(ScrollLock)
DEFINE_KEYNAME_WITH_SAME_NAME(Shift)
// DEFINE_KEYNAME_WITH_SAME_NAME(Super)
// DEFINE_KEYNAME_WITH_SAME_NAME(Symbol)
// DEFINE_KEYNAME_WITH_SAME_NAME(SymbolLock)
/******************************************************************************
* Whitespace Keys
*****************************************************************************/
DEFINE_KEYNAME_WITH_SAME_NAME(Enter)
// DEFINE_KEYNAME_WITH_SAME_NAME(Separator)
DEFINE_KEYNAME_WITH_SAME_NAME(Tab)
/******************************************************************************
* Navigation Keys
*****************************************************************************/
DEFINE_KEYNAME_WITH_SAME_NAME(Down) // Rename to ArrowDown
DEFINE_KEYNAME_WITH_SAME_NAME(Left) // Rename to ArrowLeft
DEFINE_KEYNAME_WITH_SAME_NAME(Right) // Rename to ArrowRight
DEFINE_KEYNAME_WITH_SAME_NAME(Up) // Rename to ArrowUp
DEFINE_KEYNAME_WITH_SAME_NAME(End)
DEFINE_KEYNAME_WITH_SAME_NAME(Home)
DEFINE_KEYNAME_WITH_SAME_NAME(PageDown)
DEFINE_KEYNAME_WITH_SAME_NAME(PageUp)
/******************************************************************************
* Editing Keys
*****************************************************************************/
DEFINE_KEYNAME_WITH_SAME_NAME(Backspace)
DEFINE_KEYNAME_WITH_SAME_NAME(Clear)
DEFINE_KEYNAME_WITH_SAME_NAME(Copy)
DEFINE_KEYNAME_WITH_SAME_NAME(Crsel) // Rename to CrSel
DEFINE_KEYNAME_WITH_SAME_NAME(Cut)
DEFINE_KEYNAME_WITH_SAME_NAME(Del) // Rename to Delete
DEFINE_KEYNAME_WITH_SAME_NAME(EraseEof)
DEFINE_KEYNAME_WITH_SAME_NAME(Exsel) // Rename to ExSel
DEFINE_KEYNAME_WITH_SAME_NAME(Insert)
DEFINE_KEYNAME_WITH_SAME_NAME(Paste)
// DEFINE_KEYNAME_WITH_SAME_NAME(Redo)
DEFINE_KEYNAME_WITH_SAME_NAME(Undo)
/******************************************************************************
* UI Keys
*****************************************************************************/
DEFINE_KEYNAME_WITH_SAME_NAME(Accept)
// DEFINE_KEYNAME_WITH_SAME_NAME(Again)
DEFINE_KEYNAME_WITH_SAME_NAME(Attn)
DEFINE_KEYNAME_WITH_SAME_NAME(Apps)
DEFINE_KEYNAME_WITH_SAME_NAME(Crsel)
DEFINE_KEYNAME_WITH_SAME_NAME(Exsel)
DEFINE_KEYNAME_WITH_SAME_NAME(Cancel)
DEFINE_KEYNAME_WITH_SAME_NAME(Menu) // Rename to ContextMenu
DEFINE_KEYNAME_WITH_SAME_NAME(Esc) // Rename to Escape
DEFINE_KEYNAME_WITH_SAME_NAME(Execute)
DEFINE_KEYNAME_WITH_SAME_NAME(Find)
DEFINE_KEYNAME_WITH_SAME_NAME(Help)
DEFINE_KEYNAME_WITH_SAME_NAME(Pause)
DEFINE_KEYNAME_WITH_SAME_NAME(Play)
// DEFINE_KEYNAME_WITH_SAME_NAME(Props)
DEFINE_KEYNAME_WITH_SAME_NAME(Select)
// DEFINE_KEYNAME_WITH_SAME_NAME(ZoomIn)
// DEFINE_KEYNAME_WITH_SAME_NAME(ZoomOut)
/******************************************************************************
* Device Keys
*****************************************************************************/
DEFINE_KEYNAME_WITH_SAME_NAME(BrightnessDown)
DEFINE_KEYNAME_WITH_SAME_NAME(BrightnessUp)
DEFINE_KEYNAME_WITH_SAME_NAME(Camera)
DEFINE_KEYNAME_WITH_SAME_NAME(Eject)
// DEFINE_KEYNAME_WITH_SAME_NAME(LogOff)
DEFINE_KEYNAME_WITH_SAME_NAME(Power)
// DEFINE_KEYNAME_WITH_SAME_NAME(PowerOff)
DEFINE_KEYNAME_WITH_SAME_NAME(PrintScreen)
// DEFINE_KEYNAME_WITH_SAME_NAME(Hibernate)
// DEFINE_KEYNAME_WITH_SAME_NAME(Standby)
// DEFINE_KEYNAME_WITH_SAME_NAME(WakeUp)
/******************************************************************************
* IME and Composition Keys
*****************************************************************************/
DEFINE_KEYNAME_WITH_SAME_NAME(AllCandidates)
DEFINE_KEYNAME_WITH_SAME_NAME(Alphanumeric)
DEFINE_KEYNAME_WITH_SAME_NAME(CodeInput)
DEFINE_KEYNAME_WITH_SAME_NAME(Compose)
DEFINE_KEYNAME_WITH_SAME_NAME(Convert)
// DEFINE_KEYNAME_WITH_SAME_NAME(Dead)
DEFINE_KEYNAME_WITH_SAME_NAME(FinalMode)
// DEFINE_KEYNAME_WITH_SAME_NAME(GroupFirst)
// DEFINE_KEYNAME_WITH_SAME_NAME(GroupLast)
// DEFINE_KEYNAME_WITH_SAME_NAME(GroupNext)
// DEFINE_KEYNAME_WITH_SAME_NAME(GroupPrevious)
DEFINE_KEYNAME_WITH_SAME_NAME(ModeChange)
// DEFINE_KEYNAME_WITH_SAME_NAME(NextCandidate)
DEFINE_KEYNAME_WITH_SAME_NAME(Nonconvert) // Rename to NonConvert
DEFINE_KEYNAME_WITH_SAME_NAME(PreviousCandidate)
// DEFINE_KEYNAME_WITH_SAME_NAME(Process)
// DEFINE_KEYNAME_WITH_SAME_NAME(SingleCandidate)
/******************************************************************************
* Keys specific to Korean keyboards
*****************************************************************************/
DEFINE_KEYNAME_WITH_SAME_NAME(HangulMode)
DEFINE_KEYNAME_WITH_SAME_NAME(HanjaMode)
DEFINE_KEYNAME_WITH_SAME_NAME(JunjaMode)
/******************************************************************************
* Keys specific to Japanese keyboards
*****************************************************************************/
// DEFINE_KEYNAME_WITH_SAME_NAME(Eisu)
DEFINE_KEYNAME_WITH_SAME_NAME(HalfWidth) // Rename to Hankaku
DEFINE_KEYNAME_WITH_SAME_NAME(Hiragana)
// DEFINE_KEYNAME_WITH_SAME_NAME(HiraganaKatakana)
DEFINE_KEYNAME_WITH_SAME_NAME(KanaMode)
DEFINE_KEYNAME_WITH_SAME_NAME(KanjiMode)
DEFINE_KEYNAME_WITH_SAME_NAME(Katakana)
DEFINE_KEYNAME_WITH_SAME_NAME(RomanCharacters) // Rename to Romaji
DEFINE_KEYNAME_WITH_SAME_NAME(FullWidth) // Rename to Zenkaku
// DEFINE_KEYNAME_WITH_SAME_NAME(ZenkakuHankaku)
/******************************************************************************
* General-Purpose Function Keys
*****************************************************************************/
DEFINE_KEYNAME_WITH_SAME_NAME(F1)
DEFINE_KEYNAME_WITH_SAME_NAME(F2)
DEFINE_KEYNAME_WITH_SAME_NAME(F3)
@ -62,6 +198,47 @@ DEFINE_KEYNAME_WITH_SAME_NAME(F32)
DEFINE_KEYNAME_WITH_SAME_NAME(F33)
DEFINE_KEYNAME_WITH_SAME_NAME(F34)
DEFINE_KEYNAME_WITH_SAME_NAME(F35)
// DEFINE_KEYNAME_WITH_SAME_NAME(Soft1)
// DEFINE_KEYNAME_WITH_SAME_NAME(Soft2)
// DEFINE_KEYNAME_WITH_SAME_NAME(Soft3)
// DEFINE_KEYNAME_WITH_SAME_NAME(Soft4)
/******************************************************************************
* Multimedia Keys
*****************************************************************************/
// DEFINE_KEYNAME_WITH_SAME_NAME(Close)
// DEFINE_KEYNAME_WITH_SAME_NAME(MailForward)
// DEFINE_KEYNAME_WITH_SAME_NAME(MailReply)
// DEFINE_KEYNAME_WITH_SAME_NAME(MailSend)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaPlayPause)
DEFINE_KEYNAME_WITH_SAME_NAME(SelectMedia) // Rename to MediaSelect
DEFINE_KEYNAME_WITH_SAME_NAME(MediaStop)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaNextTrack) // Rename to MediaTrackNext
DEFINE_KEYNAME_WITH_SAME_NAME(MediaPreviousTrack) // Rename to MediaTrackPrevious
// DEFINE_KEYNAME_WITH_SAME_NAME(New)
// DEFINE_KEYNAME_WITH_SAME_NAME(Open)
// DEFINE_KEYNAME_WITH_SAME_NAME(Print)
// DEFINE_KEYNAME_WITH_SAME_NAME(Save)
// DEFINE_KEYNAME_WITH_SAME_NAME(SpellCheck)
DEFINE_KEYNAME_WITH_SAME_NAME(VolumeDown)
DEFINE_KEYNAME_WITH_SAME_NAME(VolumeUp)
DEFINE_KEYNAME_WITH_SAME_NAME(VolumeMute)
/******************************************************************************
* Application Keys
*****************************************************************************/
// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchCalculator)
// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchCalendar)
DEFINE_KEYNAME_WITH_SAME_NAME(LaunchMail)
// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchMediaPlayer)
// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchMusicPlayer)
// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchMyComputer)
// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchScreenSaver)
// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchSpreadsheet)
// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchWebBrowser)
// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchWebCam)
// DEFINE_KEYNAME_WITH_SAME_NAME(LaunchWordProcessor)
DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication1)
DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication2)
DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication3)
@ -80,64 +257,103 @@ DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication15)
DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication16)
DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication17)
DEFINE_KEYNAME_WITH_SAME_NAME(LaunchApplication18)
DEFINE_KEYNAME_WITH_SAME_NAME(LaunchMail)
DEFINE_KEYNAME_WITH_SAME_NAME(List)
DEFINE_KEYNAME_WITH_SAME_NAME(Props)
DEFINE_KEYNAME_WITH_SAME_NAME(Soft1)
DEFINE_KEYNAME_WITH_SAME_NAME(Soft2)
DEFINE_KEYNAME_WITH_SAME_NAME(Soft3)
DEFINE_KEYNAME_WITH_SAME_NAME(Soft4)
DEFINE_KEYNAME_WITH_SAME_NAME(Accept)
DEFINE_KEYNAME_WITH_SAME_NAME(Again)
DEFINE_KEYNAME_WITH_SAME_NAME(Enter)
DEFINE_KEYNAME_WITH_SAME_NAME(Find)
DEFINE_KEYNAME_WITH_SAME_NAME(Help)
DEFINE_KEYNAME_WITH_SAME_NAME(Info)
DEFINE_KEYNAME_WITH_SAME_NAME(Menu)
DEFINE_KEYNAME_WITH_SAME_NAME(Pause)
DEFINE_KEYNAME_WITH_SAME_NAME(Play)
DEFINE_KEYNAME_WITH_SAME_NAME(ScrollLock) // IE9 users "Scroll"
DEFINE_KEYNAME_WITH_SAME_NAME(Execute)
DEFINE_KEYNAME_WITH_SAME_NAME(Cancel)
DEFINE_KEYNAME_WITH_SAME_NAME(Esc)
DEFINE_KEYNAME_WITH_SAME_NAME(Exit)
DEFINE_KEYNAME_WITH_SAME_NAME(Zoom)
DEFINE_KEYNAME_WITH_SAME_NAME(BrightnessDown)
DEFINE_KEYNAME_WITH_SAME_NAME(BrightnessUp)
DEFINE_KEYNAME_WITH_SAME_NAME(Camera)
DEFINE_KEYNAME_WITH_SAME_NAME(Eject)
DEFINE_KEYNAME_WITH_SAME_NAME(Power)
DEFINE_KEYNAME_WITH_SAME_NAME(PrintScreen)
/******************************************************************************
* Browser Keys
*****************************************************************************/
DEFINE_KEYNAME_WITH_SAME_NAME(BrowserBack)
DEFINE_KEYNAME_WITH_SAME_NAME(BrowserFavorites)
DEFINE_KEYNAME_WITH_SAME_NAME(BrowserForward)
DEFINE_KEYNAME_WITH_SAME_NAME(BrowserHome)
DEFINE_KEYNAME_WITH_SAME_NAME(BrowserRefresh)
DEFINE_KEYNAME_WITH_SAME_NAME(BrowserSearch)
DEFINE_KEYNAME_WITH_SAME_NAME(BrowserStop)
DEFINE_KEYNAME_WITH_SAME_NAME(BrowserBack)
DEFINE_KEYNAME_WITH_SAME_NAME(BrowserForward)
DEFINE_KEYNAME_WITH_SAME_NAME(Left)
DEFINE_KEYNAME_WITH_SAME_NAME(PageDown)
DEFINE_KEYNAME_WITH_SAME_NAME(PageUp)
DEFINE_KEYNAME_WITH_SAME_NAME(Right)
DEFINE_KEYNAME_WITH_SAME_NAME(Up)
DEFINE_KEYNAME_WITH_SAME_NAME(UpLeft)
DEFINE_KEYNAME_WITH_SAME_NAME(UpRight)
DEFINE_KEYNAME_WITH_SAME_NAME(Down)
DEFINE_KEYNAME_WITH_SAME_NAME(DownLeft)
DEFINE_KEYNAME_WITH_SAME_NAME(DownRight)
DEFINE_KEYNAME_WITH_SAME_NAME(Home)
DEFINE_KEYNAME_WITH_SAME_NAME(End)
DEFINE_KEYNAME_WITH_SAME_NAME(Select)
DEFINE_KEYNAME_WITH_SAME_NAME(Tab)
DEFINE_KEYNAME_WITH_SAME_NAME(Backspace)
DEFINE_KEYNAME_WITH_SAME_NAME(Clear)
DEFINE_KEYNAME_WITH_SAME_NAME(Copy)
DEFINE_KEYNAME_WITH_SAME_NAME(Cut)
DEFINE_KEYNAME_WITH_SAME_NAME(Del)
DEFINE_KEYNAME_WITH_SAME_NAME(EraseEof)
DEFINE_KEYNAME_WITH_SAME_NAME(Insert)
DEFINE_KEYNAME_WITH_SAME_NAME(Paste)
DEFINE_KEYNAME_WITH_SAME_NAME(Undo)
/******************************************************************************
* Media Controller Keys
*****************************************************************************/
// DEFINE_KEYNAME_WITH_SAME_NAME(AudioBalanceLeft)
// DEFINE_KEYNAME_WITH_SAME_NAME(AudioBalanceRight)
DEFINE_KEYNAME_WITH_SAME_NAME(AudioBassBoostDown)
DEFINE_KEYNAME_WITH_SAME_NAME(AudioBassBoostUp)
// DEFINE_KEYNAME_WITH_SAME_NAME(AudioFaderFront)
// DEFINE_KEYNAME_WITH_SAME_NAME(AudioFaderRear)
// DEFINE_KEYNAME_WITH_SAME_NAME(AudioSurroundModeNext)
// DEFINE_KEYNAME_WITH_SAME_NAME(AVRInput)
// DEFINE_KEYNAME_WITH_SAME_NAME(AVRPower)
DEFINE_KEYNAME_WITH_SAME_NAME(ChannelDown)
DEFINE_KEYNAME_WITH_SAME_NAME(ChannelUp)
DEFINE_KEYNAME_WITH_SAME_NAME(Red) // Rename to ColorF0Red
DEFINE_KEYNAME_WITH_SAME_NAME(Green) // Rename to ColorF1Green
DEFINE_KEYNAME_WITH_SAME_NAME(Yellow) // Rename to ColorF2Yellow
DEFINE_KEYNAME_WITH_SAME_NAME(Blue) // Rename to ColorF3Blue
// DEFINE_KEYNAME_WITH_SAME_NAME(Grey) // Rename to ColorF4Grey
// DEFINE_KEYNAME_WITH_SAME_NAME(Brown) // Rename to ColorF5Brown
// DEFINE_KEYNAME_WITH_SAME_NAME(ClosedCaptionToggle)
DEFINE_KEYNAME_WITH_SAME_NAME(Dimmer)
// DEFINE_KEYNAME_WITH_SAME_NAME(DisplaySwap)
DEFINE_KEYNAME_WITH_SAME_NAME(Exit)
// DEFINE_KEYNAME_WITH_SAME_NAME(ClearFavorite0) // Rename to FavoriteClear0
// DEFINE_KEYNAME_WITH_SAME_NAME(ClearFavorite1) // Rename to FavoriteClear1
// DEFINE_KEYNAME_WITH_SAME_NAME(ClearFavorite2) // Rename to FavoriteClear2
// DEFINE_KEYNAME_WITH_SAME_NAME(ClearFavorite3) // Rename to FavoriteClear3
// DEFINE_KEYNAME_WITH_SAME_NAME(RecallFavorite0) // Rename to FavoriteRecall0
// DEFINE_KEYNAME_WITH_SAME_NAME(RecallFavorite1) // Rename to FavoriteRecall1
// DEFINE_KEYNAME_WITH_SAME_NAME(RecallFavorite2) // Rename to FavoriteRecall2
// DEFINE_KEYNAME_WITH_SAME_NAME(RecallFavorite3) // Rename to FavoriteRecall3
// DEFINE_KEYNAME_WITH_SAME_NAME(StoreFavorite0) // Rename to FavoriteStore0
// DEFINE_KEYNAME_WITH_SAME_NAME(StoreFavorite1) // Rename to FavoriteStore1
// DEFINE_KEYNAME_WITH_SAME_NAME(StoreFavorite2) // Rename to FavoriteStore2
// DEFINE_KEYNAME_WITH_SAME_NAME(StoreFavorite3) // Rename to FavoriteStore3
DEFINE_KEYNAME_WITH_SAME_NAME(Guide)
// DEFINE_KEYNAME_WITH_SAME_NAME(NextDay) // Rename to GuideNextDay
// DEFINE_KEYNAME_WITH_SAME_NAME(PrevDay) // Rename to GuidePreviousDay
DEFINE_KEYNAME_WITH_SAME_NAME(Info)
// DEFINE_KEYNAME_WITH_SAME_NAME(InstantReplay)
// DEFINE_KEYNAME_WITH_SAME_NAME(Link)
// DEFINE_KEYNAME_WITH_SAME_NAME(List) // Rename to ListProgram
DEFINE_KEYNAME_WITH_SAME_NAME(Live) // Rename to LiveContent
// DEFINE_KEYNAME_WITH_SAME_NAME(Lock)
DEFINE_KEYNAME_WITH_SAME_NAME(Apps) // Rename to MediaApps
DEFINE_KEYNAME_WITH_SAME_NAME(FastFwd) // Rename to MediaFastForward
DEFINE_KEYNAME_WITH_SAME_NAME(MediaLast)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaPause)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaPlay)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaRecord)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaRewind)
// DEFINE_KEYNAME_WITH_SAME_NAME(MediaSkip)
// DEFINE_KEYNAME_WITH_SAME_NAME(NextFavoriteChannel)
// DEFINE_KEYNAME_WITH_SAME_NAME(NextUserProfile)
// DEFINE_KEYNAME_WITH_SAME_NAME(OnDemand)
// DEFINE_KEYNAME_WITH_SAME_NAME(PinPDown)
// DEFINE_KEYNAME_WITH_SAME_NAME(PinPMove)
DEFINE_KEYNAME_WITH_SAME_NAME(PinPToggle)
// DEFINE_KEYNAME_WITH_SAME_NAME(PinPUp)
// DEFINE_KEYNAME_WITH_SAME_NAME(PlaySpeedDown)
// DEFINE_KEYNAME_WITH_SAME_NAME(PlaySpeedReset)
// DEFINE_KEYNAME_WITH_SAME_NAME(PlaySpeedUp)
DEFINE_KEYNAME_WITH_SAME_NAME(RandomToggle)
// DEFINE_KEYNAME_WITH_SAME_NAME(RcLowBattery)
// DEFINE_KEYNAME_WITH_SAME_NAME(RecordSpeedNext)
// DEFINE_KEYNAME_WITH_SAME_NAME(RfBypass)
// DEFINE_KEYNAME_WITH_SAME_NAME(ScanChannelsToggle)
// DEFINE_KEYNAME_WITH_SAME_NAME(ScreenModeNext)
DEFINE_KEYNAME_WITH_SAME_NAME(Settings)
// DEFINE_KEYNAME_WITH_SAME_NAME(SplitScreenToggle)
// DEFINE_KEYNAME_WITH_SAME_NAME(STBInput)
// DEFINE_KEYNAME_WITH_SAME_NAME(STBPower)
DEFINE_KEYNAME_WITH_SAME_NAME(Subtitle)
// DEFINE_KEYNAME_WITH_SAME_NAME(Teletext)
// DEFINE_KEYNAME_WITH_SAME_NAME(TV)
// DEFINE_KEYNAME_WITH_SAME_NAME(TVInput)
// DEFINE_KEYNAME_WITH_SAME_NAME(TVPower)
// DEFINE_KEYNAME_WITH_SAME_NAME(VideoModeNext)
// DEFINE_KEYNAME_WITH_SAME_NAME(Wink)
DEFINE_KEYNAME_WITH_SAME_NAME(Zoom) // Rename to ZoomToggle
/******************************************************************************
* Deprecated
******************************************************************************/
DEFINE_KEYNAME_WITH_SAME_NAME(DeadGrave)
DEFINE_KEYNAME_WITH_SAME_NAME(DeadAcute)
DEFINE_KEYNAME_WITH_SAME_NAME(DeadCircumflex)
@ -154,112 +370,6 @@ DEFINE_KEYNAME_WITH_SAME_NAME(DeadOgonek)
DEFINE_KEYNAME_WITH_SAME_NAME(DeadIota)
DEFINE_KEYNAME_WITH_SAME_NAME(DeadVoicedSound)
DEFINE_KEYNAME_WITH_SAME_NAME(DeadSemivoicedSound)
DEFINE_KEYNAME_WITH_SAME_NAME(Alphanumeric)
DEFINE_KEYNAME_WITH_SAME_NAME(Alt)
DEFINE_KEYNAME_WITH_SAME_NAME(AltGraph)
DEFINE_KEYNAME_WITH_SAME_NAME(CapsLock)
DEFINE_KEYNAME_WITH_SAME_NAME(Control)
DEFINE_KEYNAME_WITH_SAME_NAME(Fn)
DEFINE_KEYNAME_WITH_SAME_NAME(FnLock)
DEFINE_KEYNAME_WITH_SAME_NAME(Meta)
DEFINE_KEYNAME_WITH_SAME_NAME(Process)
DEFINE_KEYNAME_WITH_SAME_NAME(NumLock)
DEFINE_KEYNAME_WITH_SAME_NAME(Shift)
DEFINE_KEYNAME_WITH_SAME_NAME(SymbolLock)
DEFINE_KEYNAME_WITH_SAME_NAME(OS) // IE9 uses "Win"
DEFINE_KEYNAME_WITH_SAME_NAME(Compose)
DEFINE_KEYNAME_WITH_SAME_NAME(AllCandidates)
DEFINE_KEYNAME_WITH_SAME_NAME(NextCandidate)
DEFINE_KEYNAME_WITH_SAME_NAME(PreviousCandidate)
DEFINE_KEYNAME_WITH_SAME_NAME(CodeInput)
DEFINE_KEYNAME_WITH_SAME_NAME(Convert)
DEFINE_KEYNAME_WITH_SAME_NAME(Nonconvert)
DEFINE_KEYNAME_WITH_SAME_NAME(FinalMode)
DEFINE_KEYNAME_WITH_SAME_NAME(FullWidth)
DEFINE_KEYNAME_WITH_SAME_NAME(HalfWidth)
DEFINE_KEYNAME_WITH_SAME_NAME(ModeChange)
DEFINE_KEYNAME_WITH_SAME_NAME(RomanCharacters)
DEFINE_KEYNAME_WITH_SAME_NAME(HangulMode)
DEFINE_KEYNAME_WITH_SAME_NAME(HanjaMode)
DEFINE_KEYNAME_WITH_SAME_NAME(JunjaMode)
DEFINE_KEYNAME_WITH_SAME_NAME(Hiragana)
DEFINE_KEYNAME_WITH_SAME_NAME(KanaMode)
DEFINE_KEYNAME_WITH_SAME_NAME(KanjiMode)
DEFINE_KEYNAME_WITH_SAME_NAME(Katakana)
DEFINE_KEYNAME_WITH_SAME_NAME(AudioFaderFront)
DEFINE_KEYNAME_WITH_SAME_NAME(AudioFaderRear)
DEFINE_KEYNAME_WITH_SAME_NAME(AudioBalanceLeft)
DEFINE_KEYNAME_WITH_SAME_NAME(AudioBalanceRight)
DEFINE_KEYNAME_WITH_SAME_NAME(AudioBassBoostDown)
DEFINE_KEYNAME_WITH_SAME_NAME(AudioBassBoostUp)
DEFINE_KEYNAME_WITH_SAME_NAME(VolumeMute)
DEFINE_KEYNAME_WITH_SAME_NAME(VolumeDown)
DEFINE_KEYNAME_WITH_SAME_NAME(VolumeUp)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaPause)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaPlay)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaStop)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaNextTrack)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaPreviousTrack)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaPlayPause)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaTrackSkip)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaTrackStart)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaTrackEnd)
DEFINE_KEYNAME_WITH_SAME_NAME(SelectMedia)
DEFINE_KEYNAME_WITH_SAME_NAME(Blue)
DEFINE_KEYNAME_WITH_SAME_NAME(Brown)
DEFINE_KEYNAME_WITH_SAME_NAME(ChannelDown)
DEFINE_KEYNAME_WITH_SAME_NAME(ChannelUp)
DEFINE_KEYNAME_WITH_SAME_NAME(ClearFavorite0)
DEFINE_KEYNAME_WITH_SAME_NAME(ClearFavorite1)
DEFINE_KEYNAME_WITH_SAME_NAME(ClearFavorite2)
DEFINE_KEYNAME_WITH_SAME_NAME(ClearFavorite3)
DEFINE_KEYNAME_WITH_SAME_NAME(Dimmer)
DEFINE_KEYNAME_WITH_SAME_NAME(DisplaySwap)
DEFINE_KEYNAME_WITH_SAME_NAME(FastFwd)
DEFINE_KEYNAME_WITH_SAME_NAME(Green)
DEFINE_KEYNAME_WITH_SAME_NAME(Grey)
DEFINE_KEYNAME_WITH_SAME_NAME(Guide)
DEFINE_KEYNAME_WITH_SAME_NAME(InstantReplay)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaLast)
DEFINE_KEYNAME_WITH_SAME_NAME(Link)
DEFINE_KEYNAME_WITH_SAME_NAME(Live)
DEFINE_KEYNAME_WITH_SAME_NAME(Lock)
DEFINE_KEYNAME_WITH_SAME_NAME(NextDay)
DEFINE_KEYNAME_WITH_SAME_NAME(NextFavoriteChannel)
DEFINE_KEYNAME_WITH_SAME_NAME(OnDemand)
DEFINE_KEYNAME_WITH_SAME_NAME(PinPDown)
DEFINE_KEYNAME_WITH_SAME_NAME(PinPMove)
DEFINE_KEYNAME_WITH_SAME_NAME(PinPToggle)
DEFINE_KEYNAME_WITH_SAME_NAME(PinPUp)
DEFINE_KEYNAME_WITH_SAME_NAME(PlaySpeedDown)
DEFINE_KEYNAME_WITH_SAME_NAME(PlaySpeedReset)
DEFINE_KEYNAME_WITH_SAME_NAME(PlaySpeedUp)
DEFINE_KEYNAME_WITH_SAME_NAME(PrevDay)
DEFINE_KEYNAME_WITH_SAME_NAME(RandomToggle)
DEFINE_KEYNAME_WITH_SAME_NAME(RecallFavorite0)
DEFINE_KEYNAME_WITH_SAME_NAME(RecallFavorite1)
DEFINE_KEYNAME_WITH_SAME_NAME(RecallFavorite2)
DEFINE_KEYNAME_WITH_SAME_NAME(RecallFavorite3)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaRecord)
DEFINE_KEYNAME_WITH_SAME_NAME(RecordSpeedNext)
DEFINE_KEYNAME_WITH_SAME_NAME(Red)
DEFINE_KEYNAME_WITH_SAME_NAME(MediaRewind)
DEFINE_KEYNAME_WITH_SAME_NAME(RfBypass)
DEFINE_KEYNAME_WITH_SAME_NAME(ScanChannelsToggle)
DEFINE_KEYNAME_WITH_SAME_NAME(ScreenModeNext)
DEFINE_KEYNAME_WITH_SAME_NAME(Settings)
DEFINE_KEYNAME_WITH_SAME_NAME(SplitScreenToggle)
DEFINE_KEYNAME_WITH_SAME_NAME(StoreFavorite0)
DEFINE_KEYNAME_WITH_SAME_NAME(StoreFavorite1)
DEFINE_KEYNAME_WITH_SAME_NAME(StoreFavorite2)
DEFINE_KEYNAME_WITH_SAME_NAME(StoreFavorite3)
DEFINE_KEYNAME_WITH_SAME_NAME(Subtitle)
DEFINE_KEYNAME_WITH_SAME_NAME(AudioSurroundModeNext)
DEFINE_KEYNAME_WITH_SAME_NAME(Teletext)
DEFINE_KEYNAME_WITH_SAME_NAME(VideoModeNext)
DEFINE_KEYNAME_WITH_SAME_NAME(DisplayWide)
DEFINE_KEYNAME_WITH_SAME_NAME(Wink)
DEFINE_KEYNAME_WITH_SAME_NAME(Yellow)
#undef DEFINE_KEYNAME_WITH_SAME_NAME
#undef DEFINE_KEYNAME_INTERNAL

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

@ -42,7 +42,7 @@ DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit8)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Digit9)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Equal)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(IntlBackslash)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(IntlHash)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(IntlHash)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(IntlRo)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(IntlYen)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KeyA)
@ -97,9 +97,9 @@ DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Convert)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(KanaMode)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang1)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang2)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang3)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang4)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang5)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang3)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang4)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Lang5)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NonConvert)
// Control pad section
@ -131,21 +131,21 @@ DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad8)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Numpad9)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadAdd)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadBackspace)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadClear)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadClearEntry)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadClear)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadClearEntry)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadComma)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadDecimal)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadDivide)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadEnter)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadEqual)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryAdd)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryClear)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryRecall)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryStore)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryAdd)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryClear)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryRecall)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemoryStore)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMemorySubtract)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadMultiply)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadParenLeft)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadParenRight)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadParenLeft)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadParenRight)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(NumpadSubtract)
// Function section
@ -175,7 +175,7 @@ DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F22)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F23)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(F24)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Fn)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(FLock)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(FLock)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(PrintScreen)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(ScrollLock)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Pause)
@ -205,13 +205,12 @@ DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(VolumeUp)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(WakeUp)
// Legacy keys
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Abort)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Hyper)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Meta)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Resume)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Super)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Suspend)
DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Turbo)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Abort)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Hyper)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Resume)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Super)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Suspend)
// DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME(Turbo)
#undef DEFINE_PHYSICAL_KEY_CODE_NAME_WITH_SAME_NAME
#undef NS_DEFINE_PHYSICAL_KEY_CODE_NAME_INTERNAL

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

@ -122,7 +122,7 @@ CreateDirectoryTask::HandlerCallback()
if (HasError()) {
nsRefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
mErrorValue);
mPromise->MaybeReject(domError);
mPromise->MaybeRejectBrokenly(domError);
mPromise = nullptr;
return;
}

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

@ -287,7 +287,7 @@ CreateFileTask::HandlerCallback()
if (HasError()) {
nsRefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
mErrorValue);
mPromise->MaybeReject(domError);
mPromise->MaybeRejectBrokenly(domError);
mPromise = nullptr;
return;
}

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

@ -197,7 +197,7 @@ GetFileOrDirectoryTask::HandlerCallback()
if (HasError()) {
nsRefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
mErrorValue);
mPromise->MaybeReject(domError);
mPromise->MaybeRejectBrokenly(domError);
mPromise = nullptr;
return;
}

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

@ -185,7 +185,7 @@ RemoveTask::HandlerCallback()
if (HasError()) {
nsRefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
mErrorValue);
mPromise->MaybeReject(domError);
mPromise->MaybeRejectBrokenly(domError);
mPromise = nullptr;
return;
}

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

@ -1473,7 +1473,7 @@ ContentChild::RecvSystemMemoryAvailable(const uint64_t& aGetterId,
nsRefPtr<Promise> p = dont_AddRef(reinterpret_cast<Promise*>(aGetterId));
if (!aMemoryAvailable) {
p->MaybeReject(NS_LITERAL_STRING("Abnormal"));
p->MaybeReject(NS_ERROR_NOT_AVAILABLE);
return true;
}

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

@ -61,6 +61,7 @@
#include "TabChild.h"
#include "LoadContext.h"
#include "nsNetCID.h"
#include "gfxPrefs.h"
#include <algorithm>
using namespace mozilla::dom;
@ -1888,9 +1889,7 @@ bool
TabParent::UseAsyncPanZoom()
{
bool usingOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
bool asyncPanZoomEnabled =
Preferences::GetBool("layers.async-pan-zoom.enabled", false);
return (usingOffMainThreadCompositing && asyncPanZoomEnabled &&
return (usingOffMainThreadCompositing && gfxPrefs::AsyncPanZoomEnabled() &&
GetScrollingBehavior() == ASYNC_PAN_ZOOM);
}

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

@ -7,5 +7,3 @@
DIRS += ['interfaces', 'src']
TEST_DIRS += ['tests']
if CONFIG['ENABLE_TESTS']:
XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell.ini']

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

@ -4,5 +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/.
MOCHITEST_MANIFESTS += ['mochitest.ini']
MOCHITEST_MANIFESTS += ['mochitest/mochitest.ini']
if CONFIG['ENABLE_TESTS']:
XPCSHELL_TESTS_MANIFESTS += ['xpcshell/xpcshell.ini']

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

@ -1,9 +1,6 @@
[DEFAULT]
head = header_helpers.js
tail =
support-files =
test_sms_basics.html
test_smsfilter.html
[test_smsservice_createsmsmessage.js]
[test_wsp_pdu_helper.js]

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

@ -7,6 +7,7 @@
#include "mozilla/dom/Promise.h"
#include "jsfriendapi.h"
#include "mozilla/dom/DOMError.h"
#include "mozilla/dom/OwningNonNull.h"
#include "mozilla/dom/PromiseBinding.h"
#include "mozilla/CycleCollectedJSRuntime.h"
@ -1431,5 +1432,15 @@ PromiseWorkerProxy::CleanUp(JSContext* aCx)
mCleanedUp = true;
}
// Specializations of MaybeRejectBrokenly we actually support.
template<>
void Promise::MaybeRejectBrokenly(const nsRefPtr<DOMError>& aArg) {
MaybeSomething(aArg, &Promise::MaybeReject);
}
template<>
void Promise::MaybeRejectBrokenly(const nsAString& aArg) {
MaybeSomething(aArg, &Promise::MaybeReject);
}
} // namespace dom
} // namespace mozilla

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

@ -26,6 +26,7 @@ namespace mozilla {
namespace dom {
class AnyCallback;
class DOMError;
class PromiseCallback;
class PromiseInit;
class PromiseNativeHandler;
@ -89,11 +90,21 @@ public:
MaybeSomething(aArg, &Promise::MaybeResolve);
}
// aArg is a const reference so we can pass rvalues like NS_ERROR_*
template <typename T>
void MaybeReject(const T& aArg) {
inline void MaybeReject(nsresult aArg) {
MOZ_ASSERT(NS_FAILED(aArg));
MaybeSomething(aArg, &Promise::MaybeReject);
}
// DO NOT USE MaybeRejectBrokenly with in new code. Promises should be
// rejected with Error instances.
// Note: MaybeRejectBrokenly is a template so we can use it with DOMError
// without instantiating the DOMError specialization of MaybeSomething in
// every translation unit that includes this header, because that would
// require use to include DOMError.h either here or in all those translation
// units.
template<typename T>
void MaybeRejectBrokenly(const T& aArg); // Not implemented by default; see
// specializations in the .cpp for
// the T values we support.
// WebIDL

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

@ -1494,10 +1494,13 @@ this.PushService = {
let iccInfo = icc.getIccInfo(clientId);
if (iccInfo) {
debug("Running on mobile data");
let ips = {};
let prefixLengths = {};
nm.active.getAddresses(ips, prefixLengths);
return {
mcc: iccInfo.mcc,
mnc: iccInfo.mnc,
ip: nm.active.ip
ip: ips.value[0]
}
}
}

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

@ -312,7 +312,7 @@ function CellBroadcastMessage(pdu) {
this.language = pdu.language;
this.body = pdu.fullBody;
this.messageClass = pdu.messageClass;
this.timestamp = new Date(pdu.timestamp);
this.timestamp = pdu.timestamp;
if (pdu.etws != null) {
this.etws = new CellBroadcastEtwsInfo(pdu.etws);

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

@ -12791,9 +12791,17 @@ SimRecordHelperObject.prototype = {
let ICCUtilsHelper = this.context.ICCUtilsHelper;
let RIL = this.context.RIL;
// TS 31.102, clause 4.2.18 EFAD
let mncLength = 0;
if (ad && ad[3]) {
mncLength = ad[3] & 0x0f;
if (mncLength != 0x02 && mncLength != 0x03) {
mncLength = 0;
}
}
// The 4th byte of the response is the length of MNC.
let mccMnc = ICCUtilsHelper.parseMccMncFromImsi(RIL.iccInfoPrivate.imsi,
ad && ad[3]);
mncLength);
if (mccMnc) {
RIL.iccInfo.mcc = mccMnc.mcc;
RIL.iccInfo.mnc = mccMnc.mnc;
@ -14130,6 +14138,7 @@ ICCUtilsHelperObject.prototype = {
* The imsi of icc.
* @param mncLength [optional]
* The length of mnc.
* Zero indicates we haven't got a valid mnc length.
*
* @return An object contains the parsing result of mcc and mnc.
* Or null if any error occurred.

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

@ -2504,7 +2504,7 @@ add_test(function test_reading_ad_and_parsing_mcc_mnc() {
io.loadTransparentEF = function fakeLoadTransparentEF(options) {
let ad = [0x00, 0x00, 0x00];
if (mncLengthInEf) {
if (typeof mncLengthInEf === 'number') {
ad.push(mncLengthInEf);
}
@ -2531,9 +2531,20 @@ add_test(function test_reading_ad_and_parsing_mcc_mnc() {
}
do_test(undefined, "466923202422409", "466", "92" );
do_test(0x00, "466923202422409", "466", "92" );
do_test(0x01, "466923202422409", "466", "92" );
do_test(0x02, "466923202422409", "466", "92" );
do_test(0x03, "466923202422409", "466", "923");
do_test(0x04, "466923202422409", "466", "92" );
do_test(0xff, "466923202422409", "466", "92" );
do_test(undefined, "310260542718417", "310", "260");
do_test(0x00, "310260542718417", "310", "260");
do_test(0x01, "310260542718417", "310", "260");
do_test(0x02, "310260542718417", "310", "26" );
do_test(0x03, "310260542718417", "310", "260");
do_test(0x04, "310260542718417", "310", "260");
do_test(0xff, "310260542718417", "310", "260");
run_next_test();
});

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

@ -76,7 +76,7 @@ public:
NS_IMETHODIMP
NotifyDialError(const nsAString& aError)
{
mPromise->MaybeReject(aError);
mPromise->MaybeRejectBrokenly(aError);
return NS_OK;
}
@ -255,13 +255,13 @@ Telephony::DialInternal(uint32_t aServiceId, const nsAString& aNumber,
nsRefPtr<Promise> promise = new Promise(global);
if (!IsValidNumber(aNumber) || !IsValidServiceId(aServiceId)) {
promise->MaybeReject(NS_LITERAL_STRING("InvalidAccessError"));
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
return promise.forget();
}
// We only support one outgoing call at a time.
if (HasDialingCall()) {
promise->MaybeReject(NS_LITERAL_STRING("InvalidStateError"));
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}
@ -269,7 +269,7 @@ Telephony::DialInternal(uint32_t aServiceId, const nsAString& aNumber,
new Callback(this, promise, aServiceId, aNumber);
nsresult rv = mService->Dial(aServiceId, aNumber, aIsEmergency, callback);
if (NS_FAILED(rv)) {
promise->MaybeReject(NS_LITERAL_STRING("InvalidStateError"));
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
return promise.forget();
}

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

@ -3,6 +3,7 @@ support-files =
inert_style.css
[test_bug900724.html]
[test_bug1017896.html]
[test_content_element.html]
[test_nested_content_element.html]
[test_dest_insertion_points.html]
@ -16,6 +17,7 @@ support-files =
[test_document_register_stack.html]
[test_document_shared_registry.html]
[test_template.html]
[test_template_xhtml.html]
[test_shadowroot.html]
[test_shadowroot_inert_element.html]
[test_shadowroot_style.html]

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

@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1017896
-->
<head>
<title>Test template element in stale document.</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1017896">Bug 1017896</a>
<div id="container"></div>
<script>
SimpleTest.waitForExplicitFinish();
var frame = document.createElement("iframe");
document.getElementById("container").appendChild(frame);
var staleFrameDoc = frame.contentDocument;
setTimeout(function() {
var v = staleFrameDoc.createElement("div");
v.innerHTML = "<template>Content</template>";
is(v.firstChild.content.childNodes.length, 1, "Template should have one child in template content.");
SimpleTest.finish();
}, 0);
</script>
</body>
</html>

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