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

124
gaia/tests/atoms/accessibility.js Executable file
View file

@ -0,0 +1,124 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
/* globals Components, marionetteScriptFinished */
/* exported Accessibility */
var Accessibility = {
_accRetrieval: Components.classes[
'@mozilla.org/accessibleRetrieval;1'].getService(
Components.interfaces.nsIAccessibleRetrieval),
_getAccessible:
function Accessibility__getAccessible(element, callback, once) {
let attempts = 500;
let intervalId = setInterval(() => {
let acc = this._accRetrieval.getAccessibleFor(element);
if (acc || --attempts <= 0 || once) {
clearInterval(intervalId);
if (attempts <= 0) {
let tagName = element ? element.tagName : undefined;
let elemId = element ? element.id : undefined;
console.log('accessibility.js: failed to get accessible for tag=\"' +
tagName + '\" id=\"' + elemId + '\"');
}
try {
callback(acc);
} catch (e) {
marionetteScriptFinished({ error: e.message });
}
}
}, 10);
},
_matchState: function Accessibility__matchState(acc, stateName) {
let stateToMatch = Components.interfaces.nsIAccessibleStates[stateName];
let state = {};
let extState = {};
acc.getState(state, extState);
return !!(state.value & stateToMatch);
},
click: function Accessibility_click(element) {
this._getAccessible(element.wrappedJSObject, function(acc) {
acc.doAction(0);
marionetteScriptFinished();
});
},
wheel: function Accessibility_wheel(element, direction) {
let horizontal = direction === 'left' || direction === 'right';
let page = (direction === 'left' || direction === 'up') ? 1 : -1;
let event = new window.wrappedJSObject.WheelEvent('wheel', {
bubbles: true,
cancelable: true,
deltaX: horizontal ? page : 0,
deltaY: horizontal ? 0 : page,
deltaMode: window.wrappedJSObject.WheelEvent.DOM_DELTA_PAGE,
});
element.wrappedJSObject.dispatchEvent(event);
},
isDisabled: function Accessibility_isDisabled(element) {
this._getAccessible(element.wrappedJSObject, (acc) => {
marionetteScriptFinished(
{ result: this._matchState(acc, 'STATE_UNAVAILABLE') });
});
},
_isAriaHidden: function Accessibility__isAriaHidden(element) {
do {
if (JSON.parse(element.getAttribute('aria-hidden'))) {
return true;
}
element = element.parentNode;
} while (element && element.getAttribute);
},
isHidden: function Accessibility_isHidden(element) {
let elem = element.wrappedJSObject;
if (this._isAriaHidden(elem)) {
marionetteScriptFinished({ result: true });
return;
}
this._getAccessible(elem, (acc) => {
if (!acc) {
marionetteScriptFinished({ result: true });
return;
}
marionetteScriptFinished(
{ result: this._matchState(acc, 'STATE_INVISIBLE') });
}, true);
},
isVisible: function Accessibility_isVisible(element) {
let elem = element.wrappedJSObject;
if (this._isAriaHidden(elem)) {
marionetteScriptFinished({ result: false });
return;
}
this._getAccessible(elem, (acc) => {
marionetteScriptFinished(
{ result: !this._matchState(acc, 'STATE_INVISIBLE') });
});
},
getName: function Accessibility_getName(element) {
this._getAccessible(element.wrappedJSObject, (acc) => {
marionetteScriptFinished({ result: acc.name });
});
},
getRole: function Accessibility_getRole(element) {
this._getAccessible(element.wrappedJSObject, (acc) => {
marionetteScriptFinished(
{ result: this._accRetrieval.getStringRole(acc.role) });
});
},
};

441
gaia/tests/atoms/gaia_apps.js Executable file
View file

