mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 13:55:43 +00:00
Merge m-c to inbound a=merge
This commit is contained in:
commit
b492021bca
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="07a1a20b86931ee9911b16df94df60a178825bb2"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="07a1a20b86931ee9911b16df94df60a178825bb2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="07a1a20b86931ee9911b16df94df60a178825bb2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="07a1a20b86931ee9911b16df94df60a178825bb2"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="07a1a20b86931ee9911b16df94df60a178825bb2"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="07a1a20b86931ee9911b16df94df60a178825bb2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="07a1a20b86931ee9911b16df94df60a178825bb2"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="07a1a20b86931ee9911b16df94df60a178825bb2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"git_revision": "8e64346ce8197b50b815a294278797bc144aa3e6",
|
||||
"git_revision": "07a1a20b86931ee9911b16df94df60a178825bb2",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "1bbaa54b674c42e0d8b2fe31d8b0080901811fa0",
|
||||
"revision": "99b2099a5fa6ac2567993f2c859d651934556464",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="07a1a20b86931ee9911b16df94df60a178825bb2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="8e64346ce8197b50b815a294278797bc144aa3e6"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="07a1a20b86931ee9911b16df94df60a178825bb2"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -100,7 +100,7 @@ nsContextMenu.prototype = {
|
||||
this.linkURI = makeURI(this.linkURL);
|
||||
} catch (ex) {}
|
||||
|
||||
this.linkText = this.selectionInfo.linkText;
|
||||
this.linkTextStr = this.selectionInfo.linkText;
|
||||
this.onPlainTextLink = true;
|
||||
}
|
||||
|
||||
@ -524,7 +524,7 @@ nsContextMenu.prototype = {
|
||||
this.link = null;
|
||||
this.linkURL = "";
|
||||
this.linkURI = null;
|
||||
this.linkText = "";
|
||||
this.linkTextStr = "";
|
||||
this.linkProtocol = "";
|
||||
this.linkDownload = "";
|
||||
this.linkHasNoReferrer = false;
|
||||
@ -700,7 +700,7 @@ nsContextMenu.prototype = {
|
||||
this.link = elem;
|
||||
this.linkURL = this.getLinkURL();
|
||||
this.linkURI = this.getLinkURI();
|
||||
this.linkText = this.getLinkText();
|
||||
this.linkTextStr = this.getLinkText();
|
||||
this.linkProtocol = this.getLinkProtocol();
|
||||
this.onMailtoLink = (this.linkProtocol == "mailto");
|
||||
this.onSaveableLink = this.isLinkSaveable( this.link );
|
||||
@ -1281,7 +1281,7 @@ nsContextMenu.prototype = {
|
||||
// Save URL of clicked-on link.
|
||||
saveLink: function() {
|
||||
urlSecurityCheck(this.linkURL, this.principal);
|
||||
this.saveHelper(this.linkURL, this.linkText, null, true, this.ownerDoc,
|
||||
this.saveHelper(this.linkURL, this.linkTextStr, null, true, this.ownerDoc,
|
||||
gContextMenuContentData.documentURIObject,
|
||||
gContextMenuContentData.frameOuterWindowID,
|
||||
this.linkDownload);
|
||||
@ -1496,6 +1496,11 @@ nsContextMenu.prototype = {
|
||||
return text;
|
||||
},
|
||||
|
||||
// Kept for addon compat
|
||||
linkText: function() {
|
||||
return this.linkTextStr;
|
||||
},
|
||||
|
||||
isMediaURLReusable: function(aURL) {
|
||||
return !/^(?:blob|mediasource):/.test(aURL);
|
||||
},
|
||||
@ -1563,7 +1568,7 @@ nsContextMenu.prototype = {
|
||||
|
||||
bookmarkLink: function CM_bookmarkLink() {
|
||||
window.top.PlacesCommandHook.bookmarkLink(PlacesUtils.bookmarksMenuFolderId,
|
||||
this.linkURL, this.linkText);
|
||||
this.linkURL, this.linkTextStr);
|
||||
},
|
||||
|
||||
addBookmarkForFrame: function CM_addBookmarkForFrame() {
|
||||
@ -1657,7 +1662,7 @@ nsContextMenu.prototype = {
|
||||
// Formats the 'Search <engine> for "<selection or link text>"' context menu.
|
||||
formatSearchContextItem: function() {
|
||||
var menuItem = document.getElementById("context-searchselect");
|
||||
let selectedText = this.isTextSelected ? this.textSelected : this.linkText;
|
||||
let selectedText = this.isTextSelected ? this.textSelected : this.linkTextStr;
|
||||
|
||||
// Store searchTerms in context menu item so we know what to search onclick
|
||||
menuItem.searchTerms = selectedText;
|
||||
|
@ -3347,11 +3347,13 @@
|
||||
},
|
||||
|
||||
/*
|
||||
* Telemetry related helpers for recording tab switch timing.
|
||||
* Telemetry and Profiler related helpers for recording tab switch
|
||||
* timing.
|
||||
*/
|
||||
|
||||
startTabSwitch: function () {
|
||||
TelemetryStopwatch.start("FX_TAB_SWITCH_TOTAL_E10S_MS", window);
|
||||
this.addMarker("AsyncTabSwitch:Start");
|
||||
},
|
||||
|
||||
finishTabSwitch: function () {
|
||||
@ -3360,6 +3362,7 @@
|
||||
if (time != -1) {
|
||||
TelemetryStopwatch.finish("FX_TAB_SWITCH_TOTAL_E10S_MS", window);
|
||||
this.log("DEBUG: tab switch time = " + time);
|
||||
this.addMarker("AsyncTabSwitch:Finish");
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -3367,6 +3370,7 @@
|
||||
spinnerDisplayed: function () {
|
||||
if (this.spinnerTab) {
|
||||
TelemetryStopwatch.start("FX_TAB_SWITCH_SPINNER_VISIBLE_MS", window);
|
||||
this.addMarker("AsyncTabSwitch:SpinnerShown");
|
||||
}
|
||||
},
|
||||
|
||||
@ -3375,11 +3379,18 @@
|
||||
this.log("DEBUG: spinner time = " +
|
||||
TelemetryStopwatch.timeElapsed("FX_TAB_SWITCH_SPINNER_VISIBLE_MS", window));
|
||||
TelemetryStopwatch.finish("FX_TAB_SWITCH_SPINNER_VISIBLE_MS", window);
|
||||
this.addMarker("AsyncTabSwitch:SpinnerHidden");
|
||||
// we do not get a onPaint after displaying the spinner
|
||||
this.finishTabSwitch();
|
||||
}
|
||||
},
|
||||
|
||||
addMarker: function(marker) {
|
||||
if (Services.profiler) {
|
||||
Services.profiler.AddMarker(marker);
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Debug related logging for switcher.
|
||||
*/
|
||||
|
@ -89,18 +89,15 @@ function waitForProviderLoad(cb) {
|
||||
waitForCondition(function() {
|
||||
let sbrowser = document.getElementById("social-sidebar-browser");
|
||||
let provider = SocialSidebar.provider;
|
||||
let postActivation = provider && gBrowser.contentDocument.location.href == provider.origin + "/browser/browser/base/content/test/social/social_postActivation.html";
|
||||
let postActivation = provider && gBrowser.contentDocument &&
|
||||
gBrowser.contentDocument.location.href == provider.origin + "/browser/browser/base/content/test/social/social_postActivation.html";
|
||||
|
||||
return provider &&
|
||||
provider.profile &&
|
||||
provider.profile.displayName &&
|
||||
postActivation &&
|
||||
sbrowser.docShellIsActive;
|
||||
return postActivation && sbrowser.docShellIsActive;
|
||||
}, function() {
|
||||
// executeSoon to let the browser UI observers run first
|
||||
executeSoon(cb);
|
||||
},
|
||||
"waitForProviderLoad: provider profile was not set");
|
||||
"waitForProviderLoad: provider was not loaded");
|
||||
}
|
||||
|
||||
|
||||
@ -178,22 +175,19 @@ let gProviders = [
|
||||
{
|
||||
name: "provider 1",
|
||||
origin: "https://example.com",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html?provider1",
|
||||
workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js#no-profile,no-recommend",
|
||||
sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar_empty.html?provider1",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
},
|
||||
{
|
||||
name: "provider 2",
|
||||
origin: "https://test1.example.com",
|
||||
sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar.html?provider2",
|
||||
workerURL: "https://test1.example.com/browser/browser/base/content/test/social/social_worker.js#no-profile,no-recommend",
|
||||
sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar_empty.html?provider2",
|
||||
iconURL: "chrome://branding/content/icon64.png"
|
||||
},
|
||||
{
|
||||
name: "provider 3",
|
||||
origin: "https://test2.example.com",
|
||||
sidebarURL: "https://test2.example.com/browser/browser/base/content/test/social/social_sidebar.html?provider2",
|
||||
workerURL: "https://test2.example.com/browser/browser/base/content/test/social/social_worker.js#no-profile,no-recommend",
|
||||
sidebarURL: "https://test2.example.com/browser/browser/base/content/test/social/social_sidebar_empty.html?provider2",
|
||||
iconURL: "chrome://branding/content/about-logo.png"
|
||||
}
|
||||
];
|
||||
|
@ -218,11 +218,6 @@ let LoopRoomsInternal = {
|
||||
};
|
||||
}
|
||||
|
||||
// For now, disable encryption/context if context is disabled
|
||||
if (!MozLoopService.getLoopPref("contextInConverations.enabled")) {
|
||||
return getUnencryptedData();
|
||||
}
|
||||
|
||||
var newRoomData = extend({}, roomData);
|
||||
|
||||
if (!newRoomData.context) {
|
||||
@ -700,7 +695,8 @@ let LoopRoomsInternal = {
|
||||
};
|
||||
|
||||
// If we're not encrypting currently, then only send the roomName.
|
||||
if (!Services.prefs.getBoolPref("loop.contextInConverations.enabled")) {
|
||||
// XXX This should go away once bug 1153788 is fixed.
|
||||
if (!sendData.context) {
|
||||
sendData = {
|
||||
roomName: newRoomName
|
||||
};
|
||||
|
@ -11,8 +11,6 @@ Cu.import("resource://gre/modules/Promise.jsm");
|
||||
|
||||
let openChatOrig = Chat.open;
|
||||
|
||||
const kContextEnabledPref = "loop.contextInConverations.enabled";
|
||||
|
||||
const kGuestKey = "uGIs-kGbYt1hBBwjyW7MLQ";
|
||||
|
||||
// Rooms details as responded by the server.
|
||||
@ -299,14 +297,10 @@ add_task(function* setup_server() {
|
||||
let body = CommonUtils.readBytesFromInputStream(req.bodyInputStream);
|
||||
let data = JSON.parse(body);
|
||||
|
||||
if (Services.prefs.getBoolPref(kContextEnabledPref)) {
|
||||
Assert.equal(data.roomOwner, kCreateRoomProps.roomOwner);
|
||||
Assert.equal(data.maxSize, kCreateRoomProps.maxSize);
|
||||
Assert.ok(!("decryptedContext" in data), "should not have any decrypted data");
|
||||
Assert.ok("context" in data, "should have context");
|
||||
} else {
|
||||
Assert.deepEqual(data, kCreateRoomUnencryptedProps);
|
||||
}
|
||||
Assert.equal(data.roomOwner, kCreateRoomProps.roomOwner);
|
||||
Assert.equal(data.maxSize, kCreateRoomProps.maxSize);
|
||||
Assert.ok(!("decryptedContext" in data), "should not have any decrypted data");
|
||||
Assert.ok("context" in data, "should have context");
|
||||
|
||||
res.write(JSON.stringify(kCreateRoomData));
|
||||
} else {
|
||||
@ -353,15 +347,11 @@ add_task(function* setup_server() {
|
||||
res.finish();
|
||||
} else if (req.method == "PATCH") {
|
||||
let data = getJSONData(req.bodyInputStream);
|
||||
if (Services.prefs.getBoolPref(kContextEnabledPref)) {
|
||||
Assert.ok("context" in data, "should have encrypted context");
|
||||
// We return a fake encrypted name here as the context is
|
||||
// encrypted.
|
||||
returnRoomDetails(res, "fakeEncrypted");
|
||||
} else {
|
||||
Assert.ok(!("context" in data), "should not have encrypted context");
|
||||
returnRoomDetails(res, data.roomName);
|
||||
}
|
||||
|
||||
Assert.ok("context" in data, "should have encrypted context");
|
||||
// We return a fake encrypted name here as the context is
|
||||
// encrypted.
|
||||
returnRoomDetails(res, "fakeEncrypted");
|
||||
} else {
|
||||
roomDetail.context = room.context;
|
||||
res.setStatusLine(null, 200, "OK");
|
||||
@ -415,20 +405,6 @@ add_task(function* test_errorStates() {
|
||||
|
||||
// Test if creating a new room works as expected.
|
||||
add_task(function* test_createRoom() {
|
||||
Services.prefs.setBoolPref(kContextEnabledPref, true);
|
||||
|
||||
var expectedRoom = extend({}, kCreateRoomProps);
|
||||
expectedRoom.roomToken = kCreateRoomData.roomToken;
|
||||
|
||||
gExpectedAdds.push(expectedRoom);
|
||||
let room = yield LoopRooms.promise("create", kCreateRoomProps);
|
||||
compareRooms(room, expectedRoom);
|
||||
});
|
||||
|
||||
// XXX Test unencrypted rooms. This will go away once we switch encryption on.
|
||||
add_task(function* test_createRoom_unencrypted() {
|
||||
Services.prefs.setBoolPref(kContextEnabledPref, false);
|
||||
|
||||
var expectedRoom = extend({}, kCreateRoomProps);
|
||||
expectedRoom.roomToken = kCreateRoomData.roomToken;
|
||||
|
||||
@ -601,19 +577,11 @@ add_task(function* test_sendConnectionStatus() {
|
||||
|
||||
// Test if renaming a room works as expected.
|
||||
add_task(function* test_renameRoom() {
|
||||
Services.prefs.setBoolPref(kContextEnabledPref, true);
|
||||
let roomToken = "_nxD4V4FflQ";
|
||||
let renameData = yield LoopRooms.promise("rename", roomToken, "fakeName");
|
||||
Assert.equal(renameData.roomName, "fakeEncrypted", "should have set the new name");
|
||||
});
|
||||
|
||||
add_task(function* test_renameRoom_unencrpyted() {
|
||||
Services.prefs.setBoolPref(kContextEnabledPref, false);
|
||||
let roomToken = "_nxD4V4FflQ";
|
||||
let renameData = yield LoopRooms.promise("rename", roomToken, "fakeName");
|
||||
Assert.equal(renameData.roomName, "fakeName", "should have set the new name");
|
||||
});
|
||||
|
||||
add_task(function* test_roomDeleteNotifications() {
|
||||
gExpectedDeletes.push("_nxD4V4FflQ");
|
||||
roomsPushNotification("5", kChannelGuest);
|
||||
@ -657,7 +625,6 @@ function run_test() {
|
||||
do_register_cleanup(function () {
|
||||
// Revert original Chat.open implementation
|
||||
Chat.open = openChatOrig;
|
||||
Services.prefs.clearUserPref(kContextEnabledPref);
|
||||
Services.prefs.clearUserPref("loop.key");
|
||||
|
||||
MozLoopServiceInternal.fxAOAuthTokenData = null;
|
||||
|
@ -1829,7 +1829,15 @@ MarkupContainer.prototype = {
|
||||
this.hovered = false;
|
||||
this.markup.navigate(this);
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
// Preventing the default behavior will avoid the body to gain focus on
|
||||
// mouseup (through bubbling) when clicking on a non focusable node in the
|
||||
// line. So, if the click happened outside of a focusable element, do
|
||||
// prevent the default behavior, so that the tagname or textcontent gains
|
||||
// focus.
|
||||
if (!target.closest(".open [tabindex]")) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
// Start dragging the container after a delay.
|
||||
this.markup._dragStartEl = target;
|
||||
|
@ -8,7 +8,7 @@
|
||||
// the first focusable element in the corresponding MarkupContainer so that the
|
||||
// keyboard can be used immediately.
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf8,<div></div>Text node";
|
||||
const TEST_URL = "data:text/html;charset=utf8,<div class='test-class'></div>Text node";
|
||||
|
||||
add_task(function*() {
|
||||
let {inspector, toolbox} = yield addTab(TEST_URL).then(openInspector);
|
||||
@ -31,4 +31,18 @@ add_task(function*() {
|
||||
is(inspector.markup.doc.activeElement,
|
||||
getContainerForNodeFront(divFront, inspector).editor.tag,
|
||||
"The currently focused element is the div's tagname");
|
||||
|
||||
info("Click on the test-class attribute, to make sure it gets focused");
|
||||
let editor = getContainerForNodeFront(divFront, inspector).editor;
|
||||
let attributeEditor = editor.attrElements.get("class").querySelector(".editable");
|
||||
|
||||
let onFocus = once(attributeEditor, "focus");
|
||||
EventUtils.synthesizeMouseAtCenter(attributeEditor, {type: "mousedown"},
|
||||
inspector.markup.doc.defaultView);
|
||||
EventUtils.synthesizeMouseAtCenter(attributeEditor, {type: "mouseup"},
|
||||
inspector.markup.doc.defaultView);
|
||||
yield onFocus;
|
||||
|
||||
is(inspector.markup.doc.activeElement, attributeEditor,
|
||||
"The currently focused element is the div's class attribute");
|
||||
});
|
||||
|
@ -266,8 +266,8 @@ GraphsController.prototype = {
|
||||
yield this._rendering.promise;
|
||||
}
|
||||
|
||||
for (let graphName in this._graphs) {
|
||||
yield this._graphs[graphName].destroy();
|
||||
for (let graph of this.getWidgets()) {
|
||||
yield graph.destroy();
|
||||
}
|
||||
}),
|
||||
|
||||
@ -277,9 +277,9 @@ GraphsController.prototype = {
|
||||
*/
|
||||
setTheme: function (options={}) {
|
||||
let theme = options.theme || this._getTheme();
|
||||
for (let graph in this._graphs) {
|
||||
this._graphs[graph].setTheme(theme);
|
||||
this._graphs[graph].refresh({ force: options.redraw });
|
||||
for (let graph of this.getWidgets()) {
|
||||
graph.setTheme(theme);
|
||||
graph.refresh({ force: options.redraw });
|
||||
}
|
||||
},
|
||||
|
||||
@ -348,6 +348,14 @@ GraphsController.prototype = {
|
||||
return this._getPrimaryLink().getMappedSelection({ mapStart, mapEnd });
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns an array of graphs that have been created, not necessarily
|
||||
* enabled currently.
|
||||
*/
|
||||
getWidgets: function () {
|
||||
return Object.keys(this._graphs).map(name => this._graphs[name]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Drops the selection.
|
||||
*/
|
||||
|
@ -43,6 +43,7 @@ support-files =
|
||||
[browser_perf-details-03.js]
|
||||
[browser_perf-details-04.js]
|
||||
[browser_perf-details-05.js]
|
||||
[browser_perf-details-06.js]
|
||||
[browser_perf-events-calltree.js]
|
||||
[browser_perf-front-basic-profiler-01.js]
|
||||
[browser_perf-front-basic-timeline-01.js]
|
||||
|
61
browser/devtools/performance/test/browser_perf-details-06.js
Normal file
61
browser/devtools/performance/test/browser_perf-details-06.js
Normal file
@ -0,0 +1,61 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that the views with `shouldUpdateWhileMouseIsActive` works as intended.
|
||||
*/
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, OverviewView, DetailsView, WaterfallView, JsFlameGraphView } = panel.panelWin;
|
||||
|
||||
yield startRecording(panel);
|
||||
yield stopRecording(panel);
|
||||
|
||||
// Set the debounce on WaterfallView and JsFlameGraphView to 0
|
||||
WaterfallView.rangeChangeDebounceTime = 0;
|
||||
JsFlameGraphView.rangeChangeDebounceTime = 0;
|
||||
|
||||
yield DetailsView.selectView("js-flamegraph");
|
||||
let duration = PerformanceController.getCurrentRecording().getDuration();
|
||||
|
||||
// Fake an active mouse
|
||||
Object.defineProperty(OverviewView, "isMouseActive", { value: true });
|
||||
|
||||
// Flame Graph should update on every selection, debounced, while mouse is down
|
||||
let flamegraphRendered = once(JsFlameGraphView, EVENTS.JS_FLAMEGRAPH_RENDERED);
|
||||
OverviewView.emit(EVENTS.OVERVIEW_RANGE_SELECTED, { startTime: 0, endTime: duration });
|
||||
yield flamegraphRendered;
|
||||
ok(true, "FlameGraph rerenders when mouse is active (1)");
|
||||
|
||||
flamegraphRendered = once(JsFlameGraphView, EVENTS.JS_FLAMEGRAPH_RENDERED);
|
||||
OverviewView.emit(EVENTS.OVERVIEW_RANGE_SELECTED, { startTime: 0, endTime: duration });
|
||||
yield flamegraphRendered;
|
||||
ok(true, "FlameGraph rerenders when mouse is active (2)");
|
||||
|
||||
ok(OverviewView.isMouseActive, "Fake mouse is still active");
|
||||
|
||||
// Fake an inactive mouse for rerender
|
||||
Object.defineProperty(OverviewView, "isMouseActive", { value: false });
|
||||
yield DetailsView.selectView("waterfall");
|
||||
|
||||
// Fake an active mouse for rerender
|
||||
Object.defineProperty(OverviewView, "isMouseActive", { value: true });
|
||||
|
||||
let oneSecondElapsed = false;
|
||||
let waterfallRendered = false;
|
||||
|
||||
WaterfallView.on(EVENTS.WATERFALL_RENDERED, () => waterfallRendered = true);
|
||||
|
||||
// Keep firing range selection events for one second
|
||||
idleWait(1000).then(() => oneSecondElapsed = true);
|
||||
yield waitUntil(() => {
|
||||
OverviewView.emit(EVENTS.OVERVIEW_RANGE_SELECTED, { startTime: 0, endTime: duration });
|
||||
return oneSecondElapsed;
|
||||
});
|
||||
|
||||
ok(OverviewView.isMouseActive, "Fake mouse is still active");
|
||||
ok(!waterfallRendered, "the waterfall view should not have been rendered while mouse is active.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
@ -97,9 +97,10 @@ let OverviewView = {
|
||||
* false otherwise.
|
||||
*/
|
||||
get isMouseActive() {
|
||||
return (this.markersOverview && this.markersOverview.isMouseActive) ||
|
||||
(this.memoryOverview && this.memoryOverview.isMouseActive) ||
|
||||
(this.framerateGraph && this.framerateGraph.isMouseActive);
|
||||
// Fetch all graphs currently stored in the GraphsController.
|
||||
// These graphs are not necessarily active, but will not have
|
||||
// an active mouse, in that case.
|
||||
return !!this.graphs.getWidgets().some(e => e.isMouseActive);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -119,7 +119,9 @@ function test() {
|
||||
info(customPresetIndex);
|
||||
ok(customPresetIndex >= 0, "is the previously added preset (idx = " + customPresetIndex + ") in the list of items");
|
||||
|
||||
let resizePromise = instance._test_notifyOnResize();
|
||||
instance.menulist.selectedIndex = customPresetIndex;
|
||||
yield resizePromise;
|
||||
|
||||
is(content.innerWidth, 456, "add preset, and selected in the list, dimension valid (width)");
|
||||
is(content.innerHeight, 123, "add preset, and selected in the list, dimension valid (height)");
|
||||
|
@ -53,6 +53,16 @@ exports.parseLocation = function parseLocation (frame) {
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines if the given frame is the (root) frame.
|
||||
*
|
||||
* @param object frame
|
||||
* @return boolean
|
||||
*/
|
||||
exports.isRoot = function isRoot({ location }) {
|
||||
return location === "(root)";
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the specified function represents a chrome or content frame.
|
||||
*
|
||||
@ -61,8 +71,13 @@ exports.parseLocation = function parseLocation (frame) {
|
||||
* @return boolean
|
||||
* True if a content frame, false if a chrome frame.
|
||||
*/
|
||||
exports.isContent = function isContent ({ category, location }) {
|
||||
exports.isContent = function isContent (frame) {
|
||||
if (exports.isRoot(frame)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Only C++ stack frames have associated category information.
|
||||
const { category, location } = frame;
|
||||
return !!(!category &&
|
||||
!CHROME_SCHEMES.find(e => location.includes(e)) &&
|
||||
CONTENT_SCHEMES.find(e => location.includes(e)));
|
||||
|
@ -93,15 +93,20 @@ ThreadNode.prototype = {
|
||||
|
||||
let sampleFrames = sample.frames;
|
||||
|
||||
if (!options.invertTree) {
|
||||
// Remove the (root) node if the tree is not inverted: we will synthesize
|
||||
// our own root in the view. However, for inverted trees, we wish to be
|
||||
// able to differentiate between (root)->A->B->C and (root)->B->C stacks,
|
||||
// so we need the root node in that case.
|
||||
sampleFrames = sampleFrames.slice(1);
|
||||
}
|
||||
|
||||
// Filter out platform frames if only content-related function calls
|
||||
// should be taken into consideration.
|
||||
if (options.contentOnly) {
|
||||
// The (root) node is not considered a content function, it'll be removed.
|
||||
sampleFrames = FrameUtils.filterPlatformData(sampleFrames);
|
||||
} else {
|
||||
// Remove the (root) node manually.
|
||||
sampleFrames = sampleFrames.slice(1);
|
||||
}
|
||||
|
||||
// If no frames remain after filtering, then this is a leaf node, no need
|
||||
// to continue.
|
||||
if (!sampleFrames.length) {
|
||||
|
@ -20,79 +20,56 @@ function test()
|
||||
let {tab} = yield loadTab(TEST_URI);
|
||||
hud = yield openConsole(tab);
|
||||
let jsterm = hud.jsterm;
|
||||
let result;
|
||||
let vview;
|
||||
let msg;
|
||||
|
||||
let msg = yield execute("fooObj");
|
||||
ok(msg, "output message found");
|
||||
|
||||
let anchor = msg.querySelector("a");
|
||||
let body = msg.querySelector(".message-body");
|
||||
ok(anchor, "object anchor");
|
||||
ok(body, "message body");
|
||||
ok(body.textContent.includes('testProp: "testValue"'), "message text check");
|
||||
|
||||
msg.scrollIntoView();
|
||||
executeSoon(() => {
|
||||
EventUtils.synthesizeMouse(anchor, 2, 2, {}, hud.iframeWindow);
|
||||
});
|
||||
|
||||
let vviewVar = yield jsterm.once("variablesview-fetched");
|
||||
let vview = vviewVar._variablesView;
|
||||
ok(vview, "variables view object");
|
||||
|
||||
let [result] = yield findVariableViewProperties(vviewVar, [
|
||||
{ name: "testProp", value: "testValue" },
|
||||
], { webconsole: hud });
|
||||
yield openSidebar("fooObj",
|
||||
'testProp: "testValue"',
|
||||
{ name: "testProp", value: "testValue" });
|
||||
|
||||
let prop = result.matchedProp;
|
||||
ok(prop, "matched the |testProp| property in the variables view");
|
||||
|
||||
vview.window.focus();
|
||||
|
||||
executeSoon(() => {
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
});
|
||||
yield jsterm.once("sidebar-closed");
|
||||
let sidebarClosed = jsterm.once("sidebar-closed");
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
yield sidebarClosed;
|
||||
|
||||
jsterm.clearOutput();
|
||||
|
||||
msg = yield execute("window.location");
|
||||
ok(msg, "output message found");
|
||||
|
||||
body = msg.querySelector(".message-body");
|
||||
ok(body, "message body");
|
||||
anchor = msg.querySelector("a");
|
||||
ok(anchor, "object anchor");
|
||||
ok(body.textContent.includes("Location \u2192 http://example.com/browser/"),
|
||||
"message text check");
|
||||
|
||||
msg.scrollIntoView();
|
||||
executeSoon(() => {
|
||||
EventUtils.synthesizeMouse(anchor, 2, 2, {}, hud.iframeWindow)
|
||||
});
|
||||
vviewVar = yield jsterm.once("variablesview-fetched");
|
||||
|
||||
vview = vviewVar._variablesView;
|
||||
ok(vview, "variables view object");
|
||||
|
||||
yield findVariableViewProperties(vviewVar, [
|
||||
{ name: "host", value: "example.com" },
|
||||
], { webconsole: hud });
|
||||
yield openSidebar("window.location",
|
||||
"Location \u2192 http://example.com/browser/",
|
||||
{ name: "host", value: "example.com" });
|
||||
|
||||
vview.window.focus();
|
||||
|
||||
msg.scrollIntoView();
|
||||
executeSoon(() => {
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
});
|
||||
sidebarClosed = jsterm.once("sidebar-closed");
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
yield sidebarClosed;
|
||||
|
||||
yield jsterm.once("sidebar-closed");
|
||||
}
|
||||
function* openSidebar(objName, expectedText, expectedObj) {
|
||||
msg = yield jsterm.execute(objName);
|
||||
ok(msg, "output message found");
|
||||
|
||||
function execute(str) {
|
||||
let deferred = promise.defer();
|
||||
hud.jsterm.execute(str, (msg) => {
|
||||
deferred.resolve(msg);
|
||||
});
|
||||
return deferred.promise;
|
||||
let anchor = msg.querySelector("a");
|
||||
let body = msg.querySelector(".message-body");
|
||||
ok(anchor, "object anchor");
|
||||
ok(body, "message body");
|
||||
ok(body.textContent.includes(expectedText), "message text check");
|
||||
|
||||
msg.scrollIntoView();
|
||||
yield EventUtils.synthesizeMouse(anchor, 2, 2, {}, hud.iframeWindow);
|
||||
|
||||
let vviewVar = yield jsterm.once("variablesview-fetched");
|
||||
vview = vviewVar._variablesView;
|
||||
ok(vview, "variables view object exists");
|
||||
|
||||
[result] = yield findVariableViewProperties(vviewVar, [
|
||||
expectedObj,
|
||||
], { webconsole: hud });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
// Check that clear output on page reload works - bug 705921.
|
||||
// Check that clear output and page reload remove the sidebar - bug 971967.
|
||||
|
||||
"use strict";
|
||||
|
||||
@ -19,7 +20,12 @@ let test = asyncTest(function*() {
|
||||
let hud = yield openConsole();
|
||||
ok(hud, "Web Console opened");
|
||||
|
||||
yield openSidebar("fooObj", { name: "testProp", value: "testValue" });
|
||||
|
||||
let sidebarClosed = hud.jsterm.once("sidebar-closed");
|
||||
hud.jsterm.clearOutput();
|
||||
yield sidebarClosed;
|
||||
|
||||
hud.jsterm.execute("console.log('foobarz1')");
|
||||
|
||||
yield waitForMessages({
|
||||
@ -31,8 +37,13 @@ let test = asyncTest(function*() {
|
||||
}],
|
||||
});
|
||||
|
||||
yield openSidebar("fooObj", { name: "testProp", value: "testValue" });
|
||||
|
||||
BrowserReload();
|
||||
yield loadBrowser(gBrowser.selectedBrowser);
|
||||
|
||||
sidebarClosed = hud.jsterm.once("sidebar-closed");
|
||||
loadBrowser(gBrowser.selectedBrowser);
|
||||
yield sidebarClosed;
|
||||
|
||||
hud.jsterm.execute("console.log('foobarz2')");
|
||||
|
||||
@ -51,4 +62,24 @@ let test = asyncTest(function*() {
|
||||
|
||||
is(hud.outputNode.textContent.indexOf("foobarz1"), -1,
|
||||
"foobarz1 has been removed from output");
|
||||
|
||||
function* openSidebar(objName, expectedObj) {
|
||||
let msg = yield hud.jsterm.execute(objName);
|
||||
ok(msg, "output message found");
|
||||
|
||||
let anchor = msg.querySelector("a");
|
||||
let body = msg.querySelector(".message-body");
|
||||
ok(anchor, "object anchor");
|
||||
ok(body, "message body");
|
||||
|
||||
yield EventUtils.synthesizeMouse(anchor, 2, 2, {}, hud.iframeWindow);
|
||||
|
||||
let vviewVar = yield hud.jsterm.once("variablesview-fetched");
|
||||
let vview = vviewVar._variablesView;
|
||||
ok(vview, "variables view object exists");
|
||||
|
||||
yield findVariableViewProperties(vviewVar, [
|
||||
expectedObj,
|
||||
], { webconsole: hud });
|
||||
}
|
||||
});
|
||||
|
@ -3,6 +3,10 @@
|
||||
<meta charset="utf-8">
|
||||
<title>Console test</title>
|
||||
<script type="text/javascript">
|
||||
var fooObj = {
|
||||
testProp: "testValue"
|
||||
};
|
||||
|
||||
function test() {
|
||||
var str = "Dolske Digs Bacon, Now and Forevermore."
|
||||
for (var i=0; i < 5; i++) {
|
||||
|
@ -3979,6 +3979,8 @@ JSTerm.prototype = {
|
||||
this.webConsoleClient.clearMessagesCache();
|
||||
}
|
||||
|
||||
this._sidebarDestroy();
|
||||
|
||||
this.emit("messages-cleared");
|
||||
},
|
||||
|
||||
|
@ -888,6 +888,9 @@ public:
|
||||
virtual void EnergyInfoNotification(const BluetoothActivityEnergyInfo& aInfo)
|
||||
{ }
|
||||
|
||||
virtual void BackendErrorNotification(bool aCrashed)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
BluetoothNotificationHandler()
|
||||
{ }
|
||||
|
@ -538,6 +538,7 @@ void
|
||||
BluetoothA2dpManager::OnDisconnectError()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
NS_ENSURE_TRUE_VOID(mController);
|
||||
|
||||
mController->NotifyCompletion(NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED));
|
||||
}
|
||||
@ -582,7 +583,9 @@ BluetoothA2dpManager::Disconnect(BluetoothProfileController* aController)
|
||||
|
||||
if (!sBtA2dpInterface) {
|
||||
BT_LOGR("sBluetoothA2dpInterface is null");
|
||||
aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
|
||||
if (aController) {
|
||||
aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,8 @@ using namespace mozilla::ipc;
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
static const int sRetryInterval = 100; // ms
|
||||
|
||||
//
|
||||
// Protocol initialization and setup
|
||||
//
|
||||
@ -1148,7 +1150,7 @@ private:
|
||||
|
||||
nsresult
|
||||
operator () (nsString& aArg1, nsString& aArg2, uint32_t& aArg3,
|
||||
BluetoothSspVariant aArg4, uint32_t& aArg5) const
|
||||
BluetoothSspVariant& aArg4, uint32_t& aArg5) const
|
||||
{
|
||||
BluetoothDaemonPDU& pdu = GetPDU();
|
||||
|
||||
@ -1749,6 +1751,20 @@ BluetoothDaemonChannel::GetIO()
|
||||
#define container(_t, _v, _m) \
|
||||
( (_t*)( ((const unsigned char*)(_v)) - offsetof(_t, _m) ) )
|
||||
|
||||
|
||||
static bool
|
||||
IsDaemonRunning()
|
||||
{
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
NS_WARN_IF(property_get("init.svc.bluetoothd", value, "") < 0);
|
||||
if (strcmp(value, "running")) {
|
||||
BT_LOGR("[RESTART] Bluetooth daemon state <%s>", value);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BluetoothDaemonInterface*
|
||||
BluetoothDaemonInterface::GetInstance()
|
||||
{
|
||||
@ -1769,6 +1785,42 @@ BluetoothDaemonInterface::BluetoothDaemonInterface()
|
||||
BluetoothDaemonInterface::~BluetoothDaemonInterface()
|
||||
{ }
|
||||
|
||||
class BluetoothDaemonInterface::StartDaemonTask final : public Task
|
||||
{
|
||||
public:
|
||||
StartDaemonTask(BluetoothDaemonInterface* aInterface,
|
||||
const nsACString& aCommand)
|
||||
: mInterface(aInterface)
|
||||
, mCommand(aCommand)
|
||||
{
|
||||
MOZ_ASSERT(mInterface);
|
||||
}
|
||||
|
||||
void Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
BT_LOGR("Start Daemon Task");
|
||||
// Start Bluetooth daemon again
|
||||
if (NS_WARN_IF(property_set("ctl.start", mCommand.get()) < 0)) {
|
||||
mInterface->OnConnectError(CMD_CHANNEL);
|
||||
}
|
||||
|
||||
// We're done if Bluetooth daemon is already running
|
||||
if (IsDaemonRunning()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise try again later
|
||||
MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||
new StartDaemonTask(mInterface, mCommand), sRetryInterval);
|
||||
}
|
||||
|
||||
private:
|
||||
BluetoothDaemonInterface* mInterface;
|
||||
nsCString mCommand;
|
||||
};
|
||||
|
||||
class BluetoothDaemonInterface::InitResultHandler final
|
||||
: public BluetoothSetupResultHandler
|
||||
{
|
||||
@ -1831,6 +1883,19 @@ BluetoothDaemonInterface::OnConnectSuccess(enum Channel aChannel)
|
||||
if (NS_WARN_IF(property_set("ctl.start", value.get()) < 0)) {
|
||||
OnConnectError(CMD_CHANNEL);
|
||||
}
|
||||
|
||||
/*
|
||||
* If Bluetooth daemon is not running, retry to start it later.
|
||||
*
|
||||
* This condition happens when when we restart Bluetooth daemon
|
||||
* immediately after it crashed, as the daemon state remains 'stopping'
|
||||
* instead of 'stopped'. Due to the limitation of property service,
|
||||
* hereby add delay. See Bug 1143925 Comment 41.
|
||||
*/
|
||||
if (!IsDaemonRunning()) {
|
||||
MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||
new StartDaemonTask(this, value), sRetryInterval);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CMD_CHANNEL:
|
||||
@ -1890,33 +1955,40 @@ BluetoothDaemonInterface::OnConnectError(enum Channel aChannel)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Three cases for restarting:
|
||||
* a) during startup
|
||||
* b) during regular service
|
||||
* c) during shutdown
|
||||
* For (a)/(c) cases, mResultHandlerQ contains an element, but case (b)
|
||||
* mResultHandlerQ shall be empty. The following procedure to recover from crashed
|
||||
* consists of several steps for case (b).
|
||||
* 1) Close listen socket.
|
||||
* 2) Wait for all sockets disconnected and inform BluetoothServiceBluedroid to
|
||||
* perform the regular stop bluetooth procedure.
|
||||
* 3) When stop bluetooth procedures complete, fire
|
||||
* AdapterStateChangedNotification to cleanup all necessary data members and
|
||||
* deinit ProfileManagers.
|
||||
* 4) After all resources cleanup, call |StartBluetooth|
|
||||
*/
|
||||
void
|
||||
BluetoothDaemonInterface::OnDisconnect(enum Channel aChannel)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mResultHandlerQ.IsEmpty()) {
|
||||
if (sNotificationHandler) {
|
||||
// Bluetooth daemon crashed; clear state
|
||||
sNotificationHandler->AdapterStateChangedNotification(false);
|
||||
sNotificationHandler = nullptr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aChannel) {
|
||||
case CMD_CHANNEL:
|
||||
// We don't have to do anything here. Step 4 is triggered
|
||||
// by the daemon.
|
||||
break;
|
||||
case NTF_CHANNEL:
|
||||
// Cleanup, step 4: Close listen socket
|
||||
// Cleanup, step 4 (Recovery, step 1): Close listen socket
|
||||
mListenSocket->Close();
|
||||
break;
|
||||
case LISTEN_SOCKET: {
|
||||
case LISTEN_SOCKET:
|
||||
if (!mResultHandlerQ.IsEmpty()) {
|
||||
nsRefPtr<BluetoothResultHandler> res = mResultHandlerQ.ElementAt(0);
|
||||
mResultHandlerQ.RemoveElementAt(0);
|
||||
|
||||
// Cleanup, step 5: Signal success to caller
|
||||
if (res) {
|
||||
res->Cleanup();
|
||||
@ -1924,6 +1996,20 @@ BluetoothDaemonInterface::OnDisconnect(enum Channel aChannel)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* For recovery make sure all sockets disconnected, in order to avoid
|
||||
* the remaining disconnects interfere with the restart procedure.
|
||||
*/
|
||||
if (sNotificationHandler && mResultHandlerQ.IsEmpty()) {
|
||||
if (mListenSocket->GetConnectionStatus() == SOCKET_DISCONNECTED &&
|
||||
mCmdChannel->GetConnectionStatus() == SOCKET_DISCONNECTED &&
|
||||
mNtfChannel->GetConnectionStatus() == SOCKET_DISCONNECTED) {
|
||||
// Assume daemon crashed during regular service; notify
|
||||
// BluetoothServiceBluedroid to prepare restart-daemon procedure
|
||||
sNotificationHandler->BackendErrorNotification(true);
|
||||
sNotificationHandler = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class BluetoothDaemonSocketConnector final
|
||||
@ -2198,16 +2284,18 @@ private:
|
||||
void
|
||||
BluetoothDaemonInterface::Cleanup(BluetoothResultHandler* aRes)
|
||||
{
|
||||
sNotificationHandler = nullptr;
|
||||
|
||||
mResultHandlerQ.AppendElement(aRes);
|
||||
sNotificationHandler = nullptr;
|
||||
|
||||
// Cleanup, step 1: Unregister Socket module
|
||||
nsresult rv = mProtocol->UnregisterModuleCmd(
|
||||
0x02, new CleanupResultHandler(this));
|
||||
if (NS_FAILED(rv)) {
|
||||
DispatchError(aRes, rv);
|
||||
return;
|
||||
}
|
||||
|
||||
mResultHandlerQ.AppendElement(aRes);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -24,11 +24,13 @@ class BluetoothDaemonInterface final : public BluetoothInterface
|
||||
public:
|
||||
class CleanupResultHandler;
|
||||
class InitResultHandler;
|
||||
class StartDaemonTask;
|
||||
|
||||
friend class BluetoothDaemonListenSocket;
|
||||
friend class BluetoothDaemonChannel;
|
||||
friend class CleanupResultHandler;
|
||||
friend class InitResultHandler;
|
||||
friend class StartDaemonTask;
|
||||
|
||||
static BluetoothDaemonInterface* GetInstance();
|
||||
|
||||
|
@ -102,6 +102,8 @@ static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sGetDeviceRunnableArray;
|
||||
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sFetchUuidsRunnableArray;
|
||||
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sBondingRunnableArray;
|
||||
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sUnbondingRunnableArray;
|
||||
static bool sIsRestart(false);
|
||||
static bool sIsFirstTimeToggleOffBt(false);
|
||||
|
||||
/**
|
||||
* Static callback functions
|
||||
@ -598,6 +600,8 @@ static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sGetDeviceRunnableArray;
|
||||
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sBondingRunnableArray;
|
||||
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sUnbondingRunnableArray;
|
||||
static bool sAdapterDiscoverable(false);
|
||||
static bool sIsRestart(false);
|
||||
static bool sIsFirstTimeToggleOffBt(false);
|
||||
static uint32_t sAdapterDiscoverableTimeout(0);
|
||||
|
||||
/**
|
||||
@ -2127,7 +2131,11 @@ public:
|
||||
private:
|
||||
void Proceed() const
|
||||
{
|
||||
sBtInterface->Cleanup(nullptr);
|
||||
if (!sIsRestart) {
|
||||
sBtInterface->Cleanup(nullptr);
|
||||
} else {
|
||||
BT_LOGR("ProfileDeinitResultHandler::Proceed cancel cleanup() ");
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char mNumProfiles;
|
||||
@ -2231,6 +2239,12 @@ BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState)
|
||||
|
||||
BT_LOGR("BT_STATE: %d", aState);
|
||||
|
||||
if (sIsRestart && aState) {
|
||||
// daemon restarted, reset flag
|
||||
BT_LOGR("daemon restarted, reset flag");
|
||||
sIsRestart = false;
|
||||
sIsFirstTimeToggleOffBt = false;
|
||||
}
|
||||
bool isBtEnabled = (aState == true);
|
||||
|
||||
if (!isBtEnabled) {
|
||||
@ -2279,6 +2293,11 @@ BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState)
|
||||
BT_LOGR("Fail to start BluetoothOppManager listening");
|
||||
}
|
||||
}
|
||||
// After ProfileManagers deinit and cleanup, now restarts bluetooth daemon
|
||||
if (sIsRestart && !aState) {
|
||||
BT_LOGR("sIsRestart and off, now restart");
|
||||
StartBluetooth(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -3074,3 +3093,39 @@ BluetoothServiceBluedroid::EnergyInfoNotification(
|
||||
// FIXME: This will be implemented in the later patchset
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
BluetoothServiceBluedroid::BackendErrorNotification(bool aCrashed)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// Recovery step 2 stop bluetooth
|
||||
if (aCrashed) {
|
||||
BT_LOGR("Set aRestart = true");
|
||||
sIsRestart = true;
|
||||
BT_LOGR("Reocvery step2: stop bluetooth");
|
||||
#ifdef MOZ_B2G_BT_API_V2
|
||||
StopBluetooth(false, nullptr);
|
||||
#else
|
||||
StopBluetooth(false);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothServiceBluedroid::CompleteToggleBt(bool aEnabled)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (sIsRestart && !aEnabled && sIsFirstTimeToggleOffBt) {
|
||||
// Both StopBluetooth and AdapterStateChangedNotification
|
||||
// trigger CompleteToggleBt. We don't need to call CompleteToggleBt again
|
||||
} else if (sIsRestart && !aEnabled && !sIsFirstTimeToggleOffBt) {
|
||||
// Recovery step 3: cleanup and deinit Profile managers
|
||||
BT_LOGR("CompleteToggleBt set sIsFirstTimeToggleOffBt = true");
|
||||
sIsFirstTimeToggleOffBt = true;
|
||||
BluetoothService::CompleteToggleBt(aEnabled);
|
||||
AdapterStateChangedNotification(false);
|
||||
} else {
|
||||
BluetoothService::CompleteToggleBt(aEnabled);
|
||||
}
|
||||
}
|
||||
|
@ -300,7 +300,9 @@ public:
|
||||
uint8_t aLen) override;
|
||||
virtual void LeTestModeNotification(BluetoothStatus aStatus,
|
||||
uint16_t aNumPackets) override;
|
||||
virtual void BackendErrorNotification(bool aCrashed) override;
|
||||
|
||||
virtual void CompleteToggleBt(bool aEnabled) override;
|
||||
protected:
|
||||
static nsresult StartGonkBluetooth();
|
||||
static nsresult StopGonkBluetooth();
|
||||
@ -527,6 +529,9 @@ public:
|
||||
virtual void EnergyInfoNotification(
|
||||
const BluetoothActivityEnergyInfo& aInfo) override;
|
||||
|
||||
virtual void BackendErrorNotification(bool aCrashed) override;
|
||||
virtual void CompleteToggleBt(bool aEnabled) override;
|
||||
|
||||
protected:
|
||||
static nsresult StartGonkBluetooth();
|
||||
static nsresult StopGonkBluetooth();
|
||||
|
@ -1283,6 +1283,7 @@ void
|
||||
BluetoothHfpManager::OnDisconnectError()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
NS_ENSURE_TRUE_VOID(mController);
|
||||
|
||||
mController->NotifyCompletion(NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
|
||||
}
|
||||
|
@ -365,6 +365,9 @@ protected:
|
||||
virtual nsresult
|
||||
HandleStartup();
|
||||
|
||||
virtual void
|
||||
CompleteToggleBt(bool aEnabled);
|
||||
|
||||
/**
|
||||
* Called when the startup settings check has completed.
|
||||
*/
|
||||
@ -391,7 +394,6 @@ protected:
|
||||
static BluetoothService*
|
||||
Create();
|
||||
|
||||
void CompleteToggleBt(bool aEnabled);
|
||||
|
||||
typedef nsClassHashtable<nsStringHashKey, BluetoothSignalObserverList >
|
||||
BluetoothSignalObserverTable;
|
||||
|
@ -256,6 +256,8 @@ BluetoothGatt::DiscoverServices(ErrorResult& aRv)
|
||||
BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
mDiscoveringServices = true;
|
||||
mServices.Clear();
|
||||
BluetoothGattBinding::ClearCachedServicesValue(this);
|
||||
nsRefPtr<BluetoothReplyRunnable> result =
|
||||
new BluetoothVoidReplyRunnable(nullptr /* DOMRequest */,
|
||||
promise,
|
||||
@ -292,6 +294,7 @@ BluetoothGatt::HandleServicesDiscovered(const BluetoothValue& aValue)
|
||||
const InfallibleTArray<BluetoothGattServiceId>& serviceIds =
|
||||
aValue.get_ArrayOfBluetoothGattServiceId();
|
||||
|
||||
mServices.Clear();
|
||||
for (uint32_t i = 0; i < serviceIds.Length(); i++) {
|
||||
mServices.AppendElement(new BluetoothGattService(
|
||||
GetParentObject(), mAppUuid, serviceIds[i]));
|
||||
|
@ -149,6 +149,7 @@ BluetoothGattCharacteristic::HandleDescriptorsDiscovered(
|
||||
const InfallibleTArray<BluetoothGattId>& descriptorIds =
|
||||
aValue.get_ArrayOfBluetoothGattId();
|
||||
|
||||
mDescriptors.Clear();
|
||||
for (uint32_t i = 0; i < descriptorIds.Length(); i++) {
|
||||
mDescriptors.AppendElement(new BluetoothGattDescriptor(
|
||||
GetParentObject(), this, descriptorIds[i]));
|
||||
@ -194,8 +195,6 @@ void
|
||||
BluetoothGattCharacteristic::GetValue(JSContext* cx,
|
||||
JS::MutableHandle<JSObject*> aValue) const
|
||||
{
|
||||
MOZ_ASSERT(aValue);
|
||||
|
||||
aValue.set(mValue.IsEmpty()
|
||||
? nullptr
|
||||
: ArrayBuffer::Create(cx, mValue.Length(), mValue.Elements()));
|
||||
|
@ -112,8 +112,6 @@ void
|
||||
BluetoothGattDescriptor::GetValue(JSContext* cx,
|
||||
JS::MutableHandle<JSObject*> aValue) const
|
||||
{
|
||||
MOZ_ASSERT(aValue);
|
||||
|
||||
aValue.set(mValue.IsEmpty()
|
||||
? nullptr
|
||||
: ArrayBuffer::Create(cx, mValue.Length(), mValue.Elements()));
|
||||
|
@ -85,6 +85,7 @@ BluetoothGattService::HandleIncludedServicesDiscovered(
|
||||
const InfallibleTArray<BluetoothGattServiceId>& includedServIds =
|
||||
aValue.get_ArrayOfBluetoothGattServiceId();
|
||||
|
||||
mIncludedServices.Clear();
|
||||
for (uint32_t i = 0; i < includedServIds.Length(); i++) {
|
||||
mIncludedServices.AppendElement(new BluetoothGattService(
|
||||
GetParentObject(), mAppUuid, includedServIds[i]));
|
||||
@ -103,6 +104,7 @@ BluetoothGattService::HandleCharacteristicsDiscovered(
|
||||
const InfallibleTArray<BluetoothGattCharAttribute>& characteristics =
|
||||
aValue.get_ArrayOfBluetoothGattCharAttribute();
|
||||
|
||||
mCharacteristics.Clear();
|
||||
for (uint32_t i = 0; i < characteristics.Length(); i++) {
|
||||
mCharacteristics.AppendElement(new BluetoothGattCharacteristic(
|
||||
GetParentObject(), this, characteristics[i]));
|
||||
|
@ -515,6 +515,9 @@ protected:
|
||||
virtual nsresult
|
||||
HandleStartup();
|
||||
|
||||
virtual void
|
||||
CompleteToggleBt(bool aEnabled);
|
||||
|
||||
/**
|
||||
* Called when the startup settings check has completed.
|
||||
*/
|
||||
@ -541,9 +544,6 @@ protected:
|
||||
static BluetoothService*
|
||||
Create();
|
||||
|
||||
void
|
||||
CompleteToggleBt(bool aEnabled);
|
||||
|
||||
typedef nsClassHashtable<nsStringHashKey, BluetoothSignalObserverList >
|
||||
BluetoothSignalObserverTable;
|
||||
|
||||
|
@ -1850,6 +1850,8 @@ MediaManager::GetUserMedia(
|
||||
false) ||
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
(
|
||||
// Allow tab sharing for all platforms including XP and OSX 10.6
|
||||
(src != dom::MediaSourceEnum::Browser) &&
|
||||
!Preferences::GetBool("media.getusermedia.screensharing.allow_on_old_platforms",
|
||||
false) &&
|
||||
#if defined(XP_MACOSX)
|
||||
|
@ -377,7 +377,8 @@ bool
|
||||
MP4Reader::IsSupportedAudioMimeType(const nsACString& aMimeType)
|
||||
{
|
||||
return (aMimeType.EqualsLiteral("audio/mpeg") ||
|
||||
aMimeType.EqualsLiteral("audio/mp4a-latm")) &&
|
||||
aMimeType.EqualsLiteral("audio/mp4a-latm") ||
|
||||
aMimeType.EqualsLiteral("audio/3gpp")) &&
|
||||
mPlatform->SupportsMimeType(aMimeType);
|
||||
}
|
||||
|
||||
|
@ -50,8 +50,9 @@ GonkAudioDecoderManager::GonkAudioDecoderManager(
|
||||
{
|
||||
MOZ_COUNT_CTOR(GonkAudioDecoderManager);
|
||||
MOZ_ASSERT(mAudioChannels);
|
||||
mUserData.AppendElements(aConfig.mCodecSpecificConfig->Elements(),
|
||||
aConfig.mCodecSpecificConfig->Length());
|
||||
mCodecSpecificData = aConfig.mCodecSpecificConfig;
|
||||
mMimeType = aConfig.mMimeType;
|
||||
|
||||
// Pass through mp3 without applying an ADTS header.
|
||||
if (!aConfig.mMimeType.EqualsLiteral("audio/mp4a-latm")) {
|
||||
mUseAdts = false;
|
||||
@ -66,6 +67,7 @@ GonkAudioDecoderManager::~GonkAudioDecoderManager()
|
||||
android::sp<MediaCodecProxy>
|
||||
GonkAudioDecoderManager::Init(MediaDataDecoderCallback* aCallback)
|
||||
{
|
||||
status_t rv = OK;
|
||||
if (mLooper != nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -74,7 +76,7 @@ GonkAudioDecoderManager::Init(MediaDataDecoderCallback* aCallback)
|
||||
mLooper->setName("GonkAudioDecoderManager");
|
||||
mLooper->start();
|
||||
|
||||
mDecoder = MediaCodecProxy::CreateByType(mLooper, "audio/mp4a-latm", false, nullptr);
|
||||
mDecoder = MediaCodecProxy::CreateByType(mLooper, mMimeType.get(), false, nullptr);
|
||||
if (!mDecoder.get()) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -85,8 +87,8 @@ GonkAudioDecoderManager::Init(MediaDataDecoderCallback* aCallback)
|
||||
}
|
||||
sp<AMessage> format = new AMessage;
|
||||
// Fixed values
|
||||
GADM_LOG("Init Audio channel no:%d, sample-rate:%d", mAudioChannels, mAudioRate);
|
||||
format->setString("mime", "audio/mp4a-latm");
|
||||
GADM_LOG("Configure audio mime type:%s, chan no:%d, sample-rate:%d", mMimeType.get(), mAudioChannels, mAudioRate);
|
||||
format->setString("mime", mMimeType.get());
|
||||
format->setInt32("channel-count", mAudioChannels);
|
||||
format->setInt32("sample-rate", mAudioRate);
|
||||
format->setInt32("aac-profile", mAudioProfile);
|
||||
@ -95,8 +97,11 @@ GonkAudioDecoderManager::Init(MediaDataDecoderCallback* aCallback)
|
||||
if (err != OK || !mDecoder->Prepare()) {
|
||||
return nullptr;
|
||||
}
|
||||
status_t rv = mDecoder->Input(mUserData.Elements(), mUserData.Length(), 0,
|
||||
android::MediaCodec::BUFFER_FLAG_CODECCONFIG);
|
||||
|
||||
if (mMimeType.EqualsLiteral("audio/mp4a-latm")) {
|
||||
rv = mDecoder->Input(mCodecSpecificData->Elements(), mCodecSpecificData->Length(), 0,
|
||||
android::MediaCodec::BUFFER_FLAG_CODECCONFIG);
|
||||
}
|
||||
|
||||
if (rv == OK) {
|
||||
return mDecoder;
|
||||
|
@ -51,7 +51,6 @@ private:
|
||||
const uint32_t mAudioChannels;
|
||||
const uint32_t mAudioRate;
|
||||
const uint32_t mAudioProfile;
|
||||
nsTArray<uint8_t> mUserData;
|
||||
bool mUseAdts;
|
||||
|
||||
MediaDataDecoderCallback* mReaderCallback;
|
||||
|
@ -65,6 +65,7 @@ bool
|
||||
GonkDecoderModule::SupportsMimeType(const nsACString& aMimeType)
|
||||
{
|
||||
return aMimeType.EqualsLiteral("audio/mp4a-latm") ||
|
||||
aMimeType.EqualsLiteral("audio/3gpp") ||
|
||||
aMimeType.EqualsLiteral("video/mp4") ||
|
||||
aMimeType.EqualsLiteral("video/mp4v-es") ||
|
||||
aMimeType.EqualsLiteral("video/avc");
|
||||
|
@ -69,6 +69,10 @@ protected:
|
||||
nsTArray<nsRefPtr<MediaRawData>> mQueueSample;
|
||||
|
||||
RefPtr<MediaTaskQueue> mTaskQueue;
|
||||
|
||||
nsRefPtr<MediaByteBuffer> mCodecSpecificData;
|
||||
|
||||
nsAutoCString mMimeType;
|
||||
};
|
||||
|
||||
// Samples are decoded using the GonkDecoder (MediaCodec)
|
||||
|
@ -494,7 +494,7 @@ GonkVideoDecoderManager::codecReserved()
|
||||
sp<Surface> surface;
|
||||
status_t rv = OK;
|
||||
// Fixed values
|
||||
GVDM_LOG("Configure mime type: %s, widht:%d, height:%d", mMimeType.get(), mVideoWidth, mVideoHeight);
|
||||
GVDM_LOG("Configure video mime type: %s, widht:%d, height:%d", mMimeType.get(), mVideoWidth, mVideoHeight);
|
||||
format->setString("mime", mMimeType.get());
|
||||
format->setInt32("width", mVideoWidth);
|
||||
format->setInt32("height", mVideoHeight);
|
||||
|
@ -147,7 +147,6 @@ private:
|
||||
|
||||
android::MediaBuffer* mVideoBuffer;
|
||||
|
||||
nsRefPtr<MediaByteBuffer> mCodecSpecificData;
|
||||
MediaDataDecoderCallback* mReaderCallback;
|
||||
MediaInfo mInfo;
|
||||
android::sp<VideoResourceListener> mVideoListener;
|
||||
@ -178,7 +177,6 @@ private:
|
||||
// The lock protects mPendingVideoBuffers.
|
||||
Mutex mPendingVideoBuffersLock;
|
||||
|
||||
nsAutoCString mMimeType;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
47
dom/mobilemessage/Assertions.cpp
Normal file
47
dom/mobilemessage/Assertions.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/MozMobileMessageManagerBinding.h"
|
||||
#include "nsISmsService.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace mobilemessage {
|
||||
|
||||
#define ASSERT_SMS_EQUALITY(webidlType, webidlState, xpidlState) \
|
||||
static_assert(static_cast<uint32_t>(webidlType::webidlState) == nsISmsService::xpidlState, \
|
||||
#webidlType "::" #webidlState " should equal to nsISmsService::" #xpidlState)
|
||||
|
||||
/**
|
||||
* Enum TypeOfNumber
|
||||
*/
|
||||
#define ASSERT_SMS_TYPE_OF_NUMBER_EQUALITY(webidlState, xpidlState) \
|
||||
ASSERT_SMS_EQUALITY(TypeOfNumber, webidlState, xpidlState)
|
||||
|
||||
ASSERT_SMS_TYPE_OF_NUMBER_EQUALITY(Unknown, TYPE_OF_NUMBER_UNKNOWN);
|
||||
ASSERT_SMS_TYPE_OF_NUMBER_EQUALITY(International, TYPE_OF_NUMBER_INTERNATIONAL);
|
||||
ASSERT_SMS_TYPE_OF_NUMBER_EQUALITY(National, TYPE_OF_NUMBER_NATIONAL);
|
||||
ASSERT_SMS_TYPE_OF_NUMBER_EQUALITY(Network_specific, TYPE_OF_NUMBER_NETWORK_SPECIFIC);
|
||||
ASSERT_SMS_TYPE_OF_NUMBER_EQUALITY(Dedicated_access_short_code, TYPE_OF_NUMBER_DEDICATED_ACCESS_SHORT_CODE);
|
||||
|
||||
#undef ASSERT_SMS_TYPE_OF_NUMBER_EQUALITY
|
||||
|
||||
/**
|
||||
* Enum NumberPlanIdentification
|
||||
*/
|
||||
#define ASSERT_SMS_NUMBER_PLAN_IDENTIFICATION_EQUALITY(webidlState, xpidlState) \
|
||||
ASSERT_SMS_EQUALITY(NumberPlanIdentification, webidlState, xpidlState)
|
||||
|
||||
ASSERT_SMS_NUMBER_PLAN_IDENTIFICATION_EQUALITY(Unknown, NUMBER_PLAN_IDENTIFICATION_UNKNOWN);
|
||||
ASSERT_SMS_NUMBER_PLAN_IDENTIFICATION_EQUALITY(Isdn, NUMBER_PLAN_IDENTIFICATION_ISDN);
|
||||
ASSERT_SMS_NUMBER_PLAN_IDENTIFICATION_EQUALITY(Data, NUMBER_PLAN_IDENTIFICATION_DATA);
|
||||
ASSERT_SMS_NUMBER_PLAN_IDENTIFICATION_EQUALITY(Telex, NUMBER_PLAN_IDENTIFICATION_TELEX);
|
||||
ASSERT_SMS_NUMBER_PLAN_IDENTIFICATION_EQUALITY(National, NUMBER_PLAN_IDENTIFICATION_NATIONAL);
|
||||
ASSERT_SMS_NUMBER_PLAN_IDENTIFICATION_EQUALITY(Private, NUMBER_PLAN_IDENTIFICATION_PRIVATE);
|
||||
|
||||
#undef ASSERT_SMS_EQUALITY
|
||||
|
||||
} // namespace mobilemessage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
@ -17,6 +17,7 @@
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsTArrayHelpers.h"
|
||||
#include "DOMMobileMessageError.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -80,6 +81,11 @@ MobileMessageCallback::MobileMessageCallback(DOMRequest* aDOMRequest)
|
||||
{
|
||||
}
|
||||
|
||||
MobileMessageCallback::MobileMessageCallback(Promise* aPromise)
|
||||
: mPromise(aPromise)
|
||||
{
|
||||
}
|
||||
|
||||
MobileMessageCallback::~MobileMessageCallback()
|
||||
{
|
||||
}
|
||||
@ -280,6 +286,21 @@ MobileMessageCallback::NotifyGetSmscAddressFailed(int32_t aError)
|
||||
return NotifyError(aError);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MobileMessageCallback::NotifySetSmscAddress()
|
||||
{
|
||||
mPromise->MaybeResolve(JS::UndefinedHandleValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MobileMessageCallback::NotifySetSmscAddressFailed(int32_t aError)
|
||||
{
|
||||
const nsAString& errorStr = ConvertErrorCodeToErrorString(aError);
|
||||
mPromise->MaybeRejectBrokenly(errorStr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namesapce mobilemessage
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "DOMRequest.h"
|
||||
|
||||
class Promise;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace mobilemessage {
|
||||
@ -21,11 +23,13 @@ public:
|
||||
NS_DECL_NSIMOBILEMESSAGECALLBACK
|
||||
|
||||
explicit MobileMessageCallback(DOMRequest* aDOMRequest);
|
||||
explicit MobileMessageCallback(Promise* aPromise);
|
||||
|
||||
private:
|
||||
~MobileMessageCallback();
|
||||
|
||||
nsRefPtr<DOMRequest> mDOMRequest;
|
||||
nsRefPtr<Promise> mPromise;
|
||||
|
||||
nsresult NotifySuccess(JS::Handle<JS::Value> aResult, bool aAsync = false);
|
||||
nsresult NotifySuccess(nsISupports *aMessage, bool aAsync = false);
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "mozilla/dom/MozMmsEvent.h"
|
||||
#include "mozilla/dom/MozMobileMessageManagerBinding.h"
|
||||
#include "mozilla/dom/MozSmsEvent.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
@ -697,6 +698,72 @@ MobileMessageManager::GetSmscAddress(const Optional<uint32_t>& aServiceId,
|
||||
return request.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
MobileMessageManager::SetSmscAddress(const SmscAddress& aSmscAddress,
|
||||
const Optional<uint32_t>& aServiceId,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
|
||||
if (!smsService) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Use the default one unless |serviceId| is available.
|
||||
uint32_t serviceId;
|
||||
nsresult rv;
|
||||
if (aServiceId.WasPassed()) {
|
||||
serviceId = aServiceId.Value();
|
||||
} else {
|
||||
rv = smsService->GetSmsDefaultServiceId(&serviceId);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
|
||||
if (!global) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!aSmscAddress.mAddress.WasPassed()) {
|
||||
NS_WARNING("SmscAddress.address is a mandatory field and can not be omitted.");
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
nsString address = aSmscAddress.mAddress.Value();
|
||||
TypeOfNumber ton = aSmscAddress.mTypeOfAddress.mTypeOfNumber;
|
||||
NumberPlanIdentification npi =
|
||||
aSmscAddress.mTypeOfAddress.mNumberPlanIdentification;
|
||||
|
||||
// If the address begins with +, set TON to international no matter what has
|
||||
// passed in.
|
||||
if (!address.IsEmpty() && address[0] == '+') {
|
||||
ton = TypeOfNumber::International;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIMobileMessageCallback> msgCallback =
|
||||
new MobileMessageCallback(promise);
|
||||
|
||||
rv = smsService->SetSmscAddress(serviceId, address,
|
||||
static_cast<uint32_t>(ton), static_cast<uint32_t>(npi), msgCallback);
|
||||
if (NS_FAILED(rv)) {
|
||||
promise->MaybeReject(rv);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
class nsISmsService;
|
||||
class nsIDOMMozSmsMessage;
|
||||
class nsIDOMMozMmsMessage;
|
||||
class Promise;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -24,6 +25,7 @@ struct MmsSendParameters;
|
||||
struct MobileMessageFilter;
|
||||
class OwningLongOrMozSmsMessageOrMozMmsMessage;
|
||||
struct SmsSendParameters;
|
||||
struct SmscAddress;
|
||||
|
||||
class MobileMessageManager final : public DOMEventTargetHelper
|
||||
, public nsIObserver
|
||||
@ -115,6 +117,11 @@ public:
|
||||
GetSmscAddress(const Optional<uint32_t>& aServiceId,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise>
|
||||
SetSmscAddress(const SmscAddress& aSmscAddress,
|
||||
const Optional<uint32_t>& aServiceId,
|
||||
ErrorResult& aRv);
|
||||
|
||||
IMPL_EVENT_HANDLER(received)
|
||||
IMPL_EVENT_HANDLER(retrieving)
|
||||
IMPL_EVENT_HANDLER(sending)
|
||||
|
@ -69,7 +69,20 @@ SmsService::GetSmscAddress(uint32_t aServiceId,
|
||||
nsIMobileMessageCallback *aRequest)
|
||||
{
|
||||
// TODO: bug 878016 - Android backend: implement getSMSCAddress/setSMSCAddress
|
||||
return NS_OK;
|
||||
NS_NOTYETIMPLEMENTED("Implement me!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsService::SetSmscAddress(uint32_t aServiceId,
|
||||
const nsAString& aNumber,
|
||||
uint32_t aTypeOfNumber,
|
||||
uint32_t aNumberPlanIdentification,
|
||||
nsIMobileMessageCallback* aRequest)
|
||||
{
|
||||
// TODO: bug 878016 - Android backend: implement getSMSCAddress/setSMSCAddress
|
||||
NS_NOTYETIMPLEMENTED("Implement me!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
} // namespace mobilemessage
|
||||
|
@ -802,7 +802,7 @@ SmsService.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
// An array of slient numbers.
|
||||
// An array of silent numbers.
|
||||
_silentNumbers: null,
|
||||
_isSilentNumber: function(aNumber) {
|
||||
return this._silentNumbers.indexOf(aNumber) >= 0;
|
||||
@ -990,6 +990,30 @@ SmsService.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
setSmscAddress: function(aServiceId, aNumber, aTypeOfNumber,
|
||||
aNumberPlanIdentification, aRequest) {
|
||||
if (aServiceId > (gRadioInterfaces.length - 1)) {
|
||||
throw Cr.NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
let options = {
|
||||
smscAddress: aNumber,
|
||||
typeOfNumber: aTypeOfNumber,
|
||||
numberPlanIdentification: aNumberPlanIdentification
|
||||
};
|
||||
|
||||
gRadioInterfaces[aServiceId].sendWorkerMessage("setSmscAddress",
|
||||
options,
|
||||
(aResponse) => {
|
||||
if (!aResponse.errorMsg) {
|
||||
aRequest.notifySetSmscAddress();
|
||||
} else {
|
||||
aRequest.notifySetSmscAddressFailed(
|
||||
Ci.nsIMobileMessageCallback.INVALID_ADDRESS_ERROR);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIGonkSmsService interface
|
||||
*/
|
||||
|
@ -10,7 +10,7 @@
|
||||
"@mozilla.org/sms/gonksmsservice;1"
|
||||
%}
|
||||
|
||||
[scriptable, uuid(4dda515e-05ec-47b1-b750-e42c74576c43)]
|
||||
[scriptable, uuid(76681431-8261-4540-bab8-24ef3866e8b6)]
|
||||
interface nsIGonkSmsService : nsISmsService
|
||||
{
|
||||
const unsigned short SMS_MESSAGE_ENCODING_7BITS_ALPHABET = 0x00;
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(35279dbc-9f1d-419f-b17a-230fcf49f0c7)]
|
||||
[scriptable, uuid(b1367554-51c6-4153-b20a-effec50ca827)]
|
||||
interface nsIMobileMessageCallback : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -54,4 +54,6 @@ interface nsIMobileMessageCallback : nsISupports
|
||||
*/
|
||||
void notifyGetSmscAddress(in DOMString aSmscAddress);
|
||||
void notifyGetSmscAddressFailed(in long error);
|
||||
void notifySetSmscAddress();
|
||||
void notifySetSmscAddressFailed(in long error);
|
||||
};
|
||||
|
@ -12,7 +12,7 @@ interface nsIMobileMessageCallback;
|
||||
#define SMS_SERVICE_CONTRACTID "@mozilla.org/sms/smsservice;1"
|
||||
%}
|
||||
|
||||
[scriptable, uuid(ae688bca-00c9-4d08-945d-e8a5272ad5b1)]
|
||||
[scriptable, uuid(c8ca5f06-ad76-44b0-a324-9e2910fd37da)]
|
||||
interface nsISmsService : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -41,22 +41,131 @@ interface nsISmsService : nsISupports
|
||||
const unsigned short DELIVERY_STATUS_TYPE_PENDING = 2;
|
||||
const unsigned short DELIVERY_STATUS_TYPE_ERROR = 3;
|
||||
|
||||
/**
|
||||
* Constant definitions of SM-RP type of number as defined in
|
||||
* |Table 10.5.118: Called party BCD number| of 3GPP TS 24.008.
|
||||
*/
|
||||
const unsigned short TYPE_OF_NUMBER_UNKNOWN = 0;
|
||||
const unsigned short TYPE_OF_NUMBER_INTERNATIONAL = 1;
|
||||
const unsigned short TYPE_OF_NUMBER_NATIONAL = 2;
|
||||
const unsigned short TYPE_OF_NUMBER_NETWORK_SPECIFIC = 3;
|
||||
const unsigned short TYPE_OF_NUMBER_DEDICATED_ACCESS_SHORT_CODE = 4;
|
||||
|
||||
/**
|
||||
* Constant definitions of SM-RP number plan identification as defined in
|
||||
* |Table 10.5.118: Called party BCD number| of 3GPP TS 24.008.
|
||||
*/
|
||||
const unsigned short NUMBER_PLAN_IDENTIFICATION_UNKNOWN = 0;
|
||||
const unsigned short NUMBER_PLAN_IDENTIFICATION_ISDN = 1;
|
||||
const unsigned short NUMBER_PLAN_IDENTIFICATION_DATA = 2;
|
||||
const unsigned short NUMBER_PLAN_IDENTIFICATION_TELEX = 3;
|
||||
const unsigned short NUMBER_PLAN_IDENTIFICATION_NATIONAL = 4;
|
||||
const unsigned short NUMBER_PLAN_IDENTIFICATION_PRIVATE = 5;
|
||||
|
||||
/**
|
||||
* The default RIL service ID used for SMS.
|
||||
*/
|
||||
readonly attribute unsigned long smsDefaultServiceId;
|
||||
|
||||
/**
|
||||
* Get the information necessary to create a multi-part SMS for a given text.
|
||||
*
|
||||
* @param text
|
||||
* The text message content.
|
||||
* @param request
|
||||
* The callback object to use. It invokes
|
||||
* |notifySegmentInfoForTextGot| on success, or
|
||||
* |notifyGetSegmentInfoForTextFailed| on failure.
|
||||
*/
|
||||
void getSegmentInfoForText(in DOMString text,
|
||||
in nsIMobileMessageCallback request);
|
||||
|
||||
/**
|
||||
* Send a SMS.
|
||||
*
|
||||
* @param serviceId
|
||||
* The ID of RIL service to use.
|
||||
* @param number
|
||||
* Destination number in string.
|
||||
* @param message
|
||||
* The text message content.
|
||||
* @param silent
|
||||
* |true| to send a silent message. It's used to make a SMS based
|
||||
* authentication for some services such as mobile billing.
|
||||
* @param request
|
||||
* The callback object to use. It invokes |notifyMessageSent| on
|
||||
* success, or |notifySendMessageFailed| on failure.
|
||||
* @throws NS_ERROR_INVALID_ARG
|
||||
* If |serviceId| exceeds the max value of available IDs.
|
||||
*/
|
||||
void send(in unsigned long serviceId,
|
||||
in DOMString number,
|
||||
in DOMString message,
|
||||
in boolean silent,
|
||||
in nsIMobileMessageCallback request);
|
||||
|
||||
/**
|
||||
* Add a number to the list of silent message originators. When receiving a
|
||||
* SMS sent from one of the numbers in the list, |SmsService| will notify
|
||||
* observers through the topic "silent-sms-received".
|
||||
*
|
||||
* It's used when a SMS based authentication has been initiated and the client
|
||||
* is waiting for an incoming silent message containing the authentication
|
||||
* result.
|
||||
*
|
||||
* @param number
|
||||
* Originator number in string.
|
||||
* @throw NS_ERROR_UNEXPECTED
|
||||
* If the given number has already been added before.
|
||||
*/
|
||||
void addSilentNumber(in DOMString number);
|
||||
|
||||
/**
|
||||
* Remove a number from the silent message originator list.
|
||||
*
|
||||
* @param number
|
||||
* Originator number in string.
|
||||
* @throws NS_ERROR_INVALID_ARG
|
||||
* If the number doesn't exist in the list.
|
||||
*/
|
||||
void removeSilentNumber(in DOMString number);
|
||||
|
||||
/**
|
||||
* Get the short message service center address of given |serviceId|.
|
||||
*
|
||||
* @param serviceId
|
||||
* The ID of RIL service to use.
|
||||
* @param request
|
||||
* The callback object to use. It invokes |notifyGetSmscAddress| on
|
||||
* success, or |notifyGetSmscAddressFailed| on failure.
|
||||
* @throws NS_ERROR_INVALID_ARG
|
||||
* If |serviceId| exceeds the max value of available IDs.
|
||||
*/
|
||||
void getSmscAddress(in unsigned long serviceId,
|
||||
in nsIMobileMessageCallback request);
|
||||
|
||||
/**
|
||||
* Set the short message service center address of given |serviceId|.
|
||||
*
|
||||
* @param serviceId
|
||||
* The ID of RIL service to use.
|
||||
* @param number
|
||||
* Number part of the SMSC address.
|
||||
* @param typeOfNumber
|
||||
* Type of number of the SMSC address.
|
||||
* @param numberPlanIdentification
|
||||
* Number plan identification of the SMSC address.
|
||||
* @param request
|
||||
* The callback object to use. It invokes |notifySetSmscAddress| on
|
||||
* success, or |notifySetSmscAddressFailed| on failure.
|
||||
* @throws NS_ERROR_INVALID_ARG
|
||||
* If |serviceId| exceeds the max value of available IDs.
|
||||
*/
|
||||
void setSmscAddress(in unsigned long serviceId,
|
||||
in DOMString number,
|
||||
in unsigned long typeOfNumber,
|
||||
in unsigned long numberPlanIdentification,
|
||||
in nsIMobileMessageCallback request);
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
@ -79,6 +79,14 @@ struct GetSmscAddressRequest
|
||||
uint32_t serviceId;
|
||||
};
|
||||
|
||||
struct SetSmscAddressRequest
|
||||
{
|
||||
uint32_t serviceId;
|
||||
nsString number;
|
||||
uint32_t typeOfNumber;
|
||||
uint32_t numberPlanIdentification;
|
||||
};
|
||||
|
||||
union IPCSmsRequest
|
||||
{
|
||||
SendMessageRequest;
|
||||
@ -88,6 +96,7 @@ union IPCSmsRequest
|
||||
MarkMessageReadRequest;
|
||||
GetSegmentInfoForTextRequest;
|
||||
GetSmscAddressRequest;
|
||||
SetSmscAddressRequest;
|
||||
};
|
||||
|
||||
union IPCMobileMessageCursor
|
||||
|
@ -94,6 +94,15 @@ struct ReplyGetSmscAddressFail
|
||||
int32_t error;
|
||||
};
|
||||
|
||||
struct ReplySetSmscAddress
|
||||
{
|
||||
};
|
||||
|
||||
struct ReplySetSmscAddressFail
|
||||
{
|
||||
int32_t error;
|
||||
};
|
||||
|
||||
union MessageReply
|
||||
{
|
||||
ReplyMessageSend;
|
||||
@ -108,6 +117,8 @@ union MessageReply
|
||||
ReplyGetSegmentInfoForTextFail;
|
||||
ReplyGetSmscAddress;
|
||||
ReplyGetSmscAddressFail;
|
||||
ReplySetSmscAddress;
|
||||
ReplySetSmscAddressFail;
|
||||
};
|
||||
|
||||
} // namespace mobilemessage
|
||||
|
@ -262,6 +262,12 @@ SmsRequestChild::Recv__delete__(const MessageReply& aReply)
|
||||
case MessageReply::TReplyGetSmscAddressFail:
|
||||
mReplyRequest->NotifyGetSmscAddressFailed(aReply.get_ReplyGetSmscAddressFail().error());
|
||||
break;
|
||||
case MessageReply::TReplySetSmscAddress:
|
||||
mReplyRequest->NotifySetSmscAddress();
|
||||
break;
|
||||
case MessageReply::TReplySetSmscAddressFail:
|
||||
mReplyRequest->NotifySetSmscAddressFailed(aReply.get_ReplySetSmscAddressFail().error());
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Received invalid response parameters!");
|
||||
}
|
||||
|
@ -181,6 +181,21 @@ SmsIPCService::GetSmscAddress(uint32_t aServiceId,
|
||||
return SendRequest(GetSmscAddressRequest(aServiceId), aRequest);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsIPCService::SetSmscAddress(uint32_t aServiceId,
|
||||
const nsAString& aNumber,
|
||||
uint32_t aTypeOfNumber,
|
||||
uint32_t aNumberPlanIdentification,
|
||||
nsIMobileMessageCallback* aRequest)
|
||||
{
|
||||
return SendRequest(SetSmscAddressRequest(aServiceId,
|
||||
nsString(aNumber),
|
||||
aTypeOfNumber,
|
||||
aNumberPlanIdentification),
|
||||
aRequest);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsIPCService::Send(uint32_t aServiceId,
|
||||
const nsAString& aNumber,
|
||||
|
@ -406,6 +406,8 @@ SmsParent::RecvPSmsRequestConstructor(PSmsRequestParent* aActor,
|
||||
return actor->DoRequest(aRequest.get_GetSegmentInfoForTextRequest());
|
||||
case IPCSmsRequest::TGetSmscAddressRequest:
|
||||
return actor->DoRequest(aRequest.get_GetSmscAddressRequest());
|
||||
case IPCSmsRequest::TSetSmscAddressRequest:
|
||||
return actor->DoRequest(aRequest.get_SetSmscAddressRequest());
|
||||
default:
|
||||
MOZ_CRASH("Unknown type!");
|
||||
}
|
||||
@ -574,6 +576,29 @@ SmsRequestParent::DoRequest(const GetSmscAddressRequest& aRequest)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SmsRequestParent::DoRequest(const SetSmscAddressRequest& aRequest)
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID);
|
||||
if (smsService) {
|
||||
rv = smsService->SetSmscAddress(aRequest.serviceId(),
|
||||
aRequest.number(),
|
||||
aRequest.typeOfNumber(),
|
||||
aRequest.numberPlanIdentification(),
|
||||
this);
|
||||
} else {
|
||||
return NS_SUCCEEDED(NotifySetSmscAddressFailed(nsIMobileMessageCallback::INTERNAL_ERROR));
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_SUCCEEDED(NotifySetSmscAddressFailed(nsIMobileMessageCallback::INTERNAL_ERROR));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SmsRequestParent::DoRequest(const DeleteMessageRequest& aRequest)
|
||||
{
|
||||
@ -746,6 +771,18 @@ SmsRequestParent::NotifyGetSmscAddressFailed(int32_t aError)
|
||||
return SendReply(ReplyGetSmscAddressFail(aError));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsRequestParent::NotifySetSmscAddress()
|
||||
{
|
||||
return SendReply(ReplySetSmscAddress());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SmsRequestParent::NotifySetSmscAddressFailed(int32_t aError)
|
||||
{
|
||||
return SendReply(ReplySetSmscAddressFail(aError));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* MobileMessageCursorParent
|
||||
******************************************************************************/
|
||||
|
@ -117,6 +117,9 @@ protected:
|
||||
bool
|
||||
DoRequest(const GetSmscAddressRequest& aRequest);
|
||||
|
||||
bool
|
||||
DoRequest(const SetSmscAddressRequest& aRequest);
|
||||
|
||||
nsresult
|
||||
SendReply(const MessageReply& aReply);
|
||||
};
|
||||
|
@ -50,6 +50,7 @@ EXPORTS.mozilla.dom += [
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'Assertions.cpp',
|
||||
'Constants.cpp',
|
||||
'DeletedMessageInfo.cpp',
|
||||
'DOMMobileMessageError.cpp',
|
||||
|
@ -52,3 +52,4 @@ qemu = true
|
||||
[test_ondeleted_event.js]
|
||||
[test_decode_spanish_fallback.js]
|
||||
[test_update_gsm_nl_on_mcc_chanages.js]
|
||||
[test_set_smsc_address.js]
|
||||
|
72
dom/mobilemessage/tests/marionette/test_set_smsc_address.js
Normal file
72
dom/mobilemessage/tests/marionette/test_set_smsc_address.js
Normal file
@ -0,0 +1,72 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
const SMSC_ATT = '+13123149810';
|
||||
const SMSC_ATT_TYPO = '+++1312@@@314$$$9,8,1,0';
|
||||
const SMSC_ATT_TEXT = '"+13123149810",145';
|
||||
const SMSC_O2 = '+447802000332';
|
||||
const SMSC_O2_TEXT = '"+447802000332",145';
|
||||
const SMSC_DEF = '+123456789';
|
||||
const SMSC_DEF_TEXT = '"+123456789",145';
|
||||
const SMSC_TON_UNKNOWN = '0407485455'
|
||||
const SMSC_TON_UNKNOWN_TEXT = '"0407485455",129';
|
||||
|
||||
function getSmscAddress() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let req = manager.getSmscAddress();
|
||||
if (!req) {
|
||||
reject("manager.getSmscAddress() returns null.");
|
||||
}
|
||||
|
||||
req.onsuccess = function() {
|
||||
resolve(this.result);
|
||||
};
|
||||
|
||||
req.onerror = function() {
|
||||
reject(this.error);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
startTestBase(function testCaseMain() {
|
||||
return ensureMobileMessage()
|
||||
|
||||
// Verify setting AT&T SMSC address.
|
||||
.then(() => manager.setSmscAddress({ address:SMSC_ATT }))
|
||||
.then(() => getSmscAddress())
|
||||
.then((result) => is(result, SMSC_ATT_TEXT))
|
||||
|
||||
// Verify setting O2 SMSC address.
|
||||
.then(() => manager.setSmscAddress({ address:SMSC_O2 }))
|
||||
.then(() => getSmscAddress())
|
||||
.then((result) => is(result, SMSC_O2_TEXT))
|
||||
|
||||
// Verify setting AT&T SMSC address with extra illegal characters.
|
||||
.then(() => manager.setSmscAddress({ address:SMSC_ATT_TYPO }))
|
||||
.then(() => getSmscAddress())
|
||||
.then((result) => is(result, SMSC_ATT_TEXT))
|
||||
|
||||
// Verify setting a SMSC address with TON=unknown.
|
||||
.then(() => manager.setSmscAddress({ address:SMSC_TON_UNKNOWN }))
|
||||
.then(() => getSmscAddress())
|
||||
.then((result) => is(result, SMSC_TON_UNKNOWN_TEXT))
|
||||
|
||||
// Verify setting invalid SMSC address.
|
||||
.then(() => manager.setSmscAddress({}))
|
||||
.then(() => Promise.reject("Expect for an error."),
|
||||
(err) => log("Got expected error: " + err))
|
||||
.then(() => manager.setSmscAddress({ address:"" }))
|
||||
.then(() => Promise.reject("Expect for an error."),
|
||||
(err) => log("Got expected error: " + err))
|
||||
.then(() => manager.setSmscAddress({ address:"???" }))
|
||||
.then(() => Promise.reject("Expect for an error."),
|
||||
(err) => log("Got expected error: " + err))
|
||||
|
||||
// Restore to default emulator SMSC address.
|
||||
.then(() => manager.setSmscAddress({ address:SMSC_DEF }))
|
||||
.then(() => getSmscAddress())
|
||||
.then((result) => is(result, SMSC_DEF_TEXT));
|
||||
});
|
@ -1494,6 +1494,8 @@ WorkerMessenger.prototype = {
|
||||
libcutils.property_get("ro.moz.ril.query_icc_count", "false") == "true",
|
||||
sendStkProfileDownload:
|
||||
libcutils.property_get("ro.moz.ril.send_stk_profile_dl", "false") == "true",
|
||||
smscAddressFormat:
|
||||
libcutils.property_get("ro.moz.ril.smsc_address_format", "text"),
|
||||
dataRegistrationOnDemand: RILQUIRKS_DATA_REGISTRATION_ON_DEMAND,
|
||||
subscriptionControl: RILQUIRKS_SUBSCRIPTION_CONTROL,
|
||||
signalExtraInt: RILQUIRKS_SIGNAL_EXTRA_INT32
|
||||
|
@ -1406,6 +1406,30 @@ this.CB_UMTS_MESSAGE_TYPE_CBS = 1;
|
||||
this.CB_UMTS_MESSAGE_TYPE_SCHEDULE = 2;
|
||||
this.CB_UMTS_MESSAGE_TYPE_CBS41 = 3;
|
||||
|
||||
/**
|
||||
* Number plan identification defined in
|
||||
* |Table 10.5.118: Called party BCD number| of 3GPP TS 24.008.
|
||||
*/
|
||||
this.CALLED_PARTY_BCD_NPI_UNKNOWN = 0;
|
||||
this.CALLED_PARTY_BCD_NPI_ISDN = 1;
|
||||
this.CALLED_PARTY_BCD_NPI_DATA = 3;
|
||||
this.CALLED_PARTY_BCD_NPI_TELEX = 4;
|
||||
this.CALLED_PARTY_BCD_NPI_NATIONAL = 8;
|
||||
this.CALLED_PARTY_BCD_NPI_PRIVATE = 9;
|
||||
|
||||
/**
|
||||
* Array of number plan identification values which can be used to map an
|
||||
* enumeration to the corresponding value.
|
||||
*/
|
||||
this.CALLED_PARTY_BCD_NPI = [
|
||||
CALLED_PARTY_BCD_NPI_UNKNOWN,
|
||||
CALLED_PARTY_BCD_NPI_ISDN,
|
||||
CALLED_PARTY_BCD_NPI_DATA,
|
||||
CALLED_PARTY_BCD_NPI_TELEX,
|
||||
CALLED_PARTY_BCD_NPI_NATIONAL,
|
||||
CALLED_PARTY_BCD_NPI_PRIVATE
|
||||
];
|
||||
|
||||
/**
|
||||
* GSM PDU constants
|
||||
*/
|
||||
|
@ -86,6 +86,9 @@ let RILQUIRKS_SUBSCRIPTION_CONTROL;
|
||||
|
||||
let RILQUIRKS_SIGNAL_EXTRA_INT32;
|
||||
|
||||
// Ril quirk to describe the SMSC address format.
|
||||
let RILQUIRKS_SMSC_ADDRESS_FORMAT;
|
||||
|
||||
/**
|
||||
* The RIL state machine.
|
||||
*
|
||||
@ -1728,12 +1731,91 @@ RilObject.prototype = {
|
||||
* Set the Short Message Service Center address.
|
||||
*
|
||||
* @param smscAddress
|
||||
* Short Message Service Center address in PDU format.
|
||||
* Number part of the SMSC address.
|
||||
* @param typeOfNumber
|
||||
* Type of number in integer, as defined in
|
||||
* |Table 10.5.118: Called party BCD number| of 3GPP TS 24.008.
|
||||
* @param numberPlanIdentification
|
||||
* Number plan identification in integer, as defined in
|
||||
* |Table 10.5.118: Called party BCD number| of 3GPP TS 24.008.
|
||||
*/
|
||||
setSmscAddress: function(options) {
|
||||
let ton = options.typeOfNumber;
|
||||
let npi = CALLED_PARTY_BCD_NPI[options.numberPlanIdentification];
|
||||
|
||||
// If any of the mandatory arguments is not available, return an error
|
||||
// immediately.
|
||||
if (ton === undefined || npi === undefined || !options.smscAddress) {
|
||||
options.errorMsg = GECKO_ERROR_INVALID_PARAMETER;
|
||||
this.sendChromeMessage(options);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove all illegal characters in the number string for user-input fault
|
||||
// tolerance.
|
||||
let numStart = options.smscAddress[0] === "+" ? 1 : 0;
|
||||
let number = options.smscAddress.substring(0, numStart) +
|
||||
options.smscAddress.substring(numStart)
|
||||
.replace(/[^0-9*#abc]/ig, "");
|
||||
|
||||
// If the filtered number is an empty string, return an error immediately.
|
||||
if (number.length === 0) {
|
||||
options.errorMsg = GECKO_ERROR_INVALID_PARAMETER;
|
||||
this.sendChromeMessage(options);
|
||||
return;
|
||||
}
|
||||
|
||||
// Init parcel.
|
||||
this.SMSC = null;
|
||||
let Buf = this.context.Buf;
|
||||
Buf.newParcel(REQUEST_SET_SMSC_ADDRESS, options);
|
||||
Buf.writeString(options.smscAddress);
|
||||
|
||||
// +---+-----------+---------------+
|
||||
// | 1 | TON | NPI |
|
||||
// +---+-----------+---------------+
|
||||
let tosca = (0x1 << 7) + (ton << 4) + npi;
|
||||
if (RILQUIRKS_SMSC_ADDRESS_FORMAT === "pdu") {
|
||||
let pduHelper = this.context.GsmPDUHelper;
|
||||
|
||||
// Remove the preceding '+', and covert the special BCD digits defined in
|
||||
// |Called party BCD number| of 3GPP TS 24.008 to corresponding
|
||||
// hexadecimal values (refer the following table).
|
||||
//
|
||||
// +=========+=======+=====+
|
||||
// | value | digit | hex |
|
||||
// +========================
|
||||
// | 1 0 1 0 | * | 0xA |
|
||||
// | 1 0 1 1 | # | 0xB |
|
||||
// | 1 1 0 0 | a | 0xC |
|
||||
// | 1 1 0 1 | b | 0xD |
|
||||
// | 1 1 1 0 | c | 0xE |
|
||||
// +=========+=======+=====+
|
||||
//
|
||||
// The replace order is reversed intentionally, because if the digits are
|
||||
// replaced in ascending order, "#" will be converted to "b" and then be
|
||||
// converted again to "d", which generates incorrect result.
|
||||
let pureNumber = number.substring(numStart)
|
||||
.replace(/c/ig, "e")
|
||||
.replace(/b/ig, "d")
|
||||
.replace(/a/ig, "c")
|
||||
.replace(/\#/g, "b")
|
||||
.replace(/\*/g, "a");
|
||||
|
||||
// address length and string length
|
||||
let length = Math.ceil(pureNumber.length / 2) + 1; // +1 octet for TOA
|
||||
let strlen = length * 2 + 2; // +2 semi-octets for length octet
|
||||
|
||||
Buf.writeInt32(strlen);
|
||||
pduHelper.writeHexOctet(length);
|
||||
pduHelper.writeHexOctet(tosca);
|
||||
pduHelper.writeSwappedNibbleBCD(pureNumber);
|
||||
Buf.writeStringDelimiter(strlen);
|
||||
} else /* RILQUIRKS_SMSC_ADDRESS_FORMAT === "text" */ {
|
||||
let sca;
|
||||
sca = '"' + number + '"' + ',' + tosca;
|
||||
Buf.writeString(sca);
|
||||
}
|
||||
|
||||
Buf.sendParcel();
|
||||
},
|
||||
|
||||
@ -5506,7 +5588,17 @@ RilObject.prototype[REQUEST_GET_SMSC_ADDRESS] = function REQUEST_GET_SMSC_ADDRES
|
||||
options.smscAddress = this.SMSC;
|
||||
this.sendChromeMessage(options);
|
||||
};
|
||||
RilObject.prototype[REQUEST_SET_SMSC_ADDRESS] = null;
|
||||
RilObject.prototype[REQUEST_SET_SMSC_ADDRESS] = function REQUEST_SET_SMSC_ADDRESS(length, options) {
|
||||
if (!options.rilMessageType || options.rilMessageType !== "setSmscAddress") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.rilRequestError) {
|
||||
optioins.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
|
||||
}
|
||||
|
||||
this.sendChromeMessage(options);
|
||||
};
|
||||
RilObject.prototype[REQUEST_REPORT_SMS_MEMORY_STATUS] = function REQUEST_REPORT_SMS_MEMORY_STATUS(length, options) {
|
||||
this.pendingToReportSmsMemoryStatus = !!options.errorMsg;
|
||||
};
|
||||
@ -15398,6 +15490,7 @@ let ContextPool = {
|
||||
RILQUIRKS_DATA_REGISTRATION_ON_DEMAND = quirks.dataRegistrationOnDemand;
|
||||
RILQUIRKS_SUBSCRIPTION_CONTROL = quirks.subscriptionControl;
|
||||
RILQUIRKS_SIGNAL_EXTRA_INT32 = quirks.signalExtraInt;
|
||||
RILQUIRKS_SMSC_ADDRESS_FORMAT = quirks.smscAddressFormat;
|
||||
},
|
||||
|
||||
setDebugFlag: function(aOptions) {
|
||||
|
71
dom/system/gonk/tests/test_ril_worker_smsc_address.js
Normal file
71
dom/system/gonk/tests/test_ril_worker_smsc_address.js
Normal file
@ -0,0 +1,71 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
|
||||
|
||||
const SMSC_ATT = '+13123149810';
|
||||
const SMSC_ATT_TYPO = '+++1312@@@314$$$9,8,1,0';
|
||||
const SMSC_ATT_TEXT = '"+13123149810",145';
|
||||
const SMSC_ATT_PDU = '07913121139418F0';
|
||||
const SMSC_O2 = '+447802000332';
|
||||
const SMSC_O2_TEXT = '"+447802000332",145';
|
||||
const SMSC_O2_PDU = '0791448720003023';
|
||||
const SMSC_TON_UNKNOWN = '0407485455'
|
||||
const SMSC_TON_UNKNOWN_TEXT = '"0407485455",129';
|
||||
const SMSC_TON_UNKNOWN_PDU = '06814070844555';
|
||||
|
||||
function run_test() {
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function setSmsc(context, smsc, ton, npi, expected) {
|
||||
context.Buf.sendParcel = function() {
|
||||
equal(this.readString(), expected);
|
||||
};
|
||||
|
||||
context.RIL.setSmscAddress({
|
||||
smscAddress: smsc,
|
||||
typeOfNumber: ton,
|
||||
numberPlanIdentification: npi
|
||||
});
|
||||
}
|
||||
|
||||
add_test(function test_setSmscAddress() {
|
||||
let worker = newUint8Worker();
|
||||
let context = worker.ContextPool._contexts[0];
|
||||
let parcelTypes = [];
|
||||
context.Buf.newParcel = (type, options) => parcelTypes.push(type);
|
||||
|
||||
// Test text mode.
|
||||
worker.RILQUIRKS_SMSC_ADDRESS_FORMAT = "text";
|
||||
|
||||
setSmsc(context, SMSC_ATT, 1, 1, SMSC_ATT_TEXT);
|
||||
equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
|
||||
|
||||
setSmsc(context, SMSC_O2, 1, 1, SMSC_O2_TEXT);
|
||||
equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
|
||||
|
||||
setSmsc(context, SMSC_ATT_TYPO, 1, 1, SMSC_ATT_TEXT);
|
||||
equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
|
||||
|
||||
setSmsc(context, SMSC_TON_UNKNOWN, 0, 1, SMSC_TON_UNKNOWN_TEXT);
|
||||
equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
|
||||
|
||||
// Test pdu mode.
|
||||
worker.RILQUIRKS_SMSC_ADDRESS_FORMAT = "pdu";
|
||||
|
||||
setSmsc(context, SMSC_ATT, 1, 1, SMSC_ATT_PDU);
|
||||
equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
|
||||
|
||||
setSmsc(context, SMSC_O2, 1, 1, SMSC_O2_PDU);
|
||||
equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
|
||||
|
||||
setSmsc(context, SMSC_ATT_TYPO, 1, 1, SMSC_ATT_PDU);
|
||||
equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
|
||||
|
||||
setSmsc(context, SMSC_TON_UNKNOWN, 0, 1, SMSC_TON_UNKNOWN_PDU);
|
||||
equal(parcelTypes.pop(), REQUEST_SET_SMSC_ADDRESS);
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
@ -22,6 +22,7 @@ skip-if = true
|
||||
[test_ril_worker_sms_nl_tables.js]
|
||||
[test_ril_worker_sms_gsmpduhelper.js]
|
||||
[test_ril_worker_sms_segment_info.js]
|
||||
[test_ril_worker_smsc_address.js]
|
||||
[test_ril_worker_mmi.js]
|
||||
[test_ril_worker_mmi_cf.js]
|
||||
[test_ril_worker_cf.js]
|
||||
|
@ -75,6 +75,45 @@ dictionary MobileMessageFilter
|
||||
[EnforceRange] unsigned long long? threadId = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* TON defined in |Table 10.5.118: Called party BCD number| of 3GPP TS 24.008.
|
||||
* It's used in SM-RL originator / destination address element as defined in
|
||||
* |8.2.5.2 Destination address element| of 3GPP TS 24.011.
|
||||
*/
|
||||
enum TypeOfNumber { "unknown", "international", "national", "network-specific",
|
||||
"dedicated-access-short-code" };
|
||||
|
||||
/**
|
||||
* NPI defined in |Table 10.5.118: Called party BCD number| of 3GPP TS 24.008.
|
||||
* It's used in SM-RL originator / destination address element as defined in
|
||||
* |8.2.5.2 Destination address element| of 3GPP TS 24.011.
|
||||
*/
|
||||
enum NumberPlanIdentification { "unknown", "isdn", "data", "telex", "national",
|
||||
"private" };
|
||||
|
||||
/**
|
||||
* Type of address used in SmscAddress.
|
||||
*
|
||||
* As described in |3.1 Parameters Definitions| of 3GPP TS 27.005, the default
|
||||
* value of <tosca> should be 129 (typeOfNumber=unknown,
|
||||
* numberPlanIdentification=isdn) if the number does not begin with '+'.
|
||||
*
|
||||
* |setSmscAddress| updates typeOfNumber to international automatically if the
|
||||
* given number begins with '+'.
|
||||
*/
|
||||
dictionary TypeOfAddress {
|
||||
TypeOfNumber typeOfNumber = "unknown";
|
||||
NumberPlanIdentification numberPlanIdentification = "isdn";
|
||||
};
|
||||
|
||||
/**
|
||||
* SMSC address.
|
||||
*/
|
||||
dictionary SmscAddress {
|
||||
DOMString address;
|
||||
TypeOfAddress typeOfAddress;
|
||||
};
|
||||
|
||||
[Pref="dom.sms.enabled",
|
||||
CheckPermissions="sms",
|
||||
AvailableIn="CertifiedApps"]
|
||||
@ -157,6 +196,22 @@ interface MozMobileMessageManager : EventTarget
|
||||
[Throws]
|
||||
DOMRequest getSmscAddress(optional unsigned long serviceId);
|
||||
|
||||
/**
|
||||
* Set the SMSC address.
|
||||
*
|
||||
* @param smscAddress
|
||||
* SMSC address to use.
|
||||
* Reject if smscAddress.address does not present.
|
||||
* @param serviceId (optional)
|
||||
* The ID of the RIL service which needs to be specified under
|
||||
* the multi-sim scenario.
|
||||
* @return a Promise
|
||||
* Resolve if success. Otherwise, reject with error cause.
|
||||
*/
|
||||
[NewObject]
|
||||
Promise<void> setSmscAddress(optional SmscAddress smscAddress,
|
||||
optional unsigned long serviceId);
|
||||
|
||||
attribute EventHandler onreceived;
|
||||
attribute EventHandler onretrieving;
|
||||
attribute EventHandler onsending;
|
||||
|
@ -21,7 +21,7 @@ interface nsITabParent;
|
||||
interface nsIURI;
|
||||
interface nsIWebBrowserChrome;
|
||||
|
||||
[scriptable, uuid(e28f810b-9b49-4927-a4be-62a74fadfe21)]
|
||||
[scriptable, uuid(b6c44689-f97e-4f32-a723-29eeddfbdc53)]
|
||||
|
||||
interface nsIWindowCreator2 : nsIWindowCreator {
|
||||
|
||||
@ -59,4 +59,14 @@ interface nsIWindowCreator2 : nsIWindowCreator {
|
||||
in nsIURI uri,
|
||||
in nsITabParent aOpeningTab,
|
||||
out boolean cancel);
|
||||
|
||||
/**
|
||||
* B2G multi-screen support. When open another top-level window on b2g,
|
||||
* a screen ID is needed for identifying which screen this window is
|
||||
* opened to.
|
||||
* @param aScreenId Differentiate screens of windows. It is platform-
|
||||
* specific due to the hardware limitation for now.
|
||||
*/
|
||||
[noscript]
|
||||
void setScreenId(in uint32_t aScreenId);
|
||||
};
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
#include "nsView.h"
|
||||
|
||||
#define APZCCH_LOG(...)
|
||||
// #define APZCCH_LOG(...) printf_stderr("APZCCH: " __VA_ARGS__)
|
||||
@ -499,6 +500,21 @@ GetDisplayportElementFor(nsIScrollableFrame* aScrollableFrame)
|
||||
return content->AsElement();
|
||||
}
|
||||
|
||||
|
||||
static dom::Element*
|
||||
GetRootDocumentElementFor(nsIWidget* aWidget)
|
||||
{
|
||||
// This returns the root element that ChromeProcessController sets the
|
||||
// displayport on during initialization.
|
||||
if (nsView* view = nsView::GetViewFor(aWidget)) {
|
||||
if (nsIPresShell* shell = view->GetPresShell()) {
|
||||
MOZ_ASSERT(shell->GetDocument());
|
||||
return shell->GetDocument()->GetDocumentElement();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Determine the scrollable target frame for the given point and add it to
|
||||
// the target list. If the frame doesn't have a displayport, set one.
|
||||
// Return whether or not a displayport was set.
|
||||
@ -515,7 +531,11 @@ PrepareForSetTargetAPZCNotification(nsIWidget* aWidget,
|
||||
nsIFrame* target =
|
||||
nsLayoutUtils::GetFrameForPoint(aRootFrame, point, nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME);
|
||||
nsIScrollableFrame* scrollAncestor = GetScrollableAncestorFrame(target);
|
||||
nsCOMPtr<dom::Element> dpElement = GetDisplayportElementFor(scrollAncestor);
|
||||
|
||||
// Assuming that if there's no scrollAncestor, there's already a displayPort.
|
||||
nsCOMPtr<dom::Element> dpElement = scrollAncestor
|
||||
? GetDisplayportElementFor(scrollAncestor)
|
||||
: GetRootDocumentElementFor(aWidget);
|
||||
|
||||
nsAutoString dpElementDesc;
|
||||
if (dpElement) {
|
||||
@ -534,6 +554,7 @@ PrepareForSetTargetAPZCNotification(nsIWidget* aWidget,
|
||||
}
|
||||
|
||||
APZCCH_LOG("%p didn't have a displayport, so setting one...\n", dpElement.get());
|
||||
MOZ_ASSERT(scrollAncestor);
|
||||
return nsLayoutUtils::CalculateAndSetDisplayPortMargins(
|
||||
scrollAncestor, nsLayoutUtils::RepaintMode::Repaint);
|
||||
}
|
||||
|
@ -606,6 +606,17 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer)
|
||||
// When doing so, it might be useful to look at how it was called here before
|
||||
// bug 1036967 removed the (dead) call.
|
||||
|
||||
#if defined(MOZ_ANDROID_APZ)
|
||||
if (mIsFirstPaint) {
|
||||
CSSToLayerScale geckoZoom = metrics.LayersPixelsPerCSSPixel().ToScaleFactor();
|
||||
LayerIntPoint scrollOffsetLayerPixels = RoundedToInt(metrics.GetScrollOffset() * geckoZoom);
|
||||
mContentRect = metrics.GetScrollableRect();
|
||||
SetFirstPaintViewport(scrollOffsetLayerPixels,
|
||||
geckoZoom,
|
||||
mContentRect);
|
||||
}
|
||||
#endif
|
||||
|
||||
mIsFirstPaint = false;
|
||||
mLayersUpdated = false;
|
||||
|
||||
|
@ -1521,12 +1521,12 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(nsDisplayListBuilder* aB
|
||||
nsIContent* content = nullptr;
|
||||
if (scrollFrame) {
|
||||
content = scrollFrame->GetContent();
|
||||
} else if (!gfxPrefs::LayoutUseContainersForRootFrames()) {
|
||||
// If there is no root scroll frame, and we're using containerless
|
||||
// scrolling, pick the document element instead.
|
||||
// On Android we want the root xul document to get a null scroll id
|
||||
// so that the root content document gets the first non-null scroll id.
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
} else {
|
||||
// If there is no root scroll frame, pick the document element instead.
|
||||
// The only case we don't want to do this is in non-APZ fennec, where
|
||||
// we want the root xul document to get a null scroll id so that the root
|
||||
// content document gets the first non-null scroll id.
|
||||
#if !defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ANDROID_APZ)
|
||||
content = document->GetDocumentElement();
|
||||
#endif
|
||||
}
|
||||
|
@ -3115,6 +3115,17 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
||||
}
|
||||
}
|
||||
}
|
||||
#if !defined(MOZ_WIDGET_ANDROID) || defined(MOZ_ANDROID_APZ)
|
||||
else if (presShell->GetDocument() && presShell->GetDocument()->IsRootDisplayDocument()) {
|
||||
// In cases where the root document is a XUL document, we want to take
|
||||
// the ViewID from the root element, as that will be the ViewID of the
|
||||
// root APZC in the tree.
|
||||
if (dom::Element* element = presShell->GetDocument()->GetDocumentElement()) {
|
||||
id = nsLayoutUtils::FindOrCreateIDFor(element);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
nsDisplayListBuilder::AutoCurrentScrollParentIdSetter idSetter(&builder, id);
|
||||
|
||||
PROFILER_LABEL("nsLayoutUtils", "PaintFrame::BuildDisplayList",
|
||||
|
@ -38,7 +38,7 @@ public class TabQueueDispatcher extends Locales.LocaleAwareActivity {
|
||||
|
||||
// For the moment lets exit early and start fennec as normal if we're not in nightly with
|
||||
// the tab queue build flag.
|
||||
if (!AppConstants.MOZ_ANDROID_TAB_QUEUE) {
|
||||
if (!AppConstants.MOZ_ANDROID_TAB_QUEUE || !AppConstants.NIGHTLY_BUILD) {
|
||||
loadNormally(intent.getUnsafe());
|
||||
return;
|
||||
}
|
||||
|
@ -90,6 +90,7 @@ public class StringHelper {
|
||||
public final String ROBOCOP_ADOBE_FLASH_URL = "/robocop/robocop_adobe_flash.html";
|
||||
public final String ROBOCOP_INPUT_URL = "/robocop/robocop_input.html";
|
||||
public final String ROBOCOP_READER_MODE_BASIC_ARTICLE = "/robocop/reader_mode_pages/basic_article.html";
|
||||
public final String ROBOCOP_LINK_TO_SLOW_LOADING = "/robocop/robocop_link_to_slow_loading.html";
|
||||
|
||||
private final String ROBOCOP_JS_HARNESS_URL = "/robocop/robocop_javascript.html";
|
||||
|
||||
|
@ -14,6 +14,7 @@ import org.mozilla.gecko.tests.components.AboutHomeComponent;
|
||||
import org.mozilla.gecko.tests.components.AppMenuComponent;
|
||||
import org.mozilla.gecko.tests.components.BaseComponent;
|
||||
import org.mozilla.gecko.tests.components.GeckoViewComponent;
|
||||
import org.mozilla.gecko.tests.components.TabStripComponent;
|
||||
import org.mozilla.gecko.tests.components.ToolbarComponent;
|
||||
import org.mozilla.gecko.tests.helpers.HelperInitializer;
|
||||
|
||||
@ -41,6 +42,7 @@ abstract class UITest extends BaseRobocopTest
|
||||
protected AboutHomeComponent mAboutHome;
|
||||
protected AppMenuComponent mAppMenu;
|
||||
protected GeckoViewComponent mGeckoView;
|
||||
protected TabStripComponent mTabStrip;
|
||||
protected ToolbarComponent mToolbar;
|
||||
|
||||
@Override
|
||||
@ -93,6 +95,7 @@ abstract class UITest extends BaseRobocopTest
|
||||
mAboutHome = new AboutHomeComponent(this);
|
||||
mAppMenu = new AppMenuComponent(this);
|
||||
mGeckoView = new GeckoViewComponent(this);
|
||||
mTabStrip = new TabStripComponent(this);
|
||||
mToolbar = new ToolbarComponent(this);
|
||||
}
|
||||
|
||||
|
56
mobile/android/base/tests/components/TabStripComponent.java
Normal file
56
mobile/android/base/tests/components/TabStripComponent.java
Normal file
@ -0,0 +1,56 @@
|
||||
package org.mozilla.gecko.tests.components;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import com.jayway.android.robotium.solo.Condition;
|
||||
|
||||
import org.mozilla.gecko.tests.UITestContext;
|
||||
import org.mozilla.gecko.tests.helpers.DeviceHelper;
|
||||
import org.mozilla.gecko.tests.helpers.WaitHelper;
|
||||
import org.mozilla.gecko.widget.TwoWayView;
|
||||
|
||||
import static org.mozilla.gecko.tests.helpers.AssertionHelper.*;
|
||||
|
||||
/**
|
||||
* A class representing any interactions that take place on the tablet tab strip.
|
||||
*/
|
||||
public class TabStripComponent extends BaseComponent {
|
||||
// Using a text id because the layout and therefore the id might be stripped from the (non-tablet) build
|
||||
private static final String TAB_STRIP_ID = "tab_strip";
|
||||
|
||||
public TabStripComponent(final UITestContext testContext) {
|
||||
super(testContext);
|
||||
}
|
||||
|
||||
public void switchToTab(int index) {
|
||||
// The tab strip is only available on tablets
|
||||
DeviceHelper.assertIsTablet();
|
||||
|
||||
View tabView = waitForTabView(index);
|
||||
fAssertNotNull(String.format("Tab at index %d is not null", index), tabView);
|
||||
|
||||
mSolo.clickOnView(tabView);
|
||||
}
|
||||
|
||||
private View waitForTabView(final int index) {
|
||||
final TwoWayView tabStrip = getTabStripView();
|
||||
final View[] tabView = new View[1];
|
||||
|
||||
WaitHelper.waitFor(String.format("Tab at index %d to be visible", index), new Condition() {
|
||||
@Override
|
||||
public boolean isSatisfied() {
|
||||
return (tabView[0] = tabStrip.getChildAt(index)) != null;
|
||||
}
|
||||
});
|
||||
|
||||
return tabView[0];
|
||||
}
|
||||
|
||||
private TwoWayView getTabStripView() {
|
||||
TwoWayView tabStrip = (TwoWayView) mSolo.getView("tab_strip");
|
||||
|
||||
fAssertNotNull("Tab strip is not null", tabStrip);
|
||||
|
||||
return tabStrip;
|
||||
}
|
||||
}
|
@ -84,6 +84,11 @@ public class ToolbarComponent extends BaseComponent {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ToolbarComponent assertBackButtonIsNotEnabled() {
|
||||
fAssertFalse("The back button is not enabled", isBackButtonEnabled());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root View for the browser toolbar.
|
||||
*/
|
||||
@ -306,4 +311,8 @@ public class ToolbarComponent extends BaseComponent {
|
||||
private boolean isUrlEditTextSelected() {
|
||||
return getUrlEditText().isSelected();
|
||||
}
|
||||
|
||||
private boolean isBackButtonEnabled() {
|
||||
return getBackButton().isEnabled();
|
||||
}
|
||||
}
|
||||
|
50
mobile/android/base/tests/helpers/GeckoClickHelper.java
Normal file
50
mobile/android/base/tests/helpers/GeckoClickHelper.java
Normal file
@ -0,0 +1,50 @@
|
||||
package org.mozilla.gecko.tests.helpers;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.util.DisplayMetrics;
|
||||
|
||||
import com.jayway.android.robotium.solo.Solo;
|
||||
|
||||
import org.mozilla.gecko.Driver;
|
||||
import org.mozilla.gecko.tests.StringHelper;
|
||||
import org.mozilla.gecko.tests.UITestContext;
|
||||
|
||||
/**
|
||||
* Provides helper functions for clicking elements rendered by the Gecko engine.
|
||||
*/
|
||||
public class GeckoClickHelper {
|
||||
private static Solo sSolo;
|
||||
private static Activity sActivity;
|
||||
private static Driver sDriver;
|
||||
|
||||
protected static void init(final UITestContext context) {
|
||||
sSolo = context.getSolo();
|
||||
sActivity = context.getActivity();
|
||||
sDriver = context.getDriver();
|
||||
}
|
||||
|
||||
private GeckoClickHelper() { /* To disallow instantiation. */ }
|
||||
|
||||
/**
|
||||
* Long press the link and select "Open Link in New Tab" from the context menu.
|
||||
*
|
||||
* The link should be positioned at the top of the page, at least 60px high and
|
||||
* aligned to the middle.
|
||||
*/
|
||||
public static void openCentralizedLinkInNewTab() {
|
||||
openLinkContextMenu();
|
||||
|
||||
// Click on "Open Link in New Tab"
|
||||
sSolo.clickOnText(StringHelper.get().CONTEXT_MENU_ITEMS_IN_NORMAL_TAB[0]);
|
||||
}
|
||||
|
||||
private static void openLinkContextMenu() {
|
||||
DisplayMetrics dm = new DisplayMetrics();
|
||||
sActivity.getWindowManager().getDefaultDisplay().getMetrics(dm);
|
||||
|
||||
sSolo.clickLongOnScreen(
|
||||
sDriver.getGeckoLeft() + sDriver.getGeckoWidth() / 2,
|
||||
sDriver.getGeckoTop() + 30 * dm.density
|
||||
);
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ public final class HelperInitializer {
|
||||
AssertionHelper.init(context);
|
||||
|
||||
DeviceHelper.init(context);
|
||||
GeckoClickHelper.init(context);
|
||||
GeckoHelper.init(context);
|
||||
JavascriptBridge.init(context);
|
||||
NavigationHelper.init(context);
|
||||
|
@ -166,6 +166,7 @@ skip-if = android_version == "10" || android_version == "18"
|
||||
[testSessionHistory]
|
||||
# disabled on Android 4.3, bug 1144879
|
||||
skip-if = android_version == "18"
|
||||
[testStateWhileLoading]
|
||||
|
||||
# testSelectionHandler disabled on Android 2.3 by trailing skip-if, due to bug 980074
|
||||
# also disabled on Android 4.3, bug 1144882
|
||||
|
12
mobile/android/base/tests/robocop_link_to_slow_loading.html
Normal file
12
mobile/android/base/tests/robocop_link_to_slow_loading.html
Normal file
@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Link</title>
|
||||
<meta name="viewport" content="initial-scale=1.0"/>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body style="margin: 0; padding: 0">
|
||||
<div style="text-align: center; margin: 0; padding: 0">
|
||||
<a style="font-size: 60px" href="robocop_slow_loading.html">Slow Loading Page</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
23
mobile/android/base/tests/robocop_slow_loading.html
Normal file
23
mobile/android/base/tests/robocop_slow_loading.html
Normal file
@ -0,0 +1,23 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Slow Loading</title>
|
||||
<meta name="viewport" content="initial-scale=1.0"/>
|
||||
<meta charset="utf-8">
|
||||
<script type="text/javascript">
|
||||
|
||||
// Busy wait (There's no sleep function in JavaScript)
|
||||
var waitForMilliseconds = 10000;
|
||||
var start = new Date();
|
||||
var now = null;
|
||||
do {
|
||||
now = new Date();
|
||||
} while (now - start < waitForMilliseconds);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body style="margin: 0; padding: 0">
|
||||
<div style="text-align: center; margin: 0; padding: 0">
|
||||
<h1>This page is loading very slow.</h1>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
40
mobile/android/base/tests/testStateWhileLoading.java
Normal file
40
mobile/android/base/tests/testStateWhileLoading.java
Normal file
@ -0,0 +1,40 @@
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import org.mozilla.gecko.tests.helpers.DeviceHelper;
|
||||
import org.mozilla.gecko.tests.helpers.GeckoClickHelper;
|
||||
import org.mozilla.gecko.tests.helpers.GeckoHelper;
|
||||
import org.mozilla.gecko.tests.helpers.NavigationHelper;
|
||||
import org.mozilla.gecko.tests.helpers.WaitHelper;
|
||||
|
||||
/**
|
||||
* This test ensures the back/forward state is correct when switching to loading pages
|
||||
* to prevent regressions like Bug 1124190.
|
||||
*/
|
||||
public class testStateWhileLoading extends UITest {
|
||||
public void testStateWhileLoading() {
|
||||
if (!DeviceHelper.isTablet()) {
|
||||
// This test case only covers tablets currently.
|
||||
return;
|
||||
}
|
||||
|
||||
GeckoHelper.blockForReady();
|
||||
|
||||
NavigationHelper.enterAndLoadUrl(mStringHelper.ROBOCOP_LINK_TO_SLOW_LOADING);
|
||||
|
||||
GeckoClickHelper.openCentralizedLinkInNewTab();
|
||||
|
||||
WaitHelper.waitForPageLoad(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mTabStrip.switchToTab(1);
|
||||
|
||||
// Assert that the state of the back button is correct
|
||||
// after switching to the new (still loading) tab.
|
||||
mToolbar.assertBackButtonIsNotEnabled();
|
||||
}
|
||||
});
|
||||
|
||||
// Assert that the state of the back button is still correct after the page has loaded.
|
||||
mToolbar.assertBackButtonIsNotEnabled();
|
||||
}
|
||||
}
|
@ -614,6 +614,17 @@ nsAppStartup::CreateChromeWindow(nsIWebBrowserChrome *aParent,
|
||||
// nsAppStartup->nsIWindowCreator2
|
||||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAppStartup::SetScreenId(uint32_t aScreenId)
|
||||
{
|
||||
nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
|
||||
if (!appShell) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return appShell->SetScreenId(aScreenId);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAppStartup::CreateChromeWindow2(nsIWebBrowserChrome *aParent,
|
||||
uint32_t aChromeFlags,
|
||||
|
@ -1060,10 +1060,7 @@ let loadManifestFromDir = Task.async(function* loadManifestFromDir(aDir) {
|
||||
addon.hasBinaryComponents = ChromeManifestParser.hasType(chromeManifest,
|
||||
"binary-component");
|
||||
|
||||
if (SIGNED_TYPES.has(addon.type))
|
||||
addon.signedState = yield verifyDirSignedState(aDir, addon.id);
|
||||
else
|
||||
addon.signedState = AddonManager.SIGNEDSTATE_MISSING;
|
||||
addon.signedState = yield verifyDirSignedState(aDir, addon);
|
||||
|
||||
addon.appDisabled = !isUsableAddon(addon);
|
||||
return addon;
|
||||
@ -1108,10 +1105,7 @@ let loadManifestFromZipReader = Task.async(function* loadManifestFromZipReader(a
|
||||
addon.hasBinaryComponents = false;
|
||||
}
|
||||
|
||||
if (SIGNED_TYPES.has(addon.type))
|
||||
addon.signedState = yield verifyZipSignedState(aZipReader.file, addon.id, addon.version);
|
||||
else
|
||||
addon.signedState = AddonManager.SIGNEDSTATE_MISSING;
|
||||
addon.signedState = yield verifyZipSignedState(aZipReader.file, addon);
|
||||
|
||||
addon.appDisabled = !isUsableAddon(addon);
|
||||
return addon;
|
||||
@ -1325,11 +1319,14 @@ function getSignedStatus(aRv, aCert, aExpectedID) {
|
||||
*
|
||||
* @param aFile
|
||||
* the xpi file to check
|
||||
* @param aExpectedID
|
||||
* the expected ID of the signature
|
||||
* @param aAddon
|
||||
* the add-on object to verify
|
||||
* @return a Promise that resolves to an AddonManager.SIGNEDSTATE_* constant.
|
||||
*/
|
||||
function verifyZipSignedState(aFile, aExpectedID, aVersion) {
|
||||
function verifyZipSignedState(aFile, aAddon) {
|
||||
if (!SIGNED_TYPES.has(aAddon.type))
|
||||
return Promise.resolve(undefined);
|
||||
|
||||
let certDB = Cc["@mozilla.org/security/x509certdb;1"]
|
||||
.getService(Ci.nsIX509CertDB);
|
||||
|
||||
@ -1341,7 +1338,7 @@ function verifyZipSignedState(aFile, aExpectedID, aVersion) {
|
||||
certDB.openSignedAppFileAsync(root, aFile, (aRv, aZipReader, aCert) => {
|
||||
if (aZipReader)
|
||||
aZipReader.close();
|
||||
resolve(getSignedStatus(aRv, aCert, aExpectedID));
|
||||
resolve(getSignedStatus(aRv, aCert, aAddon.id));
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -1352,11 +1349,14 @@ function verifyZipSignedState(aFile, aExpectedID, aVersion) {
|
||||
*
|
||||
* @param aDir
|
||||
* the directory to check
|
||||
* @param aExpectedID
|
||||
* the expected ID of the signature
|
||||
* @param aAddon
|
||||
* the add-on object to verify
|
||||
* @return a Promise that resolves to an AddonManager.SIGNEDSTATE_* constant.
|
||||
*/
|
||||
function verifyDirSignedState(aDir, aExpectedID) {
|
||||
function verifyDirSignedState(aDir, aAddon) {
|
||||
if (!SIGNED_TYPES.has(aAddon.type))
|
||||
return Promise.resolve(undefined);
|
||||
|
||||
// TODO: Get the certificate for an unpacked add-on (bug 1038072)
|
||||
return Promise.resolve(AddonManager.SIGNEDSTATE_MISSING);
|
||||
}
|
||||
@ -1367,14 +1367,14 @@ function verifyDirSignedState(aDir, aExpectedID) {
|
||||
*
|
||||
* @param aBundle
|
||||
* the nsIFile for the bundle to check, either a directory or zip file
|
||||
* @param aExpectedID
|
||||
* the expected ID of the signature
|
||||
* @param aAddon
|
||||
* the add-on object to verify
|
||||
* @return a Promise that resolves to an AddonManager.SIGNEDSTATE_* constant.
|
||||
*/
|
||||
function verifyBundleSignedState(aBundle, aExpectedID) {
|
||||
function verifyBundleSignedState(aBundle, aAddon) {
|
||||
if (aBundle.isFile())
|
||||
return verifyZipSignedState(aBundle, aExpectedID);
|
||||
return verifyDirSignedState(aBundle, aExpectedID);
|
||||
return verifyZipSignedState(aBundle, aAddon);
|
||||
return verifyDirSignedState(aBundle, aAddon);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2522,7 +2522,7 @@ this.XPIProvider = {
|
||||
* Verifies that all installed add-ons are still correctly signed.
|
||||
*/
|
||||
verifySignatures: function XPI_verifySignatures() {
|
||||
XPIDatabase.getAddonList(addon => SIGNED_TYPES.has(addon.type), (addons) => {
|
||||
XPIDatabase.getAddonList(a => true, (addons) => {
|
||||
Task.spawn(function*() {
|
||||
let changes = {
|
||||
enabled: [],
|
||||
@ -2534,7 +2534,7 @@ this.XPIProvider = {
|
||||
if (!addon._sourceBundle.exists())
|
||||
continue;
|
||||
|
||||
let signedState = yield verifyBundleSignedState(addon._sourceBundle, addon.id);
|
||||
let signedState = yield verifyBundleSignedState(addon._sourceBundle, addon);
|
||||
if (signedState == addon.signedState)
|
||||
continue;
|
||||
|
||||
@ -3168,7 +3168,7 @@ this.XPIProvider = {
|
||||
|
||||
// If updating from a version of the app that didn't support signedState
|
||||
// then fetch that property now
|
||||
if (aOldAddon.signedState === undefined) {
|
||||
if (aOldAddon.signedState === undefined && SIGNED_TYPES.has(aOldAddon.type)) {
|
||||
let file = aInstallLocation.getLocationForID(aOldAddon.id);
|
||||
let manifest = syncLoadManifestFromFile(file);
|
||||
aOldAddon.signedState = manifest.signedState;
|
||||
@ -5418,7 +5418,8 @@ AddonInstall.prototype = {
|
||||
"signature verification failed"])
|
||||
}
|
||||
}
|
||||
else if (this.addon.signedState == AddonManager.SIGNEDSTATE_UNKNOWN) {
|
||||
else if (this.addon.signedState == AddonManager.SIGNEDSTATE_UNKNOWN ||
|
||||
this.addon.signedState == undefined) {
|
||||
// Check object signing certificate, if any
|
||||
let x509 = zipreader.getSigningCert(null);
|
||||
if (x509) {
|
||||
|
@ -95,10 +95,12 @@ function run_test() {
|
||||
do_check_neq(d, null);
|
||||
do_check_false(d.skinnable);
|
||||
do_check_false(d.foreignInstall);
|
||||
do_check_eq(d.signedState, undefined);
|
||||
|
||||
do_check_neq(t1, null);
|
||||
do_check_false(t1.userDisabled);
|
||||
do_check_false(t1.appDisabled);
|
||||
do_check_eq(t1.signedState, undefined);
|
||||
do_check_true(t1.isActive);
|
||||
do_check_true(t1.skinnable);
|
||||
do_check_true(t1.foreignInstall);
|
||||
@ -112,6 +114,7 @@ function run_test() {
|
||||
do_check_neq(t2, null);
|
||||
do_check_true(t2.userDisabled);
|
||||
do_check_false(t2.appDisabled);
|
||||
do_check_eq(t2.signedState, undefined);
|
||||
do_check_false(t2.isActive);
|
||||
do_check_false(t2.skinnable);
|
||||
do_check_true(t2.foreignInstall);
|
||||
|
@ -40,8 +40,8 @@ body.dark a::-moz-selection {
|
||||
}
|
||||
|
||||
body.sepia {
|
||||
color: #333333;
|
||||
background-color: #f0ece7;
|
||||
color: #5b4636;
|
||||
background-color: #f4ecd8;
|
||||
}
|
||||
|
||||
body.sans-serif,
|
||||
@ -92,11 +92,14 @@ body.serif .remove-button {
|
||||
|
||||
/* Override some controls and content styles based on color scheme */
|
||||
|
||||
body.light > .container > .header > .domain,
|
||||
body.sepia > .container > .header > .domain {
|
||||
body.light > .container > .header > .domain {
|
||||
border-bottom-color: #333333 !important;
|
||||
}
|
||||
|
||||
body.sepia > .container > .header > .domain {
|
||||
border-bottom-color: #5b4636 !important;
|
||||
}
|
||||
|
||||
body.dark > .container > .header > .domain {
|
||||
border-bottom-color: #eeeeee !important;
|
||||
}
|
||||
@ -105,11 +108,14 @@ body.sepia > .container > .footer {
|
||||
background-color: #dedad4 !important;
|
||||
}
|
||||
|
||||
body.light blockquote,
|
||||
body.sepia blockquote {
|
||||
body.light blockquote {
|
||||
-moz-border-start: 2px solid #333333 !important;
|
||||
}
|
||||
|
||||
body.sepia blockquote {
|
||||
-moz-border-start: 2px solid #5b4636 !important;
|
||||
}
|
||||
|
||||
body.dark blockquote {
|
||||
-moz-border-start: 2px solid #eeeeee !important;
|
||||
}
|
||||
|
@ -13,8 +13,8 @@
|
||||
}
|
||||
|
||||
.sepia-button {
|
||||
color: #333333;
|
||||
background-color: #f0ece7;
|
||||
color: #5b4636;
|
||||
background-color: #f4ecd8;
|
||||
}
|
||||
|
||||
.sans-serif-button {
|
||||
|
@ -639,7 +639,6 @@ StartBootAnimation()
|
||||
pthread_create(&sAnimationThread, nullptr, AnimationThread, nullptr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
StopBootAnimation()
|
||||
{
|
||||
|
@ -128,16 +128,15 @@ GonkDisplayJB::GonkDisplayJB()
|
||||
#else
|
||||
sp<Surface> stc = new Surface(producer);
|
||||
#endif
|
||||
|
||||
mSTClient = stc;
|
||||
mSTClient->perform(mSTClient.get(), NATIVE_WINDOW_SET_BUFFER_COUNT, 2);
|
||||
mSTClient->perform(mSTClient.get(), NATIVE_WINDOW_SET_USAGE,
|
||||
GRALLOC_USAGE_HW_FB |
|
||||
GRALLOC_USAGE_HW_RENDER |
|
||||
GRALLOC_USAGE_HW_COMPOSER);
|
||||
|
||||
mList = (hwc_display_contents_1_t *)malloc(sizeof(*mList) + (sizeof(hwc_layer_1_t)*2));
|
||||
if (mHwc) {
|
||||
|
||||
uint32_t usage = GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER;
|
||||
if (mFBDevice) {
|
||||
// If device uses fb, they can not use single buffer for boot animation
|
||||
mSTClient->perform(mSTClient.get(), NATIVE_WINDOW_SET_BUFFER_COUNT, 2);
|
||||
mSTClient->perform(mSTClient.get(), NATIVE_WINDOW_SET_USAGE, usage);
|
||||
} else if (mHwc) {
|
||||
#if ANDROID_VERSION >= 21
|
||||
if (mHwc->common.version >= HWC_DEVICE_API_VERSION_1_4) {
|
||||
mHwc->setPowerMode(mHwc, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_NORMAL);
|
||||
@ -147,9 +146,11 @@ GonkDisplayJB::GonkDisplayJB()
|
||||
#else
|
||||
mHwc->blank(mHwc, HWC_DISPLAY_PRIMARY, 0);
|
||||
#endif
|
||||
// For devices w/ hwc v1.0 or no hwc, this buffer can not be created,
|
||||
// only create this buffer for devices w/ hwc version > 1.0.
|
||||
mBootAnimBuffer = mAlloc->createGraphicBuffer(mWidth, mHeight, surfaceformat, usage, &err);
|
||||
}
|
||||
|
||||
|
||||
ALOGI("Starting bootanimation with (%d) format framebuffer", surfaceformat);
|
||||
StartBootAnimation();
|
||||
}
|
||||
@ -166,7 +167,9 @@ GonkDisplayJB::~GonkDisplayJB()
|
||||
ANativeWindow*
|
||||
GonkDisplayJB::GetNativeWindow()
|
||||
{
|
||||
StopBootAnimation();
|
||||
if (!mBootAnimBuffer.get()) {
|
||||
StopBootAnimation();
|
||||
}
|
||||
return mSTClient.get();
|
||||
}
|
||||
|
||||
@ -232,6 +235,11 @@ GonkDisplayJB::GetDispSurface()
|
||||
bool
|
||||
GonkDisplayJB::SwapBuffers(EGLDisplay dpy, EGLSurface sur)
|
||||
{
|
||||
if (mBootAnimBuffer.get()) {
|
||||
StopBootAnimation();
|
||||
mBootAnimBuffer = nullptr;
|
||||
}
|
||||
|
||||
// Should be called when composition rendering is complete for a frame.
|
||||
// Only HWC v1.0 needs this call.
|
||||
// HWC > v1.0 case, do not call compositionComplete().
|
||||
@ -307,6 +315,9 @@ GonkDisplayJB::Post(buffer_handle_t buf, int fence)
|
||||
ANativeWindowBuffer*
|
||||
GonkDisplayJB::DequeueBuffer()
|
||||
{
|
||||
if (mBootAnimBuffer.get()) {
|
||||
return static_cast<ANativeWindowBuffer*>(mBootAnimBuffer.get());
|
||||
}
|
||||
ANativeWindowBuffer *buf;
|
||||
mSTClient->dequeueBuffer(mSTClient.get(), &buf, &mFence);
|
||||
return buf;
|
||||
@ -316,14 +327,20 @@ bool
|
||||
GonkDisplayJB::QueueBuffer(ANativeWindowBuffer* buf)
|
||||
{
|
||||
bool success = Post(buf->handle, -1);
|
||||
int error = mSTClient->queueBuffer(mSTClient.get(), buf, mFence);
|
||||
|
||||
int error = 0;
|
||||
if (!mBootAnimBuffer.get()) {
|
||||
error = mSTClient->queueBuffer(mSTClient.get(), buf, mFence);
|
||||
}
|
||||
return error == 0 && success;
|
||||
}
|
||||
|
||||
void
|
||||
GonkDisplayJB::UpdateDispSurface(EGLDisplay dpy, EGLSurface sur)
|
||||
{
|
||||
if (mBootAnimBuffer.get()) {
|
||||
StopBootAnimation();
|
||||
mBootAnimBuffer = nullptr;
|
||||
}
|
||||
eglSwapBuffers(dpy, sur);
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,7 @@ private:
|
||||
android::sp<android::DisplaySurface> mDispSurface;
|
||||
android::sp<ANativeWindow> mSTClient;
|
||||
android::sp<android::IGraphicBufferAlloc> mAlloc;
|
||||
android::sp<android::GraphicBuffer> mBootAnimBuffer;
|
||||
int mFence;
|
||||
hwc_display_contents_1_t* mList;
|
||||
uint32_t mWidth;
|
||||
|
@ -316,7 +316,7 @@ KeyEventDispatcher::DispatchKeyEventInternal(uint32_t aEventMessage)
|
||||
event.modifiers = getDOMModifiers(mData.metaState);
|
||||
event.location = mDOMKeyLocation;
|
||||
event.time = mData.timeMs;
|
||||
return nsWindow::DispatchInputEvent(event);
|
||||
return nsWindow::DispatchKeyInput(event);
|
||||
}
|
||||
|
||||
void
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user