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"
}
]
}

View file

@ -0,0 +1,53 @@
<!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" >
<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>
<div class="panel list-panel">
<div id="API-tests" class="list_and_toolbar">
<div class="toolbar">
<p></p><p class="toolbar-title">API Tests</p><p></p>
</div>
<ul class="list">
<li><a href="#test=API/contacts">Contacts</a></li>
<li><a href="#test=API/devicestorage">Device Storage</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/mobileid">MobileIdentity</a></li>
<li><a href="#test=API/keyevent_customization">KeyEvent Customization</a></li>
<li><a href="#test=API/settings">Settings</a></li>
</ul>
</div>
<div id="tabs" class="tabs">
<ul role="tablist" class="bb-tablist" data-items="1">
<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>
</ul>
</div>
</div>
<div id="test-panel" class="panel test-panel">
<div class="toolbar">
<button id="test-panel-back">back</button>
<p id="test-panel-title" class="toolbar-title"></p>
<p></p>
</div>
<iframe id="test-iframe" mozallowfullscreen="true"></iframe>
</div>
</body>
</html>

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,57 @@
'use strict';
function getDeviceStorageByType(type) {
var status = document.getElementById('status');
status.innerHTML = '';
console.log('Button Clicked: ' + type);
var target = navigator.getDeviceStorage(type);
var cursor = target.enumerate();
cursor.onsuccess = function() {
var file = this.result;
console.log('File found:' + file.name);
if (!this.done) {
this.continue;
}
status.innerHTML = 'Success';
};
cursor.onerror = function() {
console.log('Error: ' + this.error);
status.innerHTML = this.error;
};
}
function dsTest() {
document.getElementById('get-music').addEventListener('click',
function getMusic() {
getDeviceStorageByType('music');
}
);
document.getElementById('get-pictures').addEventListener('click',
function getPictures() {
getDeviceStorageByType('pictures');
}
);
document.getElementById('get-sdcard').addEventListener('click',
function getSDCard() {
getDeviceStorageByType('sdcard');
}
);
document.getElementById('get-videos').addEventListener('click',
function getVideos() {
getDeviceStorageByType('videos');
}
);
}
window.addEventListener('DOMContentLoaded', dsTest);

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,218 @@
'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 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() {
video_status = true;
startMedia({video: true});
}
function startAudioVideo() {
video_status = true;
audio_status = true;
startMedia({video: true, audio: true});
}
function startAudio() {
audio_status = true;
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) {
function success(stream) {
message.innerHTML = '<p class="success">Success!</p>';
stopButtons.style.display = 'block';
startButtons.style.display = 'none';
if (video_status) {
media.appendChild(video_frame);
video.mozSrcObject = stream;
video.play();
snapshots_frames.innerHTML = '';
stopButtons.appendChild(snapshotButton);
}
if (audio_status) {
media.appendChild(audio);
audio.mozSrcObject = stream;
audio.play();
}
}
function error(err) {
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,41 @@
'use stricts';
(function() {
function $(id) {
return document.getElementById(id);
}
var keyEventCustomization = {
init: function ke_init() {
window.addEventListener('keydown', this);
window.addEventListener('keyup', this);
},
handleEvent: function ke_handleEvent(e) {
// We shows event information at received-event.
$('received-event').textContent = e.key + ' ' + e.type;
switch(e.key) {
case 'VolumeDown':
case 'VolumeUp':
if ($('override-volume-keys').checked) {
$('received-event').textContent += ' default prevented';
// if override keys is checked, we should prevent default.
e.preventDefault();
}
break;
case 'Power':
case 'Exit':
case 'Home':
if ($('override-power-exit-keys').checked) {
$('received-event').textContent += ' default prevented';
// if override keys is checked, we should prevent default.
e.preventDefault();
}
break;
}
}
};
keyEventCustomization.init();
})();

View file

@ -0,0 +1,68 @@
'use strict';
var MobileId = {
init: function() {
this.clearButton = document.getElementById('clear-button');
this.clearButton.classList.add('hidden');
this.clearButton.addEventListener('click', this.onClear.bind(this));
this.getAssertionButton = document.getElementById('get-assertion-button');
this.getAssertionButton.addEventListener('click', (function() {
navigator.getMobileIdAssertion().then(
this.onAssertion.bind(this),
this.onError.bind(this)
);
}).bind(this));
this.forceSelectionButton = document.getElementById('force-selection-button');
this.forceSelectionButton.addEventListener('click', (function() {
navigator.getMobileIdAssertion({
forceSelection: true
}).then(
this.onAssertion.bind(this),
this.onError.bind(this)
);
}).bind(this));
this.assertionPlaceholder = document.getElementById('assertion-placeholder');
this.assertionContainer = document.getElementById('assertion-container');
this.errorPlaceholder = document.getElementById('error-placeholder');
this.errorContainer = document.getElementById('error-container');
},
onAssertion: function(aAssertion) {
var segments = aAssertion.split('.');
var decoded = JSON.parse(atob(segments[1].replace(/-/g, '+')
.replace(/_/g, '/')));
if (!decoded || !decoded.verifiedMSISDN) {
this.onError('Invalid assertion :(');
return;
}
this.assertionContainer.classList.remove('hidden');
this.assertionPlaceholder.textContent = 'Verified phone number ' +
decoded.verifiedMSISDN;
this.clearButton.classList.remove('hidden');
},
onError: function(aError) {
console.error('ERROR ' + aError.name || aError);
this.errorContainer.classList.remove('hidden');
this.errorPlaceholder.textContent = aError.name;
this.clearButton.classList.remove('hidden');
},
onClear: function() {
this.assertionPlaceholder.textContent = '';
this.assertionContainer.classList.add('hidden');
this.errorPlaceholder.textContent = '';
this.errorContainer.classList.add('hidden');
this.clearButton.classList.add('hidden');
},
};
window.addEventListener('DOMContentLoaded', function onload() {
window.removeEventListener('DOMContentLoaded', onload);
MobileId.init();
});

View file

@ -0,0 +1,53 @@
var settingsTest = {
init: function () {
this.statusPlaceholder = document.getElementById('status-placeholder');
this.statusContainer = document.getElementById('status-container');
this.errorPlaceholder = document.getElementById('error-placeholder');
this.errorContainer = document.getElementById('error-container');
},
addStatus: function (aStatus) {
this.statusPlaceholder.innerHTML = this.statusPlaceholder.innerHTML + "<br\>" + aStatus;
},
onError: function(aError) {
this.errorContainer.classList.remove('hidden');
this.errorPlaceholder.textContent = aError;
},
runTest: function() {
if (navigator.mozSettings)
{
var lock = navigator.mozSettings.createLock();
this.addStatus("Successfully created lock!");
var req = lock.get("wallpaper.image");
req.onsuccess = (() => {
this.addStatus("Successfully retrieved wallpaper");
var req2 = lock.set({"wallpaper.image": req.result["wallpaper.image"]});
req2.onsuccess = (() => {
this.addStatus("Successfully set wallpaper");
var req3 = lock.get("wifi.enabled");
req3.onsuccess = (() => {
this.onError("ERROR: SHOULD NOT BE ABLE TO GET WIFI");
});
req3.onerror = (() => {
this.addStatus("wifi.enabled request rejected as expected");
});
});
req2.onerror = (() => {
this.onError("COULD NOT SET WALLPAPER");
});
});
req.onerror = (() => {
this.onError("COULD NOT RETRIEVE WALLPAPER.")
});
}
else {
this.onError("SETTINGS API UNAVAILABLE");
}
}
}
window.addEventListener('DOMContentLoaded', function onload() {
window.removeEventListener('DOMContentLoaded', onload);
settingsTest.init();
settingsTest.runTest();
});

View file

@ -0,0 +1,175 @@
'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 backBtn() {
delete this.backBtn;
return this.backBtn = document.getElementById('test-panel-back');
},
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;
}
// handle notifications when uitest is closed
navigator.mozApps.getSelf().onsuccess = function gotSelf(evt) {
var app = evt.target.result;
app.launch();
};
},
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.backBtn.addEventListener('click', this);
navigator.mozSetMessageHandler('notification', function(msg) {
this.handleNotificationMessage(msg);
}.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.backBtn.removeEventListener('click', this);
},
getNameFromHash: function ut_getNameFromHash() {
return (/\btest=(.+)(&|$)/.exec(window.location.hash) || [])[1];
},
handleEvent: function ut_handleEvent(ev) {
switch (ev.type) {
case 'click':
if (ev.target != this.backBtn) {
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';
// we need to focus the iframe to let the key event send to it.
self.iframe.focus();
}, 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,32 @@
{
"name": "UI tests - Privileged App",
"launch_path": "/index.html",
"type": "privileged",
"developer": {
"name": "The TW QA Team",
"url": "https://github.com/Mozilla-TWQA",
"e-mail": "tw-qa@mozilla.com"
},
"messages": [
{ "notification": "/index.html" }
],
"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": {
"audio-capture":{},
"video-capture":{},
"contacts":{ "access": "readwrite" },
"device-storage:music":{ "access": "readwrite" },
"device-storage:pictures":{ "access": "readwrite" },
"device-storage:sdcard":{ "access": "readwrite" },
"device-storage:videos":{ "access": "readwrite" },
"geolocation":{},
"mobileid": {},
"settings:wallpaper.image": { "access": "readwrite"}
}
}

View file

@ -0,0 +1,34 @@
.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, input[type='button'] {
font-size: 2rem;
}
/* for mozId, smaller buttons */
li > button, .small {
font-size: 1.2rem;
}
/* secure element buttons */
.tiny > button {
font-size: 1rem;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 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,78 @@
/* ----------------------------------
* Tabs
* ---------------------------------- */
@media (orientation: landscape)
{
.bb-tablist {
right: 0;
width: 3rem;
height: 100%;
}
.bb-tablist > li {
width: 100%;
height: calc(100% / 3);
}
}
@media (orientation: portrait)
{
.bb-tablist {
bottom: 0;
width: 100%;
height: 3rem;
}
.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.3rem;
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,168 @@
html, body {
height: 100%;
padding: 0;
margin: 0;
}
body {
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: absolute;
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);
}
.toolbar {
-moz-box-sizing: border-box;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
position: absolute;
height: 3rem;
top: 0;
left: 0;
right: 0;
margin: 0;
padding: 0;
border-bottom: solid 3px #9b9b9b;
background-color: #fff;
background: url("images/app-texture.png") repeat scroll 50% 50%, -moz-linear-gradient(center top , rgb(244, 244, 244), rgb(234, 234, 234)) repeat scroll 0% 0% transparent;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.toolbar-title {
font-size: 1.7rem;
font-weight: bold;
margin: 0;
color: rgb(51, 51, 51);
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.list {
background: url("images/app-texture.png") repeat scroll 50% 50%, rgb(243, 243, 243);
margin: 0;
padding: 0;
position: absolute;
top: 3rem;
bottom: 0;
left: 0;
right: 0;
overflow-y: auto;
-moz-user-select: none;
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
}
.list > li {
-moz-box-sizing: border-box;
padding: 0px 16px;
border-top: 1px solid hsla(207,22%,92%,1);
border-bottom: 1px solid hsla(223,7%,81%,1);
font-size: 1.7rem;
font-weight: 600;
}
.list > li > a {
outline: none;
width: 100%; height: 100%;
color: rgb(18, 47, 64);
text-decoration: none;
white-space: nowrap;
display: flex;
flex-direction: column;
justify-content: center;
}
.list > li:active {
background: hsla(35,100%,50%,.2);
}
#test-iframe {
border: none;
width: 100%;
height: calc(100% - 3rem);
top: 3rem;
background-color: #fff;
position: absolute;
}
#test-panel-back {
font-size: 1.5rem;
height: 2.5rem;
}
@media (orientation: landscape)
{
.list_and_toolbar {
position: absolute;
left: 0rem;
right: 3rem; /* tabs are at right, keep some space for it */
top: 0rem;
bottom: 0rem;
}
.list > li {
height: calc(100% / 5);
}
}
@media (orientation: portrait)
{
.list_and_toolbar {
position: absolute;
left: 0rem;
right: 0rem;
top: 0rem;
bottom: 3rem; /* tabs are at bottom, keep some space for it */
}
.list > li {
height: calc(100% / 7);
}
}

View file

@ -0,0 +1,35 @@
<!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>
</head>
<body>
<div>
<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>
</div>
<div>
Contacts inserted: <span id="insertion-count">None, yet.</span>
</div>
<hr/>
<!-- Activities tests -->
<div>
<button id="activities-pick">Activities: Pick a contact</button>
<button id="activities-new">Activities: New contact</button>
<button id="activities-update">Activities: Update contact with phone</button>
<button id="activities-update-email">Activities: Update contact with email</button>
<button id="activities-update-email-phone">Activities: Update contact with phone and email</button>
<button id="activities-new-data">Activities: New contact with data</button>
<div id="activities-result"></div>
</div>
</body>
</html>

View file

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<meta charset="utf-8">
<title>Device Storage Test</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/devicestorage.js"></script>
</head>
<body>
<div>
<button id="get-music">Get Music</button><br>
<button id="get-pictures">Get Pictures</button><br>
<button id="get-sdcard">Get SD Card</button><br>
<button id="get-videos">Get Videos</button><br>
Status:<h3 id="status"></h3>
<div>
</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>Geolocation test</title>
<script defer src="../../js/API/geolocation.js"></script>
<link rel="stylesheet" type="text/css" href="../../style/API.css">
</head>
<body>
Latitude:<label id="lati"></label><br /><br />
Longitude:<label id="longi"></label><br /><br />
<input type="button" id="submit" value="Find Location" />
</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 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">
</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>
<div 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="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>
<div data-type="message"></div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<meta charset="utf-8">
<title>Keyboard Event Customization</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/keyevent_customization.js"></script>
</head>
<body>
<div>
Prevent the following keys' default behaviors:
<div>
<input type="checkbox" id="override-power-exit-keys"/>
<label for="override-power-exit-keys">Power and Exit</label>
</div>
<div>
<input type="checkbox" id="override-volume-keys"/>
<label for="override-volume-keys">Volume Up/Down</label>
</div>
</div>
<div>
Received KeyEvent: <span id="received-event"></span>
</div>
<hr/>
</body>
</html>

View file

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<meta charset="utf-8">
<title>Mobile Identity test</title>
<script defer src="../../js/API/mobileid.js"></script>
<link rel="stylesheet" type="text/css" href="../../style/API.css">
</head>
<body>
<h1>Mobile ID Tester</h1>
<div class="main-form">
<section id="action-buttons">
<button id="get-assertion-button">Get Assertion</button>
<button id="force-selection-button">Force selection</button>
<button id="clear-button">Clear</button>
</section>
<section id="results">
<div id="assertion-container">
<p id="assertion-placeholder"></p>
</div>
<div id="error-container">
<p id="error-placeholder" class="error"></p>
</div>
</section>
<div>
</body>
</html>

View file

@ -0,0 +1,25 @@
<!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/settings.js"></script>
<link rel="stylesheet" type="text/css" href="../../style/API.css">
</head>
<body>
<div class="main-form">
<section id="action-buttons">
<button id="submit">Run Settings Test</button>
</section>
<section id="results">
<div id="status-container">
<p id="status-placeholder"></p>
</div>
<div id="error-container">
<p id="error-placeholder" class="error"></p>
</div>
</section>
</div>
</body>
</html>