Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,5 @@
The contents of these fake contacts are licensed under the Creative Commons Attribution-Share Alike 3.0 United States License.
Original source attributed to: Fake Name Generator (http://www.fakenamegenerator.com/)
For more information, please see http://creativecommons.org/licenses/by-sa/3.0/us/.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,33 @@
{
"data": [
{
"name": ["DJ Trasto"],
"givenName": ["DJ"],
"familyName": ["Trasto"],
"category": ["twitter"],
"bday": "1979-11-02"
},
{
"name": ["Armin van Beer"],
"givenName": ["Armin"],
"familyName": ["van Beer"],
"category": ["facebook","twitter"],
"org": ["State of Web"],
"bday": "1974-03-15"
},
{
"name": ["Spaniard Web Mafia"],
"givenName": ["Spaniard"],
"familyName": ["Web Mafia"],
"category": ["twitter"],
"org": ["Libraries.JS"]
},
{
"name": ["David Siestta"],
"givenName": ["David"],
"familyName": ["Siestta"],
"category": ["facebook"],
"bday": "1980-04-20"
}
]
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

150
gaia/dev_apps/uitest/index.html Executable file
View file

@ -0,0 +1,150 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<meta charset="utf-8">
<title>UI tests</title>
<!-- We don't need localization in this app -->
<link rel="stylesheet" type="text/css" href="style/uitest.css">
<link rel="stylesheet" type="text/css" href="style/tabs.css" >
<link rel="stylesheet" type="text/css" href="style/lists.css" >
<link rel="stylesheet" type="text/css" href="shared/style/lists.css">
<!-- Gaia Components -->
<link rel="stylesheet" href="app://theme.gaiamobile.org/shared/elements/gaia-theme/style.css">
<link rel="stylesheet" href="shared/elements/gaia-icons/gaia-icons.css">
<!-- Gaia Components -->
<script src="shared/elements/config.js"></script>
<script src="shared/elements/gaia-header/dist/gaia-header.js"></script>
<script type="text/javascript" src="js/uitest.js"></script>
<!-- <script src="shared/js/mime_mapper.js"></script> -->
<!-- <script src="shared/js/settings_listener.js"></script> -->
<!-- <script src="shared/js/download/download_formatter.js"></script> -->
<!-- <script src="shared/js/download/download_helper.js"></script> -->
<!-- <script src="shared/js/download/download_store.js"></script> -->
<script defer src="shared/js/lazy_loader.js"></script>
<script defer src="shared/js/accessibility_helper.js"></script>
</head>
<body class="theme-productivity">
<div class="panel list-panel">
<div id="UI-tests" class="page">
<section role="region">
<gaia-header>
<h1>UI Tests</h1>
</gaia-header>
</section>
<section data-type="list">
<ul class="sublist">
<li><a href="#test=UI/alert">Alert/Prompt</a></li>
<li><a href="#test=UI/canvas">Canvas Tag</a></li>
<li><a href="#test=UI/contextmenu">Contextmenu</a></li>
<li><a href="#test=UI/css_dimension">CSS dimension</a></li>
<li><a href="#test=UI/empty">Empty</a></li>
<li><a href="#test=UI/fullscreen">mozRequestFullScreen</a></li>
<li><a href="#test=UI/fullscreen_controls">Fullscreen Ctr</a></li>
<li><a href="#test=UI/keyboard">Keyboard</a></li>
<li><a href="#test=UI/newnotification">new Notification()</a></li>
<li><a href="#test=UI/notification">mozNotification</a></li>
<li><a href="#test=UI/open">window.open</a></li>
<li><a href="#test=UI/scrollbar">Scroll bar</a></li>
<li><a href="#test=UI/select">Select</a></li>
</ul>
</section>
</div>
<div id="API-tests" class="page invisible">
<section role="region">
<gaia-header>
<h1>API Tests</h1>
</gaia-header>
</section>
<section data-type="list">
<ul class="sublist">
<li><a href="#test=API/audiotag">audio tag</a></li>
<li><a href="#test=API/browseractivities">Browser Activities</a></li>
<li><a href="#test=API/composeemail">Compose Email</a></li>
<li><a href="#test=API/contacts">Contacts</a></li>
<li><a href="#test=API/copypaste">Copy Paste</a></li>
<li><a href="#test=API/csp">CSP Warning</a></li>
<li><a href="#test=API/dialnumber">Dial Number</a></li>
<li><a href="#test=API/downloads">Downloads</a></li>
<li><a href="#test=API/geolocation">Geolocation</a></li>
<li><a href="#test=API/getusermedia">getUserMedia</a></li>
<li><a href="#test=API/httpauthentication">HTTP Auth</a></li>
<li><a href="#test=API/fxa" id="mozId-fxa">Firefox Accounts mozId</a></li>
<li><a href="#test=API/identity" id="mozId-persona">Persona mozId</a></li>
<li><a href="#test=API/identity-get" id="mozId-persona-get">Persona mozId.get</a></li>
<li><a href="#test=API/inlineactivities">Inline Activities</a></li>
<li><a href="#test=API/multiactivities">Multi Activities</a></li>
<li><a href="#test=API/openaudio">Open Audio</a></li>
<li><a href="#test=API/openvideo">Open Video</a></li>
<li><a href="#test=API/orientation">mozLockOrientation</a></li>
<li><a href="#test=API/pay">navigator.mozPay</a></li>
<li><a href="#test=API/pickphoto">Pick Photo</a></li>
<li><a href="#test=API/picktype">Pick Photo/Video</a></li>
<li><a href="#test=API/pickvideo">Pick Video</a></li>
<li><a href="#test=API/pickdownload">Pick Download</a></li>
<li><a href="#test=API/presentation_api">Presentation API</a></li>
<li><a href="#test=API/savebookmark">Save bookmark</a></li>
<li><a href="#test=API/sendsms">Send SMS</a></li>
<li><a href="#test=API/shareimage">Share Image</a></li>
<li><a href="#test=API/shareurl">Share URL</a></li>
<li><a href="#test=API/viewphoto">View Photo</a></li>
<li><a href="#test=API/search">Search keyword</a></li>
<li><a href="#test=API/secure_element">Secure Element (Wallet)</a><li>
</ul>
</section>
</div>
<div id="HW-tests" class="page invisible">
<section role="region">
<gaia-header>
<h1 class="header-title">HW Tests</h1>
</gaia-header>
</section>
<section data-type="list">
<ul class="sublist">
<li><a href="#test=HW/battery">Battery</a></li>
<li><a href="#test=HW/bluetooth">Bluetooth</a></li>
<li><a href="#test=HW/camera">Camera</a></li>
<li><a href="#test=HW/fmradio">FM radio</a></li>
<li><a href="#test=HW/headphone">Headphone</a></li>
<li><a href="#test=HW/lcd">LCD</a></li>
<li><a href="#test=HW/physicalkeys">Physical keys</a></li>
<li><a href="#test=HW/radio">Radio information</a></li>
<li><a href="#test=HW/ringer">Ringer</a></li>
<li><a href="#test=HW/sdcards">SD cards</a></li>
<li><a href="#test=HW/sensors">Sensors</a></li>
<li><a href="#test=HW/touchscreen">Touch screen</a></li>
<li><a href="#test=HW/vibrator">Vibrator</a></li>
<li><a href="#test=HW/wifi">Wi-Fi</a></li>
</ul>
</section>
</div>
<div id="tabs" class="tabs">
<ul role="tablist" class="bb-tablist" data-items="3">
<li id="panel1" role="presentation">
<a href="#UI" id="UI" role="tab" aria-controls="UIpanel">UI</a>
<div id="UIpanel" class="bb-tabpanel" role="tabpanel" aria-labelledby="UI"></div>
</li>
<li id="panel2" role="presentation">
<a href="#API" id="API" role="tab" aria-controls="APIpanel">API</a>
<div id="APIpanel" class="bb-tabpanel" role="tabpanel" aria-labelledby="API"></div>
</li>
<li id="panel3" role="presentation">
<a href="#HW" id="HW" role="tab" aria-controls="HWpanel">HW</a>
<div id="HWpanel" class="bb-tabpanel" role="tabpanel" aria-labelledby="HW"></div>
</li>
</ul>
</div>
</div>
<div id="test-panel" class="panel test-panel">
<section role="region">
<gaia-header id="test-panel-header" action="back">
<h1 id="test-panel-title" class="header-title"></h1>
</gaia-header>
</section>
<iframe id="test-iframe" mozallowfullscreen="true"></iframe>
</div>
</body>
</html>

View file

@ -0,0 +1,20 @@
'use strict';
var clickHandlers = {
'play': function play() {
var src = this.dataset.src;
var ringtonePlayer = new Audio();
ringtonePlayer.loop = true;
var selectedSound = '../../data/ringtones/' + src;
ringtonePlayer.src = selectedSound;
ringtonePlayer.play();
window.setTimeout(function _pauseRingtone() {
ringtonePlayer.pause();
}, 20000);
}
};
document.body.addEventListener('click', function(evt) {
if (clickHandlers[evt.target.id || evt.target.dataset.fn])
clickHandlers[evt.target.id || evt.target.dataset.fn].call(evt.target, evt);
});

View file

@ -0,0 +1,15 @@
'use strict';
var clickHandlers = {
'go': function _go() {
var URL = document.getElementById('URL').value;
var a = new MozActivity({ name: 'view', data: {type: 'url', url: URL }});
a.onsuccess = function() { alert('Success!'); };
a.onerror = function() { alert('Failure going to URL'); };
}
};
document.body.addEventListener('click', function(evt) {
if (clickHandlers[evt.target.id || evt.target.dataset.fn])
clickHandlers[evt.target.id || evt.target.dataset.fn].call(this, evt);
});

View file

@ -0,0 +1,12 @@
var composeEmail = document.querySelector('#compose-email');
if (composeEmail) {
composeEmail.onclick = function() {
var createEmail = new MozActivity({
name: 'new', // Possibly compose-mail in future versions
data: {
type: 'mail',
url: 'mailto:example@example.org'
}
});
};
}

View file

@ -0,0 +1,370 @@
'use stricts';
/**
* Just a couple of testing tools for the Contacts app.
*
* Right now, it just allows you to insert a large number of fake contacts
* into the database, and then clear the database.
*/
var ContactsTest = {
get loadButton() {
delete this.loadButton;
return this.loadButton = document.getElementById('insert-contacts');
},
get clearButton() {
delete this.clearButton;
return this.clearButton = document.getElementById('clear-contacts');
},
get getButton() {
delete this.getButton;
return this.getButton = document.getElementById('get-contacts');
},
get pickActivityButton() {
delete this.pickActivityButton;
return this.pickActivityButton = document.getElementById('activities-pick');
},
get newActivityButton() {
delete this.newActivityButton;
return this.newActivityButton = document.getElementById('activities-new');
},
get updateExistingActivityButton() {
delete this.updateExistingActivityButton;
return this.updateExistingActivityButton =
document.getElementById('activities-update');
},
get updateExistingActivityEmailButton() {
delete this.updateExistingActivityEmailButton;
return this.updateExistingActivityEmailButton =
document.getElementById('activities-update-email');
},
get updateExistingActivityEmailPhoneButton() {
delete this.updateExistingActivityEmailPhoneButton;
return this.updateExistingActivityEmailPhoneButton =
document.getElementById('activities-update-email-phone');
},
get newWithDataActivityButton() {
delete this.newWithDataActivityButton;
return this.newWithDataActivityButton =
document.getElementById('activities-new-data');
},
get insertSocialContacts() {
delete this.insertSocialContacts;
return this.insertSocialContacts =
document.getElementById('insert-social-contacts');
},
init: function ct_init() {
this.loadButton.addEventListener('click', this.loadContacts.bind(this));
this.clearButton.addEventListener('click', this.clearContacts.bind(this));
this.getButton.addEventListener('click', this.getContacts.bind(this));
this.pickActivityButton.addEventListener('click',
this.pickActivity.bind(this));
this.newActivityButton.addEventListener('click',
this.newActivity.bind(this));
this.updateExistingActivityButton.addEventListener('click',
this.updateExistingActivity.bind(this));
this.updateExistingActivityEmailButton.addEventListener('click',
this.updateExistingActivityEmail.bind(this));
this.updateExistingActivityEmailPhoneButton.addEventListener('click',
this.updateExistingActivityEmailPhone.bind(this));
this.newWithDataActivityButton.addEventListener('click',
this.newWithDataActivity.bind(this));
this.insertSocialContacts.addEventListener('click',
this.finsertSocialContacts.bind(this));
},
uninit: function ct_uninit() {
this.loadButton.removeEventListener('click', this.loadContacts.bind(this));
this.clearButton.removeEventListener('click',
this.clearContacts.bind(this));
this.getButton.removeEventListener('click', this.getContacts.bind(this));
this.newActivityButton.removeEventListener('click',
this.newActivity.bind(this));
this.updateExistingActivityButton.removeEventListener('click',
this.updateExistingActivity.bind(this));
},
clearContacts: function ct_clearContacts() {
if (!confirm('This will wipe out ALL of the contacts in the database. ' +
'Are you sure?'))
return;
// Ok, we're really doing this.
var req = window.navigator.mozContacts.clear();
req.onsuccess = function() {
alert('Contacts deleted.');
};
req.onerror = function() {
alert('Problem deleting contacts');
};
},
getContacts: function ct_getContacts() {
var options = {
sortBy: 'familyName',
sortOrder: 'ascending'
};
var start = new Date();
var req = window.navigator.mozContacts.find(options);
req.onsuccess = function() {
var duration = new Date() - start;
alert('Contacts received: ' + duration + 'msec');
};
req.onerror = function() {
alert('Problem receiving contacts');
};
},
setContactId: function ct_setContactId(id) {
this.contactId = id;
},
getContactId: function ct_getContactId() {
return this.contactId;
},
pickActivity: function ct_pickActivity() {
var activity = new MozActivity({
name: 'pick',
data: {
type: 'webcontacts/contact'
}
});
var self = this;
activity.onsuccess = function() {
var number = this.result.number;
document.getElementById('activities-result').innerHTML =
'Picked contact with number: ' + number;
};
activity.onerror = function() {
document.getElementById('activities-result').innerHTML =
'Activity canceled';
};
},
newActivity: function ct_newActivity() {
var activity = new MozActivity({
name: 'new',
data: {
type: 'webcontacts/contact'
}
});
var self = this;
activity.onsuccess = function() {
var contact = this.result.contact;
document.getElementById('activities-result').innerHTML =
'New contact' + ' create with id: ' + contact.id;
self.setContactId(contact.id);
};
activity.onerror = function() {
document.getElementById('activities-result').innerHTML =
'Activity canceled';
};
},
updateExistingActivityEmail: function ct_updateExistingActivityEmail() {
var activity = new MozActivity({
name: 'update',
data: {
type: 'webcontacts/contact',
params: {
'email': 'test@test.com'
}
}
});
var self = this;
activity.onsuccess = function() {
var contact = this.result.contact;
document.getElementById('activities-result').innerHTML =
'updated contact' + ' update with id: ' + contact.id;
self.setContactId(contact.id);
};
activity.onerror = function() {
document.getElementById('activities-result').innerHTML =
'Activity canceled';
};
},
updateExistingActivityEmailPhone: function() {
var activity = new MozActivity({
name: 'update',
data: {
type: 'webcontacts/contact',
params: {
'email': 'test@test.com',
'tel': '21312132'
}
}
});
var self = this;
activity.onsuccess = function() {
var contact = this.result.contact;
document.getElementById('activities-result').innerHTML =
'updated contact' + ' update with id: ' + contact.id;
self.setContactId(contact.id);
};
activity.onerror = function() {
document.getElementById('activities-result').innerHTML =
'Activity canceled';
};
},
updateExistingActivity: function ct_updateExistingActivity() {
var activity = new MozActivity({
name: 'update',
data: {
type: 'webcontacts/contact',
params: {
'tel': '4087469720'
}
}
});
var self = this;
activity.onsuccess = function() {
var contact = this.result.contact;
document.getElementById('activities-result').innerHTML =
'updated contact' + ' update with id: ' + contact.id;
self.setContactId(contact.id);
};
activity.onerror = function() {
document.getElementById('activities-result').innerHTML =
'Activity canceled';
};
},
newWithDataActivity: function ct_newActivity() {
var activity = new MozActivity({
name: 'new',
data: {
type: 'webcontacts/contact',
params: {
'tel': '555-555-555',
'email': 'cool-hunter@telefonica.es',
'address': 'San Francisco',
'note': 'This is a note',
'giveName': 'John',
'familyName': 'Orlock',
'company': 'Lost Industries'
}
}
});
var self = this;
activity.onsuccess = function() {
var contact = this.result.contact;
document.getElementById('activities-result').innerHTML =
'New contact' + ' create with id: ' + contact.id;
self.setContactId(contact.id);
};
activity.onerror = function() {
document.getElementById('activities-result').innerHTML =
'Activity canceled';
};
},
loadContacts: function ct_loadContacts() {
var req = new XMLHttpRequest();
req.overrideMimeType('application/json');
req.open('GET', '../../data/fakecontacts/fakecontacts.json', true);
req.onreadystatechange = function() {
// We will get a 0 status if the app is in app://
if (req.readyState === 4 && (req.status === 200 ||
req.status === 0)) {
var contacts = JSON.parse(req.responseText);
this._insertContacts(contacts);
}
};
req.onreadystatechange = req.onreadystatechange.bind(this);
this.loadButton.disabled = true;
req.send(null);
},
_insertContacts: function ct_insertContacts(aContacts) {
var self = this;
var cs = new ContactsSaver(aContacts);
cs.start();
cs.onsuccess = function() {
self.loadButton.disabled = false;
};
cs.onsaved = function(n) {
self._setInsertionCount(n, aContacts.length);
};
cs.onerror = function(c, e) {
Components.utils.reportError('Could not add contact with name: ' +
c.familyName[0]);
};
},
_setInsertionCount: function ct__setInsertionCount(aSoFar, aTotal) {
var insertionEl = document.getElementById('insertion-count');
insertionEl.textContent = aSoFar + ' / ' + aTotal;
},
_error: function ct__error(c) {
Components.utils.reportError('Could not add contact with name: ' +
c.familyName[0]);
},
finsertSocialContacts: function ct_finsertSocialContacts() {
var xhr = new XMLHttpRequest();
xhr.overrideMimeType('application/json');
xhr.open('GET', '../../data/fakesocialcontacts/contacts_social.json', true);
xhr.onload = function(e) {
// We will get a 0 status if the app is in app://
if (xhr.status === 200 || xhr.status === 0) {
var cdata = JSON.parse(xhr.responseText);
this._insertSocialContacts(cdata.data);
}
};
xhr.onload = xhr.onload.bind(this);
xhr.send(null);
},
_insertSocialContacts: function ct__insertSocialContacts(contacts) {
var cs = new ContactsSaver(contacts);
cs.start();
var self = this;
cs.onsuccess = function() { window.alert('Added!'); };
cs.onerror = function(e, c) {
self._error(c);
};
}
};
window.addEventListener('load', ContactsTest.init.bind(ContactsTest));
window.addEventListener('unload', ContactsTest.uninit.bind(ContactsTest));

View file

@ -0,0 +1,47 @@
'use strict';
function ContactsSaver(data) {
this.data = data;
var next = 0;
var self = this;
this.start = function() {
saveContact(data[0]);
};
function saveContact(cdata) {
if (cdata.bday) {
cdata.bday = new Date(cdata.bday);
}
if (cdata.anniversary) {
cdata.anniversary = new Date(cdata.anniversary);
}
var contact = new mozContact(cdata);
var req = navigator.mozContacts.save(contact);
req.onsuccess = function(e) {
if (typeof self.onsaved === 'function') {
self.onsaved(next + 1);
}
continuee();
};
req.onerror = function(e) {
if (typeof self.onerror === 'function') {
self.onerror(self.data[next], e.target.error);
}
};
}
function continuee() {
next++;
if (next < self.data.length) {
saveContact(self.data[next]);
}
else {
// End has been reached
if (typeof self.onsuccess === 'function') {
self.onsuccess();
}
}
}
}

View file

@ -0,0 +1,11 @@
var dial = document.querySelector('#dial');
if (dial) {
dial.onclick = function() {
var call = new MozActivity({
name: 'dial',
data: {
number: '+46777888999'
}
});
};
}

View file

@ -0,0 +1,84 @@
'use strict';
var Downloads = function Downloads() {
var deleteButton, statusButton;
var download = null;
var init = function init() {
deleteButton = document.getElementById('downloadDelete');
deleteButton.addEventListener('click', onDelete);
statusButton = document.getElementById('downloadStatus');
statusButton.addEventListener('click', onStatus);
listen();
};
var onDelete = function onDelete(evt) {
LazyLoader.load(['/shared/js/download/download_helper.js'],
function helperLoaded() {
var request = DownloadHelper.remove(download);
request.onsuccess = function() {
alert('Download removed succesfully');
download = null;
deleteButton.disabled = true;
statusButton.disabled = true;
};
request.onerror = function(msg) {
alert('Error : ' + msg.message);
};
}
);
};
var onStatus = function onStatus(evt) {
if (download === null) {
alert('No download initiated');
} else {
var msg = 'Current download:\n';
msg += 'Total bytes: ' + download.totalBytes + '\n';
msg += 'Current bytes: ' + download.currentBytes + '\n';
msg += 'Url: ' + download.url + '\n';
msg += 'Path: ' + download.path + '\n';
try {
msg += 'Start time: ' + download.startTime + '\n';
} catch (e) {
msg += 'Start: unknown\n';
}
msg += 'Id: ' + download.id + '\n';
alert('Current download: ' + JSON.stringify(msg));
console.log(msg);
}
};
var listen = function listen() {
navigator.mozDownloadManager.ondownloadstart = downloadStartedListener;
};
var downloadStartedListener = function downloadStartedListener(evt) {
download = evt.download;
download.onstatechange = downloadChangeListener;
statusButton.disabled = false;
statusButton.textContent = 'Status: ' + download.state;
//console.log('State new download: ' + download.state);
};
var downloadChangeListener = function downloadChangeListener(evt) {
statusButton.textContent = 'Status: ' + download.state;
console.log('State change: ' + download.state);
if (download.state === 'succeeded') {
console.log('Download finished');
deleteButton.disabled = false;
}
};
return {
'init': init
};
}();
window.addEventListener('load', Downloads.init.bind(Downloads));

View file

@ -0,0 +1,118 @@
/**
* Tests for Firefox Accounts observer API
*
* navigator.mozId.watch(), .request(), and .logout().
*/
function unpackAssertion(assertion) {
var parts = assertion.split('.');
return {
header: atob(parts[0]),
claim: atob(parts[1]),
payload: atob(parts[3])
};
}
function FXATests() {
this._eventNum = 1;
}
FXATests.prototype = {
_setupCallbacks: function() {
if (this._running) {
return;
}
var self = this;
try {
navigator.mozId.watch({
wantIssuer: 'firefox-accounts',
onlogin: function(assertion) {
var unpacked = JSON.stringify(unpackAssertion(assertion), null, 2);
self.recordEvent('login', 'login',
{assertion: assertion, unpacked: unpacked});
},
onlogout: function() {
self.recordEvent('logout', 'logout');
},
onready: function() {
self.recordEvent('ready', 'ready');
},
onerror: function(error) {
self.recordEvent('error: ' + JSON.stringify(error), 'error');
}
});
} catch (error) {
this.recordEvent('error: ' + JSON.stringify(error), 'error');
}
},
/**
* Bind UI components
*/
_bindEvents: function() {
if (this._running) {
return;
}
var self = this;
var testElementHandlers = {
'request': function() {
navigator.mozId.request({
oncancel: function() {
self.recordEvent('cancel', 'cancel');
}
});
},
'logout': function() {
navigator.mozId.logout();
}
};
Object.keys(testElementHandlers).forEach(function(selector) {
document.getElementById(selector).addEventListener(
'click', testElementHandlers[selector]);
});
},
recordEvent: function(message, cklass, params) {
var li = document.createElement('li');
if (cklass) {
li.classList.add(cklass);
}
var events = document.getElementById('event-stream');
var html = message;
if (typeof params === 'object') {
Object.keys(params).forEach(function(key) {
html += '<div>' + key + ':</div>';
html += '<div class="' + key + '">' + params[key] + '</div>';
});
}
li.innerHTML = html;
events.appendChild(li);
this._eventNum += 1;
},
init: function() {
this._setupCallbacks();
this._bindEvents();
this._running = true;
this.recordEvent('Starting. Wait for "ready" message.');
},
};
window.addEventListener('DOMContentLoaded', function() {
var fxaTests = new FXATests();
fxaTests.init();
}, false);

View file

@ -0,0 +1,22 @@
function Location(position)//location function is defining with parameter
{
//Specifies the longitude estimate in decimal degrees.
//The value range is [-180.00, +180.00].
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
//latitude value is defining in label element where id is lati
document.getElementById('lati').innerHTML = latitude;
document.getElementById('longi').innerHTML = longitude;
}
document.getElementById('submit').addEventListener('click',
function findLocation() {
//checking browser compatibility
if (navigator.geolocation)
{
//getCurrentPosition method retrieve
//the current geographic location of the user
navigator.geolocation.getCurrentPosition(Location);
}
}
);

View file

@ -0,0 +1,220 @@
'use stricts';
// This is an indivisual gUM test item, may be audio, video, or both
function gUMItem() {
var video_status = false;
var audio_status = false;
var capturing = false;
var constrain;
var media;
var video_frame;
var video;
var snapshots_frames;
var audio;
var startButtons;
var stopButtons;
var snapshotButton;
var message;
var snapshots = [];
var saved_stream;
this.init = function(content, i) {
media = content.querySelector('[data-type="media"]');
video_frame = content.querySelector('[data-type="video-frame"]');
video = content.querySelector('video');
snapshots_frames = content.querySelector('[data-type="snapshots-frames"]');
audio = content.querySelector('audio');
startButtons = content.querySelector('[data-type="startbuttons"]');
stopButtons = content.querySelector('[data-type="stopbuttons"]');
snapshotButton = content.querySelector('[data-type="snapshotButton"]');
message = content.querySelector('[data-type="message"]');
// remove them first, we will add them back when we need them
media.removeChild(video_frame);
media.removeChild(audio);
// label button with index
content.querySelector('[data-type="startVideoButton"]').textContent += i;
content.querySelector('[data-type="startAudioButton"]').textContent += i;
content.querySelector('[data-type="startAudioVideoButton"]').
textContent += i;
content.querySelector('[data-type="startVideoButton"]').
addEventListener('click', startVideo);
content.querySelector('[data-type="startAudioButton"]').
addEventListener('click', startAudio);
content.querySelector('[data-type="startAudioVideoButton"]').
addEventListener('click', startAudioVideo);
content.querySelector('[data-type="startDoubleRequest"]').
addEventListener('click', startDoubleRequest);
content.querySelector('[data-type="stopButton"]').
addEventListener('click', stopMedia);
content.querySelector('[data-type="pauseButton"]').
addEventListener('click', pauseMedia);
content.querySelector('[data-type="snapshotButton"]').
addEventListener('click', startSnapshot);
};
function startVideo() {
startMedia({video: true});
}
function startAudioVideo() {
startMedia({video: true, audio: true});
}
function startAudio() {
startMedia({audio: true});
}
function startDoubleRequest() {
// empty request, just for prompt
function empty() {}
function success(stream) {
message.innerHTML = '<p class="success">Double prompt!</p>';
}
function error(err) {
message.innerHTML = '<p class="error">' + err + '</p>';
}
window.navigator.mozGetUserMedia({audio: true}, empty, error);
window.navigator.mozGetUserMedia({audio: true}, success, error);
}
function startMedia(param) {
constrain = param;
function success(stream) {
message.innerHTML = '<p class="success">Success!</p>';
stopButtons.style.display = 'block';
startButtons.style.display = 'none';
if ('video' in constrain) {
video_status = true;
media.appendChild(video_frame);
video.mozSrcObject = stream;
video.play();
snapshots_frames.innerHTML = '';
stopButtons.appendChild(snapshotButton);
}
if ('audio' in constrain) {
audio_status = true;
media.appendChild(audio);
audio.mozSrcObject = stream;
audio.play();
}
}
function error(err) {
if (video_status)
video_status = false;
message.innerHTML = '<p class="error">' + err + '</p>';
}
window.navigator.mozGetUserMedia(param, success, error);
}
function pauseMedia() {
if (saved_stream) {
if (video_status) {
video.mozSrcObject = saved_stream;
video.play();
} else if (audio_status) {
audio.mozSrcObject = saved_stream;
audio.play();
}
saved_stream = null;
} else {
if (video_status) {
video.pause();
saved_stream = video.mozSrcObject;
video.mozSrcObject = null;
} else if (audio_status) {
audio.pause();
saved_stream = audio.mozSrcObject;
audio.mozSrcObject = null;
}
}
}
function stopMedia() {
message.innerHTML = '';
if (video_status) {
video.mozSrcObject.stop();
video.mozSrcObject = null;
snapshots = [];
snapshots_frames.innerHTML = '';
media.removeChild(video_frame);
stopButtons.removeChild(snapshotButton);
snapshotButton.textContent = 'Snapshot';
capturing = false;
video_status = false;
}
if (audio_status) {
audio.mozSrcObject.stop();
audio.mozSrcObject = null;
media.removeChild(audio);
audio_status = false;
}
saved_stream = null;
stopButtons.style.display = 'none';
startButtons.style.display = 'block';
}
function startSnapshot() {
capturing = !capturing;
if (capturing) {
captureImage();
snapshotButton.textContent = 'Stop Snapshot';
} else {
snapshotButton.textContent = 'Snapshot';
}
}
function captureImage() {
if (video_status && capturing) {
//dump('Capturing len ' + snapshots.length + '\n');
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = video.videoWidth / 4;
canvas.height = video.videoHeight / 4;
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
if (snapshots.unshift(canvas) > 4)
snapshots.length = 4;
snapshots_frames.innerHTML = '';
for (var j = 0; j < snapshots.length; j++) {
snapshots_frames.appendChild(snapshots[j]);
}
setTimeout(captureImage, 2000);
}
}
}
// You can modify max_instances to test more than one gUM instance
function gUMTest() {
var max_instances = 2;
var gUMItems = [];
(function init() {
var contents = document.getElementById('contents');
for (var i = 0; i < max_instances; i++) {
gUMItems[i] = new gUMItem;
// display elements
// first copy one from template then modify it.
var template = document.getElementById('content_template');
var content = template.cloneNode(true);
content.id = 'content' + (i + 1);
content.classList.remove('hidden');
gUMItems[i].init(content, (i + 1));
contents.appendChild(content);
}
})();
}
window.addEventListener('load', gUMTest);

View file

@ -0,0 +1,111 @@
/**
* In these tests, we exercise the native navigator.mozId.get method.
*/
function getUnverifiedOk() {
return document.getElementById('unverified-ok').checked;
}
function getIssuerName() {
return document.getElementById('issuer-name').value.trim();
}
function unpackAssertion(assertion) {
var parts = assertion.split('.');
return {
header: atob(parts[0]),
claim: atob(parts[1]),
payload: atob(parts[3])
};
}
function IdentityTests() {
/**
* recordEvent: make a note in the event stream
*
* message is the main text of the note
* cklass is the css class to apply to the enclosing li
* params is an optional dictionary of strings to append as divs
*/
this._eventNum = 1;
this.recordEvent = function id_recordEvent(message, cklass, params) {
var li = document.createElement('li');
if (cklass) {
li.classList.add(cklass);
}
var events = document.getElementById('event-stream');
var html = message;
if (typeof params === 'object') {
Object.keys(params).forEach(function(key) {
html += '<div>' + key + ':</div>';
html += "<div class='" + key + "'>" + params[key] + '</div>';
});
}
li.innerHTML = html;
events.appendChild(li);
this._eventNum += 1;
};
this.gotAssertion = function id_gotAssertion(assertion) {
var result = {assertion: assertion};
if (assertion) {
result.unpacked = JSON.stringify(unpackAssertion(assertion), null, 2);
}
this.recordEvent('Assertion', 'assertion', result);
};
/**
* Bind UI components
*/
this._bindEvents = function id__bindEvents() {
if (this._running) return;
var gotAssertion = this.gotAssertion.bind(this);
var self = this;
var testElementHandlers = {
't-get': function() {
navigator.mozId.get(gotAssertion);
},
't-get-allowUnverified': function() {
navigator.mozId.get(gotAssertion, {
allowUnverified: getUnverifiedOk()
});
},
't-get-forceIssuer': function() {
navigator.mozId.get(gotAssertion, {
forceIssuer: getIssuerName()
});
},
't-get-forceIssuer-allowUnverified': function() {
navigator.mozId.get(gotAssertion, {
allowUnverified: getUnverifiedOk(),
forceIssuer: getIssuerName()
});
}
};
Object.keys(testElementHandlers).forEach(function(selector) {
document.getElementById(selector).addEventListener(
'click', testElementHandlers[selector]);
});
};
this.init = function id_init() {
this._bindEvents();
this._running = true;
this.recordEvent('Tests are ready');
};
}
window.addEventListener('DOMContentLoaded', function() {
var identityTests = new IdentityTests();
identityTests.init();
}, false);

View file

@ -0,0 +1,143 @@
/**
* The IdentityTests are meant to be exercised from marionette as part of the
* gaia-ui-tests suites.
*
* In these tests, we exercise the native navigator.mozId directly.
*/
function getUnverifiedOk() {
return document.getElementById('unverified-ok').checked;
}
function getIssuerName() {
return document.getElementById('issuer-name').value.trim();
}
function unpackAssertion(assertion) {
var parts = assertion.split('.');
return {
header: atob(parts[0]),
claim: atob(parts[1]),
payload: atob(parts[3])
};
}
function IdentityTests() {
/**
* recordEvent: make a note in the event stream
*
* message is the main text of the note
* cklass is the css class to apply to the enclosing li
* params is an optional dictionary of strings to append as divs
*/
this._eventNum = 1;
this.recordEvent = function id_recordEvent(message, cklass, params) {
var li = document.createElement('li');
if (cklass) {
li.classList.add(cklass);
}
var events = document.getElementById('event-stream');
var html = message;
if (typeof params === 'object') {
Object.keys(params).forEach(function(key) {
html += '<div>' + key + ':</div>';
html += "<div class='" + key + "'>" + params[key] + '</div>';
});
}
li.innerHTML = html;
events.appendChild(li);
this._eventNum += 1;
};
this._setupCallbacks = function id__setupCallbacks() {
if (this._running) return;
var self = this;
try {
navigator.mozId.watch({
onlogin: function(assertion) {
var unpacked = JSON.stringify(unpackAssertion(assertion), null, 2);
self.recordEvent('login', 'login',
{assertion: assertion, unpacked: unpacked});
},
onlogout: function() {
self.recordEvent('logout', 'logout');
},
onready: function() {
self.recordEvent('ready', 'ready');
}
});
} catch (err) {
this.recordEvent('Error: ' + err, 'error');
}
};
/**
* Bind UI components
*/
this._bindEvents = function id__bindEvents() {
if (this._running) return;
var self = this;
var testElementHandlers = {
't-request': function() {
navigator.mozId.request();
},
't-request-withOnCancel': function() {
navigator.mozId.request({oncancel: function() {
self.recordEvent('cancel', 'cancel');
}
});
},
't-request-allowUnverified': function() {
navigator.mozId.request({
allowUnverified: getUnverifiedOk()
});
},
't-request-forceIssuer': function() {
navigator.mozId.request({
forceIssuer: getIssuerName()
});
},
't-request-forceIssuer-allowUnverified': function() {
navigator.mozId.request({
allowUnverified: getUnverifiedOk(),
forceIssuer: getIssuerName()
});
},
't-logout': function() {
navigator.mozId.logout();
}
};
Object.keys(testElementHandlers).forEach(function(selector) {
document.getElementById(selector).addEventListener(
'click', testElementHandlers[selector]);
});
};
this.init = function id_init() {
this._setupCallbacks();
this._bindEvents();
this._running = true;
this.recordEvent('Ready to rock');
};
}
window.addEventListener('DOMContentLoaded', function() {
var identityTests = new IdentityTests();
identityTests.init();
}, false);

View file

@ -0,0 +1,17 @@
document.getElementById('go').onclick = function _go() {
var a = new MozActivity(
{
name: 'test-inline',
data: {
}
}
);
a.onsuccess = function() {
document.getElementById('result').textContent = this.result.text;
};
a.onerror = function() {
document.getElementById('result').textContent = '(canceled)';
};
};

View file

@ -0,0 +1,5 @@
document.getElementById('go').onclick = function _go() {
var a = new MozActivity({ name: 'test', data: {type: 'text'}});
a.onsuccess = function() { alert('Success!'); };
a.onerror = function() { alert('Failure.'); };
};

View file

@ -0,0 +1,82 @@
var open = document.getElementById('open');
var opensavefile = document.getElementById('opensavefile');
var opensaveblob = document.getElementById('opensaveblob');
open.hidden = true;
opensavefile.hidden = true;
opensaveblob.hidden = true;
open.onclick = function() {
var a = new MozActivity({
name: 'open',
data: {
type: 'audio/ogg',
blob: localblob,
title: 'jonobacon-freesoftwaresong2.ogg'
}
});
a.onsuccess = function() {
console.log('activity returns', JSON.stringify(a.result));
};
};
opensavefile.onclick = function() {
var a = new MozActivity({
name: 'open',
data: {
type: 'audio/ogg',
blob: localblob,
allowSave: true,
filename: 'downloads/uitest/jonobacon-freesoftwaresong2.ogg'
}
});
a.onsuccess = function() {
console.log('activity returns', JSON.stringify(a.result));
};
};
opensaveblob.onclick = function() {
var a = new MozActivity({
name: 'open',
data: {
type: 'audio/ogg',
blob: remoteblob,
allowSave: true,
filename: 'downloads/uitest/Back_In_Black-sample.ogg'
}
});
a.onsuccess = function() {
console.log('activity returns', JSON.stringify(a.result));
};
};
// The audio we want to open
var localblob;
var remoteblob;
var localURL = '../../data/audio/jonobacon-freesoftwaresong2.ogg';
var remoteURL = 'http://upload.wikimedia.org/wikipedia/en/4/45/' +
'ACDC_-_Back_In_Black-sample.ogg';
var localxhr = new XMLHttpRequest();
localxhr.open('GET', localURL);
localxhr.responseType = 'blob';
localxhr.send();
localxhr.onload = function() {
localblob = new Blob([localxhr.response], { type: 'audio/ogg' });
open.hidden = false;
opensavefile.hidden = false;
};
localxhr.onerror = function() {
console.log('Error loading test audio', localxhr.error.name);
};
var remotexhr = new XMLHttpRequest();
remotexhr.open('GET', remoteURL);
remotexhr.responseType = 'blob';
remotexhr.send();
remotexhr.onload = function() {
remoteblob = new Blob([remotexhr.response], { type: 'audio/ogg' });
opensaveblob.hidden = false;
};
remotexhr.onerror = function() {
console.log('Error loading test audio from network', remotexhr.error.name);
};

View file

@ -0,0 +1,49 @@
var open = document.getElementById('open');
var opensave = document.getElementById('opensave');
open.hidden = true;
opensave.hidden = true;
open.onclick = function() {
var a = new MozActivity({
name: 'open',
data: {
type: 'video/3gpp',
blob: videoblob,
title: 'Stapler'
}
});
a.onsuccess = function() {
console.log('activity returns', JSON.stringify(a.result));
};
};
opensave.onclick = function() {
var a = new MozActivity({
name: 'open',
data: {
type: 'video/3gpp',
blob: videoblob,
allowSave: true,
filename: 'downloads/uitest/stapler.3gp'
}
});
a.onsuccess = function() {
console.log('activity returns', JSON.stringify(a.result));
};
};
// The image we want to view
var videoblob;
var xhr = new XMLHttpRequest();
xhr.open('GET', '../../data/video/stapler.3gp');
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function() {
videoblob = new Blob([xhr.response], { type: 'video/3gpp' });
open.hidden = false;
opensave.hidden = false;
};
xhr.onerror = function() {
console.log('Error loading test video', xhr.error.name);
};

View file

@ -0,0 +1,56 @@
function orientationTest(evt) {
switch (evt.target.id) {
case 'lock1':
screen.mozLockOrientation(['portrait']);
break;
case 'lock2':
screen.mozLockOrientation(['landscape']);
break;
case 'lock3':
screen.mozLockOrientation(['portrait-primary']);
break;
case 'lock4':
screen.mozLockOrientation(['portrait-secondary']);
break;
case 'lock5':
screen.mozLockOrientation(['landscape-primary']);
break;
case 'lock6':
screen.mozLockOrientation(['landscape-secondary']);
break;
case 'lock7':
screen.mozLockOrientation(['portrait', 'landscape-primary']);
break;
case 'lock8':
screen.mozLockOrientation(['portrait', 'landscape-secondary']);
break;
case 'lock9':
screen.mozLockOrientation(['landscape', 'portrait-primary']);
break;
case 'lock10':
screen.mozLockOrientation(['landscape', 'portrait-secondary']);
break;
case 'lock11':
screen.mozLockOrientation(['portrait-primary', 'landscape-primary']);
break;
case 'lock12':
screen.mozLockOrientation(['portrait-secondary', 'landscape-primary']);
break;
case 'lock13':
screen.mozLockOrientation(['portrait-primary', 'landscape-secondary']);
break;
case 'lock14':
screen.mozLockOrientation(['portrait-secondary', 'landscape-secondary']);
break;
case 'unlock':
screen.mozUnlockOrientation();
break;
}
}
window.addEventListener('load', function() {
var buttons = document.getElementsByTagName('button');
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', orientationTest);
}
});

View file

@ -0,0 +1,63 @@
/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil -*- */
/* vim: set ft=javascript sw=2 ts=2 autoindent cindent expandtab: */
'use strict';
/**
Mock payment provider JWT
{ "iss": "323d34dc-b5cf-4822-8e47-6a4515dc74db",
"request": {
"description": "The forbidden fruit",
"id": "af1f960a-3f90-4e2d-a20f-d5170aee49f2",
"postbackURL": "https://inapp-pay-test.paas.allizom.org/mozpay/postback",
"productData": "localTransID=6fc8f207-da3f-440f-9977-eb613aae0a00",
"chargebackURL": "https://inapp-pay-test.paas.allizom.org/mozpay/chargeback",
"name": "Virtual Kiwi"
},
"typ": "tests/payments/pay/v1",
"aud": "ferjm.github.io/gaia-mock-payment-provider"
}
*/
const mockJWT = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIzMjNkMzRkYy1iNWNmLTQ4MjItOGU0Ny02YTQ1MTVkYzc0ZGIiLCJhdWQiOiJmZXJqbS5naXRodWIuaW8vZ2FpYS1tb2NrLXBheW1lbnQtcHJvdmlkZXIiLCJ0eXAiOiJ0ZXN0cy9wYXltZW50cy9wYXkvdjEiLCJyZXF1ZXN0Ijp7ImlkIjoiYWYxZjk2MGEtM2Y5MC00ZTJkLWEyMGYtZDUxNzBhZWU0OWYyIiwibmFtZSI6IlZpcnR1YWwgS2l3aSIsImRlc2NyaXB0aW9uIjoiVGhlIGZvcmJpZGRlbiBmcnVpdCIsInByb2R1Y3REYXRhIjoibG9jYWxUcmFuc0lEPTZmYzhmMjA3LWRhM2YtNDQwZi05OTc3LWViNjEzYWFlMGEwMCIsInBvc3RiYWNrVVJMIjoiaHR0cHM6Ly9pbmFwcC1wYXktdGVzdC5wYWFzLmFsbGl6b20ub3JnL21venBheS9wb3N0YmFjayIsImNoYXJnZWJhY2tVUkwiOiJodHRwczovL2luYXBwLXBheS10ZXN0LnBhYXMuYWxsaXpvbS5vcmcvbW96cGF5L2NoYXJnZWJhY2sifX0.DlHejmKRlVPLYO-HVAYDzqOcv5eXMsVlpnozcADpnh4';
// Invalid typ JWT
const invalidJWT = 'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.IntcImF1ZFwiOiBcImNvbm5lY3QucWEtb3BlbnRlbC0wNC5oaS5pbmV0XCIsIFwiaXNzXCI6IFwiMzRYVjM3QkRSQkJGNEtaQ1M5UVVcIiwgXCJyZXF1ZXN0XCI6IHtcIm5hbWVcIjogXCJQaWNlIG9mIENha2VcIiwgXCJwcmljZVwiOiAxMC41LCBcInByaWNlVGllclwiOiAxLCBcInByb2R1Y3RkYXRhXCI6IFwidHJhbnNhY3Rpb25faWQ9MTJcIiwgXCJjdXJyZW5jeUNvZGVcIjogXCJVU0RcIiwgXCJkZXNjcmlwdGlvblwiOiBcIlZpcnR1YWwgY2hvY29sYXRlIGNha2UgdG8gZmlsbCB5b3VyIHZpcnR1YWwgdHVtbXlcIn0sIFwiZXhwXCI6IDEzNDIwMDMwNzA1MTMsIFwiaWF0XCI6IDEzNDIwMDMwNzQxMTMsIFwidHlwXCI6IFwicGF5bWVudHMvaW5hcHAvdjFcIn0i.I5rFwoBtgyTltMJ_11rHOgcto-HdFbYlIOgVOVSlJe0';
var PayTests = {
init: function pt_init() {
window.addEventListener('DOMContentLoaded', function() {
var jwts = {
'test-pmpp': [mockJWT],
'test-invalid': [invalidJWT],
'test-nojwt': undefined,
'test-repeated': [mockJWT, mockJWT]
};
['test-pmpp',
'test-invalid',
'test-nojwt',
'test-repeated'].forEach(function(id) {
document.getElementById(id).addEventListener('click', function() {
PayTests.pay(jwts[id]);
});
});
});
},
pay: function pt_pay(JWTs) {
var request = navigator.mozPay(JWTs);
request.onsuccess = function onsuccess() {
document.getElementById('result').innerHTML = 'Payment success';
};
request.onerror = function onerror() {
console.log("Error " + request.error.name);
document.getElementById('result').innerHTML = 'Payment error ' +
request.error.name;
};
}
};
PayTests.init();

View file

@ -0,0 +1,13 @@
function pick(type) {
var data = {type: type};
var a = new MozActivity({ name: 'pick', data: data});
a.onsuccess = function(e) {
var result = document.getElementById('result');
result.textContent = a.result.name + ' ' + a.result.type + ' (' +
a.result.size + ')';
};
}
document.getElementById('b1').onclick = function() {
pick('application/*');
};

View file

@ -0,0 +1,25 @@
function pick(type, nocrop, width, height) {
var data = {type: type};
if (nocrop) data.nocrop = true;
if (width) data.width = width;
if (height) data.height = height;
var a = new MozActivity({ name: 'pick', data: data});
a.onsuccess = function(e) {
console.log('got blob of type', a.result.blob.type);
var url = URL.createObjectURL(a.result.blob);
var img = document.getElementById('result');
img.src = url;
img.onload = function() { URL.revokeObjectURL(url); };
};
a.onerror = function() { alert('Failure picking photo'); };
}
document.getElementById('b1').onclick = function() { pick('image/jpeg'); };
document.getElementById('b2').onclick = function() { pick('image/png'); };
document.getElementById('b3').onclick = function() {
pick(['image/jpeg', 'image/png']);
};
document.getElementById('b4').onclick = function() { pick('image/*'); };
document.getElementById('b5').onclick = function() { pick('image/*', true); };
document.getElementById('b6').onclick = function() { pick('image/*', false,
100, 100); };

View file

@ -0,0 +1,32 @@
function pick(type, nocrop, width, height) {
var data = {type: type};
if (nocrop) data.nocrop = true;
if (width) data.width = width;
if (height) data.height = height;
var a = new MozActivity({ name: 'pick', data: data});
a.onsuccess = function(e) {
console.log('got blob of type', a.result.blob.type);
var url = URL.createObjectURL(a.result.blob);
var img = document.getElementById('result');
img.src = url;
img.onload = function() { URL.revokeObjectURL(url); };
};
a.onerror = function() { alert('Failure picking'); };
}
document.getElementById('b1').onclick = function() {
pick(['video/*', 'image/*']);
};
document.getElementById('b2').onclick = function() {
pick(['image/*', 'video/*']);
};
document.getElementById('b3').onclick = function() {
pick(['video/*', 'image/jpg']);
};
document.getElementById('b4').onclick = function() {
pick(['video/*', 'image/png']);
};
document.getElementById('b5').onclick = function() {
pick(['video/3gpp', 'image/jpg']);
};

View file

@ -0,0 +1,18 @@
function pick(type, nocrop, width, height) {
var data = {type: type};
if (nocrop) data.nocrop = true;
if (width) data.width = width;
if (height) data.height = height;
var a = new MozActivity({ name: 'pick', data: data});
a.onsuccess = function(e) {
console.log('got blob of type', a.result.blob.type);
var url = URL.createObjectURL(a.result.blob);
var img = document.getElementById('result');
img.src = url;
img.onload = function() { URL.revokeObjectURL(url); };
};
a.onerror = function() { alert('Failure picking video'); };
}
document.getElementById('b1').onclick = function() { pick('video/3gpp'); };
document.getElementById('b2').onclick = function() { pick('video/*'); };

View file

@ -0,0 +1,48 @@
'use strict';
window.addEventListener('DOMContentLoaded', function() {
function log(aMsg) {
console.log('-*- mdns.js : ' + aMsg + '\n');
}
if (typeof navigator.mozPresentationDeviceInfo !== 'undefined') {
navigator.mozPresentationDeviceInfo.addEventListener('devicechange',
function(e) {
log('device changed');
getAll();
});
document.getElementById('discovery').onclick = function _discovery() {
log('discovery');
navigator.mozPresentationDeviceInfo.forceDiscovery();
getAll();
};
getAll();
}
function appendDevice(device) {
var node = document.createElement('li');
var textnode = document.createTextNode(device.name);
node.appendChild(textnode);
document.getElementById('devices').appendChild(node);
}
function clearDevices() {
var devNode = document.getElementById('devices');
while (devNode.firstChild) {
devNode.removeChild(devNode.firstChild);
}
}
function getAll() {
log('getAll');
navigator.mozPresentationDeviceInfo.getAll().then(function(devices) {
log('devices found: ' + devices.length);
clearDevices();
for (var device of devices) {
appendDevice(device);
}
});
}
});

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,14 @@
var search = document.querySelector('#search');
if (search) {
search.onclick = function() {
var search_area = document.querySelector('#search_area');
console.log('Search:' + search_area.value);
var searching = new MozActivity({
name: 'search',
data: {
type: 'text/plain',
keyword: search_area.value
}
});
};
}

View file

@ -0,0 +1,179 @@
'use strict';
/* globals Utils, AID, APDU */
var SIMAccessManager = {
ERROR_MSG: {
NOT_IDLE: 'WRONG SIM ACCESS STATE',
ACCESS_FAILED: 'FAILED TO ENABLE SIM ACCESS',
APPLETS_FAILED: 'FAILED TO GET APPLETS DATA'
},
SIM_ACCESS_STATES: {
DISABLED: 'disabled',
IDLE: 'idle',
BUSY: 'busy'
},
_simState: null,
_seSession: null,
start: function start() {
if(!navigator.seManager) {
return Promise.reject('Securel Element API not present');
}
return navigator.seManager.getSEReaders()
.then((readers) => {
return readers[0].openSession();
})
.then((session) => {
this._seSession = session;
this._simState = this.SIM_ACCESS_STATES.IDLE;
})
.catch(() => {
this._simState = this.SIM_ACCESS_STATES.DISABLED;
return Promise.reject(this.ERROR_MSG.ACCESS_FAILED);
});
},
stop: function stop() {
return this._seSession.closeAll()
.then(() => {
this._seSession = null;
this._simState = this.SIM_ACCESS_STATES.DISABLED;
});
},
getAppletsData: function getAppletsData() {
if(this._simState !== this.SIM_ACCESS_STATES.IDLE) {
return Promise.reject(this.ERROR_MSG.NOT_IDLE);
}
this._simState = this.SIM_ACCESS_STATES.BUSY;
return this._seSession.openLogicalChannel(AID.CRS)
.then((channel) => {
return channel.transmit(APDU.CRS.getStatusAll1st);
})
.then((resp) => {
var receivedData = new Uint8Array();
// we can get different responses, also propriatary
// using counter to not allow to try to query the SIM indifinately
var count = 0;
var condition = (resp) =>
(count++ > 10 || resp.sw1 === 0x90 && resp.sw2 === 0x00);
var action = (resp) => {
receivedData = Utils.joinUint8Arrays(receivedData, resp.data);
return resp.channel.transmit(APDU.CRS.getStatusAllNext)
};
return Utils.whilePromise(condition, action, resp)
.then((lastResp) => {
lastResp.channel.close();
this._simState = this.SIM_ACCESS_STATES.IDLE;
return Utils.joinUint8Arrays(receivedData, lastResp.data);
});
})
.catch((e) => {
return this._cleanup(this.ERROR_MSG.APPLETS_FAILED);
});
},
toggleApplet: function toggleApplet(on, aid) {
if(this._simState !== this.SIM_ACCESS_STATES.IDLE) {
return Promise.resolve(false);
}
this._simState = this.SIM_ACCESS_STATES.BUSY;
var apdu = on ? APDU.CRS.activateCLF(aid) : APDU.CRS.deactivateCLF(aid);
return this._seSession.openLogicalChannel(AID.CRS)
.then((channel) => channel.transmit(apdu))
.then((resp) => {
return resp.channel.close()
.then(() => {
this._simState = this.SIM_ACCESS_STATES.IDLE;
return resp.sw1 === 0x90 && resp.sw2 === 0x00;
});
});
},
_cleanup: function cleanup(message) {
this._simState = this.SIM_ACCESS_STATES.IDLE;
return Promise.reject(message);
}
};
var WalletDemo = {
init: function init() {
if(!navigator.seManager) {
this._updateStatus('Secure Element API not available.');
return;
}
SIMAccessManager.start()
.then(() => {
this._updateStatus('Init SIM access, getting applets from CRS');
return this._readDataRefreshUI();
})
.catch((error) => {
this._updateStatus('Init failed.', error);
SIMAccessManager.stop();
});
},
_readDataRefreshUI: function readDataRefreshUI() {
return SIMAccessManager.getAppletsData()
.then((appletsData) => {
// parsing and filtering to get payment enabled applets
var list = Utils.parseAppletsData(appletsData).filter((applet) => {
return applet.state === '1F01' || applet.state === '1F00';
});
this._updateStatus(list.length + ' applets read from SIM');
this._updateUI(list);
});
},
_updateUI: function updateUI(parsedApplets) {
var div = document.querySelector('#applets-view div');
div.innerHTML = '';
parsedApplets.forEach((applet) => {
var button = document.createElement('button');
var state = (applet.state === '1F01') ? 'active' : 'not active' ;
button.innerHTML = '<p>' + applet.aid + '</p>' +
'<p> contactless state: ' + state + '</p>';
button.addEventListener('click',
() => this._toggleApplet(applet.state === '1F00', applet.aid));
div.appendChild(button);
});
},
_toggleApplet: function toggleApplet(activate, aid) {
SIMAccessManager.toggleApplet(activate, aid)
.then((success) => {
if(success) {
this._updateStatus(aid + ' ' + ((activate) ? 'active' : 'not active'));
return this._readDataRefreshUI();
}
})
.catch((error) => {
this._updateStatus('Failed to toggle applets', error);
});
},
_updateStatus: function showStatus(status, error) {
console.log(status);
var selector = '.success';
if(error) {
console.log(error);
selector = '.error';
status += ', error: ' + error;
}
document.querySelector(selector).textContent = status;
},
};
window.addEventListener('load', () => WalletDemo.init());

View file

@ -0,0 +1,122 @@
'use strict';
/* exported Utils, APDU, AID */
const Utils = {
byteToHexString: function byteToHexString(uint8arr) {
if (!uint8arr) {
return '';
}
var hexStr = '';
for (var i = 0; i < uint8arr.length; i++) {
var hex = (uint8arr[i] & 0xff).toString(16);
hex = (hex.length === 1) ? '0' + hex : hex;
hexStr += hex;
}
return hexStr.toUpperCase();
},
hexStringToByte: function hexStringToByte(str) {
var a = [];
for(var i = 0, len = str.length; i < len; i+=2) {
a.push(parseInt(str.substr(i,2),16));
}
return new Uint8Array(a);
},
joinUint8Arrays: function joinUint8Arrays() {
var args = Array.prototype.slice.call(arguments);
var length = args.reduce(function(a, b) { return a + b.length; }, 0);
var out = new Uint8Array(length);
args.reduce(function(previousLen, buffer) {
out.set(buffer, previousLen);
return previousLen + buffer.length;
}, 0);
return out;
},
whilePromise: function whilePromise(condition, action, init) {
return new Promise((resolve, reject) => {
var loop = (value) => {
if (condition(value)) {
return resolve(value);
}
return action(value).then(loop).catch(reject);
};
loop(init);
});
},
parseAppletsData: function parseAppletsData(data) {
var list = [];
for(var i = 0, len = data.length; i < len;) {
if(data[i] === 0x61) {
var end = i+2 + data[i+1];
var appletData = data.subarray(i+2, end);
var applet = this._parseSingleApplet(appletData);
if(applet) {
list.push(applet);
}
i = end;
}
}
return list;
},
_parseSingleApplet: function _parseSingleApplet(data) {
// checking for AID tag
if (data[0] === 0x4F) {
var applet = {
aid: this.byteToHexString(data.subarray(2, 2 + data[1])),
state: this.byteToHexString(data.subarray(data[1] + 5))
};
return applet;
}
},
};
/*
CRS AID, TAGS and APDUs based on:
GlobalPlatform Card Technology Contactless Services Card Specification v2.2
- Amendment C Version 1.1.1
*/
const AID = {
CRS: Utils.hexStringToByte('A00000015143525300')
};
const APDU = {
CRS: {
getStatusAll1st: { cla: 0x80, ins: 0xF2, p1: 0x40, p2: 0x00,
data: new Uint8Array([
0x4F, 0x00, // applet AID, empty here
0x5C, 0x03, // tag list to be returned
0x4F, // AID
0x9F, 0x70 // applet life cycle state - first byte;
// contactless activation state - second byte
])
},
getStatusAllNext: { cla: 0x80, ins: 0xF2, p1: 0x40, p2: 0x01,
data: new Uint8Array([0x4F, 0x00, 0x5C, 0x03, 0x4F, 0x9F, 0x70])
},
activateCLF: (aid) => {
return { cla: 0x80, ins: 0xF0, p1: 0x01, p2: 0x01, data:
Utils.joinUint8Arrays([0x4F, 0x0F], Utils.hexStringToByte(aid))
};
},
deactivateCLF: (aid) => {
return { cla: 0x80, ins: 0xF0, p1: 0x01, p2: 0x00, data:
Utils.joinUint8Arrays([0x4F, 0x0F], Utils.hexStringToByte(aid))
};
},
}
};

View file

@ -0,0 +1,12 @@
var sendSMS = document.querySelector('#send-sms');
if (sendSMS) {
sendSMS.onclick = function() {
var sms = new MozActivity({
name: 'new', // Possible compose-sms in future versions
data: {
type: 'websms/sms',
number: '+46777888999'
}
});
};
}

View file

@ -0,0 +1,31 @@
var shareImage = document.querySelector("#share-image"),
imgToShare = document.querySelector("#image-to-share");
if (shareImage && imgToShare) {
shareImage.onclick = function () {
if(imgToShare.naturalWidth > 0) {
// Create dummy canvas
var blobCanvas = document.createElement("canvas");
blobCanvas.width = imgToShare.width;
blobCanvas.height = imgToShare.height;
// Get context and draw image
var blobCanvasContext = blobCanvas.getContext("2d");
blobCanvasContext.drawImage(imgToShare, 0, 0);
// Export to blob and share through a Web Activitiy
blobCanvas.toBlob(function (blob) {
var sharingImage = new MozActivity({
name: "share",
data: {
type: "image/*",
number: 1,
blobs: [blob]
}
});
});
}
else {
alert("Image failed to load, can't be shared");
}
}
}

View file

@ -0,0 +1,13 @@
var share = document.querySelector('#share');
if (share) {
share.onclick = function() {
var sharing = new MozActivity({
name: 'share',
data: {
type: 'url', // Possibly text/html in future versions,
number: 1,
url: 'http://www.mozilla.org'
}
});
};
}

View file

@ -0,0 +1,59 @@
// The image we want to view
var imageblob;
// Create an image from a canvas
var canvas = document.createElement('canvas');
canvas.width = 600;
canvas.height = 800;
var context = canvas.getContext('2d');
context.font = '20pt Arial';
context.fillStyle = 'red';
context.fillText('Hello World', 100, 100);
context.strokeStyle = 'blue';
context.lineWidth = 4;
context.strokeRect(0, 0, 600, 800);
canvas.toBlob(function(blob) {
imageblob = blob;
}, 'image/png');
document.getElementById('view').onclick = function() {
var a = new MozActivity({
name: 'open',
data: {
type: 'image/png',
blob: imageblob
}
});
a.onsuccess = function() {
console.log('activity returns', JSON.stringify(a.result));
};
};
document.getElementById('viewsave').onclick = function() {
var a = new MozActivity({
name: 'open',
data: {
type: 'image/png',
blob: imageblob,
allowSave: true,
filename: 'downloads/uitests/helloworldhello.png'
}
});
a.onsuccess = function() {
console.log('activity returns', JSON.stringify(a.result));
};
};
document.getElementById('viewError').onclick = function() {
var a = new MozActivity({
name: 'open',
data: {
type: 'image/jpeg',
blob: new Blob(['empty-image'], {'type': 'image/jpeg'})
}
});
a.onsuccess = function() {
console.log('activity returns', JSON.stringify(a.result));
};
};

View file

@ -0,0 +1,25 @@
'use strict';
function batteryTest() {
var battery = window.navigator.battery;
var charging = document.getElementById('charging');
var level = document.getElementById('level');
var chargingTime = document.getElementById('charging-time');
var disChargingTime = document.getElementById('discharging-time');
function update(evt) {
charging.textContent = battery.charging;
level.textContent = battery.level * 100;
chargingTime.textContent = battery.chargingTime;
disChargingTime.textContent = battery.dischargingTime;
}
battery.addEventListener('chargingchange', update);
battery.addEventListener('levelchange', update);
battery.addEventListener('onchargingtimechange', update);
battery.addEventListener('ondischargingtimechange', update);
update();
}
window.addEventListener('load', batteryTest);

View file

@ -0,0 +1,99 @@
'use strict';
function bluetoothTest() {
var bluetooth = window.navigator.mozBluetooth;
var settings = window.navigator.mozSettings;
var switchButton = document.getElementById('switch');
var state = document.getElementById('state');
var address = document.getElementById('address');
var version = document.getElementById('version');
var btHelper = new BluetoothHelper();
function update() {
var req = settings.createLock().get('bluetooth.enabled');
req.onsuccess = function() {
var isBluetoothEnabled = req.result['bluetooth.enabled'];
switchButton.checked = isBluetoothEnabled;
if (!isBluetoothEnabled) {
state.innerHTML = 'Off';
address.innerHTML = 'unknown';
}
else {
state.innerHTML = 'On';
if (!btHelper.v2) {
btHelper.getAddress(function bt_gotAddress(addr) {
if (isBluetoothEnabled) {
address.innerHTML = addr;
}
});
}
}
};
}
// Click on switch will only update settings and
// it takes some time for bluetooth hardware to turns on.
// That's why we should listen to 'enabled' event of bluetooth
function bluetoothSwitch() {
settings.createLock().set({'bluetooth.enabled': switchButton.checked});
// set enabled stat for BT APIv2
if (switchButton.checked) {
btHelper.enable();
} else {
btHelper.disable();
}
}
if (btHelper.v2) {
version.textContent = "v2";
bluetooth.addEventListener('attributechanged', (evt) => {
for (var i in evt.attrs) {
switch (evt.attrs[i]) {
case 'defaultAdapter':
var adapter = bluetooth.defaultAdapter;
if (adapter.address) { // for default On case
address.innerHTML = adapter.address;
}
adapter.addEventListener('attributechanged', (evt) => {
for (var i in evt.attrs) {
switch (evt.attrs[i]) {
case 'state':
if (adapter.state === 'enabled') {
switchButton.checked = true;
state.innerHTML = 'On';
} else if (adapter.state === 'disabled') {
switchButton.checked = false;
state.innerHTML = 'Off';
address.innerHTML = 'unknown';
}
break;
case 'address':
address.innerHTML = adapter.address;
break;
default:
break;
}
}
});
break;
default:
break;
}
}
});
} else {
version.textContent = "v1";
bluetooth.addEventListener('adapteradded', update);
bluetooth.addEventListener('enabled', update);
bluetooth.addEventListener('disabled', update);
}
// init
switchButton.addEventListener('click', bluetoothSwitch);
// Update bluetooth information in the first load
update();
}
window.addEventListener('load', bluetoothTest);

View file

@ -0,0 +1,19 @@
'use strict';
var clickHandlers = {
'camera': function() {
var activity = new MozActivity({
name: 'record',
data: {
type: 'photos'
}
});
}
};
document.body.addEventListener('click', function(evt) {
if (clickHandlers[evt.target.id]) {
clickHandlers[evt.target.id].call(this, evt);
}
});

View file

@ -0,0 +1,154 @@
'use strict';
function FMRadioTest() {
var messageText = document.getElementById('message');
var frequencyMin = document.getElementById('frequency-min');
var frequencyMax = document.getElementById('frequency-max');
var container = document.getElementById('container');
var controlPanel = document.getElementById('controlPanel');
var frequencyInput = document.getElementById('frequency');
var switchBtn = document.getElementById('switch');
var seekUpBtn = document.getElementById('seekUp');
var seekDownBtn = document.getElementById('seekDown');
var seekAndCancelBtn = document.getElementById('seekAndCancel');
if (!navigator.mozFMRadio) {
console.log('mozFMRadio not support');
container.hidden = true;
return;
}
var radio = navigator.mozFMRadio;
var prevFreq = radio.frequencyLowerBound;
var lock = false;
if (radio.enabled) {
prevFreq = radio.frequency;
}
switchBtn.textContent = radio.enabled;
frequencyMin.textContent = radio.frequencyLowerBound;
frequencyMax.textContent = radio.frequencyUpperBound;
controlPanel.hidden = !radio.enabled;
frequencyInput.value = prevFreq;
togglePanel();
toggleControlPanel();
radio.addEventListener('antennaavailablechange', togglePanel);
radio.addEventListener('frequencychange', frequencyChanged);
frequencyInput.addEventListener('change', setFrequency);
switchBtn.addEventListener('click', onclick_radioSwitch);
seekUpBtn.addEventListener('click', seek);
seekDownBtn.addEventListener('click', seek);
seekAndCancelBtn.addEventListener('click', seekAndCancel);
window.addEventListener('unload', uninit);
function logError() {
messageText.textContent = this.error.name;
}
// show/hide panels
function togglePanel() {
if (radio && radio.antennaAvailable) {
container.hidden = false;
messageText.textContent = '';
}
else {
container.hidden = true;
messageText.textContent = 'Headphone is required for FMRadio';
}
}
function toggleControlPanel() {
lock = false;
controlPanel.hidden = !radio.enabled;
if (radio.enabled) {
switchBtn.textContent = 'Stop';
}
else {
switchBtn.textContent = 'Start';
}
switchBtn.disabled = false;
}
function onclick_radioSwitch() {
if (lock) {
return;
}
// lock button until request is finished
lock = true;
switchBtn.disabled = true;
var req;
if (!radio.enabled) {
messageText.textContent = 'turning on FM, please wait...';
req = radio.enable(prevFreq);
}
else {
req = radio.disable();
}
req.onsuccess = req.onerror = function() {
toggleControlPanel();
if (this.error) {
messageText.textContent = this.error.name;
}
else {
messageText.textContent = '';
}
};
}
function frequencyChanged() {
console.log('freq changed');
frequencyInput.value = radio.frequency;
prevFreq = radio.frequency;
}
function setFrequency() {
var req = radio.setFrequency(frequencyInput.value);
req.onerror = logError;
}
function seek(evt) {
var req;
if (evt.target.id == 'seekUp') {
req = radio.seekUp();
}
else {
req = radio.seekDown();
}
req.onerror = logError;
}
function seekAndCancel(evt) {
var req = radio.seekUp();
console.log('seekUP()');
req.onsuccess = function() {
console.log('seekUP().onsuccess');
};
req.onerror = function() {
console.log('seekUP().onerror:' + this.error.name);
};
var cancel = radio.cancelSeek();
console.log('cancel()');
cancel.onsuccess = function() {
console.log('canelSeek().onsuccess');
};
cancel.onerror = function() {
console.log('cancelSeek().onerror:' + this.error.name);
};
}
function uninit() {
if (radio.enabled) {
radio.disable();
}
}
}
window.addEventListener('load', FMRadioTest);

View file

@ -0,0 +1,23 @@
'use strict';
function headphoneTest() {
var status_display = document.getElementById('status');
var acm = navigator.mozAudioChannelManager;
if (acm) {
acm.addEventListener('headphoneschange', update.bind(this));
}
else {
status_display.textContent = 'mozAudioChannelManager not found';
}
function update() {
if (acm.headphones) {
status_display.textContent = 'plugged';
}
else {
status_display.textContent = 'unpluged';
}
}
update();
}
window.addEventListener('load', headphoneTest);

View file

@ -0,0 +1,71 @@
'use strict';
var LCDTest = {
get fullscreenDiv() {
delete this.fullScreenDiv;
return this.fullScreenDiv = document.getElementById('fullscreen-div');
},
firstTimeHint: null,
init: function() {
document.body.addEventListener('click', this);
this.fullscreenDiv.addEventListener('click',
this.exitFullscreen.bind(this));
this.firstTimeHint = true;
},
enterFullscreen: function(color) {
this.fullscreenDiv.mozRequestFullScreen();
this.fullscreenDiv.classList.remove('invisible');
this.fullscreenDiv.classList.remove('red');
this.fullscreenDiv.classList.remove('green');
this.fullscreenDiv.classList.remove('blue');
this.fullscreenDiv.classList.remove('white');
this.fullscreenDiv.classList.remove('black');
this.fullscreenDiv.classList.add(color);
if (this.firstTimeHint) {
this.firstTimeHint = false;
alert('Tap screen again to exit fullscreen mode');
}
},
exitFullscreen: function() {
document.mozCancelFullScreen();
this.fullscreenDiv.classList.add('invisible');
},
turnOn: function() {
navigator.mozPower.screenEnabled = true;
// no longer need the lock
this.wakeLock.unlock();
},
// Only handle clicks on button, clicks on div is handled by exitFullscreen
handleEvent: function(evt) {
switch (evt.target.id) {
case 'red':
this.enterFullscreen('red');
break;
case 'green':
this.enterFullscreen('green');
break;
case 'blue':
this.enterFullscreen('blue');
break;
case 'white':
this.enterFullscreen('white');
break;
case 'black':
this.enterFullscreen('black');
break;
case 'off':
// We are going to shutdown the screen, this may lead to
// the sleep of CPU. Use wake lock to prevent from sleeping
// which cause setTimeout stop working.
this.wakeLock = window.navigator.requestWakeLock('screen');
setTimeout(this.turnOn.bind(this), 3000);
navigator.mozPower.screenEnabled = false;
break;
}
},
wakeLock: null
};
window.addEventListener('load', LCDTest.init.bind(LCDTest));

View file

@ -0,0 +1,26 @@
'use strict';
/*
var ringer = function callsHandler() {
var phoneSoundURL = new SettingsURL();
SettingsListener.observe('dialer.ringtone', '', function(value) {
ringtonePlayer.pause();
ringtonePlayer.src = phoneSoundURL.set(value);
});
var ringtonePlayer = ringtonePlayer;
ringtonePlayer = new Audio();
ringtonePlayer.mozAudioChannelType = 'ringer';
ringtonePlayer.src = phoneSoundURL.get();
ringtonePlayer.loop = false;
window.addEventListener('home', function (evt) {
evt.preventDefault();
ringtonePlayer.play();
});
window.addEventListener('click', function (evt) {
evt.stopPropagation();
ringtonePlayer.play();
});
}();
*/

View file

@ -0,0 +1,173 @@
'use strict';
function IMEI(serviceId) {
var IMEIText = document.getElementById('IMEI');
navigator.mozTelephony.dial('*#06#', serviceId).then(function(call) {
return call.result.then(function getIMEI(message) {
if (message && (message.serviceCode === 'scImei') &&
message.statusMessage) {
IMEIText.textContent = message.statusMessage;
}
});
});
}
// SIM card information such as ICCID, MSISDN
function iccInfo(mozIcc, parentContainer)
{
var messageText = parentContainer.querySelector('[data-type="icc-message"]');
var ICCIDText = parentContainer.querySelector('[data-type="ICCID"]');
var MSISDNText = parentContainer.querySelector('[data-type="MSISDN"]');
var container = parentContainer.querySelector('[data-type="icc-container"]');
mozIcc.addEventListener('cardstatechange', update_icc);
update_icc();
function update_icc() {
if (mozIcc.cardState == null ||
!mozIcc.iccInfo) {
container.hidden = true;
messageText.textContent = 'Airplane mode on';
}
else {
ICCIDText.textContent = mozIcc.iccInfo.iccid;
MSISDNText.textContent = mozIcc.iccInfo.msisdn || 'Unknown';
container.hidden = false;
messageText.textContent = '';
}
}
}
// data & voice network information
function mobileConnectionInfo(conn, parentContainer)
{
conn.addEventListener('datachange', update_data_network);
conn.addEventListener('voicechange', update_voice_network);
update_data_network();
update_voice_network();
function update_data_network() {
var container = parentContainer.
querySelector('[data-type="data-container"]');
var message = parentContainer.
querySelector('[data-type="data-message"]');
var result = update_network(conn.data, container, message);
}
function update_voice_network() {
var container = parentContainer.
querySelector('[data-type="voice-container"]');
var message = parentContainer.
querySelector('[data-type="voice-message"]');
var result = update_network(conn.voice, container, message);
}
function update_network(network, container, message) {
if (!conn || conn.radioState != 'enabled' ||
!network || !network.connected || network.emergencyCallsOnly) {
container.hidden = true;
message.textContent = 'Disconnect';
}
else {
container.querySelector('[data-type="network"]').textContent =
network.network.shortName;
container.querySelector('[data-type="LAC"]').textContent =
network.cell.gsmCellId;
container.querySelector('[data-type="CID"]').textContent =
network.cell.gsmLocationAreaCode;
container.querySelector('[data-type="strength"]').textContent =
network.relSignalStrength;
container.querySelector('[data-type="type"]').textContent =
network.type;
container.querySelector('[data-type="roaming"]').textContent =
network.roaming;
container.hidden = false;
message.textContent = '';
}
}
}
function radioTest() {
var iccIdIndex = [];
var icc_num = 0;
if (('mozIccManager' in navigator) &&
navigator.mozIccManager &&
('mozMobileConnections' in navigator) &&
navigator.mozMobileConnections.length > 0) {
var iccManager = navigator.mozIccManager;
// IMEI should be the same no matter which connection is used
IMEI(0);
var template = document.getElementById('connection-template');
template.hidden = true;
if (iccManager.iccIds.length > 0) {
for (var i = 0; i < iccManager.iccIds.length; i++) {
addIcc(iccManager.iccIds[i], i);
showInfo(iccManager.iccIds[i]);
}
} else {
document.getElementById('global-message').textContent =
'SIM card not found, insert SIM and turn off airplane mode';
}
iccManager.addEventListener('iccdetected', function(evt) {
document.getElementById('global-message').textContent = '';
addIcc(evt.iccId);
showInfo(evt.iccId);
});
iccManager.addEventListener('iccundetected', function(evt) {
removeIcc(evt.iccId);
});
}
else {
alert('navigator.mozIccManager or navigator.mozMobileConnections ' +
'not supported');
}
function showInfo(iccId) {
var i = iccIdIndex[iccId];
var connectionContainer = document.getElementById('connection#' + i);
// show ICC#
connectionContainer.querySelector('[data-type="SIM-number"]')
.textContent = i;
iccInfo(navigator.mozIccManager.getIccById(iccId), connectionContainer);
mobileConnectionInfo(navigator.mozMobileConnections[i],
connectionContainer);
}
function addIcc(iccId) {
var connectionContainer = document.getElementById('connection#' + icc_num);
if (!connectionContainer) {
// copy connection-template then modify it.
connectionContainer = template.cloneNode(true);
connectionContainer.id = 'connection#' + icc_num;
connectionContainer.hidden = false;
document.getElementById('content').appendChild(connectionContainer);
}
iccIdIndex[iccId] = icc_num;
icc_num++;
}
function removeIcc(iccId) {
var i = iccIdIndex[iccId];
if (i != null) {
iccIdIndex[iccId] = null;
// re-organize index
for (var key in iccIdIndex) {
if (iccIdIndex[key] >= i) {
iccIdIndex[key]--;
}
}
icc_num--;
}
}
}
window.addEventListener('load', radioTest);

View file

@ -0,0 +1,17 @@
'use strict';
var ringtonePlayer = new Audio();
// Get ringer file path from settings
var phoneSoundURL = new SettingsURL();
SettingsListener.observe('dialer.ringtone', '', function(value) {
ringtonePlayer.pause();
ringtonePlayer.src = phoneSoundURL.set(value);
});
document.body.addEventListener('click', function(evt) {
if (evt.target.id == 'ring') {
ringtonePlayer.play();
}
});

View file

@ -0,0 +1,85 @@
'use strict';
// Whenever the check button is clicked,
// we delete previously displayed result (if any) then show new result
function checkSDCards() {
var sdcards = navigator.getDeviceStorages('sdcard');
document.getElementById('numOfCards').textContent = sdcards.length;
// cardInfo collection
var cardsInfo = document.getElementById('cardsInfo');
// Clear last result
while (cardsInfo.firstChild) {
cardsInfo.removeChild(cardsInfo.firstChild);
}
// Show new result
sdcards.forEach(function showCards(card, index, cards) {
// To add a new SD cardInfo,
// first copy one from card_template then modify it.
var template = document.getElementById('card_template');
var cardInfo = template.cloneNode(true);
cardInfo.id = 'card' + index;
cardInfo.classList.remove('invisible');
var cardNo =
cardInfo.querySelector('#card' + index + ' > .no > span');
var cardStatus =
cardInfo.querySelector('#card' + index + ' > .status > span');
var cardSpace =
cardInfo.querySelector('#card' + index + ' > .space');
var cardSpaceTotal =
cardInfo.querySelector('#card' + index + ' > .space > .totalSpace');
var cardSpaceFree =
cardInfo.querySelector('#card' + index + ' > .space > .freeSpace');
var cardSpaceUsed =
cardInfo.querySelector('#card' + index + ' > .space > .usedSpace');
cardNo.textContent = index;
// Show availability and hide other infomation if not available
var reqAvailable = card.available();
reqAvailable.onsuccess = function() {
cardStatus.textContent = this.result;
if (this.result == 'shared' || this.result == 'unavailable') {
cardSpace.classList.add('invisible');
}
};
reqAvailable.onerror = function() {
cardStatus.textContent = 'Unable to get sdcard status' + this.error.name;
};
// Show space info.
// If the other space info is already updated, show total space
var reqFree = card.freeSpace();
reqFree.onsuccess = function() {
var spaceGB = this.result / Math.pow(10, 9);
cardSpaceFree.textContent = spaceGB;
if (cardSpaceTotal.textContent == '') {
cardSpaceTotal.textContent = spaceGB;
}
else {
cardSpaceTotal.textContent =
parseFloat(cardSpaceTotal.textContent) + spaceGB;
}
};
var reqUsed = card.usedSpace();
reqUsed.onsuccess = function() {
var spaceGB = this.result / Math.pow(10, 9);
cardSpaceUsed.textContent = spaceGB;
if (cardSpaceTotal.textContent == '') {
cardSpaceTotal.textContent = spaceGB;
}
else {
cardSpaceTotal.textContent =
parseFloat(cardSpaceTotal.textContent) + spaceGB;
}
};
cardsInfo.appendChild(cardInfo);
});
}
window.addEventListener('load', function() {
document.getElementById('check').addEventListener('click', checkSDCards);
});

View file

@ -0,0 +1,67 @@
'use strict';
function sensorTest() {
var interval = document.getElementById('interval');
var accelerationX = document.getElementById('acceleration-x');
var accelerationY = document.getElementById('acceleration-y');
var accelerationZ = document.getElementById('acceleration-z');
var accelerationGX = document.getElementById('acceleration-gravity-x');
var accelerationGY = document.getElementById('acceleration-gravity-y');
var accelerationGZ = document.getElementById('acceleration-gravity-z');
var rotAlpha = document.getElementById('rot-rate-alpha');
var rotBeta = document.getElementById('rot-rate-beta');
var rotGamma = document.getElementById('rot-rate-gamma');
var orientationAlpha = document.getElementById('orientation-alpha');
var orientationBeta = document.getElementById('orientation-beta');
var orientationGamma = document.getElementById('orientation-gamma');
var proximityMin = document.getElementById('proximity-min');
var proximityMax = document.getElementById('proximity-max');
var proximityValue = document.getElementById('proximity-value');
var compassCalibration = document.getElementById('compassneedscalibration');
window.addEventListener('devicemotion', function(e) {
interval.textContent = e.interval;
if (e.acceleration) {
accelerationX.textContent = e.acceleration.x;
accelerationY.textContent = e.acceleration.y;
accelerationZ.textContent = e.acceleration.z;
}
if (e.accelerationIncludingGravity) {
accelerationGX.textContent = e.accelerationIncludingGravity.x;
accelerationGY.textContent = e.accelerationIncludingGravity.y;
accelerationGZ.textContent = e.accelerationIncludingGravity.z;
}
if (e.rotationRate) {
rotAlpha.textContent = e.rotationRate.alpha;
rotBeta.textContent = e.rotationRate.beta;
rotGamma.textContent = e.rotationRate.gamma;
}
}, false);
window.addEventListener('deviceorientation', function(e) {
if (e) {
orientationAlpha.textContent = e.alpha;
orientationBeta.textContent = e.beta;
orientationGamma.textContent = e.gamma;
}
}, false);
window.addEventListener('devicelight', function(event) {
document.getElementById('light').textContent = event.value;
});
window.addEventListener('deviceproximity', function(event) {
proximityMin.textContent = event.min;
proximityMax.textContent = event.max;
proximityValue.textContent = event.value;
});
window.addEventListener('compassneedscalibration', function(e) {
compassCalibration.textContent = 'true';
}, false);
}
window.addEventListener('load', sensorTest);

View file

@ -0,0 +1,448 @@
'use strict';
// test result indicator
var Status = {
NOT_FINISHED: 1,
FINISHED: 2,
ABORT: 3
};
// UTILS
var util = {
// Use this function to get correct click position on canvas
relMouseCoords: function(canvas, evt) {
var rect = canvas.getBoundingClientRect();
var eventX = evt.clientX - rect.left;
var eventY = evt.clientY - rect.top;
return {x: eventX, y: eventY};
},
clearScreen: function(ctx) {
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
},
drawRectFromCoord: function(ctx, x1, y1, x2, y2) {
ctx.translate(0.5, 0.5);
ctx.strokeRect(x1, y1, x2 - x1, y2 - y1);
ctx.translate(-0.5, -0.5);
},
// Fill rect without overlapping border,
fillRectFromCoord: function(ctx, x1, y1, x2, y2) {
ctx.fillRect(x1 + 1, y1 + 1, (x2 - x1) - 1, (y2 - y1) - 1);
},
drawCircle: function(ctx, x, y, radius, width, color) {
ctx.lineWidth = width;
ctx.strokeStyle = color;
ctx.beginPath();
ctx.translate(0.5, 0.5);
ctx.arc(x, y, radius, 0, 2 * Math.PI);
ctx.translate(-0.5, -0.5);
ctx.closePath();
ctx.stroke();
},
distance_sqr: function(x1, y1, x2, y2) {
return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
},
// Return the index less or equal to num
binary_search: function(arr, num) {
var begin = 0;
var end = arr.length - 1;
while (begin < end) {
var pivot = Math.round((begin + end) / 2);
if (num < arr[pivot]) {
end = pivot - 1;
}
else if (num > arr[pivot]) {
begin = pivot + 1;
}
else {
return pivot;
}
}
if (num < arr[begin]) {
return begin - 1;
}
return begin;
}
};
// TEST 1
// Draw 4 circles on the corners and 1 circle in the center
var test1 = function(canvas) {
var ctx = canvas.getContext('2d');
var circle_radius = Math.min(canvas.width, canvas.height) * 0.1;
var circles_coord =
[[circle_radius, circle_radius],
[circle_radius, canvas.height - circle_radius],
[canvas.width - circle_radius, circle_radius],
[canvas.width - circle_radius, canvas.height - circle_radius],
[canvas.width / 2, canvas.height / 2]];
var lineWidth = 2;
var lineColor = 'red';
var lineColorClicked = 'lime';
var is_clicked = [];
var exitIconPositionX;
var exitIconPositionY;
var exitIconWidth;
var exitIconHeight;
(function init() {
util.clearScreen(ctx);
// Draw not-clicked circle
for (var i = 0; i < circles_coord.length; i++) {
util.drawCircle(ctx, circles_coord[i][0], circles_coord[i][1],
circle_radius, lineWidth, lineColor);
is_clicked[i] = false;
}
// Draw exit icon
var image = document.getElementById('icon-exit');
exitIconWidth = image.width;
exitIconHeight = image.height;
// Draw icon below center
exitIconPositionX = (canvas.width - exitIconWidth) / 2;
exitIconPositionY = canvas.height * 0.65;
ctx.drawImage(image, exitIconPositionX, exitIconPositionY);
})();
// Touch test, change circle color if touch point is in the circle.
// Test ends if all circles are touched
this.test = function(x, y) {
// Clicked on exit button
if (x > exitIconPositionX && x <= exitIconPositionX + exitIconWidth &&
y > exitIconPositionY && y <= exitIconPositionY + exitIconHeight) {
return Status.ABORT;
}
for (var i = 0; i < circles_coord.length; i++) {
if (!is_clicked[i] &&
util.distance_sqr(x, y, circles_coord[i][0], circles_coord[i][1]) <
circle_radius * circle_radius) {
// Clear red circle by covering a bigger white circle on it
util.drawCircle(ctx, circles_coord[i][0], circles_coord[i][1],
circle_radius, lineWidth + 2, 'white');
// Draw new circle
util.drawCircle(ctx, circles_coord[i][0], circles_coord[i][1],
circle_radius, lineWidth, lineColorClicked);
is_clicked[i] = true;
break;
}
}
for (var i = 0; i < circles_coord.length; i++) {
if (!is_clicked[i]) {
return Status.NOT_FINISHED;
}
}
// Test over
return Status.FINISHED;
};
};
// TEST 2
// Draw several cubes on the edge of screen
var test2 = function(canvas) {
var ctx = canvas.getContext('2d');
var aspect = canvas.width / canvas.height;
var cubes_num_vertical = 20;
var cubes_num_horizontal = Math.round(cubes_num_vertical * aspect);
var cube_width = canvas.width / cubes_num_horizontal;
var cube_height = canvas.height / cubes_num_vertical;
var cube_coord_x = [];
var cube_coord_y = [];
var is_clicked_top = [];
var is_clicked_bottom = [];
var is_clicked_left = [];
var is_clicked_right = [];
var total_clicked = 0;
var exitIconPositionX;
var exitIconPositionY;
var exitIconWidth;
var exitIconHeight;
(function init() {
util.clearScreen(ctx);
ctx.strokeStyle = 'black';
ctx.fillStyle = 'lime';
ctx.lineWidth = 1;
// Because width/height of screen can not be divided evenly
// So we precaculate the grid (coordination) of cubes for future use
for (var i = 0; i < cubes_num_horizontal; i++) {
cube_coord_x[i] = Math.round(cube_width * i);
}
cube_coord_x[cubes_num_horizontal] = canvas.width - 1;
for (var i = 0; i < cubes_num_vertical; i++) {
cube_coord_y[i] = Math.round(cube_height * i);
}
cube_coord_y[cubes_num_vertical] = canvas.height - 1;
// Draw Top/Bottom/Left/Right cubes
for (var i = 0; i < cubes_num_horizontal; i++) {
util.drawRectFromCoord(ctx, cube_coord_x[i], cube_coord_y[0],
cube_coord_x[i + 1], cube_coord_y[1]);
is_clicked_top[i] = false;
}
for (var i = 0; i < cubes_num_horizontal; i++) {
util.drawRectFromCoord(ctx,
cube_coord_x[i],
cube_coord_y[cubes_num_vertical - 1],
cube_coord_x[i + 1],
cube_coord_y[cubes_num_vertical]);
is_clicked_bottom[i] = false;
}
for (var i = 0; i < cubes_num_vertical; i++) {
util.drawRectFromCoord(ctx,
cube_coord_x[0],
cube_coord_y[i],
cube_coord_x[1],
cube_coord_y[i + 1]);
is_clicked_left[i] = false;
}
for (var i = 0; i < cubes_num_vertical; i++) {
util.drawRectFromCoord(ctx,
cube_coord_x[cubes_num_horizontal - 1],
cube_coord_y[i],
cube_coord_x[cubes_num_horizontal],
cube_coord_y[i + 1]);
is_clicked_right[i] = false;
}
// Draw exit icon
var image = document.getElementById('icon-exit');
exitIconWidth = image.width;
exitIconHeight = image.height;
exitIconPositionX = (canvas.width - exitIconWidth) / 2;
exitIconPositionY = (canvas.height - exitIconHeight) / 2;
ctx.drawImage(image, exitIconPositionX, exitIconPositionY);
}
)();
// Touch test, fill cubes if touch point is in the cube.
// Test ends if all cubes are touched
this.test = function(x, y) {
// Clicked on exit button
if (x > exitIconPositionX && x <= exitIconPositionX + exitIconWidth &&
y > exitIconPositionY && y <= exitIconPositionY + exitIconHeight) {
return Status.ABORT;
}
if (cube_coord_x[1] <= x && x <= cube_coord_x[cubes_num_horizontal - 1] &&
cube_coord_y[1] <= y && y <= cube_coord_y[cubes_num_vertical - 1]) {
return Status.NOT_FINISHED;
}
var startXi = util.binary_search(cube_coord_x, x);
var startYi = util.binary_search(cube_coord_y, y);
util.fillRectFromCoord(ctx,
cube_coord_x[startXi],
cube_coord_y[startYi],
cube_coord_x[startXi + 1],
cube_coord_y[startYi + 1]);
if (startYi == 0 && !is_clicked_top[startXi]) {
is_clicked_top[startXi] = true;
}
if (startYi == cubes_num_vertical - 1 && !is_clicked_bottom[startXi]) {
is_clicked_bottom[startXi] = true;
}
if (startXi == 0 && !is_clicked_left[startYi]) {
is_clicked_left[startYi] = true;
}
if (startXi == cubes_num_horizontal - 1 && !is_clicked_right[startYi]) {
is_clicked_right[startYi] = true;
}
for (var i = 0; i < cubes_num_vertical; i++) {
if (!is_clicked_left[i] || !is_clicked_right[i]) {
return Status.NOT_FINISHED;
}
}
for (var i = 0; i < cubes_num_horizontal; i++) {
if (!is_clicked_top[i] || !is_clicked_bottom[i]) {
return Status.NOT_FINISHED;
}
}
// Test over
return Status.FINISHED;
};
};
var test_driver = function() {
var current_test = null;
var canvas = document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.style.width = canvas.width + 'px';
canvas.style.height = canvas.height + 'px';
// returns true if no other tests
function proceed() {
if (current_test == null) {
current_test = new test1(canvas);
return false;
}
else if (current_test instanceof test1) {
current_test = new test2(canvas);
return false;
}
else if (current_test instanceof test2) {
return true;
}
}
proceed();
// returns whether all tests are finished
this.touch = function(x, y) {
var touchResult = current_test.test(x, y);
if (touchResult == Status.ABORT) {
return Status.ABORT;
}
// one test finished, go on next test
if (touchResult == Status.FINISHED) {
var isAllFinished = proceed();
if (isAllFinished) {
return Status.FINISHED;
}
}
return Status.NOT_FINISHED;
};
};
// Handle touch input, Codes modified from
// https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Events/Touch_events
var touchTest = function() {
var ongoingTouches = [];
var driver = null;
var canvas = null;
function copyTouch(touch) {
return { identifier: touch.identifier,
pageX: touch.pageX,
pageY: touch.pageY };
}
function ongoingTouchIndexById(idToFind) {
for (var i = 0; i < ongoingTouches.length; i++) {
var id = ongoingTouches[i].identifier;
if (id == idToFind) {
return i;
}
}
return -1; // not found
}
function handleEvent(evt) {
var touches = evt.changedTouches;
var result;
evt.preventDefault();
switch (evt.type) {
case 'touchstart':
for (var i = 0; i < touches.length; i++) {
ongoingTouches.push(copyTouch(touches[i]));
var coord = util.relMouseCoords(canvas, touches[i]);
result = driver.touch(coord.x, coord.y);
}
break;
case 'touchmove':
for (var i = 0; i < touches.length; i++) {
var coord = util.relMouseCoords(canvas, touches[i]);
var idx = ongoingTouchIndexById(touches[i].identifier);
if (idx >= 0) {
var coord_last = util.relMouseCoords(canvas, ongoingTouches[idx]);
result = driver.touch(coord.x, coord.y);
// swap in the new touch record
ongoingTouches.splice(idx, 1, copyTouch(touches[i]));
} else {
console.log('can\'t figure out which touch to continue');
}
}
break;
case 'touchend':
for (var i = 0; i < touches.length; i++) {
var coord = util.relMouseCoords(canvas, touches[i]);
var idx = ongoingTouchIndexById(touches[i].identifier);
if (idx >= 0) {
ongoingTouches.splice(i, 1); // remove it; we're done
} else {
console.log('can\'t figure out which touch to end');
}
}
break;
case 'touchcancel':
for (var i = 0; i < touches.length; i++) {
ongoingTouches.splice(i, 1); // remove it; we're done
}
break;
}
// All tests over
if (result == Status.FINISHED || result == Status.ABORT) {
// Clear remaining touches
touches = null;
canvas.removeEventListener('touchstart', handleEvent, false);
canvas.removeEventListener('touchend', handleEvent, false);
canvas.removeEventListener('touchcancel', handleEvent, false);
canvas.removeEventListener('touchleave', handleEvent, false);
canvas.removeEventListener('touchmove', handleEvent, false);
console.log('uninitialized.');
if (result == Status.ABORT) {
alert('Test terminated by user');
} else {
alert('Test Success!');
}
document.mozCancelFullScreen();
// This is a hack to close touch test, uitest.js will close this iframe
window.parent.window.location.hash = '';
}
}
this.init = function() {
driver = new test_driver();
if (canvas == null) {
canvas = document.getElementsByTagName('canvas')[0];
canvas.addEventListener('touchstart', handleEvent, false);
canvas.addEventListener('touchend', handleEvent, false);
canvas.addEventListener('touchcancel', handleEvent, false);
canvas.addEventListener('touchleave', handleEvent, false);
canvas.addEventListener('touchmove', handleEvent, false);
console.log('initialized.');
}
};
};
// XXX: There is a problem of getting into fullscreen
// When we called mozRequestFullscreen, it actually resized two times.
// We get almost fullscreen (except status bar) after first event, and truely
// fullscreen after second event. So we need to wait for the second event.
var resizedTimes = 0;
window.addEventListener('resize', function startTest() {
if (resizedTimes < 1) {
resizedTimes++;
}
else {
window.removeEventListener('resize', startTest);
var test = new touchTest;
test.init();
}
});
window.addEventListener('load', function() {
document.getElementById('canvas').classList.remove('invisible');
var exitButton = document.getElementById('fullscreen-exit');
document.body.mozRequestFullScreen();
});

View file

@ -0,0 +1,54 @@
'use strict';
function vibratorTest() {
var durationText = document.getElementById('duration-text');
var duration = document.getElementById('duration');
var timesText = document.getElementById('times-text');
var times = document.getElementById('times');
var clickHandlers = {
'off': function() {
window.navigator.vibrate(0);
},
'one-short': function() {
window.navigator.vibrate(200);
},
'two-short': function() {
window.navigator.vibrate([200, 100, 200, 100]);
},
'one-long': function() {
window.navigator.vibrate(10000);
},
'custom-pattern': function() {
var timesNum = parseInt(times.value);
var pattern = [];
for (var i = 0; i < timesNum * 2; i++) {
pattern.push(parseInt(duration.value));
}
window.navigator.vibrate(pattern);
}
};
// Update text when sliding bar is changed
var changeHandlers = {
'duration': function() {
durationText.textContent = duration.value;
},
'times': function() {
timesText.textContent = times.value;
}
};
document.body.addEventListener('click', function(evt) {
if (clickHandlers[evt.target.id]) {
clickHandlers[evt.target.id].call(this, evt);
}
});
document.body.addEventListener('input', function(evt) {
if (changeHandlers[evt.target.id]) {
changeHandlers[evt.target.id].call(this, evt);
}
});
}
window.addEventListener('load', vibratorTest);

View file

@ -0,0 +1,37 @@
'use strict';
function wifiTest() {
var WiFiMACText = document.getElementById('address');
var WiFiStateText = document.getElementById('state');
var switchButton = document.getElementById('switch');
var settings = window.navigator.mozSettings;
var wifiManager;
function update() {
switchButton.checked = wifiManager.enabled;
if (wifiManager.enabled) {
WiFiStateText.textContent = 'On';
WiFiMACText.textContent = wifiManager.macAddress;
}
else {
WiFiStateText.textContent = 'Off';
WiFiMACText.textContent = 'Not available';
}
}
if ('mozWifiManager' in navigator) {
wifiManager = navigator.mozWifiManager;
// navigator.mozWifiManager does not have addEventListener()
wifiManager.onenabled = update.bind(this);
wifiManager.ondisabled = update.bind(this);
update();
}
// Click on switch will only update settings and
// it takes some time for hardware to turns on.
// That's why we should listen to enabled/disabled event of wifi
function wifiSwitch() {
settings.createLock().set({'wifi.enabled': switchButton.checked});
}
switchButton.addEventListener('click', wifiSwitch);
}
window.addEventListener('load', wifiTest);

View file

@ -0,0 +1,42 @@
'use strict';
var clickHandlers = {
'button1': function() {
window.parent.alert('Hello world!');
},
'button2': function() {
window.parent.alert(window.parent.confirm('Hello world?'));
},
'button3': function() {
window.parent.alert(window.parent.prompt('Hello world:', 'initial value'));
},
'button21': function() {
alert('Hello world!');
},
'button22': function() {
alert(confirm('Hello world?'));
},
'button23': function() {
alert(prompt('Hello world:', 'initial value'));
},
'button31': function() {
var msg = 'Hello world!1\n2\n3\n4\n5\n6\n7\n8\n9';
msg += '\n10\n11\n12\n13\n14\n15\n16\n17\n18\n';
alert(msg);
},
'button32': function() {
var msg = 'Hello world!1\n2\n3\n4\n5\n6\n7\n8\n9';
msg += '\n10\n11\n12\n13\n14\n15\n16\n17\n18\n';
alert(confirm(msg));
},
'button33': function() {
var msg = 'Hello world!1\n2\n3\n4\n5\n6\n7\n8\n9';
msg += '\n10\n11\n12\n13\n14\n15\n16\n17\n18\n';
alert(prompt(msg));
}
};
document.body.addEventListener('click', function(evt) {
if (clickHandlers[evt.target.id])
clickHandlers[evt.target.id].call(this, evt);
});

View file

@ -0,0 +1,59 @@
'use strict';
var CanvasTests = {
get drawButton() {
delete this.drawButton;
return this.drawButton = document.getElementById('button-draw');
},
get toggleHiddenButton() {
delete this.toggleHiddenButton;
return this.toggleHiddenButton =
document.getElementById('button-toggle-hidden');
},
get canvas() {
delete this.canvas;
return this.canvas = document.getElementById('canvas');
},
get hiddenStatus() {
delete this.hiddenStatus;
return this.hiddenStatus = document.getElementById('hidden-status');
},
init: function ct_init() {
this.hiddenStatus.innerHTML =
'hidden = ' +
this.canvas.classList.contains('hidden');
this.drawButton.addEventListener('click', this.draw.bind(this));
this.toggleHiddenButton.addEventListener('click',
this.toggleShowHide.bind(this));
},
draw: function ct_draw() {
// var element = document.getElementById('canvas');
var context = this.canvas.getContext('2d');
var image = new Image();
var path = '../../style/images/canardpc.jpg';
image.src = path;
var self = this;
image.onload = function() {
var w = image.width;
var h = image.height;
context.drawImage(image, 0, 0, w, h, 0, 0, w, h);
};
},
toggleShowHide: function ct_toggleShowHide() {
this.canvas.classList.toggle('hidden');
var status = this.canvas.classList.contains('hidden');
this.hiddenStatus.innerHTML = 'hidden = ' + status;
}
};
window.addEventListener('DOMContentLoaded', function() {
CanvasTests.init();
});

View file

@ -0,0 +1,24 @@
'use strict';
var clickHandlers = {
'reload': function() {
window.location.reload();
},
'comments': function() {
window.location = '#comments';
alert(window.location.href);
},
'twitter': function() {
window.open('http://twitter.com/intent/tweet?text=' +
document.title + ': ' + window.location.href, 'shareWindow');
},
'facebook': function() {
window.open('http://facebook.com/sharer/sharer.php?u=' +
window.location.href, 'shareWindow');
}
};
document.body.addEventListener('click', function(evt) {
if (clickHandlers[evt.target.id || evt.target.dataset.fn])
clickHandlers[evt.target.id || evt.target.dataset.fn].call(this, evt);
});

View file

@ -0,0 +1,19 @@
'use strict';
function css_dimension_test() {
var bar_inch = document.getElementById('bar_inch');
var bar_mm = document.getElementById('bar_mm');
var bar_px = document.getElementById('bar_px');
var bar_mozmm = document.getElementById('bar_mozmm');
bar_inch.style.width = '1in';
bar_inch.style.backgroundColor = '#00FF00';
bar_mm.style.width = '25.4mm';
bar_mm.style.backgroundColor = '#00DD44';
bar_px.style.width = '96px';
bar_px.style.backgroundColor = '#00BB88';
bar_mozmm.style.width = '25.4mozmm';
bar_mozmm.style.backgroundColor = '#0099CC';
}
window.addEventListener('load', css_dimension_test);

View file

@ -0,0 +1,13 @@
'use strict';
var clickHandlers = {
/*
'id': function () {
alert('event triggered!');
}, */
};
document.body.addEventListener('click', function(evt) {
if (clickHandlers[evt.target.id || evt.target.dataset.fn])
clickHandlers[evt.target.id || evt.target.dataset.fn].call(this, evt);
});

View file

@ -0,0 +1,45 @@
'use strict';
function fullscreenTest() {
var fullscreenDiv = document.getElementById('fullscreen-div');
var testBtnDiv = document.getElementById('testBtn-div');
var testBtn = document.getElementById('testBtn');
var isFullscreenDiv = false;
var isFullscreen = false;
var displayMode;
function clickHandlers(evt) {
switch (evt.target.id) {
case 'testBtn':
if (!isFullscreen) {
window.parent.document.getElementById('test-iframe')
.mozRequestFullScreen();
testBtn.textContent = 'Cancel fullscreen';
} else {
window.parent.document.mozCancelFullScreen();
testBtn.textContent = 'Test';
}
isFullscreen = !isFullscreen;
break;
case 'testBtn-div':
if (!isFullscreenDiv) {
fullscreenDiv.mozRequestFullScreen();
testBtnDiv.textContent = 'Cancel fullscreen';
} else {
document.mozCancelFullScreen();
testBtnDiv.textContent = 'Test';
// Also cancels fullscreen of caused by another button (if any)
isFullscreen = false;
testBtn.textContent = 'Test';
}
isFullscreenDiv = !isFullscreenDiv;
break;
}
};
document.body.addEventListener('click', clickHandlers.bind(this));
}
window.addEventListener('load', fullscreenTest);

View file

@ -0,0 +1,29 @@
function keyboardTest() {
(function designmode(id) {
var iframe = document.querySelector('#' + id);
iframe.contentDocument.designMode = 'on';
iframe.contentDocument.body.textContent = 'Hola supermercado';
})('iframe-designmode');
(function contentEditable(id) {
var iframe = document.querySelector('#' + id);
iframe.contentDocument.body.setAttribute('contenteditable', true);
iframe.contentDocument.body.textContent = 'Telebancos por aqui';
})('iframe-contenteditable');
var readme = document.getElementById('readme');
var readmeBtn = document.getElementById('readme_button');
readme.hidden = true;
readmeBtn.addEventListener('click',
function toggle_readme() {
readme.hidden = !readme.hidden;
if (readme.hidden) {
readmeBtn.textContent = 'Show README';
} else {
readmeBtn.textContent = 'Hide README';
}
}
);
}
window.addEventListener('load', keyboardTest);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,19 @@
document.getElementById('close').onclick = function() {
window.close();
};
document.getElementById('open').onclick = function() {
window.open('/tests_html/UI/popup.html', '', 'dialog');
};
window.addEventListener('resize', function() {
if (window.innerHeight > 60) {
document.body.style.backgroundColor = 'white';
document.body.style.fontSize = '20px';
document.body.style.color = 'black';
} else {
document.body.style.backgroundColor = 'green';
document.body.style.fontSize = '10px';
document.body.style.color = 'white';
}
});

View file

@ -0,0 +1,6 @@
window.addEventListener('load', function() {
var p = document.getElementById('probe');
document.getElementById('report').textContent =
'Scroll bar width calculated from Javascript: ' +
(p.offsetWidth - p.scrollWidth - 2) + 'px'; // 2 = border width * 2
});

View file

@ -0,0 +1,16 @@
function changeTest(evt) {
console.log('++select++ onchange: ' + this.selectedIndex);
}
function blurTest(evt) {
console.log('++select++ onblur: ' + this.id);
}
window.addEventListener('load', function() {
var elementList = ['singleSel', 'multiSel', 'sizeSel'];
elementList.forEach(function(elementId) {
console.log('elementId: ' + elementId);
document.getElementById(elementId).onchange = changeTest;
document.getElementById(elementId).addEventListener('blur', blurTest);
});
});

View file

@ -0,0 +1,35 @@
'use strict';
window.addEventListener('load', function() {
var popup = null;
var buttons = document.querySelectorAll('button');
for (var i = 0; i < buttons.length; i++) {
var button = buttons[i];
button.addEventListener('click', function(e) {
var target = e.target;
var actualWindow = window;
if (target.classList.contains('mozbrowser')) {
actualWindow = window.parent;
}
switch (target.dataset.action) {
case 'open':
var param1 = null,
param2 = null;
var hash = target.dataset.url.split('#');
if (hash.length > 1) {
param1 = hash[1];
param2 = hash[1];
}
popup = actualWindow.open(target.dataset.url, param1, param2);
break;
case 'close':
popup.close();
break;
default:
break;
}
});
}
});

184
gaia/dev_apps/uitest/js/uitest.js Executable file
View file

@ -0,0 +1,184 @@
'use stricts';
var UITest = {
get UItests() {
delete this.UItests;
return this.UItests = document.getElementById('UI-tests');
},
get APItests() {
delete this.APItests;
return this.APItests = document.getElementById('API-tests');
},
get HWtests() {
delete this.HWtests;
return this.HWtests = document.getElementById('HW-tests');
},
get iframe() {
delete this.iframe;
return this.iframe = document.getElementById('test-iframe');
},
get backHeader() {
delete this.backHeader;
return this.backHeader = document.getElementById('test-panel-header');
},
get panelTitle() {
delete this.panelTitle;
return this.panelTitle = document.getElementById('test-panel-title');
},
get tabs() {
delete this.tabs;
return this.tabs = document.querySelectorAll('[role="tab"]');
},
get UITab() {
delete this.UITab;
return this.UITab = document.getElementById('UI');
},
get APITab() {
delete this.APITab;
return this.APITab = document.getElementById('API');
},
get HWTab() {
delete this.HWTab;
return this.HWTab = document.getElementById('HW');
},
currentTab: 'UI',
handleNotificationMessage: function(message) {
if (!message.clicked) {
return;
}
this.bringSelfToForeground();
},
bringSelfToForeground: function() {
navigator.mozApps.getSelf().onsuccess = function gotSelf(evt) {
var app = evt.target.result;
app.launch();
};
},
handleActivity: function(activity) {
if (activity.source.name != 'internal-system-engineering-mode') {
return;
}
//TODO use mozEngineeringMode API to do something
},
init: function ut_init() {
this.iframe.addEventListener('load', this);
this.iframe.addEventListener('unload', this);
document.body.addEventListener('transitionend', this);
window.addEventListener('keyup', this);
window.addEventListener('hashchange', this);
this.backHeader.addEventListener('action', this);
navigator.mozSetMessageHandler('notification', function(msg) {
this.handleNotificationMessage(msg);
}.bind(this));
navigator.mozSetMessageHandler('activity', function(activity) {
this.handleActivity(activity);
}.bind(this));
var name = this.getNameFromHash();
if (name) {
this.openTest(name);
}
else {
// if no test is specified, load UI tests list (select UI tab)
window.location.hash = 'UI';
}
},
uninit: function ut_uninit() {
this.iframe.removeEventListener('load', this);
this.iframe.removeEventListener('unload', this);
document.body.removeEventListener('transitionend', this);
window.removeEventListener('keyup', this);
window.removeEventListener('hashchange', this);
this.backHeader.removeEventListener('action', this);
},
getNameFromHash: function ut_getNameFromHash() {
return (/\btest=(.+)(&|$)/.exec(window.location.hash) || [])[1];
},
handleEvent: function ut_handleEvent(ev) {
switch (ev.type) {
case 'action':
if (ev.target != this.backHeader) {
return;
}
if (window.location.hash) {
window.location.hash = '';
}
break;
case 'load':
this.iframe.contentWindow.addEventListener('keyup', this);
break;
case 'unload':
this.iframe.contentWindow.removeEventListener('keyup', this);
break;
case 'hashchange':
if (window.location.hash == '#UI')
{
this.UItests.classList.remove('invisible');
AccessibilityHelper.setAriaSelected(this.UITab, this.tabs);
if (!this.HWtests.classList.contains('invisible'))
this.HWtests.classList.add('invisible');
if (!this.APItests.classList.contains('invisible'))
this.APItests.classList.add('invisible');
}
else if (window.location.hash == '#API')
{
this.APItests.classList.remove('invisible');
AccessibilityHelper.setAriaSelected(this.APITab, this.tabs);
if (!this.UItests.classList.contains('invisible'))
this.UItests.classList.add('invisible');
if (!this.HWtests.classList.contains('invisible'))
this.HWtests.classList.add('invisible');
}
else if (window.location.hash == '#HW')
{
this.HWtests.classList.remove('invisible');
AccessibilityHelper.setAriaSelected(this.HWTab, this.tabs);
if (!this.UItests.classList.contains('invisible'))
this.UItests.classList.add('invisible');
if (!this.APItests.classList.contains('invisible'))
this.APItests.classList.add('invisible');
}
else
{
var name = this.getNameFromHash();
if (!name) {
this.closeTest();
return;
}
this.panelTitle.textContent = name;
this.openTest(name);
}
break;
case 'transitionend':
var name = this.getNameFromHash();
if (!name)
this.iframe.src = 'about:blank';
break;
}
},
openTest: function ut_openTest(name) {
// save tab name from URL
// e.g. '#test=UI/empty' => 'UI'
this.currentTab = (/=\b(.+)\//.exec(window.location.hash) || [])[1];
document.body.classList.add('test');
var self = this;
window.setTimeout(function openTestPage() {
self.iframe.src = './tests_html/' + name + '.html';
}, 200);
},
closeTest: function ut_closeTest() {
var isOpened = document.body.classList.contains('test');
if (!isOpened)
return false;
document.body.classList.remove('test');
// select tab after close test iframe
window.location.hash = this.currentTab;
return true;
}
};
window.addEventListener('load', UITest.init.bind(UITest));

View file

@ -0,0 +1,51 @@
{
"name": "UI tests",
"launch_path": "/index.html",
"type": "certified",
"developer": {
"name": "The Gaia Team",
"url": "https://github.com/mozilla-b2g/gaia"
},
"messages": [
{ "notification": "/index.html" }
],
"activities": {
"internal-system-engineering-mode": {
"filters": {},
"href": "/index.html",
"disposition": "window"
}
},
"icons": {
"84": "/style/icons/ui-test_84.png",
"126": "/style/icons/ui-test_126.png",
"142": "/style/icons/ui-test_142.png",
"189": "/style/icons/ui-test_189.png",
"284": "/style/icons/ui-test_284.png"
},
"permissions": {
"fmradio":{},
"browser":{},
"geolocation":{},
"wifi-manage":{},
"mobilenetwork":{},
"mobileconnection":{},
"power":{},
"backgroundservice":{},
"attention":{},
"contacts":{ "access": "readwrite" },
"settings":{ "access": "readwrite" },
"desktop-notification":{},
"device-storage:sdcard":{ "access": "readwrite" },
"settings":{ "access": "readwrite" },
"audio-capture":{},
"video-capture":{},
"bluetooth":{},
"downloads":{},
"firefox-accounts": {},
"engineering-mode": {},
"secureelement-manage": {},
"presentation-device-manage": {},
"moz-extremely-unstable-and-will-change-webcomponents": {}
}
}

View file

@ -0,0 +1,31 @@
.center {
display: block;
margin: 0px auto;
text-align: center;
}
.inline-block {
display: inline-block;
}
.block {
display: block;
}
.hidden {
display: none;
}
p.success {
color: green;
}
p.error {
color: red;
}
input {
font-size: 1.5rem;
}
button {
/* overwrite building blocks settings to display 2-lines button */
line-height: normal !important;
text-align: center;
}
input[type='button'] {
font-size: 2rem;
}

View file

@ -0,0 +1,21 @@
button {
font-size: 1rem;
height: 3rem;
margin-bottom: 0.3rem;
text-overflow: clip;
}
ol {
padding-left: 1rem;
padding-right:0rem;
}
.textfield {
width: 98%;
}
.panel {
display:inline-block;
width: 49%;
vertical-align: top;
}

View file

@ -0,0 +1,4 @@
button {
height: 7rem;
}

View file

@ -0,0 +1,5 @@
button {
font-size: 1.2rem;
height: 3rem;
margin-bottom: 0.3rem;
}

View file

@ -0,0 +1,39 @@
button {
font-size: 3rem;
}
button[size='small'] {
font-size: 2rem;
}
input[type='number'] {
font-size: 3rem;
width: 100%;
}
input[type='range'] {
height: 2rem;
}
input[type='range']::-moz-range-thumb {
background: orange;
height: 2rem;
width: 2rem;
}
.invisible {
display: none;
}
.red {
background: red;
}
.green {
background: green;
}
.blue {
background: blue;
}
.white {
background: white;
}
.black {
background: black;
}
.error {
color: red;
}

View file

@ -0,0 +1,77 @@
textarea, input, select, [contenteditable] {
font-size: 1.5em;
}
input, textarea, iframe {
width: 100%;
}
button {
/* overwrite building blocks settings to display 2-lines button */
line-height: normal !important;
text-align: center;
}
canvas {
display: none;
}
canvas.hidden {
display: block;
}
/* keyboard */
.table {
border-collapse: collapse;
}
.row {
display: table-row;
border-top: 1px dashed rgba(150,150,150,1);
}
.column_left,
.column_middle,
.column_right {
display: table-cell;
padding-top: 0.25rem;
padding-bottom: 0.25rem;
}
.column_left {
width: 20%;
padding-right: 0.5rem;
}
.column_middle {
width: 20%;
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.column_right {
padding-left: 0.5rem;
}
.box {
width: 200px;
height: 200px;
border: 1px solid red;
overflow: auto;
background-color: #fcc;
margin: 20px;
}
.sbox {
width: 20px;
height: 20px;
background-color: #ccc;
float: left;
}
.sbox:nth-child(2n) {
background-color: #fff;
}
.bar {
font-size: 1.5rem
}
.hidden {
display: none;
}
#fullscreen-div {
background-color: #ccf;
}
#contextMenu {
background: #eee;
border: 1px solid #ccc;
padding: 10px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,47 @@
.sublist {
margin: 0;
padding: 0;
position: absolute;
top: 5rem;
bottom: 0;
left: 0;
right: 0;
overflow-y: scroll !important;
-moz-user-select: none;
background: #fff;
}
.sublist > li {
-moz-box-sizing: border-box;
padding: 0px 16px;
border-top: 1px solid hsla(207,22%,92%,1) !important;
border-bottom: 1px solid hsla(223,7%,81%,1) !important;
font-size: 2rem;
font-weight: 600;
}
.sublist > li > a {
outline: none;
width: 100%;
height: 100% !important;
white-space: nowrap;
display: flex !important;
flex-direction: column;
justify-content: center;
}
.sublist li:active {
background-color: rgba(0,0,0,0.2);
}
/* replace build blocks CSS */
.sublist li:hover:after,
.sublist li > a:hover:after,
.sublist li:active:after,
.sublist li > a:active:after {
background-color: transparent !important;
}

View file

@ -0,0 +1,78 @@
/* ----------------------------------
* Tabs
* ---------------------------------- */
@media (orientation: landscape)
{
.bb-tablist {
right: 0;
width: 3.5rem;
height: 100%;
}
.bb-tablist > li {
width: 100%;
height: calc(100% / 3);
}
}
@media (orientation: portrait)
{
.bb-tablist {
bottom: 0;
width: 100%;
height: 3.5rem;
}
.bb-tablist > li {
width: calc(100% / 3);
height: 100%;
float: left;
}
}
.bb-tablist {
margin: 0;
padding: 0;
position: absolute;
bottom: 0;
}
.bb-tablist > li {
list-style: none;
margin: 0;
padding: 0;
}
.bb-tablist > li > a {
font-size: 1.7rem;
text-decoration: none;
text-align: center;
color: #FFF;
float: left;
width: 100%;
height: 100%;
background: #000 no-repeat center top;
position: relative;
color: #fff;
display: flex;
flex-direction: column;
justify-content: center;
}
.bb-tablist > li > a:active {
background-color: #00bbff;
}
/* Selected state */
.bb-tablist > li > a:target,
.bb-tablist > li > a[aria-selected="true"] {
color: #62c6f5
}
.bb-tablist a:target ~.bb-tabpanel,
.bb-tablist a[aria-selected="true"] ~.bb-tabpanel {
z-index: 1;
visibility: visible;
}

View file

@ -0,0 +1,84 @@
html {
font-size: 10px;
}
body {
height: 100%;
padding: 0;
margin: 0;
width: 100%;
height: 100%;
background-color: #000;
/* XXX: The below overflow property is being ignored by B2G Phone
https://bugzilla.mozilla.org/show_bug.cgi?id=777672
*/
overflow: hidden;
}
.invisible {
display: none;
}
.panel {
position: fixed;
display: block;
width: 100%;
height: 100%;
-moz-transition: -moz-transform 0.3s ease;
top: 0;
}
.test-panel {
-moz-transform: translateX(100%);
}
.list-panel{
-moz-transform: translateX(0);
}
body.test .list-panel{
-moz-transform: translateX(-100%);
}
body.test .test-panel {
-moz-transform: translateX(0);
}
#test-iframe {
border: none;
width: 100%;
height: calc(100% - 5rem);
background-color: #fff;
}
@media (orientation: landscape)
{
.page {
position: absolute;
left: 0rem;
right: 3.5rem; /* tabs are at right, keep some space for it */
top: 0rem;
bottom: 0rem;
}
.sublist > li {
height: calc(100% / 5) !important;
}
}
@media (orientation: portrait)
{
.page {
position: absolute;
left: 0rem;
right: 0rem;
top: 0rem;
bottom: 3.5rem; /* tabs are at bottom, keep some space for it */
}
.sublist > li {
height: calc(100% / 7) !important;
}
}

View file

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<meta charset="utf-8">
<title>Audio Tag test</title>
<script defer src="../../js/API/audiotag.js"></script>
<link rel="stylesheet" type="text/css" href="../../style/API.css">
<link rel="stylesheet" type="text/css" href="/shared/style/buttons.css">
</head>
<body>
<fieldset>
<legend><b>classic.ogg</b></legend>
<button data-fn="play" data-src="classic.ogg">Play</button>
</fieldset>
<div>
<fieldset>
<legend><b>AC_prgrssv__Retro_Alarm_<br>Clock_v02_SOFT.ogg</b></legend>
<button data-fn="play" data-src="AC_prgrssv__Retro_Alarm_Clock_v02_SOFT.ogg">Play</button></p>
</fieldset>
</div>
<fieldset>
<legend><b>AC_progressive_dapple10.ogg</b></legend>
<button data-fn="play" data-src="AC_progressive_dapple10.ogg">Play</button></p>
</fieldset>
<fieldset>
<legend><b>AC_progressive_shimmer07.ogg</b></legend>
<button data-fn="play" data-src="AC_progressive_shimmer07.ogg">Play</button></p>
</fieldset>
<fieldset>
<legend><b>ALARM_progressive_dapple.mp3</b></legend>
<button data-fn="play" data-src="ALARM_progressive_dapple.mp3">Play</button></p>
</fieldset>
<fieldset>
<legend><b>ALARM_progressive2_dapple.mp3</b></legend>
<button data-fn="play" data-src="ALARM_progressive2_dapple.mp3">Play</button></p>
</fieldset>
</body>
</html>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<meta charset="utf-8">
<title>Browser Web Activities Test</title>
<script defer src="../../js/API/browseractivities.js"></script>
<link rel="stylesheet" type="text/css" href="../../style/API.css">
<link rel="stylesheet" type="text/css" href="/shared/style/buttons.css">
<link rel="stylesheet" type="text/css" href="/shared/style/input_areas.css">
</head>
<body>
<h2>Go to:</h2>
<p>URL: <input type="url" id="URL" value="http://" />
<button id="go">Go</button></p>
</body>
</html>

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<meta charset="utf-8">
<title>Compose Email test</title>
<script defer src="../../js/API/composeemail.js"></script>
<link rel="stylesheet" type="text/css" href="../../style/API.css">
<link rel="stylesheet" type="text/css" href="/shared/style/buttons.css">
</head>
<body>
<h3>Compose Email with 'new' activity:</h3>
<button id="compose-email">Compose Email</button>
<h3>Compose Email with mailto url link:</h3>
<a href="mailto:example@example.org">Compose Email</a>
</body>
</html>

View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<meta charset="utf-8">
<title>Contacts testing tools</title>
<link rel="stylesheet" type="text/css" href="../../style/API.css">
<!-- We don't need localization for this app. -->
<script type="text/javascript" src="../../js/API/contacts.js"></script>
<script type="text/javascript" src="../../js/API/contacts_saver.js"></script>
<link rel="stylesheet" type="text/css" href="/shared/style/buttons.css">
</head>
<body>
<fieldset>
<legend><b>Contacts manipulation</b></legend>
<section>
Contacts inserted: <span id="insertion-count">None, yet.</span>
<button id="insert-contacts">Insert fake contacts</button>
<button id="insert-social-contacts">Insert Social Contacts</button>
<button id="clear-contacts">Clear all contacts</button>
<button id="get-contacts">Get all contacts</button>
</section>
</fieldset>
<!-- Activities tests -->
<fieldset>
<legend><b>Activities tests</b></legend>
<section>
<p id="activities-result"></p>
<button id="activities-pick">Pick a contact</button>
<button id="activities-new">New contact</button>
<button id="activities-update">Update contact with<br>phone</button>
<button id="activities-update-email">Update contact with<br>email</button>
<button id="activities-update-email-phone">Update contact with<br>phone and email</button>
<button id="activities-new-data">New contact with<br>data</button>
</section>
</fieldset>
</body>
</html>

View file

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Copy and paste test</title>
<style>
textarea {
width: 100%;
height: 50rem;
overflow: scroll;
}
</style>
</head>
<body>
<textarea id="textarea">Hollywood, California (CNN) -- Actor Brad Pitt was struck in the face as he was signing autographs at a movie premiere Wednesday, Los Angeles police said.' +
'Pitt was at the Hollywood premiere of "Maleficent," starring his partner Angelina Jolie, when a man hopped a barrier and attacked the actor, Sgt. Leonard Calderon said.' +
'Officers arrested the suspect, 25-year-old Vitalii Sediuk, on suspicion of battery.'+
'Sediuk has a history of confronting celebrities at red carpet events. In 2012, he was slapped by actor Will Smith after he attempted to kiss Smith.'+
'At the 2013 Grammy Awards, Sediuk charged the stage before singer Adele could accept her award.' +
'Sediuk also hugged actors Leonardo DiCaprio and Bradley Cooper around the knees at separate events earlier this year.' +
'Most recently, he put his head up America Ferraras dress at the Cannes premiere of "How to Train Your Dragon 2" last week.' +
'After the attack Wednesday evening, Pitt and Jolie continued walking the blue carpet. Neither appeared to look fazed by the incident."</textarea>
</body>
</html>

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<meta charset="utf-8">
<title>CSP Warning</title>
</head>
<body>
<h1>CSP Warning test</h1>
<p id="text">This line should not be removed by Javascript.</p>
<script>
window.onload = function () {
document.getElementById('text').textContent =
'Error! CSP violation is executed!';
};
</script>
</body>
</html>

View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<meta charset="utf-8">
<title>Dial Number test</title>
<script defer src="../../js/API/dialnumber.js"></script>
<link rel="stylesheet" type="text/css" href="../../style/API.css">
<link rel="stylesheet" type="text/css" href="/shared/style/buttons.css">
</head>
<body>
<button id="dial">Dial Number</button>
</body>
</html>

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Download test tools</title>
<link rel="stylesheet" type="text/css" href="/shared/style/buttons.css">
<link rel="stylesheet" type="text/css" href="../../style/API.css">
<script defer type="text/javascript" src="/shared/js/lazy_loader.js"></script>
<script defer type="text/javascript" src="../../js/API/downloads.js"></script>
</head>
<body>
<h3>Wait few seconds for initializing the download</h3>
<fieldset>
<legend>Choose one to download</legend>
<section>
<a download="Toast.doc" href="http://owd.tid.es/dm/Toast.doc">
<button>DOC (450KB)</button>
</a>
<a download="clipcanvas_14348_H264_320x180.mp4" href="http://owd.tid.es/dm/clipcanvas_14348_H264_320x180.mp4">
<button>MP4(1.1 MB)</button>
</a>
</section>
</fieldset>
<div>
<button id="downloadStatus" disabled="true">Status</button>
<button id="downloadDelete" disabled="true">Delete download</button>
</div>
</body>
</html>

View file

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<meta charset="utf-8">
<title>FxA Sign-in Demo</title>
<link rel="stylesheet" type="text/css" href="/shared/style/buttons.css">
<link rel="stylesheet" type="text/css" href="../../style/API.css">
<link rel="stylesheet" type="text/css" href="../../style/API/identity.css">
<script type="text/javascript" src="../../js/API/fxa.js"></script>
</head>
<body>
<div class="panel">
<fieldset>
<legend>Request tests</legend>
<section>
<button id="request"><code>request()</code></button>
<button id="logout"><code>logout()</button>
</section>
</fieldset>
</div>
<div class="panel">
<fieldset>
<legend>Events</legend>
<ol id="event-stream">
<li>Page render</li>
</ol>
</fieldset>
</div>
</body>
</html>

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<meta charset="utf-8">
<title>Geolocation test</title>
<script defer src="../../js/API/geolocation.js"></script>
<link rel="stylesheet" type="text/css" href="../../style/API.css">
<link rel="stylesheet" type="text/css" href="/shared/style/buttons.css">
</head>
<body>
Latitude:<label id="lati"></label><br /><br />
Longitude:<label id="longi"></label><br /><br />
<button id="submit">Find Location</button>
</body>
</html>

View file

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>gUM Test Page</title>
<script defer src="../../js/API/getusermedia.js"></script>
<link rel="stylesheet" type="text/css" href="../../style/API.css">
<link rel="stylesheet" type="text/css" href="/shared/style/buttons.css">
</head>
<body>
<div class="center">
Modified from <a href="http://mozilla.github.io/webrtc-landing/gum_test.html" target="_blank">gUM test page</a><br>
Note: Audio will feedback unless you use a headset!<br>
<div id="contents"></div>
<fieldset id="content_template" class="hidden">
<div data-type="media" class="block">
<div data-type="video-frame">
<video width="320" height="240"></video>
<div data-type="snapshots-frames" class="block"></div>
</div>
<audio controls="true"></audio>
</div>
<div data-type="message"></div>
<div data-type="startbuttons" class="block">
<button data-type="startVideoButton">Video</button>
<button data-type="startAudioButton">Audio</button>
<button data-type="startAudioVideoButton">Audio &amp; Video</button>
<button data-type="startDoubleRequest">Double Prompt</button>
</div>
<div data-type="stopbuttons" class="hidden">
<button data-type="stopButton">Stop</button>
<button data-type="pauseButton">Pause/Play</button>
<button data-type="snapshotButton">Snapshot</button>
</div>
</fieldset>
</div>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show more