@ -0,0 +1,441 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
/* globals marionetteScriptFinished, waitFor */
var GaiaApps = {
normalizeName: function(name) {
return name.replace(/[- ]+/g, '').toLowerCase();
},
getInstalledApps: function() {
let req = navigator.mozApps.mgmt.getAll();
req.onsuccess = function() {
marionetteScriptFinished(req.result);
};
},
getRunningApps: function(includeSystemApps) {
let runningApps = GaiaApps.getApps(includeSystemApps);
// Return a simplified version of the runningApps object which can be
// JSON-serialized.
let apps = {};
for (let app in runningApps) {
let anApp = {};
for (let key in runningApps[app]) {
if (['name', 'origin', 'manifest'].indexOf(key) > -1) {
anApp[key] = runningApps[app][key];
}
}
apps[runningApps[app].origin] = anApp;
}
return apps;
},
getApps: function(includeSystemApps) {
let service = window.wrappedJSObject.Service;
let apps = includeSystemApps ?
service.query('getApps') :
service.query('snapshot');
return apps;
},
getRunningAppOrigin: function(name) {
let apps = GaiaApps.getApps(true);
for (let id in apps) {
if (apps[id].name == name) {
return apps[id].origin;
}
}
return undefined;
},
getPermission: function(appName, permissionName) {
GaiaApps.locateWithName(appName, function(app) {
console.log('Getting permission \'' +
permissionName +
'\' for ' +
appName);
var mozPerms = navigator.mozPermissionSettings;
var result = mozPerms.get(
permissionName, app.manifestURL, app.origin, false
);
marionetteScriptFinished(result);
});
},
setPermission: function(appName, permissionName, value) {
GaiaApps.locateWithName(appName, function(app) {
console.log('Setting permission \'' + permissionName + '\' for ' +
appName + 'to \'' + value + '\'');
var mozPerms = navigator.mozPermissionSettings;
mozPerms.set(
permissionName, value, app.manifestURL, app.origin, false
);
marionetteScriptFinished();
});
},
setPermissionByUrl: function(manifestUrl, permissionName, value, entryPoint) {
GaiaApps.locateWithManifestURL(manifestUrl, entryPoint, function(app) {
console.log('Setting permission \'' + permissionName + '\' for ' +
manifestUrl + 'to \'' + value + '\'');
var mozPerms = navigator.mozPermissionSettings;
mozPerms.set(
permissionName, value, app.manifestURL, app.origin, false
);
marionetteScriptFinished();
});
},
sendLocateResponse:
function(aCallback, app, appName, launchPath, entryPoint) {
var callback = aCallback || marionetteScriptFinished;
if (callback === marionetteScriptFinished) {
var result = false;
if (typeof(app) === 'object') {
result = {
name: app.manifest.name,
origin: app.origin,
entryPoint: entryPoint || null,
normalizedName: appName
};
}
callback(result);
} else {
callback(app, appName, launchPath, entryPoint);
}
},
locateWithName: function(name, aCallback) {
var callback = aCallback || marionetteScriptFinished;
let apps = window.wrappedJSObject.applications ||
window.wrappedJSObject.Applications;
let installedApps = apps.installedApps;
let normalizedSearchName = GaiaApps.normalizeName(name);
for (let manifestURL in installedApps) {
let app = installedApps[manifestURL];
let entryPoints = app.manifest.entry_points;
if (entryPoints) {
for (let ep in entryPoints) {
let currentEntryPoint = entryPoints[ep];
let appName = currentEntryPoint.name;
let launchPath = currentEntryPoint.launch_path;
let locales = currentEntryPoint.locales;
if (normalizedSearchName === GaiaApps.normalizeName(appName)) {
return GaiaApps.sendLocateResponse(callback,
app,
appName,
launchPath,
ep);
} else if (locales) {
for (let id in locales) {
let localisedAppName = locales[id].name;
if (localisedAppName && normalizedSearchName ===
GaiaApps.normalizeName(localisedAppName)) {
return GaiaApps.sendLocateResponse(callback,
app,
appName,
launchPath,
ep);
}
}
}
}
} else {
let appName = app.manifest.name;
let launchPath = app.manifest.launch_path;
let locales = app.manifest.locales;
if (normalizedSearchName === GaiaApps.normalizeName(appName)) {
return GaiaApps.sendLocateResponse(callback,
app,
appName,
launchPath);
} else if (locales) {
for (let id in locales) {
let localisedAppName = locales[id].name;
if (localisedAppName && normalizedSearchName ===
GaiaApps.normalizeName(localisedAppName)) {
return GaiaApps.sendLocateResponse(callback,
app,
appName,
launchPath);
}
}
}
}
}
callback(false);
},
locateWithManifestURL: function(manifestURL, entryPoint, aCallback) {
var callback = aCallback || marionetteScriptFinished;
var apps = window.wrappedJSObject.applications ||
window.wrappedJSObject.Applications;
var app = apps.getByManifestURL(manifestURL);
var launchPath;
if (app != null) {
GaiaApps._formatApp(app, manifestURL, entryPoint, callback, launchPath);
} else {
callback(false);
}
},
_formatApp: function(app, manifestURL, entryPoint, callback, launchPath) {
if (entryPoint) {
if (app.manifest.entry_points[entryPoint]) {
launchPath = app.manifest.entry_points[entryPoint].launch_path;
} else {
app = null;
}
} else {
launchPath = app.manifest.launch_path;
}
GaiaApps.sendLocateResponse(callback, app,
manifestURL, launchPath, entryPoint);
},
// Returns the number of running apps.
// if includeSystemApps is true then system always-running
// apps (eg Homescreen) will be counted
numRunningApps: function(includeSystemApps) {
return Object.keys(GaiaApps.getApps(includeSystemApps)).length;
},
isRunning: function(origin) {
var apps = GaiaApps.getApps(true);
for (var id in apps) {
if (apps[id].origin === origin) {
return true;
}
}
return false;
},
// Kills the specified app.
kill: function(aOrigin, aCallback) {
var callback = aCallback || marionetteScriptFinished;
if (!GaiaApps.isRunning(aOrigin)) {
callback(false);
}
else {
window.addEventListener('appterminated', function gt_onAppTerminated() {
window.removeEventListener('appterminated', gt_onAppTerminated);
waitFor(
function() {
console.log('app with origin \'' + aOrigin + '\' has terminated');
callback(true);
},
function() {
return !GaiaApps.isRunning(aOrigin);
}
);
});
console.log('terminating app with origin \'' + aOrigin + '\'');
window.wrappedJSObject.Service.request('AppWindowManager:kill', aOrigin);
}
},
// Kills all running apps that may be killed by the user, defined as
// being accessible by the Cards View/Stack Manager
killAll: function() {
let originsToClose = [];
let that = this;
let apps = GaiaApps.getApps();
for (let id in apps) {
let origin = apps[id].origin;
originsToClose.push(origin);
}
if (!originsToClose.length) {
marionetteScriptFinished(true);
return;
}
originsToClose.slice(0).forEach(function(origin) {
GaiaApps.kill(origin, function() {});
});
// Even after the 'appterminated' event has been fired for an app,
// it can still exist in the apps list, so wait until 1 or fewer
// apps are running (since we don't close the homescreen app).
waitFor(
function() { marionetteScriptFinished(true); },
function() { return that.numRunningApps() <= 1; }
);
},
launch: function(app, appName, launchPath, entryPoint) {
if (app) {
let manifestURL = app.manifestURL;
let origin = app.origin;
let sendResponse = function() {
let result = GaiaApps.getDisplayedApp();
marionetteScriptFinished(result);
};
let displayedApp = GaiaApps.getDisplayedApp();
if ((displayedApp.manifestURL == manifestURL &&
displayedApp.entryPoint == entryPoint) ||
(!displayedApp.manifestURL && displayedApp.origin == origin)) {
console.log(`app with origin: ${displayedApp.origin} and
manifestURL: ${displayedApp.manifestURL} and
entryPoint: ${displayedApp.entryPoint} is already running`);
sendResponse();
} else {
window.addEventListener('windowopened', function appOpen() {
window.removeEventListener('windowopened', appOpen);
waitFor(
function() {
console.log(`app with origin: ${displayedApp.origin} and
manifestURL: ${displayedApp.manifestURL} and
entryPoint: ${displayedApp.entryPoint} has launched`);
sendResponse();
},
function() {
// wait for the displayed app to have expected manifestURL/origin
let displayedApp = GaiaApps.getDisplayedApp();
if (displayedApp.manifestURL) {
return displayedApp.manifestURL == manifestURL &&
displayedApp.entryPoint == entryPoint;
} else {
return displayedApp.origin == origin;
}
}
);
});
console.log('launching app with name \'' + appName + '\'');
app.launch(entryPoint || null);
}
} else {
marionetteScriptFinished(false);
}
},
// Launches app with the specified name (e.g., 'Calculator'); returns the
// an object with the app frame if successful, false if the app can't be
// found, or times out if the app frame can't be found after launching the
// app.
launchWithName: function(name) {
GaiaApps.locateWithName(name, this.launch.bind(this));
},
// Launches app with the specified manifestURL. returns the
// an object with the app frame if successful, false if the app can't be
// found, or times out if the app frame can't be found after launching the
// app.
//
// This is prefered over launchWithName because localized builds have
// different names
launchWithManifestURL: function(manifestURL, entryPoint) {
GaiaApps.locateWithManifestURL(manifestURL, entryPoint, this.launch);
},
close: function(app, appName, entryPoint) {
if (app) {
let origin = GaiaApps.getRunningAppOrigin(appName);
GaiaApps.kill(origin);
} else {
marionetteScriptFinished(false);
}
},
// Closes app with the specified name (e.g., 'Calculator'); returns nothing
closeWithName: function(name) {
GaiaApps.locateWithName(name, this.close);
},
closeWithManifestURL: function(manifestURL, entryPoint) {
GaiaApps.locateWithManifestURL(manifestURL, entryPoint, this.close);
},
/**
* Returns the currently displayed app.
* This is more like getDisplayedFrame really,
* as we return what frame the user is interacting with
*/
getDisplayedApp: function() {
let app = window.wrappedJSObject.Service.query('getTopMostWindow');
if (!app || app.isLockscreen) {
// fallback to app window.
app = window.wrappedJSObject.Service
.query('AppWindowManager.getActiveWindow').getTopMostWindow();
}
let currentEntryPoint = null;
// When browser is on a website, app.manifest is null
if (app.manifest) {
let entryPoints = app.manifest.entry_points;
if (entryPoints) {
for (let ep in entryPoints) {
if (entryPoints[ep].launch_path == app.manifest.launch_path) {
currentEntryPoint = ep;
break;
}
}
}
}
let result = {
frame: (app.browser) ? app.browser.element : app.frame.firstChild,
src: (app.browser) ? app.browser.element.src : app.iframe.src,
name: app.name,
origin: app.origin,
manifestURL: app.manifestURL,
entryPoint: currentEntryPoint
};
return result;
},
/**
* Install the app with the specified ManifestURL
*/
install: function(manifestURL) {
let req = navigator.mozApps.install(manifestURL);
req.onsuccess = function() {
marionetteScriptFinished(true);
};
req.onerror = function() {
marionetteScriptFinished(req.error);
};
},
installPackage: function(manifestURL) {
let req = navigator.mozApps.installPackage(manifestURL);
req.onsuccess = function() {
marionetteScriptFinished(true);
};
req.onerror = function() {
marionetteScriptFinished(req.error);
};
},
/**
* Uninstall the app with the specified ManifestURL
*/
uninstall: function(manifestURL) {
GaiaApps.locateWithManifestURL(manifestURL, null, function uninstall(app) {
if (typeof(app) !== 'object') {
// App is already not there, so nothing to do here
marionetteScriptFinished(true);
return;
}
let req = navigator.mozApps.mgmt.uninstall(app);
req.onsuccess = function() {
marionetteScriptFinished(true);
};
req.onerror = function() {
marionetteScriptFinished(req.error);
};
});
}
};

