438 lines
13 KiB
JavaScript
Executable file
438 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 &&
|
|
document.documentElement.dataset.vulpesLayout !== 'compact') {
|
|
NavbarManager.hide();
|
|
} else {
|
|
NavbarManager.show();
|
|
}
|
|
};
|