зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound.
This commit is contained in:
Коммит
a6b0347165
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"revision": "d717e2e751a6bb1303499bde6be9dbd88b275e30",
|
||||
"revision": "846f8e7089361d42e1362ab591561f94d3bd31e9",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -228,6 +228,12 @@ let StyleSheet = function(form, debuggee) {
|
|||
this._client.addListener("propertyChange", this._onPropertyChange);
|
||||
this._client.addListener("styleApplied", this._onStyleApplied);
|
||||
|
||||
// Backwards compatibility
|
||||
this._client.addListener("sourceLoad-" + this._actor, this._onSourceLoad);
|
||||
this._client.addListener("propertyChange-" + this._actor, this._onPropertyChange);
|
||||
this._client.addListener("styleApplied-" + this._actor, this._onStyleApplied);
|
||||
|
||||
|
||||
// set initial property values
|
||||
for (let attr in form) {
|
||||
this[attr] = form[attr];
|
||||
|
@ -324,5 +330,9 @@ StyleSheet.prototype = {
|
|||
this._client.removeListener("sourceLoad", this._onSourceLoad);
|
||||
this._client.removeListener("propertyChange", this._onPropertyChange);
|
||||
this._client.removeListener("styleApplied", this._onStyleApplied);
|
||||
|
||||
this._client.removeListener("sourceLoad-" + this._actor, this._onSourceLoad);
|
||||
this._client.removeListener("propertyChange-" + this._actor, this._onPropertyChange);
|
||||
this._client.removeListener("styleApplied-" + this._actor, this._onStyleApplied);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1270,6 +1270,7 @@ BluetoothHfpManager::GetNumberOfCalls(uint16_t aState)
|
|||
void
|
||||
BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
|
||||
uint16_t aCallState,
|
||||
const nsAString& aError,
|
||||
const nsAString& aNumber,
|
||||
const bool aIsOutgoing,
|
||||
bool aSend)
|
||||
|
@ -1391,7 +1392,6 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
|
|||
case nsITelephonyProvider::CALL_STATE_DISCONNECTED:
|
||||
switch (prevCallState) {
|
||||
case nsITelephonyProvider::CALL_STATE_INCOMING:
|
||||
case nsITelephonyProvider::CALL_STATE_BUSY:
|
||||
// Incoming call, no break
|
||||
sStopSendingRingFlag = true;
|
||||
case nsITelephonyProvider::CALL_STATE_DIALING:
|
||||
|
@ -1424,7 +1424,7 @@ BluetoothHfpManager::HandleCallStateChanged(uint32_t aCallIndex,
|
|||
GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_DISCONNECTED)) {
|
||||
// In order to let user hear busy tone via connected Bluetooth headset,
|
||||
// we postpone the timing of dropping SCO.
|
||||
if (prevCallState != nsITelephonyProvider::CALL_STATE_BUSY) {
|
||||
if (!(aError.Equals(NS_LITERAL_STRING("BusyError")))) {
|
||||
DisconnectSco();
|
||||
} else {
|
||||
// Close Sco later since Dialer is still playing busy tone via HF.
|
||||
|
|
|
@ -86,8 +86,8 @@ public:
|
|||
* @param aSend A boolean indicates whether we need to notify headset or not
|
||||
*/
|
||||
void HandleCallStateChanged(uint32_t aCallIndex, uint16_t aCallState,
|
||||
const nsAString& aNumber, const bool aIsOutgoing,
|
||||
bool aSend);
|
||||
const nsAString& aError, const nsAString& aNumber,
|
||||
const bool aIsOutgoing, bool aSend);
|
||||
|
||||
bool IsConnected();
|
||||
bool IsScoConnected();
|
||||
|
|
|
@ -35,7 +35,7 @@ TelephonyListener::CallStateChanged(uint32_t aCallIndex,
|
|||
bool aIsEmergency)
|
||||
{
|
||||
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
|
||||
hfp->HandleCallStateChanged(aCallIndex, aCallState, aNumber,
|
||||
hfp->HandleCallStateChanged(aCallIndex, aCallState, EmptyString(), aNumber,
|
||||
aIsOutgoing, true);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -57,7 +57,7 @@ TelephonyListener::EnumerateCallState(uint32_t aCallIndex,
|
|||
bool* aResult)
|
||||
{
|
||||
BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
|
||||
hfp->HandleCallStateChanged(aCallIndex, aCallState, aNumber,
|
||||
hfp->HandleCallStateChanged(aCallIndex, aCallState, EmptyString(), aNumber,
|
||||
aIsOutgoing, false);
|
||||
*aResult = true;
|
||||
return NS_OK;
|
||||
|
@ -77,7 +77,7 @@ TelephonyListener::NotifyError(int32_t aCallIndex,
|
|||
// via setting CALL_STATE_DISCONNECTED
|
||||
hfp->HandleCallStateChanged(aCallIndex,
|
||||
nsITelephonyProvider::CALL_STATE_DISCONNECTED,
|
||||
EmptyString(), false, true);
|
||||
aError, EmptyString(), false, true);
|
||||
NS_WARNING("Reset the call state due to call transition ends abnormally");
|
||||
}
|
||||
|
||||
|
|
|
@ -640,6 +640,8 @@ ContactManager.prototype = {
|
|||
case "Contact:Save:Return:KO":
|
||||
case "Contact:Remove:Return:KO":
|
||||
case "Contacts:Clear:Return:KO":
|
||||
case "Contacts:GetRevision:Return:KO":
|
||||
case "Contacts:Count:Return:KO":
|
||||
req = this.getRequest(msg.requestID);
|
||||
if (req)
|
||||
Services.DOMRequest.fireError(req.request, msg.errorMsg);
|
||||
|
|
|
@ -93,284 +93,8 @@ ContactDB.prototype = {
|
|||
_dispatcher: {},
|
||||
|
||||
upgradeSchema: function upgradeSchema(aTransaction, aDb, aOldVersion, aNewVersion) {
|
||||
if (DEBUG) debug("upgrade schema from: " + aOldVersion + " to " + aNewVersion + " called!");
|
||||
let db = aDb;
|
||||
let objectStore;
|
||||
for (let currVersion = aOldVersion; currVersion < aNewVersion; currVersion++) {
|
||||
if (currVersion == 0) {
|
||||
/**
|
||||
* Create the initial database schema.
|
||||
*
|
||||
* The schema of records stored is as follows:
|
||||
*
|
||||
* {id: "...", // UUID
|
||||
* published: Date(...), // First published date.
|
||||
* updated: Date(...), // Last updated date.
|
||||
* properties: {...} // Object holding the ContactProperties
|
||||
* }
|
||||
*/
|
||||
if (DEBUG) debug("create schema");
|
||||
objectStore = db.createObjectStore(STORE_NAME, {keyPath: "id"});
|
||||
|
||||
// Properties indexes
|
||||
objectStore.createIndex("familyName", "properties.familyName", { multiEntry: true });
|
||||
objectStore.createIndex("givenName", "properties.givenName", { multiEntry: true });
|
||||
|
||||
objectStore.createIndex("familyNameLowerCase", "search.familyName", { multiEntry: true });
|
||||
objectStore.createIndex("givenNameLowerCase", "search.givenName", { multiEntry: true });
|
||||
objectStore.createIndex("telLowerCase", "search.tel", { multiEntry: true });
|
||||
objectStore.createIndex("emailLowerCase", "search.email", { multiEntry: true });
|
||||
} else if (currVersion == 1) {
|
||||
if (DEBUG) debug("upgrade 1");
|
||||
|
||||
// Create a new scheme for the tel field. We move from an array of tel-numbers to an array of
|
||||
// ContactTelephone.
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
// Delete old tel index.
|
||||
if (objectStore.indexNames.contains("tel")) {
|
||||
objectStore.deleteIndex("tel");
|
||||
}
|
||||
|
||||
// Upgrade existing tel field in the DB.
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (DEBUG) debug("upgrade tel1: " + JSON.stringify(cursor.value));
|
||||
for (let number in cursor.value.properties.tel) {
|
||||
cursor.value.properties.tel[number] = {number: number};
|
||||
}
|
||||
cursor.update(cursor.value);
|
||||
if (DEBUG) debug("upgrade tel2: " + JSON.stringify(cursor.value));
|
||||
cursor.continue();
|
||||
}
|
||||
};
|
||||
|
||||
// Create new searchable indexes.
|
||||
objectStore.createIndex("tel", "search.tel", { multiEntry: true });
|
||||
objectStore.createIndex("category", "properties.category", { multiEntry: true });
|
||||
} else if (currVersion == 2) {
|
||||
if (DEBUG) debug("upgrade 2");
|
||||
// Create a new scheme for the email field. We move from an array of emailaddresses to an array of
|
||||
// ContactEmail.
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
|
||||
// Delete old email index.
|
||||
if (objectStore.indexNames.contains("email")) {
|
||||
objectStore.deleteIndex("email");
|
||||
}
|
||||
|
||||
// Upgrade existing email field in the DB.
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (cursor.value.properties.email) {
|
||||
if (DEBUG) debug("upgrade email1: " + JSON.stringify(cursor.value));
|
||||
cursor.value.properties.email =
|
||||
cursor.value.properties.email.map(function(address) { return { address: address }; });
|
||||
cursor.update(cursor.value);
|
||||
if (DEBUG) debug("upgrade email2: " + JSON.stringify(cursor.value));
|
||||
}
|
||||
cursor.continue();
|
||||
}
|
||||
};
|
||||
|
||||
// Create new searchable indexes.
|
||||
objectStore.createIndex("email", "search.email", { multiEntry: true });
|
||||
} else if (currVersion == 3) {
|
||||
if (DEBUG) debug("upgrade 3");
|
||||
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
|
||||
// Upgrade existing impp field in the DB.
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (cursor.value.properties.impp) {
|
||||
if (DEBUG) debug("upgrade impp1: " + JSON.stringify(cursor.value));
|
||||
cursor.value.properties.impp =
|
||||
cursor.value.properties.impp.map(function(value) { return { value: value }; });
|
||||
cursor.update(cursor.value);
|
||||
if (DEBUG) debug("upgrade impp2: " + JSON.stringify(cursor.value));
|
||||
}
|
||||
cursor.continue();
|
||||
}
|
||||
};
|
||||
// Upgrade existing url field in the DB.
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (cursor.value.properties.url) {
|
||||
if (DEBUG) debug("upgrade url1: " + JSON.stringify(cursor.value));
|
||||
cursor.value.properties.url =
|
||||
cursor.value.properties.url.map(function(value) { return { value: value }; });
|
||||
cursor.update(cursor.value);
|
||||
if (DEBUG) debug("upgrade impp2: " + JSON.stringify(cursor.value));
|
||||
}
|
||||
cursor.continue();
|
||||
}
|
||||
};
|
||||
} else if (currVersion == 4) {
|
||||
if (DEBUG) debug("Add international phone numbers upgrade");
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (cursor.value.properties.tel) {
|
||||
if (DEBUG) debug("upgrade : " + JSON.stringify(cursor.value));
|
||||
cursor.value.properties.tel.forEach(
|
||||
function(duple) {
|
||||
let parsedNumber = PhoneNumberUtils.parse(duple.value.toString());
|
||||
if (parsedNumber) {
|
||||
if (DEBUG) {
|
||||
debug("InternationalFormat: " + parsedNumber.internationalFormat);
|
||||
debug("InternationalNumber: " + parsedNumber.internationalNumber);
|
||||
debug("NationalNumber: " + parsedNumber.nationalNumber);
|
||||
debug("NationalFormat: " + parsedNumber.nationalFormat);
|
||||
}
|
||||
if (duple.value.toString() !== parsedNumber.internationalNumber) {
|
||||
cursor.value.search.tel.push(parsedNumber.internationalNumber);
|
||||
}
|
||||
} else {
|
||||
dump("Warning: No international number found for " + duple.value + "\n");
|
||||
}
|
||||
}
|
||||
)
|
||||
cursor.update(cursor.value);
|
||||
}
|
||||
if (DEBUG) debug("upgrade2 : " + JSON.stringify(cursor.value));
|
||||
cursor.continue();
|
||||
}
|
||||
};
|
||||
} else if (currVersion == 5) {
|
||||
if (DEBUG) debug("Add index for equals tel searches");
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
|
||||
// Delete old tel index (not on the right field).
|
||||
if (objectStore.indexNames.contains("tel")) {
|
||||
objectStore.deleteIndex("tel");
|
||||
}
|
||||
|
||||
// Create new index for "equals" searches
|
||||
objectStore.createIndex("tel", "search.exactTel", { multiEntry: true });
|
||||
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (cursor.value.properties.tel) {
|
||||
if (DEBUG) debug("upgrade : " + JSON.stringify(cursor.value));
|
||||
cursor.value.properties.tel.forEach(
|
||||
function(duple) {
|
||||
let number = duple.value.toString();
|
||||
let parsedNumber = PhoneNumberUtils.parse(number);
|
||||
|
||||
cursor.value.search.exactTel = [number];
|
||||
if (parsedNumber &&
|
||||
parsedNumber.internationalNumber &&
|
||||
number !== parsedNumber.internationalNumber) {
|
||||
cursor.value.search.exactTel.push(parsedNumber.internationalNumber);
|
||||
}
|
||||
}
|
||||
)
|
||||
cursor.update(cursor.value);
|
||||
}
|
||||
if (DEBUG) debug("upgrade : " + JSON.stringify(cursor.value));
|
||||
cursor.continue();
|
||||
}
|
||||
};
|
||||
} else if (currVersion == 6) {
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
let names = objectStore.indexNames;
|
||||
let blackList = ["tel", "familyName", "givenName", "familyNameLowerCase",
|
||||
"givenNameLowerCase", "telLowerCase", "category", "email",
|
||||
"emailLowerCase"];
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
if (blackList.indexOf(names[i]) < 0) {
|
||||
objectStore.deleteIndex(names[i]);
|
||||
}
|
||||
}
|
||||
} else if (currVersion == 7) {
|
||||
if (DEBUG) debug("Adding object store for cached searches");
|
||||
db.createObjectStore(SAVED_GETALL_STORE_NAME);
|
||||
} else if (currVersion == 8) {
|
||||
if (DEBUG) debug("Make exactTel only contain the value entered by the user");
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (cursor.value.properties.tel) {
|
||||
cursor.value.search.exactTel = [];
|
||||
cursor.value.properties.tel.forEach(
|
||||
function(tel) {
|
||||
let normalized = PhoneNumberUtils.normalize(tel.value.toString());
|
||||
cursor.value.search.exactTel.push(normalized);
|
||||
}
|
||||
);
|
||||
cursor.update(cursor.value);
|
||||
}
|
||||
cursor.continue();
|
||||
}
|
||||
};
|
||||
} else if (currVersion == 9) {
|
||||
// no-op, see https://bugzilla.mozilla.org/show_bug.cgi?id=883770#c16
|
||||
} else if (currVersion == 10) {
|
||||
if (DEBUG) debug("Adding object store for database revision");
|
||||
db.createObjectStore(REVISION_STORE).put(0, REVISION_KEY);
|
||||
} else if (currVersion == 11) {
|
||||
if (DEBUG) debug("Add a telMatch index with national and international numbers");
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
if (!objectStore.indexNames.contains("telMatch")) {
|
||||
objectStore.createIndex("telMatch", "search.parsedTel", {multiEntry: true});
|
||||
}
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (cursor.value.properties.tel) {
|
||||
cursor.value.search.parsedTel = [];
|
||||
cursor.value.properties.tel.forEach(
|
||||
function(tel) {
|
||||
let parsed = PhoneNumberUtils.parse(tel.value.toString());
|
||||
if (parsed) {
|
||||
cursor.value.search.parsedTel.push(parsed.nationalNumber);
|
||||
cursor.value.search.parsedTel.push(PhoneNumberUtils.normalize(parsed.nationalFormat));
|
||||
cursor.value.search.parsedTel.push(parsed.internationalNumber);
|
||||
cursor.value.search.parsedTel.push(PhoneNumberUtils.normalize(parsed.internationalFormat));
|
||||
}
|
||||
cursor.value.search.parsedTel.push(PhoneNumberUtils.normalize(tel.value.toString()));
|
||||
}
|
||||
);
|
||||
cursor.update(cursor.value);
|
||||
}
|
||||
cursor.continue();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Increment the DB revision on future schema changes as well
|
||||
if (currVersion > 11) {
|
||||
this.incrementRevision(aTransaction);
|
||||
}
|
||||
}
|
||||
|
||||
// Add default contacts
|
||||
if (aOldVersion == 0) {
|
||||
function loadInitialContacts() {
|
||||
// Add default contacts
|
||||
let jsm = {};
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm", jsm);
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm", jsm);
|
||||
|
@ -419,6 +143,334 @@ ContactDB.prototype = {
|
|||
objectStore.put(contact);
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) debug("upgrade schema from: " + aOldVersion + " to " + aNewVersion + " called!");
|
||||
let db = aDb;
|
||||
let objectStore;
|
||||
|
||||
let steps = [
|
||||
function upgrade0to1() {
|
||||
/**
|
||||
* Create the initial database schema.
|
||||
*
|
||||
* The schema of records stored is as follows:
|
||||
*
|
||||
* {id: "...", // UUID
|
||||
* published: Date(...), // First published date.
|
||||
* updated: Date(...), // Last updated date.
|
||||
* properties: {...} // Object holding the ContactProperties
|
||||
* }
|
||||
*/
|
||||
if (DEBUG) debug("create schema");
|
||||
objectStore = db.createObjectStore(STORE_NAME, {keyPath: "id"});
|
||||
|
||||
// Properties indexes
|
||||
objectStore.createIndex("familyName", "properties.familyName", { multiEntry: true });
|
||||
objectStore.createIndex("givenName", "properties.givenName", { multiEntry: true });
|
||||
|
||||
objectStore.createIndex("familyNameLowerCase", "search.familyName", { multiEntry: true });
|
||||
objectStore.createIndex("givenNameLowerCase", "search.givenName", { multiEntry: true });
|
||||
objectStore.createIndex("telLowerCase", "search.tel", { multiEntry: true });
|
||||
objectStore.createIndex("emailLowerCase", "search.email", { multiEntry: true });
|
||||
next();
|
||||
},
|
||||
function upgrade1to2() {
|
||||
if (DEBUG) debug("upgrade 1");
|
||||
|
||||
// Create a new scheme for the tel field. We move from an array of tel-numbers to an array of
|
||||
// ContactTelephone.
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
// Delete old tel index.
|
||||
if (objectStore.indexNames.contains("tel")) {
|
||||
objectStore.deleteIndex("tel");
|
||||
}
|
||||
|
||||
// Upgrade existing tel field in the DB.
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (DEBUG) debug("upgrade tel1: " + JSON.stringify(cursor.value));
|
||||
for (let number in cursor.value.properties.tel) {
|
||||
cursor.value.properties.tel[number] = {number: number};
|
||||
}
|
||||
cursor.update(cursor.value);
|
||||
if (DEBUG) debug("upgrade tel2: " + JSON.stringify(cursor.value));
|
||||
cursor.continue();
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
||||
// Create new searchable indexes.
|
||||
objectStore.createIndex("tel", "search.tel", { multiEntry: true });
|
||||
objectStore.createIndex("category", "properties.category", { multiEntry: true });
|
||||
},
|
||||
function upgrade2to3() {
|
||||
if (DEBUG) debug("upgrade 2");
|
||||
// Create a new scheme for the email field. We move from an array of emailaddresses to an array of
|
||||
// ContactEmail.
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
|
||||
// Delete old email index.
|
||||
if (objectStore.indexNames.contains("email")) {
|
||||
objectStore.deleteIndex("email");
|
||||
}
|
||||
|
||||
// Upgrade existing email field in the DB.
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (cursor.value.properties.email) {
|
||||
if (DEBUG) debug("upgrade email1: " + JSON.stringify(cursor.value));
|
||||
cursor.value.properties.email =
|
||||
cursor.value.properties.email.map(function(address) { return { address: address }; });
|
||||
cursor.update(cursor.value);
|
||||
if (DEBUG) debug("upgrade email2: " + JSON.stringify(cursor.value));
|
||||
}
|
||||
cursor.continue();
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
||||
// Create new searchable indexes.
|
||||
objectStore.createIndex("email", "search.email", { multiEntry: true });
|
||||
},
|
||||
function upgrade3to4() {
|
||||
if (DEBUG) debug("upgrade 3");
|
||||
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
|
||||
// Upgrade existing impp field in the DB.
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (cursor.value.properties.impp) {
|
||||
if (DEBUG) debug("upgrade impp1: " + JSON.stringify(cursor.value));
|
||||
cursor.value.properties.impp =
|
||||
cursor.value.properties.impp.map(function(value) { return { value: value }; });
|
||||
cursor.update(cursor.value);
|
||||
if (DEBUG) debug("upgrade impp2: " + JSON.stringify(cursor.value));
|
||||
}
|
||||
cursor.continue();
|
||||
}
|
||||
};
|
||||
// Upgrade existing url field in the DB.
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (cursor.value.properties.url) {
|
||||
if (DEBUG) debug("upgrade url1: " + JSON.stringify(cursor.value));
|
||||
cursor.value.properties.url =
|
||||
cursor.value.properties.url.map(function(value) { return { value: value }; });
|
||||
cursor.update(cursor.value);
|
||||
if (DEBUG) debug("upgrade impp2: " + JSON.stringify(cursor.value));
|
||||
}
|
||||
cursor.continue();
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
};
|
||||
},
|
||||
function upgrade4to5() {
|
||||
if (DEBUG) debug("Add international phone numbers upgrade");
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (cursor.value.properties.tel) {
|
||||
if (DEBUG) debug("upgrade : " + JSON.stringify(cursor.value));
|
||||
cursor.value.properties.tel.forEach(
|
||||
function(duple) {
|
||||
let parsedNumber = PhoneNumberUtils.parse(duple.value.toString());
|
||||
if (parsedNumber) {
|
||||
if (DEBUG) {
|
||||
debug("InternationalFormat: " + parsedNumber.internationalFormat);
|
||||
debug("InternationalNumber: " + parsedNumber.internationalNumber);
|
||||
debug("NationalNumber: " + parsedNumber.nationalNumber);
|
||||
debug("NationalFormat: " + parsedNumber.nationalFormat);
|
||||
}
|
||||
if (duple.value.toString() !== parsedNumber.internationalNumber) {
|
||||
cursor.value.search.tel.push(parsedNumber.internationalNumber);
|
||||
}
|
||||
} else {
|
||||
dump("Warning: No international number found for " + duple.value + "\n");
|
||||
}
|
||||
}
|
||||
)
|
||||
cursor.update(cursor.value);
|
||||
}
|
||||
if (DEBUG) debug("upgrade2 : " + JSON.stringify(cursor.value));
|
||||
cursor.continue();
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
};
|
||||
},
|
||||
function upgrade5to6() {
|
||||
if (DEBUG) debug("Add index for equals tel searches");
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
|
||||
// Delete old tel index (not on the right field).
|
||||
if (objectStore.indexNames.contains("tel")) {
|
||||
objectStore.deleteIndex("tel");
|
||||
}
|
||||
|
||||
// Create new index for "equals" searches
|
||||
objectStore.createIndex("tel", "search.exactTel", { multiEntry: true });
|
||||
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (cursor.value.properties.tel) {
|
||||
if (DEBUG) debug("upgrade : " + JSON.stringify(cursor.value));
|
||||
cursor.value.properties.tel.forEach(
|
||||
function(duple) {
|
||||
let number = duple.value.toString();
|
||||
let parsedNumber = PhoneNumberUtils.parse(number);
|
||||
|
||||
cursor.value.search.exactTel = [number];
|
||||
if (parsedNumber &&
|
||||
parsedNumber.internationalNumber &&
|
||||
number !== parsedNumber.internationalNumber) {
|
||||
cursor.value.search.exactTel.push(parsedNumber.internationalNumber);
|
||||
}
|
||||
}
|
||||
)
|
||||
cursor.update(cursor.value);
|
||||
}
|
||||
if (DEBUG) debug("upgrade : " + JSON.stringify(cursor.value));
|
||||
cursor.continue();
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
};
|
||||
},
|
||||
function upgrade6to7() {
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
let names = objectStore.indexNames;
|
||||
let blackList = ["tel", "familyName", "givenName", "familyNameLowerCase",
|
||||
"givenNameLowerCase", "telLowerCase", "category", "email",
|
||||
"emailLowerCase"];
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
if (blackList.indexOf(names[i]) < 0) {
|
||||
objectStore.deleteIndex(names[i]);
|
||||
}
|
||||
}
|
||||
next();
|
||||
},
|
||||
function upgrade7to8() {
|
||||
if (DEBUG) debug("Adding object store for cached searches");
|
||||
db.createObjectStore(SAVED_GETALL_STORE_NAME);
|
||||
next();
|
||||
},
|
||||
function upgrade8to9() {
|
||||
if (DEBUG) debug("Make exactTel only contain the value entered by the user");
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (cursor.value.properties.tel) {
|
||||
cursor.value.search.exactTel = [];
|
||||
cursor.value.properties.tel.forEach(
|
||||
function(tel) {
|
||||
let normalized = PhoneNumberUtils.normalize(tel.value.toString());
|
||||
cursor.value.search.exactTel.push(normalized);
|
||||
}
|
||||
);
|
||||
cursor.update(cursor.value);
|
||||
}
|
||||
cursor.continue();
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
};
|
||||
},
|
||||
function upgrade9to10() {
|
||||
// no-op, see https://bugzilla.mozilla.org/show_bug.cgi?id=883770#c16
|
||||
next();
|
||||
},
|
||||
function upgrade10to11() {
|
||||
if (DEBUG) debug("Adding object store for database revision");
|
||||
db.createObjectStore(REVISION_STORE).put(0, REVISION_KEY);
|
||||
next();
|
||||
},
|
||||
function upgrade11to12() {
|
||||
if (DEBUG) debug("Add a telMatch index with national and international numbers");
|
||||
if (!objectStore) {
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
}
|
||||
if (!objectStore.indexNames.contains("telMatch")) {
|
||||
objectStore.createIndex("telMatch", "search.parsedTel", {multiEntry: true});
|
||||
}
|
||||
objectStore.openCursor().onsuccess = function(event) {
|
||||
let cursor = event.target.result;
|
||||
if (cursor) {
|
||||
if (cursor.value.properties.tel) {
|
||||
cursor.value.search.parsedTel = [];
|
||||
cursor.value.properties.tel.forEach(
|
||||
function(tel) {
|
||||
let parsed = PhoneNumberUtils.parse(tel.value.toString());
|
||||
if (parsed) {
|
||||
cursor.value.search.parsedTel.push(parsed.nationalNumber);
|
||||
cursor.value.search.parsedTel.push(PhoneNumberUtils.normalize(parsed.nationalFormat));
|
||||
cursor.value.search.parsedTel.push(parsed.internationalNumber);
|
||||
cursor.value.search.parsedTel.push(PhoneNumberUtils.normalize(parsed.internationalFormat));
|
||||
}
|
||||
cursor.value.search.parsedTel.push(PhoneNumberUtils.normalize(tel.value.toString()));
|
||||
}
|
||||
);
|
||||
cursor.update(cursor.value);
|
||||
}
|
||||
cursor.continue();
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
let index = aOldVersion;
|
||||
let outer = this;
|
||||
function next() {
|
||||
if (index == aNewVersion) {
|
||||
if (aOldVersion === 0) {
|
||||
loadInitialContacts();
|
||||
}
|
||||
outer.incrementRevision(aTransaction);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var i = index++;
|
||||
if (DEBUG) debug("Upgrade step: " + i + "\n");
|
||||
steps[i]();
|
||||
} catch(ex) {
|
||||
dump("Caught exception" + ex);
|
||||
aTransaction.abort();
|
||||
return;
|
||||
}
|
||||
};
|
||||
if (aNewVersion > steps.length) {
|
||||
dump("Contacts DB upgrade error!");
|
||||
aTransaction.abort();
|
||||
}
|
||||
next();
|
||||
},
|
||||
|
||||
makeImport: function makeImport(aContact) {
|
||||
|
@ -739,22 +791,22 @@ ContactDB.prototype = {
|
|||
}.bind(this), aFailureCb);
|
||||
},
|
||||
|
||||
getRevision: function CDB_getRevision(aSuccessCb) {
|
||||
getRevision: function CDB_getRevision(aSuccessCb, aErrorCb) {
|
||||
if (DEBUG) debug("getRevision");
|
||||
this.newTxn("readonly", REVISION_STORE, function (txn, store) {
|
||||
store.get(REVISION_KEY).onsuccess = function (e) {
|
||||
aSuccessCb(e.target.result);
|
||||
};
|
||||
});
|
||||
},null, aErrorCb);
|
||||
},
|
||||
|
||||
getCount: function CDB_getCount(aSuccessCb) {
|
||||
getCount: function CDB_getCount(aSuccessCb, aErrorCb) {
|
||||
if (DEBUG) debug("getCount");
|
||||
this.newTxn("readonly", STORE_NAME, function (txn, store) {
|
||||
store.count().onsuccess = function (e) {
|
||||
aSuccessCb(e.target.result);
|
||||
};
|
||||
});
|
||||
}, null, aErrorCb);
|
||||
},
|
||||
|
||||
/*
|
||||
|
|
|
@ -205,7 +205,8 @@ let ContactService = {
|
|||
requestID: msg.requestID,
|
||||
revision: revision
|
||||
});
|
||||
}
|
||||
},
|
||||
function(aErrorMsg) { mm.sendAsyncMessage("Contacts:GetRevision:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this)
|
||||
);
|
||||
break;
|
||||
case "Contacts:GetCount":
|
||||
|
@ -218,7 +219,8 @@ let ContactService = {
|
|||
requestID: msg.requestID,
|
||||
count: count
|
||||
});
|
||||
}
|
||||
},
|
||||
function(aErrorMsg) { mm.sendAsyncMessage("Contacts:Count:Return:KO", { requestID: msg.requestID, errorMsg: aErrorMsg }); }.bind(this)
|
||||
);
|
||||
break;
|
||||
case "Contacts:RegisterForMessages":
|
||||
|
|
|
@ -257,10 +257,12 @@ ok(mozContacts, "mozContacts exists");
|
|||
ok("mozContact" in window, "mozContact exists");
|
||||
var steps = [
|
||||
function() {
|
||||
mozContacts.getRevision().onsuccess = function(e) {
|
||||
req = mozContacts.getRevision();
|
||||
req.onsuccess = function(e) {
|
||||
initialRev = e.target.result;
|
||||
next();
|
||||
};
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
ok(true, "Deleting database");
|
||||
|
|
|
@ -730,19 +730,28 @@ ContentParent::TransformPreallocatedIntoApp(const nsAString& aAppManifestURL,
|
|||
}
|
||||
|
||||
void
|
||||
ContentParent::ShutDownProcess()
|
||||
ContentParent::ShutDownProcess(bool aFromActorDestroyed)
|
||||
{
|
||||
if (!mIsDestroyed) {
|
||||
mIsDestroyed = true;
|
||||
|
||||
const InfallibleTArray<PIndexedDBParent*>& idbParents =
|
||||
ManagedPIndexedDBParent();
|
||||
for (uint32_t i = 0; i < idbParents.Length(); ++i) {
|
||||
static_cast<IndexedDBParent*>(idbParents[i])->Disconnect();
|
||||
}
|
||||
|
||||
// Close() can only be called once. It kicks off the
|
||||
// destruction sequence.
|
||||
Close();
|
||||
mIsDestroyed = true;
|
||||
if (aFromActorDestroyed) {
|
||||
// If ActorDestroyed() is calling this method but mIsDestroyed was false,
|
||||
// we're in an error state.
|
||||
AsyncChannel* channel = GetIPCChannel();
|
||||
if (channel) {
|
||||
channel->CloseWithError();
|
||||
}
|
||||
} else {
|
||||
// Close() can only be called once: It kicks off the destruction sequence.
|
||||
Close();
|
||||
}
|
||||
}
|
||||
// NB: must MarkAsDead() here so that this isn't accidentally
|
||||
// returned from Get*() while in the midst of shutdown.
|
||||
|
@ -948,6 +957,11 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
|
|||
obs->NotifyObservers((nsIPropertyBag2*) props, "ipc:content-shutdown", nullptr);
|
||||
}
|
||||
|
||||
// If the child process was terminated due to a SIGKIL, ShutDownProcess
|
||||
// might not have been called yet. We must call it to ensure that our
|
||||
// channel is closed, etc.
|
||||
ShutDownProcess(/* aForce = */ true);
|
||||
|
||||
MessageLoop::current()->
|
||||
PostTask(FROM_HERE,
|
||||
NewRunnableFunction(DelayedDeleteSubprocess, mSubprocess));
|
||||
|
@ -1006,7 +1020,8 @@ ContentParent::NotifyTabDestroyed(PBrowserParent* aTab,
|
|||
if (ManagedPBrowserParent().Length() == 1) {
|
||||
MessageLoop::current()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableMethod(this, &ContentParent::ShutDownProcess));
|
||||
NewRunnableMethod(this, &ContentParent::ShutDownProcess,
|
||||
/* force */ false));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1464,7 +1479,7 @@ ContentParent::Observe(nsISupports* aSubject,
|
|||
const PRUnichar* aData)
|
||||
{
|
||||
if (!strcmp(aTopic, "xpcom-shutdown") && mSubprocess) {
|
||||
ShutDownProcess();
|
||||
ShutDownProcess(/* force */ false);
|
||||
NS_ASSERTION(!mSubprocess, "Close should have nulled mSubprocess");
|
||||
}
|
||||
|
||||
|
|
|
@ -243,8 +243,14 @@ private:
|
|||
* will return false and this ContentParent will not be returned
|
||||
* by the Get*() funtions. However, the shutdown sequence itself
|
||||
* may be asynchronous.
|
||||
*
|
||||
* If aFromActorDestroyed is true and this is the first call to
|
||||
* ShutDownProcess, then we'll close our channel using CloseWithError()
|
||||
* rather than vanilla Close(). CloseWithError() indicates to IPC that this
|
||||
* is an abnormal shutdown (e.g. a crash); when the process shuts down
|
||||
* cleanly, ShutDownProcess runs before ActorDestroyed.
|
||||
*/
|
||||
void ShutDownProcess();
|
||||
void ShutDownProcess(bool aFromActorDestroyed);
|
||||
|
||||
PCompositorParent*
|
||||
AllocPCompositorParent(mozilla::ipc::Transport* aTransport,
|
||||
|
|
|
@ -34,15 +34,6 @@ this.SystemMessagePermissionsTable = {
|
|||
"bluetooth-dialer-command": {
|
||||
"telephony": []
|
||||
},
|
||||
"bluetooth-requestconfirmation": {
|
||||
"bluetooth": []
|
||||
},
|
||||
"bluetooth-requestpasskey": {
|
||||
"bluetooth": []
|
||||
},
|
||||
"bluetooth-requestpincode": {
|
||||
"bluetooth": []
|
||||
},
|
||||
"bluetooth-authorize": {
|
||||
"bluetooth": []
|
||||
},
|
||||
|
@ -52,6 +43,9 @@ this.SystemMessagePermissionsTable = {
|
|||
"bluetooth-pairedstatuschanged": {
|
||||
"bluetooth": []
|
||||
},
|
||||
"bluetooth-a2dp-status-changed": {
|
||||
"bluetooth": []
|
||||
},
|
||||
"bluetooth-hfp-status-changed": {
|
||||
"bluetooth": []
|
||||
},
|
||||
|
|
|
@ -780,6 +780,11 @@ MobileMessageDatabaseService.prototype = {
|
|||
if (DEBUG) {
|
||||
debug("MMS: part[" + i + "]: " + JSON.stringify(part));
|
||||
}
|
||||
// Sometimes the part is incomplete because the device reboots when
|
||||
// downloading MMS. Don't need to expose this part to the content.
|
||||
if (!part) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let partHeaders = part["headers"];
|
||||
let partContent = part["content"];
|
||||
|
|
|
@ -194,8 +194,6 @@ function convertRILCallState(state) {
|
|||
case RIL.CALL_STATE_INCOMING:
|
||||
case RIL.CALL_STATE_WAITING:
|
||||
return nsITelephonyProvider.CALL_STATE_INCOMING;
|
||||
case RIL.CALL_STATE_BUSY:
|
||||
return nsITelephonyProvider.CALL_STATE_BUSY;
|
||||
default:
|
||||
throw new Error("Unknown rilCallState: " + state);
|
||||
}
|
||||
|
|
|
@ -442,7 +442,6 @@ this.CALL_STATE_DIALING = 2;
|
|||
this.CALL_STATE_ALERTING = 3;
|
||||
this.CALL_STATE_INCOMING = 4;
|
||||
this.CALL_STATE_WAITING = 5;
|
||||
this.CALL_STATE_BUSY = 6;
|
||||
|
||||
this.TOA_INTERNATIONAL = 0x91;
|
||||
this.TOA_UNKNOWN = 0x81;
|
||||
|
|
|
@ -4690,11 +4690,6 @@ RIL[REQUEST_LAST_CALL_FAIL_CAUSE] = function REQUEST_LAST_CALL_FAIL_CAUSE(length
|
|||
case CALL_FAIL_NORMAL:
|
||||
this._handleDisconnectedCall(options);
|
||||
break;
|
||||
case CALL_FAIL_BUSY:
|
||||
options.state = CALL_STATE_BUSY;
|
||||
this._handleChangedCallState(options);
|
||||
this._handleDisconnectedCall(options);
|
||||
break;
|
||||
default:
|
||||
options.rilMessageType = "callError";
|
||||
options.errorMsg = RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[failCause];
|
||||
|
|
|
@ -61,9 +61,6 @@ TelephonyCall::ChangeStateInternal(uint16_t aCallState, bool aFireEvents)
|
|||
case nsITelephonyProvider::CALL_STATE_ALERTING:
|
||||
stateString.AssignLiteral("alerting");
|
||||
break;
|
||||
case nsITelephonyProvider::CALL_STATE_BUSY:
|
||||
stateString.AssignLiteral("busy");
|
||||
break;
|
||||
case nsITelephonyProvider::CALL_STATE_CONNECTING:
|
||||
stateString.AssignLiteral("connecting");
|
||||
break;
|
||||
|
@ -269,7 +266,6 @@ TelephonyCall::Resume()
|
|||
NS_IMPL_EVENT_HANDLER(TelephonyCall, statechange)
|
||||
NS_IMPL_EVENT_HANDLER(TelephonyCall, dialing)
|
||||
NS_IMPL_EVENT_HANDLER(TelephonyCall, alerting)
|
||||
NS_IMPL_EVENT_HANDLER(TelephonyCall, busy)
|
||||
NS_IMPL_EVENT_HANDLER(TelephonyCall, connecting)
|
||||
NS_IMPL_EVENT_HANDLER(TelephonyCall, connected)
|
||||
NS_IMPL_EVENT_HANDLER(TelephonyCall, disconnecting)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
interface nsIDOMEventListener;
|
||||
|
||||
[scriptable, builtinclass, uuid(22e44e8c-cb74-44f2-abe6-b37e9f42ea79)]
|
||||
[scriptable, builtinclass, uuid(74d240f5-a379-4ac0-a085-a7f714189a27)]
|
||||
interface nsIDOMTelephonyCall : nsIDOMEventTarget
|
||||
{
|
||||
readonly attribute DOMString number;
|
||||
|
@ -32,7 +32,6 @@ interface nsIDOMTelephonyCall : nsIDOMEventTarget
|
|||
|
||||
[implicit_jscontext] attribute jsval ondialing;
|
||||
[implicit_jscontext] attribute jsval onalerting;
|
||||
[implicit_jscontext] attribute jsval onbusy;
|
||||
[implicit_jscontext] attribute jsval onconnecting;
|
||||
[implicit_jscontext] attribute jsval onconnected;
|
||||
[implicit_jscontext] attribute jsval ondisconnecting;
|
||||
|
|
|
@ -83,15 +83,14 @@ interface nsITelephonyProvider : nsISupports
|
|||
const unsigned short CALL_STATE_UNKNOWN = 0;
|
||||
const unsigned short CALL_STATE_DIALING = 1;
|
||||
const unsigned short CALL_STATE_ALERTING = 2;
|
||||
const unsigned short CALL_STATE_BUSY = 3;
|
||||
const unsigned short CALL_STATE_CONNECTING = 4;
|
||||
const unsigned short CALL_STATE_CONNECTED = 5;
|
||||
const unsigned short CALL_STATE_HOLDING = 6;
|
||||
const unsigned short CALL_STATE_HELD = 7;
|
||||
const unsigned short CALL_STATE_RESUMING = 8;
|
||||
const unsigned short CALL_STATE_DISCONNECTING = 9;
|
||||
const unsigned short CALL_STATE_DISCONNECTED = 10;
|
||||
const unsigned short CALL_STATE_INCOMING = 11;
|
||||
const unsigned short CALL_STATE_CONNECTING = 3;
|
||||
const unsigned short CALL_STATE_CONNECTED = 4;
|
||||
const unsigned short CALL_STATE_HOLDING = 5;
|
||||
const unsigned short CALL_STATE_HELD = 6;
|
||||
const unsigned short CALL_STATE_RESUMING = 7;
|
||||
const unsigned short CALL_STATE_DISCONNECTING = 8;
|
||||
const unsigned short CALL_STATE_DISCONNECTED = 9;
|
||||
const unsigned short CALL_STATE_INCOMING = 10;
|
||||
|
||||
/**
|
||||
* Called when a content process registers receiving unsolicited messages from
|
||||
|
|
|
@ -92,10 +92,10 @@ function dial() {
|
|||
function busy() {
|
||||
log("The receiver is busy.");
|
||||
|
||||
outgoing.onbusy = function onbusy(event) {
|
||||
log("Received 'busy' call event.");
|
||||
outgoing.onerror = function onerror(event) {
|
||||
log("Received 'error' call event.");
|
||||
is(outgoing, event.call);
|
||||
is(outgoing.state, "busy");
|
||||
is(event.call.error.name, "BusyError");
|
||||
|
||||
runEmulatorCmd("gsm list", function(result) {
|
||||
log("Call list is now: " + result);
|
||||
|
@ -103,6 +103,7 @@ function busy() {
|
|||
cleanUp();
|
||||
});
|
||||
};
|
||||
|
||||
runEmulatorCmd("gsm busy " + number);
|
||||
};
|
||||
|
||||
|
|
|
@ -101,11 +101,11 @@ namespace mozilla {
|
|||
* One hint: if you're writing a move constructor where the type has members
|
||||
* that should be moved themselves, it's much nicer to write this:
|
||||
*
|
||||
* C(MoveRef<C> c) : x(c->x), y(c->y) { }
|
||||
* C(MoveRef<C> c) : x(Move(c->x)), y(Move(c->y)) { }
|
||||
*
|
||||
* than the equivalent:
|
||||
*
|
||||
* C(MoveRef<C> c) { new(&x) X(c->x); new(&y) Y(c->y); }
|
||||
* C(MoveRef<C> c) { new(&x) X(Move(c->x)); new(&y) Y(Move(c->y)); }
|
||||
*
|
||||
* especially since GNU C++ fails to notice that this does indeed initialize x
|
||||
* and y, which may matter if they're const.
|
||||
|
|
|
@ -187,7 +187,7 @@ class BaseBootstrapper(object):
|
|||
|
||||
info = self.check_output([hg, '--version']).splitlines()[0]
|
||||
|
||||
match = re.search('version ([^\)]+)', info)
|
||||
match = re.search('version ([^\+\)]+)', info)
|
||||
if not match:
|
||||
print('ERROR: Unable to identify Mercurial version.')
|
||||
return True, False, None
|
||||
|
|
|
@ -36,6 +36,16 @@ this.Log4Moz = {
|
|||
20: "DEBUG",
|
||||
10: "TRACE",
|
||||
0: "ALL"
|
||||
},
|
||||
Numbers: {
|
||||
"FATAL": 70,
|
||||
"ERROR": 60,
|
||||
"WARN": 50,
|
||||
"INFO": 40,
|
||||
"CONFIG": 30,
|
||||
"DEBUG": 20,
|
||||
"TRACE": 10,
|
||||
"ALL": 0,
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -55,6 +65,7 @@ this.Log4Moz = {
|
|||
|
||||
Formatter: Formatter,
|
||||
BasicFormatter: BasicFormatter,
|
||||
StructuredFormatter: StructuredFormatter,
|
||||
|
||||
Appender: Appender,
|
||||
DumpAppender: DumpAppender,
|
||||
|
@ -109,10 +120,15 @@ this.Log4Moz = {
|
|||
* LogMessage
|
||||
* Encapsulates a single log event's data
|
||||
*/
|
||||
function LogMessage(loggerName, level, message){
|
||||
function LogMessage(loggerName, level, message, params) {
|
||||
this.loggerName = loggerName;
|
||||
this.level = level;
|
||||
this.message = message;
|
||||
this.params = params;
|
||||
|
||||
// The _structured field will correspond to whether this message is to
|
||||
// be interpreted as a structured message.
|
||||
this._structured = this.params && this.params.action;
|
||||
this.time = Date.now();
|
||||
}
|
||||
LogMessage.prototype = {
|
||||
|
@ -123,8 +139,12 @@ LogMessage.prototype = {
|
|||
},
|
||||
|
||||
toString: function LogMsg_toString(){
|
||||
return "LogMessage [" + this.time + " " + this.level + " " +
|
||||
this.message + "]";
|
||||
let msg = "LogMessage [" + this.time + " " + this.level + " " +
|
||||
this.message;
|
||||
if (this.params) {
|
||||
msg += " " + JSON.stringify(this.params);
|
||||
}
|
||||
return msg + "]"
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -211,7 +231,39 @@ Logger.prototype = {
|
|||
this.updateAppenders();
|
||||
},
|
||||
|
||||
log: function Logger_log(level, string) {
|
||||
/**
|
||||
* Logs a structured message object.
|
||||
*
|
||||
* @param action
|
||||
* (string) A message action, one of a set of actions known to the
|
||||
* log consumer.
|
||||
* @param params
|
||||
* (object) Parameters to be included in the message.
|
||||
* If _level is included as a key and the corresponding value
|
||||
* is a number or known level name, the message will be logged
|
||||
* at the indicated level.
|
||||
*/
|
||||
logStructured: function (action, params) {
|
||||
if (!action) {
|
||||
throw "An action is required when logging a structured message.";
|
||||
}
|
||||
if (!params) {
|
||||
return this.log(this.level, undefined, {"action": action});
|
||||
}
|
||||
if (typeof params != "object") {
|
||||
throw "The params argument is required to be an object.";
|
||||
}
|
||||
|
||||
let level = params._level || this.level;
|
||||
if ((typeof level == "string") && level in Log4Moz.Level.Numbers) {
|
||||
level = Log4Moz.Level.Numbers[level];
|
||||
}
|
||||
|
||||
params.action = action;
|
||||
this.log(level, params._message, params);
|
||||
},
|
||||
|
||||
log: function (level, string, params) {
|
||||
if (this.level > level)
|
||||
return;
|
||||
|
||||
|
@ -224,32 +276,32 @@ Logger.prototype = {
|
|||
continue;
|
||||
}
|
||||
if (!message) {
|
||||
message = new LogMessage(this._name, level, string);
|
||||
message = new LogMessage(this._name, level, string, params);
|
||||
}
|
||||
appender.append(message);
|
||||
}
|
||||
},
|
||||
|
||||
fatal: function Logger_fatal(string) {
|
||||
this.log(Log4Moz.Level.Fatal, string);
|
||||
fatal: function (string, params) {
|
||||
this.log(Log4Moz.Level.Fatal, string, params);
|
||||
},
|
||||
error: function Logger_error(string) {
|
||||
this.log(Log4Moz.Level.Error, string);
|
||||
error: function (string, params) {
|
||||
this.log(Log4Moz.Level.Error, string, params);
|
||||
},
|
||||
warn: function Logger_warn(string) {
|
||||
this.log(Log4Moz.Level.Warn, string);
|
||||
warn: function (string, params) {
|
||||
this.log(Log4Moz.Level.Warn, string, params);
|
||||
},
|
||||
info: function Logger_info(string) {
|
||||
this.log(Log4Moz.Level.Info, string);
|
||||
info: function (string, params) {
|
||||
this.log(Log4Moz.Level.Info, string, params);
|
||||
},
|
||||
config: function Logger_config(string) {
|
||||
this.log(Log4Moz.Level.Config, string);
|
||||
config: function (string, params) {
|
||||
this.log(Log4Moz.Level.Config, string, params);
|
||||
},
|
||||
debug: function Logger_debug(string) {
|
||||
this.log(Log4Moz.Level.Debug, string);
|
||||
debug: function (string, params) {
|
||||
this.log(Log4Moz.Level.Debug, string, params);
|
||||
},
|
||||
trace: function Logger_trace(string) {
|
||||
this.log(Log4Moz.Level.Trace, string);
|
||||
trace: function (string, params) {
|
||||
this.log(Log4Moz.Level.Trace, string, params);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -314,8 +366,8 @@ LoggerRepository.prototype = {
|
|||
|
||||
/*
|
||||
* Formatters
|
||||
* These massage a LogMessage into whatever output is desired
|
||||
* Only the BasicFormatter is currently implemented
|
||||
* These massage a LogMessage into whatever output is desired.
|
||||
* BasicFormatter and StructuredFormatter are implemented here.
|
||||
*/
|
||||
|
||||
// Abstract formatter
|
||||
|
@ -324,7 +376,7 @@ Formatter.prototype = {
|
|||
format: function Formatter_format(message) {}
|
||||
};
|
||||
|
||||
// Basic formatter that doesn't do anything fancy
|
||||
// Basic formatter that doesn't do anything fancy.
|
||||
function BasicFormatter(dateFormat) {
|
||||
if (dateFormat)
|
||||
this.dateFormat = dateFormat;
|
||||
|
@ -340,6 +392,36 @@ BasicFormatter.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
// Structured formatter that outputs JSON based on message data.
|
||||
// This formatter will format unstructured messages by supplying
|
||||
// default values.
|
||||
function StructuredFormatter() { }
|
||||
StructuredFormatter.prototype = {
|
||||
__proto__: Formatter.prototype,
|
||||
|
||||
format: function (logMessage) {
|
||||
let output = {
|
||||
_time: logMessage.time,
|
||||
_namespace: logMessage.loggerName,
|
||||
_level: logMessage.levelDesc
|
||||
};
|
||||
|
||||
for (let key in logMessage.params) {
|
||||
output[key] = logMessage.params[key];
|
||||
}
|
||||
|
||||
if (!output.action) {
|
||||
output.action = "UNKNOWN";
|
||||
}
|
||||
|
||||
if (!output._message && logMessage.message) {
|
||||
output._message = logMessage.message;
|
||||
}
|
||||
|
||||
return JSON.stringify(output);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Appenders
|
||||
* These can be attached to Loggers to log to different places
|
||||
|
|
|
@ -41,8 +41,9 @@ add_test(function test_Logger() {
|
|||
log.debug("this should be logged but not appended.");
|
||||
|
||||
do_check_eq(appender.messages.length, 1);
|
||||
do_check_true(appender.messages[0].indexOf("info test") > 0);
|
||||
do_check_true(appender.messages[0].indexOf("INFO") > 0);
|
||||
|
||||
let msgRe = /\d+\ttest.logger\t\INFO\tinfo test/;
|
||||
do_check_true(msgRe.test(appender.messages[0]));
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
@ -69,6 +70,113 @@ add_test(function test_Logger_parent() {
|
|||
run_next_test();
|
||||
});
|
||||
|
||||
// A utility method for checking object equivalence.
|
||||
// Fields with a reqular expression value in expected will be tested
|
||||
// against the corresponding value in actual. Otherwise objects
|
||||
// are expected to have the same keys and equal values.
|
||||
function checkObjects(expected, actual) {
|
||||
do_check_true(expected instanceof Object);
|
||||
do_check_true(actual instanceof Object);
|
||||
for (let key in expected) {
|
||||
do_check_neq(actual[key], undefined);
|
||||
if (expected[key] instanceof RegExp) {
|
||||
do_check_true(expected[key].test(actual[key].toString()));
|
||||
} else {
|
||||
if (expected[key] instanceof Object) {
|
||||
checkObjects(expected[key], actual[key]);
|
||||
} else {
|
||||
do_check_eq(expected[key], actual[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let key in actual) {
|
||||
do_check_neq(expected[key], undefined);
|
||||
}
|
||||
}
|
||||
|
||||
add_test(function test_StructuredLogCommands() {
|
||||
let appender = new MockAppender(new Log4Moz.StructuredFormatter());
|
||||
let logger = Log4Moz.repository.getLogger("test.StructuredOutput");
|
||||
logger.addAppender(appender);
|
||||
logger.level = Log4Moz.Level.Info;
|
||||
|
||||
logger.logStructured("test_message", {_message: "message string one"});
|
||||
logger.logStructured("test_message", {_message: "message string two",
|
||||
_level: "ERROR",
|
||||
source_file: "test_log4moz.js"});
|
||||
logger.logStructured("test_message");
|
||||
logger.logStructured("test_message", {source_file: "test_log4moz.js",
|
||||
message_position: 4});
|
||||
|
||||
let messageOne = {"_time": /\d+/,
|
||||
"_namespace": "test.StructuredOutput",
|
||||
"_level": "INFO",
|
||||
"_message": "message string one",
|
||||
"action": "test_message"};
|
||||
|
||||
let messageTwo = {"_time": /\d+/,
|
||||
"_namespace": "test.StructuredOutput",
|
||||
"_level": "ERROR",
|
||||
"_message": "message string two",
|
||||
"action": "test_message",
|
||||
"source_file": "test_log4moz.js"};
|
||||
|
||||
let messageThree = {"_time": /\d+/,
|
||||
"_namespace": "test.StructuredOutput",
|
||||
"_level": "INFO",
|
||||
"action": "test_message"};
|
||||
|
||||
let messageFour = {"_time": /\d+/,
|
||||
"_namespace": "test.StructuredOutput",
|
||||
"_level": "INFO",
|
||||
"action": "test_message",
|
||||
"source_file": "test_log4moz.js",
|
||||
"message_position": 4};
|
||||
|
||||
checkObjects(messageOne, JSON.parse(appender.messages[0]));
|
||||
checkObjects(messageTwo, JSON.parse(appender.messages[1]));
|
||||
checkObjects(messageThree, JSON.parse(appender.messages[2]));
|
||||
checkObjects(messageFour, JSON.parse(appender.messages[3]));
|
||||
|
||||
let errored = false;
|
||||
try {
|
||||
logger.logStructured("", {_message: "invalid message"});
|
||||
} catch (e) {
|
||||
errored = true;
|
||||
do_check_eq(e, "An action is required when logging a structured message.");
|
||||
} finally {
|
||||
do_check_true(errored);
|
||||
}
|
||||
|
||||
let errored = false;
|
||||
try {
|
||||
logger.logStructured("message_action", "invalid params");
|
||||
} catch (e) {
|
||||
errored = true;
|
||||
do_check_eq(e, "The params argument is required to be an object.");
|
||||
} finally {
|
||||
do_check_true(errored);
|
||||
}
|
||||
|
||||
// Logging with unstructured interface should produce the same messages
|
||||
// as the structured interface for these cases.
|
||||
let appender = new MockAppender(new Log4Moz.StructuredFormatter());
|
||||
let logger = Log4Moz.repository.getLogger("test.StructuredOutput1");
|
||||
messageOne._namespace = "test.StructuredOutput1";
|
||||
messageTwo._namespace = "test.StructuredOutput1";
|
||||
logger.addAppender(appender);
|
||||
logger.level = Log4Moz.Level.All;
|
||||
logger.info("message string one", {action: "test_message"});
|
||||
logger.error("message string two", {action: "test_message",
|
||||
source_file: "test_log4moz.js"});
|
||||
|
||||
checkObjects(messageOne, JSON.parse(appender.messages[0]));
|
||||
checkObjects(messageTwo, JSON.parse(appender.messages[1]));
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_StorageStreamAppender() {
|
||||
let appender = new Log4Moz.StorageStreamAppender(testFormatter);
|
||||
do_check_eq(appender.getInputStream(), null);
|
||||
|
|
Загрузка…
Ссылка в новой задаче