Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
437 lines
13 KiB
JavaScript
Executable file
437 lines
13 KiB
JavaScript
Executable file
'use strict';
|
|
|
|
/* global CallLog, CallLogDBManager, Contacts, KeypadManager, LazyLoader,
|
|
MmiManager, Notification, NotificationHelper, SettingsListener,
|
|
SimSettingsHelper, SuggestionBar, TelephonyHelper, Utils, Voicemail,
|
|
MozActivity, Navigation */
|
|
|
|
var NavbarManager = {
|
|
init: function nm_init() {
|
|
Navigation.show('keypad');
|
|
|
|
document.getElementById('views').addEventListener(
|
|
'click',
|
|
function(e) {
|
|
var destination = e.target.dataset &&
|
|
e.target.dataset.destination;
|
|
if (!destination) {
|
|
return;
|
|
}
|
|
Navigation.show(destination);
|
|
}
|
|
);
|
|
},
|
|
|
|
hide: function() {
|
|
var views = document.getElementById('views');
|
|
views.classList.add('hide-toolbar');
|
|
},
|
|
|
|
show: function() {
|
|
var views = document.getElementById('views');
|
|
views.classList.remove('hide-toolbar');
|
|
},
|
|
};
|
|
|
|
var CallHandler = (function callHandler() {
|
|
var COMMS_APP_ORIGIN = document.location.protocol + '//' +
|
|
document.location.host;
|
|
var FB_SYNC_ERROR_PARAM = 'isSyncError';
|
|
|
|
/* === Settings === */
|
|
var engineeringModeKey = null;
|
|
|
|
/* === WebActivity === */
|
|
function handleActivity(activity) {
|
|
// Workaround here until the bug 787415 is fixed
|
|
// Gecko is sending an activity event in every multiple entry point
|
|
// instead only the one that the href match.
|
|
if (activity.source.name != 'dial') {
|
|
return;
|
|
}
|
|
|
|
var number = activity.source.data.number;
|
|
if (number) {
|
|
KeypadManager.updatePhoneNumber(number, 'begin', false);
|
|
if (Navigation.currentView != 'keypad') {
|
|
Navigation.showKeypad();
|
|
}
|
|
} else {
|
|
if (Navigation.currentView != 'contacts') {
|
|
Navigation.showContacts();
|
|
}
|
|
}
|
|
}
|
|
|
|
/* === Notifications support === */
|
|
|
|
/**
|
|
* Retrieves the parameters from an URL and forms an object with them.
|
|
*
|
|
* @param {String} input A string holding the parameters attached to an URL.
|
|
* @return {Object} An object built using the parameters.
|
|
*/
|
|
function deserializeParameters(input) {
|
|
var rparams = /([^?=&]+)(?:=([^&]*))?/g;
|
|
var parsed = {};
|
|
|
|
input.replace(rparams, function($0, $1, $2) {
|
|
parsed[$1] = decodeURIComponent($2);
|
|
});
|
|
|
|
return parsed;
|
|
}
|
|
|
|
function handleNotification(evt) {
|
|
if (!evt.clicked) {
|
|
return;
|
|
}
|
|
|
|
navigator.mozApps.getSelf().onsuccess = function gotSelf(selfEvt) {
|
|
var app = selfEvt.target.result;
|
|
app.launch('dialer');
|
|
var location = document.createElement('a');
|
|
location.href = evt.imageURL;
|
|
if (location.search.indexOf(FB_SYNC_ERROR_PARAM) !== -1) {
|
|
Navigation.showContacts();
|
|
} else if (location.search.indexOf('ussdMessage') !== -1) {
|
|
var params = deserializeParameters(evt.imageURL);
|
|
|
|
Notification.get({ tag: evt.tag }).then(function(notifications) {
|
|
for (var i = 0; i < notifications.length; i++) {
|
|
notifications[i].close();
|
|
}
|
|
});
|
|
|
|
MmiManager.handleMMIReceived(evt.body, /* sessionEnded */ true,
|
|
params.cardIndex);
|
|
} else {
|
|
Navigation.showCalllog();
|
|
}
|
|
};
|
|
}
|
|
|
|
/* === Telephony Call Ended Support === */
|
|
function sendNotification(number, serviceId) {
|
|
LazyLoader.load('/shared/js/dialer/utils.js', function() {
|
|
Contacts.findByNumber(number, function lookup(contact, matchingTel) {
|
|
var title;
|
|
if (navigator.mozIccManager.iccIds.length > 1) {
|
|
title = { id: 'missedCallMultiSims', args: { n: serviceId + 1 } };
|
|
} else {
|
|
title = 'missedCall';
|
|
}
|
|
|
|
var body;
|
|
if (!number) {
|
|
body = 'from-withheld-number';
|
|
} else if (contact) {
|
|
var primaryInfo = Utils.getPhoneNumberPrimaryInfo(matchingTel,
|
|
contact);
|
|
if (primaryInfo) {
|
|
if (primaryInfo !== matchingTel.value) {
|
|
// primaryInfo is an object here
|
|
body = {
|
|
id: 'from-contact',
|
|
args: { contact: primaryInfo.toString() }
|
|
};
|
|
} else {
|
|
body = { id: 'from-number', args: { number: primaryInfo } };
|
|
}
|
|
} else {
|
|
body = 'from-withheld-number';
|
|
}
|
|
} else {
|
|
body = { id: 'from-number', args: { number: number } };
|
|
}
|
|
|
|
navigator.mozApps.getSelf().onsuccess = function getSelfCB(evt) {
|
|
var app = evt.target.result;
|
|
|
|
var iconURL = NotificationHelper.getIconURI(app, 'dialer');
|
|
var clickCB = function() {
|
|
app.launch('dialer');
|
|
Navigation.showCalllog();
|
|
};
|
|
|
|
NotificationHelper.send(title, {
|
|
bodyL10n: body,
|
|
icon: iconURL
|
|
}).then(function(notification) {
|
|
notification.addEventListener('click', clickCB);
|
|
});
|
|
};
|
|
});
|
|
});
|
|
}
|
|
|
|
function callEnded(data) {
|
|
var highPriorityWakeLock = navigator.requestWakeLock('high-priority');
|
|
var number = data.number;
|
|
var incoming = data.direction === 'incoming';
|
|
|
|
// Missed call when not rejected by user
|
|
if (incoming && !data.duration && !data.hangUpLocal) {
|
|
sendNotification(number, data.serviceId);
|
|
}
|
|
|
|
Voicemail.check(number, data.serviceId).then(function(isVoicemailNumber) {
|
|
var entry = {
|
|
date: Date.now() - parseInt(data.duration),
|
|
duration: data.duration,
|
|
type: incoming ? 'incoming' : 'dialing',
|
|
number: number,
|
|
serviceId: data.serviceId,
|
|
emergency: data.emergency || false,
|
|
voicemail: isVoicemailNumber,
|
|
status: (incoming && data.duration > 0) ? 'connected' : null
|
|
};
|
|
|
|
// Store and display the call that ended
|
|
CallLogDBManager.add(entry, function(logEntry) {
|
|
CallLog.appendGroup(logEntry);
|
|
|
|
// A CDMA call can contain two calls. If it only has one call,
|
|
// we have nothing left to do and release the lock.
|
|
if (!data.secondNumber) {
|
|
highPriorityWakeLock.unlock();
|
|
return;
|
|
}
|
|
|
|
_addSecondCdmaCall(data, isVoicemailNumber, highPriorityWakeLock);
|
|
});
|
|
});
|
|
}
|
|
|
|
function _addSecondCdmaCall(data, isVoicemailNumber, wakeLock) {
|
|
var entryCdmaSecond = {
|
|
date: Date.now() - parseInt(data.duration),
|
|
duration: data.duration,
|
|
type: 'incoming',
|
|
number: data.secondNumber,
|
|
serviceId: data.serviceId,
|
|
emergency: false,
|
|
voicemail: isVoicemailNumber,
|
|
status: 'connected'
|
|
};
|
|
|
|
CallLogDBManager.add(entryCdmaSecond, function(logGroupCdmaSecondCall) {
|
|
CallLog.appendGroup(logGroupCdmaSecondCall);
|
|
wakeLock.unlock();
|
|
});
|
|
}
|
|
|
|
/* === postMessage support === */
|
|
function handleMessage(evt) {
|
|
if (evt.origin !== COMMS_APP_ORIGIN) {
|
|
return;
|
|
}
|
|
|
|
var data = evt.data;
|
|
|
|
if (!data.type) {
|
|
return;
|
|
}
|
|
|
|
if (data.type === 'contactsiframe') {
|
|
handleContactsIframeRequest(data.message);
|
|
} else if (data.type === 'hide-navbar') {
|
|
NavbarManager.hide();
|
|
} else if (data.type === 'show-navbar') {
|
|
NavbarManager.show();
|
|
}
|
|
}
|
|
window.addEventListener('message', handleMessage);
|
|
|
|
function handleContactsIframeRequest(message) {
|
|
switch (message) {
|
|
case 'back':
|
|
var contactsIframe = document.getElementById('iframe-contacts');
|
|
// disable the function of receiving the messages posted from the iframe
|
|
contactsIframe.contentWindow.history.pushState(null, null,
|
|
'/contacts/index.html');
|
|
Navigation.showCalllog();
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* === Bluetooth Support === */
|
|
function btCommandHandler(message) {
|
|
var command = message.command;
|
|
var isAtd = command.startsWith('ATD');
|
|
|
|
// Not a dialing request
|
|
if (command !== 'BLDN' && !isAtd) {
|
|
return;
|
|
}
|
|
|
|
// Dialing a specific number
|
|
if (isAtd && command[3] !== '>') {
|
|
var phoneNumber = command.substring(3);
|
|
LazyLoader.load(['/shared/js/sim_settings_helper.js'], function() {
|
|
SimSettingsHelper.getCardIndexFrom('outgoingCall',
|
|
function(defaultCardIndex) {
|
|
if (defaultCardIndex === SimSettingsHelper.ALWAYS_ASK_OPTION_VALUE) {
|
|
LazyLoader.load(['/shared/js/component_utils.js',
|
|
'/shared/elements/gaia_sim_picker/script.js'],
|
|
function() {
|
|
var simPicker = document.getElementById('sim-picker');
|
|
simPicker.getOrPick(defaultCardIndex, phoneNumber, function(ci) {
|
|
CallHandler.call(phoneNumber, ci);
|
|
});
|
|
// Show the dialer so the user can select the SIM.
|
|
navigator.mozApps.getSelf().onsuccess = function(selfEvt) {
|
|
var app = selfEvt.target.result;
|
|
app.launch('dialer');
|
|
};
|
|
});
|
|
} else {
|
|
CallHandler.call(phoneNumber, defaultCardIndex);
|
|
}
|
|
});
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Dialing from the call log
|
|
// ATD>3 means we have to call the 3rd recent number.
|
|
var position = isAtd ? parseInt(command.substring(4), 10) : 1;
|
|
CallLogDBManager.getGroupAtPosition(
|
|
position, 'lastEntryDate', true, 'dialing',
|
|
function(result) {
|
|
if (result && (typeof result === 'object') && result.number) {
|
|
LazyLoader.load(['/shared/js/sim_settings_helper.js'], function() {
|
|
SimSettingsHelper.getCardIndexFrom('outgoingCall', function(ci) {
|
|
// If the default outgoing call SIM is set to "Always ask", or is
|
|
// unset, we place this call on the SIM that was used the last time
|
|
// we were in a phone call with this number/contact.
|
|
if (ci === undefined || ci === null ||
|
|
ci == SimSettingsHelper.ALWAYS_ASK_OPTION_VALUE) {
|
|
ci = result.serviceId;
|
|
}
|
|
|
|
CallHandler.call(result.number, ci);
|
|
});
|
|
});
|
|
} else {
|
|
console.log('Could not get the group at: ' + position +
|
|
'. Error: ' + result);
|
|
}
|
|
});
|
|
}
|
|
|
|
/* === Calls === */
|
|
function call(number, cardIndex) {
|
|
if (engineeringModeKey && number === engineeringModeKey) {
|
|
var activity = new MozActivity({
|
|
name: 'internal-system-engineering-mode'
|
|
});
|
|
activity.onerror = function() {
|
|
console.log('Could not launch engineering mode');
|
|
};
|
|
return;
|
|
}
|
|
|
|
if (MmiManager.isImei(number)) {
|
|
MmiManager.showImei();
|
|
|
|
// Clearing the code from the dialer screen gives the user immediate
|
|
// feedback.
|
|
KeypadManager.updatePhoneNumber('', 'begin', true);
|
|
SuggestionBar.clear();
|
|
return;
|
|
}
|
|
|
|
var connected, disconnected;
|
|
connected = disconnected = function clearPhoneView() {
|
|
KeypadManager.updatePhoneNumber('', 'begin', true);
|
|
};
|
|
|
|
var oncall = function() {
|
|
SuggestionBar.hideOverlay();
|
|
SuggestionBar.clear();
|
|
};
|
|
|
|
LazyLoader.load(['/dialer/js/telephony_helper.js'], function() {
|
|
TelephonyHelper.call(
|
|
number, cardIndex, oncall, connected, disconnected
|
|
).catch(function() {
|
|
KeypadManager.updatePhoneNumber(number, 'begin', false);
|
|
});
|
|
});
|
|
}
|
|
|
|
/* === MMI === */
|
|
function onUssdReceived(evt) {
|
|
var lock = null;
|
|
var safetyId;
|
|
|
|
function releaseWakeLock() {
|
|
if (lock) {
|
|
lock.unlock();
|
|
lock = null;
|
|
clearTimeout(safetyId);
|
|
}
|
|
}
|
|
|
|
if (document.hidden) {
|
|
lock = navigator.requestWakeLock('high-priority');
|
|
safetyId = setTimeout(releaseWakeLock, 30000);
|
|
document.addEventListener('visibilitychange', releaseWakeLock);
|
|
}
|
|
|
|
if (!document.hidden || evt.session) {
|
|
MmiManager.handleMMIReceived(evt.message, evt.session, evt.serviceId);
|
|
} else if (evt.message) {
|
|
/* If the dialer is not visible and the session ends with this message
|
|
* then this is most likely an unsollicited message. To prevent
|
|
* interrupting the user we post a notification for it instead of
|
|
* displaying the dialer UI. */
|
|
MmiManager.sendNotification(evt.message, evt.serviceId)
|
|
.then(releaseWakeLock);
|
|
} else {
|
|
releaseWakeLock();
|
|
}
|
|
}
|
|
|
|
function init() {
|
|
LazyLoader.load(['/shared/js/mobile_operator.js',
|
|
'/dialer/js/mmi.js',
|
|
'/dialer/js/mmi_ui.js',
|
|
'/shared/style/progress_activity.css',
|
|
'/dialer/style/mmi.css'], function() {
|
|
|
|
if (window.navigator.mozSetMessageHandler) {
|
|
window.navigator.mozSetMessageHandler('telephony-call-ended',
|
|
callEnded);
|
|
window.navigator.mozSetMessageHandler('activity', handleActivity);
|
|
window.navigator.mozSetMessageHandler('notification',
|
|
handleNotification);
|
|
window.navigator.mozSetMessageHandler('bluetooth-dialer-command',
|
|
btCommandHandler);
|
|
|
|
window.navigator.mozSetMessageHandler('ussd-received', onUssdReceived);
|
|
}
|
|
});
|
|
LazyLoader.load('/shared/js/settings_listener.js', function() {
|
|
SettingsListener.observe('engineering-mode.key', null, function(value) {
|
|
engineeringModeKey = value || null;
|
|
});
|
|
});
|
|
}
|
|
|
|
return {
|
|
init: init,
|
|
call: call
|
|
};
|
|
})();
|
|
|
|
// Listening to the keyboard being shown
|
|
// Waiting for issue 787444 being fixed
|
|
window.onresize = function(e) {
|
|
if (window.innerHeight < 440) {
|
|
NavbarManager.hide();
|
|
} else {
|
|
NavbarManager.show();
|
|
}
|
|
};
|