View file

@ -0,0 +1,621 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
/* global marionetteScriptFinished, pair, mozContact, i */
/* global waitFor, aContacts */
/* exported pair, discovery, GaiaDataLayer */
/* jshint -W083 */
var GaiaDataLayer = {
getBluetoothDefaultAdapter: function() {
var bluetooth = window.navigator.mozBluetooth;
if (bluetooth.defaultAdapter) {
return bluetooth.defaultAdapter;
} else {
return bluetooth.getAdapters()[0];
}
},
setBluetooth: function(aState) {
var adapter = this.getBluetoothDefaultAdapter();
if (adapter.state == aState) {
console.log('bluetooth already ' + aState);
marionetteScriptFinished(true);
return;
}
waitFor(
function() {
console.log('bluetooth ' + aState);
marionetteScriptFinished(true);
},
function() {
console.log('bluetooth enable status: ' + adapter.state);
// Wait for the adapter state to become 'disabled' or 'enabled'
if (adapter.state === 'disabling' || adapter.state === 'enabling') {
return false;
}
if (adapter.state != aState) {
console.log('trying to make bluetooth ' + aState);
if (aState === 'enabled') {
adapter.enable();
} else {
adapter.disable();
}
return false;
}
return adapter.state === aState;
}
);
},
disableBluetooth: function() {
this.setBluetooth('disabled');
},
enableBluetooth: function() {
this.setBluetooth('enabled');
},
insertContact: function(aContact) {
// requires the 'contacts-create' permission
if (aContact.photo) {
var blob = GaiaDataLayer.base64ToBlob(aContact.photo, 'image/jpg');
aContact.photo = [blob];
}
var contact = new mozContact(aContact);
var req = window.navigator.mozContacts.save(contact);
req.onsuccess = function() {
console.log('success saving contact');
marionetteScriptFinished(true);
};
req.onerror = function() {
console.error('error saving contact', req.error.name);
marionetteScriptFinished(false);
};
},
insertSIMContact: function(aType, aContact) {
// Get 1st SIM
var iccId = window.navigator.mozIccManager.iccIds[0];
var icc = window.navigator.mozIccManager.getIccById(iccId);
var simContact = new window.mozContact(aContact);
if ('id' in aContact) {
simContact.id = aContact.id;
}
var req = icc.updateContact(aType, simContact);
req.onsuccess = function() {
console.log('success saving contact to SIM');
marionetteScriptFinished(req.result);
};
req.onerror = function() {
console.error('error saving contact to SIM', req.error.name);
marionetteScriptFinished(false);
};
},
deleteSIMContact: function(aType, aId) {
// Get 1st SIM
var iccId = window.navigator.mozIccManager.iccIds[0];
var icc = window.navigator.mozIccManager.getIccById(iccId);
var aContact = new mozContact();
aContact.id = aId;
var req = icc.updateContact(aType, aContact);
req.onsuccess = function() {
console.log('success removing contact from SIM');
marionetteScriptFinished(true);
};
req.onerror = function() {
console.error('error removing contact from SIM', req.error.name);
marionetteScriptFinished(false);
};
},
getAllContacts: function(aCallback) {
// requires 'contacts-read' permission
var callback = aCallback || marionetteScriptFinished;
var req = window.navigator.mozContacts.find({});
req.onsuccess = function() {
console.log('success finding contacts');
callback(req.result);
};
req.onerror = function() {
console.error('error finding contacts ' + req.error.name);
callback([]);
};
},
getSIMContacts: function(aType, aCallback) {
var type = aType || 'adn';
var callback = aCallback || marionetteScriptFinished;
var icc = navigator.mozIccManager;
// See bug 932134
// To keep all tests passed while introducing multi-sim APIs, in bug 928325
// we do the following check. Remove it after the APIs land.
if (icc && icc.iccIds && icc.iccIds[0]) {
icc = icc.getIccById(icc.iccIds[0]);
}
var req = icc.readContacts(type);
req.onsuccess = function() {
console.log('success finding ' + type + ' contacts');
callback(req.result);
};
req.onerror = function() {
console.error('error finding ' + type + ' contacts ' + req.error.name);
callback([]);
};
},
removeAllContacts: function() {
var self = this;
this.getAllContacts(function(aContacts) {
if (aContacts.length > 0) {
var contactsLength = aContacts.length;
var done = 0;
for (var i = 0; i < contactsLength; i++) {
self.removeContact(aContacts[i], function() {
if (++done === contactsLength) {
marionetteScriptFinished(true);
}
});
}
}
else {
console.log('no contacts to remove');
marionetteScriptFinished(true);
}
});
},
removeContact: function(aContact, aCallback) {
// requires the 'contacts-write' persmission
var callback = aCallback || marionetteScriptFinished;
console.log('removing contact with id \'' + aContact.id + '\'');
var req = window.navigator.mozContacts.remove(aContact);
req.onsuccess = function() {
console.log('success removing contact with id \'' + aContact.id + '\'');
callback(true);
};
req.onerror = function() {
console.error('error removing contact with id \'' +
aContacts[i].id + '\'');
callback(false);
};
},
getSetting: function(aName, aCallback) {
// requires the 'settings-read' and 'settings-api-read' permissions
var callback = aCallback || marionetteScriptFinished;
var req = window.navigator.mozSettings.createLock().get(aName);
req.onsuccess = function() {
console.log('setting retrieved');
let result = aName === '*' ? req.result : req.result[aName];
callback(result);
};
req.onerror = function() {
console.log('error getting setting ' + req.error.name);
};
},
setSetting: function(aName, aValue, aReturnOnSuccess) {
// requires the 'settings-write' and 'settings-api-write' permissions
var returnOnSuccess = aReturnOnSuccess || aReturnOnSuccess === undefined;
var setting = {};
setting[aName] = aValue;
console.log('setting ' + aName + ' to ' + aValue);
var lock = window.navigator.mozSettings.createLock();
var req = lock.set(setting);
lock.onsettingstransactionsuccess = function() {
console.log('setting changed');
if (returnOnSuccess) {
marionetteScriptFinished(true);
}
};
lock.onsettingstransactionfailure = function() {
console.log('error changing setting ' + req.error.name);
marionetteScriptFinished(false);
};
},
connectToWiFi: function(aNetwork, aCallback) {
var callback = aCallback || marionetteScriptFinished;
var manager = window.navigator.mozWifiManager;
if (this.isWiFiConnected(aNetwork)) {
console.log('already connected to network with ssid \'' +
aNetwork.ssid + '\'');
callback(true);
}
else {
var req;
if (window.MozWifiNetwork === undefined) {
req = manager.associate(aNetwork);
} else {
req = manager.associate(new window.MozWifiNetwork(aNetwork));
}
req.onsuccess = function() {
console.log('waiting for connection status \'connected\'');
waitFor(
function() {
console.log('success connecting to network with ssid \'' +
aNetwork.ssid + '\'');
callback(true);
},
function() {
console.log('connection status: ' + manager.connection.status);
return manager.connection.status === 'connected';
}
);
};
req.onerror = function() {
console.log('error connecting to network ' + req.error.name);
callback(false);
};
}
},
disableWiFi: function() {
var manager = window.navigator.mozWifiManager;
if (manager.enabled) {
waitFor(
function() { marionetteScriptFinished(true); },
function() {
console.log('wifi enabled status: ' + manager.enabled);
return manager.enabled === false;
});
this.setSetting('wifi.enabled', false, false);
}
else {
console.log('wifi already disabled');
marionetteScriptFinished(true);
}
},
enableWiFi: function() {
var manager = window.navigator.mozWifiManager;
if (!manager.enabled) {
waitFor(
function() { marionetteScriptFinished(true); },
function() {
console.log('wifi enabled status: ' + manager.enabled);
return manager.enabled === true;
});
this.setSetting('wifi.enabled', true, false);
}
else {
console.log('wifi already enabled');
marionetteScriptFinished(true);
}
},
forgetAllNetworks: function(aCallback) {
var callback = aCallback || marionetteScriptFinished;
var self = this;
this.getKnownNetworks(function(aNetworks) {
if (aNetworks.length > 0) {
var networksLength = aNetworks.length;
var done = 0;
for (var i = 0; i < networksLength; i++) {
self.forgetWiFi(aNetworks[i], function() {
if (++done === networksLength) {
callback(true);
}
}, false);
}
}
else {
console.log('no known networks to forget');
callback(true);
}
});
},
getKnownNetworks: function(aCallback) {
var callback = aCallback || marionetteScriptFinished;
var manager = window.navigator.mozWifiManager;
var req = manager.getKnownNetworks();
req.onsuccess = function() {
console.log('success getting known networks');
callback(req.result);
};
req.onerror = function() {
console.log('error getting known networks ' + req.error.name);
callback([]);
};
},
forgetWiFi: function(aNetwork, aCallback, aWaitForStatus) {
var callback = aCallback || marionetteScriptFinished;
var waitForStatus = aWaitForStatus || 'disconnected';
var manager = window.navigator.mozWifiManager;
var req = manager.forget(aNetwork);
req.onsuccess = function() {
console.log('success forgetting network with ssid \'' +
aNetwork.ssid + '\'');
if (waitForStatus !== false) {
console.log('waiting for connection status \'' +
waitForStatus + '\'');
waitFor(
function() { callback(true); },
function() {
console.log('connection status: ' + manager.connection.status);
return manager.connection.status === waitForStatus;
}
);
}
else {
callback(true);
}
};
req.onerror = function() {
console.log('error forgetting network with ssid \'' +
aNetwork.ssid + '\' ' + req.error.name);
callback(false);
};
},
isWiFiConnected: function(aNetwork) {
let manager = window.navigator.mozWifiManager;
let connected = manager.connection.status === 'connected';
if (connected && aNetwork) {
return manager.connection.network.ssid === aNetwork.ssid;
} else {
return connected;
}
},
getMozTelephonyState: function() {
return window.navigator.mozTelephony.active.state;
},
connectToCellData: function() {
var manager = window.navigator.mozMobileConnections &&
window.navigator.mozMobileConnections[0];
if (!manager.data.connected) {
waitFor(
function() {
console.log('cell data enabled');
marionetteScriptFinished(true);
},
function() { return manager.data.connected; }
);
this.setSetting('ril.data.enabled', true, false);
}
else {
console.log('cell data already connected');
marionetteScriptFinished(true);
}
},
disableCellData: function() {
var self = this;
this.getSetting('ril.data.enabled', function(aCellDataEnabled) {
var manager = window.navigator.mozMobileConnections &&
window.navigator.mozMobileConnections[0];
if (aCellDataEnabled) {
waitFor(
function() {
console.log('cell data disabled');
marionetteScriptFinished(true);
},
function() { return !manager.data.connected; }
);
self.setSetting('ril.data.enabled', false, false);
}
else {
console.log('cell data already disabled');
marionetteScriptFinished(true);
}
});
},
getAllPictures: function() {
this.getFiles('pictures');
},
getAllVideos: function() {
this.getFiles('videos');
},
getAllMusic: function() {
this.getFiles('music');
},
getAllSDCardFiles: function() {
this.getFiles('sdcard');
},
getFiles: function(aType, aCallback) {
var callback = aCallback || marionetteScriptFinished;
var files = [];
console.log('getting ' + aType);
var storage = navigator.getDeviceStorage(aType);
var req = storage.enumerate();
req.onsuccess = function() {
var file = req.result;
if (file) {
if (aType === 'music' && file.name.slice(-4) === '.3gp') {
// 3gp is both music and video; we skip the music definition
req.continue();
}
else {
// File.name returns a fully qualified path
files.push({'name': file.name, 'size': file.size});
req.continue();
}
}
else {
callback(files);
}
};
req.onerror = function() {
console.error('failed to enumerate ' + aType + ' ' + req.error.name);
callback(false);
};
},
sendSMS: function(recipient, content, skipVerification, aCallback) {
// requires the 'sms' permission and the 'dom.sms.enabled' pref
var callback = aCallback || marionetteScriptFinished;
console.log('sending sms message to number: ' + recipient);
let messageManager = window.navigator.mozMobileMessage;
let request = messageManager.send(recipient, content);
if (skipVerification) {
marionetteScriptFinished(true);
return;
}
request.onsuccess = function(event) {
var sms = event.target.result;
waitFor(
function() { callback(true); },
function() {
console.log('sms delivery state: ' + sms.delivery);
return sms.delivery === 'sent';
}
);
};
request.onerror = function() {
console.log('sms message not sent');
callback(false);
};
},
getAllSms: function(aCallback) {
// requires the 'sms' permission and the 'dom.sms.enabled' pref
var callback = aCallback || marionetteScriptFinished;
console.log('searching for sms messages');
let sms = window.navigator.mozMobileMessage;
let msgList = [];
let cursor = sms.getMessages(null, false);
cursor.onsuccess = function(event) {
if(cursor.result) {
// Add the sms to the list
msgList.push(cursor.result);
// Now get the next in the list
cursor.continue();
}else{
// Send back the list
callback(msgList);
}
};
cursor.onerror = function(event) {
console.log('sms.getMessages error: ' + event.target.error.name);
callback(false);
};
},
deleteAllSms: function(aCallback) {
// requires the 'sms' permission and the 'dom.sms.enabled' pref
var callback = aCallback || marionetteScriptFinished;
console.log('searching for sms messages');
let sms = window.navigator.mozMobileMessage;
let msgList = [];
let cursor = sms.getMessages(null, false);
cursor.onsuccess = function(event) {
// Check if message was found
if (cursor.result) {
msgList.push(cursor.result.id);
// Now get next message in the list
cursor.continue();
} else {
// No (more) messages found
if (msgList.length) {
console.log('found ' + msgList.length + ' sms messages to delete');
deleteSmsMsgs(msgList);
} else {
console.log('zero sms messages found');
callback(true);
}
}
};
cursor.onerror = function(event) {
console.log('sms.getMessages error: ' + event.target.error.name);
callback(false);
};
function deleteSmsMsgs(msgList) {
let smsId = msgList.shift();
console.log('deleting sms id: ' + smsId);
let request = sms.delete(smsId);
request.onsuccess = function(event) {
if (event.target.result) {
// Message deleted, continue until none are left
if (msgList.length) {
deleteSmsMsgs(msgList);
} else {
// All messages deleted
console.log('finished deleting all sms messages');
callback(true);
}
} else {
console.log('sms delete failed');
callback(false);
}
};
request.onerror = function(event) {
console.log('sms.delete request returned unexpected error: ' +
event.target.error.name);
callback(false);
};
}
},
deleteAllAlarms: function() {
window.wrappedJSObject.AlarmManager.getAlarmList(function(aList) {
aList.forEach(function(aAlarm) {
console.log('Deleting alarm with id \'' + aAlarm.id + '\'');
window.wrappedJSObject.AlarmManager.delete(aAlarm);
});
});
},
base64ToBlob: function(base64, mimeType) {
var binary = atob(base64);
var len = binary.length;
var buffer = new ArrayBuffer(len);
var view = new Uint8Array(buffer);
for (var i = 0; i < len; i++) {
view[i] = binary.charCodeAt(i);
}
return new Blob([view], {type: mimeType});
}
};

