зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound.
This commit is contained in:
Коммит
6d3218ffe0
|
@ -471,6 +471,8 @@
|
|||
@BINPATH@/components/DOMWifiManager.manifest
|
||||
@BINPATH@/components/NetworkStatsManager.js
|
||||
@BINPATH@/components/NetworkStatsManager.manifest
|
||||
@BINPATH@/components/NetworkInterfaceListService.manifest
|
||||
@BINPATH@/components/NetworkInterfaceListService.js
|
||||
#endif
|
||||
#ifdef MOZ_B2G_FM
|
||||
@BINPATH@/components/DOMFMRadioChild.js
|
||||
|
|
|
@ -62,7 +62,10 @@ this.BrowserNewTabPreloader = {
|
|||
newTab: function Preloader_newTab(aTab) {
|
||||
let win = aTab.ownerDocument.defaultView;
|
||||
if (win.gBrowser) {
|
||||
let {boxObject: {width, height}} = win.gBrowser;
|
||||
let utils = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
let {width, height} = utils.getBoundsWithoutFlushing(win.gBrowser);
|
||||
let hiddenBrowser = HiddenBrowsers.get(width, height)
|
||||
if (hiddenBrowser) {
|
||||
return hiddenBrowser.swapWithNewTab(aTab);
|
||||
|
|
|
@ -1540,6 +1540,35 @@ nsDOMWindowUtils::GetScrollbarSize(bool aFlushLayout, int32_t* aWidth,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetBoundsWithoutFlushing(nsIDOMElement *aElement,
|
||||
nsIDOMClientRect** aResult)
|
||||
{
|
||||
if (!nsContentUtils::IsCallerChrome()) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
|
||||
NS_ENSURE_STATE(window);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<nsClientRect> rect = new nsClientRect(window);
|
||||
nsIFrame* frame = content->GetPrimaryFrame();
|
||||
|
||||
if (frame) {
|
||||
nsRect r = nsLayoutUtils::GetAllInFlowRectsUnion(frame,
|
||||
nsLayoutUtils::GetContainingBlockForClientRect(frame),
|
||||
nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS);
|
||||
rect->SetLayoutRect(r);
|
||||
}
|
||||
|
||||
rect.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetRootBounds(nsIDOMClientRect** aResult)
|
||||
{
|
||||
|
|
|
@ -903,14 +903,7 @@ RunDBusCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable,
|
|||
// being gtk based, sometimes we'll get signals/reply coming in on the main
|
||||
// thread. There's not a lot we can do about that for the time being and it
|
||||
// (technically) shouldn't hurt anything. However, on gonk, die.
|
||||
|
||||
// Due to the fact introducing workaround in Bug 827888, the callback for a
|
||||
// message gets executed immediately. The proper fix is in bug 830290, but
|
||||
// it's a intrusive change, it is better to remove assertion here since it
|
||||
// would not hurt anything.
|
||||
// Tracking bug 830290 for intrusive solution.
|
||||
|
||||
// MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
#endif
|
||||
nsRefPtr<BluetoothReplyRunnable> replyRunnable =
|
||||
dont_AddRef(static_cast< BluetoothReplyRunnable* >(aBluetoothReplyRunnable));
|
||||
|
|
|
@ -205,6 +205,39 @@ const CONTACT_CONTRACTID = "@mozilla.org/contact;1";
|
|||
const CONTACT_CID = Components.ID("{72a5ee28-81d8-4af8-90b3-ae935396cc66}");
|
||||
const nsIDOMContact = Components.interfaces.nsIDOMContact;
|
||||
|
||||
function checkBlobArray(aBlob) {
|
||||
if (Array.isArray(aBlob)) {
|
||||
for (let i = 0; i < aBlob.length; i++) {
|
||||
if (typeof aBlob != 'object') {
|
||||
return null;
|
||||
}
|
||||
if (!(aBlob[i] instanceof Components.interfaces.nsIDOMBlob)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return aBlob;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function isVanillaObj(aObj) {
|
||||
return Object.prototype.toString.call(aObj) == "[object Object]";
|
||||
}
|
||||
|
||||
function validateArrayField(data, createCb) {
|
||||
if (data) {
|
||||
data = Array.isArray(data) ? data : [data];
|
||||
let filtered = [];
|
||||
for (let obj of data) {
|
||||
if (obj && isVanillaObj(obj)) {
|
||||
filtered.push(createCb(obj));
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function Contact() { };
|
||||
|
||||
Contact.prototype = {
|
||||
|
@ -235,120 +268,220 @@ Contact.prototype = {
|
|||
genderIdentity: 'rw'
|
||||
},
|
||||
|
||||
set name(aName) {
|
||||
this._name = sanitizeStringArray(aName);
|
||||
},
|
||||
|
||||
get name() {
|
||||
return this._name;
|
||||
},
|
||||
|
||||
set honorificPrefix(aHonorificPrefix) {
|
||||
this._honorificPrefix = sanitizeStringArray(aHonorificPrefix);
|
||||
},
|
||||
|
||||
get honorificPrefix() {
|
||||
return this._honorificPrefix;
|
||||
},
|
||||
|
||||
set givenName(aGivenName) {
|
||||
this._givenName = sanitizeStringArray(aGivenName);
|
||||
},
|
||||
|
||||
get givenName() {
|
||||
return this._givenName;
|
||||
},
|
||||
|
||||
set additionalName(aAdditionalName) {
|
||||
this._additionalName = sanitizeStringArray(aAdditionalName);
|
||||
},
|
||||
|
||||
get additionalName() {
|
||||
return this._additionalName;
|
||||
},
|
||||
|
||||
set familyName(aFamilyName) {
|
||||
this._familyName = sanitizeStringArray(aFamilyName);
|
||||
},
|
||||
|
||||
get familyName() {
|
||||
return this._familyName;
|
||||
},
|
||||
|
||||
set honorificSuffix(aHonorificSuffix) {
|
||||
this._honorificSuffix = sanitizeStringArray(aHonorificSuffix);
|
||||
},
|
||||
|
||||
get honorificSuffix() {
|
||||
return this._honorificSuffix;
|
||||
},
|
||||
|
||||
set nickname(aNickname) {
|
||||
this._nickname = sanitizeStringArray(aNickname);
|
||||
},
|
||||
|
||||
get nickname() {
|
||||
return this._nickname;
|
||||
},
|
||||
|
||||
set photo(aPhoto) {
|
||||
this._photo = checkBlobArray(aPhoto);
|
||||
},
|
||||
|
||||
get photo() {
|
||||
return this._photo;
|
||||
},
|
||||
|
||||
set category(aCategory) {
|
||||
this._category = sanitizeStringArray(aCategory);
|
||||
},
|
||||
|
||||
get category() {
|
||||
return this._category;
|
||||
},
|
||||
|
||||
set email(aEmail) {
|
||||
this._email = validateArrayField(aEmail, function(email) {
|
||||
return new ContactField(email.type, email.value, email.pref);
|
||||
});
|
||||
},
|
||||
|
||||
get email() {
|
||||
return this._email;
|
||||
},
|
||||
|
||||
set adr(aAdr) {
|
||||
this._adr = validateArrayField(aAdr, function(adr) {
|
||||
return new ContactAddress(adr.type, adr.streetAddress, adr.locality,
|
||||
adr.region, adr.postalCode, adr.countryName,
|
||||
adr.pref);
|
||||
});
|
||||
},
|
||||
|
||||
get adr() {
|
||||
return this._adr;
|
||||
},
|
||||
|
||||
set tel(aTel) {
|
||||
this._tel = validateArrayField(aTel, function(tel) {
|
||||
return new ContactTelField(tel.type, tel.value, tel.carrier, tel.pref);
|
||||
});
|
||||
},
|
||||
|
||||
get tel() {
|
||||
return this._tel;
|
||||
},
|
||||
|
||||
set impp(aImpp) {
|
||||
this._impp = validateArrayField(aImpp, function(impp) {
|
||||
return new ContactField(impp.type, impp.value, impp.pref);
|
||||
});
|
||||
},
|
||||
|
||||
get impp() {
|
||||
return this._impp;
|
||||
},
|
||||
|
||||
set url(aUrl) {
|
||||
this._url = validateArrayField(aUrl, function(url) {
|
||||
return new ContactField(url.type, url.value, url.pref);
|
||||
});
|
||||
},
|
||||
|
||||
get url() {
|
||||
return this._url;
|
||||
},
|
||||
|
||||
set org(aOrg) {
|
||||
this._org = sanitizeStringArray(aOrg);
|
||||
},
|
||||
|
||||
get org() {
|
||||
return this._org;
|
||||
},
|
||||
|
||||
set jobTitle(aJobTitle) {
|
||||
this._jobTitle = sanitizeStringArray(aJobTitle);
|
||||
},
|
||||
|
||||
get jobTitle() {
|
||||
return this._jobTitle;
|
||||
},
|
||||
|
||||
set note(aNote) {
|
||||
this._note = sanitizeStringArray(aNote);
|
||||
},
|
||||
|
||||
get note() {
|
||||
return this._note;
|
||||
},
|
||||
|
||||
set bday(aBday) {
|
||||
if (aBday !== undefined && aBday !== null) {
|
||||
this._bday = new Date(aBday);
|
||||
}
|
||||
},
|
||||
|
||||
get bday() {
|
||||
return this._bday;
|
||||
},
|
||||
|
||||
set anniversary(aAnniversary) {
|
||||
if (aAnniversary !== undefined && aAnniversary !== null) {
|
||||
this._anniversary = new Date(aAnniversary);
|
||||
}
|
||||
},
|
||||
|
||||
get anniversary() {
|
||||
return this._anniversary;
|
||||
},
|
||||
|
||||
set sex(aSex) {
|
||||
if (aSex !== "undefined") {
|
||||
this._sex = aSex;
|
||||
} else {
|
||||
this._sex = null;
|
||||
}
|
||||
},
|
||||
|
||||
get sex() {
|
||||
return this._sex;
|
||||
},
|
||||
|
||||
set genderIdentity(aGenderIdentity) {
|
||||
if (aGenderIdentity !== "undefined") {
|
||||
this._genderIdentity = aGenderIdentity;
|
||||
} else {
|
||||
this._genderIdentity = null;
|
||||
}
|
||||
},
|
||||
|
||||
get genderIdentity() {
|
||||
return this._genderIdentity;
|
||||
},
|
||||
|
||||
init: function init(aProp) {
|
||||
function _checkBlobArray(aBlob) {
|
||||
if (Array.isArray(aBlob)) {
|
||||
for (let i = 0; i < aBlob.length; i++) {
|
||||
if (typeof aBlob != 'object') {
|
||||
return null;
|
||||
}
|
||||
if (!(aBlob[i] instanceof Components.interfaces.nsIDOMBlob)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return aBlob;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function _isVanillaObj(aObj) {
|
||||
return Object.prototype.toString.call(aObj) == "[object Object]";
|
||||
}
|
||||
|
||||
let _create = sanitizeStringArray;
|
||||
|
||||
this.name = _create(aProp.name);
|
||||
this.honorificPrefix = _create(aProp.honorificPrefix);
|
||||
this.givenName = _create(aProp.givenName);
|
||||
this.additionalName = _create(aProp.additionalName);
|
||||
this.familyName = _create(aProp.familyName);
|
||||
this.honorificSuffix = _create(aProp.honorificSuffix);
|
||||
this.nickname = _create(aProp.nickname);
|
||||
|
||||
if (aProp.email) {
|
||||
aProp.email = Array.isArray(aProp.email) ? aProp.email : [aProp.email];
|
||||
this.email = new Array();
|
||||
for (let email of aProp.email) {
|
||||
if (_isVanillaObj(email)) {
|
||||
this.email.push(new ContactField(email.type, email.value, email.pref));
|
||||
} else if (DEBUG) {
|
||||
debug("email field is not a ContactField and was ignored.");
|
||||
}
|
||||
}
|
||||
} else if (DEBUG) {
|
||||
this.email = null;
|
||||
}
|
||||
|
||||
this.photo = _checkBlobArray(aProp.photo);
|
||||
this.category = _create(aProp.category);
|
||||
|
||||
if (aProp.adr) {
|
||||
aProp.adr = Array.isArray(aProp.adr) ? aProp.adr : [aProp.adr];
|
||||
this.adr = new Array();
|
||||
for (let adr of aProp.adr) {
|
||||
if (_isVanillaObj(adr)) {
|
||||
this.adr.push(new ContactAddress(adr.type, adr.streetAddress, adr.locality,
|
||||
adr.region, adr.postalCode, adr.countryName,
|
||||
adr.pref));
|
||||
} else if (DEBUG) {
|
||||
debug("adr field is not a ContactAddress and was ignored.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.adr = null;
|
||||
}
|
||||
|
||||
if (aProp.tel) {
|
||||
aProp.tel = Array.isArray(aProp.tel) ? aProp.tel : [aProp.tel];
|
||||
this.tel = new Array();
|
||||
for (let tel of aProp.tel) {
|
||||
if (_isVanillaObj(tel)) {
|
||||
this.tel.push(new ContactTelField(tel.type, tel.value, tel.carrier,
|
||||
tel.pref));
|
||||
} else if (DEBUG) {
|
||||
debug("tel field is not a ContactTelField and was ignored.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.tel = null;
|
||||
}
|
||||
|
||||
this.org = _create(aProp.org);
|
||||
this.jobTitle = _create(aProp.jobTitle);
|
||||
this.bday = (aProp.bday == undefined || aProp.bday == null) ? null : new Date(aProp.bday);
|
||||
this.note = _create(aProp.note);
|
||||
|
||||
if (aProp.impp) {
|
||||
aProp.impp = Array.isArray(aProp.impp) ? aProp.impp : [aProp.impp];
|
||||
this.impp = new Array();
|
||||
for (let impp of aProp.impp) {
|
||||
if (_isVanillaObj(impp)) {
|
||||
this.impp.push(new ContactField(impp.type, impp.value, impp.pref));
|
||||
} else if (DEBUG) {
|
||||
debug("impp field is not a ContactField and was ignored.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.impp = null;
|
||||
}
|
||||
|
||||
if (aProp.url) {
|
||||
aProp.url = Array.isArray(aProp.url) ? aProp.url : [aProp.url];
|
||||
this.url = new Array();
|
||||
for (let url of aProp.url) {
|
||||
if (_isVanillaObj(url)) {
|
||||
this.url.push(new ContactField(url.type, url.value, url.pref));
|
||||
} else if (DEBUG) {
|
||||
debug("url field is not a ContactField and was ignored.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.url = null;
|
||||
}
|
||||
|
||||
this.anniversary = (aProp.anniversary == undefined || aProp.anniversary == null) ? null : new Date(aProp.anniversary);
|
||||
this.sex = (aProp.sex != "undefined") ? aProp.sex : null;
|
||||
this.genderIdentity = (aProp.genderIdentity != "undefined") ? aProp.genderIdentity : null;
|
||||
this.name = aProp.name;
|
||||
this.honorificPrefix = aProp.honorificPrefix;
|
||||
this.givenName = aProp.givenName;
|
||||
this.additionalName = aProp.additionalName;
|
||||
this.familyName = aProp.familyName;
|
||||
this.honorificSuffix = aProp.honorificSuffix;
|
||||
this.nickname = aProp.nickname;
|
||||
this.email = aProp.email;
|
||||
this.photo = aProp.photo;
|
||||
this.url = aProp.url;
|
||||
this.category = aProp.category;
|
||||
this.adr = aProp.adr;
|
||||
this.tel = aProp.tel;
|
||||
this.org = aProp.org;
|
||||
this.jobTitle = aProp.jobTitle;
|
||||
this.bday = aProp.bday;
|
||||
this.note = aProp.note;
|
||||
this.impp = aProp.impp;
|
||||
this.anniversary = aProp.anniversary;
|
||||
this.sex = aProp.sex;
|
||||
this.genderIdentity = aProp.genderIdentity;
|
||||
},
|
||||
|
||||
get published () {
|
||||
|
@ -380,7 +513,7 @@ Contact.prototype = {
|
|||
// ContactManager
|
||||
|
||||
const CONTACTMANAGER_CONTRACTID = "@mozilla.org/contactManager;1";
|
||||
const CONTACTMANAGER_CID = Components.ID("{7bfb6481-f946-4254-afc5-d7fe9f5c45a3}");
|
||||
const CONTACTMANAGER_CID = Components.ID("{8beb3a66-d70a-4111-b216-b8e995ad3aff}");
|
||||
const nsIDOMContactManager = Components.interfaces.nsIDOMContactManager;
|
||||
|
||||
function ContactManager()
|
||||
|
@ -525,6 +658,13 @@ ContactManager.prototype = {
|
|||
Services.DOMRequest.fireSuccess(req, msg.revision);
|
||||
}
|
||||
break;
|
||||
case "Contacts:Count":
|
||||
if (DEBUG) debug("count: " + msg.count);
|
||||
req = this.getRequest(msg.requestID);
|
||||
if (req) {
|
||||
Services.DOMRequest.fireSuccess(req, msg.count);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (DEBUG) debug("Wrong message: " + aMessage.name);
|
||||
}
|
||||
|
@ -545,6 +685,7 @@ ContactManager.prototype = {
|
|||
case "find":
|
||||
case "listen":
|
||||
case "revision":
|
||||
case "count":
|
||||
access = "read";
|
||||
break;
|
||||
default:
|
||||
|
@ -734,6 +875,23 @@ ContactManager.prototype = {
|
|||
return request;
|
||||
},
|
||||
|
||||
getCount: function() {
|
||||
let request = this.createRequest();
|
||||
|
||||
let allowCallback = function() {
|
||||
cpmm.sendAsyncMessage("Contacts:GetCount", {
|
||||
requestID: this.getRequestId(request)
|
||||
});
|
||||
}.bind(this);
|
||||
|
||||
let cancelCallback = function() {
|
||||
Services.DOMRequest.fireError(request);
|
||||
};
|
||||
|
||||
this.askPermission("count", request, allowCallback, cancelCallback);
|
||||
return request;
|
||||
},
|
||||
|
||||
init: function(aWindow) {
|
||||
this.initHelper(aWindow, ["Contacts:Find:Return:OK", "Contacts:Find:Return:KO",
|
||||
"Contacts:Clear:Return:OK", "Contacts:Clear:Return:KO",
|
||||
|
@ -741,8 +899,8 @@ ContactManager.prototype = {
|
|||
"Contact:Remove:Return:OK", "Contact:Remove:Return:KO",
|
||||
"Contact:Changed",
|
||||
"PermissionPromptHelper:AskPermission:OK",
|
||||
"Contacts:GetAll:Next",
|
||||
"Contacts:Revision"]);
|
||||
"Contacts:GetAll:Next", "Contacts:Revision",
|
||||
"Contacts:Count"]);
|
||||
},
|
||||
|
||||
// Called from DOMRequestIpcHelper
|
||||
|
|
|
@ -20,6 +20,6 @@ component {72a5ee28-81d8-4af8-90b3-ae935396cc66} ContactManager.js
|
|||
contract @mozilla.org/contact;1 {72a5ee28-81d8-4af8-90b3-ae935396cc66}
|
||||
category JavaScript-global-constructor mozContact @mozilla.org/contact;1
|
||||
|
||||
component {7bfb6481-f946-4254-afc5-d7fe9f5c45a3} ContactManager.js
|
||||
contract @mozilla.org/contactManager;1 {7bfb6481-f946-4254-afc5-d7fe9f5c45a3}
|
||||
component {8beb3a66-d70a-4111-b216-b8e995ad3aff} ContactManager.js
|
||||
contract @mozilla.org/contactManager;1 {8beb3a66-d70a-4111-b216-b8e995ad3aff}
|
||||
category JavaScript-navigator-property mozContacts @mozilla.org/contactManager;1
|
||||
|
|
|
@ -727,7 +727,16 @@ ContactDB.prototype = {
|
|||
this.newTxn("readonly", REVISION_STORE, function (txn, store) {
|
||||
store.get(REVISION_KEY).onsuccess = function (e) {
|
||||
aSuccessCb(e.target.result);
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
getCount: function CDB_getCount(aSuccessCb) {
|
||||
if (DEBUG) debug("getCount");
|
||||
this.newTxn("readonly", STORE_NAME, function (txn, store) {
|
||||
store.count().onsuccess = function (e) {
|
||||
aSuccessCb(e.target.result);
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -29,7 +29,8 @@ let ContactService = {
|
|||
this._messages = ["Contacts:Find", "Contacts:GetAll", "Contacts:GetAll:SendNow",
|
||||
"Contacts:Clear", "Contact:Save",
|
||||
"Contact:Remove", "Contacts:RegisterForMessages",
|
||||
"child-process-shutdown", "Contacts:GetRevision"];
|
||||
"child-process-shutdown", "Contacts:GetRevision",
|
||||
"Contacts:GetCount"];
|
||||
this._children = [];
|
||||
this._cursors = {};
|
||||
this._messages.forEach(function(msgName) {
|
||||
|
@ -184,6 +185,19 @@ let ContactService = {
|
|||
}
|
||||
);
|
||||
break;
|
||||
case "Contacts:GetCount":
|
||||
if (!this.assertPermission(aMessage, "contacts-read")) {
|
||||
return null;
|
||||
}
|
||||
this._db.getCount(
|
||||
function(count) {
|
||||
mm.sendAsyncMessage("Contacts:Count", {
|
||||
requestID: msg.requestID,
|
||||
count: count
|
||||
});
|
||||
}
|
||||
);
|
||||
break;
|
||||
case "Contacts:RegisterForMessages":
|
||||
if (!aMessage.target.assertPermission("contacts-read")) {
|
||||
return null;
|
||||
|
|
|
@ -137,6 +137,14 @@ function onFailure() {
|
|||
}
|
||||
|
||||
function checkStr(str1, str2, msg) {
|
||||
if (str1 ^ str2) {
|
||||
ok(false, "Expected both strings to be either present or absent");
|
||||
return;
|
||||
}
|
||||
is(str1, str2, msg);
|
||||
}
|
||||
|
||||
function checkStrArray(str1, str2, msg) {
|
||||
// comparing /[null(,null)+]/ and undefined should pass
|
||||
function nonNull(e) {
|
||||
return e != null;
|
||||
|
@ -150,88 +158,71 @@ function checkStr(str1, str2, msg) {
|
|||
}
|
||||
|
||||
function checkAddress(adr1, adr2) {
|
||||
checkStr(adr1.type, adr2.type, "Same type");
|
||||
checkStr(adr1.streetAddress, adr2.streetAddress, "Same streetAddress");
|
||||
checkStr(adr1.locality, adr2.locality, "Same locality");
|
||||
checkStr(adr1.region, adr2.region, "Same region");
|
||||
checkStr(adr1.postalCode, adr2.postalCode, "Same postalCode");
|
||||
checkStr(adr1.countryName, adr2.countryName, "Same countryName");
|
||||
if (adr1 ^ adr2) {
|
||||
ok(false, "Expected both adrs to be either present or absent");
|
||||
return;
|
||||
}
|
||||
dump("adr1: " + adr1 + ", adr2: " + adr2 + "\n");
|
||||
checkStrArray(adr1.type, adr2.type, "Same type");
|
||||
checkStrArray(adr1.streetAddress, adr2.streetAddress, "Same streetAddress");
|
||||
checkStrArray(adr1.locality, adr2.locality, "Same locality");
|
||||
checkStrArray(adr1.region, adr2.region, "Same region");
|
||||
checkStrArray(adr1.postalCode, adr2.postalCode, "Same postalCode");
|
||||
checkStrArray(adr1.countryName, adr2.countryName, "Same countryName");
|
||||
is(adr1.pref, adr2.pref, "Same pref");
|
||||
}
|
||||
|
||||
function checkTel(tel1, tel2) {
|
||||
checkStr(tel1.type, tel2.type, "Same type");
|
||||
checkStr(tel1.value, tel2.value, "Same value");
|
||||
checkStr(tel1.carrier, tel2.carrier, "Same carrier");
|
||||
if (tel1 ^ tel2) {
|
||||
ok(false, "Expected both tels to be either present or absent");
|
||||
return;
|
||||
}
|
||||
checkStrArray(tel1.type, tel2.type, "Same type");
|
||||
checkStrArray(tel1.value, tel2.value, "Same value");
|
||||
checkStrArray(tel1.carrier, tel2.carrier, "Same carrier");
|
||||
is(tel1.pref, tel2.pref, "Same pref");
|
||||
}
|
||||
|
||||
function checkField(field1, field2) {
|
||||
checkStr(field1.type, field2.type, "Same type");
|
||||
checkStr(field1.value, field2.value, "Same value");
|
||||
if (field1 ^ field2) {
|
||||
ok(false, "Expected both fields to be either present or absent");
|
||||
return;
|
||||
}
|
||||
checkStrArray(field1.type, field2.type, "Same type");
|
||||
checkStrArray(field1.value, field2.value, "Same value");
|
||||
is(field1.pref, field2.pref, "Same pref");
|
||||
}
|
||||
|
||||
function checkContacts(contact1, contact2) {
|
||||
checkStr(contact1.name, contact2.name, "Same name");
|
||||
checkStr(contact1.honorificPrefix, contact2.honorificPrefix, "Same honorificPrefix");
|
||||
checkStr(contact1.givenName, contact2.givenName, "Same givenName");
|
||||
checkStr(contact1.additionalName, contact2.additionalName, "Same additionalName");
|
||||
checkStr(contact1.familyName, contact2.familyName, "Same familyName");
|
||||
checkStr(contact1.honorificSuffix, contact2.honorificSuffix, "Same honorificSuffix");
|
||||
checkStr(contact1.nickname, contact2.nickname, "Same nickname");
|
||||
checkStr(contact1.category, contact2.category, "Same category");
|
||||
checkStr(contact1.org, contact2.org, "Same org");
|
||||
checkStr(contact1.jobTitle, contact2.jobTitle, "Same jobTitle");
|
||||
checkStrArray(contact1.name, contact2.name, "Same name");
|
||||
checkStrArray(contact1.honorificPrefix, contact2.honorificPrefix, "Same honorificPrefix");
|
||||
checkStrArray(contact1.givenName, contact2.givenName, "Same givenName");
|
||||
checkStrArray(contact1.additionalName, contact2.additionalName, "Same additionalName");
|
||||
checkStrArray(contact1.familyName, contact2.familyName, "Same familyName");
|
||||
checkStrArray(contact1.honorificSuffix, contact2.honorificSuffix, "Same honorificSuffix");
|
||||
checkStrArray(contact1.nickname, contact2.nickname, "Same nickname");
|
||||
checkStrArray(contact1.category, contact2.category, "Same category");
|
||||
checkStrArray(contact1.org, contact2.org, "Same org");
|
||||
checkStrArray(contact1.jobTitle, contact2.jobTitle, "Same jobTitle");
|
||||
is(contact1.bday ? contact1.bday.valueOf() : null, contact2.bday ? contact2.bday.valueOf() : null, "Same birthday");
|
||||
checkStr(contact1.note, contact2.note, "Same note");
|
||||
checkStrArray(contact1.note, contact2.note, "Same note");
|
||||
is(contact1.anniversary ? contact1.anniversary.valueOf() : null , contact2.anniversary ? contact2.anniversary.valueOf() : null, "Same anniversary");
|
||||
is(contact1.sex, contact2.sex, "Same sex");
|
||||
is(contact1.genderIdentity, contact2.genderIdentity, "Same genderIdentity");
|
||||
checkStr(contact1.sex, contact2.sex, "Same sex");
|
||||
checkStr(contact1.genderIdentity, contact2.genderIdentity, "Same genderIdentity");
|
||||
|
||||
for (var i in contact1.email) {
|
||||
if (contact1.email) {
|
||||
ok(contact2.email != null, "conatct2.email exists");
|
||||
}
|
||||
if (contact2.email) {
|
||||
ok(contact1.email != null, "conatct1.email exists");
|
||||
}
|
||||
checkField(contact1.email[i], contact2.email[i]);
|
||||
}
|
||||
for (var i in contact1.adr) {
|
||||
if (contact1.adr) {
|
||||
ok(contact2.adr != null, "conatct2.adr exists");
|
||||
}
|
||||
if (contact2.adr) {
|
||||
ok(contact1.adr != null, "conatct1.adr exists");
|
||||
}
|
||||
checkAddress(contact1.adr[i], contact2.adr[i]);
|
||||
}
|
||||
for (var i in contact1.tel) {
|
||||
if (contact1.tel) {
|
||||
ok(contact2.tel != null, "conatct2.tel exists");
|
||||
}
|
||||
if (contact2.tel) {
|
||||
ok(contact1.tel != null, "conatct1.tel exists");
|
||||
}
|
||||
checkTel(contact1.tel[i], contact2.tel[i]);
|
||||
}
|
||||
for (var i in contact1.url) {
|
||||
if (contact1.url) {
|
||||
ok(contact2.url != null, "conatct2.url exists");
|
||||
}
|
||||
if (contact2.url) {
|
||||
ok(contact1.url != null, "conatct1.url exists");
|
||||
}
|
||||
checkField(contact1.url[i], contact2.url[i]);
|
||||
}
|
||||
for (var i in contact1.impp) {
|
||||
if (contact1.impp) {
|
||||
ok(contact2.impp != null, "conatct2.impp exists");
|
||||
}
|
||||
if (contact2.impp) {
|
||||
ok(contact1.impp != null, "conatct1.impp exists");
|
||||
}
|
||||
checkField(contact1.impp[i], contact2.impp[i]);
|
||||
}
|
||||
}
|
||||
|
@ -250,6 +241,15 @@ function checkRevision(revision, msg, then) {
|
|||
revReq.onerror = onFailure;
|
||||
}
|
||||
|
||||
function checkCount(count, msg, then) {
|
||||
var request = navigator.mozContacts.getCount();
|
||||
request.onsuccess = function(e) {
|
||||
is(e.target.result, count, msg);
|
||||
then();
|
||||
};
|
||||
request.onerror = onFailure;
|
||||
}
|
||||
|
||||
var mozContacts = window.navigator.mozContacts;
|
||||
ok(mozContacts, "mozContacts exists");
|
||||
ok("mozContact" in window, "mozContact exists");
|
||||
|
@ -266,7 +266,9 @@ var steps = [
|
|||
req = mozContacts.clear();
|
||||
req.onsuccess = function () {
|
||||
ok(true, "Deleted the database");
|
||||
checkRevision(1, "Revision was incremented on clear", next);
|
||||
checkCount(0, "No contacts after clear", function() {
|
||||
checkRevision(1, "Revision was incremented on clear", next);
|
||||
});
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
});
|
||||
|
@ -288,7 +290,9 @@ var steps = [
|
|||
req.onsuccess = function () {
|
||||
ok(createResult1.id, "The contact now has an ID.");
|
||||
sample_id1 = createResult1.id;
|
||||
checkRevision(2, "Revision was incremented on save", next);
|
||||
checkCount(1, "1 contact after adding empty contact", function() {
|
||||
checkRevision(2, "Revision was incremented on save", next);
|
||||
});
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
|
@ -331,7 +335,7 @@ var steps = [
|
|||
req.onsuccess = function () {
|
||||
ok(createResult1.id, "The contact now has an ID.");
|
||||
sample_id1 = createResult1.id;
|
||||
checkContacts(properties1, createResult1);
|
||||
checkContacts(createResult1, properties1);
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
|
@ -498,7 +502,7 @@ var steps = [
|
|||
req.onsuccess = function () {
|
||||
ok(createResult1.id, "The contact now has an ID.");
|
||||
sample_id1 = createResult1.id;
|
||||
checkContacts(properties1, createResult1);
|
||||
checkContacts(createResult1, properties1);
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
|
@ -999,7 +1003,7 @@ var steps = [
|
|||
req.onsuccess = function () {
|
||||
ok(createResult1.id, "The contact now has an ID.");
|
||||
ok(createResult1.name == properties1.name, "Same Name");
|
||||
next();
|
||||
checkCount(20, "20 contacts in DB", next);
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
|
@ -1091,7 +1095,7 @@ var steps = [
|
|||
req = mozContacts.save(cloned);
|
||||
req.onsuccess = function () {
|
||||
ok(cloned.id, "The contact now has an ID.");
|
||||
ok(cloned.email.value == "new email!", "Same Email");
|
||||
ok(cloned.email[0].value == "new email!", "Same Email");
|
||||
ok(createResult1.email != cloned.email, "Clone has different email");
|
||||
ok(cloned.givenName == "Tom", "New Name");
|
||||
next();
|
||||
|
@ -1255,7 +1259,7 @@ var steps = [
|
|||
var req2 = mozContacts.find(options);
|
||||
req2.onsuccess = function() {
|
||||
is(req2.result.length, 1, "1 Entry");
|
||||
checkStr(req2.result.givenName, "customTest", "same name");
|
||||
checkStrArray(req2.result.givenName, "customTest", "same name");
|
||||
ok(req2.result.yyy === undefined, "custom property undefined");
|
||||
next();
|
||||
}
|
||||
|
@ -1430,6 +1434,23 @@ var steps = [
|
|||
}
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function() {
|
||||
ok(true, "Test setting array properties to scalar values")
|
||||
const DOMStrings = ["name","honorificPrefix","givenName","additionalName",
|
||||
"familyName", "honorificSuffix","nickname","category",
|
||||
"org","jobTitle","note"];
|
||||
const FIELDS = ["email","url","adr","tel","impp"];
|
||||
createResult1 = new mozContact();
|
||||
for (var prop of DOMStrings) {
|
||||
createResult1[prop] = "foo";
|
||||
ok(Array.isArray(createResult1[prop]), prop + " is array");
|
||||
}
|
||||
for (var prop of FIELDS) {
|
||||
createResult1[prop] = {type: "foo"};
|
||||
ok(Array.isArray(createResult1[prop]), prop + " is array");
|
||||
}
|
||||
next();
|
||||
},
|
||||
function () {
|
||||
ok(true, "all done!\n");
|
||||
clearTemps();
|
||||
|
@ -1445,11 +1466,11 @@ function next() {
|
|||
return;
|
||||
}
|
||||
try {
|
||||
steps[index]();
|
||||
var i = index++;
|
||||
steps[i]();
|
||||
} catch(ex) {
|
||||
ok(false, "Caught exception", ex);
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
|
|
@ -42,7 +42,7 @@ interface nsIURI;
|
|||
interface nsIDOMEventTarget;
|
||||
interface nsIRunnable;
|
||||
|
||||
[scriptable, uuid(dba80826-6251-4947-bf2a-a3873b9ec764)]
|
||||
[scriptable, uuid(a806d366-cc52-11e2-bc9a-ba3212c84021)]
|
||||
interface nsIDOMWindowUtils : nsISupports {
|
||||
|
||||
/**
|
||||
|
@ -658,6 +658,11 @@ interface nsIDOMWindowUtils : nsISupports {
|
|||
*/
|
||||
void getScrollbarSize(in boolean aFlushLayout, out long aWidth, out long aHeight);
|
||||
|
||||
/**
|
||||
* Returns the given element's bounds without flushing pending layout changes.
|
||||
*/
|
||||
nsIDOMClientRect getBoundsWithoutFlushing(in nsIDOMElement aElement);
|
||||
|
||||
/**
|
||||
* Returns the bounds of the window's currently loaded document. This will
|
||||
* generally be (0, 0, pageWidth, pageHeight) but in some cases (e.g. RTL
|
||||
|
|
|
@ -20,7 +20,7 @@ interface nsIDOMContact : nsIContactProperties
|
|||
void init(in nsIContactProperties properties); // Workaround BUG 723206
|
||||
};
|
||||
|
||||
[scriptable, uuid(e01ebfe7-e972-4e01-b04b-1d162dc74983)]
|
||||
[scriptable, uuid(8beb3a66-d70a-4111-b216-b8e995ad3aff)]
|
||||
interface nsIDOMContactManager : nsISupports
|
||||
{
|
||||
nsIDOMDOMRequest find(in nsIContactFindOptions options);
|
||||
|
@ -36,4 +36,6 @@ interface nsIDOMContactManager : nsISupports
|
|||
attribute nsIDOMEventListener oncontactchange;
|
||||
|
||||
nsIDOMDOMRequest getRevision();
|
||||
|
||||
nsIDOMDOMRequest getCount();
|
||||
};
|
||||
|
|
|
@ -1263,7 +1263,8 @@ MmsService.prototype = {
|
|||
this.retrieveMessage(url,
|
||||
this.retrieveMessageCallback.bind(this,
|
||||
wish,
|
||||
savableMessage));
|
||||
savableMessage),
|
||||
domMessage);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1294,8 +1295,7 @@ MmsService.prototype = {
|
|||
.saveReceivedMessage(savableMessage,
|
||||
this.saveReceivedMessageCallback.bind(this,
|
||||
retrievalMode,
|
||||
savableMessage),
|
||||
domMessage);
|
||||
savableMessage));
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
|
@ -1476,7 +1476,7 @@ MmsService.prototype = {
|
|||
retrieve: function retrieve(aMessageId, aRequest) {
|
||||
if (DEBUG) debug("Retrieving message with ID " + aMessageId);
|
||||
gMobileMessageDatabaseService.getMessageRecordById(aMessageId,
|
||||
(function notifyResult(aRv, aMessageRecord) {
|
||||
(function notifyResult(aRv, aMessageRecord, aDomMessage) {
|
||||
if (Ci.nsIMobileMessageCallback.SUCCESS_NO_ERROR != aRv) {
|
||||
if (DEBUG) debug("Function getMessageRecordById() return error.");
|
||||
aRequest.notifyGetMessageFailed(aRv);
|
||||
|
@ -1526,10 +1526,17 @@ MmsService.prototype = {
|
|||
let wish = aMessageRecord.headers["x-mms-delivery-report"];
|
||||
let responseNotify = function responseNotify(mmsStatus, retrievedMsg) {
|
||||
// If the mmsStatus is still MMS_PDU_STATUS_DEFERRED after retry,
|
||||
// we should not store it into database.
|
||||
// we should not store it into database and update its delivery
|
||||
// status to 'error'.
|
||||
if (MMS.MMS_PDU_STATUS_RETRIEVED !== mmsStatus) {
|
||||
if (DEBUG) debug("RetrieveMessage fail after retry.");
|
||||
aRequest.notifyGetMessageFailed(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
|
||||
gMobileMessageDatabaseService.setMessageDelivery(aMessageId,
|
||||
null,
|
||||
null,
|
||||
DELIVERY_STATUS_ERROR,
|
||||
function () {
|
||||
aRequest.notifyGetMessageFailed(Ci.nsIMobileMessageCallback.INTERNAL_ERROR);
|
||||
});
|
||||
return;
|
||||
}
|
||||
// In OMA-TS-MMS_ENC-V1_3, Table 5 in page 25. This header field
|
||||
|
@ -1585,7 +1592,9 @@ MmsService.prototype = {
|
|||
null,
|
||||
null,
|
||||
DELIVERY_STATUS_PENDING,
|
||||
this.retrieveMessage(url, responseNotify.bind(this)));
|
||||
this.retrieveMessage(url,
|
||||
responseNotify.bind(this),
|
||||
aDomMessage));
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
|
|
|
@ -43,6 +43,8 @@ EXTRA_COMPONENTS = \
|
|||
RadioInterfaceLayer.manifest \
|
||||
RadioInterfaceLayer.js \
|
||||
RILContentHelper.js \
|
||||
NetworkInterfaceListService.manifest \
|
||||
NetworkInterfaceListService.js \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const NETWORKLISTSERVICE_CONTRACTID =
|
||||
"@mozilla.org/network/interface-list-service;1";
|
||||
const NETWORKLISTSERVICE_CID =
|
||||
Components.ID("{3780be6e-7012-4e53-ade6-15212fb88a0d}");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
"@mozilla.org/childprocessmessagemanager;1",
|
||||
"nsISyncMessageSender");
|
||||
|
||||
function NetworkInterfaceListService () {
|
||||
}
|
||||
|
||||
NetworkInterfaceListService.prototype = {
|
||||
classID: NETWORKLISTSERVICE_CID,
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterfaceListService]),
|
||||
|
||||
getDataInterfaceList: function(aConditions) {
|
||||
return new NetworkInterfaceList(
|
||||
cpmm.sendSyncMessage(
|
||||
'NetworkInterfaceList:ListInterface',
|
||||
{
|
||||
excludeSupl: (aConditions &
|
||||
Ci.nsINetworkInterfaceListService.
|
||||
LIST_NOT_INCLUDE_SUPL_INTERFACES) != 0,
|
||||
excludeMms: (aConditions &
|
||||
Ci.nsINetworkInterfaceListService.
|
||||
LIST_NOT_INCLUDE_MMS_INTERFACES) != 0
|
||||
}
|
||||
)[0]);
|
||||
}
|
||||
};
|
||||
|
||||
function NetworkInterfaceList (aInterfaces) {
|
||||
this._interfaces = aInterfaces;
|
||||
}
|
||||
|
||||
NetworkInterfaceList.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkInterfaceList]),
|
||||
getNumberOfInterface: function() {
|
||||
return this._interfaces.length;
|
||||
},
|
||||
|
||||
getInterface: function(index) {
|
||||
if (!this._interfaces) {
|
||||
return null;
|
||||
}
|
||||
return this._interfaces[index];
|
||||
}
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkInterfaceListService]);
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
# Copyright 2012 Mozilla Foundation and Mozilla contributors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# NetworkInterfaceListService.js
|
||||
component {3780be6e-7012-4e53-ade6-15212fb88a0d} NetworkInterfaceListService.js
|
||||
contract @mozilla.org/network/interface-list-service;1 {3780be6e-7012-4e53-ade6-15212fb88a0d}
|
|
@ -22,6 +22,10 @@ const DEFAULT_PREFERRED_NETWORK_TYPE = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI;
|
|||
XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
|
||||
"@mozilla.org/settingsService;1",
|
||||
"nsISettingsService");
|
||||
XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
|
||||
return Cc["@mozilla.org/parentprocessmessagemanager;1"]
|
||||
.getService(Ci.nsIMessageBroadcaster);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
|
||||
"@mozilla.org/network/dns-service;1",
|
||||
|
@ -210,6 +214,8 @@ function NetworkManager() {
|
|||
debug("Error reading the 'tethering.wifi.enabled' setting: " + aErrorMessage);
|
||||
}
|
||||
});
|
||||
|
||||
ppmm.addMessageListener('NetworkInterfaceList:ListInterface', this);
|
||||
}
|
||||
NetworkManager.prototype = {
|
||||
classID: NETWORKMANAGER_CID,
|
||||
|
@ -320,6 +326,38 @@ NetworkManager.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
receiveMessage: function receiveMessage(aMsg) {
|
||||
switch (aMsg.name) {
|
||||
case "NetworkInterfaceList:ListInterface": {
|
||||
let excludeMms = aMsg.json.exculdeMms;
|
||||
let excludeSupl = aMsg.json.exculdeSupl;
|
||||
let interfaces = [];
|
||||
|
||||
for each (let i in this.networkInterfaces) {
|
||||
if ((i.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS && excludeMms) ||
|
||||
(i.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL && excludeSupl)) {
|
||||
continue;
|
||||
}
|
||||
interfaces.push({
|
||||
state: i.state,
|
||||
type: i.type,
|
||||
name: i.name,
|
||||
dhcp: i.dhcp,
|
||||
ip: i.ip,
|
||||
netmask: i.netmask,
|
||||
broadcast: i.broadcast,
|
||||
gateway: i.gateway,
|
||||
dns1: i.dns1,
|
||||
dns2: i.dns2,
|
||||
httpProxyHost: i.httpProxyHost,
|
||||
httpProxyPort: i.httpProxyPort
|
||||
});
|
||||
}
|
||||
return interfaces;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// nsINetworkManager
|
||||
|
||||
registerNetworkInterface: function registerNetworkInterface(network) {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
XPIDL_SOURCES += [
|
||||
'nsIAudioManager.idl',
|
||||
'nsINavigatorAudioChannelManager.idl',
|
||||
'nsINetworkInterfaceListService.idl',
|
||||
'nsINetworkManager.idl',
|
||||
'nsIRadioInterfaceLayer.idl',
|
||||
'nsISystemWorkerManager.idl',
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/* 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 "nsINetworkManager.idl"
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(b44d74db-c9d6-41dd-98ae-a56918d6e6ad)]
|
||||
interface nsINetworkInterfaceList : nsISupports
|
||||
{
|
||||
/**
|
||||
* Number of the network interfaces that is available.
|
||||
*/
|
||||
long getNumberOfInterface();
|
||||
|
||||
/**
|
||||
* Get the i-th interface from the list.
|
||||
* @param interfaceIndex index of interface, from 0 to number of interface - 1.
|
||||
*/
|
||||
nsINetworkInterface getInterface(in long interfaceIndex);
|
||||
};
|
||||
|
||||
[scriptable, uuid(5be50bcb-bfe9-4742-b7e6-3e9bb4835369)]
|
||||
interface nsINetworkInterfaceListService : nsISupports
|
||||
{
|
||||
const long LIST_NOT_INCLUDE_MMS_INTERFACES = 1;
|
||||
const long LIST_NOT_INCLUDE_SUPL_INTERFACES = 2;
|
||||
|
||||
/**
|
||||
* Obtain a list of network interfaces that satisfy the specified condition.
|
||||
* @param condition flags that specify the interfaces to be returned. This
|
||||
* can be OR combination of LIST_* flags, or zero to make all available
|
||||
* interfaces returned.
|
||||
*/
|
||||
nsINetworkInterfaceList getDataInterfaceList(in long condition);
|
||||
};
|
|
@ -0,0 +1,129 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
extern "C" {
|
||||
#include <arpa/inet.h>
|
||||
#include "r_types.h"
|
||||
#include "stun.h"
|
||||
#include "addrs.h"
|
||||
}
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "nsINetworkManager.h"
|
||||
#include "nsINetworkInterfaceListService.h"
|
||||
#include "runnable_utils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
namespace {
|
||||
struct NetworkInterface {
|
||||
struct sockaddr_in addr;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
nsresult
|
||||
GetInterfaces(std::vector<NetworkInterface>* aInterfaces)
|
||||
{
|
||||
MOZ_ASSERT(aInterfaces);
|
||||
|
||||
// Obtain network interfaces from network manager.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetworkInterfaceListService> listService =
|
||||
do_GetService("@mozilla.org/network/interface-list-service;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
int32_t flags =
|
||||
nsINetworkInterfaceListService::LIST_NOT_INCLUDE_SUPL_INTERFACES |
|
||||
nsINetworkInterfaceListService::LIST_NOT_INCLUDE_MMS_INTERFACES;
|
||||
nsCOMPtr<nsINetworkInterfaceList> networkList;
|
||||
NS_ENSURE_SUCCESS(listService->GetDataInterfaceList(flags,
|
||||
getter_AddRefs(networkList)),
|
||||
NS_ERROR_FAILURE);
|
||||
|
||||
// Translate nsINetworkInterfaceList to NetworkInterface.
|
||||
int32_t listLength;
|
||||
NS_ENSURE_SUCCESS(networkList->GetNumberOfInterface(&listLength),
|
||||
NS_ERROR_FAILURE);
|
||||
aInterfaces->clear();
|
||||
|
||||
nsAutoString ip;
|
||||
nsAutoString ifaceName;
|
||||
for (int32_t i = 0; i < listLength; i++) {
|
||||
nsCOMPtr<nsINetworkInterface> iface;
|
||||
if (NS_FAILED(networkList->GetInterface(i, getter_AddRefs(iface)))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NetworkInterface interface;
|
||||
memset(&(interface.addr), 0, sizeof(interface.addr));
|
||||
interface.addr.sin_family = AF_INET;
|
||||
if (NS_FAILED(iface->GetIp(ip))) {
|
||||
continue;
|
||||
}
|
||||
if (inet_pton(AF_INET, NS_ConvertUTF16toUTF8(ip).get(),
|
||||
&(interface.addr.sin_addr.s_addr)) != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (NS_FAILED(iface->GetName(ifaceName))) {
|
||||
continue;
|
||||
}
|
||||
interface.name = NS_ConvertUTF16toUTF8(ifaceName).get();
|
||||
|
||||
aInterfaces->push_back(interface);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
int
|
||||
nr_stun_get_addrs(nr_transport_addr aAddrs[], int aMaxAddrs,
|
||||
int aDropLoopback, int* aCount)
|
||||
{
|
||||
nsresult rv;
|
||||
int r;
|
||||
|
||||
// Get network interface list.
|
||||
std::vector<NetworkInterface> interfaces;
|
||||
if (NS_FAILED(NS_DispatchToMainThread(
|
||||
mozilla::WrapRunnableNMRet(&GetInterfaces, &interfaces, &rv),
|
||||
NS_DISPATCH_SYNC))) {
|
||||
return R_FAILED;
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return R_FAILED;
|
||||
}
|
||||
|
||||
// Translate to nr_transport_addr.
|
||||
int32_t n = 0;
|
||||
size_t num_interface = std::min(interfaces.size(), (size_t)aMaxAddrs);
|
||||
for (size_t i = 0; i < num_interface; ++i) {
|
||||
NetworkInterface &interface = interfaces[i];
|
||||
if (nr_sockaddr_to_transport_addr((sockaddr*)&(interface.addr),
|
||||
sizeof(struct sockaddr_in),
|
||||
IPPROTO_UDP, 0, &(aAddrs[n]))) {
|
||||
r_log(NR_LOG_STUN, LOG_WARNING, "Problem transforming address");
|
||||
return R_FAILED;
|
||||
}
|
||||
strlcpy(aAddrs[n].ifname, interface.name.c_str(), sizeof(aAddrs[n].ifname));
|
||||
n++;
|
||||
}
|
||||
|
||||
*aCount = n;
|
||||
r = nr_stun_remove_duplicate_addrs(aAddrs, aDropLoopback, aCount);
|
||||
if (r != 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
for (int i = 0; i < *aCount; ++i) {
|
||||
r_log(NR_LOG_STUN, LOG_DEBUG, "Address %d: %s on %s", i,
|
||||
aAddrs[i].as_string, aAddrs[i].ifname);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -79,5 +79,11 @@ MTRANSPORT_LCPPSRCS = \
|
|||
transportlayerprsock.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_B2G_RIL
|
||||
MTRANSPORT_LCPPSRCS += \
|
||||
gonk_addrs.cpp \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
MTRANSPORT_CPPSRCS = $(addprefix $(topsrcdir)/media/mtransport/, $(MTRANSPORT_LCPPSRCS))
|
||||
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
#
|
||||
#
|
||||
{
|
||||
'variables' : {
|
||||
'build_with_gonk%': 0,
|
||||
},
|
||||
'targets' : [
|
||||
{
|
||||
'target_name' : 'nicer',
|
||||
|
@ -213,6 +216,12 @@
|
|||
'NO_REG_RPC',
|
||||
],
|
||||
}],
|
||||
# Gonk has its own nr_stun_get_addrs implementation.
|
||||
['build_with_gonk==1', {
|
||||
'defines': [
|
||||
"USE_PLATFORM_NR_STUN_GET_ADDRS",
|
||||
]
|
||||
}]
|
||||
],
|
||||
}]
|
||||
}
|
||||
|
|
|
@ -687,6 +687,8 @@ nr_stun_remove_duplicate_addrs(nr_transport_addr addrs[], int remove_loopback, i
|
|||
return _status;
|
||||
}
|
||||
|
||||
#ifndef USE_PLATFORM_NR_STUN_GET_ADDRS
|
||||
|
||||
int
|
||||
nr_stun_get_addrs(nr_transport_addr addrs[], int maxaddrs, int drop_loopback, int *count)
|
||||
{
|
||||
|
@ -712,3 +714,4 @@ nr_stun_get_addrs(nr_transport_addr addrs[], int maxaddrs, int drop_loopback, in
|
|||
return _status;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче