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,123 @@
/* global bridge,
BroadcastChannel,
EventDispatcher
*/
(function(exports) {
'use strict';
/**
* Name of the service that is responsible for managing activities.
* @type {string}
*/
const SERVICE_NAME = 'activity-service';
/**
* Reference to active bridge client instance. For every app instance that is
* run as inline activity we have only one bridge service (hosted in the main
* window context) and only one bridge client (hosted in the same context).
* Client should only communicate with the service that holds reference to
* the corresponding activity request. Since we can potentially have more than
* one inline activity instance we should use unique bridge service name for
* every app instance to avoid message collision.
*
* @type {Client}
*/
var client;
/**
* Indicates if there is pending activity request.
* @type {boolean}
*/
var hasPendingRequest;
/**
* ActivityClient is a wrapper around bridge client connected to the bridge
* service hosted in the context that can handle system messages. It allows
* to access "activity" request coming from system message when consumer can't
* receive it directly (document in a different URL or even worker).
* @type {Object}
*/
var ActivityClient = {
/**
* Initialized activity bridge client.
* @param {string} appInstanceId Unique identifier of app instance where
* client resides in.
*/
init(appInstanceId) {
if (!appInstanceId) {
throw new Error('AppInstanceId is required!');
}
client = bridge.client({
service: SERVICE_NAME,
endpoint: new BroadcastChannel(
`${SERVICE_NAME}-channel-${appInstanceId}`
),
// Disable service response timeouts.
timeout: false
});
hasPendingRequest = false;
client.on('activity-request', (request) => {
// This case should never happen since we use "inline" activities only.
if (hasPendingRequest) {
this.postError('Concurrent activity requests are not allowed');
return;
}
hasPendingRequest = true;
this.emit(request.name + '-activity-request', request.data);
});
},
/**
* Posts results to the activity caller.
* @param {*?} result
* @returns {Promise} Promise that resolves once operation is completed.
*/
postResult(result) {
if (!hasPendingRequest) {
return Promise.reject(
new Error('There is no any activity request to post result to!')
);
}
hasPendingRequest = false;
return client.method('postResult', result);
},
/**
* Notifies activity caller that exception occurred.
* @param {*?} error
* @returns {Promise} Promise that resolves once operation is completed.
*/
postError(error) {
if (!hasPendingRequest) {
return Promise.reject(
new Error('There is no any activity request to post error to!')
);
}
hasPendingRequest = false;
console.error('Activity request was rejected with "%s" reason', error);
return client.method('postError', error);
},
/**
* Checks if client has pending activity request.
* @returns {boolean}
*/
hasPendingRequest() {
return hasPendingRequest;
}
};
exports.ActivityClient = Object.freeze(
EventDispatcher.mixin(
ActivityClient, ['new-activity-request', 'share-activity-request']
)
);
})(window);

View file

@ -0,0 +1,144 @@
/* global BridgeServiceMixin,
BroadcastChannel
*/
/* exported ActivityShim */
'use strict';
(function(exports) {
const priv = Object.freeze({
request: Symbol('request'),
setMessageHandler: Symbol('setMessageHandler'),
onActivityRequest: Symbol('onActivityRequest')
});
/**
* Name of the service that is responsible for managing activities.
* @type {string}
*/
const SERVICE_NAME = 'activity-service';
/**
* Name of the system message that is leveraged by activities.
* @type {string}
*/
const SYSTEM_MESSAGE_NAME = 'activity';
/**
* List of methods exposed by shim.
* @type {Array.<string>}
*/
const METHODS = Object.freeze(['postResult', 'postError']);
/**
* List of event that can be broadcasted by shim.
* @type {Array.<string>}
*/
const EVENTS = Object.freeze(['activity-request']);
/**
* ActivityShim is a shim around "activity" system message handling code that
* allows to access activity request data by the consumer that can't handle
* system messages directly (document hosted in a different URl or worker) via
* exposing bridge service with required methods.
* @type {Object}
*/
var ActivityShim = {
/**
* Reference to currently active activity request.
* @type {ActivityRequestHandler}
* @private
*/
[priv.request]: null,
/**
* Reference to mozSetMessageHandler function.
* @type {Function}
* @private
*/
[priv.setMessageHandler]: null,
/**
* Initialized activity shim bridge service.
* @param {string} appInstanceId Unique identifier of app instance where
* shim resides in.
*/
init(appInstanceId, setMessageHandler) {
if (!appInstanceId) {
throw new Error('AppInstanceId is required!');
}
this[priv.setMessageHandler] = setMessageHandler;
// We may consider using exports.parent as endpoint instead in patch for
// bug 1223363, once it is unblocked.
this.initService(
new BroadcastChannel(`${SERVICE_NAME}-channel-${appInstanceId}`)
);
},
/**
* Method is called by bridge when a new client is connected to the service.
* @private
*/
onConnected() {
// We subscribe for the system message only when we have client connected,
// to avoid the case when service broadcasts message, but no one listens
// for it yet.
this[priv.setMessageHandler](
SYSTEM_MESSAGE_NAME, this[priv.onActivityRequest].bind(this)
);
},
/**
* Posts activity request result.
* @param {*} result Data to post as activity request result.
* @private
*/
postResult(result) {
var request = this[priv.request];
if (!request) {
throw new Error('There is no any activity request to post result to!');
}
request.postResult(result || { success: true });
this[priv.request] = null;
},
/**
* Posts activity request error.
* @param {*} error Error to post as activity request error.
* @private
*/
postError(error) {
var request = this[priv.request];
if (!request) {
throw new Error('There is no any activity request to post error to!');
}
request.postError(error);
this[priv.request] = null;
},
/**
* Handler that fires once app receives activity request via system message.
* @param {ActivityRequestHandler} request Activity request.
* @private
*/
[priv.onActivityRequest](request) {
this[priv.request] = request;
this.broadcast('activity-request', request.source);
}
};
exports.ActivityShim = Object.seal(
BridgeServiceMixin.mixin(
ActivityShim,
SERVICE_NAME,
{ methods: METHODS, events: EVENTS }
)
);
})(window);