View file

@ -0,0 +1,57 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
'use strict';
/* globals waitFor, finish */
/* exported GaiaLockScreen */
var GaiaLockScreen = {
unlock: function(forcibly) {
let setlock = window.wrappedJSObject.SettingsListener.getSettingsLock();
let service = window.wrappedJSObject.Service;
let obj = {'screen.timeout': 0};
setlock.set(obj);
waitFor(
function() {
service.request('unlock', { forcibly: forcibly });
waitFor(
function() {
finish(service.locked);
},
function() {
return !service.locked;
}
);
},
function() {
return !!service;
}
);
},
lock: function(forcibly) {
let service = window.wrappedJSObject.Service;
let setlock = window.wrappedJSObject.SettingsListener.getSettingsLock();
let obj = {'screen.timeout': 0};
setlock.set(obj);
waitFor(
function() {
service.request('lock', { forcibly: forcibly });
waitFor(
function() {
finish(!service.locked);
},
function() {
return service.locked;
}
);
},
function() {
return !!service;
}
);
}
};

37
gaia/tests/atoms/reflow.js Executable file
View file

@ -0,0 +1,37 @@
'use strict';
(function(exports) {
if ('MozReflowAtom' in exports) {
return;
}
exports.MozReflowAtom = {
count: null,
_trackingManifest: null,
init: function rw_init() {
exports.addEventListener('developer-hud-update', this);
},
handleEvent: function rw_handleEvent(evt) {
var metric = evt.detail.metric.name || evt.detail.metric;
if (metric !== 'reflows' ||
evt.detail.manifest !== this._trackingManifest) {
return;
}
this.count++;
},
startTracking: function(manifestURL) {
this._trackingManifest = manifestURL;
this.count = 0;
},
stopTracking: function() {
this.count = 0;
this._trackingManifest = null;
},
};
exports.MozReflowAtom.init();
})(window);

15
gaia/tests/atoms/remote_date.js Executable file
View file

@ -0,0 +1,15 @@
return (function(ms) {
var date = new Date();
return {
year: date.getFullYear(),
month: date.getMonth(),
date: date.getDate(),
hours: date.getHours(),
minutes: date.getMinutes(),
seconds: date.getSeconds()
};
}.apply(this, arguments));

20
gaia/tests/atoms/screenshot.js Executable file
View file

@ -0,0 +1,20 @@
return (function takeScreenshot() {
var canvas = document.createElementNS('http://www.w3.org/1999/xhtml',
'canvas');
var width = window.innerWidth;
var height = window.innerHeight;
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
var context = canvas.getContext('2d');
var flags =
context.DRAWWINDOW_DRAW_CARET |
context.DRAWWINDOW_DRAW_VIEW |
context.DRAWWINDOW_USE_WIDGET_LAYERS;
context.drawWindow(window, 0, 0, width, height,
'rgb(255,255,255)', flags);
return context.canvas.toDataURL('image/png');
}.apply(this, arguments));